Compare commits

..

274 Commits

Author SHA1 Message Date
Matthias Clasen e16a3b6232 Remove no longer needed code
We no longer use superset or any matchers to find changes.
2020-01-17 11:12:13 -05:00
Matthias Clasen 20dddd83d6 Go back to the tree for computing change 2020-01-17 11:11:55 -05:00
Matthias Clasen 6cc5331e6b Redo the way we compute change
Instead of expecting a superset matcher, call
gtk_css_selector_match_for_change while walking
the tree with the original matcher.
2020-01-17 11:10:14 -05:00
Matthias Clasen ee2b1601ff Bring back the reserved bit 2020-01-17 11:08:31 -05:00
Matthias Clasen 2c317b99a2 Revert "Remove no longer used code"
This reverts commit 105acfe908.
2020-01-17 11:08:31 -05:00
Timm Bäder da2e184639 Merge branch 'fix-imwayland-cursor' into 'master'
imwayland: Fix get_preedit_string cursor position (GTK4)

Closes #2383

See merge request GNOME/gtk!1328
2020-01-17 09:24:48 +00:00
xdavidwu 9576222b47 imwayland: Fix get_preedit_string cursor position
GtkIMContext get_preedit_string should return cursor position counted
in characters, but cursor_begin here is counted in bytes. This add the
missing conversion.
2020-01-17 16:16:13 +08:00
Matthias Clasen 7738a05bd2 Merge branch 'matthiasc/css-change-tracking-3' into 'master'
Preliminary css matcher work

See merge request GNOME/gtk!1326
2020-01-17 00:38:04 +00:00
Matthias Clasen 93b5b487ae cssmatcher: Change get_state to has_state
This matches all the other vfuncs, and it gets us
out of keeping several big state flag enumerations
in sync.

Update all callers.
2020-01-16 19:24:43 -05:00
Matthias Clasen 7588655a42 Allow printing css matchers
This can help in debugging css matching.
2020-01-16 19:11:21 -05:00
Matthias Clasen 007713c0ba css: Add a matcher type enum
For now, this just replaces the is_any boolean
by a type field in the class. It will be used in
future commits.
2020-01-16 19:11:21 -05:00
Matthias Clasen f0c1c3349f css: Simplify the superset matcher
We use the superset matcher in exactly one place,
so there is no need for the generality of allowing
to ignore different aspects. Just hardcode the one
case we need: ignoring everything except for name,
id and class.
2020-01-16 19:11:08 -05:00
Matthias Clasen 0dba6e5759 Cosmetic change
Update comments for name changes that happened long ago.
2020-01-16 19:10:03 -05:00
Matthias Clasen 60cd7cd96c css: Fix the ANY matcher state list
The ANY and matcher was not, in fact, matching any state,
since the list of states was not up-to-date.

The same fix applies to the superset matcher as well.
2020-01-16 19:09:19 -05:00
Matthias Clasen 2b504201e3 Merge branch 'matthiasc/css-change-tracking-2' into 'master'
Better css change tracking

See merge request GNOME/gtk!1325
2020-01-16 23:00:17 +00:00
Matthias Clasen 3fcbe8d5f3 Remove an unused define
We no longer use the GTK_CSS_CHANGE_RESERVED_BIT define.
2020-01-16 17:39:03 -05:00
Matthias Clasen 105acfe908 Remove no longer used code
We no longer consult the selector tree to find changes,
so this code is no longer needed.
2020-01-16 17:24:34 -05:00
Matthias Clasen 1caf197a0d css: Don't got to the selector tree for change
The tree is optimized for mimizing the decisions, and is built ahead-of-time.
That prevents us from taking advantage of the information in the matcher when
collecting changes.

So, instead do what we used to do for verification: Use the selector tree
for finding the superset matches, then just walk the rulesets to collect
the changes.

Since we are now recomputing the change masks much less frequently, this
slightly less optimized way of computing them is not a problem, and will
let us compute better results in the future, by improving the superset
matcher to be more precise.
2020-01-16 17:20:45 -05:00
Matthias Clasen 0a49726c73 cssprovider: Keep selectors around
Don't remove selectors from the rulsets after
creating the selector tree. We want to use them
in future commits.
2020-01-16 17:17:07 -05:00
Benjamin Otte dd0cc9df9f Merge branch 'matthiasc/css-change-tracking' into 'master'
Better css change handling

See merge request GNOME/gtk!1324
2020-01-16 22:13:57 +00:00
Matthias Clasen 789f6f3941 css: Avoid computing change too often
Most of the time when styles need to be recreated, the name and classes
of the css node haven't changed. In this case, the change value will not
change either, since we are computing change under the assumption that
name and classes are unchanged.

So don't recompute the change. This avoids the second match we do to
find the superset, cutting down the number of times we consult the
selector tree.
2020-01-16 17:03:51 -05:00
Matthias Clasen 2c231f4336 Revisit gtk_css_style_get_static_style one more time
Move the implementation to where it belongs.
2020-01-16 17:02:21 -05:00
Matthias Clasen 3c50e5324f Change the signature of gtk_css_style_get_static_style
It is clearer if this function returns a GtkCssStaticStyle.
2020-01-16 14:06:14 -05:00
Matthias Clasen 3182063ffe Quiet a compiler warning
This was causing warnings in a release build.
2020-01-16 13:04:33 -05:00
Matthias Clasen 5910e5ac6d Merge branch 'static-style-getter' into 'master'
css: Add gtk_css_style_get_static_style

See merge request GNOME/gtk!1323
2020-01-16 17:10:31 +00:00
Matthias Clasen b2b89f6c57 css: Add gtk_css_style_get_static_style
This lets us avoid poking directly at the GtkCssAnimatedStyle
struct in gtkcssnode.c.
2020-01-16 12:02:44 -05:00
Matthias Clasen 5ac24db049 Merge branch 'matthiasc/css-split-states' into 'master'
Split off some states in css change tracking

See merge request GNOME/gtk!1322
2020-01-16 16:58:23 +00:00
Matthias Clasen 192a24fa1f css: Track selected state separately
Like the previous change, this reduces the number of
css nodes reacting to parent-state changes. The remaining
parent-state cases here are due to :link.

Before (numbers from widget-factory with Adwaita):
2247 nodes
class 612
name 2246
id 2
first-child 148
last-child 156
state 2245
hover 562
disabled 859
backdrop 1080
sibling-name 63
sibling-disabled 51
parent-class 586
parent-name 788
parent-id 2
parent-first-child 78
parent-last-child 78
parent-state 236
parent-hover 5
parent-disabled 91
parent-backdrop 4

After:
2247 nodes
class 612
name 2246
id 2
first-child 148
last-child 156
state 2245
hover 562
disabled 859
backdrop 1080
selected 579
sibling-name 63
sibling-disabled 51
parent-class 586
parent-name 788
parent-id 2
parent-first-child 78
parent-last-child 78
parent-state 115
parent-hover 5
parent-disabled 91
parent-backdrop 4
parent-selected 144
2020-01-16 11:26:46 -05:00
Matthias Clasen 2426b9e23a css: Track backdrop state separately
Like the previous change, this reduces the number of
css nodes reacting to parent-state changes.

Before (numbers from widget-factory with Adwaita):
2247 nodes
class 612
name 2246
id 2
first-child 148
last-child 156
state 2247
hover 562
disabled 859
sibling-name 63
sibling-disabled 51
parent-class 586
parent-name 788
parent-id 2
parent-first-child 78
parent-last-child 78
parent-state 236
parent-hover 5
parent-disabled 91

After:
2247 nodes
class 612
name 2246
id 2
first-child 148
last-child 156
state 2245
hover 562
disabled 859
backdrop 1080
sibling-name 63
sibling-disabled 51
parent-class 586
parent-name 788
parent-id 2
parent-first-child 78
parent-last-child 78
parent-state 236
parent-hover 5
parent-disabled 91
parent-backdrop 4
2020-01-16 11:25:04 -05:00
Matthias Clasen 64848aebf4 css: Track disabled state separately
Significantly reduces the number of nodes that react to
parent-state changes.

Before (numbers from widget-factory with Adwaita):
2247 nodes
class 612
name 2246
id 2
first-child 148
last-child 156
state 2247
hover 2247
sibling-name 63
sibling-state 51
parent-class 586
parent-name 788
parent-id 2
parent-first-child 78
parent-last-child 78
parent-state 2226
parent-hover 5

After:
2247 nodes
class 612
name 2246
id 2
first-child 148
last-child 156
state 2247
hover 562
disabled 859
sibling-name 63
sibling-disabled 51
parent-class 586
parent-name 788
parent-id 2
parent-first-child 78
parent-last-child 78
parent-state 236
parent-hover 5
parent-disabled 91
2020-01-16 11:23:25 -05:00
Matthias Clasen fcceac6d11 css: Track hover state changes separately
The idea is that this reduce the amount of frequently
changing state that css nodes are sensitive to.

This is going to reduce the amount of style recomputation.
2020-01-16 11:17:48 -05:00
Matthias Clasen 975f6529b1 Merge branch 'wip/carlosg/x11-dnd' into 'master'
X11 dnd fixes.

See merge request GNOME/gtk!1321
2020-01-16 14:29:48 +00:00
Carlos Garnacho 357e215fb8 gdkdrag/x11: Issue XdndLeave on cancellation
According to XDND "The XdndLeave message cancels the session.",
issue one when cancelling a drag, so the dest side has an opportunity
to forget about the GdkDrop.
2020-01-16 15:03:24 +01:00
Carlos Garnacho 4716c9ae2f gdkdrag/x11: Drop timestamp argument from gdk_drag_do_leave()
This is not necessary for the XdndLeave message, nor used.
2020-01-16 15:02:16 +01:00
Carlos Garnacho 5aad3d7d0e gdk/x11: Ensure to hide DnD surface after failed operation
The drag source might be cached and held alive, only disposed after
future drag begin operations. Ensure the drag surface gets hidden
properly or might might stay transparent but mapped till then.
2020-01-16 13:34:08 +01:00
Carlos Garnacho fe36c24b07 gdk/x11: Ensure to sync type list after sending XdndEnter
Otherwise we are not ensured the GdkDrop is up-to-date, might even
be a stale one from an older DnD operation.
2020-01-16 13:33:57 +01:00
Carlos Garnacho 682068f887 gdk/x11: Serialize gtype content formats before sending Xdnd enter
This ensures GType handlers get serialized to mimetypes at the time
the drag dest inspects the XdndTypeList property.
2020-01-16 13:31:40 +01:00
Matthias Clasen e8eb1df29f Speed up gtk_widget_pick
Add early exits, and avoid as much work as
possible.
2020-01-15 11:01:20 -05:00
Matthias Clasen 82dc7b903c Fix the filetransfer portal initialization
Reusing the cancellable only works if you don't throw
it away after first use.
2020-01-15 10:58:54 -05:00
Matthias Clasen b020a3fcf9 Try harder to make ci not timeout
Make getting the file transfer portal proxy more
async, and avoid leaking a bus connection. This
causes GTestDBus to hang at the end of the test
run.
2020-01-14 18:32:05 -05:00
Matthias Clasen cb88de5938 css: Drop unsused bitmasks
GtkCssProvider was maintaining bitmasks for the
set properties in each ruleset. The masks are never
used, so drop them.
2020-01-14 18:32:05 -05:00
Matthias Clasen 94b1e72aa3 css: Remove an unused function
_gtk_css_style_property_get_mask_affecting was superseded
by GtkCssStyleChange back in 2015.
2020-01-14 18:32:05 -05:00
Matthias Clasen 20b92638ec testsuite: Improve --generate support
We don't want annoying spew from GTest when
using --generate, since it interferes with just
piping the output to a text file.
2020-01-14 18:32:05 -05:00
Matthias Clasen dccb83c9ec quiet a compiler warning in release builds 2020-01-14 18:32:05 -05:00
Alex Samorukov d668d2fa25 Use bundle id instead of package name for the macOS preview as filename is now changed 2020-01-14 22:15:05 +00:00
Matthias Clasen 34f1ae8fad fontchooser: Fix up the previous commit 2020-01-14 15:42:01 -05:00
Matthias Clasen 042537cf0d fontchooser: Fix objects-finalize test
The treeview is evil and keeps reference cycles in the
form of various tree row references. That gets cleaned up
if you explicitly gtk_widget_destroy the treeview. But since
07f2024bfc, the scrolled window no longer destroys
its child, exposing this issue as a reference leak in
the objects-finalize test.

The font chooser widget is affected here because it calls
gtk_tree_view_scroll_to_path from init(), which creates one
of those reference cycles. Work around this in the font
chooser by unsetting the tree view model in dispose, which
clears up this cycle.
2020-01-14 15:25:27 -05:00
Matthias Clasen d03f38470e Fix encoding symbolic pixbufs
This was broken in 1a931da046.
2020-01-14 14:14:45 -05:00
Sucipto a7d72cf69b Update Indonesian translation 2020-01-14 15:11:27 +00:00
Matthias Clasen 256139baab testsuite: Skip GtkDragIcon
GtkDragIcon needs a special surface, so skip it
in the notify tests.
2020-01-14 09:20:18 -05:00
Daniel Mustieles a935aae6f1 Updated Spanish translation 2020-01-14 12:39:44 +01:00
Kukuh Syafaat 9955d686ee Update Indonesian translation 2020-01-14 06:27:18 +00:00
Matthias Clasen a9da41c66a Merge branch 'adwaita-cross-fade-fix-gtk4' into 'master'
Adwaita: Fix syntax error in cross-fade() (GTK4)

Closes #2371

See merge request GNOME/gtk!1308
2020-01-14 06:08:24 +00:00
Matthias Clasen 4d8691b762 Merge branch 'wip/chergert/fix-dragicon-installation' into 'master'
build: fix gtkdragicon header installation

See merge request GNOME/gtk!1306
2020-01-14 06:06:35 +00:00
Matthias Clasen 806e159b8b Handle lack of file transfer portal
Don't block for 25 seconds trying to get a bus
connection. Give up after 1 second.
2020-01-14 01:03:48 -05:00
Matthias Clasen 794ee0b8c0 gtk-demo: Use a default action in the infobars demo
This makes the question infobar activatable by clicking
anywhere in it.
2020-01-14 00:05:23 -05:00
Matthias Clasen 2b7de841a9 Adwaita: Add hover for clickable infobars 2020-01-14 00:05:23 -05:00
Matthias Clasen 45309811c5 infobar: Activate default action on clicks
When we have a default action set on the infobar, activate it
for clicks anywhere in the infobar.  Also add an .action style
class in this case, so we can add a hover highlight to the infobar
just for this case.
2020-01-14 00:05:23 -05:00
Matthias Clasen 2b695ac8d1 Merge branch 'wip/chergert/textview-propagate-undo-state' into 'master'
textview: propagate GtkTextBuffer can-undo/redo action state

See merge request GNOME/gtk!1311
2020-01-14 01:59:22 +00:00
Christian Hergert cb03969c5f textview: propagate GtkTextBuffer can-undo/redo action state
This ensures the action state for undo and redo are propagated from the
buffer. Doing so means menu items now properly show sensitivity.
2020-01-13 17:26:18 -08:00
Matthias Clasen 57e71a6a69 Merge branch 'wip/chergert/textview-undo-menu-item' into 'master'
textview: add undo/redo menu actions

See merge request GNOME/gtk!1310
2020-01-13 23:51:40 +00:00
Christian Hergert 15b5a404b8 textview: add undo/redo menu actions 2020-01-13 15:25:05 -08:00
nana-4 4056a40d2d Adwaita: Fix syntax error in cross-fade()
cross-fade() requires two images.

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/2371
2020-01-14 06:19:12 +09:00
Christian Hergert c1e9523f0e build: fix gtkdragicon header installation 2020-01-13 09:07:24 -08:00
Daniel Mustieles 4c1ccfd7be Updated Spanish translation 2020-01-13 16:51:22 +01:00
Daniel Mustieles 823e00dec9 Updated Spanish translation 2020-01-13 16:50:21 +01:00
Timm Bäder 3e51966ea9 Merge branch 'wip/jimmac/updated-checkmark' into 'master'
Adwaita: update checkbox & radio

Closes #2291

See merge request GNOME/gtk!1289
2020-01-13 14:12:51 +00:00
Jakub Steiner e292767a01 Adwaita: update checkbox & radio
Fixes https://gitlab.gnome.org/GNOME/gtk/issues/2291
2020-01-13 13:45:34 +01:00
Matthias Clasen 75c433fb5f Merge branch 'closure-annotations' into 'master'
Fix incorrect use of GIR closure annotations.

See merge request GNOME/gtk!1305
2020-01-13 05:00:12 +00:00
Robert Ancell 83867f9cbf Add missing (closure) GIR annotations 2020-01-13 14:26:50 +13:00
Robert Ancell ea9f0df67b Fix incorrect use of GIR closure annotations.
They were being applied to the callback function, not the data that is passed
to that function.
2020-01-13 14:11:15 +13:00
Matthias Clasen 15c7980ba6 Merge branch 'textbuffer-missing-api-docs' into 'master'
Add missing public API documentation.

See merge request GNOME/gtk!1301
2020-01-13 00:51:24 +00:00
Matthias Clasen de5fde1e12 Merge branch 'menutoolbutton-missing-api-docs' into 'master'
menutoolbutton: Add missing public API documentation.

See merge request GNOME/gtk!1303
2020-01-13 00:50:58 +00:00
Matthias Clasen a83b360224 Merge branch 'docstring-typos' into 'master'
Fix docstring errors with drag and drop code

See merge request GNOME/gtk!1304
2020-01-13 00:50:16 +00:00
Matthias Clasen 4d55d23c1a Merge branch 'missing-transfer-notation' into 'master'
Add missing transfer notation for function return types.

See merge request GNOME/gtk!1302
2020-01-13 00:49:25 +00:00
Robert Ancell 2b6162116d Fix docstring errors with drag and drop code 2020-01-13 12:30:17 +13:00
Robert Ancell b2ca947934 textbuffer: Add missing public API documentation.
This API was added in a52757874e.
2020-01-13 12:19:43 +13:00
Robert Ancell 3eaf88b84c menutoolbutton: Add missing public API documentation.
This API was added in 03e30431a8
2020-01-13 12:17:55 +13:00
Robert Ancell 9e9eae3ad4 Add missing transfer notation for function return types. 2020-01-13 12:14:08 +13:00
Matthias Clasen 903afcbddd Adwaita: Fix needs-attention
Stack switchers are now stackswitcher, no longer .stack-switcher.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/2370
2020-01-11 20:14:35 -05:00
Piotr Drąg d37612a476 Update POTFILES.in 2020-01-11 16:07:48 +01:00
Matthias Clasen f5daecf353 Merge branch 'dnd-gestures-2' into 'master'
Add new dnd api

See merge request GNOME/gtk!1278
2020-01-11 06:09:58 +00:00
Matthias Clasen b76940bab5 dragdest: More documentation 2020-01-11 00:50:22 -05:00
Matthias Clasen ec255f9bb1 Update all callers 2020-01-11 00:50:22 -05:00
Matthias Clasen 9dc6be4fb0 Reshuffle droptarget api a little bit
Add a ::drag-motion signal back, remove x,y from
the ::accept signal, and only emit ::accept once.
2020-01-11 00:49:59 -05:00
Matthias Clasen 186b783f9d Merge branch 'wip/chergert/gtk4-gtk-main-sync' into 'master'
Rubustness fixes for gtk_main_sync()

See merge request GNOME/gtk!1299
2020-01-11 04:41:46 +00:00
Christian Hergert 2f3518c80d gtkmain: be deterministic in source removal
Fixes gtk_main_sync() to only remove a source if it has not
already executed (and been removed). The previous code was
using gtk_main_quit() directly which would be non-determinstic
based on the previous value in the return register.
2020-01-10 15:04:44 -08:00
Christian Hergert 4a7f68e79e gtkmain: short-circuit gtk_main_sync() where no display
If there is no display, we will hit the slow path here which
can introduce long latencies in unit tests. This checks for
a NULL list of displays and simply short-circuits.
2020-01-10 15:00:10 -08:00
Matthias Clasen 65af983ddb Merge branch 'css-font-values' into 'master'
Css font values

See merge request GNOME/gtk!1298
2020-01-10 22:47:41 +00:00
Matthias Clasen f0dc5e0be5 css: Simplify font features
Don't store numbers as GtkCssValues needlessly.
2020-01-10 16:59:56 -05:00
Alex Samorukov f0cbd175cd gdk_quartz_keymap_translate_keyboard_state fills consumed_modifiers
incorrectly (closes #2102)

See merge request GNOME/gtk!1225
2020-01-10 22:18:24 +01:00
Matthias Clasen 99aa47185e css: Simplify compute for font variations
Just like font features, font variations are stored
as a hash table mapping strings to pure number values,
which never change during compute.
2020-01-10 15:49:00 -05:00
Matthias Clasen 898e29c989 css: Simplify compute for font features
Font features consist of a hash table of number
values, which will never change during compute,
so there is no point in recreating a new value
with a copy of the hash table, constaining the
same string->number mapping.
2020-01-10 15:48:51 -05:00
Matthias Clasen cf1700fd13 Merge branch 'kill-builtin-image' into 'master'
Kill builtin image

See merge request GNOME/gtk!1297
2020-01-10 19:43:14 +00:00
Matthias Clasen 112aed590f Remove builtin icons altogether
This removes support for GtkCssImageBuiltin and
GtkCssImageBuiltinType from everywhere.
2020-01-10 14:34:56 -05:00
Matthias Clasen 6763443c5d css: Stop supporting builtin images
Change the default value of -gtk-icon-source to 'none',
and stop parsing 'builtin' as a value.
2020-01-10 14:32:06 -05:00
Dušan Kazik 7d99339c39 Update Slovak translation 2020-01-10 06:47:50 +00:00
Matthias Clasen f33fe6daed testdnd: Fix up for current api 2020-01-09 10:29:33 -05:00
Matthias Clasen c7dc17d837 docs: Expand the dnd migration hints 2020-01-09 07:47:28 -05:00
Matthias Clasen a51ee20ed9 dragicon: Add docs 2020-01-09 00:50:33 -05:00
Matthias Clasen 8d3e1eb314 docs: Fix a typo 2020-01-09 00:31:13 -05:00
Matthias Clasen c941a2d9c6 Properly export GtkDragIcon
The get_type function was missing.
2020-01-09 00:30:41 -05:00
Matthias Clasen 1c03bbeb9c Update all users 2020-01-08 18:48:23 -05:00
Matthias Clasen a4059cd02d dragdest: Rename ::drag-motion to ::accept 2020-01-08 18:48:23 -05:00
Matthias Clasen eab6df31ac dragdest: Allow denying drops asynchronously
Add an api to deny a drop, this is meant to be used
when delaying the decision on whether to accept a
drop until after reading the data.
2020-01-08 18:48:23 -05:00
Matthias Clasen 8a085fcc5a remove debug spew 2020-01-08 18:48:23 -05:00
Matthias Clasen 7668669d56 dragdest: Add a ::drag-enter signal
Mainly for symmetry with ::drag-leave.
2020-01-08 18:48:22 -05:00
Matthias Clasen 5e57b3d07a testdnd2: Fix the text case
We must take mime types into account when checking.
2020-01-08 18:48:22 -05:00
Matthias Clasen 187a701a99 content provider impl: Take mime types into account 2020-01-08 18:48:22 -05:00
Matthias Clasen d5f4579384 dragdest: Steps towards allowing nested drop sites 2020-01-08 18:48:22 -05:00
Matthias Clasen 0297039b38 Add another dnd testcase
This one tests nested drop sites and interaction between
DND and other gestures.
2020-01-08 18:48:22 -05:00
Matthias Clasen 5206a92522 Update all callers 2020-01-08 18:48:22 -05:00
Matthias Clasen 233ec1a5d6 Add GdkDrop back to signal signatures 2020-01-08 18:48:22 -05:00
Matthias Clasen 579d8e427b Drop gtk_drag_(un)highlight 2020-01-08 18:48:22 -05:00
Matthias Clasen 9c11c60530 filechooser: Remove code for sidebar pre-arming
This is just not a feature we can support currently.
Doing it properly would require infrastructure for
a generalized :drag(sensitive) state highlighting
potential drag sites everywhere.
2020-01-08 18:48:22 -05:00
Matthias Clasen 66c8da4750 listbox: Stop using gtk_drag_(un)highlight
This api is going away, so just do what needs to
be done manually.
2020-01-08 18:48:22 -05:00
Matthias Clasen 05a9b72fc8 calendar: Remove drag highlighting calls
This is happening unconditionally, anyway.
2020-01-08 18:48:22 -05:00
Matthias Clasen 4fe5710456 textview: Remove unnecessary drag highlighting
GTK does this unconditionally anyway, now.
2020-01-08 18:48:22 -05:00
Matthias Clasen ac5b4a6307 text: Remove unnecessary drag highlighting
GTK does this unconditionally anyway, now.
2020-01-08 18:48:22 -05:00
Matthias Clasen 5ce7bfbbd8 notebook: Receive tab dnd on the tabs
Don't make the whole notebook a drop target
for tab dnd, but just the tab bar. This will
help with drag highlighting, and it arguably
more correct anyway.
2020-01-08 18:48:22 -05:00
Matthias Clasen 7646d1b22c Adwaita: No drag highlight for placessidebar
It does its own custom thing.
2020-01-08 18:48:22 -05:00
Matthias Clasen 61db81ab8e Adwaita: No dnd highlight for iconviews
We only want to highlight the drop location
that is rendered with a separate css node now.
2020-01-08 18:48:22 -05:00
Matthias Clasen 24d7586163 iconview: Use a named subnode for dnd highlight
This is necessary because we want to style the
iconview itself and the item highlighting differently.
2020-01-08 18:48:22 -05:00
Matthias Clasen b150625105 Adwaita: No dnd highlight for treeviews
We only want to highlight the drop location
that is rendered with a separate css node now.
2020-01-08 18:48:22 -05:00
Matthias Clasen 5787146238 treeview: Use a named subnode for dnd highlight
This is necessary because we want to style the
treeview itself and the row highlighting differently.
2020-01-08 18:48:22 -05:00
Matthias Clasen 8a72031e99 Adwaita: No drag highlight for stack switchers 2020-01-08 18:48:22 -05:00
Matthias Clasen 201a791076 Adwaita: No drag highlight for expanders
This is pretty ugly, because Adwaita has a very
generic drop-highlight implementaiton that we
need to overrule.
2020-01-08 18:48:22 -05:00
Matthias Clasen 359003670a dragdest: Rename ::armed to ::contains 2020-01-08 18:48:22 -05:00
Matthias Clasen 6b7c5174ed gtk-demo: Update the ::prepare handler 2020-01-08 18:48:22 -05:00
Matthias Clasen 8a521accbc dragsource: Change the ::prepare return type
Make it return the content provider to use for
the next drag. This allows just-in-time provision
of the content provider. The default handler just
returns the value of the ::content property.
2020-01-08 18:48:22 -05:00
Matthias Clasen d116bbf0c8 docs: Expand the GDK dnd docs 2020-01-08 18:48:22 -05:00
Matthias Clasen 42e440a111 docs: Add GtkDragIcon 2020-01-08 18:48:22 -05:00
Matthias Clasen 13adb2591c docs: Add GtkDropTarget section 2020-01-08 18:48:22 -05:00
Matthias Clasen 7b73824dfe docs: Remove dropped drag source apis 2020-01-08 18:48:22 -05:00
Matthias Clasen 403aba82a9 docs: Remove the dnd section
These functions in this section are all gone.
2020-01-08 18:48:22 -05:00
Matthias Clasen a053d7ddb1 dragsource: Drop gtk_drag_source_drag_begin
No longer used. Also, minor cleanups all over.
2020-01-08 18:48:22 -05:00
Matthias Clasen c878f650ce dragksource: Small doc fix 2020-01-08 18:48:22 -05:00
Matthias Clasen 2d2cdeae88 Drop GTK content formats apis
These functions have been superseded by better
facilities in GDK.
2020-01-08 18:48:22 -05:00
Matthias Clasen 009228471c testdnd2: Use GDK content formats api 2020-01-08 18:48:22 -05:00
Matthias Clasen 379166e1ff text: Use GDK content formats API 2020-01-08 18:48:22 -05:00
Matthias Clasen a59a20c1d4 placessidebar: Use GDK content formats api 2020-01-08 18:48:22 -05:00
Matthias Clasen fb4b5c666b filechooserwidget: Use GDK content formats api: 2020-01-08 18:48:22 -05:00
Matthias Clasen b59c70aaeb filechooserbutton: Use GDK content formats api 2020-01-08 18:48:22 -05:00
Matthias Clasen 6fcae42dde calendar: Use GDK content formats api 2020-01-08 18:48:22 -05:00
Matthias Clasen 2ee087f25f iconbrowser: Use GDK content formats api 2020-01-08 18:48:22 -05:00
Matthias Clasen 9cc29efa25 gtk-demo: Use GDK content formats api 2020-01-08 18:48:22 -05:00
Matthias Clasen a04d314910 text: Fix dragging of text across focus changes
When dragging selected text from an entry over a stackswitcher
to show a different page, the focus changes, causing the selection
to be lost; we should not lose the dragged content in this case.
2020-01-08 18:48:22 -05:00
Matthias Clasen f83f7a2b4d Adwaita: Add drop highlight for iconview items 2020-01-08 18:48:22 -05:00
Matthias Clasen edb175cf75 iconview: Render drop highlight properly
Use :drop(active) and render a frame, not focus.
2020-01-08 18:48:22 -05:00
Matthias Clasen 1eefaf8b41 dragsource: Fix cancellation
We need to properly end the drag.
2020-01-08 18:48:22 -05:00
Matthias Clasen 0224517806 filechooser: Stop using gtk_drag_source_get_drag 2020-01-08 18:48:22 -05:00
Matthias Clasen 27c521cce8 placessidebar: Update a comment 2020-01-08 18:48:22 -05:00
Matthias Clasen 62b87182c5 Remove an unused enum
We are not using GtkDragResult anymore.
2020-01-08 18:48:22 -05:00
Matthias Clasen c95659bf32 testdnd2: Update to the api change in the previous commit 2020-01-08 18:48:22 -05:00
Matthias Clasen 865fc9c925 dragsource: Rename ::drag-failed to ::drag-cancel
This matches the names of the GdkDrag signals.
2020-01-08 18:48:22 -05:00
Matthias Clasen a1f4f52fcb dragsource: Tweak docs more 2020-01-08 18:48:22 -05:00
Matthias Clasen bdb4bf00c5 dragsource: Document prepare 2020-01-08 18:48:22 -05:00
Matthias Clasen aca252837d dragsource: Make ::prepare return a boolean
Make ::prepare return TRUE to start a drag.
The default handler simply checks that we
have a content provider and actions.
2020-01-08 18:48:22 -05:00
Matthias Clasen 8b058572f0 dragsource: Drop gtk_drag_get_source 2020-01-08 18:48:22 -05:00
Matthias Clasen df050c51bb notebook: Stop using gtk_drag_get_source 2020-01-08 18:48:21 -05:00
Matthias Clasen bd20ae4fa5 dragsource: Drop gtk_drag_source_get_origin 2020-01-08 18:48:21 -05:00
Matthias Clasen 818b456f9f filechooserwidget: Stop using gtk_drag_source_get_origin 2020-01-08 18:48:21 -05:00
Matthias Clasen c1c8abf275 notebook: Stop using gtk_drag_source_get_origin 2020-01-08 18:48:21 -05:00
Matthias Clasen c1029535ca testtoolbar: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen a5ca5eb865 testlist3: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen 2227d2a2b5 testdnd2: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen 61559e38f4 testdnd: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen 134fca47e3 pathbar: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen 4630dd8d68 notebook: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen d2f7d1b1d7 linkbutton: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen cfa9e6da4a colorswatch: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen ceca2f9202 colorbutton: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen bf98ebcb12 iconbrowser: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen 1a5dece09c gtk-demo: Use gtk_widget_add_controller for drag source 2020-01-08 18:48:21 -05:00
Matthias Clasen 8e8254feae filechooserwidget: wip 2020-01-08 18:48:21 -05:00
Matthias Clasen 90cda9e307 treeview: Use gdk_drag_begin 2020-01-08 18:48:21 -05:00
Matthias Clasen fdfa371d90 iconview: Use gdk_drag_begin
This is a little more involved here.
2020-01-08 18:48:21 -05:00
Matthias Clasen deb16c1a00 Make GtkDragSource a gesture 2020-01-08 18:48:21 -05:00
Matthias Clasen 8c3736709e notebook: Use gdk_drag_begin
Use gdk_drag_begin for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen f459164f8a placessidebar: Use gdk_drag_begin
Use gdk_drag_begin for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen 00169a06bf textview: Use gdk_drag_begin
Use gdk_drag_begin for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen e09f2b8b56 entry: Use gdk_drag_begin
Use gdk_drag_begin for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen 092c115ff0 text: Use gdk_drag_begin
Use gdk_drag_begin directly for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen 5144d15168 calendar: Use gdk_drag_begin
Use gdk_drag_begin directly for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen 5a6ab8cbd3 label: Use gdk_drag_begin
Use gdk_drag_begin directly for one-off drags.
2020-01-08 18:48:21 -05:00
Matthias Clasen 8c73f882af dragsource: Use public drag icon api 2020-01-08 18:48:21 -05:00
Matthias Clasen 78832c65b5 Make GtkDragIcon public
This is needed if we want to use gdk_drag_begin
for one-off drags, without a GtkDragSource.
2020-01-08 18:48:21 -05:00
Matthias Clasen e8b830a3dd dragsource: Reshuffle api a bit
Remove arguments from the constructor.

For actions, we now default to COPY, which is the most common one
that we should enable by default (MOVE requires handling deletion
on the the source side, and ASK only makes sense if we have
multiple actions).

For the content provider, we add a new ::prepare signal where
it should be provided just-in-time.
2020-01-08 18:48:21 -05:00
Matthias Clasen 38974d7d2b dragsource: Tweak api, update all callers
Add GdkDrag back to signals, drop ::drag-data-delete,
and replace it with a boolean in ::drag-end.
2020-01-08 18:48:21 -05:00
Carlos Garnacho f6f331efe3 gdk/x11: Forward suggested action (if any) to XdndStatus
Go ahead with the suggested action, so the drag source may update
cursor feedback properly, and eventually result in the correct
action.
2020-01-08 18:48:21 -05:00
Carlos Garnacho dbb3727b03 popover: Use g_signal_connect_object on parent widget signal
The popover may be destroyed, leaving this dangling signal. This
may cause crashes on future parent widget resizes.
2020-01-08 18:48:21 -05:00
Matthias Clasen 508570864d Remove gtk_drop_target_get_target
Now that drop targets are event controllers,
we can just use gtk_event_controller_get_widget.
Update all callers.
2020-01-08 18:48:21 -05:00
Matthias Clasen 96c77b61c1 Remove an unused signal 2020-01-08 18:48:21 -05:00
Matthias Clasen 2b819c830b docs: Tweak GtkDropTarget docs 2020-01-08 18:48:21 -05:00
Matthias Clasen f3be49838f Move code over
Move remaining code from gtkdnd.c to gtkdragdest.c
and nuke gtkdnd.c and gtkdndprivate.h.
2020-01-08 18:48:21 -05:00
Matthias Clasen e9067ae2db Replace gtk_drop_target_attach/detach
Since drop targets are now just event controller,
gtk_widget_add/remove_controller works just fine
for them.
2020-01-08 18:48:21 -05:00
Matthias Clasen f898bee032 Use normal event propagation for DND events
This works just fine, now that drop targets are
event controllers. There is only a very vestigial
gtk_drag_dest_handle_event() left that deals with
corner cases.
2020-01-08 18:48:21 -05:00
Matthias Clasen 6a7f39e6d2 Get rid of GtkDragDestInfo
We can just attach the GtkDropTarget directly to
the GdkDrop.
2020-01-08 18:48:21 -05:00
Matthias Clasen dfb2cbdfdb Turn GtkDropTarget into an event controller
We are still propagating the drag events manually,
but we are now calling gtk_widget_run_controllers
to pass them to drop targets.
2020-01-08 18:48:21 -05:00
Matthias Clasen f960eb6ab4 More internal restructuring 2020-01-08 18:48:21 -05:00
Matthias Clasen 60fc2c6a7a dnd: Another internal refactoring step 2020-01-08 18:48:21 -05:00
Matthias Clasen 3080592234 gdk: Make gdk_event_set_coords support dnd events
GTK event propagation code relies on this working.
2020-01-08 18:48:21 -05:00
Matthias Clasen 532fdde720 dnd: More internal restructuring 2020-01-08 18:48:21 -05:00
Matthias Clasen f8399588e9 dnd: Some internal restructuring
Nudge the code towards being like event controllers.
2020-01-08 18:48:20 -05:00
Matthias Clasen ad019be75b Drop an unused define 2020-01-08 18:48:20 -05:00
Matthias Clasen e505dab487 Stop passing timestamps around
We were not using these in a useful way in the end,
so stop passing them around.
2020-01-08 18:48:20 -05:00
Matthias Clasen 1262184269 droptarget: Drop the track-motion property
It does not have any effect anymore.

Update all callers
2020-01-08 18:48:20 -05:00
Matthias Clasen 46f42fc53d droptarget: Drop defaults flags
These no longer have any effect.

Update all callers.
2020-01-08 18:48:20 -05:00
Matthias Clasen cb26cd7391 Simplify some drag dest internals
Change things around to make the default handler
of GtkDropTarget::drag-motion implement the default
handling. Always emit ::drag-motion and ::drag-leave,
and always arm the drop target.

This makes the GTK_DEST_DEFAULT_MOTION flag and
the ::track-motion property unnecessary.

Drop targets that are purely after track-motion
handling for ui switching purposes, such as
GtkStackSwitcher, will have to undo the automatic
arming in a notify::armed handler.
2020-01-08 18:48:20 -05:00
Matthias Clasen 1a3eeb1233 Drop GTK_DEST_DEFAULT_HIGHLIGHT
Redo highlight handling slightly. GtkDropTarget now has
a ::armed property that can be tracked to do custom highlighting,
and we always add the dnd style class to armed drop sites.
2020-01-08 18:48:20 -05:00
Matthias Clasen e1f74c8f69 dragdest: Clean up internals
Remove the no-longer needed GtkDragDest struct
and just attach the GtkDropTarget directly.
2020-01-08 18:48:20 -05:00
Matthias Clasen 58106af54d testdnd2: Add a test for ASK handling
It is a bit unfortunate that we need to extend the
lifespan of the drop object by keeping our own
ref, but I don't see a better way of doing it.
2020-01-08 18:48:20 -05:00
Matthias Clasen 1e000c3dac Remove gtkdnd.h 2020-01-08 18:48:20 -05:00
Matthias Clasen 19ee9b4c57 Remove gdk_drag_get_data
This is not used anymore, so we can remove it,
and the GtkDropTarget::drag-data-received signal
that it emits.
2020-01-08 18:48:20 -05:00
Matthias Clasen 1075607528 treeview: Stop using ::drag-data-received 2020-01-08 18:48:20 -05:00
Matthias Clasen d2bd9b0850 iconview: Avoid drag-data-received 2020-01-08 18:48:20 -05:00
Matthias Clasen 74d445636c testtreednd: Use the new asyn selection read 2020-01-08 18:48:20 -05:00
Matthias Clasen 7048790931 testlist3: Use async read api for selection 2020-01-08 18:48:20 -05:00
Matthias Clasen b9034015d7 filechooser: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen c7b70b122a placessidebar: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 6e01a49d10 iconview: Port to GtkDropTarget
A small api change here is that
gtk_icon_view_enable_model_drag_dest now returns
a GtkDropTarget that can be used to connect signals.
2020-01-08 18:48:20 -05:00
Matthias Clasen c290bd6367 Add an async read function for selection
This is meant as a replacement for ::drag-data-received
in cases where a #GtkSelectionData object is still needed,
such as when using GtkTreeModel DND support.
2020-01-08 18:48:20 -05:00
Matthias Clasen 853063bea7 Remove old drag dest api 2020-01-08 18:48:20 -05:00
Matthias Clasen 69e3fee5e2 Move some remaining api over 2020-01-08 18:48:20 -05:00
Matthias Clasen aa276a181e listbox: Remove unhighlighting
This will have to be done differently, if necessary.
2020-01-08 18:48:20 -05:00
Matthias Clasen 583705b4ae notebook: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen cd7303d47c testtreednd: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 0f9cbf49ac testnotebookdnd: Fix, partially
Make this mostly work again.
2020-01-08 18:48:20 -05:00
Matthias Clasen a309e74be7 testtoolbar: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen ccaf70e1b7 testlist3: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 2fd9431f23 testdnd: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 3f33a0ed27 testdnd2: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 4ea18a22e6 treeview: Port to GtkDropTarget
A small api change here is that
gtk_tree_view_enable_model_drag_dest now returns
a GtkDropTarget that can be used to connect signals.
2020-01-08 18:48:20 -05:00
Matthias Clasen 746dc5c3a2 textview: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 17131f1137 filechoserbutton: Convert to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 07c889c5ea stackswitcher: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen b0d9a6ff20 expander: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 802c7975e2 window: Port to GtkDragDest 2020-01-08 18:48:20 -05:00
Matthias Clasen 6e602e052b text: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 025eee112c colorswatch: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 70cdd4e951 colorbutton: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen 75b789f20f calendar: Port to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen ac09500d74 gtk-demo: Convert clipboard demo to GtkDropTarget 2020-01-08 18:48:20 -05:00
Matthias Clasen a76b187a5b drop: Add a convenience api
This is a question that drag-drop handlers frequently
need to answer, so make it easy.
2020-01-08 18:48:20 -05:00
Matthias Clasen 45679d7bc3 dragdest: doc improvements 2020-01-08 18:48:20 -05:00
Matthias Clasen 6dc8fc3a4d Add a GtkDropTarget object
Add an explicit GtkDropTarget object, and move the destination-side
DND signals here. The object is used by connecting to its signals
and attaching it to a widget with gtk_drop_target_attach().
2020-01-08 18:48:20 -05:00
Matthias Clasen e53e0f461e Hook up the GtkDragSource docs 2020-01-08 18:48:20 -05:00
Matthias Clasen 37b849b808 Move the rest of the drag-source api over
Just reshuffling some source.
2020-01-08 18:48:20 -05:00
Matthias Clasen e03bdbe307 docs: Mention DND in the migration guide 2020-01-08 18:48:20 -05:00
Matthias Clasen 9b01d9a784 Remove traditional drag source API
gtk_drag_source_set, gtk_drag_begin, related apis
and the GtkWidget source-side signals have all been
replaced by GtkDragSource.
2020-01-08 18:48:20 -05:00
Matthias Clasen b4c689ecd6 tests: Convert to GtkDragSource
Some tests, such as testimage did not have
anything particularly worth keeping, so
were removed instead of fixed.
2020-01-08 18:48:19 -05:00
Matthias Clasen 78a0913f0f notebook: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 74722fb10e filechooser: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 3891ce36fe treeview: Port to GtkDragSource
A small api change here is that
gtk_tree_view_enable_model_drag_source now returns
a GtkDragSource that can be used to connect signals.
2020-01-08 18:48:19 -05:00
Matthias Clasen 5a940408fe placessidebar: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen efce8c2899 iconview: Port to GtkDragSource
A small api change here is that
gtk_icon_view_enable_model_drag_source now returns
a GtkDragSource that can be used to connect signals.
2020-01-08 18:48:19 -05:00
Matthias Clasen ea9f2abcc4 Add another callback-based provider
This one can be used in cases where data needs
to be served in multiple formats that may not
all be covered by content serializers.
2020-01-08 18:48:19 -05:00
Matthias Clasen 993d6388ee iconbrowser: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 5ad4b75ae2 gtk-demo: Convert the clipboard demo to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 24ef9df0f1 pathbar: Convert to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 5d49b11ffd colorswatch: Convert to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 8e3db48482 colorbutton: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen fdcfe0e80a Add a generic callback content provider
This one is convenient to use in cases where a
drag is just serving an existing GType which
is covered by content serializers.
2020-01-08 18:48:19 -05:00
Matthias Clasen 8137dea8c1 Add (de)serializers for GdkRGBA
This is a format that we use in various
color picker widgets, so support it in GDK.
2020-01-08 18:48:19 -05:00
Matthias Clasen b15c31a3f7 textview: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen a52757874e textbuffer: Add a content provider api
We need a content provider for the selection,
to implement DND, and the text buffer already
has one. Just add an api to get it.
2020-01-08 18:48:19 -05:00
Matthias Clasen e9203eeef7 text: Convert to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 337057eb35 entry: Port icon dnd to GtkDragSource
This requires a small change in the api,
since we need to provide a GdkContentProvider now.
2020-01-08 18:48:19 -05:00
Matthias Clasen 2803a15a51 calendar: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen d145032cb6 linkbutton: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen 2612331282 label: Port to GtkDragSource 2020-01-08 18:48:19 -05:00
Matthias Clasen d3fd071809 dnd: Patch up gtk_drag_get_source_widget
This is temporary until gtk_drag_dest_set users
have been ported over.
2020-01-08 18:48:19 -05:00
Matthias Clasen 303c9becf8 Add a GtkDragSource object
Add an explicit GtkDragSource object, and move the source-side
DND signals here. The object can be used on the spot, by calling
gtk_drag_source_drag_begin() yourself, or for static drag-source
configuration, by calling gtk_drag_source_attach(). In the latter
case, we set up and conect a drag gesture to trigger the drag_begin
call.
2020-01-08 18:48:19 -05:00
Matthias Clasen 6bf46c8f30 marshalers: Add another 2020-01-08 18:48:19 -05:00
162 changed files with 15566 additions and 13499 deletions
+75 -50
View File
@@ -119,48 +119,76 @@ get_image_paintable (GtkImage *image)
}
static void
drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
drag_begin (GtkDragSource *source,
GdkDrag *drag,
GtkWidget *widget)
{
GdkPaintable *paintable;
paintable = get_image_paintable (GTK_IMAGE (widget));
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
gtk_drag_source_set_icon (source, paintable, -2, -2);
g_object_unref (paintable);
}
}
void
drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
guint info,
gpointer data)
static void
get_texture (GValue *value,
gpointer data)
{
GdkPaintable *paintable;
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
paintable = get_image_paintable (GTK_IMAGE (widget));
if (GDK_IS_TEXTURE (paintable))
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
g_value_set_object (value, paintable);
}
static GdkContentProvider *
prepare_drag (GtkDragSource *source,
double x,
double y,
GtkWidget *image)
{
return gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
}
static void
drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data,
gpointer data)
got_texture (GObject *source,
GAsyncResult *result,
gpointer data)
{
if (gtk_selection_data_get_length (selection_data) > 0)
{
GdkTexture *texture;
GdkDrop *drop = GDK_DROP (source);
GtkWidget *image = data;
const GValue *value;
GError *error = NULL;
texture = gtk_selection_data_get_texture (selection_data);
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
g_object_unref (texture);
value = gdk_drop_read_value_finish (drop, result, &error);
if (value)
{
GdkTexture *texture = g_value_get_object (value);
gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (texture));
}
else
{
g_print ("Failed to get data: %s\n", error->message);
g_error_free (error);
}
}
static gboolean
drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkWidget *widget)
{
if (gdk_drop_has_value (drop, GDK_TYPE_TEXTURE))
{
gdk_drop_read_value_async (drop, GDK_TYPE_TEXTURE, G_PRIORITY_DEFAULT, NULL, got_texture, widget);
return TRUE;
}
return FALSE;
}
static void
@@ -171,12 +199,8 @@ copy_image (GSimpleAction *action,
GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
g_print ("copy image\n");
if (GDK_IS_TEXTURE (paintable))
{
g_print ("set clipboard\n");
gdk_clipboard_set_texture (clipboard, GDK_TEXTURE (paintable));
}
gdk_clipboard_set_texture (clipboard, GDK_TEXTURE (paintable));
if (paintable)
g_object_unref (paintable);
@@ -247,6 +271,9 @@ do_clipboard (GtkWidget *do_widget)
{ "paste", paste_image, NULL, NULL, NULL },
};
GActionGroup *actions;
GtkDragSource *source;
GtkDropTarget *dest;
GdkContentFormats *formats;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
@@ -305,22 +332,21 @@ do_clipboard (GtkWidget *do_widget)
/* Create the first image */
image = gtk_image_new_from_icon_name ("dialog-warning");
gtk_image_set_pixel_size (GTK_IMAGE (image), 48);
gtk_container_add (GTK_CONTAINER (hbox), image);
/* make image a drag source */
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag-begin",
G_CALLBACK (drag_begin), image);
g_signal_connect (image, "drag-data-get",
G_CALLBACK (drag_data_get), image);
source = gtk_drag_source_new ();
g_signal_connect (source, "prepare", G_CALLBACK (prepare_drag), NULL);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
/* accept drops on image */
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
NULL, GDK_ACTION_COPY);
gtk_drag_dest_add_image_targets (image);
g_signal_connect (image, "drag-data-received",
G_CALLBACK (drag_data_received), image);
formats = gdk_content_formats_new_for_gtype (GDK_TYPE_TEXTURE);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (dest));
/* context menu on image */
gesture = gtk_gesture_click_new ();
@@ -337,22 +363,21 @@ do_clipboard (GtkWidget *do_widget)
/* Create the second image */
image = gtk_image_new_from_icon_name ("process-stop");
gtk_image_set_pixel_size (GTK_IMAGE (image), 48);
gtk_container_add (GTK_CONTAINER (hbox), image);
/* make image a drag source */
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag-begin",
G_CALLBACK (drag_begin), image);
g_signal_connect (image, "drag-data-get",
G_CALLBACK (drag_data_get), image);
source = gtk_drag_source_new ();
g_signal_connect (source, "prepare", G_CALLBACK (prepare_drag), NULL);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
/* accept drops on image */
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
NULL, GDK_ACTION_COPY);
gtk_drag_dest_add_image_targets (image);
g_signal_connect (image, "drag-data-received",
G_CALLBACK (drag_data_received), image);
formats = gdk_content_formats_new_for_gtype (GDK_TYPE_TEXTURE);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (dest));
/* context menu on image */
gesture = gtk_gesture_click_new ();
+1
View File
@@ -97,6 +97,7 @@ do_infobar (GtkWidget *do_widget)
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
gtk_info_bar_set_default_response (GTK_INFO_BAR (bar), GTK_RESPONSE_OK);
button = gtk_toggle_button_new_with_label ("Question");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+79 -74
View File
@@ -5,9 +5,6 @@
#include <gtk/gtk.h>
/* Drag 'n Drop */
static const char *target_table[] = {
"text/uri-list"
};
typedef struct
{
@@ -76,30 +73,11 @@ search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
gtk_tree_model_filter_refilter (win->filter_model);
}
static GdkPixbuf *
get_icon (GtkWidget *image, const gchar *name, gint size)
{
GtkIconInfo *info;
GtkStyleContext *context;
GdkTexture *texture;
GdkPixbuf *pixbuf;
context = gtk_widget_get_style_context (image);
info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (), name, size, 0);
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (info, context, NULL, NULL));
pixbuf = gdk_pixbuf_get_from_texture (texture);
g_object_unref (texture);
g_object_unref (info);
return pixbuf;
}
static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
gtk_drag_source_set_icon_name (image, name);
}
static void
@@ -365,78 +343,107 @@ search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *w
gtk_list_box_unselect_all (GTK_LIST_BOX (win->context_list));
}
static void
get_image_data (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
guint target_info,
gpointer data)
static GdkPaintable *
get_image_paintable (GtkImage *image)
{
GtkWidget *image;
const gchar *name;
gint size;
GdkPixbuf *pixbuf;
const gchar *icon_name;
GtkIconTheme *icon_theme;
GtkIconInfo *icon_info;
int size;
image = gtk_bin_get_child (GTK_BIN (widget));
name = gtk_image_get_icon_name (GTK_IMAGE (image));
size = gtk_image_get_pixel_size (GTK_IMAGE (image));
pixbuf = get_icon (image, name, size);
gtk_selection_data_set_pixbuf (selection, pixbuf);
g_object_unref (pixbuf);
switch (gtk_image_get_storage_type (image))
{
case GTK_IMAGE_PAINTABLE:
return g_object_ref (gtk_image_get_paintable (image));
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
size = gtk_image_get_pixel_size (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size,
GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (icon_info == NULL)
return NULL;
return gtk_icon_info_load_icon (icon_info, NULL);
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
return NULL;
}
}
static void
get_scalable_image_data (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
guint target_info,
gpointer data)
drag_begin (GtkDragSource *source,
GdkDrag *drag,
GtkWidget *widget)
{
gchar *uris[2];
GtkIconInfo *info;
GtkWidget *image;
GFile *file;
const gchar *name;
GdkPaintable *paintable;
image = gtk_bin_get_child (GTK_BIN (widget));
name = gtk_image_get_icon_name (GTK_IMAGE (image));
paintable = get_image_paintable (GTK_IMAGE (widget));
if (paintable)
{
int w, h;
w = gdk_paintable_get_intrinsic_width (paintable);
h = gdk_paintable_get_intrinsic_height (paintable);
gtk_drag_source_set_icon (source, paintable, w, h);
g_object_unref (paintable);
}
}
static void
get_texture (GValue *value,
gpointer data)
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
if (GDK_IS_TEXTURE (paintable))
g_value_set_object (value, paintable);
}
static void
get_file (GValue *value,
gpointer data)
{
const char *name;
GtkIconInfo *info;
GFile *file;
name = gtk_image_get_icon_name (GTK_IMAGE (data));
info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (), name, -1, 0);
file = g_file_new_for_path (gtk_icon_info_get_filename (info));
uris[0] = g_file_get_uri (file);
uris[1] = NULL;
gtk_selection_data_set_uris (selection, uris);
g_free (uris[0]);
g_object_unref (info);
g_value_set_object (value, file);
g_object_unref (file);
g_object_unref (info);
}
static void
setup_image_dnd (GtkWidget *image)
{
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
gtk_drag_source_add_image_targets (image);
g_signal_connect (image, "drag-data-get", G_CALLBACK (get_image_data), NULL);
GdkContentProvider *content;
GtkDragSource *source;
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
}
static void
setup_scalable_image_dnd (GtkWidget *image)
{
GtkWidget *parent;
GdkContentFormats *targets;
GdkContentProvider *content;
GtkDragSource *source;
parent = gtk_widget_get_parent (image);
targets = gdk_content_formats_new (target_table, G_N_ELEMENTS (target_table));
gtk_drag_source_set (parent, GDK_BUTTON1_MASK,
targets,
GDK_ACTION_COPY);
gdk_content_formats_unref (targets);
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (G_TYPE_FILE, get_file, image);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (parent, "drag-data-get", G_CALLBACK (get_scalable_image_data), NULL);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
}
static void
@@ -446,8 +453,7 @@ icon_browser_window_init (IconBrowserWindow *win)
gtk_widget_init_template (GTK_WIDGET (win));
list = gdk_content_formats_new (NULL, 0);
list = gtk_content_formats_add_text_targets (list);
list = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (win->list),
GDK_BUTTON1_MASK,
list,
@@ -459,7 +465,6 @@ icon_browser_window_init (IconBrowserWindow *win)
setup_image_dnd (win->image3);
setup_image_dnd (win->image4);
setup_image_dnd (win->image5);
setup_image_dnd (win->image6);
setup_scalable_image_dnd (win->image6);
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
+7 -1
View File
@@ -344,6 +344,13 @@
<xi:include href="xml/gtkpadcontroller.xml" />
</chapter>
<chapter>
<title>Data exchange, clipboards and Drag-and-Drop</title>
<xi:include href="xml/gtkdragsource.xml"/>
<xi:include href="xml/gtkdragicon.xml"/>
<xi:include href="xml/gtkdroptarget.xml"/>
</chapter>
</part>
<part id="gtkbase">
@@ -352,7 +359,6 @@
<xi:include href="xml/gtkfeatures.xml" />
<xi:include href="xml/gtkaccelgroup.xml" />
<xi:include href="xml/gtkaccelmap.xml" />
<xi:include href="xml/gtkdnd.xml" />
<xi:include href="xml/gtksettings.xml" />
<xi:include href="xml/gtkbindings.xml" />
<xi:include href="xml/gtkenums.xml" />
+66 -43
View File
@@ -5001,49 +5001,6 @@ GTK_TYPE_SELECTION_DATA
gtk_selection_data_get_type
</SECTION>
<SECTION>
<FILE>gtkdnd</FILE>
<TITLE>Drag and Drop</TITLE>
GtkDestDefaults
GtkDragResult
<SUBSECTION Destination Side>
gtk_drag_dest_set
gtk_drag_dest_unset
gtk_drag_dest_find_target
gtk_drag_dest_get_target_list
gtk_drag_dest_set_target_list
gtk_drag_dest_add_text_targets
gtk_drag_dest_add_image_targets
gtk_drag_dest_add_uri_targets
gtk_drag_dest_set_track_motion
gtk_drag_dest_get_track_motion
gtk_drag_get_data
gtk_drag_get_source_widget
gtk_drag_highlight
gtk_drag_unhighlight
<SUBSECTION Source Side>
gtk_drag_begin
gtk_drag_cancel
gtk_drag_set_icon_widget
gtk_drag_set_icon_paintable
gtk_drag_set_icon_name
gtk_drag_set_icon_gicon
gtk_drag_set_icon_default
gtk_drag_check_threshold
gtk_drag_source_set
gtk_drag_source_set_icon_name
gtk_drag_source_set_icon_gicon
gtk_drag_source_set_icon_paintable
gtk_drag_source_unset
gtk_drag_source_set_target_list
gtk_drag_source_get_target_list
gtk_drag_source_add_text_targets
gtk_drag_source_add_image_targets
gtk_drag_source_add_uri_targets
</SECTION>
<SECTION>
<FILE>gtkbindings</FILE>
<TITLE>Bindings</TITLE>
@@ -7191,3 +7148,69 @@ gtk_constraint_guide_get_max_size
GTK_TYPE_CONSTRAINT_GUIDE
gtk_constraint_guide_get_tyoe
</SECTION>
<SECTION>
<FILE>gtkdragsource</FILE>
GtkDragSource
gtk_drag_source_new
gtk_drag_source_set_content
gtk_drag_source_get_content
gtk_drag_source_set_actions
gtk_drag_source_get_actions
gtk_drag_source_set_icon
gtk_drag_source_drag_cancel
gtk_drag_source_get_drag
gtk_drag_check_threshold
<SUBSECTION Standard>
GTK_TYPE_DRAG_SOURCE
GTK_DRAG_SOURCE
GTK_DRAG_SOURCE_CLASS
GTK_IS_DRAG_SOURCE
GTK_IS_DRAG_SOURCE_CLASS
GTK_DRAG_SOURCE_GET_CLASS
<SUBSECTION Private>
gtk_drag_source_get_type
</SECTION>
<SECTION>
<FILE>gtkdroptarget</FILE>
GtkDropTarget
gtk_drop_target_new
gtk_drop_target_set_formats
gtk_drop_target_get_formats
gtk_drop_target_set_actions
gtk_drop_target_get_actions
gtk_drop_target_get_drop
gtk_drop_target_find_mimetype
gtk_drop_target_read_selection
gtk_drop_target_read_selection_finish
gtk_drag_highlight
gtk_drag_unhighlight
<SUBSECTION Standard>
GTK_TYPE_DROP_TARGET
GTK_DROP_TARGET
GTK_DROP_TARGET_CLASS
GTK_IS_DROP_TARGET
GTK_IS_DROP_TARGET_CLASS
GTK_DROP_TARGET_GET_CLASS
<SUBSECTION Private>
gtk_drop_target_get_type
</SECTION>
<SECTION>
<FILE>gtkdragicon</FILE>
GtkDragIcon
gtk_drag_icon_new_for_drag
gtk_drag_icon_set_from_paintable
<SUBSECTION Standard>
GTK_TYPE_DRAG_ICON
GTK_DRAG_ICON
GTK_DRAG_ICON_CLASS
GTK_IS_DRAG_ICON
GTK_IS_DRAG_ICON_CLASS
GTK_DRAG_ICON_GET_CLASS
<SUBSECTION Private>
gtk_drag_icon_get_type
</SECTION>
+3
View File
@@ -57,7 +57,10 @@ gtk_constraint_target_get_type
gtk_container_get_type
gtk_css_provider_get_type
gtk_dialog_get_type
gtk_drag_icon_get_type
gtk_drag_source_get_type
gtk_drawing_area_get_type
gtk_drop_target_get_type
gtk_editable_get_type
gtk_entry_buffer_get_type
gtk_entry_completion_get_type
-2
View File
@@ -48,7 +48,6 @@ private_headers = [
'gtkcssfontfeaturesvalueprivate.h',
'gtkcssfontvariationsvalueprivate.h',
'gtkcssiconthemevalueprivate.h',
'gtkcssimagebuiltinprivate.h',
'gtkcssimagecrossfadeprivate.h',
'gtkcssimagefallbackprivate.h',
'gtkcssimageiconthemeprivate.h',
@@ -97,7 +96,6 @@ private_headers = [
'gtkcsswidgetnodeprivate.h',
'gtkcsswin32sizevalueprivate.h',
'gtkdialogprivate.h',
'gtkdndprivate.h',
'gtkentryprivate.h',
'gtkeventcontrollerlegacyprivate.h',
'gtkeventcontrollerprivate.h',
+31
View File
@@ -903,6 +903,37 @@
gtk_tooltip_set_custom().
</para>
</section>
<section>
<title>Switch to the new DND api</title>
<para>
The source-side DND apis in GTK 4 have been changed to use an event controller, #GtkDragSource.
</para>
<para>
Instead of calling gtk_drag_source_set() and connecting to #GtkWidget signals, you create
a #GtkDragSource object, attach it to the widget with gtk_widget_add_controller(), and connect
to #GtkDragSource signals. Instead of calling gtk_drag_begin() on a widget to start a drag
manually, call gdk_drag_begin().
</para>
<para>
The ::drag-data-get signal has been replaced by the #GtkDragSource::prepare signal, which
returns a #GdkContentProvider for the drag operation.
</para>
<para>
The destination-side DND apis in GTK 4 have also been changed to use and event controller,
#GTkDropTarget.
</para>
<para>
Instead of calling gtk_drag_dest_set() and connecting to #GtkWidget signals, you create
a #GtkDropTarget object, attach it to the widget with gtk_widget_add_controller(), and
connect to #GtkDropTarget signals.
</para>
<para>
The ::drag-motion signal has been renamed to #GtkDragSource::accept, and instead of
::drag-data-received, you need to use async read methods on the #GdkDrop object, such
as gdk_drop_read_value_async() or gdk_drop_read_text_async().
</para>
</section>
</section>
</chapter>
+100 -13
View File
@@ -42,29 +42,116 @@
#include "filetransferportalprivate.h"
static GDBusProxy *file_transfer_proxy = NULL;
static gboolean done;
static guint timeout_id;
static void
got_proxy (GObject *source,
GAsyncResult *result,
gpointer data)
{
GError *error = NULL;
file_transfer_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
if (!file_transfer_proxy)
{
g_message ("failed to get file transfer portal proxy: %s", error->message);
g_error_free (error);
}
if (timeout_id)
{
g_source_remove (timeout_id);
timeout_id = 0;
}
done = TRUE;
g_main_context_wakeup (NULL);
}
static void
got_bus (GObject *source,
GAsyncResult *result,
gpointer data)
{
GDBusConnection **bus = data;
GError *error = NULL;
*bus = g_bus_get_finish (result, &error);
if (!*bus)
{
g_message ("failed to get session bus connection: %s", error->message);
g_error_free (error);
}
if (timeout_id)
{
g_source_remove (timeout_id);
timeout_id = 0;
}
done = TRUE;
g_main_context_wakeup (NULL);
}
static gboolean
give_up_on_proxy (gpointer data)
{
GCancellable *cancellable = data;
g_cancellable_cancel (cancellable);
timeout_id = 0;
done = TRUE;
g_main_context_wakeup (NULL);
return G_SOURCE_REMOVE;
}
static GDBusProxy *
ensure_file_transfer_portal (void)
{
if (file_transfer_proxy == NULL)
{
GError *error = NULL;
GCancellable *cancellable;
GDBusConnection *bus = NULL;
file_transfer_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
| G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.FileTransfer",
NULL, &error);
cancellable = g_cancellable_new ();
done = FALSE;
timeout_id = g_timeout_add (500, give_up_on_proxy, cancellable);
g_bus_get (G_BUS_TYPE_SESSION,
cancellable,
got_bus,
&bus);
if (error)
while (!done)
g_main_context_iteration (NULL, TRUE);
if (bus)
{
g_debug ("Failed to get proxy: %s", error->message);
g_error_free (error);
done = FALSE;
timeout_id = g_timeout_add (500, give_up_on_proxy, cancellable);
g_dbus_proxy_new (bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
| G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.FileTransfer",
cancellable,
got_proxy,
NULL);
while (!done)
g_main_context_iteration (NULL, TRUE);
g_clear_object (&bus);
}
g_clear_object (&cancellable);
}
if (file_transfer_proxy)
+64
View File
@@ -24,6 +24,7 @@
#include "gdkcontentformats.h"
#include "filetransferportalprivate.h"
#include "gdktexture.h"
#include "gdkrgbaprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -848,6 +849,63 @@ file_uri_deserializer (GdkContentDeserializer *deserializer)
g_object_unref (output);
}
static void
color_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
gssize written;
written = g_output_stream_splice_finish (stream, result, &error);
if (written < 0)
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
else if (written == 0)
{
GdkRGBA black = GDK_RGBA ("000");
/* Never return NULL, we only return that on error */
g_value_set_boxed (gdk_content_deserializer_get_value (deserializer), &black);
}
else
{
guint16 *data;
GdkRGBA rgba;
data = (guint16 *)g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream));
rgba.red = data[0] / 65535.0;
rgba.green = data[1] / 65535.0;
rgba.blue = data[2] / 65535.0;
rgba.alpha = data[3] / 65535.0;
g_value_set_boxed (gdk_content_deserializer_get_value (deserializer), &rgba);
}
gdk_content_deserializer_return_success (deserializer);
}
static void
color_deserializer (GdkContentDeserializer *deserializer)
{
GOutputStream *output;
guint16 *data;
data = g_new0 (guint16, 4);
output = g_memory_output_stream_new (data, 4 * sizeof (guint16), NULL, g_free);
g_output_stream_splice_async (output,
gdk_content_deserializer_get_input_stream (deserializer),
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
gdk_content_deserializer_get_priority (deserializer),
gdk_content_deserializer_get_cancellable (deserializer),
color_deserializer_finish,
deserializer);
g_object_unref (output);
}
static void
init (void)
{
@@ -956,5 +1014,11 @@ init (void)
string_deserializer,
(gpointer) "ASCII",
NULL);
gdk_content_register_deserializer ("application/x-color",
GDK_TYPE_RGBA,
color_deserializer,
NULL,
NULL);
}
+230
View File
@@ -21,6 +21,7 @@
#include "gdkcontentprovider.h"
#include "gdkcontentformats.h"
#include "gdkcontentserializer.h"
#include "gdkintl.h"
#include "gdkcontentproviderimpl.h"
@@ -280,3 +281,232 @@ gdk_content_provider_new_for_bytes (const char *mime_type,
return GDK_CONTENT_PROVIDER (content);
}
#define GDK_TYPE_CONTENT_PROVIDER_CALLBACK (gdk_content_provider_callback_get_type ())
#define GDK_CONTENT_PROVIDER_CALLBACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK, GdkContentProviderCallback))
typedef struct _GdkContentProviderCallback GdkContentProviderCallback;
typedef struct _GdkContentProviderCallbackClass GdkContentProviderCallbackClass;
struct _GdkContentProviderCallback
{
GdkContentProvider parent;
GType type;
GdkContentProviderGetValueFunc func;
gpointer data;
};
struct _GdkContentProviderCallbackClass
{
GdkContentProviderClass parent_class;
};
GType gdk_content_provider_callback_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GdkContentProviderCallback, gdk_content_provider_callback, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gdk_content_provider_callback_ref_formats (GdkContentProvider *provider)
{
GdkContentProviderCallback *callback = GDK_CONTENT_PROVIDER_CALLBACK (provider);
return gdk_content_formats_new_for_gtype (callback->type);
}
static gboolean
gdk_content_provider_callback_get_value (GdkContentProvider *provider,
GValue *value,
GError **error)
{
GdkContentProviderCallback *callback = GDK_CONTENT_PROVIDER_CALLBACK (provider);
if (G_VALUE_HOLDS (value, callback->type) && callback->func != NULL)
{
callback->func (value, callback->data);
return TRUE;
}
return GDK_CONTENT_PROVIDER_CLASS (gdk_content_provider_callback_parent_class)->get_value (provider, value, error);
}
static void
gdk_content_provider_callback_class_init (GdkContentProviderCallbackClass *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
provider_class->ref_formats = gdk_content_provider_callback_ref_formats;
provider_class->get_value = gdk_content_provider_callback_get_value;
}
static void
gdk_content_provider_callback_init (GdkContentProviderCallback *content)
{
}
/**
* gdk_content_provider_new_for_callback:
* @type: the type that the callback provides
* @func: callback to populate a #GValue
* @data: (closure): data that gets passed to @func
*
* Create a content provider that provides data that is provided via a callback.
*
* Returns: a new #GdkContentProvider
**/
GdkContentProvider *
gdk_content_provider_new_with_callback (GType type,
GdkContentProviderGetValueFunc func,
gpointer data)
{
GdkContentProviderCallback *content;
content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK, NULL);
content->type = type;
content->func = func;
content->data = data;
return GDK_CONTENT_PROVIDER (content);
}
#define GDK_TYPE_CONTENT_PROVIDER_CALLBACK2 (gdk_content_provider_callback2_get_type ())
#define GDK_CONTENT_PROVIDER_CALLBACK2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, GdkContentProviderCallback2))
typedef struct _GdkContentProviderCallback2 GdkContentProviderCallback2;
typedef struct _GdkContentProviderCallback2Class GdkContentProviderCallback2Class;
struct _GdkContentProviderCallback2
{
GdkContentProvider parent;
GdkContentFormats *formats;
GdkContentProviderGetBytesFunc func;
gpointer data;
};
struct _GdkContentProviderCallback2Class
{
GdkContentProviderClass parent_class;
};
GType gdk_content_provider_callback2_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GdkContentProviderCallback2, gdk_content_provider_callback2, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gdk_content_provider_callback2_ref_formats (GdkContentProvider *provider)
{
GdkContentProviderCallback2 *callback = GDK_CONTENT_PROVIDER_CALLBACK2 (provider);
return gdk_content_formats_ref (callback->formats);
}
static void
gdk_content_provider_callback2_write_mime_type_done (GObject *stream,
GAsyncResult *result,
gpointer task)
{
GError *error = NULL;
if (!g_output_stream_write_all_finish (G_OUTPUT_STREAM (stream), result, NULL, &error))
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
gdk_content_provider_callback2_write_mime_type_async (GdkContentProvider *provider,
const char *mime_type,
GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GdkContentProviderCallback2 *content = GDK_CONTENT_PROVIDER_CALLBACK2 (provider);
GTask *task;
GBytes *bytes;
task = g_task_new (content, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gdk_content_provider_callback2_write_mime_type_async);
if (!gdk_content_formats_contain_mime_type (content->formats, mime_type))
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Cannot provide contents as “%s”"), mime_type);
g_object_unref (task);
return;
}
bytes = content->func (mime_type, content->data);
if (!bytes)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Failed to get contents as “%s”"), mime_type);
g_object_unref (task);
return;
}
g_object_set_data_full (G_OBJECT (task), "bytes", bytes, (GDestroyNotify)g_bytes_unref);
g_output_stream_write_all_async (stream,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
io_priority,
cancellable,
gdk_content_provider_callback2_write_mime_type_done,
task);
}
static gboolean
gdk_content_provider_callback2_write_mime_type_finish (GdkContentProvider *provider,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, provider), FALSE);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_content_provider_callback2_write_mime_type_async, FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
gdk_content_provider_callback2_class_init (GdkContentProviderCallback2Class *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
provider_class->ref_formats = gdk_content_provider_callback2_ref_formats;
provider_class->write_mime_type_async = gdk_content_provider_callback2_write_mime_type_async;
provider_class->write_mime_type_finish = gdk_content_provider_callback2_write_mime_type_finish;
}
static void
gdk_content_provider_callback2_init (GdkContentProviderCallback2 *content)
{
}
/**
* gdk_content_provider_new_with_formats:
* @formats: formats to advertise
* @func: callback to populate a #GValue
* @data: data that gets passed to @func
*
* Create a content provider that provides data that is provided via a callback.
*
* Returns: a new #GdkContentProvider
**/
GdkContentProvider *
gdk_content_provider_new_with_formats (GdkContentFormats *formats,
GdkContentProviderGetBytesFunc func,
gpointer data)
{
GdkContentProviderCallback2 *content;
content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, NULL);
content->formats = gdk_content_formats_union_serialize_mime_types (gdk_content_formats_ref (formats));
content->func = func;
content->data = data;
return GDK_CONTENT_PROVIDER (content);
}
+15
View File
@@ -35,6 +35,21 @@ GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_for_bytes (const char *mime_type,
GBytes *bytes);
typedef void (*GdkContentProviderGetValueFunc) (GValue *value,
gpointer data);
GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_with_callback (GType type,
GdkContentProviderGetValueFunc func,
gpointer data);
typedef GBytes * (*GdkContentProviderGetBytesFunc) (const char *mime_type,
gpointer data);
GDK_AVAILABLE_IN_ALL
GdkContentProvider * gdk_content_provider_new_with_formats (GdkContentFormats *formats,
GdkContentProviderGetBytesFunc func,
gpointer data);
G_END_DECLS
+49
View File
@@ -25,6 +25,7 @@
#include "gdkpixbuf.h"
#include "filetransferportalprivate.h"
#include "gdktextureprivate.h"
#include "gdkrgba.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <string.h>
@@ -862,6 +863,48 @@ file_text_serializer (GdkContentSerializer *serializer)
gdk_content_serializer_set_task_data (serializer, path, g_free);
}
static void
color_serializer_finish (GObject *source,
GAsyncResult *result,
gpointer serializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
if (!g_output_stream_write_all_finish (stream, result, NULL, &error))
gdk_content_serializer_return_error (serializer, error);
else
gdk_content_serializer_return_success (serializer);
}
static void
color_serializer (GdkContentSerializer *serializer)
{
const GValue *value;
GdkRGBA *rgba;
guint16 *data;
value = gdk_content_serializer_get_value (serializer);
rgba = g_value_get_boxed (value);
data = g_new0 (guint16, 4);
if (rgba)
{
data[0] = (guint16) (rgba->red * 65535);
data[1] = (guint16) (rgba->green * 65535);
data[2] = (guint16) (rgba->blue * 65535);
data[3] = (guint16) (rgba->alpha * 65535);
}
g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
data,
4 * sizeof (guint16),
gdk_content_serializer_get_priority (serializer),
gdk_content_serializer_get_cancellable (serializer),
color_serializer_finish,
serializer);
gdk_content_serializer_set_task_data (serializer, data, g_free);
}
static void
init (void)
{
@@ -984,5 +1027,11 @@ init (void)
string_serializer,
(gpointer) "ASCII",
NULL);
gdk_content_register_serializer (GDK_TYPE_RGBA,
"application/x-color",
color_serializer,
NULL,
NULL);
}
+17 -7
View File
@@ -90,20 +90,30 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkDrag, gdk_drag, G_TYPE_OBJECT)
/**
* SECTION:dnd
* @title: Drag And Drop
* @short_description: Functions for controlling drag and drop handling
* @Title: Drag And Drop
* @Short_description: Functions for controlling drag and drop handling
*
* These functions provide a low level interface for drag and drop.
* These functions provide a low-level interface for drag and drop.
*
* The GdkDrag object represents the source side of an ongoing DND operation.
* It is created when a drag is started, and stays alive for duration of
* the DND operation.
* the DND operation. After a drag has been started with gdk_drag_begin(),
* the caller gets informed about the status of the ongoing drag operation
* with signals on the #GtkDrag object.
*
* The GdkDrop object represents the target side of an ongoing DND operation.
* Possible drop sites get informed about the status of the ongoing drag operation
* with events of type %GDK_DRAG_ENTER, %GDK_DRAG_LEAVE, %GDK_DRAG_MOTION and
* %GDK_DROP_START. The #GdkDrop object can be obtained from these #GdkEvents
* using gdk_event_get_drop().
*
* The actual data transfer is initiated from the target side via an async
* read, using one of the GdkDrop functions for this purpose: gdk_drop_read_async(),
* gdk_drop_read_value_async() or gdk_drop_read_text_async().
*
* GTK+ provides a higher level abstraction based on top of these functions,
* and so they are not normally needed in GTK+ applications. See the
* [Drag and Drop][gtk4-Drag-and-Drop] section of the GTK+ documentation
* GTK provides a higher level abstraction based on top of these functions,
* and so they are not normally needed in GTK applications. See the
* [Drag and Drop][gtk4-Drag-and-Drop] section of the GTK documentation
* for more information.
*/
+27
View File
@@ -1001,3 +1001,30 @@ gdk_drop_emit_drop_event (GdkDrop *self,
gdk_drop_do_emit_event (event, dont_queue);
}
/**
* gdk_drop_has_value:
* @self: a #GdkDrop
* @type: the type to check
*
* Returns whether calling gdk_drop_read_value_async() for @type
* can succeed.
*
* Returns: %TRUE if the data can be deserialized to the given type
*/
gboolean
gdk_drop_has_value (GdkDrop *self,
GType type)
{
GdkContentFormats *formats;
gboolean ret;
formats = gdk_content_formats_ref (gdk_drop_get_formats (self));
formats = gdk_content_formats_union_deserialize_gtypes (formats);
ret = gdk_content_formats_contain_gtype (formats, type);
gdk_content_formats_unref (formats);
return ret;
}
+3
View File
@@ -92,6 +92,9 @@ char * gdk_drop_read_text_finish (GdkDrop
GAsyncResult *result,
GError **error);
GDK_AVAILABLE_IN_ALL
gboolean gdk_drop_has_value (GdkDrop *self,
GType type);
G_END_DECLS
+7
View File
@@ -1013,6 +1013,13 @@ gdk_event_set_coords (GdkEvent *event,
event->touchpad_pinch.x = x;
event->touchpad_pinch.y = y;
break;
case GDK_DRAG_ENTER:
case GDK_DRAG_LEAVE:
case GDK_DRAG_MOTION:
case GDK_DROP_START:
event->dnd.x = x;
event->dnd.y = y;
break;
default:
break;
}
+2 -2
View File
@@ -248,10 +248,10 @@ gdk_seat_get_capabilities (GdkSeat *seat)
* elsewhere.
* @event: (nullable): the event that is triggering the grab, or %NULL if none
* is available.
* @prepare_func: (nullable) (scope call) (closure prepare_func_data): function to
* @prepare_func: (nullable) (scope call): function to
* prepare the surface to be grabbed, it can be %NULL if @surface is
* visible before this call.
* @prepare_func_data: user data to pass to @prepare_func
* @prepare_func_data: (closure): user data to pass to @prepare_func
*
* Grabs the seat so that all events corresponding to the given @capabilities
* are passed to this application until the seat is ungrabbed with gdk_seat_ungrab(),
+7 -1
View File
@@ -3583,7 +3583,13 @@ gdk_surface_register_dnd (GdkSurface *surface)
*
* Starts a drag and creates a new drag context for it.
*
* This function is called by the drag source.
* This function is called by the drag source. After this call, you
* probably want to set up the drag icon using the surface returned
* by gdk_drag_get_drag_surface().
*
* Note: if @actions include %GDK_ACTION_MOVE, you need to listen for
* the #GdkDrag::dnd-finished signal and delete the data at the source
* if gdk_drag_get_selected_action() returns %GDK_ACTION_MOVE.
*
* Returns: (transfer full) (nullable): a newly created #GdkDrag or
* %NULL on error.
+14 -16
View File
@@ -680,7 +680,6 @@ gdk_quartz_keymap_translate_keyboard_state (GdkKeymap *keymap,
{
guint tmp_keyval;
GdkModifierType bit;
guint tmp_modifiers = 0;
if (keyval)
*keyval = 0;
@@ -694,24 +693,23 @@ gdk_quartz_keymap_translate_keyboard_state (GdkKeymap *keymap,
if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
return FALSE;
/* Check if modifiers modify the keyval */
for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
{
if (translate_keysym (hardware_keycode,
(bit == GDK_MOD1_MASK) ? 0 : group,
state & ~bit,
NULL, NULL) !=
translate_keysym (hardware_keycode,
(bit == GDK_MOD1_MASK) ? 1 : group,
state | bit,
NULL, NULL))
tmp_modifiers |= bit;
}
tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
/* Check if modifiers modify the keyval */
if (consumed_modifiers)
*consumed_modifiers = tmp_modifiers;
{
guint tmp_modifiers = (state & GDK_MODIFIER_MASK);
for (bit = 1; bit <= tmp_modifiers; bit <<= 1)
{
if ((bit & tmp_modifiers) &&
translate_keysym (hardware_keycode, group, state & ~bit,
NULL, NULL) == tmp_keyval)
tmp_modifiers &= ~bit;
}
*consumed_modifiers = tmp_modifiers;
}
if (keyval)
*keyval = tmp_keyval;
+1 -1
View File
@@ -4109,7 +4109,7 @@ gdk_wayland_surface_is_exported (GdkSurface *surface)
* gdk_wayland_surface_export_handle:
* @surface: the #GdkSurface to obtain a handle for
* @callback: callback to call with the handle
* @user_data: user data for @callback
* @user_data: (closure): user data for @callback
* @destroy_func: destroy notify for @user_data
*
* Asynchronously obtains a handle for a surface that can be passed
+26 -21
View File
@@ -1061,6 +1061,7 @@ xdnd_send_enter (GdkX11Drag *drag_x11)
{
GdkDrag *drag = GDK_DRAG (drag_x11);
GdkDisplay *display = gdk_drag_get_display (drag);
GdkContentFormats *formats;
const char * const *atoms;
gsize i, n_atoms;
XEvent xev;
@@ -1080,7 +1081,10 @@ xdnd_send_enter (GdkX11Drag *drag_x11)
GDK_DISPLAY_NOTE (display, DND,
g_message ("Sending enter source window %#lx XDND protocol version %d\n",
GDK_SURFACE_XID (drag_x11->ipc_surface), drag_x11->version));
atoms = gdk_content_formats_get_mime_types (gdk_drag_get_formats (drag), &n_atoms);
formats = gdk_content_formats_ref (gdk_drag_get_formats (drag));
formats = gdk_content_formats_union_serialize_mime_types (formats);
atoms = gdk_content_formats_get_mime_types (formats, &n_atoms);
if (n_atoms > 3)
{
@@ -1300,8 +1304,7 @@ xdnd_precache_atoms (GdkDisplay *display)
/* Source side */
static void
gdk_drag_do_leave (GdkX11Drag *drag_x11,
guint32 time)
gdk_drag_do_leave (GdkX11Drag *drag_x11)
{
if (drag_x11->proxy_xid)
{
@@ -1502,27 +1505,10 @@ gdk_x11_drag_drag_motion (GdkDrag *drag,
}
}
/* When we have a Xdnd target, make sure our XdndActionList
* matches the current actions;
*/
if (protocol == GDK_DRAG_PROTO_XDND && drag_x11->xdnd_actions != gdk_drag_get_actions (drag))
{
if (proxy_xid)
{
GdkDisplay *display = gdk_drag_get_display (drag);
GdkDrop *drop = GDK_X11_DISPLAY (display)->current_drop;
if (drop && GDK_SURFACE_XID (gdk_drop_get_surface (drop)) == proxy_xid)
gdk_x11_drop_read_actions (drop);
else
xdnd_set_actions (drag_x11);
}
}
if (drag_x11->proxy_xid != proxy_xid)
{
/* Send a leave to the last destination */
gdk_drag_do_leave (drag_x11, time);
gdk_drag_do_leave (drag_x11);
drag_x11->drag_status = GDK_DRAG_STATUS_DRAG;
/* Check if new destination accepts drags, and which protocol */
@@ -1558,6 +1544,23 @@ gdk_x11_drag_drag_motion (GdkDrag *drag,
drag_x11->current_action = gdk_drag_get_selected_action (drag);
}
/* When we have a Xdnd target, make sure our XdndActionList
* matches the current actions;
*/
if (protocol == GDK_DRAG_PROTO_XDND && drag_x11->xdnd_actions != gdk_drag_get_actions (drag))
{
if (proxy_xid)
{
GdkDisplay *display = gdk_drag_get_display (drag);
GdkDrop *drop = GDK_X11_DISPLAY (display)->current_drop;
if (drop && GDK_SURFACE_XID (gdk_drop_get_surface (drop)) == proxy_xid)
gdk_x11_drop_read_actions (drop);
else
xdnd_set_actions (drag_x11);
}
}
/* Send a drag-motion event */
drag_x11->last_x = x_root;
@@ -1814,6 +1817,7 @@ struct _GdkDragAnim {
static void
gdk_drag_anim_destroy (GdkDragAnim *anim)
{
gdk_surface_hide (anim->drag->drag_surface);
g_object_unref (anim->drag);
g_slice_free (GdkDragAnim, anim);
}
@@ -2137,6 +2141,7 @@ static void
gdk_x11_drag_cancel (GdkDrag *drag,
GdkDragCancelReason reason)
{
gdk_drag_do_leave (GDK_X11_DRAG (drag));
drag_ungrab (drag);
gdk_drag_drop_done (drag, FALSE);
}
+13 -2
View File
@@ -747,7 +747,7 @@ gdk_x11_drop_status (GdkDrop *drop,
GdkDragAction actions)
{
GdkX11Drop *drop_x11 = GDK_X11_DROP (drop);
GdkDragAction possible_actions;
GdkDragAction possible_actions, suggested_action;
XEvent xev;
GdkDisplay *display;
@@ -755,6 +755,17 @@ gdk_x11_drop_status (GdkDrop *drop,
possible_actions = actions & gdk_drop_get_actions (drop);
if (drop_x11->suggested_action != 0)
suggested_action = drop_x11->suggested_action;
else if (possible_actions & GDK_ACTION_COPY)
suggested_action = GDK_ACTION_COPY;
else if (possible_actions & GDK_ACTION_MOVE)
suggested_action = GDK_ACTION_MOVE;
else if (possible_actions & GDK_ACTION_ASK)
suggested_action = GDK_ACTION_ASK;
else
suggested_action = 0;
xev.xclient.type = ClientMessage;
xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "XdndStatus");
xev.xclient.format = 32;
@@ -764,7 +775,7 @@ gdk_x11_drop_status (GdkDrop *drop,
xev.xclient.data.l[1] = (possible_actions != 0) ? (2 | 1) : 0;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = xdnd_action_to_atom (display, possible_actions);
xev.xclient.data.l[4] = xdnd_action_to_atom (display, suggested_action);
if (gdk_drop_get_drag (drop))
{
+1 -1
View File
@@ -90,8 +90,8 @@
#include <gtk/gtkcustomlayout.h>
#include <gtk/gtkdebug.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtkdnd.h>
#include <gtk/gtkdragdest.h>
#include <gtk/gtkdragicon.h>
#include <gtk/gtkdragsource.h>
#include <gtk/gtkdrawingarea.h>
#include <gtk/gtkeditable.h>
+2 -2
View File
@@ -412,7 +412,7 @@ gtk_builder_cscope_init (GtkBuilderCScope *self)
* Calling this function is only necessary if you want to add custom
* callbacks via gtk_builder_cscope_add_callback_symbol().
*
* Returns: a new #GtkBuilderCScope
* Returns: (transfer full): a new #GtkBuilderCScope
**/
GtkBuilderScope *
gtk_builder_cscope_new (void)
@@ -502,7 +502,7 @@ gtk_builder_cscope_add_callback_symbols (GtkBuilderCScope *self,
* Fetches a symbol previously added to @self
* with gtk_builder_cscope_add_callback_symbol().
*
* Returns: (nullable): The callback symbol in @builder for @callback_name, or %NULL
* Returns: (nullable) (transfer none): The callback symbol in @builder for @callback_name, or %NULL
*/
GCallback
gtk_builder_cscope_lookup_callback_symbol (GtkBuilderCScope *self,
+119 -133
View File
@@ -72,7 +72,6 @@
#endif
#include "gtkcalendar.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkintl.h"
#include "gtkmain.h"
@@ -87,6 +86,10 @@
#include "gtkgesturedrag.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkeventcontrollerkey.h"
#include "gtkdragsource.h"
#include "gtknative.h"
#include "gtkicontheme.h"
#include "gtkdragicon.h"
#define TIMEOUT_INITIAL 500
#define TIMEOUT_REPEAT 50
@@ -248,7 +251,6 @@ struct _GtkCalendarPrivate
guint need_timer : 1;
guint in_drag : 1;
guint drag_highlight : 1;
guint32 timer;
gint click_child;
@@ -329,22 +331,17 @@ static gboolean gtk_calendar_query_tooltip (GtkWidget *widget,
gboolean keyboard_mode,
GtkTooltip *tooltip);
static void gtk_calendar_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_calendar_drag_data_received (GtkWidget *widget,
static gboolean gtk_calendar_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
GtkSelectionData *selection_data);
static gboolean gtk_calendar_drag_motion (GtkWidget *widget,
GtkCalendar *calendar);
static void gtk_calendar_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
static void gtk_calendar_drag_leave (GtkWidget *widget,
GdkDrop *drop);
static gboolean gtk_calendar_drag_drop (GtkWidget *widget,
GtkCalendar *calendar);
static gboolean gtk_calendar_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
int x,
int y,
GtkCalendar *calendar);
static void calendar_start_spinning (GtkCalendar *calendar,
@@ -392,12 +389,6 @@ gtk_calendar_class_init (GtkCalendarClass *class)
widget_class->grab_notify = gtk_calendar_grab_notify;
widget_class->query_tooltip = gtk_calendar_query_tooltip;
widget_class->drag_data_get = gtk_calendar_drag_data_get;
widget_class->drag_motion = gtk_calendar_drag_motion;
widget_class->drag_leave = gtk_calendar_drag_leave;
widget_class->drag_drop = gtk_calendar_drag_drop;
widget_class->drag_data_received = gtk_calendar_drag_data_received;
/**
* GtkCalendar:year:
*
@@ -675,6 +666,8 @@ gtk_calendar_init (GtkCalendar *calendar)
#else
gchar *week_start;
#endif
GdkContentFormats *formats;
GtkDropTarget *dest;
gtk_widget_set_can_focus (widget, TRUE);
@@ -792,11 +785,17 @@ gtk_calendar_init (GtkCalendar *calendar)
priv->click_child = -1;
priv->in_drag = 0;
priv->drag_highlight = 0;
gtk_drag_dest_set (widget, 0, NULL, GDK_ACTION_COPY);
gtk_drag_dest_add_text_targets (widget);
formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "accept", G_CALLBACK (gtk_calendar_drag_accept), calendar);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_calendar_drag_leave), calendar);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_calendar_drag_drop), calendar);
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (dest));
priv->year_before = 0;
/* Translate to calendar:YM if you want years to be displayed
@@ -2395,7 +2394,6 @@ calendar_snapshot_arrow (GtkCalendar *calendar,
{
GtkWidget *widget = GTK_WIDGET (calendar);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GtkCssImageBuiltinType image_type;
GtkStyleContext *context;
GtkStateFlags state;
GdkRectangle rect;
@@ -2418,19 +2416,11 @@ calendar_snapshot_arrow (GtkCalendar *calendar,
rect.x, rect.y,
rect.width, rect.height);
if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
image_type = GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT;
else
image_type = GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT;
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT(
rect.x + (rect.width - 8) / 2,
rect.y + (rect.height - 8) / 2));
gtk_css_style_snapshot_icon (gtk_style_context_lookup_style (context),
snapshot,
8, 8,
image_type);
gtk_css_style_snapshot_icon (gtk_style_context_lookup_style (context), snapshot, 8, 8);
gtk_snapshot_restore (snapshot);
gtk_style_context_restore (context);
@@ -2670,6 +2660,27 @@ gtk_calendar_drag_begin (GtkGestureDrag *gesture,
priv->in_drag = TRUE;
}
static GdkContentProvider *
get_calendar_content (GtkCalendar *calendar)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GDate *date;
gchar str[128];
GValue value = G_VALUE_INIT;
GdkContentProvider *content;
date = g_date_new_dmy (priv->selected_day, priv->month + 1, priv->year);
g_date_strftime (str, 127, "%x", date);
g_free (date);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, str);
content = gdk_content_provider_new_for_value (&value);
g_value_unset (&value);
return content;
}
static void
gtk_calendar_drag_update (GtkGestureDrag *gesture,
double x,
@@ -2680,8 +2691,12 @@ gtk_calendar_drag_update (GtkGestureDrag *gesture,
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
gdouble start_x, start_y;
GdkContentProvider *content;
GdkDevice *device;
GdkDrag *drag;
GdkContentFormats *targets;
GtkIconTheme *theme;
GdkPaintable *paintable;
GdkSurface *surface;
if (!priv->in_drag)
return;
@@ -2691,19 +2706,22 @@ gtk_calendar_drag_update (GtkGestureDrag *gesture,
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
surface = gtk_native_get_surface (gtk_widget_get_native (widget));
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
targets = gdk_content_formats_new (NULL, 0);
targets = gtk_content_formats_add_text_targets (targets);
drag = gtk_drag_begin (widget,
gtk_gesture_get_device (GTK_GESTURE (gesture)),
targets, GDK_ACTION_COPY,
start_x, start_y);
content = get_calendar_content (calendar);
drag = gdk_drag_begin (surface, device, content, GDK_ACTION_COPY, start_x, start_y);
theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
paintable = gtk_icon_theme_load_icon (theme, "text-x-generic", 32, 0, NULL);
gtk_drag_icon_set_from_paintable (drag, paintable, 0, 0);
g_clear_object (&paintable);
g_object_unref (content);
g_object_unref (drag);
priv->in_drag = 0;
gdk_content_formats_unref (targets);
gtk_drag_set_icon_default (drag);
}
static gboolean
@@ -2923,24 +2941,6 @@ gtk_calendar_grab_notify (GtkWidget *widget,
* Drag and Drop *
****************************************/
static void
gtk_calendar_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GDate *date;
gchar str[128];
gsize len;
date = g_date_new_dmy (priv->selected_day, priv->month + 1, priv->year);
len = g_date_strftime (str, 127, "%x", date);
gtk_selection_data_set_text (selection_data, str, len);
g_free (date);
}
/* Get/set whether drag_motion requested the drag data and
* drag_data_received should thus not actually insert the data,
* since the data doesnt result from a drop.
@@ -2962,87 +2962,33 @@ get_status_pending (GdkDrop *drop)
}
static void
gtk_calendar_drag_leave (GtkWidget *widget,
GdkDrop *drop)
gtk_calendar_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkCalendar *calendar)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
priv->drag_highlight = 0;
gtk_drag_unhighlight (widget);
}
static gboolean
gtk_calendar_drag_motion (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GdkAtom target;
if (!priv->drag_highlight)
{
priv->drag_highlight = 1;
gtk_drag_highlight (widget);
}
target = gtk_drag_dest_find_target (widget, drop, NULL);
if (target == NULL || gdk_drop_get_actions (drop) == 0)
gdk_drop_status (drop, 0);
else if (get_status_pending (drop) == 0)
{
set_status_pending (drop, gdk_drop_get_actions (drop));
gtk_drag_get_data (widget, drop, target);
}
return TRUE;
}
static gboolean
gtk_calendar_drag_drop (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
{
GdkAtom target;
target = gtk_drag_dest_find_target (widget, drop, NULL);
if (target != NULL)
{
gtk_drag_get_data (widget, drop, target);
return TRUE;
}
return FALSE;
}
static void
gtk_calendar_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data)
got_text (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkCalendar *calendar = GTK_CALENDAR (widget);
GtkDropTarget *dest = GTK_DROP_TARGET (data);
GtkCalendar *calendar = GTK_CALENDAR (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest)));
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GdkDrop *drop = GDK_DROP (source);
guint day, month, year;
gchar *str;
GDate *date;
GdkDragAction suggested_action;
suggested_action = get_status_pending (drop);
set_status_pending (drop, 0);
str = gdk_drop_read_text_finish (drop, result, NULL);
if (suggested_action)
{
set_status_pending (drop, 0);
/* We are getting this data due to a request in drag_motion,
* rather than due to a request in drag_drop, so we are just
* supposed to call drag_status, not actually paste in the
* data.
*/
str = (gchar*) gtk_selection_data_get_text (selection_data);
if (str)
{
date = g_date_new ();
@@ -3054,14 +3000,13 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
}
else
suggested_action = 0;
gdk_drop_status (drop, suggested_action);
if (suggested_action == 0)
gtk_drop_target_deny_drop (dest, drop);
return;
}
date = g_date_new ();
str = (gchar*) gtk_selection_data_get_text (selection_data);
if (str)
{
g_date_set_parse (date, str);
@@ -3073,6 +3018,7 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
g_warning ("Received invalid date data");
g_date_free (date);
gdk_drop_finish (drop, 0);
gtk_drop_target_deny_drop (dest, drop);
return;
}
@@ -3083,7 +3029,6 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
gdk_drop_finish (drop, suggested_action);
g_object_freeze_notify (G_OBJECT (calendar));
if (!(priv->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
&& (priv->display_flags & GTK_CALENDAR_SHOW_HEADING))
@@ -3092,6 +3037,47 @@ gtk_calendar_drag_data_received (GtkWidget *widget,
g_object_thaw_notify (G_OBJECT (calendar));
}
static gboolean
gtk_calendar_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
GtkCalendar *calendar)
{
GdkAtom target;
target = gtk_drop_target_find_mimetype (dest);
if (!target || gdk_drop_get_actions (drop) == 0)
{
gdk_drop_status (drop, 0);
return FALSE;
}
else if (get_status_pending (drop) == 0)
{
set_status_pending (drop, gdk_drop_get_actions (drop));
gdk_drop_read_text_async (drop, NULL, got_text, dest);
}
return TRUE;
}
static gboolean
gtk_calendar_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkCalendar *calendar)
{
GdkAtom target;
target = gtk_drop_target_find_mimetype (dest);
if (target != NULL)
{
set_status_pending (drop, 0);
gdk_drop_read_text_async (drop, NULL, got_text, dest);
return TRUE;
}
return FALSE;
}
/****************************************
* Public API *
+1 -22
View File
@@ -406,7 +406,6 @@ gtk_cell_renderer_toggle_snapshot (GtkCellRenderer *cell,
gint xpad, ypad;
GtkStateFlags state;
GtkBorder padding, border;
GtkCssImageBuiltinType image_type;
gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
&x_offset, &y_offset,
@@ -452,32 +451,12 @@ gtk_cell_renderer_toggle_snapshot (GtkCellRenderer *cell,
gtk_style_context_get_padding (context, &padding);
gtk_style_context_get_border (context, &border);
if (priv->radio)
{
if (state & GTK_STATE_FLAG_INCONSISTENT)
image_type = GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT;
else if (state & GTK_STATE_FLAG_CHECKED)
image_type = GTK_CSS_IMAGE_BUILTIN_OPTION;
else
image_type = GTK_CSS_IMAGE_BUILTIN_NONE;
}
else
{
if (state & GTK_STATE_FLAG_INCONSISTENT)
image_type = GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT;
else if (state & GTK_STATE_FLAG_CHECKED)
image_type = GTK_CSS_IMAGE_BUILTIN_CHECK;
else
image_type = GTK_CSS_IMAGE_BUILTIN_NONE;
}
gtk_snapshot_translate (snapshot,
&GRAPHENE_POINT_INIT (cell_area->x + x_offset + xpad + padding.left + border.left,
cell_area->y + y_offset + ypad + padding.top + border.top));
gtk_css_style_snapshot_icon (gtk_style_context_lookup_style (context), snapshot,
width - padding.left - padding.right - border.left - border.right,
height - padding.top - padding.bottom - border.top - border.bottom,
image_type);
height - padding.top - padding.bottom - border.top - border.bottom);
gtk_style_context_restore (context);
gtk_snapshot_pop (snapshot);
-12
View File
@@ -98,7 +98,6 @@ static void
gtk_check_button_update_node_state (GtkWidget *widget)
{
GtkCheckButtonPrivate *priv = gtk_check_button_get_instance_private (GTK_CHECK_BUTTON (widget));
GtkCssImageBuiltinType image_type;
GtkStateFlags state;
if (!priv->indicator_widget)
@@ -106,17 +105,6 @@ gtk_check_button_update_node_state (GtkWidget *widget)
state = gtk_widget_get_state_flags (widget);
/* XXX: This is somewhat awkward here, but there's no better
* way to update the icon
*/
if (state & GTK_STATE_FLAG_CHECKED)
image_type = GTK_IS_RADIO_BUTTON (widget) ? GTK_CSS_IMAGE_BUILTIN_OPTION : GTK_CSS_IMAGE_BUILTIN_CHECK;
else if (state & GTK_STATE_FLAG_INCONSISTENT)
image_type = GTK_IS_RADIO_BUTTON (widget) ? GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT : GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT;
else
image_type = GTK_CSS_IMAGE_BUILTIN_NONE;
gtk_icon_set_image (GTK_ICON (priv->indicator_widget), image_type);
gtk_widget_set_state_flags (priv->indicator_widget, state, TRUE);
}
+54 -97
View File
@@ -36,7 +36,6 @@
#include "gtkcolorchooserprivate.h"
#include "gtkcolorchooserdialog.h"
#include "gtkcolorswatchprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkdragsource.h"
#include "gtkintl.h"
@@ -45,6 +44,9 @@
#include "gtkprivate.h"
#include "gtksnapshot.h"
#include "gtkstylecontext.h"
#include "gtkdragsource.h"
#include "gtkdragdest.h"
#include "gtkeventcontroller.h"
/**
@@ -121,21 +123,6 @@ static void gtk_color_button_get_property (GObject *object,
static void gtk_color_button_clicked (GtkButton *button,
gpointer user_data);
/* source side drag signals */
static void gtk_color_button_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data);
static void gtk_color_button_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
GtkColorButton *button);
/* target side drag signals */
static void gtk_color_button_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data,
GtkColorButton *button);
static guint color_button_signals[LAST_SIGNAL] = { 0 };
@@ -245,91 +232,64 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
}
static void
gtk_color_button_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data,
GtkColorButton *button)
got_color (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
gint length;
guint16 *dropped;
GdkDrop *drop = GDK_DROP (source);
const GValue *value;
length = gtk_selection_data_get_length (selection_data);
if (length < 0)
return;
/* We accept drops with the wrong format, since the KDE color
* chooser incorrectly drops application/x-color with format 8.
*/
if (length != 8)
value = gdk_drop_read_value_finish (drop, result, NULL);
if (value)
{
g_warning ("%s: Received invalid color data", G_STRFUNC);
return;
GdkRGBA *color = g_value_get_boxed (value);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (data), color);
gdk_drop_finish (drop, GDK_ACTION_COPY);
}
else
gdk_drop_finish (drop, 0);
}
static gboolean
gtk_color_button_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkColorButton *button)
{
if (gdk_drop_has_value (drop, GDK_TYPE_RGBA))
{
gdk_drop_read_value_async (drop, GDK_TYPE_RGBA, G_PRIORITY_DEFAULT, NULL, got_color, button);
return TRUE;
}
dropped = (guint16 *) gtk_selection_data_get_data (selection_data);
priv->rgba.red = dropped[0] / 65535.;
priv->rgba.green = dropped[1] / 65535.;
priv->rgba.blue = dropped[2] / 65535.;
priv->rgba.alpha = dropped[3] / 65535.;
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (priv->swatch), &priv->rgba);
g_signal_emit (button, color_button_signals[COLOR_SET], 0);
g_object_freeze_notify (G_OBJECT (button));
g_object_notify (G_OBJECT (button), "rgba");
g_object_thaw_notify (G_OBJECT (button));
return FALSE;
}
static void
set_color_icon (GdkDrag *drag,
const GdkRGBA *rgba)
gtk_color_button_drag_begin (GtkDragSource *source,
GdkDrag *drag,
GtkColorButton *button)
{
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
GtkSnapshot *snapshot;
GdkPaintable *paintable;
snapshot = gtk_snapshot_new ();
gtk_snapshot_append_color (snapshot,
rgba,
&GRAPHENE_RECT_INIT(0, 0, 48, 32));
gtk_snapshot_append_color (snapshot, &priv->rgba, &GRAPHENE_RECT_INIT(0, 0, 48, 32));
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_drag_set_icon_paintable (drag, paintable, 0, 0);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
}
static void
gtk_color_button_drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
get_rgba_value (GValue *value,
gpointer data)
{
GtkColorButton *button = data;
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
set_color_icon (drag, &priv->rgba);
}
static void
gtk_color_button_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
GtkColorButton *button)
{
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button);
guint16 dropped[4];
dropped[0] = (guint16) (priv->rgba.red * 65535);
dropped[1] = (guint16) (priv->rgba.green * 65535);
dropped[2] = (guint16) (priv->rgba.blue * 65535);
dropped[3] = (guint16) (priv->rgba.alpha * 65535);
gtk_selection_data_set (selection_data,
gtk_selection_data_get_target (selection_data),
16, (guchar *)dropped, 8);
GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (GTK_COLOR_BUTTON (data));
g_value_set_boxed (value, &priv->rgba);
}
static void
@@ -340,6 +300,9 @@ gtk_color_button_init (GtkColorButton *button)
PangoRectangle rect;
GtkStyleContext *context;
GdkContentFormats *targets;
GdkContentProvider *content;
GtkDragSource *source;
GtkDropTarget *dest;
priv->button = gtk_button_new ();
g_signal_connect (priv->button, "clicked", G_CALLBACK (gtk_color_button_clicked), button);
@@ -364,23 +327,17 @@ gtk_color_button_init (GtkColorButton *button)
priv->use_alpha = FALSE;
targets = gdk_content_formats_new (drop_types, G_N_ELEMENTS (drop_types));
gtk_drag_dest_set (priv->button,
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_DROP,
targets,
GDK_ACTION_COPY);
gtk_drag_source_set (priv->button,
GDK_BUTTON1_MASK|GDK_BUTTON3_MASK,
targets,
GDK_ACTION_COPY);
dest = gtk_drop_target_new (targets, GDK_ACTION_COPY);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_color_button_drag_drop), button);
gtk_widget_add_controller (GTK_WIDGET (button), GTK_EVENT_CONTROLLER (dest));
gdk_content_formats_unref (targets);
g_signal_connect (priv->button, "drag-begin",
G_CALLBACK (gtk_color_button_drag_begin), button);
g_signal_connect (priv->button, "drag-data-received",
G_CALLBACK (gtk_color_button_drag_data_received), button);
g_signal_connect (priv->button, "drag-data-get",
G_CALLBACK (gtk_color_button_drag_data_get), button);
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, button);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_button_drag_begin), button);
gtk_widget_add_controller (priv->button, GTK_EVENT_CONTROLLER (source));
context = gtk_widget_get_style_context (GTK_WIDGET (priv->button));
gtk_style_context_add_class (context, "color");
+83 -86
View File
@@ -22,7 +22,6 @@
#include "gtkbox.h"
#include "gtkcolorchooserprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkdragsource.h"
#include "gtkgesturelongpress.h"
@@ -40,6 +39,7 @@
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerkey.h"
#include "gtknative.h"
#include "gtkdragsource.h"
#include "a11y/gtkcolorswatchaccessibleprivate.h"
@@ -66,6 +66,7 @@ typedef struct
GtkWidget *overlay_widget;
GtkWidget *popover;
GtkDropTarget *dest;
} GtkColorSwatchPrivate;
enum
@@ -73,7 +74,8 @@ enum
PROP_ZERO,
PROP_RGBA,
PROP_SELECTABLE,
PROP_HAS_MENU
PROP_HAS_MENU,
PROP_CAN_DROP
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_WIDGET)
@@ -113,87 +115,57 @@ swatch_snapshot (GtkWidget *widget,
gtk_widget_snapshot_child (widget, priv->overlay_widget, snapshot);
}
static void
drag_set_color_icon (GdkDrag *drag,
const GdkRGBA *color)
gtk_color_swatch_drag_begin (GtkDragSource *source,
GdkDrag *drag,
GtkColorSwatch *swatch)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
GtkSnapshot *snapshot;
GdkPaintable *paintable;
snapshot = gtk_snapshot_new ();
gtk_snapshot_append_color (snapshot,
color,
&GRAPHENE_RECT_INIT(0, 0, 48, 32));
gtk_snapshot_append_color (snapshot, &priv->color, &GRAPHENE_RECT_INIT(0, 0, 48, 32));
paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
gtk_drag_set_icon_paintable (drag, paintable, 4, 4);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
}
static void
swatch_drag_begin (GtkWidget *widget,
GdkDrag *drag)
got_color (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
GdkRGBA color;
GdkDrop *drop = GDK_DROP (source);
const GValue *value;
gtk_color_swatch_get_rgba (swatch, &color);
drag_set_color_icon (drag, &color);
}
static void
swatch_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
guint16 vals[4];
GdkRGBA color;
gtk_color_swatch_get_rgba (swatch, &color);
vals[0] = color.red * 0xffff;
vals[1] = color.green * 0xffff;
vals[2] = color.blue * 0xffff;
vals[3] = color.alpha * 0xffff;
gtk_selection_data_set (selection_data,
g_intern_static_string ("application/x-color"),
16, (guchar *)vals, 8);
}
static void
swatch_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data)
{
gint length;
guint16 *vals;
GdkRGBA color;
length = gtk_selection_data_get_length (selection_data);
if (length < 0)
return;
/* We accept drops with the wrong format, since the KDE color
* chooser incorrectly drops application/x-color with format 8.
*/
if (length != 8)
value = gdk_drop_read_value_finish (drop, result, NULL);
if (value)
{
g_warning ("Received invalid color data");
return;
GdkRGBA *color = g_value_get_boxed (value);
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (data), color);
gdk_drop_finish (drop, GDK_ACTION_COPY);
}
else
gdk_drop_finish (drop, 0);
}
static gboolean
swatch_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkColorSwatch *swatch)
{
if (gdk_drop_has_value (drop, GDK_TYPE_RGBA))
{
gdk_drop_read_value_async (drop, GDK_TYPE_RGBA, G_PRIORITY_DEFAULT, NULL, got_color, swatch);
return TRUE;
}
vals = (guint16 *) gtk_selection_data_get_data (selection_data);
color.red = (gdouble)vals[0] / 0xffff;
color.green = (gdouble)vals[1] / 0xffff;
color.blue = (gdouble)vals[2] / 0xffff;
color.alpha = (gdouble)vals[3] / 0xffff;
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (widget), &color);
return FALSE;
}
static void
@@ -455,6 +427,9 @@ swatch_get_property (GObject *object,
case PROP_HAS_MENU:
g_value_set_boolean (value, priv->has_menu);
break;
case PROP_CAN_DROP:
g_value_set_boolean (value, priv->dest != NULL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -481,6 +456,9 @@ swatch_set_property (GObject *object,
case PROP_HAS_MENU:
priv->has_menu = g_value_get_boolean (value);
break;
case PROP_CAN_DROP:
gtk_color_swatch_set_can_drop (swatch, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -495,7 +473,7 @@ swatch_finalize (GObject *object)
g_free (priv->icon);
gtk_widget_unparent (priv->overlay_widget);
G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object);
}
@@ -523,9 +501,6 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
widget_class->measure = gtk_color_swatch_measure;
widget_class->snapshot = swatch_snapshot;
widget_class->drag_begin = swatch_drag_begin;
widget_class->drag_data_get = swatch_drag_data_get;
widget_class->drag_data_received = swatch_drag_data_received;
widget_class->popup_menu = swatch_popup_menu;
widget_class->size_allocate = swatch_size_allocate;
widget_class->state_flags_changed = swatch_state_flags_changed;
@@ -539,6 +514,9 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
g_object_class_install_property (object_class, PROP_HAS_MENU,
g_param_spec_boolean ("has-menu", P_("Has Menu"), P_("Whether the swatch should offer customization"),
TRUE, GTK_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_CAN_DROP,
g_param_spec_boolean ("can-drop", P_("Can Drop"), P_("Whether the swatch should accept drops"),
FALSE, GTK_PARAM_READWRITE));
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_COLOR_SWATCH_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("colorswatch"));
@@ -600,6 +578,14 @@ static const char *dnd_targets[] = {
"application/x-color"
};
static void
get_rgba_value (GValue *value,
gpointer data)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (GTK_COLOR_SWATCH (data));
g_value_set_boxed (value, &priv->color);
}
void
gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
const GdkRGBA *color)
@@ -611,12 +597,16 @@ gtk_color_swatch_set_rgba (GtkColorSwatch *swatch,
if (!priv->has_color)
{
GdkContentFormats *targets = gdk_content_formats_new (dnd_targets, G_N_ELEMENTS (dnd_targets));
gtk_drag_source_set (GTK_WIDGET (swatch),
GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
targets,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gdk_content_formats_unref (targets);
GdkContentProvider *content;
GtkDragSource *source;
source = gtk_drag_source_new ();
content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, swatch);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_swatch_drag_begin), swatch);
gtk_widget_add_controller (GTK_WIDGET (swatch), GTK_EVENT_CONTROLLER (source));
}
priv->has_color = TRUE;
@@ -676,21 +666,28 @@ void
gtk_color_swatch_set_can_drop (GtkColorSwatch *swatch,
gboolean can_drop)
{
if (can_drop)
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
if (can_drop == (priv->dest != NULL))
return;
if (can_drop && !priv->dest)
{
GdkContentFormats *targets = gdk_content_formats_new (dnd_targets, G_N_ELEMENTS (dnd_targets));
gtk_drag_dest_set (GTK_WIDGET (swatch),
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_DROP,
targets,
GDK_ACTION_COPY);
GdkContentFormats *targets;
targets = gdk_content_formats_new (dnd_targets, G_N_ELEMENTS (dnd_targets));
priv->dest = gtk_drop_target_new (targets, GDK_ACTION_COPY);
g_signal_connect (priv->dest, "drag-drop", G_CALLBACK (swatch_drag_drop), swatch);
gtk_widget_add_controller (GTK_WIDGET (swatch), GTK_EVENT_CONTROLLER (priv->dest));
gdk_content_formats_unref (targets);
}
else
if (!can_drop && priv->dest)
{
gtk_drag_dest_unset (GTK_WIDGET (swatch));
gtk_widget_remove_controller (GTK_WIDGET (swatch), GTK_EVENT_CONTROLLER (priv->dest));
priv->dest = NULL;
}
g_object_notify (G_OBJECT (swatch), "can-drop");
}
void
+2 -2
View File
@@ -480,8 +480,8 @@ gtk_container_get_request_mode (GtkWidget *widget)
/**
* gtk_container_forall: (virtual forall)
* @container: a #GtkContainer
* @callback: (scope call) (closure callback_data): a callback
* @callback_data: callback user data
* @callback: (scope call): a callback
* @callback_data: (closure): callback user data
*
* Invokes @callback on each direct child of @container, including
* children that are considered internal (implementation details
+10
View File
@@ -79,6 +79,15 @@ gtk_css_animated_style_is_static (GtkCssStyle *style)
return TRUE;
}
static GtkCssStaticStyle *
gtk_css_animated_style_get_static_style (GtkCssStyle *style)
{
/* This is called a lot, so we avoid a dynamic type check here */
GtkCssAnimatedStyle *animated = (GtkCssAnimatedStyle *) style;
return (GtkCssStaticStyle *)animated->style;
}
static void
gtk_css_animated_style_dispose (GObject *object)
{
@@ -123,6 +132,7 @@ gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass)
style_class->get_value = gtk_css_animated_style_get_value;
style_class->get_section = gtk_css_animated_style_get_section;
style_class->is_static = gtk_css_animated_style_is_static;
style_class->get_static_style = gtk_css_animated_style_get_static_style;
}
static void
+21 -48
View File
@@ -35,10 +35,10 @@ static GtkCssValue *gtk_css_font_features_value_new_empty (void);
static void
gtk_css_font_features_value_add_feature (GtkCssValue *value,
const char *name,
GtkCssValue *val)
const char *name,
int num)
{
g_hash_table_insert (value->features, g_strdup (name), val);
g_hash_table_insert (value->features, g_strdup (name), GINT_TO_POINTER (num));
}
@@ -57,29 +57,7 @@ gtk_css_value_font_features_compute (GtkCssValue *specified,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GHashTableIter iter;
gpointer name, val;
GtkCssValue *computed_val;
GtkCssValue *result;
gboolean changes = FALSE;
result = gtk_css_font_features_value_new_empty ();
g_hash_table_iter_init (&iter, specified->features);
while (g_hash_table_iter_next (&iter, &name, &val))
{
computed_val = _gtk_css_value_compute (val, property_id, provider, style, parent_style);
changes |= computed_val != val;
gtk_css_font_features_value_add_feature (result, name, computed_val);
}
if (!changes)
{
_gtk_css_value_unref (result);
result = _gtk_css_value_ref (specified);
}
return result;
return _gtk_css_value_ref (specified);
}
static gboolean
@@ -96,10 +74,8 @@ gtk_css_value_font_features_equal (const GtkCssValue *value1,
while (g_hash_table_iter_next (&iter, &name, &val1))
{
val2 = g_hash_table_lookup (value2->features, name);
if (val2 == NULL)
return FALSE;
if (!_gtk_css_value_equal (val1, val2))
if (val1 != val2)
return FALSE;
}
@@ -113,9 +89,10 @@ gtk_css_value_font_features_transition (GtkCssValue *start,
double progress)
{
const char *name;
GtkCssValue *start_val, *end_val;
gpointer start_val, end_val;
GHashTableIter iter;
GtkCssValue *result, *transition;
gpointer transition;
GtkCssValue *result;
/* XXX: For value that are only in start or end but not both,
* we don't transition but just keep the value.
@@ -129,11 +106,11 @@ gtk_css_value_font_features_transition (GtkCssValue *start,
{
end_val = g_hash_table_lookup (end->features, name);
if (end_val == NULL)
transition = _gtk_css_value_ref (start_val);
transition = start_val;
else
transition = _gtk_css_value_transition (start_val, end_val, property_id, progress);
transition = progress > 0.5 ? start_val : end_val;
gtk_css_font_features_value_add_feature (result, name, transition);
gtk_css_font_features_value_add_feature (result, name, GPOINTER_TO_INT (transition));
}
g_hash_table_iter_init (&iter, end->features);
@@ -143,7 +120,7 @@ gtk_css_value_font_features_transition (GtkCssValue *start,
if (start_val != NULL)
continue;
gtk_css_font_features_value_add_feature (result, name, _gtk_css_value_ref (end_val));
gtk_css_font_features_value_add_feature (result, name, GPOINTER_TO_INT (end_val));
}
return result;
@@ -155,7 +132,7 @@ gtk_css_value_font_features_print (const GtkCssValue *value,
{
GHashTableIter iter;
const char *name;
GtkCssValue *val;
gpointer val;
gboolean first = TRUE;
if (value == default_font_features)
@@ -172,7 +149,7 @@ gtk_css_value_font_features_print (const GtkCssValue *value,
else
g_string_append (string, ", ");
g_string_append_printf (string, "\"%s\" ", name);
_gtk_css_value_print (val, string);
g_string_append_printf (string, "%d", GPOINTER_TO_INT (val));
}
}
@@ -226,7 +203,7 @@ is_valid_opentype_tag (const char *s)
GtkCssValue *
gtk_css_font_features_value_parse (GtkCssParser *parser)
{
GtkCssValue *result, *val;
GtkCssValue *result;
char *name;
int num;
@@ -252,16 +229,12 @@ gtk_css_font_features_value_parse (GtkCssParser *parser)
}
if (gtk_css_parser_try_ident (parser, "on"))
val = _gtk_css_number_value_new (1.0, GTK_CSS_NUMBER);
num = 1;
else if (gtk_css_parser_try_ident (parser, "off"))
val = _gtk_css_number_value_new (0.0, GTK_CSS_NUMBER);
num = 0;
else if (gtk_css_parser_has_integer (parser))
{
if (gtk_css_parser_consume_integer (parser, &num))
{
val = _gtk_css_number_value_new ((double)num, GTK_CSS_NUMBER);
}
else
if (!gtk_css_parser_consume_integer (parser, &num))
{
g_free (name);
_gtk_css_value_unref (result);
@@ -269,9 +242,9 @@ gtk_css_font_features_value_parse (GtkCssParser *parser)
}
}
else
val = _gtk_css_number_value_new (1.0, GTK_CSS_NUMBER);
num = 1;
gtk_css_font_features_value_add_feature (result, name, val);
gtk_css_font_features_value_add_feature (result, name, num);
g_free (name);
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
@@ -301,7 +274,7 @@ gtk_css_font_features_value_get_features (GtkCssValue *value)
first = FALSE;
else
g_string_append (string, ", ");
g_string_append_printf (string, "%s %d", name, (int)_gtk_css_number_value_get (val, 100));
g_string_append_printf (string, "%s %d", name, GPOINTER_TO_INT (val));
}
return g_string_free (string, FALSE);
+1 -23
View File
@@ -56,29 +56,7 @@ gtk_css_value_font_variations_compute (GtkCssValue *specified,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GHashTableIter iter;
gpointer name, coord;
GtkCssValue *computed_coord;
GtkCssValue *result;
gboolean changes = FALSE;
result = gtk_css_font_variations_value_new_empty ();
g_hash_table_iter_init (&iter, specified->axes);
while (g_hash_table_iter_next (&iter, &name, &coord))
{
computed_coord = _gtk_css_value_compute (coord, property_id, provider, style, parent_style);
changes |= computed_coord != coord;
gtk_css_font_variations_value_add_axis (result, name, computed_coord);
}
if (!changes)
{
_gtk_css_value_unref (result);
result = _gtk_css_value_ref (specified);
}
return result;
return _gtk_css_value_ref (specified);
}
static gboolean
-670
View File
@@ -1,670 +0,0 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssimagebuiltinprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcssstyleprivate.h"
#include "gtkhslaprivate.h"
#include <math.h>
#include "fallback-c89.c"
G_DEFINE_TYPE (GtkCssImageBuiltin, gtk_css_image_builtin, GTK_TYPE_CSS_IMAGE)
static GtkCssImage *the_one_true_image;
static void
gtk_css_image_builtin_draw_check (GtkCssImage *image,
cairo_t *cr,
double width,
double height,
gboolean checked,
gboolean inconsistent)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
gint x, y, exterior_size, interior_size, pad;
exterior_size = MIN (width, height);
if (exterior_size % 2 == 0) /* Ensure odd */
exterior_size -= 1;
pad = 1 + MAX (1, (exterior_size - 2) / 9);
interior_size = MAX (1, exterior_size - 2 * pad);
if (interior_size < 7)
pad = MAX (0, (exterior_size - interior_size) / 2);
x = - (1 + exterior_size - (gint) width) / 2;
y = - (1 + exterior_size - (gint) height) / 2;
gdk_cairo_set_source_rgba (cr, &builtin->fg_color);
if (inconsistent)
{
int line_thickness = MAX (1, (3 + interior_size * 2) / 7);
cairo_rectangle (cr,
x + pad,
y + pad + (1 + interior_size - line_thickness) / 2,
interior_size,
line_thickness);
cairo_fill (cr);
}
else
{
if (checked)
{
cairo_save (cr);
cairo_translate (cr,
x + pad, y + pad);
cairo_scale (cr, interior_size / 7., interior_size / 7.);
cairo_rectangle (cr, 0, 0, 7, 7);
cairo_clip (cr);
cairo_move_to (cr, 7.0, 0.0);
cairo_line_to (cr, 7.5, 1.0);
cairo_curve_to (cr, 5.3, 2.0,
4.3, 4.0,
3.5, 7.0);
cairo_curve_to (cr, 3.0, 5.7,
1.3, 4.7,
0.0, 4.7);
cairo_line_to (cr, 0.2, 3.5);
cairo_curve_to (cr, 1.1, 3.5,
2.3, 4.3,
3.0, 5.0);
cairo_curve_to (cr, 1.0, 3.9,
2.4, 4.1,
3.2, 4.9);
cairo_curve_to (cr, 3.5, 3.1,
5.2, 2.0,
7.0, 0.0);
cairo_fill (cr);
cairo_restore (cr);
}
}
}
static void
gtk_css_image_builtin_draw_option (GtkCssImage *image,
cairo_t *cr,
double width,
double height,
gboolean checked,
gboolean inconsistent)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
gint x, y, exterior_size, interior_size, pad;
exterior_size = MIN (width, height);
if (exterior_size % 2 == 0) /* Ensure odd */
exterior_size -= 1;
x = - (1 + exterior_size - width) / 2;
y = - (1 + exterior_size - height) / 2;
gdk_cairo_set_source_rgba (cr, &builtin->fg_color);
pad = 1 + MAX (1, 2 * (exterior_size - 2) / 9);
interior_size = MAX (1, exterior_size - 2 * pad);
if (interior_size < 7)
pad = MAX (0, (exterior_size - interior_size) / 2);
if (inconsistent)
{
gint line_thickness;
line_thickness = MAX (1, (3 + interior_size * 2) / 7);
cairo_rectangle (cr,
x + pad,
y + pad + (interior_size - line_thickness) / 2.,
interior_size,
line_thickness);
cairo_fill (cr);
}
else if (checked)
{
cairo_new_sub_path (cr);
cairo_arc (cr,
x + pad + interior_size / 2.,
y + pad + interior_size / 2.,
interior_size / 2.,
0, 2 * G_PI);
cairo_fill (cr);
}
}
static void
gtk_css_image_builtin_draw_arrow (GtkCssImage *image,
cairo_t *cr,
double width,
double height,
GtkCssImageBuiltinType image_type)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
double line_width;
double size;
size = MIN (width, height);
cairo_translate (cr, width / 2.0, height / 2.0);
switch ((guint) image_type)
{
case GTK_CSS_IMAGE_BUILTIN_ARROW_UP:
break;
case GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN:
cairo_rotate (cr, G_PI);
break;
case GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT:
cairo_rotate (cr, 3 * G_PI / 2);
break;
case GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT:
cairo_rotate (cr, G_PI / 2);
break;
default:
g_assert_not_reached ();
break;
}
line_width = size / 3.0 / sqrt (2);
cairo_set_line_width (cr, line_width);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_scale (cr,
(size / (size + line_width)),
(size / (size + line_width)));
cairo_move_to (cr, -size / 2.0, size / 4.0);
cairo_rel_line_to (cr, size / 2.0, -size / 2.0);
cairo_rel_line_to (cr, size / 2.0, size / 2.0);
gdk_cairo_set_source_rgba (cr, &builtin->fg_color);
cairo_stroke (cr);
}
static void
gtk_css_image_builtin_draw_expander (GtkCssImage *image,
cairo_t *cr,
double width,
double height,
gboolean horizontal,
gboolean is_rtl,
gboolean expanded)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
double vertical_overshoot;
int diameter;
double radius;
double interp; /* interpolation factor for center position */
double x_double_horz, y_double_horz;
double x_double_vert, y_double_vert;
double x_double, y_double;
gdouble angle;
gint line_width;
gdouble progress;
line_width = 1;
progress = expanded ? 1 : 0;
if (!horizontal)
{
if (is_rtl)
angle = (G_PI) - ((G_PI / 2) * progress);
else
angle = (G_PI / 2) * progress;
}
else
{
if (is_rtl)
angle = (G_PI / 2) + ((G_PI / 2) * progress);
else
angle = (G_PI / 2) - ((G_PI / 2) * progress);
}
interp = progress;
/* Compute distance that the stroke extends beyonds the end
* of the triangle we draw.
*/
vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
/* For odd line widths, we end the vertical line of the triangle
* at a half pixel, so we round differently.
*/
if (line_width % 2 == 1)
vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
else
vertical_overshoot = ceil (vertical_overshoot);
/* Adjust the size of the triangle we draw so that the entire stroke fits
*/
diameter = (gint) MAX (3, width - 2 * vertical_overshoot);
/* If the line width is odd, we want the diameter to be even,
* and vice versa, so force the sum to be odd. This relationship
* makes the point of the triangle look right.
*/
diameter -= (1 - (diameter + line_width) % 2);
radius = diameter / 2.;
/* Adjust the center so that the stroke is properly aligned with
* the pixel grid. The center adjustment is different for the
* horizontal and vertical orientations. For intermediate positions
* we interpolate between the two.
*/
x_double_vert = floor ((width / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.;
y_double_vert = (height / 2) - 0.5;
x_double_horz = (width / 2) - 0.5;
y_double_horz = floor ((height / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.;
x_double = x_double_vert * (1 - interp) + x_double_horz * interp;
y_double = y_double_vert * (1 - interp) + y_double_horz * interp;
cairo_translate (cr, x_double, y_double);
cairo_rotate (cr, angle);
cairo_move_to (cr, - radius / 2., - radius);
cairo_line_to (cr, radius / 2., 0);
cairo_line_to (cr, - radius / 2., radius);
cairo_close_path (cr);
cairo_set_line_width (cr, line_width);
gdk_cairo_set_source_rgba (cr, &builtin->fg_color);
cairo_fill (cr);
}
static void
color_shade (const GdkRGBA *color,
gdouble factor,
GdkRGBA *color_return)
{
GtkHSLA hsla;
_gtk_hsla_init_from_rgba (&hsla, color);
_gtk_hsla_shade (&hsla, &hsla, factor);
_gdk_rgba_init_from_hsla (color_return, &hsla);
}
static void
render_dot (cairo_t *cr,
const GdkRGBA *lighter,
const GdkRGBA *darker,
gdouble x,
gdouble y,
gdouble size)
{
size = CLAMP ((gint) size, 2, 3);
if (size == 2)
{
gdk_cairo_set_source_rgba (cr, lighter);
cairo_rectangle (cr, x, y, 1, 1);
cairo_rectangle (cr, x + 1, y + 1, 1, 1);
cairo_fill (cr);
}
else if (size == 3)
{
gdk_cairo_set_source_rgba (cr, lighter);
cairo_rectangle (cr, x, y, 2, 1);
cairo_rectangle (cr, x, y, 1, 2);
cairo_fill (cr);
gdk_cairo_set_source_rgba (cr, darker);
cairo_rectangle (cr, x + 1, y + 1, 2, 1);
cairo_rectangle (cr, x + 2, y, 1, 2);
cairo_fill (cr);
}
}
static void
gtk_css_image_builtin_draw_pane_separator (GtkCssImage *image,
cairo_t *cr,
double width,
double height)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
GdkRGBA lighter, darker;
gint xx, yy;
cairo_set_line_width (cr, 1.0);
color_shade (&builtin->bg_color, 0.7, &darker);
color_shade (&builtin->bg_color, 1.3, &lighter);
if (width > height)
for (xx = width / 2 - 15; xx <= width / 2 + 15; xx += 5)
render_dot (cr, &lighter, &darker, xx, height / 2 - 1, 3);
else
for (yy = height / 2 - 15; yy <= height / 2 + 15; yy += 5)
render_dot (cr, &lighter, &darker, width / 2 - 1, yy, 3);
}
static void
gtk_css_image_builtin_draw_handle (GtkCssImage *image,
cairo_t *cr,
double width,
double height)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
GdkRGBA lighter, darker;
gint xx, yy;
cairo_set_line_width (cr, 1.0);
color_shade (&builtin->bg_color, 0.7, &darker);
color_shade (&builtin->bg_color, 1.3, &lighter);
for (yy = 0; yy < height; yy += 3)
for (xx = 0; xx < width; xx += 6)
{
render_dot (cr, &lighter, &darker, xx, yy, 2);
render_dot (cr, &lighter, &darker, xx + 3, yy + 1, 2);
}
}
static void
gtk_css_image_builtin_draw_spinner (GtkCssImage *image,
cairo_t *cr,
double width,
double height)
{
GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image);
guint num_steps;
gdouble radius;
gdouble half;
gint i;
radius = MIN (width / 2, height / 2);
cairo_translate (cr, width / 2, height / 2);
num_steps = 12;
cairo_set_line_width (cr, 2.0);
half = num_steps / 2;
for (i = 0; i < num_steps; i++)
{
gint inset = 0.7 * radius;
/* transparency is a function of time and intial value */
gdouble t = 1.0 - (gdouble) i / num_steps;
gdouble xscale = - sin (i * G_PI / half);
gdouble yscale = - cos (i * G_PI / half);
cairo_move_to (cr,
(radius - inset) * xscale,
(radius - inset) * yscale);
cairo_line_to (cr,
radius * xscale,
radius * yscale);
cairo_set_source_rgba (cr,
builtin->fg_color.red,
builtin->fg_color.green,
builtin->fg_color.blue,
builtin->fg_color.alpha * t);
cairo_stroke (cr);
}
}
static void
gtk_css_image_builtin_real_snapshot (GtkCssImage *image,
GtkSnapshot *snapshot,
double width,
double height)
{
/* It's a builtin image, other code will draw things */
}
static gboolean
gtk_css_image_builtin_parse (GtkCssImage *image,
GtkCssParser *parser)
{
if (!gtk_css_parser_try_ident (parser, "builtin"))
{
gtk_css_parser_error_syntax (parser, "Expected 'builtin'");
return FALSE;
}
return TRUE;
}
static void
gtk_css_image_builtin_print (GtkCssImage *image,
GString *string)
{
g_string_append (string, "builtin");
}
static GtkCssImage *
gtk_css_image_builtin_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GtkCssImageBuiltin *result;
result = g_object_new (GTK_TYPE_CSS_IMAGE_BUILTIN, NULL);
result->fg_color = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_COLOR));
result->bg_color = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BACKGROUND_COLOR));
return GTK_CSS_IMAGE (result);
}
static gboolean
gtk_css_image_builtin_equal (GtkCssImage *image1,
GtkCssImage *image2)
{
GtkCssImageBuiltin *builtin1 = (GtkCssImageBuiltin *) image1;
GtkCssImageBuiltin *builtin2 = (GtkCssImageBuiltin *) image2;
return gdk_rgba_equal (&builtin1->fg_color, &builtin2->fg_color)
&& gdk_rgba_equal (&builtin1->bg_color, &builtin2->bg_color);
}
static void
gtk_css_image_builtin_dispose (GObject *object)
{
if (the_one_true_image == GTK_CSS_IMAGE (object))
the_one_true_image = NULL;
G_OBJECT_CLASS (gtk_css_image_builtin_parent_class)->dispose (object);
}
static void
gtk_css_image_builtin_class_init (GtkCssImageBuiltinClass *klass)
{
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
image_class->snapshot = gtk_css_image_builtin_real_snapshot;
image_class->parse = gtk_css_image_builtin_parse;
image_class->print = gtk_css_image_builtin_print;
image_class->compute = gtk_css_image_builtin_compute;
image_class->equal = gtk_css_image_builtin_equal;
object_class->dispose = gtk_css_image_builtin_dispose;
}
static void
gtk_css_image_builtin_init (GtkCssImageBuiltin *builtin)
{
/* white background */
builtin->bg_color.red = builtin->bg_color.green = builtin->bg_color.blue = builtin->bg_color.alpha = 1.0;
/* black foreground */
builtin->fg_color.alpha = 1.0;
}
GtkCssImage *
gtk_css_image_builtin_new (void)
{
if (the_one_true_image == NULL)
the_one_true_image = g_object_new (GTK_TYPE_CSS_IMAGE_BUILTIN, NULL);
else
g_object_ref (the_one_true_image);
return the_one_true_image;
}
void
gtk_css_image_builtin_draw (GtkCssImage *image,
cairo_t *cr,
double width,
double height,
GtkCssImageBuiltinType image_type)
{
if (!GTK_IS_CSS_IMAGE_BUILTIN (image))
{
_gtk_css_image_draw (image, cr, width, height);
return;
}
switch (image_type)
{
default:
g_assert_not_reached ();
break;
case GTK_CSS_IMAGE_BUILTIN_NONE:
break;
case GTK_CSS_IMAGE_BUILTIN_CHECK:
case GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT:
gtk_css_image_builtin_draw_check (image, cr,
width, height,
image_type == GTK_CSS_IMAGE_BUILTIN_CHECK,
image_type == GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT);
break;
case GTK_CSS_IMAGE_BUILTIN_OPTION:
case GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT:
gtk_css_image_builtin_draw_option (image, cr,
width, height,
image_type == GTK_CSS_IMAGE_BUILTIN_OPTION,
image_type == GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT);
break;
case GTK_CSS_IMAGE_BUILTIN_ARROW_UP:
case GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN:
case GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT:
case GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT:
gtk_css_image_builtin_draw_arrow (image, cr,
width, height,
image_type);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
TRUE, FALSE, FALSE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
FALSE, FALSE, FALSE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
TRUE, TRUE, FALSE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
FALSE, TRUE, FALSE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT_EXPANDED:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
TRUE, FALSE, TRUE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT_EXPANDED:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
FALSE, FALSE, TRUE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT_EXPANDED:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
TRUE, TRUE, TRUE);
break;
case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT_EXPANDED:
gtk_css_image_builtin_draw_expander (image, cr,
width, height,
FALSE, TRUE, TRUE);
break;
case GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR:
gtk_css_image_builtin_draw_pane_separator (image, cr,
width, height);
break;
case GTK_CSS_IMAGE_BUILTIN_HANDLE:
gtk_css_image_builtin_draw_handle (image, cr,
width, height);
break;
case GTK_CSS_IMAGE_BUILTIN_SPINNER:
gtk_css_image_builtin_draw_spinner (image, cr,
width, height);
break;
}
}
void
gtk_css_image_builtin_snapshot (GtkCssImage *image,
GtkSnapshot *snapshot,
double width,
double height,
GtkCssImageBuiltinType image_type)
{
g_return_if_fail (GTK_IS_CSS_IMAGE (image));
g_return_if_fail (snapshot != NULL);
g_return_if_fail (width > 0);
g_return_if_fail (height > 0);
if (!GTK_IS_CSS_IMAGE_BUILTIN (image))
{
gtk_css_image_snapshot (image, snapshot, width, height);
return;
}
if (image_type != GTK_CSS_IMAGE_BUILTIN_NONE)
{
cairo_t *cr = gtk_snapshot_append_cairo (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_css_image_builtin_draw (image, cr, width, height, image_type);
cairo_destroy (cr);
}
}
-68
View File
@@ -1,68 +0,0 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_IMAGE_BUILTIN_PRIVATE_H__
#define __GTK_CSS_IMAGE_BUILTIN_PRIVATE_H__
#include "gtk/gtkcssimageprivate.h"
#include "gtk/gtkicontheme.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_IMAGE_BUILTIN (gtk_css_image_builtin_get_type ())
#define GTK_CSS_IMAGE_BUILTIN(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_BUILTIN, GtkCssImageBuiltin))
#define GTK_CSS_IMAGE_BUILTIN_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_BUILTIN, GtkCssImageBuiltinClass))
#define GTK_IS_CSS_IMAGE_BUILTIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_BUILTIN))
#define GTK_IS_CSS_IMAGE_BUILTIN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMAGE_BUILTIN))
#define GTK_CSS_IMAGE_BUILTIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMAGE_BUILTIN, GtkCssImageBuiltinClass))
typedef struct _GtkCssImageBuiltin GtkCssImageBuiltin;
typedef struct _GtkCssImageBuiltinClass GtkCssImageBuiltinClass;
struct _GtkCssImageBuiltin
{
GtkCssImage parent;
GdkRGBA fg_color;
GdkRGBA bg_color;
};
struct _GtkCssImageBuiltinClass
{
GtkCssImageClass parent_class;
};
GType gtk_css_image_builtin_get_type (void) G_GNUC_CONST;
GtkCssImage * gtk_css_image_builtin_new (void);
void gtk_css_image_builtin_draw (GtkCssImage *image,
cairo_t *cr,
double width,
double height,
GtkCssImageBuiltinType image_type);
void gtk_css_image_builtin_snapshot (GtkCssImage *image,
GtkSnapshot *snapshot,
double width,
double height,
GtkCssImageBuiltinType image_type);
G_END_DECLS
#endif /* __GTK_CSS_IMAGE_BUILTIN_PRIVATE_H__ */
+57 -195
View File
@@ -23,6 +23,21 @@
#include "gtkcssnodeprivate.h"
#include "gtkwidgetpath.h"
void
gtk_css_matcher_print (const GtkCssMatcher *matcher,
GString *string)
{
matcher->klass->print (matcher, string);
}
char *
gtk_css_matcher_to_string (const GtkCssMatcher *matcher)
{
GString *string = g_string_new ("");
gtk_css_matcher_print (matcher, string);
return g_string_free (string, FALSE);
}
/* GTK_CSS_MATCHER_WIDGET_PATH */
static gboolean
@@ -57,19 +72,26 @@ gtk_css_matcher_widget_path_get_previous (GtkCssMatcher *matcher,
return TRUE;
}
static GtkStateFlags
gtk_css_matcher_widget_path_get_state (const GtkCssMatcher *matcher)
static gboolean
gtk_css_matcher_widget_path_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{
const GtkWidgetPath *siblings;
GtkStateFlags path_state;
if (matcher->path.decl)
return gtk_css_node_declaration_get_state (matcher->path.decl);
siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
return gtk_widget_path_iter_get_state (siblings, matcher->path.sibling_index);
path_state = gtk_css_node_declaration_get_state (matcher->path.decl);
else
return gtk_widget_path_iter_get_state (matcher->path.path, matcher->path.index);
{
const GtkWidgetPath *siblings;
siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
path_state = gtk_widget_path_iter_get_state (siblings, matcher->path.sibling_index);
else
path_state = gtk_widget_path_iter_get_state (matcher->path.path, matcher->path.index);
}
return (path_state & state) == state;
}
static gboolean
@@ -158,15 +180,25 @@ gtk_css_matcher_widget_path_has_position (const GtkCssMatcher *matcher,
return x / a >= 0;
}
static void
gtk_css_matcher_widget_path_print (const GtkCssMatcher *matcher,
GString *string)
{
char *s = gtk_widget_path_to_string (matcher->path.path);
g_string_append (string, s);
g_free (s);
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_WIDGET_PATH = {
GTK_CSS_MATCHER_TYPE_WIDGET_PATH,
gtk_css_matcher_widget_path_get_parent,
gtk_css_matcher_widget_path_get_previous,
gtk_css_matcher_widget_path_get_state,
gtk_css_matcher_widget_path_has_state,
gtk_css_matcher_widget_path_has_name,
gtk_css_matcher_widget_path_has_class,
gtk_css_matcher_widget_path_has_id,
gtk_css_matcher_widget_path_has_position,
FALSE
gtk_css_matcher_widget_path_print
};
gboolean
@@ -234,10 +266,11 @@ gtk_css_matcher_node_get_previous (GtkCssMatcher *matcher,
return gtk_css_node_init_matcher (node, matcher);
}
static GtkStateFlags
gtk_css_matcher_node_get_state (const GtkCssMatcher *matcher)
static gboolean
gtk_css_matcher_node_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{
return matcher->node.node_state;
return (matcher->node.node_state & state) == state;
}
static gboolean
@@ -334,15 +367,23 @@ gtk_css_matcher_node_has_position (const GtkCssMatcher *matcher,
a, b);
}
static void
gtk_css_matcher_node_print (const GtkCssMatcher *matcher,
GString *string)
{
gtk_css_node_print (matcher->node.node, 0, string, 0);
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_NODE = {
GTK_CSS_MATCHER_TYPE_NODE,
gtk_css_matcher_node_get_parent,
gtk_css_matcher_node_get_previous,
gtk_css_matcher_node_get_state,
gtk_css_matcher_node_has_state,
gtk_css_matcher_node_has_name,
gtk_css_matcher_node_has_class,
gtk_css_matcher_node_has_id,
gtk_css_matcher_node_has_position,
FALSE
gtk_css_matcher_node_print
};
void
@@ -357,182 +398,3 @@ _gtk_css_matcher_node_init (GtkCssMatcher *matcher,
matcher->node.classes = gtk_css_node_declaration_get_classes (gtk_css_node_get_declaration (node),
&matcher->node.n_classes);
}
/* GTK_CSS_MATCHER_WIDGET_ANY */
static gboolean
gtk_css_matcher_any_get_parent (GtkCssMatcher *matcher,
const GtkCssMatcher *child)
{
_gtk_css_matcher_any_init (matcher);
return TRUE;
}
static gboolean
gtk_css_matcher_any_get_previous (GtkCssMatcher *matcher,
const GtkCssMatcher *next)
{
_gtk_css_matcher_any_init (matcher);
return TRUE;
}
static GtkStateFlags
gtk_css_matcher_any_get_state (const GtkCssMatcher *matcher)
{
/* XXX: This gets tricky when we implement :not() */
return GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED
| GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_INCONSISTENT
| GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_LINK
| GTK_STATE_FLAG_VISITED;
}
static gboolean
gtk_css_matcher_any_has_name (const GtkCssMatcher *matcher,
/*interned*/ const char *name)
{
return TRUE;
}
static gboolean
gtk_css_matcher_any_has_class (const GtkCssMatcher *matcher,
GQuark class_name)
{
return TRUE;
}
static gboolean
gtk_css_matcher_any_has_id (const GtkCssMatcher *matcher,
const char *id)
{
return TRUE;
}
static gboolean
gtk_css_matcher_any_has_position (const GtkCssMatcher *matcher,
gboolean forward,
int a,
int b)
{
return TRUE;
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_ANY = {
gtk_css_matcher_any_get_parent,
gtk_css_matcher_any_get_previous,
gtk_css_matcher_any_get_state,
gtk_css_matcher_any_has_name,
gtk_css_matcher_any_has_class,
gtk_css_matcher_any_has_id,
gtk_css_matcher_any_has_position,
TRUE
};
void
_gtk_css_matcher_any_init (GtkCssMatcher *matcher)
{
matcher->klass = &GTK_CSS_MATCHER_ANY;
}
/* GTK_CSS_MATCHER_WIDGET_SUPERSET */
static gboolean
gtk_css_matcher_superset_get_parent (GtkCssMatcher *matcher,
const GtkCssMatcher *child)
{
_gtk_css_matcher_any_init (matcher);
return TRUE;
}
static gboolean
gtk_css_matcher_superset_get_previous (GtkCssMatcher *matcher,
const GtkCssMatcher *next)
{
_gtk_css_matcher_any_init (matcher);
return TRUE;
}
static GtkStateFlags
gtk_css_matcher_superset_get_state (const GtkCssMatcher *matcher)
{
/* XXX: This gets tricky when we implement :not() */
if (matcher->superset.relevant & GTK_CSS_CHANGE_STATE)
return _gtk_css_matcher_get_state (matcher->superset.subset);
else
return GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED
| GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_INCONSISTENT
| GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_LINK
| GTK_STATE_FLAG_VISITED;
}
static gboolean
gtk_css_matcher_superset_has_name (const GtkCssMatcher *matcher,
/*interned*/ const char *name)
{
if (matcher->superset.relevant & GTK_CSS_CHANGE_NAME)
return _gtk_css_matcher_has_name (matcher->superset.subset, name);
else
return TRUE;
}
static gboolean
gtk_css_matcher_superset_has_class (const GtkCssMatcher *matcher,
GQuark class_name)
{
if (matcher->superset.relevant & GTK_CSS_CHANGE_CLASS)
return _gtk_css_matcher_has_class (matcher->superset.subset, class_name);
else
return TRUE;
}
static gboolean
gtk_css_matcher_superset_has_id (const GtkCssMatcher *matcher,
const char *id)
{
if (matcher->superset.relevant & GTK_CSS_CHANGE_NAME)
return _gtk_css_matcher_has_id (matcher->superset.subset, id);
else
return TRUE;
}
static gboolean
gtk_css_matcher_superset_has_position (const GtkCssMatcher *matcher,
gboolean forward,
int a,
int b)
{
if (matcher->superset.relevant & GTK_CSS_CHANGE_POSITION)
return _gtk_css_matcher_has_position (matcher->superset.subset, forward, a, b);
else
return TRUE;
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_SUPERSET = {
gtk_css_matcher_superset_get_parent,
gtk_css_matcher_superset_get_previous,
gtk_css_matcher_superset_get_state,
gtk_css_matcher_superset_has_name,
gtk_css_matcher_superset_has_class,
gtk_css_matcher_superset_has_id,
gtk_css_matcher_superset_has_position,
FALSE
};
void
_gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
const GtkCssMatcher *subset,
GtkCssChange relevant)
{
g_return_if_fail (subset != NULL);
g_return_if_fail ((relevant & ~(GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_STATE)) == 0);
matcher->superset.klass = &GTK_CSS_MATCHER_SUPERSET;
matcher->superset.subset = subset;
matcher->superset.relevant = relevant;
}
+18 -23
View File
@@ -29,13 +29,20 @@ typedef struct _GtkCssMatcherSuperset GtkCssMatcherSuperset;
typedef struct _GtkCssMatcherWidgetPath GtkCssMatcherWidgetPath;
typedef struct _GtkCssMatcherClass GtkCssMatcherClass;
typedef enum {
GTK_CSS_MATCHER_TYPE_NODE,
GTK_CSS_MATCHER_TYPE_WIDGET_PATH
} GtkCssMatcherType;
struct _GtkCssMatcherClass {
GtkCssMatcherType type;
gboolean (* get_parent) (GtkCssMatcher *matcher,
const GtkCssMatcher *child);
gboolean (* get_previous) (GtkCssMatcher *matcher,
const GtkCssMatcher *next);
GtkStateFlags (* get_state) (const GtkCssMatcher *matcher);
gboolean (* has_state) (const GtkCssMatcher *matcher,
GtkStateFlags state);
gboolean (* has_name) (const GtkCssMatcher *matcher,
/*interned*/const char*name);
gboolean (* has_class) (const GtkCssMatcher *matcher,
@@ -46,7 +53,8 @@ struct _GtkCssMatcherClass {
gboolean forward,
int a,
int b);
gboolean is_any;
void (* print) (const GtkCssMatcher *matcher,
GString *string);
};
struct _GtkCssMatcherWidgetPath {
@@ -67,17 +75,10 @@ struct _GtkCssMatcherNode {
guint n_classes;
};
struct _GtkCssMatcherSuperset {
const GtkCssMatcherClass *klass;
const GtkCssMatcher *subset;
GtkCssChange relevant;
};
union _GtkCssMatcher {
const GtkCssMatcherClass *klass;
GtkCssMatcherWidgetPath path;
GtkCssMatcherNode node;
GtkCssMatcherSuperset superset;
};
gboolean _gtk_css_matcher_init (GtkCssMatcher *matcher,
@@ -85,10 +86,10 @@ gboolean _gtk_css_matcher_init (GtkCssMatcher *match
const GtkCssNodeDeclaration *decl) G_GNUC_WARN_UNUSED_RESULT;
void _gtk_css_matcher_node_init (GtkCssMatcher *matcher,
GtkCssNode *node);
void _gtk_css_matcher_any_init (GtkCssMatcher *matcher);
void _gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
const GtkCssMatcher *subset,
GtkCssChange relevant);
void gtk_css_matcher_print (const GtkCssMatcher *matcher,
GString *string);
char * gtk_css_matcher_to_string (const GtkCssMatcher *matcher);
static inline gboolean
@@ -105,10 +106,11 @@ _gtk_css_matcher_get_previous (GtkCssMatcher *matcher,
return next->klass->get_previous (matcher, next);
}
static inline GtkStateFlags
_gtk_css_matcher_get_state (const GtkCssMatcher *matcher)
static inline gboolean
_gtk_css_matcher_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
{
return matcher->klass->get_state (matcher);
return matcher->klass->has_state (matcher, state);
}
static inline gboolean
@@ -141,13 +143,6 @@ _gtk_css_matcher_has_position (const GtkCssMatcher *matcher,
return matcher->klass->has_position (matcher, forward, a, b);
}
static inline gboolean
_gtk_css_matcher_matches_any (const GtkCssMatcher *matcher)
{
return matcher->klass->is_any;
}
G_END_DECLS
#endif /* __GTK_CSS_MATCHER_PRIVATE_H__ */
+46 -13
View File
@@ -87,6 +87,11 @@
* if we need to change things. */
#define GTK_CSS_RADICAL_CHANGE (GTK_CSS_CHANGE_ID | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_SOURCE | GTK_CSS_CHANGE_PARENT_STYLE)
/* When these change, we need to recompute the change flags for the new style
* since they may have changed.
*/
#define GTK_CSS_CHANGE_NEEDS_RECOMPUTE (GTK_CSS_RADICAL_CHANGE & ~GTK_CSS_CHANGE_PARENT_STYLE)
G_DEFINE_TYPE (GtkCssNode, gtk_css_node, G_TYPE_OBJECT)
enum {
@@ -348,12 +353,14 @@ store_in_global_parent_cache (GtkCssNode *node,
}
static GtkCssStyle *
gtk_css_node_create_style (GtkCssNode *cssnode)
gtk_css_node_create_style (GtkCssNode *cssnode,
GtkCssChange change)
{
const GtkCssNodeDeclaration *decl;
GtkCssMatcher matcher;
GtkCssStyle *parent;
GtkCssStyle *style;
GtkCssChange style_change;
decl = gtk_css_node_get_declaration (cssnode);
@@ -363,14 +370,26 @@ gtk_css_node_create_style (GtkCssNode *cssnode)
parent = cssnode->parent ? cssnode->parent->style : NULL;
if (change & GTK_CSS_CHANGE_NEEDS_RECOMPUTE)
{
/* Need to recompute the change flags */
style_change = 0;
}
else
{
style_change = gtk_css_static_style_get_change (gtk_css_style_get_static_style (cssnode->style));
}
if (gtk_css_node_init_matcher (cssnode, &matcher))
style = gtk_css_static_style_new_compute (gtk_css_node_get_style_provider (cssnode),
&matcher,
parent);
parent,
style_change);
else
style = gtk_css_static_style_new_compute (gtk_css_node_get_style_provider (cssnode),
NULL,
parent);
parent,
style_change);
store_in_global_parent_cache (cssnode, decl, style);
@@ -407,17 +426,10 @@ gtk_css_node_real_update_style (GtkCssNode *cssnode,
{
GtkCssStyle *static_style, *new_static_style, *new_style;
if (GTK_IS_CSS_ANIMATED_STYLE (style))
{
static_style = GTK_CSS_ANIMATED_STYLE (style)->style;
}
else
{
static_style = style;
}
static_style = GTK_CSS_STYLE (gtk_css_style_get_static_style (style));
if (gtk_css_style_needs_recreation (static_style, change))
new_static_style = gtk_css_node_create_style (cssnode);
new_static_style = gtk_css_node_create_style (cssnode, change);
else
new_static_style = g_object_ref (static_style);
@@ -1138,9 +1150,30 @@ void
gtk_css_node_set_state (GtkCssNode *cssnode,
GtkStateFlags state_flags)
{
GtkStateFlags old_state;
old_state = gtk_css_node_declaration_get_state (cssnode->decl);
if (gtk_css_node_declaration_set_state (&cssnode->decl, state_flags))
{
gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_STATE);
GtkStateFlags states = old_state ^ state_flags;
GtkCssChange change = 0;
if (states & GTK_STATE_FLAG_PRELIGHT)
change |= GTK_CSS_CHANGE_HOVER;
if (states & GTK_STATE_FLAG_INSENSITIVE)
change |= GTK_CSS_CHANGE_DISABLED;
if (states & GTK_STATE_FLAG_BACKDROP)
change |= GTK_CSS_CHANGE_BACKDROP;
if (states & GTK_STATE_FLAG_SELECTED)
change |= GTK_CSS_CHANGE_SELECTED;
if (states & ~(GTK_STATE_FLAG_PRELIGHT |
GTK_STATE_FLAG_INSENSITIVE |
GTK_STATE_FLAG_BACKDROP |
GTK_STATE_FLAG_SELECTED))
change |= GTK_CSS_CHANGE_STATE;
gtk_css_node_invalidate (cssnode, change);
g_object_notify_by_pspec (G_OBJECT (cssnode), cssnode_properties[PROP_STATE]);
}
}
+1 -88
View File
@@ -99,7 +99,6 @@ struct GtkCssRuleset
GtkCssSelector *selector;
GtkCssSelectorTree *selector_match;
PropertyValue *styles;
GtkBitmask *set_styles;
guint n_styles;
guint owns_styles : 1;
};
@@ -236,8 +235,6 @@ gtk_css_ruleset_init_copy (GtkCssRuleset *new,
/* First copy takes over ownership */
if (ruleset->owns_styles)
ruleset->owns_styles = FALSE;
if (new->set_styles)
new->set_styles = _gtk_bitmask_copy (new->set_styles);
}
static void
@@ -256,8 +253,6 @@ gtk_css_ruleset_clear (GtkCssRuleset *ruleset)
}
g_free (ruleset->styles);
}
if (ruleset->set_styles)
_gtk_bitmask_free (ruleset->set_styles);
if (ruleset->selector)
_gtk_css_selector_free (ruleset->selector);
@@ -274,13 +269,6 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset,
g_return_if_fail (ruleset->owns_styles || ruleset->n_styles == 0);
if (ruleset->set_styles == NULL)
ruleset->set_styles = _gtk_bitmask_new ();
ruleset->set_styles = _gtk_bitmask_set (ruleset->set_styles,
_gtk_css_style_property_get_id (property),
TRUE);
ruleset->owns_styles = TRUE;
for (i = 0; i < ruleset->n_styles; i++)
@@ -437,62 +425,6 @@ verify_tree_match_results (GtkCssProvider *provider,
#endif
}
static void
verify_tree_get_change_results (GtkCssProvider *provider,
const GtkCssMatcher *matcher,
GtkCssChange change)
{
#ifdef VERIFY_TREE
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (provider);
GtkCssChange verify_change = 0;
GPtrArray *tree_rules;
int i;
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, matcher);
if (tree_rules)
{
verify_tree_match_results (provider, matcher, tree_rules);
for (i = tree_rules->len - 1; i >= 0; i--)
{
GtkCssRuleset *ruleset;
ruleset = tree_rules->pdata[i];
verify_change |= _gtk_css_selector_get_change (ruleset->selector);
}
g_ptr_array_free (tree_rules, TRUE);
}
if (change != verify_change)
{
GString *s;
s = g_string_new ("");
g_string_append (s, "expected change ");
gtk_css_change_print (verify_change, s);
g_string_append (s, ", but it was ");
gtk_css_change_print (change, s);
if ((change & ~verify_change) != 0)
{
g_string_append (s, ", unexpectedly set: ");
gtk_css_change_print (change & ~verify_change, s);
}
if ((~change & verify_change) != 0)
{
g_string_append_printf (s, ", unexpectedly not set: ");
gtk_css_change_print (~change & verify_change, s);
}
g_warning (s->str);
g_string_free (s, TRUE);
}
}
#endif
}
static GtkCssValue *
gtk_css_style_provider_get_color (GtkStyleProvider *provider,
const char *name)
@@ -563,14 +495,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
}
if (change)
{
GtkCssMatcher change_matcher;
_gtk_css_matcher_superset_init (&change_matcher, matcher, GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS);
*change = _gtk_css_selector_tree_get_change_all (priv->tree, &change_matcher);
verify_tree_get_change_results (css_provider, &change_matcher, *change);
}
*change = _gtk_css_selector_tree_get_change_all (priv->tree, matcher);
}
static void
@@ -1059,18 +984,6 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
priv->tree = _gtk_css_selector_tree_builder_build (builder);
_gtk_css_selector_tree_builder_free (builder);
#ifndef VERIFY_TREE
for (i = 0; i < priv->rulesets->len; i++)
{
GtkCssRuleset *ruleset;
ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
_gtk_css_selector_free (ruleset->selector);
ruleset->selector = NULL;
}
#endif
}
static void
+78 -29
View File
@@ -62,7 +62,8 @@ struct _GtkCssSelectorClass {
int (* compare_one) (const GtkCssSelector *a,
const GtkCssSelector *b);
guint is_simple :1;
guint is_simple : 1;
guint ignore_for_change : 1;
};
typedef enum {
@@ -294,11 +295,6 @@ gtk_css_selector_descendant_foreach_matcher (const GtkCssSelector *selector
if (func (selector, &ancestor, data))
return TRUE;
/* any matchers are dangerous here, as we may loop forever, but
we can terminate now as all possible matches have already been added */
if (_gtk_css_matcher_matches_any (matcher))
break;
}
return FALSE;
@@ -319,7 +315,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE
FALSE,
TRUE
};
/* CHILD */
@@ -360,7 +357,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE
FALSE,
TRUE
};
/* SIBLING */
@@ -386,11 +384,6 @@ gtk_css_selector_sibling_foreach_matcher (const GtkCssSelector *selector,
if (func (selector, matcher, data))
return TRUE;
/* any matchers are dangerous here, as we may loop forever, but
we can terminate now as all possible matches have already been added */
if (_gtk_css_matcher_matches_any (matcher))
break;
}
return FALSE;
@@ -411,7 +404,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE
FALSE,
TRUE
};
/* ADJACENT */
@@ -452,7 +446,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE
FALSE,
TRUE
};
/* SIMPLE SELECTOR DEFINE */
@@ -465,7 +460,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
comp_func, \
increase_id_specificity, \
increase_class_specificity, \
increase_element_specificity) \
increase_element_specificity, \
ignore_for_change) \
static void \
gtk_css_selector_ ## n ## _print (const GtkCssSelector *selector, \
GString *string) \
@@ -524,7 +520,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
TRUE \
TRUE, \
ignore_for_change \
};\
\
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
@@ -536,7 +533,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
TRUE \
TRUE, \
ignore_for_change \
};
/* ANY */
@@ -559,7 +557,7 @@ match_any (const GtkCssSelector *selector,
#define GTK_CSS_CHANGE_ANY 0
DEFINE_SIMPLE_SELECTOR(any, ANY, print_any, match_any,
gtk_css_selector_default_hash_one, gtk_css_selector_default_compare_one,
FALSE, FALSE, FALSE)
FALSE, FALSE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_ANY
/* NAME */
@@ -592,7 +590,7 @@ comp_name (const GtkCssSelector *a,
b->name.name);
}
DEFINE_SIMPLE_SELECTOR(name, NAME, print_name, match_name, hash_name, comp_name, FALSE, FALSE, TRUE)
DEFINE_SIMPLE_SELECTOR(name, NAME, print_name, match_name, hash_name, comp_name, FALSE, FALSE, TRUE, FALSE)
/* CLASS */
@@ -629,7 +627,7 @@ comp_class (const GtkCssSelector *a,
return 0;
}
DEFINE_SIMPLE_SELECTOR(class, CLASS, print_class, match_class, hash_class, comp_class, FALSE, TRUE, FALSE)
DEFINE_SIMPLE_SELECTOR(class, CLASS, print_class, match_class, hash_class, comp_class, FALSE, TRUE, FALSE, FALSE)
/* ID */
@@ -666,7 +664,7 @@ comp_id (const GtkCssSelector *a,
return 0;
}
DEFINE_SIMPLE_SELECTOR(id, ID, print_id, match_id, hash_id, comp_id, TRUE, FALSE, FALSE)
DEFINE_SIMPLE_SELECTOR(id, ID, print_id, match_id, hash_id, comp_id, TRUE, FALSE, FALSE, FALSE)
const gchar *
gtk_css_pseudoclass_name (GtkStateFlags state)
@@ -711,7 +709,7 @@ static gboolean
match_pseudoclass_state (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
return (_gtk_css_matcher_get_state (matcher) & selector->state.state) == selector->state.state;
return _gtk_css_matcher_has_state (matcher, selector->state.state);
}
static guint
@@ -728,10 +726,34 @@ comp_pseudoclass_state (const GtkCssSelector *a,
return a->state.state - b->state.state;
}
#define GTK_CSS_CHANGE_PSEUDOCLASS_HOVER GTK_CSS_CHANGE_HOVER
DEFINE_SIMPLE_SELECTOR(pseudoclass_hover, PSEUDOCLASS_HOVER, print_pseudoclass_state,
match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
FALSE, TRUE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_PSEUDOCLASS_HOVER
#define GTK_CSS_CHANGE_PSEUDOCLASS_DISABLED GTK_CSS_CHANGE_DISABLED
DEFINE_SIMPLE_SELECTOR(pseudoclass_disabled, PSEUDOCLASS_DISABLED, print_pseudoclass_state,
match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
FALSE, TRUE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_PSEUDOCLASS_DISABLED
#define GTK_CSS_CHANGE_PSEUDOCLASS_BACKDROP GTK_CSS_CHANGE_BACKDROP
DEFINE_SIMPLE_SELECTOR(pseudoclass_backdrop, PSEUDOCLASS_BACKDROP, print_pseudoclass_state,
match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
FALSE, TRUE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_PSEUDOCLASS_BACKDROP
#define GTK_CSS_CHANGE_PSEUDOCLASS_SELECTED GTK_CSS_CHANGE_SELECTED
DEFINE_SIMPLE_SELECTOR(pseudoclass_selected, PSEUDOCLASS_SELECTED, print_pseudoclass_state,
match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
FALSE, TRUE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_PSEUDOCLASS_SELECTED
#define GTK_CSS_CHANGE_PSEUDOCLASS_STATE GTK_CSS_CHANGE_STATE
DEFINE_SIMPLE_SELECTOR(pseudoclass_state, PSEUDOCLASS_STATE, print_pseudoclass_state,
match_pseudoclass_state, hash_pseudoclass_state, comp_pseudoclass_state,
FALSE, TRUE, FALSE)
FALSE, TRUE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_PSEUDOCLASS_STATE
/* PSEUDOCLASS FOR POSITION */
@@ -885,7 +907,7 @@ change_pseudoclass_position (const GtkCssSelector *selector)
#define GTK_CSS_CHANGE_PSEUDOCLASS_POSITION change_pseudoclass_position(selector)
DEFINE_SIMPLE_SELECTOR(pseudoclass_position, PSEUDOCLASS_POSITION, print_pseudoclass_position,
match_pseudoclass_position, hash_pseudoclass_position, comp_pseudoclass_position,
FALSE, TRUE, FALSE)
FALSE, TRUE, FALSE, TRUE)
#undef GTK_CSS_CHANGE_PSEUDOCLASS_POSITION
/* API */
@@ -1288,9 +1310,26 @@ gtk_css_selector_parse_selector_pseudo_class (GtkCssParser *parser,
{
if (pseudo_classes[i].state_flag)
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
if (pseudo_classes[i].state_flag == GTK_STATE_FLAG_PRELIGHT)
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_HOVER
: &GTK_CSS_SELECTOR_PSEUDOCLASS_HOVER,
selector);
else if (pseudo_classes[i].state_flag == GTK_STATE_FLAG_INSENSITIVE)
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_DISABLED
: &GTK_CSS_SELECTOR_PSEUDOCLASS_DISABLED,
selector);
else if (pseudo_classes[i].state_flag == GTK_STATE_FLAG_BACKDROP)
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_BACKDROP
: &GTK_CSS_SELECTOR_PSEUDOCLASS_BACKDROP,
selector);
else if (pseudo_classes[i].state_flag == GTK_STATE_FLAG_SELECTED)
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_SELECTED
: &GTK_CSS_SELECTOR_PSEUDOCLASS_SELECTED,
selector);
else
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = pseudo_classes[i].state_flag;
}
else
@@ -1687,6 +1726,16 @@ _gtk_css_selector_matches (const GtkCssSelector *selector,
return gtk_css_selector_foreach (selector, matcher, gtk_css_selector_foreach_match, NULL);
}
static gboolean
gtk_css_selector_match_for_change (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
if (selector->class->ignore_for_change)
return TRUE;
return selector->class->match_one (selector, matcher);
}
/* Computes specificity according to CSS 2.1.
* The arguments must be initialized to 0 */
static void
@@ -1870,7 +1919,7 @@ gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
GtkCssChange change = 0;
const GtkCssSelectorTree *prev;
if (!gtk_css_selector_match (&tree->selector, matcher))
if (!gtk_css_selector_match_for_change (&tree->selector, matcher))
return 0;
if (!tree->selector.class->is_simple)
+12 -4
View File
@@ -83,6 +83,12 @@ gtk_css_static_style_dispose (GObject *object)
G_OBJECT_CLASS (gtk_css_static_style_parent_class)->dispose (object);
}
static GtkCssStaticStyle *
gtk_css_static_style_get_static_style (GtkCssStyle *style)
{
return (GtkCssStaticStyle *)style;
}
static void
gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass)
{
@@ -93,6 +99,7 @@ gtk_css_static_style_class_init (GtkCssStaticStyleClass *klass)
style_class->get_value = gtk_css_static_style_get_value;
style_class->get_section = gtk_css_static_style_get_section;
style_class->get_static_style = gtk_css_static_style_get_static_style;
}
static void
@@ -158,7 +165,8 @@ gtk_css_static_style_get_default (void)
settings = gtk_settings_get_default ();
default_style = gtk_css_static_style_new_compute (GTK_STYLE_PROVIDER (settings),
NULL,
NULL);
NULL,
TRUE);
g_object_set_data_full (G_OBJECT (settings), I_("gtk-default-style"),
default_style, clear_default_style);
}
@@ -169,11 +177,11 @@ gtk_css_static_style_get_default (void)
GtkCssStyle *
gtk_css_static_style_new_compute (GtkStyleProvider *provider,
const GtkCssMatcher *matcher,
GtkCssStyle *parent)
GtkCssStyle *parent,
GtkCssChange change)
{
GtkCssStaticStyle *result;
GtkCssLookup lookup;
GtkCssChange change = GTK_CSS_CHANGE_ANY_SELF | GTK_CSS_CHANGE_ANY_SIBLING | GTK_CSS_CHANGE_ANY_PARENT;
_gtk_css_lookup_init (&lookup);
@@ -181,7 +189,7 @@ gtk_css_static_style_new_compute (GtkStyleProvider *provider,
gtk_style_provider_lookup (provider,
matcher,
&lookup,
&change);
change == 0 ? &change : NULL);
result = g_object_new (GTK_TYPE_CSS_STATIC_STYLE, NULL);
+2 -2
View File
@@ -32,7 +32,6 @@ G_BEGIN_DECLS
#define GTK_IS_CSS_STATIC_STYLE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_STATIC_STYLE))
#define GTK_CSS_STATIC_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_STATIC_STYLE, GtkCssStaticStyleClass))
typedef struct _GtkCssStaticStyle GtkCssStaticStyle;
typedef struct _GtkCssStaticStyleClass GtkCssStaticStyleClass;
struct _GtkCssStaticStyle
@@ -55,7 +54,8 @@ GType gtk_css_static_style_get_type (void) G_GNUC_CO
GtkCssStyle * gtk_css_static_style_get_default (void);
GtkCssStyle * gtk_css_static_style_new_compute (GtkStyleProvider *provider,
const GtkCssMatcher *matcher,
GtkCssStyle *parent);
GtkCssStyle *parent,
GtkCssChange change);
void gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
+8
View File
@@ -89,6 +89,14 @@ gtk_css_style_is_static (GtkCssStyle *style)
return GTK_CSS_STYLE_GET_CLASS (style)->is_static (style);
}
GtkCssStaticStyle *
gtk_css_style_get_static_style (GtkCssStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
return GTK_CSS_STYLE_GET_CLASS (style)->get_static_style (style);
}
/*
* gtk_css_style_print:
* @style: a #GtkCssStyle
+3
View File
@@ -56,6 +56,8 @@ struct _GtkCssStyleClass
guint id);
/* TRUE if this style will require changes based on timestamp */
gboolean (* is_static) (GtkCssStyle *style);
GtkCssStaticStyle * (* get_static_style) (GtkCssStyle *style);
};
GType gtk_css_style_get_type (void) G_GNUC_CONST;
@@ -74,6 +76,7 @@ gboolean gtk_css_style_print (GtkCssStyle
PangoAttrList * gtk_css_style_get_pango_attributes (GtkCssStyle *style);
PangoFontDescription * gtk_css_style_get_pango_font (GtkCssStyle *style);
GtkCssStaticStyle * gtk_css_style_get_static_style (GtkCssStyle *style);
G_END_DECLS
-30
View File
@@ -372,33 +372,3 @@ _gtk_css_style_property_get_initial_value (GtkCssStyleProperty *property)
return property->initial_value;
}
/**
* _gtk_css_style_property_get_mask_affecting:
* @flags: the flags that are affected
*
* Computes a bitmask for all properties that have at least one of @flags
* set.
*
* Returns: (transfer full): A #GtkBitmask with the bit set for every
* property that has at least one of @flags set.
*/
GtkBitmask *
_gtk_css_style_property_get_mask_affecting (GtkCssAffects affects)
{
GtkBitmask *result;
guint i;
result = _gtk_bitmask_new ();
for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
{
GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i);
if (_gtk_css_style_property_get_affects (prop) & affects)
result = _gtk_bitmask_set (result, i, TRUE);
}
return result;
}
+2 -13
View File
@@ -46,7 +46,6 @@
#include "gtkcssfontfeaturesvalueprivate.h"
#include "gtkcssiconthemevalueprivate.h"
#include "gtkcssimageprivate.h"
#include "gtkcssimagebuiltinprivate.h"
#include "gtkcssimagevalueprivate.h"
#include "gtkcssinitialvalueprivate.h"
#include "gtkcssenumvalueprivate.h"
@@ -677,16 +676,6 @@ css_image_value_parse (GtkCssStyleProperty *property,
return _gtk_css_image_value_new (image);
}
static GtkCssValue *
css_image_value_parse_with_builtin (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
if (gtk_css_parser_try_ident (parser, "builtin"))
return _gtk_css_image_value_new (gtk_css_image_builtin_new ());
return css_image_value_parse (property, parser);
}
static GtkCssValue *
background_image_value_parse_one (GtkCssParser *parser)
{
@@ -1512,9 +1501,9 @@ _gtk_css_style_property_init_properties (void)
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
css_image_value_parse_with_builtin,
css_image_value_parse,
NULL,
_gtk_css_image_value_new (gtk_css_image_builtin_new ()));
_gtk_css_image_value_new (NULL));
gtk_css_style_property_register ("-gtk-icon-size",
GTK_CSS_PROPERTY_ICON_SIZE,
G_TYPE_NONE,
-3
View File
@@ -80,9 +80,6 @@ void _gtk_css_style_property_print_value (GtkCssStyleProp
GtkCssValue *value,
GString *string);
GtkBitmask * _gtk_css_style_property_get_mask_affecting
(GtkCssAffects affects);
/* XXX - find a better place for these */
GtkCssValue * gtk_css_font_family_value_parse (GtkCssParser *parser);
GtkCssValue * gtk_css_font_size_value_parse (GtkCssParser *parser);
+38 -9
View File
@@ -74,19 +74,20 @@ _gtk_css_change_for_sibling (GtkCssChange match)
| GTK_CSS_CHANGE_LAST_CHILD \
| GTK_CSS_CHANGE_NTH_CHILD \
| GTK_CSS_CHANGE_NTH_LAST_CHILD \
| GTK_CSS_CHANGE_STATE )
| GTK_CSS_CHANGE_STATE \
| GTK_CSS_CHANGE_HOVER \
| GTK_CSS_CHANGE_DISABLED \
| GTK_CSS_CHANGE_SELECTED \
| GTK_CSS_CHANGE_BACKDROP)
#define KEEP_STATES ( ~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE) \
| GTK_CSS_CHANGE_NTH_CHILD \
| GTK_CSS_CHANGE_NTH_LAST_CHILD)
#define SIBLING_SHIFT 8
return (match & KEEP_STATES) | ((match & BASE_STATES) << SIBLING_SHIFT);
return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_SIBLING_SHIFT);
#undef BASE_STATES
#undef KEEP_STATES
#undef SIBLING_SHIFT
}
GtkCssChange
@@ -100,6 +101,10 @@ _gtk_css_change_for_child (GtkCssChange match)
| GTK_CSS_CHANGE_NTH_CHILD \
| GTK_CSS_CHANGE_NTH_LAST_CHILD \
| GTK_CSS_CHANGE_STATE \
| GTK_CSS_CHANGE_HOVER \
| GTK_CSS_CHANGE_DISABLED \
| GTK_CSS_CHANGE_BACKDROP \
| GTK_CSS_CHANGE_SELECTED \
| GTK_CSS_CHANGE_SIBLING_CLASS \
| GTK_CSS_CHANGE_SIBLING_NAME \
| GTK_CSS_CHANGE_SIBLING_ID \
@@ -107,14 +112,18 @@ _gtk_css_change_for_child (GtkCssChange match)
| GTK_CSS_CHANGE_SIBLING_LAST_CHILD \
| GTK_CSS_CHANGE_SIBLING_NTH_CHILD \
| GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD \
| GTK_CSS_CHANGE_SIBLING_STATE )
| GTK_CSS_CHANGE_SIBLING_STATE \
| GTK_CSS_CHANGE_SIBLING_HOVER \
| GTK_CSS_CHANGE_SIBLING_DISABLED \
| GTK_CSS_CHANGE_SIBLING_BACKDROP \
| GTK_CSS_CHANGE_SIBLING_SELECTED)
#define PARENT_SHIFT 16
#define KEEP_STATES (~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE))
return (match & ~(BASE_STATES|GTK_CSS_CHANGE_SOURCE|GTK_CSS_CHANGE_PARENT_STYLE)) | ((match & BASE_STATES) << PARENT_SHIFT);
return (match & KEEP_STATES) | ((match & BASE_STATES) << GTK_CSS_CHANGE_PARENT_SHIFT);
#undef BASE_STATES
#undef PARENT_SHIFT
#undef KEEP_STATES
}
void
@@ -133,6 +142,11 @@ gtk_css_change_print (GtkCssChange change,
{ GTK_CSS_CHANGE_NTH_CHILD, "nth-child" },
{ GTK_CSS_CHANGE_NTH_LAST_CHILD, "nth-last-child" },
{ GTK_CSS_CHANGE_STATE, "state" },
{ GTK_CSS_CHANGE_HOVER, "hover" },
{ GTK_CSS_CHANGE_DISABLED, "disabled" },
{ GTK_CSS_CHANGE_BACKDROP, "backdrop" },
{ GTK_CSS_CHANGE_SELECTED, "selected" },
{ GTK_CSS_CHANGE_SIBLING_CLASS, "sibling-class" },
{ GTK_CSS_CHANGE_SIBLING_NAME, "sibling-name" },
{ GTK_CSS_CHANGE_SIBLING_ID, "sibling-id" },
@@ -141,6 +155,11 @@ gtk_css_change_print (GtkCssChange change,
{ GTK_CSS_CHANGE_SIBLING_NTH_CHILD, "sibling-nth-child" },
{ GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD, "sibling-nth-last-child" },
{ GTK_CSS_CHANGE_SIBLING_STATE, "sibling-state" },
{ GTK_CSS_CHANGE_SIBLING_HOVER, "sibling-hover" },
{ GTK_CSS_CHANGE_SIBLING_DISABLED, "sibling-disabled" },
{ GTK_CSS_CHANGE_SIBLING_BACKDROP, "sibling-backdrop" },
{ GTK_CSS_CHANGE_SIBLING_SELECTED, "sibling-selected" },
{ GTK_CSS_CHANGE_PARENT_CLASS, "parent-class" },
{ GTK_CSS_CHANGE_PARENT_NAME, "parent-name" },
{ GTK_CSS_CHANGE_PARENT_ID, "parent-id" },
@@ -149,6 +168,11 @@ gtk_css_change_print (GtkCssChange change,
{ GTK_CSS_CHANGE_PARENT_NTH_CHILD, "parent-nth-child" },
{ GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD, "parent-nth-last-child" },
{ GTK_CSS_CHANGE_PARENT_STATE, "parent-state" },
{ GTK_CSS_CHANGE_PARENT_HOVER, "parent-hover" },
{ GTK_CSS_CHANGE_PARENT_DISABLED, "parent-disabled" },
{ GTK_CSS_CHANGE_PARENT_BACKDROP, "parent-backdrop" },
{ GTK_CSS_CHANGE_PARENT_SELECTED, "parent-selected" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_CLASS, "parent-sibling-" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_NAME, "parent-sibling-name" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_ID, "parent-sibling-id" },
@@ -157,6 +181,11 @@ gtk_css_change_print (GtkCssChange change,
{ GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD, "parent-sibling-nth-child" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD, "parent-sibling-nth-last-child" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_STATE, "parent-sibling-state" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_HOVER, "parent-sibling-hover" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_DISABLED, "parent-sibling-disabled" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_BACKDROP, "parent-sibling-backdrop" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_SELECTED, "parent-sibling-selected" },
{ GTK_CSS_CHANGE_SOURCE, "source" },
{ GTK_CSS_CHANGE_PARENT_STYLE, "parent-style" },
{ GTK_CSS_CHANGE_TIMESTAMP, "timestamp" },
+80 -70
View File
@@ -27,6 +27,7 @@ typedef union _GtkCssMatcher GtkCssMatcher;
typedef struct _GtkCssNode GtkCssNode;
typedef struct _GtkCssNodeDeclaration GtkCssNodeDeclaration;
typedef struct _GtkCssStyle GtkCssStyle;
typedef struct _GtkCssStaticStyle GtkCssStaticStyle;
#define GTK_CSS_CHANGE_CLASS (1ULL << 0)
#define GTK_CSS_CHANGE_NAME (1ULL << 1)
@@ -36,61 +37,93 @@ typedef struct _GtkCssStyle GtkCssStyle;
#define GTK_CSS_CHANGE_NTH_CHILD (1ULL << 5)
#define GTK_CSS_CHANGE_NTH_LAST_CHILD (1ULL << 6)
#define GTK_CSS_CHANGE_STATE (1ULL << 7)
#define GTK_CSS_CHANGE_SIBLING_CLASS (1ULL << 8)
#define GTK_CSS_CHANGE_SIBLING_NAME (1ULL << 9)
#define GTK_CSS_CHANGE_SIBLING_ID (1ULL << 10)
#define GTK_CSS_CHANGE_SIBLING_FIRST_CHILD (1ULL << 11)
#define GTK_CSS_CHANGE_SIBLING_LAST_CHILD (1ULL << 12)
#define GTK_CSS_CHANGE_SIBLING_NTH_CHILD (1ULL << 13)
#define GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD (1ULL << 14)
#define GTK_CSS_CHANGE_SIBLING_STATE (1ULL << 15)
#define GTK_CSS_CHANGE_PARENT_CLASS (1ULL << 16)
#define GTK_CSS_CHANGE_PARENT_NAME (1ULL << 17)
#define GTK_CSS_CHANGE_PARENT_ID (1ULL << 18)
#define GTK_CSS_CHANGE_PARENT_FIRST_CHILD (1ULL << 19)
#define GTK_CSS_CHANGE_PARENT_LAST_CHILD (1ULL << 20)
#define GTK_CSS_CHANGE_PARENT_NTH_CHILD (1ULL << 21)
#define GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD (1ULL << 22)
#define GTK_CSS_CHANGE_PARENT_STATE (1ULL << 23)
#define GTK_CSS_CHANGE_PARENT_SIBLING_CLASS (1ULL << 24)
#define GTK_CSS_CHANGE_PARENT_SIBLING_ID (1ULL << 25)
#define GTK_CSS_CHANGE_PARENT_SIBLING_NAME (1ULL << 26)
#define GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD (1ULL << 27)
#define GTK_CSS_CHANGE_PARENT_SIBLING_LAST_CHILD (1ULL << 28)
#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD (1ULL << 29)
#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD (1ULL << 30)
#define GTK_CSS_CHANGE_PARENT_SIBLING_STATE (1ULL << 31)
#define GTK_CSS_CHANGE_HOVER (1ULL << 8)
#define GTK_CSS_CHANGE_DISABLED (1ULL << 9)
#define GTK_CSS_CHANGE_BACKDROP (1ULL << 10)
#define GTK_CSS_CHANGE_SELECTED (1ULL << 11)
#define GTK_CSS_CHANGE_SIBLING_SHIFT 12
#define GTK_CSS_CHANGE_SIBLING_CLASS (1ULL << 12)
#define GTK_CSS_CHANGE_SIBLING_NAME (1ULL << 13)
#define GTK_CSS_CHANGE_SIBLING_ID (1ULL << 14)
#define GTK_CSS_CHANGE_SIBLING_FIRST_CHILD (1ULL << 15)
#define GTK_CSS_CHANGE_SIBLING_LAST_CHILD (1ULL << 16)
#define GTK_CSS_CHANGE_SIBLING_NTH_CHILD (1ULL << 17)
#define GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD (1ULL << 18)
#define GTK_CSS_CHANGE_SIBLING_STATE (1ULL << 19)
#define GTK_CSS_CHANGE_SIBLING_HOVER (1ULL << 20)
#define GTK_CSS_CHANGE_SIBLING_DISABLED (1ULL << 21)
#define GTK_CSS_CHANGE_SIBLING_BACKDROP (1ULL << 22)
#define GTK_CSS_CHANGE_SIBLING_SELECTED (1ULL << 23)
#define GTK_CSS_CHANGE_PARENT_SHIFT (GTK_CSS_CHANGE_SIBLING_SHIFT + GTK_CSS_CHANGE_SIBLING_SHIFT)
#define GTK_CSS_CHANGE_PARENT_CLASS (1ULL << 24)
#define GTK_CSS_CHANGE_PARENT_NAME (1ULL << 25)
#define GTK_CSS_CHANGE_PARENT_ID (1ULL << 26)
#define GTK_CSS_CHANGE_PARENT_FIRST_CHILD (1ULL << 27)
#define GTK_CSS_CHANGE_PARENT_LAST_CHILD (1ULL << 28)
#define GTK_CSS_CHANGE_PARENT_NTH_CHILD (1ULL << 29)
#define GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD (1ULL << 30)
#define GTK_CSS_CHANGE_PARENT_STATE (1ULL << 31)
#define GTK_CSS_CHANGE_PARENT_HOVER (1ULL << 32)
#define GTK_CSS_CHANGE_PARENT_DISABLED (1ULL << 33)
#define GTK_CSS_CHANGE_PARENT_BACKDROP (1ULL << 34)
#define GTK_CSS_CHANGE_PARENT_SELECTED (1ULL << 35)
#define GTK_CSS_CHANGE_PARENT_SIBLING_SHIFT (GTK_CSS_CHANGE_PARENT_SHIFT + GTK_CSS_CHANGE_SIBLING_SHIFT)
#define GTK_CSS_CHANGE_PARENT_SIBLING_CLASS (1ULL << 36)
#define GTK_CSS_CHANGE_PARENT_SIBLING_ID (1ULL << 37)
#define GTK_CSS_CHANGE_PARENT_SIBLING_NAME (1ULL << 38)
#define GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD (1ULL << 39)
#define GTK_CSS_CHANGE_PARENT_SIBLING_LAST_CHILD (1ULL << 40)
#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD (1ULL << 41)
#define GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD (1ULL << 42)
#define GTK_CSS_CHANGE_PARENT_SIBLING_STATE (1ULL << 43)
#define GTK_CSS_CHANGE_PARENT_SIBLING_HOVER (1ULL << 44)
#define GTK_CSS_CHANGE_PARENT_SIBLING_DISABLED (1ULL << 45)
#define GTK_CSS_CHANGE_PARENT_SIBLING_BACKDROP (1ULL << 46)
#define GTK_CSS_CHANGE_PARENT_SIBLING_SELECTED (1ULL << 47)
/* add more */
#define GTK_CSS_CHANGE_SOURCE (1ULL << 32)
#define GTK_CSS_CHANGE_PARENT_STYLE (1ULL << 33)
#define GTK_CSS_CHANGE_TIMESTAMP (1ULL << 34)
#define GTK_CSS_CHANGE_ANIMATIONS (1ULL << 35)
#define GTK_CSS_CHANGE_SOURCE (1ULL << 48)
#define GTK_CSS_CHANGE_PARENT_STYLE (1ULL << 49)
#define GTK_CSS_CHANGE_TIMESTAMP (1ULL << 50)
#define GTK_CSS_CHANGE_ANIMATIONS (1ULL << 51)
#define GTK_CSS_CHANGE_RESERVED_BIT (1ULL << 62) /* Used internally in gtkcssselector.c */
#define GTK_CSS_CHANGE_RESERVED_BIT (1ULL << 62)
typedef guint64 GtkCssChange;
#define GTK_CSS_CHANGE_POSITION (GTK_CSS_CHANGE_FIRST_CHILD | GTK_CSS_CHANGE_LAST_CHILD | \
GTK_CSS_CHANGE_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD)
#define GTK_CSS_CHANGE_SIBLING_POSITION (GTK_CSS_CHANGE_SIBLING_FIRST_CHILD | GTK_CSS_CHANGE_SIBLING_LAST_CHILD | \
GTK_CSS_CHANGE_SIBLING_NTH_CHILD | GTK_CSS_CHANGE_SIBLING_NTH_LAST_CHILD)
#define GTK_CSS_CHANGE_PARENT_POSITION (GTK_CSS_CHANGE_PARENT_FIRST_CHILD | GTK_CSS_CHANGE_PARENT_LAST_CHILD | \
GTK_CSS_CHANGE_PARENT_NTH_CHILD | GTK_CSS_CHANGE_PARENT_NTH_LAST_CHILD)
#define GTK_CSS_CHANGE_PARENT_SIBLING_POSITION (GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD | GTK_CSS_CHANGE_PARENT_SIBLING_LAST_CHILD | \
GTK_CSS_CHANGE_PARENT_SIBLING_NTH_CHILD | GTK_CSS_CHANGE_PARENT_SIBLING_NTH_LAST_CHILD)
#define GTK_CSS_CHANGE_POSITION (GTK_CSS_CHANGE_FIRST_CHILD | \
GTK_CSS_CHANGE_LAST_CHILD | \
GTK_CSS_CHANGE_NTH_CHILD | \
GTK_CSS_CHANGE_NTH_LAST_CHILD)
#define GTK_CSS_CHANGE_SIBLING_POSITION (GTK_CSS_CHANGE_POSITION << GTK_CSS_CHANGE_SIBLING_SHIFT)
#define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS | \
GTK_CSS_CHANGE_NAME | \
GTK_CSS_CHANGE_ID | \
GTK_CSS_CHANGE_POSITION | \
GTK_CSS_CHANGE_STATE | \
GTK_CSS_CHANGE_DISABLED | \
GTK_CSS_CHANGE_BACKDROP | \
GTK_CSS_CHANGE_SELECTED | \
GTK_CSS_CHANGE_HOVER)
#define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_ANY_SELF << GTK_CSS_CHANGE_SIBLING_SHIFT)
#define GTK_CSS_CHANGE_ANY_PARENT (GTK_CSS_CHANGE_ANY_SELF << GTK_CSS_CHANGE_PARENT_SHIFT)
#define GTK_CSS_CHANGE_ANY_PARENT_SIBLING (GTK_CSS_CHANGE_ANY_SELF << GTK_CSS_CHANGE_PARENT_SIBLING_SHIFT)
#define GTK_CSS_CHANGE_ANY ((1 << 19) - 1)
#define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_ID | GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_STATE)
#define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_SIBLING_CLASS | GTK_CSS_CHANGE_SIBLING_NAME | \
GTK_CSS_CHANGE_SIBLING_ID | \
GTK_CSS_CHANGE_SIBLING_POSITION | GTK_CSS_CHANGE_SIBLING_STATE)
#define GTK_CSS_CHANGE_ANY_PARENT (GTK_CSS_CHANGE_PARENT_CLASS | GTK_CSS_CHANGE_PARENT_SIBLING_CLASS | \
GTK_CSS_CHANGE_PARENT_NAME | GTK_CSS_CHANGE_PARENT_SIBLING_NAME | \
GTK_CSS_CHANGE_PARENT_ID | GTK_CSS_CHANGE_PARENT_SIBLING_ID | \
GTK_CSS_CHANGE_PARENT_POSITION | GTK_CSS_CHANGE_PARENT_SIBLING_POSITION | \
GTK_CSS_CHANGE_PARENT_STATE | GTK_CSS_CHANGE_PARENT_SIBLING_STATE)
#define GTK_CSS_CHANGE_ANY (GTK_CSS_CHANGE_ANY_SELF | \
GTK_CSS_CHANGE_ANY_SIBLING | \
GTK_CSS_CHANGE_ANY_PARENT | \
GTK_CSS_CHANGE_ANY_PARENT_SIBLING | \
GTK_CSS_CHANGE_SOURCE | \
GTK_CSS_CHANGE_PARENT_STYLE | \
GTK_CSS_CHANGE_TIMESTAMP | \
GTK_CSS_CHANGE_ANIMATIONS)
/*
* GtkCssAffects:
@@ -247,29 +280,6 @@ enum { /*< skip >*/
GTK_CSS_PROPERTY_N_PROPERTIES
};
typedef enum /*< skip >*/ {
GTK_CSS_IMAGE_BUILTIN_NONE,
GTK_CSS_IMAGE_BUILTIN_CHECK,
GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT,
GTK_CSS_IMAGE_BUILTIN_OPTION,
GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT,
GTK_CSS_IMAGE_BUILTIN_ARROW_UP,
GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN,
GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT,
GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT_EXPANDED,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT_EXPANDED,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT_EXPANDED,
GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT_EXPANDED,
GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR,
GTK_CSS_IMAGE_BUILTIN_HANDLE,
GTK_CSS_IMAGE_BUILTIN_SPINNER
} GtkCssImageBuiltinType;
typedef enum /*< skip >*/ {
GTK_CSS_AREA_BORDER_BOX,
GTK_CSS_AREA_PADDING_BOX,
-1425
View File
File diff suppressed because it is too large Load Diff
-102
View File
@@ -1,102 +0,0 @@
/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_DND_H__
#define __GTK_DND_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkwidget.h>
#include <gtk/gtkselection.h>
G_BEGIN_DECLS
/* Destination side */
GDK_AVAILABLE_IN_ALL
void gtk_drag_get_data (GtkWidget *widget,
GdkDrop *drop,
GdkAtom target);
GDK_AVAILABLE_IN_ALL
GtkWidget *gtk_drag_get_source_widget (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
void gtk_drag_highlight (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_unhighlight (GtkWidget *widget);
/* Source side */
GDK_AVAILABLE_IN_ALL
GdkDrag *gtk_drag_begin (GtkWidget *widget,
GdkDevice *device,
GdkContentFormats *targets,
GdkDragAction actions,
gint x,
gint y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_cancel (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_widget (GdkDrag *drag,
GtkWidget *widget,
gint hot_x,
gint hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_paintable (GdkDrag *drag,
GdkPaintable *paintable,
int hot_x,
int hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_name (GdkDrag *drag,
const gchar *icon_name,
gint hot_x,
gint hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_gicon (GdkDrag *drag,
GIcon *icon,
gint hot_x,
gint hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_set_icon_default (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
gboolean gtk_drag_check_threshold (GtkWidget *widget,
gint start_x,
gint start_y,
gint current_x,
gint current_y);
G_END_DECLS
#endif /* __GTK_DND_H__ */
-59
View File
@@ -1,59 +0,0 @@
/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
/* GTK - The GIMP Toolkit
* Copyright (C) 2015 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_DND_PRIVATE_H__
#define __GTK_DND_PRIVATE_H__
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkimagedefinitionprivate.h"
#include "gtkselection.h"
#include "gtkwidget.h"
typedef struct _GtkDragDestSite GtkDragDestSite;
struct _GtkDragDestSite
{
GtkDestDefaults flags;
GdkContentFormats *target_list;
GdkDragAction actions;
guint do_proxy : 1;
guint proxy_coords : 1;
guint have_drag : 1;
guint track_motion : 1;
};
G_BEGIN_DECLS
GdkDrag * gtk_drag_begin_internal (GtkWidget *widget,
GdkDevice *device,
GtkImageDefinition *icon,
GdkContentFormats *target_list,
GdkDragAction actions,
int x,
int y);
void gtk_drag_set_icon_definition (GdkDrag *drag,
GtkImageDefinition *def,
gint hot_x,
gint hot_y);
void _gtk_drag_dest_handle_event (GtkWidget *toplevel,
GdkEvent *event);
G_END_DECLS
#endif /* __GTK_DND_PRIVATE_H__ */
+961 -317
View File
File diff suppressed because it is too large Load Diff
+42 -49
View File
@@ -37,65 +37,58 @@
G_BEGIN_DECLS
/**
* GtkDestDefaults:
* @GTK_DEST_DEFAULT_MOTION: If set for a widget, GTK+, during a drag over this
* widget will check if the drag matches this widgets list of possible formats
* and actions.
* GTK+ will then call gdk_drag_status() as appropriate.
* @GTK_DEST_DEFAULT_HIGHLIGHT: If set for a widget, GTK+ will draw a highlight on
* this widget as long as a drag is over this widget and the widget drag format
* and action are acceptable.
* @GTK_DEST_DEFAULT_DROP: If set for a widget, when a drop occurs, GTK+ will
* will check if the drag matches this widgets list of possible formats and
* actions. If so, GTK+ will call gtk_drag_get_data() on behalf of the widget.
* Whether or not the drop is successful, GTK+ will call gdk_drag_finish(). If
* the action was a move, then if the drag was successful, then %TRUE will be
* passed for the @delete parameter to gdk_drag_finish().
* @GTK_DEST_DEFAULT_ALL: If set, specifies that all default actions should
* be taken.
*
* The #GtkDestDefaults enumeration specifies the various
* types of action that will be taken on behalf
* of the user for a drag destination site.
*/
typedef enum {
GTK_DEST_DEFAULT_MOTION = 1 << 0,
GTK_DEST_DEFAULT_HIGHLIGHT = 1 << 1,
GTK_DEST_DEFAULT_DROP = 1 << 2,
GTK_DEST_DEFAULT_ALL = 0x07
} GtkDestDefaults;
typedef struct _GtkDropTarget GtkDropTarget;
#define GTK_TYPE_DROP_TARGET (gtk_drop_target_get_type ())
#define GTK_DROP_TARGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_DROP_TARGET, GtkDropTarget))
#define GTK_DROP_TARGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_DROP_TARGET, GtkDropTargetClass))
#define GTK_IS_DROP_TARGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_DROP_TARGET))
#define GTK_IS_DROP_TARGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_DROP_TARGET))
#define GTK_DROP_TARGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_DROP_TARGET, GtkDropTargetClass))
typedef struct _GtkDropTargetClass GtkDropTargetClass;
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_set (GtkWidget *widget,
GtkDestDefaults flags,
GdkContentFormats *targets,
GdkDragAction actions);
GType gtk_drop_target_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_unset (GtkWidget *widget);
GtkDropTarget *gtk_drop_target_new (GdkContentFormats *formats,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
const char * gtk_drag_dest_find_target (GtkWidget *widget,
GdkDrop *drop,
GdkContentFormats *target_list);
void gtk_drop_target_set_formats (GtkDropTarget *dest,
GdkContentFormats *formats);
GDK_AVAILABLE_IN_ALL
GdkContentFormats* gtk_drag_dest_get_target_list (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_set_target_list (GtkWidget *widget,
GdkContentFormats *target_list);
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_add_text_targets (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_add_image_targets (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_add_uri_targets (GtkWidget *widget);
GdkContentFormats *gtk_drop_target_get_formats (GtkDropTarget *dest);
GDK_AVAILABLE_IN_ALL
void gtk_drag_dest_set_track_motion (GtkWidget *widget,
gboolean track_motion);
void gtk_drop_target_set_actions (GtkDropTarget *dest,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
gboolean gtk_drag_dest_get_track_motion (GtkWidget *widget);
GdkDragAction gtk_drop_target_get_actions (GtkDropTarget *dest);
GDK_AVAILABLE_IN_ALL
GdkDrop *gtk_drop_target_get_drop (GtkDropTarget *dest);
GDK_AVAILABLE_IN_ALL
const char *gtk_drop_target_find_mimetype (GtkDropTarget *dest);
GDK_AVAILABLE_IN_ALL
void gtk_drop_target_read_selection (GtkDropTarget *dest,
GdkAtom target,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
GtkSelectionData *gtk_drop_target_read_selection_finish
(GtkDropTarget *dest,
GAsyncResult *result,
GError **error);
GDK_AVAILABLE_IN_ALL
void gtk_drop_target_deny_drop (GtkDropTarget *dest,
GdkDrop *drop);
G_END_DECLS
+32
View File
@@ -0,0 +1,32 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2020 Matthias Clasen
*
* 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_DRAG_DEST_PRIVATE_H__
#define __GTK_DRAG_DEST_PRIVATE_H__
#include "gtkdragdest.h"
G_BEGIN_DECLS
void gtk_drag_dest_handle_event (GtkWidget *toplevel,
GdkEvent *event);
G_END_DECLS
#endif
+74
View File
@@ -23,8 +23,25 @@
#include "gtkintl.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtknativeprivate.h"
#include "gtkpicture.h"
/**
* SECTION:gtkdragicon
* @Short_description: A toplevel to use as drag icon
* @Title: GtkDragIcon
*
* GtkDragIcon is a #GtkNative implementation with the sole purpose
* to serve as a drag icon during DND operations. A drag icon moves
* with the pointer during a drag operation and is destroyed when
* the drag ends.
*
* To set up a drag icon and associate it with an ongoing drag operation,
* use gtk_drag_icon_set_from_paintable(). It is also possible to create
* a GtkDragIcon with gtk_drag_icon_new_for_drag(() and populate it
* with widgets yourself.
*/
struct _GtkDragIcon
{
GtkWidget parent_instance;
@@ -374,6 +391,63 @@ gtk_drag_icon_new (void)
return g_object_new (GTK_TYPE_DRAG_ICON, NULL);
}
/**
* gtk_drag_icon_new_for_drag:
* @drag: a #GtkDrag
*
* Creates a #GtkDragIcon and associates it with the drag operation.
*
* Returns: the new #GtkDragIcon
*/
GtkWidget *
gtk_drag_icon_new_for_drag (GdkDrag *drag)
{
GtkWidget *icon;
g_return_val_if_fail (GDK_IS_DRAG (drag), NULL);
icon = g_object_new (GTK_TYPE_DRAG_ICON, NULL);
gtk_drag_icon_set_surface (GTK_DRAG_ICON (icon), gdk_drag_get_drag_surface (drag));
return icon;
}
/**
* gtk_drag_icon_set_from_paintable:
* @drag: a #GdkDrag
* @paintable: a #GdkPaintable to display
* @hot_x: X coordinate of the hotspot
* @hot_y: Y coordinate of the hotspot
*
* Creates a #GtkDragIcon that shows @paintable, and associates
* it with the drag operation. The hotspot position on the paintable
* is aligned with the hotspot of the cursor.
*/
void
gtk_drag_icon_set_from_paintable (GdkDrag *drag,
GdkPaintable *paintable,
int hot_x,
int hot_y)
{
GtkWidget *icon;
GtkWidget *picture;
gdk_drag_set_hotspot (drag, hot_x, hot_y);
icon = gtk_drag_icon_new_for_drag (drag);
picture = gtk_picture_new_for_paintable (paintable);
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
gtk_container_add (GTK_CONTAINER (icon), picture);
g_object_set_data_full (G_OBJECT (drag),
"icon",
g_object_ref_sink (icon),
(GDestroyNotify)gtk_widget_destroy);
gtk_widget_show (icon);
}
void
gtk_drag_icon_set_surface (GtkDragIcon *icon,
GdkSurface *surface)
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright © 2020 Matthias Clasen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_DRAG_ICON_H__
#define __GTK_DRAG_ICON_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gio/gio.h>
#include <gtk/gtkwidget.h>
#include <gtk/gtkcontainer.h>
G_BEGIN_DECLS
#define GTK_TYPE_DRAG_ICON (gtk_drag_icon_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkDragIcon, gtk_drag_icon, GTK, DRAG_ICON, GtkContainer)
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_drag_icon_new_for_drag (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
void gtk_drag_icon_set_from_paintable (GdkDrag *drag,
GdkPaintable *paintable,
int hot_x,
int hot_y);
G_END_DECLS
#endif /* __GTK_DRAG_ICON_H__ */
+1 -5
View File
@@ -26,14 +26,10 @@
#define __GTK_DRAG_ICON_PRIVATE_H__
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <gtk/gtkdragicon.h>
G_BEGIN_DECLS
#define GTK_TYPE_DRAG_ICON (gtk_drag_icon_get_type ())
G_DECLARE_FINAL_TYPE (GtkDragIcon, gtk_drag_icon, GTK, DRAG_ICON, GtkContainer)
GtkWidget * gtk_drag_icon_new (void);
void gtk_drag_icon_set_surface (GtkDragIcon *icon,
+599 -287
View File
@@ -26,365 +26,677 @@
#include "gtkdragsource.h"
#include "gtkdnd.h"
#include "gtkdndprivate.h"
#include "gtkgesturedrag.h"
#include "gtkgesturesingleprivate.h"
#include "gtkimagedefinitionprivate.h"
#include "gtknative.h"
#include "gtkwidgetprivate.h"
#include "gtkintl.h"
#include "gtkstylecontext.h"
#include "gtkimageprivate.h"
#include "gtkdragiconprivate.h"
#include "gtkprivate.h"
#include "gtkmarshalers.h"
#include "gtkicontheme.h"
#include "gtkpicture.h"
#include "gtksettingsprivate.h"
#include "gtkgesturesingle.h"
/**
* SECTION:gtkdragsource
* @Short_description: Event controller to initiate DND operations
* @Title: GtkDragSource
*
* GtkDragSource is an auxiliary object that is used to initiate
* Drag-And-Drop operations. It can be set up with the necessary
* ingredients for a DND operation ahead of time. This includes
* the source for the data that is being transferred, in the form
* of a #GdkContentProvider, the desired action, and the icon to
* use during the drag operation. After setting it up, the drag
* source must be added to a widget as an event controller, using
* gtk_widget_add_controller().
*
* Setting up the content provider and icon ahead of time only
* makes sense when the data does not change. More commonly, you
* will want to set them up just in time. To do so, #GtkDragSource
* has #GtkDragSource::prepare and #GtkDragSource::drag-begin signals.
* The ::prepare signal is emitted before a drag is started, and
* can be used to set the content provider and actions that the
* drag should be started with. The ::drag-begin signal is emitted
* after the #GdkDrag object has been created, and can be used
* to set up the drag icon.
*
* During the DND operation, GtkDragSource emits signals that
* can be used to obtain updates about the status of the operation,
* but it is not normally necessary to connect to any signals,
* except for one case: when the supported actions include
* %GDK_DRAG_MOVE, you need to listen for the
* #GtkDragSource::drag-end signal and delete the
* data after it has been transferred.
*/
typedef struct _GtkDragSourceSite GtkDragSourceSite;
struct _GtkDragSourceSite
struct _GtkDragSource
{
GdkModifierType start_button_mask;
GdkContentFormats *target_list; /* Targets for drag data */
GdkDragAction actions; /* Possible actions */
GtkGestureSingle parent_instance;
GtkImageDefinition *image_def;
GtkGesture *drag_gesture;
GdkContentProvider *content;
GdkDragAction actions;
GdkPaintable *paintable;
int hot_x;
int hot_y;
gdouble start_x;
gdouble start_y;
GdkDrag *drag;
};
static void
gtk_drag_source_gesture_begin (GtkGesture *gesture,
GdkEventSequence *sequence,
gpointer data)
struct _GtkDragSourceClass
{
GtkDragSourceSite *site = data;
guint button;
GtkGestureSingleClass parent_class;
if (gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture)))
button = 1;
else
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
GdkContentProvider *(* prepare) (GtkDragSource *source,
double x,
double y);
};
g_assert (button >= 1);
enum {
PROP_CONTENT = 1,
PROP_ACTIONS,
NUM_PROPERTIES
};
if (!site->start_button_mask ||
!(site->start_button_mask & (GDK_BUTTON1_MASK << (button - 1))))
gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
static GParamSpec *properties[NUM_PROPERTIES];
enum {
PREPARE,
DRAG_BEGIN,
DRAG_END,
DRAG_CANCEL,
NUM_SIGNALS
};
static guint signals[NUM_SIGNALS];
static void gtk_drag_source_dnd_finished_cb (GdkDrag *drag,
GtkDragSource *source);
static void gtk_drag_source_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkDragSource *source);
static GdkContentProvider *gtk_drag_source_prepare (GtkDragSource *source,
double x,
double y);
static void gtk_drag_source_drag_begin (GtkDragSource *source);
G_DEFINE_TYPE (GtkDragSource, gtk_drag_source, GTK_TYPE_GESTURE_SINGLE);
static void
gtk_drag_source_init (GtkDragSource *source)
{
source->actions = GDK_ACTION_COPY;
}
static void
gtk_drag_source_gesture_update (GtkGesture *gesture,
GdkEventSequence *sequence,
gpointer data)
gtk_drag_source_finalize (GObject *object)
{
gdouble start_x, start_y, offset_x, offset_y;
GtkDragSourceSite *site = data;
GtkDragSource *source = GTK_DRAG_SOURCE (object);
g_clear_object (&source->content);
g_clear_object (&source->paintable);
G_OBJECT_CLASS (gtk_drag_source_parent_class)->finalize (object);
}
static void
gtk_drag_source_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkDragSource *source = GTK_DRAG_SOURCE (object);
switch (prop_id)
{
case PROP_CONTENT:
gtk_drag_source_set_content (source, g_value_get_object (value));
break;
case PROP_ACTIONS:
gtk_drag_source_set_actions (source, g_value_get_flags (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gtk_drag_source_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkDragSource *source = GTK_DRAG_SOURCE (object);
switch (prop_id)
{
case PROP_CONTENT:
g_value_set_object (value, gtk_drag_source_get_content (source));
break;
case PROP_ACTIONS:
g_value_set_flags (value, gtk_drag_source_get_actions (source));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static gboolean
gtk_drag_source_filter_event (GtkEventController *controller,
const GdkEvent *event)
{
/* Let touchpad swipe events go through, only if they match n-points */
if (gdk_event_get_event_type (event) == GDK_TOUCHPAD_SWIPE)
{
guint n_points;
guint n_fingers;
g_object_get (G_OBJECT (controller), "n-points", &n_points, NULL);
gdk_event_get_touchpad_gesture_n_fingers (event, &n_fingers);
if (n_fingers == n_points)
return FALSE;
else
return TRUE;
}
return GTK_EVENT_CONTROLLER_CLASS (gtk_drag_source_parent_class)->filter_event (controller, event);
}
static void
gtk_drag_source_begin (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkDragSource *source = GTK_DRAG_SOURCE (gesture);
GdkEventSequence *current;
current = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
gtk_gesture_get_point (gesture, current, &source->start_x, &source->start_y);
}
static void
gtk_drag_source_update (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkDragSource *source = GTK_DRAG_SOURCE (gesture);
GtkWidget *widget;
double x, y;
if (!gtk_gesture_is_recognized (gesture))
return;
gtk_gesture_get_point (gesture, sequence, &x, &y);
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
if (gtk_gesture_is_recognized (site->drag_gesture))
if (gtk_drag_check_threshold (widget, source->start_x, source->start_y, x, y))
{
gtk_gesture_drag_get_start_point (GTK_GESTURE_DRAG (site->drag_gesture),
&start_x, &start_y);
gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (site->drag_gesture),
&offset_x, &offset_y);
if (gtk_drag_check_threshold (widget, start_x, start_y,
start_x + offset_x, start_y + offset_y))
{
GdkDevice *device = gtk_gesture_get_device (site->drag_gesture);
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (site->drag_gesture));
gtk_drag_begin_internal (widget,
device,
site->image_def, site->target_list,
site->actions,
start_x, start_y);
}
gtk_drag_source_drag_begin (source);
}
}
static void
gtk_drag_source_site_destroy (gpointer data)
gtk_drag_source_class_init (GtkDragSourceClass *class)
{
GtkDragSourceSite *site = data;
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (class);
GtkGestureClass *gesture_class = GTK_GESTURE_CLASS (class);
if (site->target_list)
gdk_content_formats_unref (site->target_list);
object_class->finalize = gtk_drag_source_finalize;
object_class->set_property = gtk_drag_source_set_property;
object_class->get_property = gtk_drag_source_get_property;
gtk_image_definition_unref (site->image_def);
/* This gets called only during widget finalization.
* And widget finalization takes care of gestures. */
g_slice_free (GtkDragSourceSite, site);
controller_class->filter_event = gtk_drag_source_filter_event;
gesture_class->begin = gtk_drag_source_begin;
gesture_class->update = gtk_drag_source_update;
gesture_class->end = NULL;
class->prepare = gtk_drag_source_prepare;
/**
* GtkDragSource:content:
*
* The data that is offered by drag operations from this source,
* in the form of a #GdkContentProvider.
*/
properties[PROP_CONTENT] =
g_param_spec_object ("content",
P_("Content"),
P_("The content provider for the dragged data"),
GDK_TYPE_CONTENT_PROVIDER,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkDragSource:actions:
*
* The actions that are supported by drag operations from the source.
*
* Note that you must handle the #GtkDragSource::drag-end signal
* if the actions include %GDK_ACTION_MOVE.
*/
properties[PROP_ACTIONS] =
g_param_spec_flags ("actions",
P_("Actions"),
P_("Supported actions"),
GDK_TYPE_DRAG_ACTION, GDK_ACTION_COPY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
/**
* GtkDragSource::prepare:
* @source: the #GtkDragSource
* @x: the X coordinate of the drag starting point
* @y: the Y coordinate fo the drag starting point
*
* The ::prepare signal is emitted when a drag is about to be initiated.
* It returns the * #GdkContentProvider to use for the drag that is about
* to start. The default handler for this signal returns the value of
* the #GtkDragSource::content property, so if you set up that property
* ahead of time, you don't need to connect to this signal.
*
* Returns: (transfer full) (nullable): a #GdkContentProvider, or %NULL
*/
signals[PREPARE] =
g_signal_new (I_("prepare"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkDragSourceClass, prepare),
g_signal_accumulator_first_wins, NULL,
NULL,
GDK_TYPE_CONTENT_PROVIDER, 2,
G_TYPE_DOUBLE, G_TYPE_DOUBLE);
/**
* GtkDragSource::drag-begin:
* @source: the #GtkDragSource
* @drag: the #GtkDrag object
*
* The ::drag-begin signal is emitted on the drag source when a drag
* is started. It can be used to e.g. set a custom drag icon with
* gtk_drag_source_set_icon().
*/
signals[DRAG_BEGIN] =
g_signal_new (I_("drag-begin"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GDK_TYPE_DRAG);
/**
* GtkDragSource::drag-end:
* @source: the #GtkDragSource
* @drag: the #GtkDrag object
* @delete_data: %TRUE if the drag was performing %GDK_ACTION_MOVE,
* and the data should be deleted
*
* The ::drag-end signal is emitted on the drag source when a drag is
* finished. A typical reason to connect to this signal is to undo
* things done in #GtkDragSource::prepare or #GtkDragSource::drag-begin.
*/
signals[DRAG_END] =
g_signal_new (I_("drag-end"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 2,
GDK_TYPE_DRAG,
G_TYPE_BOOLEAN);
/**
* GtkDragSource::drag-cancel:
* @source: the #GtkDragSource
* @drag: the #GtkDrag object
* @reason: information on why the drag failed
*
* The ::drag-cancel signal is emitted on the drag source when a drag has
* failed. The signal handler may handle a failed drag operation based on
* the type of error. It should return %TRUE if the failure has been handled
* and the default "drag operation failed" animation should not be shown.
*
* Returns: %TRUE if the failed drag operation has been already handled
*/
signals[DRAG_CANCEL] =
g_signal_new (I_("drag-cancel"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
0,
_gtk_boolean_handled_accumulator, NULL,
_gtk_marshal_BOOLEAN__OBJECT_ENUM,
G_TYPE_BOOLEAN, 2,
GDK_TYPE_DRAG,
GDK_TYPE_DRAG_CANCEL_REASON);
}
/**
* gtk_drag_source_set: (method)
* @widget: a #GtkWidget
* @start_button_mask: the bitmask of buttons that can start the drag
* @targets: (allow-none): the targets that the drag will support,
* may be %NULL
* @actions: the bitmask of possible actions for a drag from this widget
*
* Sets up a widget so that GTK+ will start a drag operation when the user
* clicks and drags on the widget. The widget must have a window.
*/
void
gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
GdkContentFormats *targets,
GdkDragAction actions)
static GdkContentProvider *
gtk_drag_source_prepare (GtkDragSource *source,
double x,
double y)
{
GtkDragSourceSite *site;
if (source->actions == 0)
return NULL;
g_return_if_fail (GTK_IS_WIDGET (widget));
if (source->content == NULL)
return NULL;
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
return g_object_ref (source->content);
}
if (site)
static void
drag_end (GtkDragSource *source,
gboolean success)
{
gboolean delete_data;
g_signal_handlers_disconnect_by_func (source->drag, gtk_drag_source_dnd_finished_cb, source);
g_signal_handlers_disconnect_by_func (source->drag, gtk_drag_source_cancel_cb, source);
delete_data = success && gdk_drag_get_selected_action (source->drag) == GDK_ACTION_MOVE;
g_signal_emit (source, signals[DRAG_END], 0, source->drag, delete_data);
gdk_drag_drop_done (source->drag, success);
g_clear_object (&source->drag);
}
static void
gtk_drag_source_dnd_finished_cb (GdkDrag *drag,
GtkDragSource *source)
{
drag_end (source, TRUE);
}
static void
gtk_drag_source_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkDragSource *source)
{
gboolean success = FALSE;
g_signal_emit (source, signals[DRAG_CANCEL], 0, source->drag, reason, &success);
drag_end (source, FALSE);
}
static void
gtk_drag_source_drag_begin (GtkDragSource *source)
{
GtkWidget *widget;
GdkDevice *device;
int x, y;
GtkNative *native;
GdkSurface *surface;
double px, py;
int dx, dy;
GdkContentProvider *content = NULL;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
device = gtk_gesture_get_device (GTK_GESTURE (source));
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
device = gdk_device_get_associated_device (device);
native = gtk_widget_get_native (widget);
surface = gtk_native_get_surface (native);
gtk_widget_translate_coordinates (widget, GTK_WIDGET (native), source->start_x, source->start_y, &x, &y);
gdk_surface_get_device_position (surface, device, &px, &py, NULL);
dx = round (px) - x;
dy = round (py) - y;
g_signal_emit (source, signals[PREPARE], 0, source->start_x, source->start_y, &content);
if (!content)
return;
source->drag = gdk_drag_begin (surface, device, content, source->actions, dx, dy);
g_object_unref (content);
if (source->drag == NULL)
return;
gtk_widget_reset_controllers (widget);
g_signal_emit (source, signals[DRAG_BEGIN], 0, source->drag);
if (!source->paintable)
{
if (site->target_list)
gdk_content_formats_unref (site->target_list);
}
else
{
site = g_slice_new0 (GtkDragSourceSite);
site->image_def = gtk_image_definition_new_empty ();
site->drag_gesture = gtk_gesture_drag_new ();
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (site->drag_gesture),
GTK_PHASE_CAPTURE);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (site->drag_gesture), 0);
g_signal_connect (site->drag_gesture, "begin",
G_CALLBACK (gtk_drag_source_gesture_begin),
site);
g_signal_connect (site->drag_gesture, "update",
G_CALLBACK (gtk_drag_source_gesture_update),
site);
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (site->drag_gesture));
g_object_set_data_full (G_OBJECT (widget),
I_("gtk-site-data"),
site, gtk_drag_source_site_destroy);
GtkIconTheme *theme;
theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
source->paintable = gtk_icon_theme_load_icon (theme, "text-x-generic", 32, 0, NULL);
source->hot_x = 0;
source->hot_y = 0;
}
site->start_button_mask = start_button_mask;
gtk_drag_icon_set_from_paintable (source->drag, source->paintable, source->hot_x, source->hot_y);
if (targets)
site->target_list = gdk_content_formats_ref (targets);
else
site->target_list = NULL;
site->actions = actions;
g_signal_connect (source->drag, "dnd-finished",
G_CALLBACK (gtk_drag_source_dnd_finished_cb), source);
g_signal_connect (source->drag, "cancel",
G_CALLBACK (gtk_drag_source_cancel_cb), source);
}
/**
* gtk_drag_source_unset: (method)
* @widget: a #GtkWidget
* gtk_drag_source_new:
*
* Undoes the effects of gtk_drag_source_set().
* Creates a new #GtkDragSource object.
*
* Returns: the new #GtkDragSource
*/
void
gtk_drag_source_unset (GtkWidget *widget)
GtkDragSource *
gtk_drag_source_new (void)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_object_set_data (G_OBJECT (widget), I_("gtk-site-data"), NULL);
return g_object_new (GTK_TYPE_DRAG_SOURCE, NULL);
}
/**
* gtk_drag_source_get_target_list: (method)
* @widget: a #GtkWidget
* gtk_drag_source_get_content:
* @source: a #GtkDragSource
*
* Gets the list of targets this widget can provide for
* drag-and-drop.
* Gets the current content provider of a #GtkDragSource.
*
* Returns: (nullable) (transfer none): the #GdkContentFormats, or %NULL if none
* Returns: (transfer none): the #GtkContentProvider of @source
*/
GdkContentFormats *
gtk_drag_source_get_target_list (GtkWidget *widget)
GdkContentProvider *
gtk_drag_source_get_content (GtkDragSource *source)
{
GtkDragSourceSite *site;
g_return_val_if_fail (GTK_IS_DRAG_SOURCE (source), NULL);
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
return site ? site->target_list : NULL;
return source->content;
}
/**
* gtk_drag_source_set_target_list: (method)
* @widget: a #GtkWidget thats a drag source
* @target_list: (allow-none): list of draggable targets, or %NULL for none
* gtk_drag_source_set_content:
* @source: a #GtkDragSource
* @content: (nullable): a #GtkContentProvider, or %NULL
*
* Changes the target types that this widget offers for drag-and-drop.
* The widget must first be made into a drag source with
* gtk_drag_source_set().
* Sets a content provider on a #GtkDragSource.
*
* When the data is requested in the cause of a
* DND operation, it will be obtained from the
* content provider.
*
* This function can be called before a drag is started,
* or in a handler for the #GtkDragSource::prepare signal.
*
* You may consider setting the content provider back to
* %NULL in a #GTkDragSource::drag-end signal handler.
*/
void
gtk_drag_source_set_target_list (GtkWidget *widget,
GdkContentFormats *target_list)
gtk_drag_source_set_content (GtkDragSource *source,
GdkContentProvider *content)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_DRAG_SOURCE (source));
g_return_if_fail (GTK_IS_WIDGET (widget));
if (!g_set_object (&source->content, content))
return;
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
if (site == NULL)
g_object_notify_by_pspec (G_OBJECT (source), properties[PROP_CONTENT]);
}
/**
* gtk_drag_source_get_actions:
* @source: a #GtkDragSource
*
* Gets the actions that are currently set on the #GtkDragSource.
*
* Returns: the actions set on @source
*/
GdkDragAction
gtk_drag_source_get_actions (GtkDragSource *source)
{
g_return_val_if_fail (GTK_IS_DRAG_SOURCE (source), 0);
return source->actions;
}
/**
* gtk_drag_source_set_actions:
* @source: a #GtkDragSource
* @actions: the actions to offer
*
* Sets the actions on the #GtkDragSource.
*
* During a DND operation, the actions are offered
* to potential drop targets. If @actions include
* %GDK_ACTION_MOVE, you need to listen to the
* #GtkDraGSource::drag-end signal and handle
* @delete_data being %TRUE.
*
* This function can be called before a drag is started,
* or in a handler for the #GtkDragSource::prepare signal.
*/
void
gtk_drag_source_set_actions (GtkDragSource *source,
GdkDragAction actions)
{
g_return_if_fail (GTK_IS_DRAG_SOURCE (source));
if (source->actions == actions)
return;
source->actions = actions;
g_object_notify_by_pspec (G_OBJECT (source), properties[PROP_ACTIONS]);
}
/**
* gtk_drag_source_set_icon:
* @source: a #GtkDragSource
* @paintable: (nullable): the #GtkPaintable to use as icon, or %NULL
* @hot_x: the hotspot X coordinate on the icon
* @hot_y: the hotspot Y coordinate on the icon
*
* Sets a paintable to use as icon during DND operations.
*
* The hotspot coordinates determine the point on the icon
* that gets aligned with the hotspot of the cursor.
*
* If @paintable is %NULL, a default icon is used.
*
* This function can be called before a drag is started, or in
* a #GtkDragSource::prepare or #GtkDragSource::drag-begin signal handler.
*/
void
gtk_drag_source_set_icon (GtkDragSource *source,
GdkPaintable *paintable,
int hot_x,
int hot_y)
{
g_return_if_fail (GTK_IS_DRAG_SOURCE (source));
g_set_object (&source->paintable, paintable);
source->hot_x = hot_x;
source->hot_y = hot_y;
}
/**
* gtk_drag_source_get_drag:
* @source: a #GtkDragSource
*
* Returns the underlying #GtkDrag object for an ongoing drag.
*
* Returns: (nullable) (transfer none): the #GdkDrag of the current drag operation, or %NULL
*/
GdkDrag *
gtk_drag_source_get_drag (GtkDragSource *source)
{
g_return_val_if_fail (GTK_IS_DRAG_SOURCE (source), NULL);
return source->drag;
}
/**
* gtk_drag_source_drag_cancel:
* @source: a #GtkDragSource
*
* Cancels a currently ongoing drag operation.
*/
void
gtk_drag_source_drag_cancel (GtkDragSource *source)
{
g_return_if_fail (GTK_IS_DRAG_SOURCE (source));
if (source->drag)
{
g_warning ("gtk_drag_source_set_target_list() requires the widget "
"to already be a drag source.");
return;
gboolean success = FALSE;
g_signal_emit (source, signals[DRAG_CANCEL], 0, source->drag, GDK_DRAG_CANCEL_ERROR, &success);
drag_end (source, FALSE);
}
if (target_list)
gdk_content_formats_ref (target_list);
if (site->target_list)
gdk_content_formats_unref (site->target_list);
site->target_list = target_list;
}
/**
* gtk_drag_source_add_text_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the text targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_content_formats_add_text_targets() and
* gtk_drag_source_set_target_list().
*/
void
gtk_drag_source_add_text_targets (GtkWidget *widget)
{
GdkContentFormats *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gdk_content_formats_ref (target_list);
else
target_list = gdk_content_formats_new (NULL, 0);
target_list = gtk_content_formats_add_text_targets (target_list);
gtk_drag_source_set_target_list (widget, target_list);
gdk_content_formats_unref (target_list);
}
/**
* gtk_drag_source_add_image_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the writable image targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_target_list_add_image_targets() and
* gtk_drag_source_set_target_list().
*/
void
gtk_drag_source_add_image_targets (GtkWidget *widget)
{
GdkContentFormats *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gdk_content_formats_ref (target_list);
else
target_list = gdk_content_formats_new (NULL, 0);
target_list = gtk_content_formats_add_image_targets (target_list, TRUE);
gtk_drag_source_set_target_list (widget, target_list);
gdk_content_formats_unref (target_list);
}
/**
* gtk_drag_source_add_uri_targets: (method)
* @widget: a #GtkWidget thats is a drag source
*
* Add the URI targets supported by #GtkSelectionData to
* the target list of the drag source. The targets
* are added with @info = 0. If you need another value,
* use gtk_content_formats_add_uri_targets() and
* gtk_drag_source_set_target_list().
*/
void
gtk_drag_source_add_uri_targets (GtkWidget *widget)
{
GdkContentFormats *target_list;
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gdk_content_formats_ref (target_list);
else
target_list = gdk_content_formats_new (NULL, 0);
target_list = gtk_content_formats_add_uri_targets (target_list);
gtk_drag_source_set_target_list (widget, target_list);
gdk_content_formats_unref (target_list);
}
/**
* gtk_drag_source_set_icon_name: (method)
* gtk_drag_check_threshold: (method)
* @widget: a #GtkWidget
* @icon_name: name of icon to use
*
* Sets the icon that will be used for drags from a particular source
* to a themed icon. See the docs for #GtkIconTheme for more details.
*/
void
gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon_name != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
gtk_image_definition_unref (site->image_def);
site->image_def = gtk_image_definition_new_icon_name (icon_name);
}
/**
* gtk_drag_source_set_icon_gicon: (method)
* @widget: a #GtkWidget
* @icon: A #GIcon
* @start_x: X coordinate of start of drag
* @start_y: Y coordinate of start of drag
* @current_x: current X coordinate
* @current_y: current Y coordinate
*
* Sets the icon that will be used for drags from a particular source
* to @icon. See the docs for #GtkIconTheme for more details.
*/
void
gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon)
{
GtkDragSourceSite *site;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (icon != NULL);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
gtk_image_definition_unref (site->image_def);
site->image_def = gtk_image_definition_new_gicon (icon);
}
/**
* gtk_drag_source_set_icon_paintable: (method)
* @widget: a #GtkWidget
* @paintable: A #GdkPaintable
* Checks to see if a mouse drag starting at (@start_x, @start_y) and ending
* at (@current_x, @current_y) has passed the GTK drag threshold, and thus
* should trigger the beginning of a drag-and-drop operation.
*
* Sets the icon that will be used for drags from a particular source
* to @paintable.
* Returns: %TRUE if the drag threshold has been passed.
*/
void
gtk_drag_source_set_icon_paintable (GtkWidget *widget,
GdkPaintable *paintable)
gboolean
gtk_drag_check_threshold (GtkWidget *widget,
int start_x,
int start_y,
int current_x,
int current_y)
{
GtkDragSourceSite *site;
gint drag_threshold;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_PAINTABLE (paintable));
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
site = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
g_return_if_fail (site != NULL);
drag_threshold = gtk_settings_get_dnd_drag_threshold (gtk_widget_get_settings (widget));
gtk_image_definition_unref (site->image_def);
site->image_def = gtk_image_definition_new_paintable (paintable);
return (ABS (current_x - start_x) > drag_threshold ||
ABS (current_y - start_y) > drag_threshold);
}
+37 -22
View File
@@ -37,36 +37,51 @@
G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set (GtkWidget *widget,
GdkModifierType start_button_mask,
GdkContentFormats *targets,
GdkDragAction actions);
#define GTK_TYPE_DRAG_SOURCE (gtk_drag_source_get_type ())
#define GTK_DRAG_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_DRAG_SOURCE, GtkDragSource))
#define GTK_DRAG_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_DRAG_SOURCE, GtkDragSourceClass))
#define GTK_IS_DRAG_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_DRAG_SOURCE))
#define GTK_IS_DRAG_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_DRAG_SOURCE))
#define GTK_DRAG_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_DRAG_SOURCE, GtkDragSourceClass))
typedef struct _GtkDragSource GtkDragSource;
typedef struct _GtkDragSourceClass GtkDragSourceClass;
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_unset (GtkWidget *widget);
GType gtk_drag_source_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GdkContentFormats * gtk_drag_source_get_target_list (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_target_list (GtkWidget *widget,
GdkContentFormats *target_list);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_add_text_targets (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_add_image_targets (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_add_uri_targets (GtkWidget *widget);
GtkDragSource *gtk_drag_source_new (void);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_name (GtkWidget *widget,
const gchar *icon_name);
void gtk_drag_source_set_content (GtkDragSource *source,
GdkContentProvider *content);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_gicon (GtkWidget *widget,
GIcon *icon);
GdkContentProvider *gtk_drag_source_get_content (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon_paintable (GtkWidget *widget,
GdkPaintable *paintable);
void gtk_drag_source_set_actions (GtkDragSource *source,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
GdkDragAction gtk_drag_source_get_actions (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_set_icon (GtkDragSource *source,
GdkPaintable *paintable,
int hot_x,
int hot_y);
GDK_AVAILABLE_IN_ALL
void gtk_drag_source_drag_cancel (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
GdkDrag * gtk_drag_source_get_drag (GtkDragSource *source);
GDK_AVAILABLE_IN_ALL
gboolean gtk_drag_check_threshold (GtkWidget *widget,
int start_x,
int start_y,
int current_x,
int current_y);
G_END_DECLS
+2 -2
View File
@@ -411,9 +411,9 @@ gtk_drawing_area_get_content_height (GtkDrawingArea *self)
/**
* gtk_drawing_area_set_draw_func:
* @self: a #GtkDrawingArea
* @draw_func: (closure user_data) (allow-none): callback that lets you draw
* @draw_func: (allow-none): callback that lets you draw
* the drawing area's contents
* @user_data: user data passed to @draw_func
* @user_data: (closure): user data passed to @draw_func
* @destroy: destroy notifier for @user_data
*
* Setting a draw function is the main thing you want to do when using a drawing
+25 -22
View File
@@ -38,8 +38,6 @@
#include "gtkcelllayout.h"
#include "gtkcssnodeprivate.h"
#include "gtkdebug.h"
#include "gtkdnd.h"
#include "gtkdndprivate.h"
#include "gtkeditable.h"
#include "gtkemojichooser.h"
#include "gtkemojicompletion.h"
@@ -70,6 +68,9 @@
#include "gtkwindow.h"
#include "gtknative.h"
#include "gtkgestureclick.h"
#include "gtkdragsource.h"
#include "gtkdragicon.h"
#include "gtkwidgetpaintable.h"
#include "a11y/gtkentryaccessible.h"
@@ -172,7 +173,7 @@ struct _EntryIconInfo
guint in_drag : 1;
GdkDragAction actions;
GdkContentFormats *target_list;
GdkContentProvider *content;
};
enum {
@@ -1320,8 +1321,7 @@ gtk_entry_finalize (GObject *object)
if (icon_info == NULL)
continue;
if (icon_info->target_list != NULL)
gdk_content_formats_unref (icon_info->target_list);
g_clear_object (&icon_info->content);
gtk_widget_unparent (icon_info->widget);
@@ -1462,17 +1462,25 @@ icon_drag_update_cb (GtkGestureDrag *gesture,
pos = get_icon_position_from_controller (entry, GTK_EVENT_CONTROLLER (gesture));
icon_info = priv->icons[pos];
if (icon_info->target_list != NULL &&
gtk_drag_check_threshold (icon_info->widget,
start_x, start_y,
x, y))
if (icon_info->content != NULL &&
gtk_drag_check_threshold (icon_info->widget, start_x, start_y, x, y))
{
GdkPaintable *paintable;
GdkSurface *surface;
GdkDevice *device;
GdkDrag *drag;
icon_info->in_drag = TRUE;
gtk_drag_begin (GTK_WIDGET (entry),
gtk_gesture_get_device (GTK_GESTURE (gesture)),
icon_info->target_list,
icon_info->actions,
start_x, start_y);
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (entry)));
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
drag = gdk_drag_begin (surface, device, icon_info->content, icon_info->actions, start_x, start_y);
paintable = gtk_widget_paintable_new (icon_info->widget);
gtk_drag_icon_set_from_paintable (drag, paintable, -2, -2);
g_object_unref (paintable);
g_object_unref (drag);
}
}
@@ -2722,7 +2730,7 @@ gtk_entry_get_icon_at_pos (GtkEntry *entry,
* gtk_entry_set_icon_drag_source:
* @entry: a #GtkEntry
* @icon_pos: icon position
* @formats: the targets (data formats) in which the data can be provided
* @provider: a #GdkContentProvider
* @actions: a bitmask of the allowed drag actions
*
* Sets up the icon at the given position so that GTK+ will start a drag
@@ -2742,7 +2750,7 @@ gtk_entry_get_icon_at_pos (GtkEntry *entry,
void
gtk_entry_set_icon_drag_source (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GdkContentFormats *formats,
GdkContentProvider *provider,
GdkDragAction actions)
{
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
@@ -2754,12 +2762,7 @@ gtk_entry_set_icon_drag_source (GtkEntry *entry,
if ((icon_info = priv->icons[icon_pos]) == NULL)
icon_info = construct_icon_info (GTK_WIDGET (entry), icon_pos);
if (icon_info->target_list)
gdk_content_formats_unref (icon_info->target_list);
icon_info->target_list = formats;
if (icon_info->target_list)
gdk_content_formats_ref (icon_info->target_list);
g_set_object (&icon_info->content, provider);
icon_info->actions = actions;
}
+1 -1
View File
@@ -266,7 +266,7 @@ gchar * gtk_entry_get_icon_tooltip_markup (GtkEntry *
GDK_AVAILABLE_IN_ALL
void gtk_entry_set_icon_drag_source (GtkEntry *entry,
GtkEntryIconPosition icon_pos,
GdkContentFormats *formats,
GdkContentProvider *provider,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
gint gtk_entry_get_current_icon_drag_source (GtkEntry *entry);
-25
View File
@@ -693,31 +693,6 @@ typedef enum
GTK_TREE_VIEW_GRID_LINES_BOTH
} GtkTreeViewGridLines;
/**
* GtkDragResult:
* @GTK_DRAG_RESULT_SUCCESS: The drag operation was successful.
* @GTK_DRAG_RESULT_NO_TARGET: No suitable drag target.
* @GTK_DRAG_RESULT_USER_CANCELLED: The user cancelled the drag operation.
* @GTK_DRAG_RESULT_TIMEOUT_EXPIRED: The drag operation timed out.
* @GTK_DRAG_RESULT_GRAB_BROKEN: The pointer or keyboard grab used
* for the drag operation was broken.
* @GTK_DRAG_RESULT_ERROR: The drag operation failed due to some
* unspecified error.
*
* Gives an indication why a drag operation failed.
* The value can by obtained by connecting to the
* #GtkWidget::drag-failed signal.
*/
typedef enum
{
GTK_DRAG_RESULT_SUCCESS,
GTK_DRAG_RESULT_NO_TARGET,
GTK_DRAG_RESULT_USER_CANCELLED,
GTK_DRAG_RESULT_TIMEOUT_EXPIRED,
GTK_DRAG_RESULT_GRAB_BROKEN,
GTK_DRAG_RESULT_ERROR
} GtkDragResult;
/**
* GtkSizeGroupMode:
* @GTK_SIZE_GROUP_NONE: group has no effect
+19 -18
View File
@@ -115,7 +115,6 @@
#include "gtkbox.h"
#include "gtkbuildable.h"
#include "gtkcontainerprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkiconprivate.h"
#include "gtkgestureclick.h"
@@ -193,12 +192,12 @@ static void gtk_expander_size_allocate (GtkWidget *widget,
int baseline);
static gboolean gtk_expander_focus (GtkWidget *widget,
GtkDirectionType direction);
static gboolean gtk_expander_drag_motion (GtkWidget *widget,
static gboolean gtk_expander_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
static void gtk_expander_drag_leave (GtkWidget *widget,
GdkDrop *drop);
GtkExpander *expander);
static void gtk_expander_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkExpander *expander);
static void gtk_expander_add (GtkContainer *container,
GtkWidget *widget);
@@ -268,8 +267,6 @@ gtk_expander_class_init (GtkExpanderClass *klass)
widget_class->destroy = gtk_expander_destroy;
widget_class->size_allocate = gtk_expander_size_allocate;
widget_class->focus = gtk_expander_focus;
widget_class->drag_motion = gtk_expander_drag_motion;
widget_class->drag_leave = gtk_expander_drag_leave;
widget_class->measure = gtk_expander_measure;
container_class->add = gtk_expander_add;
@@ -350,6 +347,8 @@ gtk_expander_init (GtkExpander *expander)
{
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
GtkGesture *gesture;
GtkDropTarget *dest;
GdkContentFormats *formats;
gtk_widget_set_can_focus (GTK_WIDGET (expander), TRUE);
@@ -375,8 +374,12 @@ gtk_expander_init (GtkExpander *expander)
GTK_STYLE_CLASS_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (priv->title_widget), priv->arrow_widget);
gtk_drag_dest_set (GTK_WIDGET (expander), 0, NULL, 0);
gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
formats = gdk_content_formats_new (NULL, 0);
dest = gtk_drop_target_new (formats, 0);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "accept", G_CALLBACK (gtk_expander_drag_accept), expander);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_expander_drag_leave), expander);
gtk_widget_add_controller (GTK_WIDGET (expander), GTK_EVENT_CONTROLLER (dest));
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture),
@@ -544,12 +547,10 @@ expand_timeout (gpointer data)
}
static gboolean
gtk_expander_drag_motion (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
gtk_expander_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
GtkExpander *expander)
{
GtkExpander *expander = GTK_EXPANDER (widget);
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
if (!priv->expanded && !priv->expand_timer)
@@ -562,10 +563,10 @@ gtk_expander_drag_motion (GtkWidget *widget,
}
static void
gtk_expander_drag_leave (GtkWidget *widget,
GdkDrop *drop)
gtk_expander_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkExpander *expander)
{
GtkExpander *expander = GTK_EXPANDER (widget);
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
if (priv->expand_timer)
+88 -56
View File
@@ -37,7 +37,6 @@
#include "gtkcellrendererpixbuf.h"
#include "gtkcombobox.h"
#include "gtkcssiconthemevalueprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkicontheme.h"
#include "gtkimage.h"
@@ -61,6 +60,7 @@
#include "gtksettings.h"
#include "gtkstylecontextprivate.h"
#include "gtkbitmaskprivate.h"
#include "gtkeventcontroller.h"
/**
* SECTION:gtkfilechooserbutton
@@ -267,9 +267,11 @@ static void gtk_file_chooser_button_finalize (GObject *ob
/* GtkWidget Functions */
static void gtk_file_chooser_button_destroy (GtkWidget *widget);
static void gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *data);
static gboolean gtk_file_chooser_button_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkWidget *widget);
static void gtk_file_chooser_button_show (GtkWidget *widget);
static void gtk_file_chooser_button_hide (GtkWidget *widget);
static void gtk_file_chooser_button_root (GtkWidget *widget);
@@ -366,7 +368,6 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
gobject_class->finalize = gtk_file_chooser_button_finalize;
widget_class->destroy = gtk_file_chooser_button_destroy;
widget_class->drag_data_received = gtk_file_chooser_button_drag_data_received;
widget_class->show = gtk_file_chooser_button_show;
widget_class->hide = gtk_file_chooser_button_hide;
widget_class->map = gtk_file_chooser_button_map;
@@ -443,7 +444,9 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
GtkWidget *box;
GtkWidget *icon;
GdkContentFormatsBuilder *builder;
GdkContentFormats *target_list;
GtkDropTarget *dest;
priv->button = gtk_button_new ();
g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb), button);
@@ -495,13 +498,13 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
NULL, NULL);
/* DnD */
target_list = gdk_content_formats_new (NULL, 0);
target_list = gtk_content_formats_add_uri_targets (target_list);
target_list = gtk_content_formats_add_text_targets (target_list);
gtk_drag_dest_set (GTK_WIDGET (button),
(GTK_DEST_DEFAULT_ALL),
target_list,
GDK_ACTION_COPY);
builder = gdk_content_formats_builder_new ();
gdk_content_formats_builder_add_gtype (builder, G_TYPE_STRING);
gdk_content_formats_builder_add_gtype (builder, GDK_TYPE_FILE_LIST);
target_list = gdk_content_formats_builder_free_to_formats (builder);
dest = gtk_drop_target_new (target_list, GDK_ACTION_COPY);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_file_chooser_button_drag_drop), button);
gtk_widget_add_controller (GTK_WIDGET (button), GTK_EVENT_CONTROLLER (dest));
gdk_content_formats_unref (target_list);
}
@@ -1146,62 +1149,91 @@ dnd_select_folder_get_info_cb (GCancellable *cancellable,
}
static void
gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *data)
dnd_select_file (GtkFileChooserButton *button,
GFile *file)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
GFile *file;
gchar *text;
struct DndSelectFolderData *info;
if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received != NULL)
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->drag_data_received (widget,
drop,
data);
info = g_new0 (struct DndSelectFolderData, 1);
info->button = g_object_ref (button);
info->i = 0;
info->uris = g_new0 (char *, 2);
info->selected = FALSE;
info->file_system = priv->fs;
g_object_get (priv->chooser, "action", &info->action, NULL);
if (widget == NULL || gtk_selection_data_get_length (data) < 0)
return;
info->file = g_object_ref (file);
if (gtk_selection_data_targets_include_uri (data))
if (priv->dnd_select_folder_cancellable)
g_cancellable_cancel (priv->dnd_select_folder_cancellable);
priv->dnd_select_folder_cancellable =
_gtk_file_system_get_info (priv->fs, info->file,
"standard::type",
dnd_select_folder_get_info_cb, info);
}
static void
got_file (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (data);
GdkDrop *drop = GDK_DROP (source);
const GValue *value;
value = gdk_drop_read_value_finish (drop, result, NULL);
if (value)
{
gchar **uris;
struct DndSelectFolderData *info;
GFile *file;
uris = gtk_selection_data_get_uris (data);
if (uris != NULL)
{
info = g_new0 (struct DndSelectFolderData, 1);
info->button = g_object_ref (button);
info->i = 0;
info->uris = uris;
info->selected = FALSE;
info->file_system = priv->fs;
g_object_get (priv->chooser, "action", &info->action, NULL);
info->file = g_file_new_for_uri (info->uris[info->i]);
if (priv->dnd_select_folder_cancellable)
g_cancellable_cancel (priv->dnd_select_folder_cancellable);
priv->dnd_select_folder_cancellable =
_gtk_file_system_get_info (priv->fs, info->file,
"standard::type",
dnd_select_folder_get_info_cb, info);
}
file = g_value_get_object (value);
dnd_select_file (button, file);
}
else if (gtk_selection_data_targets_include_text (data))
}
static void
got_text (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (data);
GdkDrop *drop = GDK_DROP (source);
char *str;
str = gdk_drop_read_text_finish (drop, result, NULL);
if (str)
{
text = (char*) gtk_selection_data_get_text (data);
file = g_file_new_for_uri (text);
gtk_file_chooser_select_file (GTK_FILE_CHOOSER (priv->chooser), file, NULL);
GFile *file;
file = g_file_new_for_uri (str);
dnd_select_file (button, file);
g_object_unref (file);
g_free (text);
g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
}
gdk_drop_finish (drop, GDK_ACTION_COPY);
}
static gboolean
gtk_file_chooser_button_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkWidget *button)
{
if (gdk_drop_has_value (drop, G_TYPE_FILE))
{
gdk_drop_read_value_async (drop, G_TYPE_FILE, G_PRIORITY_DEFAULT, NULL, got_file, button);
return TRUE;
}
else
{
gdk_drop_read_text_async (drop, NULL, got_text, button);
return TRUE;
}
return FALSE;
}
static void
+33 -61
View File
@@ -1982,25 +1982,26 @@ out:
}
static void
file_list_drag_data_received_cb (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data,
gpointer user_data)
file_list_drag_data_received_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GtkDropTarget *dest = GTK_DROP_TARGET (source);
GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
GdkDrop *drop = gtk_drop_target_get_drop (dest);
GdkDrag *drag = gdk_drop_get_drag (drop);
gchar **uris;
char *uri;
GFile *file;
GtkSelectionData *selection_data;
selection_data = gtk_drop_target_read_selection_finish (dest, result, NULL);
/* Allow only drags from other widgets; see bug #533891. */
if (gdk_drop_get_drag (drop) &&
gtk_drag_get_source_widget (gdk_drop_get_drag (drop)) == widget)
{
g_signal_stop_emission_by_name (widget, "drag-data-received");
return;
}
if (drag && gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag)) == widget)
return;
/* Parse the text/uri-list string, navigate to the first one */
uris = gtk_selection_data_get_uris (selection_data);
@@ -2025,60 +2026,34 @@ file_list_drag_data_received_cb (GtkWidget *widget,
file_list_drag_data_received_get_info_cb,
data);
}
g_signal_stop_emission_by_name (widget, "drag-data-received");
}
/* Don't do anything with the drag_drop signal */
static gboolean
file_list_drag_drop_cb (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y,
file_list_drag_drop_cb (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkFileChooserWidget *impl)
{
g_signal_stop_emission_by_name (widget, "drag-drop");
const char *target = g_intern_static_string ("text/uri-list");
gtk_drop_target_read_selection (dest, target, NULL, file_list_drag_data_received_cb, impl);
return TRUE;
}
static void
file_list_drag_begin_cb (GtkWidget *widget,
GdkDrag *drag,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (priv->places_sidebar),
TRUE,
drag);
}
/* Disable the normal tree drag motion handler, it makes it look like you're
dropping the dragged item onto a tree item */
static gboolean
file_list_drag_motion_cb (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y,
file_list_drag_accept_cb (GtkDropTarget *dest,
GdkDrop *drop,
GtkFileChooserWidget *impl)
{
g_signal_stop_emission_by_name (widget, "drag-motion");
g_signal_stop_emission_by_name (dest, "accept");
return TRUE;
}
static void
file_list_drag_end_cb (GtkWidget *widget,
GdkDrag *drag,
gpointer user_data)
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
gtk_places_sidebar_set_drop_targets_visible (GTK_PLACES_SIDEBAR (priv->places_sidebar),
FALSE,
drag);
}
/* Sensitizes the "Copy files location" and other context menu items if there is actually
* a selection active.
*/
@@ -8468,14 +8443,9 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, box);
/* And a *lot* of callbacks to bind ... */
gtk_widget_class_bind_template_callback (widget_class, file_list_drag_drop_cb);
gtk_widget_class_bind_template_callback (widget_class, file_list_drag_data_received_cb);
gtk_widget_class_bind_template_callback (widget_class, list_popup_menu_cb);
gtk_widget_class_bind_template_callback (widget_class, file_list_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, list_row_activated);
gtk_widget_class_bind_template_callback (widget_class, file_list_drag_begin_cb);
gtk_widget_class_bind_template_callback (widget_class, file_list_drag_motion_cb);
gtk_widget_class_bind_template_callback (widget_class, file_list_drag_end_cb);
gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
gtk_widget_class_bind_template_callback (widget_class, list_cursor_changed);
gtk_widget_class_bind_template_callback (widget_class, browse_files_tree_view_keynav_failed_cb);
@@ -8510,23 +8480,25 @@ post_process_ui (GtkFileChooserWidget *impl)
GtkCellRenderer *cell;
GList *cells;
GFile *file;
GtkDropTarget *dest;
GdkContentFormats *formats;
/* Setup file list treeview */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_set_select_function (selection,
list_select_func,
impl, NULL);
formats = gdk_content_formats_new_for_gtype (GDK_TYPE_FILE_LIST);
gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->browse_files_tree_view),
GDK_BUTTON1_MASK,
NULL,
formats,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_source_add_uri_targets (priv->browse_files_tree_view);
gtk_drag_dest_set (priv->browse_files_tree_view,
GTK_DEST_DEFAULT_ALL,
NULL,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_dest_add_uri_targets (priv->browse_files_tree_view);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
g_signal_connect (dest, "accept", G_CALLBACK (file_list_drag_accept_cb), impl);
g_signal_connect (dest, "drag-drop", G_CALLBACK (file_list_drag_drop_cb), impl);
gtk_widget_add_controller (priv->browse_files_tree_view, GTK_EVENT_CONTROLLER (dest));
gdk_content_formats_unref (formats);
/* File browser treemodel columns are shared between GtkFileChooser implementations,
* so we don't set cell renderer attributes in GtkBuilder, but rather keep that
+2 -2
View File
@@ -458,7 +458,7 @@ gtk_filter_list_model_augment (GtkRbTree *filter,
* gtk_filter_list_model_new:
* @model: the model to sort
* @filter_func: (allow-none): filter function or %NULL to not filter items
* @user_data: user data passed to @filter_func
* @user_data: (closure): user data passed to @filter_func
* @user_destroy: destroy notifier for @user_data
*
* Creates a new #GtkFilterListModel that will filter @model using the given
@@ -511,7 +511,7 @@ gtk_filter_list_model_new_for_type (GType item_type)
* gtk_filter_list_model_set_filter_func:
* @self: a #GtkFilterListModel
* @filter_func: (allow-none): filter function or %NULL to not filter items
* @user_data: user data passed to @filter_func
* @user_data: (closure): user data passed to @filter_func
* @user_destroy: destroy notifier for @user_data
*
* Sets the function used to filter items. The function will be called for every
+5 -5
View File
@@ -4045,7 +4045,7 @@ gtk_flow_box_check_model_compat (GtkFlowBox *box)
* @box: a #GtkFlowBox
* @model: (allow-none): the #GListModel to be bound to @box
* @create_widget_func: a function that creates widgets for items
* @user_data: user data passed to @create_widget_func
* @user_data: (closure): user data passed to @create_widget_func
* @user_data_free_func: function for freeing @user_data
*
* Binds @model to @box.
@@ -4583,9 +4583,9 @@ gtk_flow_box_get_selection_mode (GtkFlowBox *box)
/**
* gtk_flow_box_set_filter_func:
* @box: a #GtkFlowBox
* @filter_func: (closure user_data) (allow-none): callback that
* @filter_func: (allow-none): callback that
* lets you filter which children to show
* @user_data: user data passed to @filter_func
* @user_data: (closure): user data passed to @filter_func
* @destroy: destroy notifier for @user_data
*
* By setting a filter function on the @box one can decide dynamically
@@ -4663,8 +4663,8 @@ gtk_flow_box_invalidate_filter (GtkFlowBox *box)
/**
* gtk_flow_box_set_sort_func:
* @box: a #GtkFlowBox
* @sort_func: (closure user_data) (allow-none): the sort function
* @user_data: user data passed to @sort_func
* @sort_func: (allow-none): the sort function
* @user_data: (closure): user data passed to @sort_func
* @destroy: destroy notifier for @user_data
*
* By setting a sort function on the @box, one can dynamically
+1 -1
View File
@@ -407,7 +407,7 @@ gtk_font_chooser_set_show_preview_entry (GtkFontChooser *fontchooser,
* gtk_font_chooser_set_filter_func:
* @fontchooser: a #GtkFontChooser
* @filter: (allow-none): a #GtkFontFilterFunc, or %NULL
* @user_data: data to pass to @filter
* @user_data: (closure): data to pass to @filter
* @destroy: function to call to free @data when it is no longer needed
*
* Adds a filter function that decides which fonts to display
+2
View File
@@ -716,6 +716,8 @@ gtk_font_chooser_widget_dispose (GObject *object)
GtkFontChooserWidget *self = GTK_FONT_CHOOSER_WIDGET (object);
GtkFontChooserWidgetPrivate *priv = gtk_font_chooser_widget_get_instance_private (self);
if (priv->family_face_list)
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->family_face_list), NULL);
g_clear_pointer (&priv->stack, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_font_chooser_widget_parent_class)->dispose (object);
+1 -1
View File
@@ -37,7 +37,7 @@
#include "gtkgesturelongpressprivate.h"
#include "gtkgestureprivate.h"
#include "gtkmarshalers.h"
#include "gtkdnd.h"
#include "gtkdragsource.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
+1 -15
View File
@@ -36,8 +36,6 @@
struct _GtkIcon
{
GtkWidget parent;
GtkCssImageBuiltinType image;
};
G_DEFINE_TYPE (GtkIcon, gtk_icon, GTK_TYPE_WIDGET)
@@ -46,7 +44,6 @@ static void
gtk_icon_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkIcon *self = GTK_ICON (widget);
GtkCssStyle *style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
int width, height;
@@ -54,10 +51,7 @@ gtk_icon_snapshot (GtkWidget *widget,
height = gtk_widget_get_height (widget);
if (width > 0 && height > 0)
gtk_css_style_snapshot_icon (style,
snapshot,
width, height,
self->image);
gtk_css_style_snapshot_icon (style, snapshot, width, height);
}
static void
@@ -87,7 +81,6 @@ gtk_icon_class_init (GtkIconClass *klass)
static void
gtk_icon_init (GtkIcon *self)
{
self->image = GTK_CSS_IMAGE_BUILTIN_NONE;
}
GtkWidget *
@@ -98,13 +91,6 @@ gtk_icon_new (const char *css_name)
NULL);
}
void
gtk_icon_set_image (GtkIcon *self,
GtkCssImageBuiltinType image)
{
self->image = image;
}
void
gtk_icon_set_css_name (GtkIcon *self,
const char *css_name)
-3
View File
@@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (GtkIcon, gtk_icon, GTK, ICON, GtkWidget)
GtkWidget * gtk_icon_new (const char *css_name);
void gtk_icon_set_image (GtkIcon *self,
GtkCssImageBuiltinType image);
void gtk_icon_set_css_name (GtkIcon *self,
const char *css_name);
+4 -6
View File
@@ -3638,7 +3638,6 @@ gtk_icon_info_load_symbolic_svg (GtkIconInfo *icon_info,
gchar *width;
gchar *height;
char *escaped_file_data;
gint symbolic_size;
double alpha;
gchar alphastr[G_ASCII_DTOSTR_BUF_SIZE];
@@ -3707,9 +3706,8 @@ gtk_icon_info_load_symbolic_svg (GtkIconInfo *icon_info,
g_object_unref (pixbuf);
}
symbolic_size = MAX (icon_info->symbolic_width, icon_info->symbolic_height);
GTK_NOTE (ICONTHEME,
GTK_NOTE (ICONTHEME, {
int symbolic_size = MAX (icon_info->symbolic_width, icon_info->symbolic_height);
if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED)
g_message ("Symbolic icon %s is not in an icon theme directory",
icon_info->key.icon_names ? icon_info->key.icon_names[0] : icon_info->filename);
@@ -3717,8 +3715,8 @@ gtk_icon_info_load_symbolic_svg (GtkIconInfo *icon_info,
g_message ("Symbolic icon %s of size %d is in an icon theme directory of size %d",
icon_info->key.icon_names ? icon_info->key.icon_names[0] : icon_info->filename,
symbolic_size,
icon_info->dir_size * icon_info->dir_scale)
);
icon_info->dir_size * icon_info->dir_scale);
});
width = g_strdup_printf ("%d", icon_info->symbolic_width);
height = g_strdup_printf ("%d", icon_info->symbolic_height);
+170 -194
View File
@@ -30,7 +30,6 @@
#include "gtkcellrenderertext.h"
#include "gtkcombobox.h"
#include "gtkcssnodeprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkdragsource.h"
#include "gtkentry.h"
@@ -48,6 +47,11 @@
#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
#include "gtkeventcontrollerkey.h"
#include "gtkdragsource.h"
#include "gtkdragdest.h"
#include "gtkdragicon.h"
#include "gtkselectionprivate.h"
#include "gtknative.h"
#include "a11y/gtkiconviewaccessibleprivate.h"
@@ -279,30 +283,28 @@ static void update_text_cell (GtkIco
static void update_pixbuf_cell (GtkIconView *icon_view);
/* Source side drag signals */
static void gtk_icon_view_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_icon_view_drag_end (GtkWidget *widget,
GdkDrag *drag);
static void gtk_icon_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_icon_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag);
static void gtk_icon_view_dnd_finished_cb (GdkDrag *drag,
GtkWidget *widget);
static GBytes * gtk_icon_view_drag_data_get (const char *mime_type,
gpointer data);
/* Target side drag signals */
static void gtk_icon_view_drag_leave (GtkWidget *widget,
GdkDrop *drop);
static gboolean gtk_icon_view_drag_motion (GtkWidget *widget,
static void gtk_icon_view_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
static gboolean gtk_icon_view_drag_drop (GtkWidget *widget,
GtkIconView *icon_view);
static void gtk_icon_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
static void gtk_icon_view_drag_data_received (GtkWidget *widget,
int x,
int y,
GtkIconView *icon_view);
static gboolean gtk_icon_view_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
GtkSelectionData *selection_data);
int x,
int y,
GtkIconView *icon_view);
static void gtk_icon_view_drag_data_received (GObject *source,
GAsyncResult *result,
gpointer data);
static gboolean gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
double x,
double y,
@@ -360,14 +362,6 @@ gtk_icon_view_class_init (GtkIconViewClass *klass)
widget_class->measure = gtk_icon_view_measure;
widget_class->size_allocate = gtk_icon_view_size_allocate;
widget_class->snapshot = gtk_icon_view_snapshot;
widget_class->drag_begin = gtk_icon_view_drag_begin;
widget_class->drag_end = gtk_icon_view_drag_end;
widget_class->drag_data_get = gtk_icon_view_drag_data_get;
widget_class->drag_data_delete = gtk_icon_view_drag_data_delete;
widget_class->drag_leave = gtk_icon_view_drag_leave;
widget_class->drag_motion = gtk_icon_view_drag_motion;
widget_class->drag_drop = gtk_icon_view_drag_drop;
widget_class->drag_data_received = gtk_icon_view_drag_data_received;
container_class->remove = gtk_icon_view_remove;
container_class->forall = gtk_icon_view_forall;
@@ -1033,6 +1027,8 @@ gtk_icon_view_dispose (GObject *object)
g_clear_object (&priv->key_controller);
g_clear_pointer (&priv->source_formats, gdk_content_formats_unref);
G_OBJECT_CLASS (gtk_icon_view_parent_class)->dispose (object);
}
@@ -1761,9 +1757,14 @@ gtk_icon_view_snapshot (GtkWidget *widget,
break;
}
gtk_snapshot_render_focus (snapshot, context,
gtk_style_context_save_to_node (context, icon_view->priv->dndnode);
gtk_style_context_set_state (context, gtk_style_context_get_state (context) | GTK_STATE_FLAG_DROP_ACTIVE);
gtk_snapshot_render_frame (snapshot, context,
rect.x, rect.y,
rect.width, rect.height);
gtk_style_context_restore (context);
}
if (icon_view->priv->doing_rubberband)
@@ -5712,35 +5713,6 @@ unset_reorderable (GtkIconView *icon_view)
}
}
static void
set_source_row (GdkDrag *drag,
GtkTreeModel *model,
GtkTreePath *source_row)
{
if (source_row)
g_object_set_data_full (G_OBJECT (drag),
I_("gtk-icon-view-source-row"),
gtk_tree_row_reference_new (model, source_row),
(GDestroyNotify) gtk_tree_row_reference_free);
else
g_object_set_data_full (G_OBJECT (drag),
I_("gtk-icon-view-source-row"),
NULL, NULL);
}
static GtkTreePath*
get_source_row (GdkDrag *drag)
{
GtkTreeRowReference *ref;
ref = g_object_get_data (G_OBJECT (drag), "gtk-icon-view-source-row");
if (ref)
return gtk_tree_row_reference_get_path (ref);
else
return NULL;
}
typedef struct
{
GtkTreeRowReference *dest_row;
@@ -5886,7 +5858,7 @@ drag_scroll_timeout (gpointer data)
static gboolean
set_destination (GtkIconView *icon_view,
GdkDrop *drop,
GtkDropTarget *dest,
gint x,
gint y,
GdkDragAction *suggested_action,
@@ -5919,8 +5891,7 @@ set_destination (GtkIconView *icon_view,
return FALSE; /* no longer a drop site */
}
*target = gtk_drag_dest_find_target (widget, drop,
gtk_drag_dest_get_target_list (widget));
*target = gtk_drop_target_find_mimetype (dest);
if (*target == NULL)
return FALSE;
@@ -6030,11 +6001,14 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
double y,
GdkDevice *device)
{
GtkWidget *widget = GTK_WIDGET (icon_view);
GdkDrag *drag;
GtkTreePath *path = NULL;
GtkTreeModel *model;
gboolean retval = FALSE;
GdkContentProvider *content;
GdkPaintable *icon;
GtkIconViewItem *item;
GdkSurface *surface;
GdkDrag *drag;
if (!icon_view->priv->source_set)
goto out;
@@ -6055,16 +6029,19 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
icon_view->priv->pressed_button = -1;
path = gtk_icon_view_get_path_at_pos (icon_view,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y);
item = _gtk_icon_view_get_item_at_coords (icon_view,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y,
TRUE,
NULL);
if (path == NULL)
if (item == NULL)
goto out;
path = gtk_tree_path_new_from_indices (item->index, -1);
if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
!gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
path))
!gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model), path))
goto out;
/* FIXME Check whether we're a start button, if not return FALSE and
@@ -6075,14 +6052,35 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
retval = TRUE;
drag = gtk_drag_begin (widget,
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (icon_view)));
content = gdk_content_provider_new_with_formats (icon_view->priv->source_formats,
gtk_icon_view_drag_data_get,
icon_view);
drag = gdk_drag_begin (surface,
device,
gtk_drag_source_get_target_list (widget),
icon_view->priv->source_actions,
content,
icon_view->priv->source_actions,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y);
set_source_row (drag, model, path);
g_object_unref (content);
g_signal_connect (drag, "dnd-finished", G_CALLBACK (gtk_icon_view_dnd_finished_cb), icon_view);
icon_view->priv->source_item = gtk_tree_row_reference_new (model, path);
x = icon_view->priv->press_start_x - item->cell_area.x + icon_view->priv->item_padding;
y = icon_view->priv->press_start_y - item->cell_area.y + icon_view->priv->item_padding;
icon = gtk_icon_view_create_drag_icon (icon_view, path);
gtk_drag_icon_set_from_paintable (drag, icon, x, y);
g_object_unref (icon);
icon_view->priv->drag = drag;
g_object_unref (drag);
out:
if (path)
@@ -6092,71 +6090,28 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
}
/* Source side drag signals */
static void
gtk_icon_view_drag_begin (GtkWidget *widget,
GdkDrag *drag)
static GBytes *
gtk_icon_view_drag_data_get (const char *mime_type,
gpointer data)
{
GtkIconView *icon_view;
GtkIconViewItem *item;
GdkPaintable *icon;
gint x, y;
GtkTreePath *path;
icon_view = GTK_ICON_VIEW (widget);
/* if the user uses a custom DnD impl, we don't set the icon here */
if (!icon_view->priv->dest_set && !icon_view->priv->source_set)
return;
item = _gtk_icon_view_get_item_at_coords (icon_view,
icon_view->priv->press_start_x,
icon_view->priv->press_start_y,
TRUE,
NULL);
g_return_if_fail (item != NULL);
x = icon_view->priv->press_start_x - item->cell_area.x + icon_view->priv->item_padding;
y = icon_view->priv->press_start_y - item->cell_area.y + icon_view->priv->item_padding;
path = gtk_tree_path_new_from_indices (item->index, -1);
icon = gtk_icon_view_create_drag_icon (icon_view, path);
gtk_tree_path_free (path);
gtk_drag_set_icon_paintable (drag, icon, x, y);
g_object_unref (icon);
}
static void
gtk_icon_view_drag_end (GtkWidget *widget,
GdkDrag *drag)
{
/* do nothing */
}
static void
gtk_icon_view_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
GtkIconView *icon_view;
GtkIconView *icon_view = data;
GtkTreeModel *model;
GtkTreePath *source_row;
GtkSelectionData sdata = { 0, };
sdata.target = g_intern_string (mime_type);
icon_view = GTK_ICON_VIEW (widget);
model = gtk_icon_view_get_model (icon_view);
if (model == NULL)
return;
return NULL;
if (!icon_view->priv->source_set)
return;
source_row = get_source_row (drag);
return NULL;
source_row = gtk_tree_row_reference_get_path (icon_view->priv->source_item);
if (source_row == NULL)
return;
return NULL;
/* We can implement the GTK_TREE_MODEL_ROW target generically for
* any model; for DragSource models there are some other formats
@@ -6164,29 +6119,31 @@ gtk_icon_view_drag_data_get (GtkWidget *widget,
*/
if (GTK_IS_TREE_DRAG_SOURCE (model) &&
gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
source_row,
selection_data))
gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model), source_row, &sdata))
goto done;
/* If drag_data_get does nothing, try providing row data. */
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("GTK_TREE_MODEL_ROW"))
gtk_tree_set_row_drag_data (selection_data,
model,
source_row);
if (gtk_selection_data_get_target (&sdata) == g_intern_static_string ("GTK_TREE_MODEL_ROW"))
gtk_tree_set_row_drag_data (&sdata, model, source_row);
done:
gtk_tree_path_free (source_row);
return g_bytes_new_take ((gpointer)gtk_selection_data_get_data (&sdata),
gtk_selection_data_get_length (&sdata));
}
static void
gtk_icon_view_drag_data_delete (GtkWidget *widget,
GdkDrag *drag)
gtk_icon_view_dnd_finished_cb (GdkDrag *drag,
GtkWidget *widget)
{
GtkTreeModel *model;
GtkIconView *icon_view;
GtkTreePath *source_row;
if (gdk_drag_get_selected_action (drag) != GDK_ACTION_MOVE)
return;
icon_view = GTK_ICON_VIEW (widget);
model = gtk_icon_view_get_model (icon_view);
@@ -6196,28 +6153,24 @@ gtk_icon_view_drag_data_delete (GtkWidget *widget,
if (!icon_view->priv->source_set)
return;
source_row = get_source_row (drag);
source_row = gtk_tree_row_reference_get_path (icon_view->priv->source_item);
if (source_row == NULL)
return;
gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
source_row);
gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model), source_row);
gtk_tree_path_free (source_row);
set_source_row (drag, NULL, NULL);
g_clear_pointer (&icon_view->priv->source_item, gtk_tree_row_reference_free);
icon_view->priv->drag = NULL;
}
/* Target side drag signals */
static void
gtk_icon_view_drag_leave (GtkWidget *widget,
GdkDrop *drop)
gtk_icon_view_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkIconView *icon_view)
{
GtkIconView *icon_view;
icon_view = GTK_ICON_VIEW (widget);
/* unset any highlight row */
gtk_icon_view_set_drag_dest_item (icon_view,
NULL,
@@ -6226,26 +6179,24 @@ gtk_icon_view_drag_leave (GtkWidget *widget,
remove_scroll_timeout (icon_view);
}
static gboolean
gtk_icon_view_drag_motion (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
static void
gtk_icon_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkIconView *icon_view)
{
GtkTreePath *path = NULL;
GtkIconViewDropPosition pos;
GtkIconView *icon_view;
GdkDragAction suggested_action = 0;
GdkAtom target;
gboolean empty;
icon_view = GTK_ICON_VIEW (widget);
if (!set_destination (icon_view, drop, x, y, &suggested_action, &target))
return FALSE;
icon_view->priv->event_last_x = x;
icon_view->priv->event_last_y = y;
if (!set_destination (icon_view, dest, x, y, &suggested_action, &target))
{
gdk_drop_status (drop, 0);
return;
}
gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
@@ -6271,7 +6222,7 @@ gtk_icon_view_drag_motion (GtkWidget *widget,
* determining whether to accept the drop
*/
set_status_pending (drop, suggested_action);
gtk_drag_get_data (widget, drop, target);
gtk_drop_target_read_selection (dest, target, NULL, gtk_icon_view_drag_data_received, icon_view);
}
else
{
@@ -6282,27 +6233,24 @@ gtk_icon_view_drag_motion (GtkWidget *widget,
if (path)
gtk_tree_path_free (path);
return TRUE;
}
static gboolean
gtk_icon_view_drag_drop (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
gtk_icon_view_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
GtkIconView *icon_view)
{
GtkIconView *icon_view;
GtkTreePath *path;
GdkDragAction suggested_action = 0;
GdkAtom target = NULL;
GtkTreeModel *model;
gboolean drop_append_mode;
icon_view = GTK_ICON_VIEW (widget);
model = gtk_icon_view_get_model (icon_view);
remove_scroll_timeout (GTK_ICON_VIEW (widget));
remove_scroll_timeout (icon_view);
if (!icon_view->priv->dest_set)
return FALSE;
@@ -6310,7 +6258,7 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-drop"))
return FALSE;
if (!set_destination (icon_view, drop, x, y, &suggested_action, &target))
if (!set_destination (icon_view, dest, x, y, &suggested_action, &target))
return FALSE;
path = get_logical_destination (icon_view, &drop_append_mode);
@@ -6333,7 +6281,7 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
if (target != NULL)
{
gtk_drag_get_data (widget, drop, target);
gtk_drop_target_read_selection (dest, target, NULL, gtk_icon_view_drag_data_received, icon_view);
return TRUE;
}
else
@@ -6341,16 +6289,16 @@ gtk_icon_view_drag_drop (GtkWidget *widget,
}
static GdkDragAction
gtk_icon_view_get_action (GtkWidget *treeview,
gtk_icon_view_get_action (GtkWidget *widget,
GdkDrop *drop)
{
GtkIconView *iconview = GTK_ICON_VIEW (widget);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget = gtk_drag_get_source_widget (drag);
GdkDragAction actions;
actions = gdk_drop_get_actions (drop);
if (source_widget == treeview &&
if (drag == iconview->priv->drag &&
actions & GDK_ACTION_MOVE)
return GDK_ACTION_MOVE;
@@ -6367,25 +6315,31 @@ gtk_icon_view_get_action (GtkWidget *treeview,
}
static void
gtk_icon_view_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data)
gtk_icon_view_drag_data_received (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkDropTarget *dest = GTK_DROP_TARGET (source);
GtkIconView *icon_view = data;
GdkDrop *drop = gtk_drop_target_get_drop (dest);
GtkTreePath *path;
GtkTreeModel *model;
GtkIconView *icon_view;
GtkTreePath *dest_row;
GdkDragAction suggested_action;
gboolean drop_append_mode;
icon_view = GTK_ICON_VIEW (widget);
GtkSelectionData *selection_data;
selection_data = gtk_drop_target_read_selection_finish (dest, result, NULL);
if (!selection_data)
return;
model = gtk_icon_view_get_model (icon_view);
if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-data-received"))
return;
goto out;
if (!icon_view->priv->dest_set)
return;
goto out;
suggested_action = get_status_pending (drop);
@@ -6419,18 +6373,18 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
gtk_icon_view_set_drag_dest_item (icon_view,
NULL,
GTK_ICON_VIEW_DROP_LEFT);
return;
goto out;
}
dest_row = get_dest_row (drop);
if (dest_row == NULL)
return;
goto out;
if (gtk_selection_data_get_length (selection_data) >= 0)
{
suggested_action = gtk_icon_view_get_action (widget, drop);
suggested_action = gtk_icon_view_get_action (GTK_WIDGET (icon_view), drop);
if (suggested_action &&
!gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
@@ -6445,9 +6399,13 @@ gtk_icon_view_drag_data_received (GtkWidget *widget,
/* drop dest_row */
set_dest_row (drop, NULL, NULL, FALSE, FALSE);
out:
gtk_selection_data_free (selection_data);
}
/* Drag-and-Drop support */
/**
* gtk_icon_view_enable_model_drag_source:
* @icon_view: a #GtkIconView
@@ -6467,9 +6425,7 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
{
g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
gtk_drag_source_set (GTK_WIDGET (icon_view), 0, formats, actions);
icon_view->priv->start_button_mask = start_button_mask;
icon_view->priv->source_formats = gdk_content_formats_ref (formats);
icon_view->priv->source_actions = actions;
icon_view->priv->source_set = TRUE;
@@ -6486,21 +6442,37 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
*
* Turns @icon_view into a drop destination for automatic DND. Calling this
* method sets #GtkIconView:reorderable to %FALSE.
*
* Returns: (transfer none): the drop target that was attached
**/
void
GtkDropTarget *
gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view,
GdkContentFormats *formats,
GdkDragAction actions)
{
g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
GtkCssNode *widget_node;
gtk_drag_dest_set (GTK_WIDGET (icon_view), 0, formats, actions);
icon_view->priv->dest = gtk_drop_target_new (formats, actions);
g_signal_connect (icon_view->priv->dest, "drag-leave", G_CALLBACK (gtk_icon_view_drag_leave), icon_view);
g_signal_connect (icon_view->priv->dest, "drag-motion", G_CALLBACK (gtk_icon_view_drag_motion), icon_view);
g_signal_connect (icon_view->priv->dest, "drag-drop", G_CALLBACK (gtk_icon_view_drag_drop), icon_view);
gtk_widget_add_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (icon_view->priv->dest));
icon_view->priv->dest_actions = actions;
icon_view->priv->dest_set = TRUE;
unset_reorderable (icon_view);
widget_node = gtk_widget_get_css_node (GTK_WIDGET (icon_view));
icon_view->priv->dndnode = gtk_css_node_new ();
gtk_css_node_set_name (icon_view->priv->dndnode, I_("dndtarget"));
gtk_css_node_set_parent (icon_view->priv->dndnode, widget_node);
gtk_css_node_set_state (icon_view->priv->dndnode, gtk_css_node_get_state (widget_node));
g_object_unref (icon_view->priv->dndnode);
return icon_view->priv->dest;
}
/**
@@ -6517,7 +6489,7 @@ gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view)
if (icon_view->priv->source_set)
{
gtk_drag_source_unset (GTK_WIDGET (icon_view));
g_clear_pointer (&icon_view->priv->source_formats, gdk_content_formats_unref);
icon_view->priv->source_set = FALSE;
}
@@ -6538,8 +6510,12 @@ gtk_icon_view_unset_model_drag_dest (GtkIconView *icon_view)
if (icon_view->priv->dest_set)
{
gtk_drag_dest_unset (GTK_WIDGET (icon_view));
gtk_widget_remove_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (icon_view->priv->dest));
icon_view->priv->dest = NULL;
icon_view->priv->dest_set = FALSE;
gtk_css_node_set_parent (icon_view->priv->dndnode, NULL);
icon_view->priv->dndnode = NULL;
}
unset_reorderable (icon_view);
+3 -1
View File
@@ -28,6 +28,8 @@
#include <gtk/gtkcellarea.h>
#include <gtk/gtkselection.h>
#include <gtk/gtktooltip.h>
#include <gtk/gtkdragsource.h>
#include <gtk/gtkdragdest.h>
G_BEGIN_DECLS
@@ -218,7 +220,7 @@ void gtk_icon_view_enable_model_drag_source (GtkIconView
GdkContentFormats *formats,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
void gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view,
GtkDropTarget * gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view,
GdkContentFormats *formats,
GdkDragAction actions);
GDK_AVAILABLE_IN_ALL
+8
View File
@@ -19,6 +19,7 @@
#include "gtk/gtkcssnodeprivate.h"
#include "gtk/gtkgestureclick.h"
#include "gtk/gtkeventcontrollermotion.h"
#include "gtk/gtkdragsource.h"
#ifndef __GTK_ICON_VIEW_PRIVATE_H__
#define __GTK_ICON_VIEW_PRIVATE_H__
@@ -132,9 +133,16 @@ struct _GtkIconViewPrivate
gint press_start_x;
gint press_start_y;
GdkContentFormats *source_formats;
GtkDropTarget *dest;
GtkCssNode *dndnode;
GdkDrag *drag;
GdkDragAction source_actions;
GdkDragAction dest_actions;
GtkTreeRowReference *source_item;
GtkTreeRowReference *dest_item;
GtkIconViewDropPosition dest_pos;
+2 -1
View File
@@ -592,7 +592,8 @@ gtk_im_context_wayland_get_preedit_string (GtkIMContext *context,
if (str)
*str = g_strdup (preedit_str);
if (cursor_pos)
*cursor_pos = context_wayland->current_preedit.cursor_begin;
*cursor_pos = g_utf8_strlen (preedit_str,
context_wayland->current_preedit.cursor_begin);
if (attrs)
{
+22 -82
View File
@@ -32,7 +32,6 @@
#include "gtkcssnodeprivate.h"
#include "gtkcssshadowsvalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkdnd.h"
#include "gtkeventcontrollermotion.h"
#include "gtkgesturedrag.h"
#include "gtkgestureclick.h"
@@ -54,6 +53,8 @@
#include "gtkwindow.h"
#include "gtkpopovermenu.h"
#include "gtknative.h"
#include "gtkdragsource.h"
#include "gtkdragicon.h"
#include "a11y/gtklabelaccessibleprivate.h"
@@ -501,9 +502,6 @@ static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
static void gtk_label_setup_mnemonic (GtkLabel *label,
GtkWidget *toplevel,
guint last_key);
static void gtk_label_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data);
static void gtk_label_buildable_interface_init (GtkBuildableIface *iface);
static gboolean gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
@@ -652,7 +650,6 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->unroot = gtk_label_unroot;
widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
widget_class->popup_menu = gtk_label_popup_menu;
widget_class->drag_data_get = gtk_label_drag_data_get;
widget_class->grab_focus = gtk_label_grab_focus;
widget_class->focus = gtk_label_focus;
widget_class->get_request_mode = gtk_label_get_request_mode;
@@ -4597,16 +4594,10 @@ connect_mnemonics_visible_notify (GtkLabel *label)
}
}
static void
drag_begin_cb (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
static GdkPaintable *
get_selection_paintable (GtkLabel *label)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GdkPaintable *paintable = NULL;
g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL);
if ((priv->select_info->selection_anchor !=
priv->select_info->selection_end) &&
@@ -4628,20 +4619,10 @@ drag_begin_cb (GtkWidget *widget,
if (start > len)
start = len;
paintable = gtk_text_util_create_drag_icon (widget,
priv->text + start,
end - start);
return gtk_text_util_create_drag_icon (GTK_WIDGET (label), priv->text + start, end - start);
}
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, 0, 0);
g_object_unref (paintable);
}
else
{
gtk_drag_set_icon_default (drag);
}
return NULL;
}
static void
@@ -4734,27 +4715,27 @@ gtk_label_drag_gesture_update (GtkGestureDrag *gesture,
if (info->in_drag)
{
if (gtk_drag_check_threshold (widget,
info->drag_start_x,
info->drag_start_y,
x, y))
if (gtk_drag_check_threshold (widget, info->drag_start_x, info->drag_start_y, x, y))
{
GdkContentFormats *target_list = gdk_content_formats_new (NULL, 0);
GdkDrag *drag;
GdkSurface *surface;
GdkDevice *device;
target_list = gtk_content_formats_add_text_targets (target_list);
surface = gtk_native_get_surface (gtk_widget_get_native (widget));
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
g_signal_connect (widget, "drag-begin",
G_CALLBACK (drag_begin_cb), NULL);
gtk_drag_begin (widget,
gtk_gesture_get_device (GTK_GESTURE (gesture)),
target_list,
GDK_ACTION_COPY,
info->drag_start_x,
info->drag_start_y);
drag = gdk_drag_begin (surface,
device,
info->provider,
GDK_ACTION_COPY,
info->drag_start_x,
info->drag_start_y);
gtk_drag_icon_set_from_paintable (drag, get_selection_paintable (label), 0, 0);
g_object_unref (drag);
info->in_drag = FALSE;
gdk_content_formats_unref (target_list);
}
}
else
@@ -5140,47 +5121,6 @@ gtk_label_get_selectable (GtkLabel *label)
return priv->select_info && priv->select_info->selectable;
}
static void
gtk_label_set_selection_text (GtkLabel *label,
GtkSelectionData *selection_data)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
if (priv->select_info &&
(priv->select_info->selection_anchor !=
priv->select_info->selection_end) &&
priv->text)
{
gint start, end;
gint len;
start = MIN (priv->select_info->selection_anchor,
priv->select_info->selection_end);
end = MAX (priv->select_info->selection_anchor,
priv->select_info->selection_end);
len = strlen (priv->text);
if (end > len)
end = len;
if (start > len)
start = len;
gtk_selection_data_set_text (selection_data,
priv->text + start,
end - start);
}
}
static void
gtk_label_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data)
{
gtk_label_set_selection_text (GTK_LABEL (widget), selection_data);
}
static void
gtk_label_select_region_index (GtkLabel *label,
gint anchor_index,
+78 -36
View File
@@ -124,10 +124,6 @@ static void gtk_link_button_set_property (GObject *object,
GParamSpec *pspec);
static void gtk_link_button_clicked (GtkButton *button);
static gboolean gtk_link_button_popup_menu (GtkWidget *widget);
static void gtk_link_button_drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
gpointer user_data);
static gboolean gtk_link_button_query_tooltip_cb (GtkWidget *widget,
gint x,
gint y,
@@ -251,31 +247,97 @@ gtk_link_button_get_menu_model (void)
return G_MENU_MODEL (menu);
}
#define GTK_TYPE_LINK_CONTENT (gtk_link_content_get_type ())
#define GTK_LINK_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_LINK_CONTENT, GtkLinkContent))
typedef struct _GtkLinkContent GtkLinkContent;
typedef struct _GtkLinkContentClass GtkLinkContentClass;
struct _GtkLinkContent
{
GdkContentProvider parent;
GtkLinkButton *link;
};
struct _GtkLinkContentClass
{
GdkContentProviderClass parent_class;
};
GType gtk_link_content_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GtkLinkContent, gtk_link_content, GDK_TYPE_CONTENT_PROVIDER)
static GdkContentFormats *
gtk_link_content_ref_formats (GdkContentProvider *provider)
{
GtkLinkContent *content = GTK_LINK_CONTENT (provider);
if (content->link)
return gdk_content_formats_union (gdk_content_formats_new_for_gtype (G_TYPE_STRING),
gdk_content_formats_new (link_drop_types, G_N_ELEMENTS (link_drop_types)));
else
return gdk_content_formats_new (NULL, 0);
}
static gboolean
gtk_link_content_get_value (GdkContentProvider *provider,
GValue *value,
GError **error)
{
GtkLinkContent *content = GTK_LINK_CONTENT (provider);
if (G_VALUE_HOLDS (value, G_TYPE_STRING) &&
content->link != NULL)
{
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (content->link);
char *uri;
uri = g_strdup_printf ("%s\r\n", priv->uri);
g_value_set_string (value, uri);
g_free (uri);
return TRUE;
}
return GDK_CONTENT_PROVIDER_CLASS (gtk_link_content_parent_class)->get_value (provider, value, error);
}
static void
gtk_link_content_class_init (GtkLinkContentClass *class)
{
GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
provider_class->ref_formats = gtk_link_content_ref_formats;
provider_class->get_value = gtk_link_content_get_value;
}
static void
gtk_link_content_init (GtkLinkContent *content)
{
}
static void
gtk_link_button_init (GtkLinkButton *link_button)
{
GtkStyleContext *context;
GdkContentFormats *targets;
GtkGesture *gesture;
GdkContentProvider *content;
GtkDragSource *source;
gtk_button_set_relief (GTK_BUTTON (link_button), GTK_RELIEF_NONE);
gtk_widget_set_state_flags (GTK_WIDGET (link_button), GTK_STATE_FLAG_LINK, FALSE);
gtk_widget_set_has_tooltip (GTK_WIDGET (link_button), TRUE);
g_signal_connect (link_button, "drag-data-get",
G_CALLBACK (gtk_link_button_drag_data_get_cb), NULL);
g_signal_connect (link_button, "query-tooltip",
G_CALLBACK (gtk_link_button_query_tooltip_cb), NULL);
/* enable drag source */
targets = gdk_content_formats_new (link_drop_types, G_N_ELEMENTS (link_drop_types));
gtk_drag_source_set (GTK_WIDGET (link_button),
GDK_BUTTON1_MASK,
targets,
GDK_ACTION_COPY);
gdk_content_formats_unref (targets);
gtk_drag_source_set_icon_name (GTK_WIDGET (link_button), "text-x-generic");
source = gtk_drag_source_new ();
content = g_object_new (GTK_TYPE_LINK_CONTENT, NULL);
GTK_LINK_CONTENT (content)->link = link_button;
gtk_drag_source_set_content (source, content);
g_object_unref (content);
gtk_widget_add_controller (GTK_WIDGET (link_button), GTK_EVENT_CONTROLLER (source));
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), FALSE);
@@ -449,26 +511,6 @@ gtk_link_button_popup_menu (GtkWidget *widget)
return TRUE;
}
static void
gtk_link_button_drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection,
gpointer user_data)
{
GtkLinkButton *link_button = GTK_LINK_BUTTON (widget);
GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button);
gchar *uri;
uri = g_strdup_printf ("%s\r\n", priv->uri);
gtk_selection_data_set (selection,
gtk_selection_data_get_target (selection),
8,
(guchar *) uri,
strlen (uri));
g_free (uri);
}
/**
* gtk_link_button_new:
* @uri: a valid URI
+10 -20
View File
@@ -25,7 +25,7 @@
#include "gtkbuildable.h"
#include "gtkcontainerprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkgestureclick.h"
#include "gtkintl.h"
#include "gtkmain.h"
@@ -264,8 +264,6 @@ static void gtk_list_box_size_allocate (GtkWidget
int width,
int height,
int baseline);
static void gtk_list_box_drag_leave (GtkWidget *widget,
GdkDrop *drop);
static void gtk_list_box_activate_cursor_row (GtkListBox *box);
static void gtk_list_box_toggle_cursor_row (GtkListBox *box);
static void gtk_list_box_move_cursor (GtkListBox *box,
@@ -452,7 +450,6 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
widget_class->get_request_mode = gtk_list_box_get_request_mode;
widget_class->measure = gtk_list_box_measure;
widget_class->size_allocate = gtk_list_box_size_allocate;
widget_class->drag_leave = gtk_list_box_drag_leave;
container_class->add = gtk_list_box_add;
container_class->remove = gtk_list_box_remove;
container_class->forall = gtk_list_box_forall;
@@ -1126,8 +1123,8 @@ gtk_list_box_get_selection_mode (GtkListBox *box)
/**
* gtk_list_box_set_filter_func:
* @box: a #GtkListBox
* @filter_func: (closure user_data) (allow-none): callback that lets you filter which rows to show
* @user_data: user data passed to @filter_func
* @filter_func: (allow-none): callback that lets you filter which rows to show
* @user_data: (closure): user data passed to @filter_func
* @destroy: destroy notifier for @user_data
*
* By setting a filter function on the @box one can decide dynamically which
@@ -1166,8 +1163,8 @@ gtk_list_box_set_filter_func (GtkListBox *box,
/**
* gtk_list_box_set_header_func:
* @box: a #GtkListBox
* @update_header: (closure user_data) (allow-none): callback that lets you add row headers
* @user_data: user data passed to @update_header
* @update_header: (allow-none): callback that lets you add row headers
* @user_data: (closure): user data passed to @update_header
* @destroy: destroy notifier for @user_data
*
* By setting a header function on the @box one can dynamically add headers
@@ -1321,8 +1318,8 @@ gtk_list_box_invalidate_headers (GtkListBox *box)
/**
* gtk_list_box_set_sort_func:
* @box: a #GtkListBox
* @sort_func: (closure user_data) (allow-none): the sort function
* @user_data: user data passed to @sort_func
* @sort_func: (allow-none): the sort function
* @user_data: (closure): user data passed to @sort_func
* @destroy: destroy notifier for @user_data
*
* By setting a sort function on the @box one can dynamically reorder the rows
@@ -2728,7 +2725,7 @@ gtk_list_box_drag_unhighlight_row (GtkListBox *box)
if (priv->drag_highlighted_row == NULL)
return;
gtk_drag_unhighlight (GTK_WIDGET (priv->drag_highlighted_row));
gtk_widget_unset_state_flags (GTK_WIDGET (priv->drag_highlighted_row), GTK_STATE_FLAG_DROP_ACTIVE);
g_clear_object (&priv->drag_highlighted_row);
}
@@ -2757,17 +2754,10 @@ gtk_list_box_drag_highlight_row (GtkListBox *box,
return;
gtk_list_box_drag_unhighlight_row (box);
gtk_drag_highlight (GTK_WIDGET (row));
gtk_widget_set_state_flags (GTK_WIDGET (row), GTK_STATE_FLAG_DROP_ACTIVE, FALSE);
priv->drag_highlighted_row = g_object_ref (row);
}
static void
gtk_list_box_drag_leave (GtkWidget *widget,
GdkDrop *drop)
{
gtk_list_box_drag_unhighlight_row (GTK_LIST_BOX (widget));
}
static void
gtk_list_box_activate_cursor_row (GtkListBox *box)
{
@@ -3591,7 +3581,7 @@ gtk_list_box_check_model_compat (GtkListBox *box)
* @model: (nullable): the #GListModel to be bound to @box
* @create_widget_func: (nullable): a function that creates widgets for items
* or %NULL in case you also passed %NULL as @model
* @user_data: user data passed to @create_widget_func
* @user_data: (closure): user data passed to @create_widget_func
* @user_data_free_func: function for freeing @user_data
*
* Binds @model to @box.
+74 -17
View File
@@ -116,7 +116,7 @@
#include "gtkaccelmapprivate.h"
#include "gtkbox.h"
#include "gtkdebug.h"
#include "gtkdndprivate.h"
#include "gtkdragdestprivate.h"
#include "gtkmain.h"
#include "gtkmediafileprivate.h"
#include "gtkmodulesprivate.h"
@@ -1044,6 +1044,7 @@ gtk_main (void)
typedef struct {
GMainLoop *store_loop;
guint n_clipboards;
guint timeout_id;
} ClipboardStore;
static void
@@ -1071,16 +1072,26 @@ clipboard_store_finished (GObject *source,
g_main_loop_quit (store->store_loop);
}
static gboolean
sync_timed_out_cb (ClipboardStore *store)
{
store->timeout_id = 0;
g_main_loop_quit (store->store_loop);
return G_SOURCE_REMOVE;
}
void
gtk_main_sync (void)
{
ClipboardStore store = { NULL, };
GSList *displays, *l;
GCancellable *cancel;
guint store_timeout;
/* Try storing all clipboard data we have */
displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
if (displays == NULL)
return;
cancel = g_cancellable_new ();
for (l = displays; l; l = l->next)
@@ -1098,17 +1109,16 @@ gtk_main_sync (void)
g_slist_free (displays);
store.store_loop = g_main_loop_new (NULL, TRUE);
store_timeout = g_timeout_add_seconds (10, (GSourceFunc) g_main_loop_quit, store.store_loop);
g_source_set_name_by_id (store_timeout, "[gtk] gtk_main_sync clipboard store timeout");
store.timeout_id = g_timeout_add_seconds (10, (GSourceFunc) sync_timed_out_cb, &store);
g_source_set_name_by_id (store.timeout_id, "[gtk] gtk_main_sync clipboard store timeout");
if (g_main_loop_is_running (store.store_loop))
g_main_loop_run (store.store_loop);
g_cancellable_cancel (cancel);
g_object_unref (cancel);
g_source_remove (store_timeout);
g_main_loop_unref (store.store_loop);
store.store_loop = NULL;
g_clear_handle_id (&store.timeout_id, g_source_remove);
g_clear_pointer (&store.store_loop, g_main_loop_unref);
/* Synchronize the recent manager singleton */
_gtk_recent_manager_sync ();
@@ -1676,6 +1686,20 @@ is_focus_event (GdkEvent *event)
}
}
static gboolean
is_dnd_event (GdkEvent *event)
{
switch ((guint) event->any.type)
{
case GDK_DRAG_ENTER:
case GDK_DRAG_LEAVE:
case GDK_DRAG_MOTION:
case GDK_DROP_START:
return TRUE;
default:
return FALSE;
}
}
static inline void
set_widget_active_state (GtkWidget *target,
@@ -1818,6 +1842,25 @@ handle_key_event (GdkEvent *event)
return focus_widget ? focus_widget : event_widget;
}
static GtkWidget *
handle_dnd_event (GdkEvent *event)
{
GtkWidget *event_widget;
GtkWidget *target;
gdouble x, y;
GtkWidget *native;
event_widget = gtk_get_event_widget (event);
if (!gdk_event_get_coords (event, &x, &y))
return event_widget;
native = GTK_WIDGET (gtk_widget_get_native (event_widget));
target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT);
return target;
}
/**
* gtk_main_do_event:
* @event: An event to process (normally passed by GDK)
@@ -1914,6 +1957,8 @@ gtk_main_do_event (GdkEvent *event)
goto cleanup;
}
}
else if (is_dnd_event (event))
target_widget = handle_dnd_event (event);
if (!target_widget)
goto cleanup;
@@ -2028,12 +2073,17 @@ gtk_main_do_event (GdkEvent *event)
/* Crossing event propagation happens during picking */
break;
case GDK_DRAG_ENTER:
case GDK_DRAG_LEAVE:
case GDK_DRAG_MOTION:
case GDK_DROP_START:
_gtk_drag_dest_handle_event (target_widget, event);
if (gtk_propagate_event (target_widget, event))
break;
G_GNUC_FALLTHROUGH;
case GDK_DRAG_ENTER:
case GDK_DRAG_LEAVE:
gtk_drag_dest_handle_event (target_widget, event);
break;
case GDK_EVENT_LAST:
default:
g_assert_not_reached ();
@@ -2623,14 +2673,19 @@ propagate_event_down (GtkWidget *widget,
return handled_event;
}
void
gboolean
gtk_propagate_event_internal (GtkWidget *widget,
GdkEvent *event,
GtkWidget *topmost)
{
/* Propagate the event down and up */
if (!propagate_event_down (widget, event, topmost))
propagate_event_up (widget, event, topmost);
if (propagate_event_down (widget, event, topmost))
return TRUE;
if (propagate_event_up (widget, event, topmost))
return TRUE;
return FALSE;
}
/**
@@ -2657,8 +2712,10 @@ gtk_propagate_event_internal (GtkWidget *widget,
* certainly better ways to achieve your goals. For example, use
* gtk_widget_queue_draw() instead
* of making up expose events.
*
* Returns: %TRUE if the event was handled
*/
void
gboolean
gtk_propagate_event (GtkWidget *widget,
GdkEvent *event)
{
@@ -2666,8 +2723,8 @@ gtk_propagate_event (GtkWidget *widget,
GtkWidget *event_widget, *topmost = NULL;
GdkDevice *device;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (event != NULL);
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
event_widget = gtk_get_event_widget (event);
window_group = gtk_main_get_window_group (event_widget);
@@ -2679,5 +2736,5 @@ gtk_propagate_event (GtkWidget *widget,
if (!topmost)
topmost = gtk_window_group_get_current_grab (window_group);
gtk_propagate_event_internal (widget, event, topmost);
return gtk_propagate_event_internal (widget, event, topmost);
}
+1 -1
View File
@@ -160,7 +160,7 @@ GtkWidget *gtk_get_event_target_with_type (GdkEvent *event,
GType type);
GDK_AVAILABLE_IN_ALL
void gtk_propagate_event (GtkWidget *widget,
gboolean gtk_propagate_event (GtkWidget *widget,
GdkEvent *event);
+2 -2
View File
@@ -424,7 +424,7 @@ gtk_map_list_model_augment (GtkRbTree *map,
* @item_type: the #GType to use as the model's item type
* @model: (allow-none): The model to map or %NULL for none
* @map_func: (allow-none): map function or %NULL to not map items
* @user_data: user data passed to @map_func
* @user_data: (closure): user data passed to @map_func
* @user_destroy: destroy notifier for @user_data
*
* Creates a new #GtkMapListModel for the given arguments.
@@ -501,7 +501,7 @@ gtk_map_list_model_init_items (GtkMapListModel *self)
* gtk_map_list_model_set_map_func:
* @self: a #GtkMapListModel
* @map_func: (allow-none): map function or %NULL to not map items
* @user_data: user data passed to @map_func
* @user_data: (closure): user data passed to @map_func
* @user_destroy: destroy notifier for @user_data
*
* Sets the function used to map items. The function will be called whenever
+1
View File
@@ -58,6 +58,7 @@ OBJECT:VOID
STRING:DOUBLE
STRING:STRING
VOID:BOOLEAN,BOOLEAN,BOOLEAN
VOID:BOXED
VOID:BOXED,BOXED
VOID:BOXED,BOXED,POINTER
VOID:BOXED,ENUM
+1 -1
View File
@@ -1035,7 +1035,7 @@ gtk_menu_button_add_child (GtkMenuButton *menu_button,
* @func: (nullable): function to call when a popuop is about to
* be shown, but none has been provided via other means, or %NULL
* to reset to default behavior.
* @user_data: (nullable): user data to pass to @callback
* @user_data: (closure): user data to pass to @func.
* @destroy_notify: (nullable): destroy notify for @user_data
*
* Sets @func to be called when a popup is about to be shown.
-1
View File
@@ -583,7 +583,6 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item,
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (box->item_box)), "inline-buttons");
spacer = gtk_icon_new ("none");
gtk_icon_set_image (GTK_ICON (spacer), GTK_CSS_IMAGE_BUILTIN_NONE);
gtk_container_add (GTK_CONTAINER (box->item_box), spacer);
gtk_size_group_add_widget (box->indicators, spacer);
+10
View File
@@ -377,6 +377,16 @@ gtk_menu_tool_button_set_popover (GtkMenuToolButton *button,
g_object_notify (G_OBJECT (button), "popover");
}
/**
* gtk_menu_tool_button_get_popover:
* @menu_button: a #GtkMenuToolButton
*
* Returns the #GtkPopover that pops out of the button.
* If the button is not using a #GtkPopover, this function
* returns %NULL.
*
* Returns: (nullable) (transfer none): a #GtkPopover or %NULL
**/
GtkWidget *
gtk_menu_tool_button_get_popover (GtkMenuToolButton *button)
{
-15
View File
@@ -352,12 +352,6 @@ update_end_indicator (GtkModelButton *self)
if (!self->end_indicator)
return;
if (self->role == GTK_BUTTON_ROLE_NORMAL &&
(self->menu_name != NULL || self->popover != NULL))
{
gtk_icon_set_image (GTK_ICON (self->end_indicator), GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT);
}
context = gtk_widget_get_style_context (self->end_indicator);
if (is_ltr)
@@ -398,15 +392,6 @@ update_start_indicator (GtkModelButton *self)
if (!self->start_indicator)
return;
if (self->role == GTK_BUTTON_ROLE_CHECK)
gtk_icon_set_image (GTK_ICON (self->start_indicator), GTK_CSS_IMAGE_BUILTIN_CHECK);
else if (self->role == GTK_BUTTON_ROLE_RADIO)
gtk_icon_set_image (GTK_ICON (self->start_indicator), GTK_CSS_IMAGE_BUILTIN_OPTION);
else if (self->role == GTK_BUTTON_ROLE_TITLE)
gtk_icon_set_image (GTK_ICON (self->start_indicator), GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT);
else
gtk_icon_set_image (GTK_ICON (self->start_indicator), GTK_CSS_IMAGE_BUILTIN_NONE);
gtk_widget_set_state_flags (self->start_indicator, get_start_indicator_state (self), TRUE);
context = gtk_widget_get_style_context (self->start_indicator);
+178 -191
View File
@@ -33,8 +33,8 @@
#include "gtkbuildable.h"
#include "gtkbutton.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkdnd.h"
#include "gtkdragdest.h"
#include "gtkdragicon.h"
#include "gtkeventcontrollermotion.h"
#include "gtkgestureclick.h"
#include "gtkgizmoprivate.h"
@@ -52,6 +52,10 @@
#include "gtktypebuiltins.h"
#include "gtkwidgetpath.h"
#include "gtkwidgetprivate.h"
#include "gtkdragsource.h"
#include "gtkwidgetpaintable.h"
#include "gtkselectionprivate.h"
#include "gtknative.h"
#include "a11y/gtknotebookaccessible.h"
@@ -234,7 +238,6 @@ struct _GtkNotebookPrivate
GtkNotebookPage *detached_tab;
GdkContentFormats *source_targets;
GtkWidget *action_widget[N_ACTION_WIDGETS];
GtkWidget *dnd_child;
GtkWidget *menu;
GtkWidget *menu_box;
@@ -695,29 +698,22 @@ static gboolean gtk_notebook_focus (GtkWidget *widget,
GtkDirectionType direction);
/*** Drag and drop Methods ***/
static void gtk_notebook_drag_begin (GtkWidget *widget,
GdkDrag *drag);
static void gtk_notebook_drag_end (GtkWidget *widget,
GdkDrag *drag);
static gboolean gtk_notebook_drag_failed (GtkWidget *widget,
GdkDrag *drag,
GtkDragResult result);
static gboolean gtk_notebook_drag_motion (GtkWidget *widget,
static void gtk_notebook_dnd_finished_cb (GdkDrag *drag,
GtkWidget *widget);
static void gtk_notebook_drag_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkWidget *widget);
static void gtk_notebook_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
static void gtk_notebook_drag_leave (GtkWidget *widget,
GdkDrop *drop);
static gboolean gtk_notebook_drag_drop (GtkWidget *widget,
int x,
int y);
static void gtk_notebook_drag_leave (GtkDropTarget *dest);
static gboolean gtk_notebook_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y);
static void gtk_notebook_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data);
static void gtk_notebook_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *data);
int x,
int y);
static GBytes * gtk_notebook_drag_data_get (const char *mime_type,
gpointer data);
/*** GtkContainer Methods ***/
static void gtk_notebook_add (GtkContainer *container,
@@ -964,14 +960,6 @@ gtk_notebook_class_init (GtkNotebookClass *class)
widget_class->grab_notify = gtk_notebook_grab_notify;
widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
widget_class->focus = gtk_notebook_focus;
widget_class->drag_begin = gtk_notebook_drag_begin;
widget_class->drag_end = gtk_notebook_drag_end;
widget_class->drag_motion = gtk_notebook_drag_motion;
widget_class->drag_leave = gtk_notebook_drag_leave;
widget_class->drag_drop = gtk_notebook_drag_drop;
widget_class->drag_data_get = gtk_notebook_drag_data_get;
widget_class->drag_data_received = gtk_notebook_drag_data_received;
widget_class->drag_failed = gtk_notebook_drag_failed;
widget_class->compute_expand = gtk_notebook_compute_expand;
container_class->add = gtk_notebook_add;
@@ -1306,6 +1294,7 @@ gtk_notebook_init (GtkNotebook *notebook)
GtkEventController *controller;
GtkGesture *gesture;
GtkLayoutManager *layout;
GtkDropTarget *dest;
gtk_widget_set_can_focus (GTK_WIDGET (notebook), TRUE);
@@ -1337,14 +1326,6 @@ gtk_notebook_init (GtkNotebook *notebook)
priv->detached_tab = NULL;
priv->has_scrolled = FALSE;
targets = gdk_content_formats_new (dst_notebook_targets, G_N_ELEMENTS (dst_notebook_targets));
gtk_drag_dest_set (GTK_WIDGET (notebook), 0,
targets,
GDK_ACTION_MOVE);
gdk_content_formats_unref (targets);
gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
priv->header_widget = g_object_new (GTK_TYPE_BOX,
"css-name", "header",
NULL);
@@ -1366,6 +1347,14 @@ gtk_notebook_init (GtkNotebook *notebook)
gtk_widget_set_vexpand (priv->stack_widget, TRUE);
gtk_widget_set_parent (priv->stack_widget, GTK_WIDGET (notebook));
targets = gdk_content_formats_new (dst_notebook_targets, G_N_ELEMENTS (dst_notebook_targets));
dest = gtk_drop_target_new (targets, GDK_ACTION_MOVE);
g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_notebook_drag_motion), NULL);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_notebook_drag_leave), NULL);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_notebook_drag_drop), NULL);
gtk_widget_add_controller (GTK_WIDGET (priv->tabs_widget), GTK_EVENT_CONTROLLER (dest));
gdk_content_formats_unref (targets);
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), GTK_PHASE_CAPTURE);
@@ -1835,7 +1824,6 @@ gtk_notebook_get_property (GObject *object,
* gtk_notebook_drag_motion
* gtk_notebook_drag_drop
* gtk_notebook_drag_data_get
* gtk_notebook_drag_data_received
*/
static void
remove_switch_tab_timer (GtkNotebook *notebook)
@@ -2881,12 +2869,43 @@ gtk_notebook_motion (GtkEventController *controller,
if (page->detachable &&
check_threshold (notebook, priv->mouse_x, priv->mouse_y))
{
GdkSurface *surface;
GdkDevice *device;
GdkContentProvider *content;
GdkDrag *drag;
GdkPaintable *paintable;
priv->detached_tab = priv->cur_page;
gtk_drag_begin (widget,
gtk_get_current_event_device (),
priv->source_targets, GDK_ACTION_MOVE,
priv->drag_begin_x, priv->drag_begin_y);
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (notebook)));
device = gtk_get_current_event_device ();
content = gdk_content_provider_new_with_formats (priv->source_targets,
gtk_notebook_drag_data_get,
widget);
drag = gdk_drag_begin (surface, device, content, GDK_ACTION_MOVE, priv->drag_begin_x, priv->drag_begin_y);
g_object_unref (content);
g_signal_connect (drag, "dnd-finished", G_CALLBACK (gtk_notebook_dnd_finished_cb), notebook);
g_signal_connect (drag, "cancel", G_CALLBACK (gtk_notebook_drag_cancel_cb), notebook);
paintable = gtk_widget_paintable_new (priv->detached_tab->tab_widget);
gtk_drag_icon_set_from_paintable (drag, paintable, -2, -2);
g_object_unref (paintable);
if (priv->dnd_timer)
{
g_source_remove (priv->dnd_timer);
priv->dnd_timer = 0;
}
priv->operation = DRAG_OPERATION_DETACH;
tab_drag_end (notebook, priv->cur_page);
g_object_set_data (G_OBJECT (drag), "gtk-notebook-drag-origin", notebook);
g_object_unref (drag);
return;
}
@@ -3088,46 +3107,8 @@ update_arrow_nodes (GtkNotebook *notebook)
}
static void
gtk_notebook_drag_begin (GtkWidget *widget,
GdkDrag *drag)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
graphene_rect_t bounds;
GtkWidget *tab_label;
if (priv->dnd_timer)
{
g_source_remove (priv->dnd_timer);
priv->dnd_timer = 0;
}
g_assert (priv->cur_page != NULL);
priv->operation = DRAG_OPERATION_DETACH;
tab_label = priv->detached_tab->tab_label;
tab_drag_end (notebook, priv->cur_page);
g_object_ref (tab_label);
gtk_widget_unparent (tab_label);
priv->dnd_child = tab_label;
if (gtk_widget_compute_bounds (priv->dnd_child, priv->dnd_child, &bounds))
gtk_widget_set_size_request (priv->dnd_child,
ceilf (bounds.size.width),
ceilf (bounds.size.height));
gtk_style_context_add_class (gtk_widget_get_style_context (priv->dnd_child), "background");
gtk_drag_set_icon_widget (drag, tab_label, -2, -2);
g_object_set_data (G_OBJECT (priv->dnd_child), "drag-context", drag);
g_object_unref (tab_label);
}
static void
gtk_notebook_drag_end (GtkWidget *widget,
GdkDrag *drag)
gtk_notebook_dnd_finished_cb (GdkDrag *drag,
GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
@@ -3148,17 +3129,9 @@ gtk_notebook_drag_end (GtkWidget *widget,
}
else if (priv->detached_tab)
{
gtk_widget_set_size_request (priv->dnd_child, -1, -1);
g_object_ref (priv->dnd_child);
gtk_widget_unparent (priv->dnd_child);
gtk_widget_set_parent (priv->dnd_child, priv->detached_tab->tab_widget);
g_object_unref (priv->dnd_child);
gtk_notebook_switch_page (notebook, priv->detached_tab);
}
gtk_style_context_remove_class (gtk_widget_get_style_context (priv->dnd_child), "background");
priv->dnd_child = NULL;
priv->operation = DRAG_OPERATION_NONE;
}
@@ -3169,17 +3142,17 @@ gtk_notebook_create_window (GtkNotebook *notebook,
return NULL;
}
static gboolean
gtk_notebook_drag_failed (GtkWidget *widget,
GdkDrag *drag,
GtkDragResult result)
static void
gtk_notebook_drag_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
priv->rootwindow_drop = FALSE;
if (result == GTK_DRAG_RESULT_NO_TARGET)
if (reason == GDK_DRAG_CANCEL_NO_TARGET)
{
GtkNotebook *dest_notebook = NULL;
@@ -3188,11 +3161,7 @@ gtk_notebook_drag_failed (GtkWidget *widget,
if (dest_notebook)
do_detach_tab (notebook, dest_notebook, priv->detached_tab->child);
return TRUE;
}
return FALSE;
}
static gboolean
@@ -3219,19 +3188,20 @@ gtk_notebook_switch_tab_timeout (gpointer data)
return FALSE;
}
static gboolean
gtk_notebook_drag_motion (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
static void
gtk_notebook_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y)
{
GtkWidget *tabs = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
GtkWidget *widget = gtk_widget_get_ancestor (tabs, GTK_TYPE_NOTEBOOK);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
graphene_rect_t position;
GtkNotebookArrow arrow;
GdkAtom target, tab_target;
GList *tab;
gboolean retval = FALSE;
arrow = gtk_notebook_get_arrow (notebook, x, y);
if (arrow != ARROW_NONE)
@@ -3240,41 +3210,46 @@ gtk_notebook_drag_motion (GtkWidget *widget,
gtk_notebook_set_scroll_timer (notebook);
gdk_drop_status (drop, 0);
retval = TRUE;
goto out;
}
stop_scrolling (notebook);
target = gtk_drag_dest_find_target (widget, drop, NULL);
target = gtk_drop_target_find_mimetype (dest);
tab_target = g_intern_static_string ("GTK_NOTEBOOK_TAB");
if (target == tab_target)
{
GQuark group, source_group;
GtkNotebook *source;
GtkWidget *source_child;
GdkDrag *drag = gdk_drop_get_drag (drop);
retval = TRUE;
source = GTK_NOTEBOOK (gtk_drag_get_source_widget (gdk_drop_get_drag (drop)));
g_assert (source->priv->cur_page != NULL);
source_child = source->priv->cur_page->child;
group = notebook->priv->group;
source_group = source->priv->group;
if (group != 0 && group == source_group &&
!(widget == source_child ||
gtk_widget_is_ancestor (widget, source_child)))
if (!drag)
{
gdk_drop_status (drop, GDK_ACTION_MOVE);
goto out;
gdk_drop_status (drop, 0);
}
else
{
/* it's a tab, but doesn't share
* ID with this notebook */
gdk_drop_status (drop, 0);
GtkNotebook *source = GTK_NOTEBOOK (g_object_get_data (G_OBJECT (drag), "gtk-notebook-drag-origin"));
g_assert (source->priv->cur_page != NULL);
source_child = source->priv->cur_page->child;
group = notebook->priv->group;
source_group = source->priv->group;
if (group != 0 && group == source_group &&
!(widget == source_child ||
gtk_widget_is_ancestor (widget, source_child)))
{
gdk_drop_status (drop, GDK_ACTION_MOVE);
goto out;
}
else
{
/* it's a tab, but doesn't share
* ID with this notebook */
gdk_drop_status (drop, 0);
}
}
}
@@ -3285,8 +3260,6 @@ gtk_notebook_drag_motion (GtkWidget *widget,
priv->mouse_x = x;
priv->mouse_y = y;
retval = TRUE;
if (tab != priv->switch_tab)
remove_switch_tab_timer (notebook);
@@ -3303,40 +3276,86 @@ gtk_notebook_drag_motion (GtkWidget *widget,
remove_switch_tab_timer (notebook);
}
out:
return retval;
out:;
}
static void
gtk_notebook_drag_leave (GtkWidget *widget,
GdkDrop *drop)
gtk_notebook_drag_leave (GtkDropTarget *dest)
{
GtkWidget *tabs = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
GtkWidget *widget = gtk_widget_get_ancestor (tabs, GTK_TYPE_NOTEBOOK);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
remove_switch_tab_timer (notebook);
stop_scrolling (notebook);
}
static gboolean
gtk_notebook_drag_drop (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y)
static void
got_page (GObject *source,
GAsyncResult *result,
gpointer data)
{
GtkNotebook *notebook = GTK_NOTEBOOK (data);
GdkDrop *drop = GDK_DROP (source);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget;
GInputStream *stream;
const char *mime_type;
source_widget = GTK_WIDGET (drag ? g_object_get_data (G_OBJECT (drag), "gtk-notebook-drag-origin") : NULL);
stream = gdk_drop_read_finish (drop, result, &mime_type, NULL);
if (stream)
{
GBytes *bytes;
GtkWidget **child;
bytes = g_input_stream_read_bytes (stream, sizeof (gpointer), NULL, NULL);
child = (gpointer)g_bytes_get_data (bytes, NULL);
do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child);
gdk_drop_finish (drop, GDK_ACTION_MOVE);
g_bytes_unref (bytes);
g_object_unref (stream);
}
else
gdk_drop_finish (drop, 0);
}
static gboolean
gtk_notebook_drag_drop (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y)
{
GtkWidget *tabs = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
GtkWidget *widget = gtk_widget_get_ancestor (tabs, GTK_TYPE_NOTEBOOK);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GdkDrag *drag = gdk_drop_get_drag (drop);
GtkWidget *source_widget;
GdkAtom target, tab_target;
target = gtk_drag_dest_find_target (widget, drop, NULL);
source_widget = GTK_WIDGET (drag ? g_object_get_data (G_OBJECT (drag), "gtk-notebook-drag-origin") : NULL);
target = gtk_drop_target_find_mimetype (dest);
tab_target = g_intern_static_string ("GTK_NOTEBOOK_TAB");
if (target == tab_target)
if (GTK_IS_NOTEBOOK (source_widget) &&
target == tab_target &&
(gdk_drop_get_actions (drop) & GDK_ACTION_MOVE))
{
notebook->priv->mouse_x = x;
notebook->priv->mouse_y = y;
gtk_drag_get_data (widget, drop, target);
gdk_drop_read_async (drop, (const char *[]) { "GTK_NOTEBOOK_TAB", NULL }, G_PRIORITY_DEFAULT, NULL, got_page, notebook);
return TRUE;
}
gdk_drop_finish (drop, 0);
return FALSE;
}
@@ -3419,57 +3438,32 @@ do_detach_tab (GtkNotebook *from,
gtk_notebook_set_current_page (to, page_num);
}
static void
gtk_notebook_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data)
static GBytes *
gtk_notebook_drag_data_get (const char *mime_type,
gpointer data)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebook *notebook = GTK_NOTEBOOK (data);
GtkNotebookPrivate *priv = notebook->priv;
GdkAtom target;
GtkSelectionData sdata = { 0, };
target = gtk_selection_data_get_target (data);
if (target == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
sdata.target = g_intern_string (mime_type);
if (sdata.target == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
{
gtk_selection_data_set (data,
target,
gtk_selection_data_set (&sdata,
sdata.target,
8,
(void*) &priv->detached_tab->child,
sizeof (gpointer));
priv->rootwindow_drop = FALSE;
}
else if (target == g_intern_static_string ("application/x-rootwindow-drop"))
else if (sdata.target == g_intern_static_string ("application/x-rootwindow-drop"))
{
gtk_selection_data_set (data, target, 8, NULL, 0);
gtk_selection_data_set (&sdata, sdata.target, 8, NULL, 0);
priv->rootwindow_drop = TRUE;
}
}
static void
gtk_notebook_drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *data)
{
GtkNotebook *notebook;
GdkDrag *drag;
GtkWidget *source_widget;
GtkWidget **child;
notebook = GTK_NOTEBOOK (widget);
drag = gdk_drop_get_drag (drop);
source_widget = gtk_drag_get_source_widget (drag);
if (source_widget &&
(gdk_drop_get_actions (drop) & GDK_ACTION_MOVE) &&
gtk_selection_data_get_target (data) == g_intern_static_string ("GTK_NOTEBOOK_TAB"))
{
child = (void*) gtk_selection_data_get_data (data);
do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child);
gdk_drop_finish (drop, GDK_ACTION_MOVE);
}
else
gdk_drop_finish (drop, 0);
return g_bytes_new_take (sdata.data, sdata.length);
}
/* Private GtkContainer Methods :
@@ -4249,17 +4243,8 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
}
if (priv->detached_tab == list->data)
{
priv->detached_tab = NULL;
priv->detached_tab = NULL;
if (priv->operation == DRAG_OPERATION_DETACH && !priv->remove_in_detach)
{
GdkDrag *drag;
drag = (GdkDrag *)g_object_get_data (G_OBJECT (priv->dnd_child), "drag-context");
gtk_drag_cancel (drag);
}
}
if (priv->switch_tab == list)
priv->switch_tab = NULL;
@@ -7099,15 +7084,17 @@ gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
* |[<!-- language="C" -->
* static void
* on_drag_data_received (GtkWidget *widget,
* GdkDrag *drag,
* GdkDrop *drop,
* GtkSelectionData *data,
* guint time,
* gpointer user_data)
* {
* GtkDrag *drag;
* GtkWidget *notebook;
* GtkWidget **child;
*
* notebook = gtk_drag_get_source_widget (drag);
* drag = gtk_drop_get_drag (drop);
* notebook = g_object_get_data (drag, "gtk-notebook-drag-origin");
* child = (void*) gtk_selection_data_get_data (data);
*
* // process_widget (*child);
+1 -4
View File
@@ -1326,10 +1326,7 @@ gtk_paned_render_handle (GtkGizmo *gizmo,
height = gtk_widget_get_height (widget);
if (width > 0 && height > 0)
gtk_css_style_snapshot_icon (style,
snapshot,
width, height,
GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR);
gtk_css_style_snapshot_icon (style, snapshot, width, height);
}
static void
+13 -35
View File
@@ -24,7 +24,6 @@
#include "gtkbox.h"
#include "gtkcssnodeprivate.h"
#include "gtkdnd.h"
#include "gtkdragsource.h"
#include "gtkicontheme.h"
#include "gtkimage.h"
@@ -37,6 +36,7 @@
#include "gtkwidgetpath.h"
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkdragsource.h"
typedef struct
{
@@ -1240,15 +1240,8 @@ set_button_image (GtkPathBar *path_bar,
static void
button_data_free (ButtonData *button_data)
{
if (button_data->file)
g_object_unref (button_data->file);
button_data->file = NULL;
g_clear_object (&button_data->file);
g_free (button_data->dir_name);
button_data->dir_name = NULL;
button_data->button = NULL;
g_free (button_data);
}
@@ -1312,25 +1305,6 @@ find_button_type (GtkPathBar *path_bar,
return NORMAL_BUTTON;
}
static void
button_drag_data_get_cb (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
gpointer data)
{
ButtonData *button_data;
char *uris[2];
button_data = data;
uris[0] = g_file_get_uri (button_data->file);
uris[1] = NULL;
gtk_selection_data_set_uris (selection_data, uris);
g_free (uris[0]);
}
static ButtonData *
make_directory_button (GtkPathBar *path_bar,
const char *dir_name,
@@ -1341,6 +1315,9 @@ make_directory_button (GtkPathBar *path_bar,
AtkObject *atk_obj;
GtkWidget *child = NULL;
ButtonData *button_data;
GValue value = G_VALUE_INIT;
GdkContentProvider *content;
GtkDragSource *source;
file_is_hidden = !! file_is_hidden;
/* Is it a special button? */
@@ -1387,13 +1364,14 @@ make_directory_button (GtkPathBar *path_bar,
g_object_weak_ref (G_OBJECT (button_data->button),
(GWeakNotify) button_data_free, button_data);
gtk_drag_source_set (button_data->button,
GDK_BUTTON1_MASK,
NULL,
GDK_ACTION_COPY);
gtk_drag_source_add_uri_targets (button_data->button);
g_signal_connect (button_data->button, "drag-data-get",
G_CALLBACK (button_drag_data_get_cb), button_data);
g_value_init (&value, G_TYPE_FILE);
g_value_set_object (&value, button_data->file);
source = gtk_drag_source_new ();
content = gdk_content_provider_new_for_value (&value);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
gtk_widget_add_controller (button_data->button, GTK_EVENT_CONTROLLER (source));
g_value_unset (&value);
return button_data;
}
+126 -135
View File
@@ -52,7 +52,6 @@
#include "gtklistbox.h"
#include "gtkselection.h"
#include "gtkdragdest.h"
#include "gtkdnd.h"
#include "gtkseparator.h"
#include "gtkentry.h"
#include "gtkgesturelongpress.h"
@@ -63,6 +62,10 @@
#include "gtkgestureclick.h"
#include "gtkgesturedrag.h"
#include "gtknative.h"
#include "gtkdragsource.h"
#include "gtkdragicon.h"
#include "gtkwidgetpaintable.h"
#include "gtkselectionprivate.h"
/*< private >
* SECTION:gtkplacessidebar
@@ -309,16 +312,6 @@ enum {
DND_TEXT_URI_LIST
};
/* Target types for dragging from the shortcuts list */
static const char *dnd_source_targets[] = {
"DND_GTK_SIDEBAR_ROW"
};
/* Target types for dropping into the shortcuts list */
static const char *dnd_drop_targets [] = {
"DND_GTK_SIDEBAR_ROW"
};
G_DEFINE_TYPE (GtkPlacesSidebar, gtk_places_sidebar, GTK_TYPE_WIDGET);
static void
@@ -1641,21 +1634,25 @@ update_possible_drop_targets (GtkPlacesSidebar *sidebar,
g_list_free (rows);
}
static void drag_data_received_callback (GObject *source,
GAsyncResult *result,
gpointer user_data);
static gboolean
get_drag_data (GtkWidget *list_box,
GdkDrop *drop,
GtkDropTarget *dest,
GtkListBoxRow *row)
{
GdkAtom target;
target = gtk_drag_dest_find_target (list_box, drop, NULL);
target = gtk_drop_target_find_mimetype (dest);
if (target == NULL)
return FALSE;
if (row)
g_object_set_data_full (G_OBJECT (drop), "places-sidebar-row", g_object_ref (row), g_object_unref);
gtk_drag_get_data (list_box, drop, target);
g_object_set_data_full (G_OBJECT (dest), "places-sidebar-row", g_object_ref (row), g_object_unref);
gtk_drop_target_read_selection (dest, target, NULL, drag_data_received_callback, list_box);
return TRUE;
}
@@ -1678,7 +1675,8 @@ start_drop_feedback (GtkPlacesSidebar *sidebar,
GtkSidebarRow *row,
GdkDrag *drag)
{
if (sidebar->drag_data_info != DND_GTK_SIDEBAR_ROW)
if (sidebar->drag_data_received &&
sidebar->drag_data_info != DND_GTK_SIDEBAR_ROW)
{
gtk_sidebar_row_reveal (GTK_SIDEBAR_ROW (sidebar->new_bookmark_row));
/* If the state is permanent, don't change it. The application controls it. */
@@ -1719,48 +1717,22 @@ stop_drop_feedback (GtkPlacesSidebar *sidebar)
sidebar->drag_data_info = DND_UNKNOWN;
}
static void
drag_begin_callback (GtkWidget *widget,
GdkDrag *drag,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
GtkAllocation allocation;
GtkWidget *drag_widget;
gtk_widget_get_allocation (sidebar->drag_row, &allocation);
gtk_widget_hide (sidebar->drag_row);
drag_widget = GTK_WIDGET (gtk_sidebar_row_clone (GTK_SIDEBAR_ROW (sidebar->drag_row)));
sidebar->drag_row_height = allocation.height;
gtk_widget_set_size_request (drag_widget, allocation.width, allocation.height);
gtk_widget_set_opacity (drag_widget, 0.8);
gtk_drag_set_icon_widget (drag,
drag_widget,
sidebar->drag_row_x,
sidebar->drag_row_y);
}
static GtkWidget *
create_placeholder_row (GtkPlacesSidebar *sidebar)
{
return g_object_new (GTK_TYPE_SIDEBAR_ROW,
"placeholder", TRUE,
NULL);
return g_object_new (GTK_TYPE_SIDEBAR_ROW, "placeholder", TRUE, NULL);
}
static gboolean
drag_motion_callback (GtkWidget *widget,
GdkDrop *drop,
gint x,
gint y,
gpointer user_data)
static void
drag_motion_callback (GtkDropTarget *dest,
GdkDrop *drop,
gint x,
gint y,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
gint action;
GtkListBoxRow *row;
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
GtkPlacesSidebarPlaceType place_type;
gchar *drop_target_uri = NULL;
gint row_index;
@@ -1776,7 +1748,7 @@ drag_motion_callback (GtkWidget *widget,
/* Nothing to do if no drag data */
if (!sidebar->drag_data_received &&
!get_drag_data (sidebar->list_box, drop, row))
!get_drag_data (sidebar->list_box, dest, row))
goto out;
/* Nothing to do if the target is not valid drop destination */
@@ -1791,7 +1763,6 @@ drag_motion_callback (GtkWidget *widget,
if (sidebar->row_placeholder == NULL)
{
sidebar->row_placeholder = create_placeholder_row (sidebar);
gtk_widget_show (sidebar->row_placeholder);
g_object_ref_sink (sidebar->row_placeholder);
}
else if (GTK_WIDGET (row) == sidebar->row_placeholder)
@@ -1822,7 +1793,7 @@ drag_motion_callback (GtkWidget *widget,
* of the row, we need to increase the order-index.
*/
row_placeholder_index = row_index;
gtk_widget_translate_coordinates (widget, GTK_WIDGET (row),
gtk_widget_translate_coordinates (GTK_WIDGET (sidebar), GTK_WIDGET (row),
x, y,
&dest_x, &dest_y);
@@ -1879,12 +1850,7 @@ drag_motion_callback (GtkWidget *widget,
out:
start_drop_feedback (sidebar, GTK_SIDEBAR_ROW (row), drag);
g_signal_stop_emission_by_name (sidebar->list_box, "drag-motion");
gdk_drop_status (drop, action);
return TRUE;
}
/* Takes an array of URIs and turns it into a list of GFile */
@@ -1950,42 +1916,41 @@ drop_files_as_bookmarks (GtkPlacesSidebar *sidebar,
}
}
static void
drag_data_get_callback (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *data,
gpointer user_data)
static GBytes *
drag_data_get_callback (const char *mimetype,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
GdkAtom target = gtk_selection_data_get_target (data);
if (target == g_intern_static_string ("DND_GTK_SIDEBAR_ROW"))
{
gtk_selection_data_set (data,
target,
8,
(void*)&sidebar->drag_row,
sizeof (gpointer));
}
if (mimetype == g_intern_static_string ("DND_GTK_SIDEBAR_ROW"))
return g_bytes_new ((gpointer)&sidebar->drag_row, sizeof (gpointer));
return NULL;
}
static void
drag_data_received_callback (GtkWidget *list_box,
GdkDrop *drop,
GtkSelectionData *selection_data,
gpointer user_data)
drag_data_received_callback (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GtkDropTarget *dest = GTK_DROP_TARGET (source);
GtkWidget *list_box = user_data;
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (gtk_widget_get_ancestor (list_box, GTK_TYPE_PLACES_SIDEBAR));
GdkDrop *drop = gtk_drop_target_get_drop (dest);
GdkDrag *drag = gdk_drop_get_drag (drop);
gint target_order_index;
GtkPlacesSidebarPlaceType target_place_type;
GtkPlacesSidebarSectionType target_section_type;
gchar *target_uri;
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
GtkListBoxRow *target_row;
GdkDragAction real_action;
GtkSelectionData *selection_data;
selection_data = gtk_drop_target_read_selection_finish (dest, result, NULL);
if (!sidebar->drag_data_received)
{
if (gtk_selection_data_targets_include_uri (selection_data))
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("text/uri-list"))
{
gchar **uris;
@@ -2001,19 +1966,22 @@ drag_data_received_callback (GtkWidget *list_box,
{
sidebar->drag_list = NULL;
if (gtk_selection_data_get_target (selection_data) == g_intern_static_string ("DND_GTK_SIDEBAR_ROW"))
sidebar->drag_data_info = DND_GTK_SIDEBAR_ROW;
{
sidebar->drag_data_info = DND_GTK_SIDEBAR_ROW;
}
}
sidebar->drag_data_received = TRUE;
}
g_signal_stop_emission_by_name (list_box, "drag-data-received");
if (!sidebar->drop_occurred)
return;
goto out_free;
target_row = g_object_get_data (G_OBJECT (drop), "places-sidebar-row");
target_row = g_object_get_data (G_OBJECT (dest), "places-sidebar-row");
if (target_row == NULL)
return;
goto out_free;
if (!check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (target_row), drag))
goto out_free;
g_object_get (target_row,
"place-type", &target_place_type,
@@ -2021,12 +1989,8 @@ drag_data_received_callback (GtkWidget *list_box,
"order-index", &target_order_index,
"uri", &target_uri,
NULL);
real_action = 0;
if (!check_valid_drop_target (sidebar, GTK_SIDEBAR_ROW (target_row), gdk_drop_get_drag (drop)))
goto out;
if (sidebar->drag_data_info == DND_GTK_SIDEBAR_ROW)
{
GtkWidget **source_row;
@@ -2081,18 +2045,20 @@ drag_data_received_callback (GtkWidget *list_box,
out:
sidebar->drop_occurred = FALSE;
g_object_set_data (G_OBJECT (drop), "places-sidebar-row", NULL);
g_object_set_data (G_OBJECT (dest), "places-sidebar-row", NULL);
gdk_drop_finish (drop, real_action);
stop_drop_feedback (sidebar);
g_free (target_uri);
out_free:
gtk_selection_data_free (selection_data);
}
static void
drag_end_callback (GtkWidget *widget,
GdkDrag *drag,
gpointer user_data)
dnd_finished_cb (GdkDrag *drag,
GtkPlacesSidebar *sidebar)
{
stop_drop_feedback (GTK_PLACES_SIDEBAR (user_data));
stop_drop_feedback (sidebar);
}
/* This functions is called every time the drag source leaves
@@ -2105,8 +2071,8 @@ drag_end_callback (GtkWidget *widget,
* but that's not true, because this function is called also before drag_drop,
* which needs the data from the drag so we cannot free the drag data here.
* So now one could think we could just do nothing here, and wait for
* drag-end or drag-failed signals and just stop_drop_feedback there. But that
* is also not true, since when the drag comes from a diferent widget than the
* drag-end or drag-cancel signals and just stop_drop_feedback there. But that
* is also not true, since when the drag comes from a different widget than the
* sidebar, when the drag stops the last drag signal we receive is drag-leave.
* So here what we will do is restore the state of the sidebar as if no drag
* is being done (and if the application didnt request for permanent hints with
@@ -2114,9 +2080,9 @@ drag_end_callback (GtkWidget *widget,
* we build new drag data in drag_data_received.
*/
static void
drag_leave_callback (GtkWidget *widget,
GdkDrop *drop,
gpointer user_data)
drag_leave_callback (GtkDropTarget *dest,
GdkDrop *drop,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
@@ -2133,20 +2099,20 @@ drag_leave_callback (GtkWidget *widget,
}
static gboolean
drag_drop_callback (GtkWidget *list_box,
GdkDrop *drop,
gint x,
gint y,
gpointer user_data)
drag_drop_callback (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
gpointer user_data)
{
gboolean retval = FALSE;
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
gboolean retval = FALSE;
GtkListBoxRow *row;
row = gtk_list_box_get_row_at_y (GTK_LIST_BOX (sidebar->list_box), y);
sidebar->drop_occurred = TRUE;
retval = get_drag_data (sidebar->list_box, drop, row);
g_signal_stop_emission_by_name (sidebar->list_box, "drag-drop");
retval = get_drag_data (sidebar->list_box, dest, row);
return retval;
}
@@ -3778,6 +3744,13 @@ on_row_dragged (GtkGestureDrag *gesture,
{
gdouble start_x, start_y;
gint drag_x, drag_y;
GdkContentProvider *content;
GdkSurface *surface;
GdkDevice *device;
GtkAllocation allocation;
GtkWidget *drag_widget;
GdkPaintable *paintable;
GdkDrag *drag;
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
gtk_widget_translate_coordinates (GTK_WIDGET (row),
@@ -3787,10 +3760,35 @@ on_row_dragged (GtkGestureDrag *gesture,
sidebar->dragging_over = TRUE;
gtk_drag_begin (GTK_WIDGET (sidebar),
gtk_gesture_get_device (GTK_GESTURE (gesture)),
sidebar->source_targets, GDK_ACTION_MOVE,
drag_x, drag_y);
content = gdk_content_provider_new_with_formats (sidebar->source_targets,
drag_data_get_callback,
sidebar);
surface = gtk_native_get_surface (gtk_widget_get_native (GTK_WIDGET (sidebar)));
device = gtk_gesture_get_device (GTK_GESTURE (gesture));
drag = gdk_drag_begin (surface, device, content, GDK_ACTION_MOVE, drag_x, drag_y);
g_object_unref (content);
g_signal_connect (drag, "dnd-finished", G_CALLBACK (dnd_finished_cb), sidebar);
gtk_widget_get_allocation (sidebar->drag_row, &allocation);
gtk_widget_hide (sidebar->drag_row);
drag_widget = GTK_WIDGET (gtk_sidebar_row_clone (GTK_SIDEBAR_ROW (sidebar->drag_row)));
sidebar->drag_row_height = allocation.height;
gtk_widget_set_size_request (drag_widget, allocation.width, allocation.height);
gtk_widget_set_opacity (drag_widget, 0.8);
paintable = gtk_widget_paintable_new (drag_widget);
gtk_drag_icon_set_from_paintable (drag, paintable, sidebar->drag_row_x, sidebar->drag_row_y);
g_object_unref (paintable);
g_object_set_data_full (G_OBJECT (drag), "row-widget", drag_widget, (GDestroyNotify)gtk_widget_destroy);
g_object_unref (drag);
}
g_object_unref (sidebar);
@@ -4022,11 +4020,13 @@ shell_shows_desktop_changed (GtkSettings *settings,
static void
gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
{
GdkContentFormats *target_list;
GdkContentFormats *formats;
GtkDropTarget *dest;
gboolean show_desktop;
GtkStyleContext *context;
GtkEventController *controller;
GtkGesture *gesture;
GdkContentFormatsBuilder *builder;
sidebar->cancellable = g_cancellable_new ();
@@ -4079,31 +4079,22 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
gtk_widget_add_controller (GTK_WIDGET (sidebar), GTK_EVENT_CONTROLLER (gesture));
/* DND support */
gtk_drag_dest_set (sidebar->list_box,
0,
NULL,
GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
target_list = gdk_content_formats_new (dnd_drop_targets, G_N_ELEMENTS (dnd_drop_targets));
target_list = gtk_content_formats_add_uri_targets (target_list);
gtk_drag_dest_set_target_list (sidebar->list_box, target_list);
gdk_content_formats_unref (target_list);
sidebar->source_targets = gdk_content_formats_new (dnd_source_targets, G_N_ELEMENTS (dnd_source_targets));
sidebar->source_targets = gtk_content_formats_add_text_targets (sidebar->source_targets);
builder = gdk_content_formats_builder_new ();
gdk_content_formats_builder_add_mime_type (builder, "DND_GTK_SIDEBAR_ROW");
gdk_content_formats_builder_add_gtype (builder, GDK_TYPE_FILE_LIST);
formats = gdk_content_formats_builder_free_to_formats (builder);
dest = gtk_drop_target_new (formats, GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-motion", G_CALLBACK (drag_motion_callback), sidebar);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop_callback), sidebar);
g_signal_connect (dest, "drag-leave", G_CALLBACK (drag_leave_callback), sidebar);
gtk_widget_add_controller (sidebar->list_box, GTK_EVENT_CONTROLLER (dest));
builder = gdk_content_formats_builder_new ();
gdk_content_formats_builder_add_mime_type (builder, "DND_GTK_SIDEBAR_ROW");
gdk_content_formats_builder_add_gtype (builder, G_TYPE_STRING);
sidebar->source_targets = gdk_content_formats_builder_free_to_formats (builder);
g_signal_connect (sidebar->list_box, "drag-begin",
G_CALLBACK (drag_begin_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-motion",
G_CALLBACK (drag_motion_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-data-get",
G_CALLBACK (drag_data_get_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-data-received",
G_CALLBACK (drag_data_received_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-drop",
G_CALLBACK (drag_drop_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-end",
G_CALLBACK (drag_end_callback), sidebar);
g_signal_connect (sidebar->list_box, "drag-leave",
G_CALLBACK (drag_leave_callback), sidebar);
sidebar->drag_row = NULL;
sidebar->row_placeholder = NULL;
sidebar->dragging_over = FALSE;
+2 -1
View File
@@ -1482,7 +1482,8 @@ gtk_popover_set_relative_to (GtkPopover *popover,
if (priv->relative_to)
{
g_signal_connect (priv->relative_to, "size-allocate", G_CALLBACK (size_changed), popover);
g_signal_connect_object (priv->relative_to, "size-allocate",
G_CALLBACK (size_changed), popover, 0);
gtk_css_node_set_parent (gtk_widget_get_css_node (GTK_WIDGET (popover)),
gtk_widget_get_css_node (relative_to));
gtk_widget_set_parent (GTK_WIDGET (popover), relative_to);
+1 -1
View File
@@ -633,7 +633,7 @@ gtk_popover_menu_set_menu_model (GtkPopoverMenu *popover,
*
* Returns the menu model used to populate the popover.
*
* Returns: the menu model of @popover
* Returns: (transfer none): the menu model of @popover
*/
GMenuModel *
gtk_popover_menu_get_menu_model (GtkPopoverMenu *popover)
+1 -1
View File
@@ -693,7 +693,7 @@ gtk_print_job_get_property (GObject *object,
* gtk_print_job_send:
* @job: a GtkPrintJob
* @callback: function to call when the job completes or an error occurs
* @user_data: user data that gets passed to @callback
* @user_data: (closure): user data that gets passed to @callback
* @dnotify: destroy notify for @user_data
*
* Sends the print job off to the printer.
+1 -1
View File
@@ -460,7 +460,7 @@ gtk_print_settings_set_int (GtkPrintSettings *settings,
* gtk_print_settings_foreach:
* @settings: a #GtkPrintSettings
* @func: (scope call): the function to call
* @user_data: user data for @func
* @user_data: (closure): user data for @func
*
* Calls @func for each key-value pair of @settings.
*/
+1 -1
View File
@@ -90,7 +90,7 @@ gboolean _gtk_translate_keyboard_accel_state (GdkKeymap *keymap,
gint *level,
GdkModifierType *consumed_modifiers);
void gtk_propagate_event_internal (GtkWidget *widget,
gboolean gtk_propagate_event_internal (GtkWidget *widget,
GdkEvent *event,
GtkWidget *topmost);

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