Compare commits

..

264 Commits

Author SHA1 Message Date
Matthias Clasen
4ab0e7956e css: Reshuffle the inner loop of value computation
The loop over all properties in gtk_css_static_style_compute_values
is the inner loop of the css value computation, we hit it thousands
of times per frame. Rearrange things to make this faster, by avoiding
function calls, pulling the section handling out of the separate loop,
and handling the border-width special case in a neater way.

Before: 50 runs, min 12.45, max 20.419, avg 15.9414
After:  50 runs, min 12.622, max 21.195, avg 15.0449
2020-01-25 01:20:17 -05:00
Matthias Clasen
1eec7362b9 Adwaita: Fix some entry styling
This was accidentally broken when parent selectors
were introduced here.
2020-01-24 21:01:42 -05:00
Matthias Clasen
a105256611 GtkSpinner: Pay attention to style changes
Make GtkIcon redraw and resize when style changes
require it.
2020-01-24 20:55:42 -05:00
Matthias Clasen
2ee04ee8ed GtkPaned: Pay attention to style changes
Make GtkPaned redraw and resize when style change
require it.
2020-01-24 20:55:42 -05:00
Matthias Clasen
6e358e2a49 GtkIcon: Pay attention to style changes
Make GtkIcon redraw and resize when style changes
require it.
2020-01-24 20:55:42 -05:00
Matthias Clasen
71ee4df357 css: Update affects flags for icons
We want to differentiate what requires recreating the
texture and what doesn't. In particular, the current
flags are not handling symbolic icons right.
2020-01-24 20:55:42 -05:00
Matthias Clasen
2bc6e1b875 Merge branch 'wayland-cursors' into 'master'
Make wayland load cursors on demand

See merge request GNOME/gtk!1350
2020-01-24 23:03:56 +00:00
Matthias Clasen
4e58541d52 Make wayland load cursors on demand
Copy just enough of libwayland-cursor to make our own
loading. This lets us drop the dependency on libwayland-cursor,
and changes the startup cost for cursor theme loading
from 25ms to 0.1ms.

At the same time, simplify the handling of scaled cursors -
instead of creating an array of theme objects, just make a
single theme object provide all scaled cursor sizes.
2020-01-24 17:27:45 -05:00
Matthias Clasen
53bc1d60c4 Revert "css: Print selectors"
This reverts commit da5d524324.

And this one too. The commits are there, if people need this
kind of statistics again, they can just be cherry-picked.
2020-01-24 11:51:18 -05:00
Matthias Clasen
5b6b4f5075 Revert "css: Print out relative costs of selectors"
This reverts commit 5dcce0c0bd.

I forgot to ifdef a few things in here, so lets take this out
again.
2020-01-24 11:50:40 -05:00
Matthias Clasen
16654eeef4 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!1348
2020-01-24 16:20:42 +00:00
Matthias Clasen
871959c88c Adwaita: Drop selection mode
This is not really a feature that GTK has; and it lets
us drop a significant amount of css.
2020-01-24 09:09:27 -05:00
Matthias Clasen
55d08d8400 Adwaita: Drop menu remnants
Menus are gone.
2020-01-24 09:09:27 -05:00
Matthias Clasen
5dcce0c0bd css: Print out relative costs of selectors
Count how often each tree node is visited, and print the number
at the end. This gives a good indication what selectors are costly
and should be avoided. #ifdefed out.
2020-01-24 09:09:08 -05:00
Matthias Clasen
975fe76a0e Adwaita: Remove a wildcard rule for tooltips
These rules are expensive, and don't seem to make
any difference for typical tooltip content.
2020-01-24 09:09:08 -05:00
Matthias Clasen
00be314feb Adwaita: Drop menuitem support
menuitems don't exist anymore.
2020-01-24 09:09:08 -05:00
Matthias Clasen
da5d524324 css: Print selectors
Add code that prints all the selectors when a theme
is loaded. #ifdefed out.
2020-01-24 09:08:52 -05:00
Timm Bäder
8e41fa2778 widget: Use gsk_transform_transform_point() in gtk_widget_pick()
This also covers the 2D_AFFINE case.
2020-01-24 06:19:16 +01:00
Timm Bäder
f80a341b4f gl renderer: handle cross-fade nodes with invisible children 2020-01-24 06:19:16 +01:00
Timm Bäder
77f8245c0c gl renderer: Handle blur nodes with invisible children 2020-01-24 06:19:16 +01:00
Timm Bäder
8afdbd6ee3 gl renderer: Make render_rounded_clip_node clearer 2020-01-24 06:19:16 +01:00
Timm Bäder
ac4e98f16a testsuite: Add test cases for last commit
Easy enough to test
2020-01-24 06:19:16 +01:00
Timm Bäder
ab0869ecbc gl renderer: Add builder offset correctly for non-affine modelviews 2020-01-24 06:19:16 +01:00
Timm Bäder
cff8304133 GskTransform: Add gsk_transform_transform_point()
Equivalent of gsk_transform_transform_bounds() and
graphene_matrix_transform_point() respectively.
2020-01-24 06:19:12 +01:00
Timm Bäder
962e38c5c9 gl renderer: Shorten shaders a bit 2020-01-24 06:08:39 +01:00
Timm Bäder
7855a98fd1 cssimageicontheme: Avoid copying colors 2020-01-24 06:08:39 +01:00
Timm Bäder
aea27b86c1 cssimagepaintable: Implement is_computed() 2020-01-24 06:08:39 +01:00
Timm Bäder
d4caf3d679 cssimagescaled: Implement is_computed() 2020-01-24 06:08:39 +01:00
Timm Bäder
d9652675ef cssimagerecolor: Implement is_computed() 2020-01-24 06:08:39 +01:00
Timm Bäder
685288216f gl renderer: Move rect transformation to the vertex shader
No need to do this for every fragment.
2020-01-24 06:08:39 +01:00
Timm Bäder
c8fa1f19db gl renderer: Transform rounded rect on the GPU
Change the RoundedRect struct we use in our shaders so we can transform
it using (affine) matrices.
2020-01-24 06:08:39 +01:00
Matthias Clasen
7e4feb092b colorbutton: Use a css name
This was the sole widget to show up as 'widget' in
the css tree.
2020-01-23 23:48:43 -05:00
Matthias Clasen
9eadcd8d55 testsuite: Update mark names
We've changed some of the profiler mark names to
be clearer and more unique. Update the tests that
look for those marks to use the new names.
2020-01-23 23:48:43 -05:00
Matthias Clasen
86aa011587 Adwaita: Use child selectors in many more places
These are much cheaper to match than descendent
selectors, so use them whenever we know the element
is a direct child.
2020-01-23 23:48:43 -05:00
Matthias Clasen
f9e613f8fd text: Don't compute invisible char in init
This causes us to create a pango layout and
validate the css style, a high-overhead
operation. Just do it when the entry is set
to be invisible.
2020-01-23 15:12:38 -05:00
Matthias Clasen
e13692c52f Fix Emoji completion
This was broken in various ways; Tabbing between pages
was causing segfaults, and using the hover state like
this does not work anymore, with hover now being completely
managed by GTK. Use focus instead, and also fix up the
style.
2020-01-23 14:07:09 -05:00
Matthias Clasen
cbed409f52 Replace .emoji with emoji for css 2020-01-23 14:07:09 -05:00
Matthias Clasen
0351f27af2 Adwaita: Drop .context-menu
We are not using it anymore, and yet fonts on a bold
textview are fine. So no need for this.
2020-01-23 14:07:09 -05:00
Matthias Clasen
f84ecf9cd2 Adwaita: Just use .menu, instead of .appmenu
No need for this one-off class, there's no other menus
that could show up here.
2020-01-23 14:07:09 -05:00
Emmanuele Bassi
5e9d186c26 Merge branch 'fix-avahi_service_resolver_cb-crash-master' into 'master'
printing: Fix crash in avahi_service_resolver_cb (master)

See merge request GNOME/gtk!1347
2020-01-23 17:50:47 +00:00
WGH
de9f0c5505 printing: Fix crash in avahi_service_resolver_cb
printer_name_compressed_strv is NULL-terminated array
of gchar*, which means N+1 memory should be allocated.

Otherwise, if the printer name has no empty components
(which is usually the case), printer_name_compressed_strv[N],
which should contain the NULL sentinel, will actually lie
just outside of allocated memory, which is UB.

In my case, it led to crashes inside g_strjoinv
when Print... dialog is opened in evince.

    #0  0x00007fad2ce1bad7 in __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:96
    #1  0x00007fad2d04d88d in g_strjoinv (separator=separator@entry=0x7fad0c9bc508 "-", str_array=str_array@entry=0x556b017f0200) at ../glib-2.60.7/glib/gstrfuncs.c:2585
    #2  0x00007fad0c9b8a89 in avahi_service_resolver_cb (source_object=<optimized out>, res=<optimized out>, user_data=0x7fad08020ee0) at /var/tmp/portage/x11-libs/gtk+-3.24.13/work/gtk+-3.24.13/modules/printbackends/cups/gtkprintbackendcups.c:3223
    #3  0x00007fad2d1f8ed3 in g_task_return_now (task=0x556b017a8b00 [GTask]) at ../glib-2.60.7/gio/gtask.c:1209
    #4  0x00007fad2d1f987d in g_task_return (task=0x556b017a8b00 [GTask], type=<optimized out>) at ../glib-2.60.7/gio/gtask.c:1278
    #5  0x00007fad2d1f9dec in g_task_return (type=G_TASK_RETURN_SUCCESS, task=<optimized out>) at ../glib-2.60.7/gio/gtask.c:1678
    #6  0x00007fad2d1f9dec in g_task_return_pointer (task=<optimized out>, result=<optimized out>, result_destroy=<optimized out>) at ../glib-2.60.7/gio/gtask.c:1683
    #7  0x00007fad2d24b6af in g_dbus_connection_call_done (source=<optimized out>, result=0x556b017a8bc0, user_data=0x556b017a8b00) at ../glib-2.60.7/gio/gdbusconnection.c:5747
    #8  0x00007fad2d1f8ed3 in g_task_return_now (task=0x556b017a8bc0 [GTask]) at ../glib-2.60.7/gio/gtask.c:1209
    #9  0x00007fad2d1f8f09 in complete_in_idle_cb (task=0x556b017a8bc0) at ../glib-2.60.7/gio/gtask.c:1223
    #10 0x00007fad2d02d2c0 in g_main_dispatch (context=0x556b00eee090) at ../glib-2.60.7/glib/gmain.c:3189
    #11 0x00007fad2d02d2c0 in g_main_context_dispatch (context=context@entry=0x556b00eee090) at ../glib-2.60.7/glib/gmain.c:3854
    #12 0x00007fad2d02d658 in g_main_context_iterate (context=context@entry=0x556b00eee090, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib-2.60.7/glib/gmain.c:3927
    #13 0x00007fad2d02d6df in g_main_context_iteration (context=context@entry=0x556b00eee090, may_block=may_block@entry=1) at ../glib-2.60.7/glib/gmain.c:3988
    #14 0x00007fad2d22248d in g_application_run (application=0x556b0116f130 [EvApplication], argc=<optimized out>, argv=<optimized out>) at ../glib-2.60.7/gio/gapplication.c:2519
    #15 0x0000556b002e55a1 in  ()
    #16 0x00007fad2ccd6f1b in __libc_start_main (main=0x556b002e50d0, argc=2, argv=0x7ffe1057fa88, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffe1057fa78) at ../csu/libc-start.c:308
    #17 0x0000556b002e567a in  ()

    (gdb) p printer_name_compressed_strv[0]
    $4 = (gchar *) 0x556d4a4be430 "Brother"
    (gdb) p printer_name_compressed_strv[1]
    $5 = (gchar *) 0x7f9dbc011090 "MFC"
    (gdb) p printer_name_compressed_strv[2]
    $6 = (gchar *) 0x556d4a51ba50 "7860DW"
    (gdb) p printer_name_compressed_strv[3]
    $7 = (gchar *) 0x401 <error: Cannot access memory at address 0x401>
2020-01-23 20:32:05 +03:00
Matthias Clasen
f5865b125e Add profiler marks around css selector tree building
This is a big part of theme loading, and worth
showing in traces.
2020-01-23 10:29:22 -05:00
Matthias Clasen
3483c1a45b Adwaita: Remove .entry-tag class
Not used in GTK.
2020-01-23 00:14:49 -05:00
Matthias Clasen
5cc088128f Adwaita: Remove .rubberband class
All GTK widget are using a rubberband element now.
2020-01-23 00:13:54 -05:00
Matthias Clasen
c4548e9c7b Adwaita: Remove .location-bar class
Not used in GTK.
2020-01-23 00:08:53 -05:00
Matthias Clasen
5d6aeb4bf7 Adwaita: Remove gtkstyle-fallback 2020-01-23 00:04:41 -05:00
Matthias Clasen
560e03f962 Adwaita: Remove the .drag-icon class
This class was not used in GTK.
2020-01-22 23:57:30 -05:00
Matthias Clasen
c3f1ff7db4 pathbar: Use a css name insead of a style class
Use pathbar for GtkPathBar in css, instead of the
previous .path-bar. Update Adwaita to match.
2020-01-22 23:56:22 -05:00
Matthias Clasen
88d26b7549 Ensure icon themes are loaded with other themes
Trigger icon theme loading from the code in GtkApplication
where we set up the icon theme search path. This makes
it happen before the first frame.
2020-01-22 23:44:01 -05:00
Matthias Clasen
4ac8011126 icontheme: Add profiler marks around icon theme loading
This is happening during the first frame.
2020-01-22 23:44:01 -05:00
Matthias Clasen
9b29da93b6 iconhelper: Add profiler marks around icon loading
These mainly happen during the first frame, causing
it to be longer than 'normal' frames.
2020-01-22 23:44:01 -05:00
Matthias Clasen
0fe9643728 css: Add a profiler mark around theme loading
This is also time spent before the first frame.
2020-01-22 23:44:01 -05:00
Matthias Clasen
73a214d1a9 application: Add some profiler marks
Add marks around gtk_init and application startup
helps to understand where the time before the first
frame goes.
2020-01-22 23:44:01 -05:00
Matthias Clasen
59a31e05bc gdk: Add a profiler mark for paint_idle
This is the big frame clock function where most
signals are emitted, and it can keep us away from
the mainloop for a long time.
2020-01-22 23:44:01 -05:00
Matthias Clasen
527b67af3d wayland: Add a mark for cursor loading
This is much too slow.
2020-01-22 23:44:01 -05:00
Matthias Clasen
3c03d7970a More profiler reshuffling
Add more of the marks without requiring a debug build.
2020-01-22 23:44:01 -05:00
Matthias Clasen
278762f00a gtk: Clearer names for profiler marks
Naming matters. Don't be overly generic here.
2020-01-22 16:38:40 -05:00
Matthias Clasen
1565f597c8 gl: Disambiguate profiler marks
"render" was used for both GL and widgets. Oops.
2020-01-22 16:37:48 -05:00
Matthias Clasen
fea42def61 surface: Always dd events to the profiler trace
We want to get this data for release builds as well.
2020-01-22 16:36:54 -05:00
Matthias Clasen
56b8d1dfbe frame clock: Redo the profiler marks
Instead of reporting the frame clock phases as defined,
report the duration of the signal emissions, which is more
useful for tracking down what is taking time.
2020-01-22 16:36:02 -05:00
Matthias Clasen
3120fb29e1 ci: Save syscap files from performance tests
They might become useful at some point.
2020-01-22 15:55:31 -05:00
Matthias Clasen
119457279b window: Rename a profiler mark
The "layout" name was already taken for the frame clock
phase by that name. Oops.
2020-01-22 15:12:03 -05:00
Matthias Clasen
dfea9bf0e8 wayland: Add profiler marks around surface handling
Add marks for when we do commits, swap buffer or
receive frame events. These are the low-level start
and end points of the frame cycle, and it is useful
to see them in the profiler.
2020-01-22 15:12:03 -05:00
Matthias Clasen
36cb812ad8 surface: Add enter/leave events to profiler traces
These are just as likely to trigger extra work than
other mouse events, so it is useful to show them.
2020-01-22 15:12:03 -05:00
Matthias Clasen
95ed9de706 icontheme: Add profiler marks for loading icons
This helps to clearly identify the places where we
do IO, in profiler traces.
2020-01-22 15:12:03 -05:00
sicklylife
a0448e2c7f Update Japanese translation 2020-01-22 17:32:21 +00:00
sicklylife
a6b05a19f1 Update Japanese translation 2020-01-22 17:29:36 +00:00
Matthias Clasen
672d7f679a Merge branch 'wip/jimmac/typography-classes' into 'master'
Adwaita: general typography classes

Closes #1808

See merge request GNOME/gtk!1339
2020-01-22 12:54:48 +00:00
Jakub Steiner
feecfcab27 Adwaita: general typography classes
- many moons and some iterations later, these are the suggested
  general typographic styles. Already being referenced in apps like
  Banner Viewer (for now shipping custom definitions)

Fixes https://gitlab.gnome.org/GNOME/gtk/issues/1808
2020-01-22 12:02:51 +01:00
Matthias Clasen
24fa0f8e28 testsuite: Move the meson performance tests up
Since the binary is moved, there is no need for
the subdirectory here anymore.
2020-01-22 00:59:09 -05:00
Matthias Clasen
878f35515d Make the performance testcase more general
Reuse the performance test for layout and snapshot timings.
2020-01-22 00:59:04 -05:00
Matthias Clasen
68fd796125 css: Make performance test more flexible
Allow to specify the name of the mark that we're looking
for the first instance of.
2020-01-22 00:29:43 -05:00
Matthias Clasen
5014b2a7fe widget: Add profiler marks
This gives high-level entries for the duration of
snapshotting and layout in the frame cycle.
2020-01-21 23:43:37 -05:00
Matthias Clasen
8cb375de11 window: Add a profiler mark around size allocation
This give a high-level entry for the duration of size allocation
in the frame cycle.
2020-01-21 23:43:01 -05:00
Matthias Clasen
7927bcf6c5 container: Remove an unnecessary check
GtkWindow implements GtkRoot, so we can avoid
treating them separately.
2020-01-21 23:19:24 -05:00
Matthias Clasen
d24d0e9667 Merge branch 'matthiasc/perf-tests' into 'master'
Performance tests

See merge request GNOME/gtk!1338
2020-01-22 03:38:50 +00:00
Matthias Clasen
e9e4bd423a testsuite: Make performance test fail
If a child process exits unsuccessfully,
make the performance test fail.
2020-01-21 19:55:08 -05:00
Matthias Clasen
81ddf4b946 testsuite: Point performance tests at uninstalled schemas
widget-factory won't run otherwise.
2020-01-21 19:51:14 -05:00
Matthias Clasen
c8485af819 Use the v9 image for ci runs
The v9 image add sysprof-devel, so we can build
and run performance tests using libsysprof.
2020-01-21 19:30:59 -05:00
Matthias Clasen
704a659438 ci: Build with profiler support
This will let us run sysprof-based performance tests.
2020-01-21 18:20:05 -05:00
Matthias Clasen
d32b0d3118 ci: Add sysprof-devel to the image
We need it to build with profiler support.
2020-01-21 18:17:50 -05:00
Matthias Clasen
23426b0f39 Fix testsuite without -Dprofiler=true
Only build and run the performance tests if we have sysprof.
2020-01-21 18:09:43 -05:00
Matthias Clasen
417edd28fb Run the css performance test in the testsuite
The numbers just end up in the testlog for now.
2020-01-21 17:49:40 -05:00
Matthias Clasen
ea17728ee5 Prototype a sysprof helper
This is an attempt to see how we can use sysprof data
in our tests to extract useful performance numbers.

Use it as a wrapper around any GTK+ process:

./testperf ./gtk4-widget-factory

Currently, it repeatedly runs the given commandline,
extracts the first css validation time from the resulting
syscap file, and prints out the min/max/avg of the runs
at the end.

This relies on the environment variable GTK_DEBUG_AUTO_QUIT
to cause the process to exit soon after launch.
2020-01-21 17:31:48 -05:00
Matthias Clasen
a6f300cefd widget-factory: Add a way to quit automatically
This can be used to measure startup cost in tests.
2020-01-21 17:31:48 -05:00
Matthias Clasen
05b98c3834 gdk: Make profiler support unconditional
We are still not providing samples unless debugging is enabled.
That needs a bit more work.
2020-01-21 11:50:12 -05:00
Matthias Clasen
820c9403e3 cssnode: Make the profiler support unconditional 2020-01-21 11:38:34 -05:00
Matthias Clasen
509531349d Merge branch 'otte/for-master' into 'master'
selector: Add GtkSelectorCategory

See merge request GNOME/gtk!1337
2020-01-21 16:17:17 +00:00
Benjamin Otte
2a5a52dd4b selector: Add GtkSelectorCategory
This will make it easier to write more complex matching algorithms.
2020-01-21 16:59:37 +01:00
Benjamin Otte
f42e18507f Merge branch 'otte/for-master' into 'master'
Otte/for master

See merge request GNOME/gtk!1336
2020-01-21 14:13:02 +00:00
Benjamin Otte
e6a0a2f587 stylecontext: Remove excess gtk_css_node_invalidate() call
This call is not necessary, because gtk_css_node_set_parent() does the
right thing. (It probably hasn't been necessary for years, but I'm
not gonna try my luck on GTK3 at this stage.)

This code is usually called the first time
gtk_widget_get_style_context() is called on a widget and its style
context gets create. At that point however, the css nodes are in the
right place already, so no invalidation should happen.
2020-01-21 14:49:25 +01:00
Benjamin Otte
631ea5caac Merge branch 'otte/for-master' into 'master'
Otte/for master

See merge request GNOME/gtk!1333
2020-01-21 12:09:26 +00:00
Benjamin Otte
d59784f7c7 win32: Don't save/restore the context for querying the font
Use the font in the current state.
2020-01-21 12:48:20 +01:00
Benjamin Otte
193eb5b0dd widget: Remove gtk_widget_get_path() 2020-01-21 12:47:16 +01:00
Benjamin Otte
6a1adf6f1a cssnode: Remove unused widget path vfuncs 2020-01-21 12:47:16 +01:00
Benjamin Otte
563ad2db1b containter: Remove gtk_container_get_path_for_child() 2020-01-21 12:47:16 +01:00
Benjamin Otte
c85d9a3259 stylecontext: Change semantics of gtk_style_context_get_path()
Widget contexts now return NULL here. A non-NULL result requires a
previous call to gtk_style_context_set_path()
2020-01-21 12:47:16 +01:00
Benjamin Otte
b9c81b1b94 widget: Initialize cssnode name asap
That way, it's correct in subclass's init functions.
2020-01-21 12:47:16 +01:00
Matthias Clasen
b52bcf7e0a Merge branch 'matthiasc/for-master' into 'master'
Add some static assertions

See merge request GNOME/gtk!1334
2020-01-21 04:52:12 +00:00
Matthias Clasen
a38ba91e35 Add some static assertions
Add assertions that ensure the relationships between
css property IDs that we rely on are preserved.
2020-01-20 22:54:26 -05:00
Matthias Clasen
a350c2452a Add profiler support for css validation
Push numbers about css validation and style creation
to sysprof.
2020-01-20 21:55:16 -05:00
Benjamin Otte
025902b9fb textview: Make cursor work when blinking is disabled 2020-01-21 01:42:00 +01:00
Matthias Clasen
7e2e92a87e cssselector: Inline a few things 2020-01-19 15:56:54 -05:00
Matthias Clasen
be4d42507c style cascade: Remove some pointless casts
The casts and checks in gtkstylecascade.c are leftovers
from when we had GtkStyleProviderPrivate, and no longer
serve any purpose.
2020-01-19 15:56:54 -05:00
Matthias Clasen
6e88ccf7fb pick: Take advantage of transform categories
Transform categories let us easily avoid doing matrix math
when we can just do a simple translation.
2020-01-19 15:56:54 -05:00
Matthias Clasen
cec4c15f05 Refactor gtk_widget_pick
Split this into a recursive part and a public
entry point. This lets us avoid some duplicate
checks.
2020-01-19 15:56:54 -05:00
Piotr Drąg
ce1f1f7dec Update Polish translation 2020-01-19 13:04:34 +01:00
Matthias Clasen
95f00c6071 css: Redo the pseudoclass selectors
There is no need to duplicate the classes, we can make
do with a single class for all the states.
2020-01-18 23:06:25 -05:00
Matthias Clasen
55cfeccfd2 css: Go back to clearing out selectors
Now that we use the selector tree for change computation
again, we don't need the ruleset selectors anymore.
Bring back the code that cleans them out.
2020-01-18 23:06:25 -05:00
Goran Vidović
2301916fa4 Update Croatian translation 2020-01-19 00:33:57 +00:00
Goran Vidović
bb4efe18b7 Update Croatian translation 2020-01-19 00:13:42 +00:00
Matthias Clasen
a463dccd81 Refine the selector tree printing
Also show which tree nodes have exact matches.
2020-01-18 14:32:55 -05:00
Matthias Clasen
eff129323f Fix a css change testcase
The ui file here was invalid, leading to nonsensical
results.
2020-01-18 14:32:55 -05:00
Matthias Clasen
a5530caec3 Actually turn of css value accounting
We need an #undef here. While doing so, make sure
it compiles without warnings when disabled.
2020-01-18 14:30:23 -05:00
Matthias Clasen
92cfc03821 inspector: Avoid an array overrun
Commit 3f56af3738 added a new value to the
GdkInputSource enum, forgetting that the inspector
has an array of names to match this enum.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/2385
2020-01-18 11:49:16 -05:00
Matthias Clasen
46bb1a9b6a wayland: Fix release build warnings 2020-01-18 11:49:16 -05:00
Matthias Clasen
19280db075 x11: Fix release build warnings 2020-01-18 11:49:16 -05:00
Piotr Drąg
7210c5484e Update POTFILES.skip 2020-01-18 17:39:53 +01:00
Timm Bäder
433c8307b2 gl renderer: Pull a local variable in the closest scope 2020-01-18 08:49:52 +01:00
Timm Bäder
26506b0a15 cssimagefallback: Don't snapshot invisible colors
This avoids a few render nodes later.
2020-01-18 08:49:52 +01:00
Timm Bäder
f8fa946989 widget: Get opacity without GtkStyleContext
GtkStyleContext is really just unnecessary here.
2020-01-18 08:49:52 +01:00
Timm Bäder
119ebe1d70 cssstyle: set font variations in get_pango_font()
Doesn't make sense to set all the css values on the font description in
there except for the font variations, so do these here as well.
2020-01-18 08:49:52 +01:00
Timm Bäder
dda54b2b8f widget: Get DPI from style directly
Instead of going through GtkStyleContext.
2020-01-18 08:49:52 +01:00
Timm Bäder
821efcb725 cssstyle: Implement get_pango_font() directly
Instead of going through the slow GValue code path. This function was
unused, so use it in GtkWidget's update_pango_context() now.
2020-01-18 08:49:52 +01:00
Timm Bäder
85793fe6b6 testsuite: Update expected css errors 2020-01-18 08:49:52 +01:00
Timm Bäder
dc8dedce07 gl renderer: Draw outset shadows white
and only apply the actual shadow color when we draw them from the
texture. This way we can reuse the cached shadows during color
transitions.
2020-01-18 08:49:52 +01:00
Matthias Clasen
f5182f1c35 css: Mark transform value as computed
This is not very useful, since transitions generate
a ton of transforms anyway.
2020-01-18 08:49:52 +01:00
Matthias Clasen
1efa39672b css: Simplify default values
We no longer need to create one-element arrays or
corners with two identical values.
2020-01-18 08:49:52 +01:00
Matthias Clasen
3f38a1c94c css: Re-add a lost special case
When the border-style special cases were moved in
c687f485fd, the one for outline-width was lost.

Make the code more compact, and bring the special
case back.
2020-01-18 08:49:52 +01:00
Timm Bäder
d861dd5df8 csshorthandproperty: Try to avoid allocating a GString for 1 font 2020-01-18 08:49:52 +01:00
Timm Bäder
8c98fd2e46 cssdimensionvalue: remove early-out code from transition()
We do this directly in gtk_css_value_transition() now
2020-01-18 08:49:52 +01:00
Timm Bäder
3091679ffa gl renderer: Render simple border nodes in a simple way
Roughly 80% of the border nodes are just one color and have the same
width on all sides, so we can draw them by uploading just one rect and
not four.
2020-01-18 08:49:52 +01:00
Timm Bäder
2e89c5360a numbervalue: Add early-out to multiply()
If the factor is 1, we already know what the result is going to be.
2020-01-18 08:49:52 +01:00
Timm Bäder
e448fc41f3 cssnumbervalue: Move early-out code to GtkCssValue
These checks make sense for all css values.
2020-01-18 08:49:52 +01:00
Timm Bäder
c9e972eecb cssdimensionvalue: Implement transition()
Instead of falling back to the generic gtk_css_number_value_transition
(which can allocate multiple new css values), just implement this here.
2020-01-18 08:49:52 +01:00
Timm Bäder
45455f1bdb Remove GtkCssShadowsValue
Previously, we wrapped all GtkCssShadowValues in a GtkCssShadowsValue,
even if it was just one shadow. This causes an unnecessary bloat in
css values.

Make each GtkCssShadowValue able to handle multiple shadows instead, and
use gtk_css_shadow_value* API everywhere.
2020-01-18 08:49:52 +01:00
Timm Bäder
a3769eb0e5 cssshadowvalue: Only create 2 shadows values for transitions
This is for cases where we want to transition from "no shadow" to
"shadow", which we need quite a lot.
2020-01-18 08:49:52 +01:00
Timm Bäder
7c75ea376f cssvalue: Improve css value accounting output
And make it fully optional behind an #ifdef.
2020-01-18 08:49:52 +01:00
Timm Bäder
96143548ac csscolorvalue: check for singletons in new_literal
Gets rid of another ~400 GtkCssValue instances in the widget-factory.
2020-01-18 08:49:51 +01:00
Timm Bäder
0b2a6e34c4 cssimage: Add is_computed vfunc
Same semantics as the is_computed field of GtkCssValue
2020-01-18 08:49:51 +01:00
Timm Bäder
24d8c0a7dc css: Set the is_computed flag for more values
With these changes, we skip roughly 85% of compute() calls during
widget-factory startup
2020-01-18 08:49:51 +01:00
Timm Bäder
ba08f5e67d cssvalue: Don't call compute() for already computed css values
As per the previous commit, this is unnecessary.

Even with the small amount of css values we mark as is_computed, we
already skip computing over 60% of them like this during the startup of
the widget factory.
2020-01-18 08:49:51 +01:00
Timm Bäder
31aa5a0e53 cssvalue: Add is_computed flag
When a css value has "child" css values (e.g. a linear gradient has
several color stop css values) which are all computed (won't change when
compute() is called on them), we want to skip computing the entire
subtree.

Since css values are immutable, we can set the is_computed flag at
construct time.

Since GtkCssValue instances are 0-initialized in _gtk_css_value_alloc,
the default for is_computed it FALSE. This commit only sets it to TRUE
in a few cases, such as various "none" singleton values which will never
change. Later commits will refine this and set it for more values.
2020-01-18 08:49:51 +01:00
Timm Bäder
7aa17afe7a testsuite: Update css color output 2020-01-18 08:49:51 +01:00
Timm Bäder
8c678ac756 css: Move border-width special cases out of GtkCssDimensionValue
Move them to style computation instead, so we don't have them in such a
generic place.
2020-01-18 08:49:51 +01:00
Timm Bäder
7d1f915a61 csscolorvalue: Don't copy rgbas when applying function
We get const pointers to the colors, so just use those and unref the
values later.
2020-01-18 08:49:51 +01:00
Timm Bäder
afa991752c gl renderer: Look at shadow color in the outset shadow cache
It would probably be better to not do this and always render the outline
in plain white, then later recolor it but do this for no, just for
correctness.
2020-01-18 08:49:51 +01:00
Timm Bäder
fc2d05ee38 cssimageradial: Use array + length instead of GArray
This makes sense since we're not going to change the (amount of) colors
after parsing.
2020-01-18 08:49:51 +01:00
Timm Bäder
00aa4f0597 cssimagelinear: Use count+array for the color stops, not GArray
This makse sense but will also make later changes to GtkCssImageLinear
simpler.
2020-01-18 08:49:51 +01:00
Timm Bäder
3401150cca cssimagefallback: Don't compute new image if only a color is set
Themes might use e.g. image(red), which is a constant value and will
never change. In that case, the fallback image has ->color set, but not
->images. If that's the case and the computed color is the same as
the one we already have, just return the already existing image.
2020-01-18 08:49:51 +01:00
Timm Bäder
67991ed0f4 Remove GtkCssRgbaValue
The differenciation between a literal color value and an RGBA value
caused problems in various situations. Just treat the two the same but
don't allow access to the rgba value of a non-literal color value.

This gets rid of around 1.6k rgba values in the widget-factory.
2020-01-18 08:49:51 +01:00
Matthias Clasen
741e12012d dump css value stats 2020-01-18 08:49:51 +01:00
Timm Bäder
91aa60b210 csssshadwovalue: Remove unused function prototype 2020-01-18 08:49:51 +01:00
Timm Bäder
e31c0898e5 cssnumbervalue: Add early-outs to transition code
we don't need to do the calculation at all if the progress is 0 or 1
anyway.

We also sometimes transition from 0 to 0 etc., so we can short-circuit
that as well by doing the fast pointer-equality check and relying on the
singletons.
2020-01-18 08:49:51 +01:00
Timm Bäder
1f2f2777e1 csscornervalue: Accept other values if x == y
Most corners are square, so x == y. In that case, just accept either of
them. This makes the corner value unnecessary.

In fact none of the corner values in the widget-factory are needed, so
this spares us around 500 corner value allocations.

css value stats before:

GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssCornerValue: 556
GtkCssArrayValue: 143
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
GtkCssColorValue: 1452
GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
SUM: 8428

and after:

GtkCssColorValue: 1452
GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssArrayValue: 143
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
SUM: 7872

8428 to 7872 is a 556 reduction (6.5%)

asdf
2020-01-18 08:49:51 +01:00
Timm Bäder
9cb2fe5cac cssarrayvalue: Don't allocate memory when parsing array values
We probably won't find CSS with more than 128 values in array.
2020-01-18 08:49:51 +01:00
Timm Bäder
8d15efba8f cssarrayvalue: Allow calling array API on non-arrays
Just allow calling _get_nth() and _get_n_values() on every kind of css
value. This way we can allow all values in places where only array
values would be allowed before.

This spares us around 1000 array values in the widget factory.

css value stats before:

GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssCornerValue: 556
GtkCssArrayValue: 1130
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
GtkCssColorValue: 1452
SUM: 9415

and after:

GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssCornerValue: 556
GtkCssArrayValue: 143
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
GtkCssColorValue: 1452
GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
SUM: 8428

9415 to 8428 is a 987 reduction (10.4%)
2020-01-18 08:49:51 +01:00
Timm Bäder
1200fe2daf cssvalue: Add type names for all classes
This is important to have for debugging and e.g. to print statistics for
the individual css value types
2020-01-18 08:49:51 +01:00
Timm Bäder
515a527b27 csscolorvalue: Compute alpha/shade/mix of color literals directly
The values of these are never gonna change so we can as well create
literal color values from the resulting colors instead.
2020-01-18 08:49:51 +01:00
Timm Bäder
06dbde22a0 csscolorvalue: Don't resolve literal color values 2020-01-18 08:49:51 +01:00
Matthias Clasen
c21280e455 Merge branch 'adwaita-performance' into 'master'
Adwaita: Remove wildcards

Closes #2380

See merge request GNOME/gtk!1330
2020-01-18 06:43:11 +00:00
Matthias Clasen
0d9a7fe089 Adwaita: Remove wildcards
Selectors like *:disabled or *:link have bad performance
implications, since they cause all styles to be recomputed
when the state of the window changes. Replace these by a
list of the elements that are actually affected.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/2380
2020-01-18 01:30:02 -05:00
Matthias Clasen
03883b8b1a Merge branch 'matthiasc/css-change-tracking-4' into 'master'
Improve change computation

See merge request GNOME/gtk!1327
2020-01-18 05:41:26 +00:00
Matthias Clasen
f28cd6cea9 Remove the widget-factory test again
This was failing in ci, in hard to track down ways.
2020-01-18 00:27:52 -05:00
Matthias Clasen
b8b90fefd8 change tests: Update test output
Some of these test cases involve :not, and thus are affected
by our now correct handling of it for change computation.

All of them are affected by the window now being visible.
2020-01-17 23:47:34 -05:00
Matthias Clasen
b4a9cf2bfb Remove no longer needed code
We no longer use superset or any matchers to find changes.
2020-01-17 23:47:34 -05:00
Matthias Clasen
2a919a4d4f Go back to the tree for computing change 2020-01-17 23:47:34 -05:00
Matthias Clasen
b2775d9bdd 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. This fixes the handling of :not while determining
changes.
2020-01-17 23:47:34 -05:00
Matthias Clasen
d0a8a717ef Bring back the reserved bit 2020-01-17 23:47:34 -05:00
Matthias Clasen
7d72703d54 Revert "Remove no longer used code"
This reverts commit 105acfe908.
2020-01-17 23:47:34 -05:00
Matthias Clasen
8ecd4e87e3 Add testcases for css change flags
Add various tests for the change flag computation that
we do in the css selector tree.

test1: Just test the basic machinery of this test
test2: Trigger every change flag at least once
test3: Test that multiple states combine as expected
test4: Test negations (known to produce wrong results)
test5: Test a complex selector (not producing the expected
       output atm)
widget-factory.ui:
       The real thing: widget-factory+Adwaita. Note that
       this expedts to be run with GSETTINGS_BACKEND=memory

Note that test4 checks the wrong results that we currently
produce for selectors involving :not. It will have to be
updated when we fix the handling of :not. The widget-factory.ui
testcase will certainly also be affected.
2020-01-17 23:47:34 -05:00
Matthias Clasen
9de31929d6 Add a test for css change flags 2020-01-17 23:47:34 -05:00
Matthias Clasen
b41bba07fa Add a way to dump css node change values
Add a GTK_STYLE_CONTEXT_PRINT_SHOW_CHANGE flag that
tells gtk_style_context_to_string to include the
change values of nodes in the output. This will
help debugging css change tracking.
2020-01-17 23:47:34 -05:00
Matthias Clasen
0f694b8beb style tests: Update expected output
The printing of css nodes has changed, and the window
is visible now.
2020-01-17 23:47:34 -05:00
Matthias Clasen
7b1ab8fb8b style tests: Show the window
Not doing so somewhat defeats the point that we want
to verify the regular styles, not some weird initial
conditions.
2020-01-17 23:47:34 -05:00
Matthias Clasen
d9b1a1ebb1 style tests: Clean up --generate support
Reshuffle things so we don't call gtk_test_init() when --generate
is passed, to avoid polluting the output with test spew.
2020-01-17 23:47:34 -05:00
Matthias Clasen
d4f3979896 node tests: Update expected output
The printing of css nodes has changed and the
window is visible now.
2020-01-17 23:47:34 -05:00
Matthias Clasen
2e7cb6019f node tests: Show the window
This avoids using default styles.
2020-01-17 23:47:34 -05:00
Matthias Clasen
f1fce5253e node tests: Clean up --generate support
Reshuffle things so we don't call gtk_test_init() when --generate
is passed, to avoid polluting the output with test spew.
2020-01-17 23:47:34 -05:00
Matthias Clasen
81b65eadcb Add an Empty theme for tests 2020-01-17 23:47:34 -05:00
Matthias Clasen
1e7705c08e cssnode: Fix a corner case in style computation
When we recomputed the change flags, and the style
did not change, we still need to replace the style
object, since it holds the new change flags.
2020-01-17 23:47:34 -05:00
Matthias Clasen
cc3cf581ab cssnodedeclaration: Make print output deterministic
This was depending on the memory order of quarks, which
is not a good fit for tests that depend on this output.
2020-01-17 23:47:34 -05:00
Matthias Clasen
6e09c5cee8 Quiet compiler warnings in release builds 2020-01-17 23:47:34 -05:00
Matthias Clasen
69fb3648b2 Tweak the file transfer portal _again_
This is a neverending story. I was seeing problems in tests where
the nested mainloop was picking up unrelated timeouts.

Break down and make this async. This changes the ordering in which
the (de)serializers are registered. If this is causing issues, we
can introduce priorities or something else.
2020-01-17 23:46:37 -05:00
Matthias Clasen
23f84e3a3d Merge branch 'gtk-fix-gesture-get-center' into 'master'
gtkgesture: Fix gtk_gesture_get_bounding_box_center() for touchpads

Closes #2316

See merge request GNOME/gtk!1257
2020-01-17 21:59:33 +00:00
Yariv Barkan
1a9b1f38a4 demo: Use pinch translation in the gestures demo
Add the pinch translation offset to the pinch gesture demo. That allows
moving the square around in addition to the already-supported rotate and
zoom.
2020-01-17 22:34:48 +02:00
Yariv Barkan
00a488a5b5 gtkgesture: Fix get-center for touchpad gestures
Touchpad gestures have only a single event sequence. The current
'center' of the gesture is the starting point + accumulated deltas.
Update gtk_gesture_get_bounding_box_center() accordingly.
2020-01-17 22:34:48 +02:00
Matthias Clasen
26c4c28068 Fix a few bugs in the css change flag definition
These were found by the new change flag tests.
2020-01-17 11:26:50 -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
257 changed files with 14191 additions and 11501 deletions

View File

@@ -13,7 +13,7 @@ stages:
- subprojects/pango/
fedora-x86_64: &fedora-x86_64-defaults
image: registry.gitlab.gnome.org/gnome/gtk/master:v8
image: registry.gitlab.gnome.org/gnome/gtk/master:v9
stage: build
script:
- bash -x ./.gitlab-ci/test-docker.sh
@@ -29,6 +29,7 @@ fedora-x86_64: &fedora-x86_64-defaults
- "${CI_PROJECT_DIR}/_build/report.html"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*.syscap"
cache:
key: "$CI_JOB_NAME"
<<: *cache-paths

View File

@@ -67,6 +67,7 @@ RUN dnf -y install \
python3-wheel \
redhat-rpm-config \
sassc \
sysprof-devel \
systemtap-sdt-devel \
vulkan-devel \
wayland-devel \

View File

@@ -16,6 +16,7 @@ meson \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=yes \
-Dprofiler=true \
--werror \
${EXTRA_MESON_FLAGS:-} \
_build $srcdir

View File

@@ -262,7 +262,7 @@ draw_menu (GtkWidget *widget,
gint toggle_x, toggle_y, toggle_width, toggle_height;
/* This information is taken from the GtkMenu docs, see "CSS nodes" */
menu_context = get_style (gtk_widget_get_style_context(widget), "menu");
menu_context = get_style (NULL, "menu");
hovermenuitem_context = get_style (menu_context, "menuitem:hover");
hoveredarrowmenuitem_context = get_style (hovermenuitem_context, "arrow.right:dir(ltr)");
menuitem_context = get_style (menu_context, "menuitem");

View File

@@ -94,9 +94,12 @@ drawing_area_draw (GtkDrawingArea *area,
cairo_pattern_t *pat;
cairo_matrix_t matrix;
gdouble angle, scale;
gdouble x_center, y_center;
gtk_gesture_get_bounding_box_center (GTK_GESTURE (zoom), &x_center, &y_center);
cairo_get_matrix (cr, &matrix);
cairo_matrix_translate (&matrix, width / 2, height / 2);
cairo_matrix_translate (&matrix, x_center, y_center);
cairo_save (cr);

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);

View File

@@ -2000,6 +2000,13 @@ toggle_action (GSimpleAction *action,
g_variant_new_boolean (!g_variant_get_boolean (state)));
}
static gboolean
quit_timeout (gpointer data)
{
exit (0);
return G_SOURCE_REMOVE;
}
int
main (int argc, char *argv[])
{
@@ -2065,6 +2072,9 @@ main (int argc, char *argv[])
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0, G_OPTION_ARG_NONE, "Show program version", NULL);
if (g_getenv ("GTK_DEBUG_AUTO_QUIT"))
g_timeout_add (500, quit_timeout, NULL);
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);

View File

@@ -183,6 +183,7 @@ gsk_transform_perspective
gsk_transform_equal
<SUBSECTION>
gsk_transform_transform_bounds
gsk_transform_transform_point
<SUBSECTION Private>
GSK_TYPE_TRANSFORM
gsk_transform_get_type

View File

@@ -775,7 +775,6 @@ gtk_container_add
gtk_container_remove
gtk_container_foreach
gtk_container_get_children
gtk_container_get_path_for_child
gtk_container_get_focus_vadjustment
gtk_container_set_focus_vadjustment
gtk_container_get_focus_hadjustment
@@ -4412,7 +4411,6 @@ gtk_widget_get_layout_manager
gtk_widget_should_layout
<SUBSECTION>
gtk_widget_get_path
gtk_widget_get_style_context
gtk_widget_reset_style
gtk_widget_class_get_css_name

View File

@@ -23,6 +23,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#include "gdkcontentformats.h"
#include "gdkcontentserializer.h"
#include "gdkcontentdeserializer.h"
#include <gio/gio.h>
#ifdef G_OS_UNIX
@@ -43,58 +47,6 @@
static GDBusProxy *file_transfer_proxy = NULL;
static GDBusProxy *
ensure_file_transfer_portal (void)
{
if (file_transfer_proxy == NULL)
{
GError *error = 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);
if (error)
{
g_debug ("Failed to get proxy: %s", error->message);
g_error_free (error);
}
}
if (file_transfer_proxy)
{
char *owner = g_dbus_proxy_get_name_owner (file_transfer_proxy);
if (owner)
{
g_free (owner);
return file_transfer_proxy;
}
}
return NULL;
}
gboolean
file_transfer_portal_available (void)
{
gboolean available;
ensure_file_transfer_portal ();
available = file_transfer_proxy != NULL;
g_clear_object (&file_transfer_proxy);
return available;
}
typedef struct {
GTask *task;
const char **files;
@@ -241,15 +193,12 @@ file_transfer_portal_register_files (const char **files,
gpointer data)
{
GTask *task;
GDBusProxy *proxy;
AddFileData *afd;
GVariantBuilder options;
task = g_task_new (NULL, NULL, callback, data);
proxy = ensure_file_transfer_portal ();
if (proxy == NULL)
if (file_transfer_proxy == NULL)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"No portal found");
@@ -267,7 +216,7 @@ file_transfer_portal_register_files (const char **files,
g_variant_builder_add (&options, "{sv}", "writable", g_variant_new_boolean (writable));
g_variant_builder_add (&options, "{sv}", "autostop", g_variant_new_boolean (TRUE));
g_dbus_proxy_call (proxy, "StartTransfer",
g_dbus_proxy_call (file_transfer_proxy, "StartTransfer",
g_variant_new ("(a{sv})", &options),
0, -1, NULL, start_session_done, afd);
}
@@ -319,15 +268,12 @@ file_transfer_portal_retrieve_files (const char *key,
GAsyncReadyCallback callback,
gpointer data)
{
GDBusProxy *proxy;
GTask *task;
GVariantBuilder options;
task = g_task_new (NULL, NULL, callback, data);
proxy = ensure_file_transfer_portal ();
if (proxy == NULL)
if (file_transfer_proxy == NULL)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"No portal found");
@@ -336,7 +282,7 @@ file_transfer_portal_retrieve_files (const char *key,
}
g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
g_dbus_proxy_call (proxy,
g_dbus_proxy_call (file_transfer_proxy,
"RetrieveFiles",
g_variant_new ("(sa{sv})", key, &options),
0, -1, NULL,
@@ -357,4 +303,235 @@ file_transfer_portal_retrieve_files_finish (GAsyncResult *result,
return FALSE;
}
/* serializer */
static void
file_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
portal_ready (GObject *object,
GAsyncResult *result,
gpointer serializer)
{
GError *error = NULL;
char *key;
if (!file_transfer_portal_register_files_finish (result, &key, &error))
{
gdk_content_serializer_return_error (serializer, error);
return;
}
g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
key,
strlen (key) + 1,
gdk_content_serializer_get_priority (serializer),
gdk_content_serializer_get_cancellable (serializer),
file_serializer_finish,
serializer);
gdk_content_serializer_set_task_data (serializer, key, g_free);
}
static void
portal_file_serializer (GdkContentSerializer *serializer)
{
GFile *file;
const GValue *value;
GPtrArray *files;
files = g_ptr_array_new_with_free_func (g_free);
value = gdk_content_serializer_get_value (serializer);
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
file = g_value_get_object (gdk_content_serializer_get_value (serializer));
if (file)
g_ptr_array_add (files, g_file_get_path (file));
g_ptr_array_add (files, NULL);
}
else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
{
GSList *l;
for (l = g_value_get_boxed (value); l; l = l->next)
g_ptr_array_add (files, g_file_get_path (l->data));
g_ptr_array_add (files, NULL);
}
/* this call doesn't copy the strings, so keep the array around until the registration is done */
file_transfer_portal_register_files ((const char **)files->pdata, TRUE, portal_ready, serializer);
gdk_content_serializer_set_task_data (serializer, files, (GDestroyNotify)g_ptr_array_unref);
}
/* deserializer */
static void
portal_finish (GObject *object,
GAsyncResult *result,
gpointer deserializer)
{
char **files = NULL;
GError *error = NULL;
GValue *value;
if (!file_transfer_portal_retrieve_files_finish (result, &files, &error))
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
value = gdk_content_deserializer_get_value (deserializer);
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
if (files[0] != NULL)
g_value_take_object (value, g_file_new_for_path (files[0]));
}
else
{
GSList *l = NULL;
gsize i;
for (i = 0; files[i] != NULL; i++)
l = g_slist_prepend (l, g_file_new_for_path (files[i]));
g_value_take_boxed (value, g_slist_reverse (l));
}
g_strfreev (files);
gdk_content_deserializer_return_success (deserializer);
}
static void
portal_file_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
gssize written;
char *key;
written = g_output_stream_splice_finish (stream, result, &error);
if (written < 0)
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
/* write terminating NULL */
if (!g_output_stream_write (stream, "", 1, NULL, &error))
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
key = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
if (key == NULL)
{
GError *gerror = g_error_new (G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not convert data from %s to %s",
gdk_content_deserializer_get_mime_type (deserializer),
g_type_name (gdk_content_deserializer_get_gtype (deserializer)));
gdk_content_deserializer_return_error (deserializer, gerror);
return;
}
file_transfer_portal_retrieve_files (key, portal_finish, deserializer);
gdk_content_deserializer_set_task_data (deserializer, key, g_free);
}
static void
portal_file_deserializer (GdkContentDeserializer *deserializer)
{
GOutputStream *output;
output = g_memory_output_stream_new_resizable ();
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),
portal_file_deserializer_finish,
deserializer);
g_object_unref (output);
}
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: %s", error->message);
g_clear_error (&error);
return;
}
gdk_content_register_serializer (G_TYPE_FILE,
"application/vnd.portal.files",
portal_file_serializer,
NULL,
NULL);
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"application/vnd.portal.files",
portal_file_serializer,
NULL,
NULL);
gdk_content_register_deserializer ("application/vnd.portal.files",
GDK_TYPE_FILE_LIST,
portal_file_deserializer,
NULL,
NULL);
gdk_content_register_deserializer ("application/vnd.portal.files",
G_TYPE_FILE,
portal_file_deserializer,
NULL,
NULL);
}
void
file_transfer_portal_register (void)
{
static gboolean called;
if (!called)
{
called = TRUE;
g_dbus_proxy_new_for_bus (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,
got_proxy,
NULL);
}
}
#endif /* G_OS_UNIX */

View File

@@ -19,7 +19,8 @@
#define __FILE_TRANSFER_PROTOCOL_H__
gboolean file_transfer_portal_available (void);
void file_transfer_portal_register (void);
void file_transfer_portal_register_files (const char **files,
gboolean writable,
GAsyncReadyCallback callback,

View File

@@ -212,14 +212,14 @@ gdk_pre_parse (void)
_gdk_debug_flags = g_parse_debug_string (debug_string,
(GDebugKey *) gdk_debug_keys,
G_N_ELEMENTS (gdk_debug_keys));
if (g_getenv ("GTK_TRACE_FD"))
gdk_profiler_start (atoi (g_getenv ("GTK_TRACE_FD")));
else if (g_getenv ("GTK_TRACE"))
gdk_profiler_start (-1);
}
#endif /* G_ENABLE_DEBUG */
if (g_getenv ("GTK_TRACE_FD"))
gdk_profiler_start (atoi (g_getenv ("GTK_TRACE_FD")));
else if (g_getenv ("GTK_TRACE"))
gdk_profiler_start (-1);
#ifndef G_HAS_CONSTRUCTORS
stash_desktop_startup_notification_id ();
#endif

View File

@@ -692,95 +692,6 @@ string_deserializer (GdkContentDeserializer *deserializer)
g_object_unref (filter);
}
#ifdef G_OS_UNIX
static void
portal_finish (GObject *object,
GAsyncResult *result,
gpointer deserializer)
{
char **files = NULL;
GError *error = NULL;
GValue *value;
if (!file_transfer_portal_retrieve_files_finish (result, &files, &error))
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
value = gdk_content_deserializer_get_value (deserializer);
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
if (files[0] != NULL)
g_value_take_object (value, g_file_new_for_path (files[0]));
}
else
{
GSList *l = NULL;
gsize i;
for (i = 0; files[i] != NULL; i++)
l = g_slist_prepend (l, g_file_new_for_path (files[i]));
g_value_take_boxed (value, g_slist_reverse (l));
}
g_strfreev (files);
gdk_content_deserializer_return_success (deserializer);
}
static void
portal_file_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
gssize written;
char *key;
written = g_output_stream_splice_finish (stream, result, &error);
if (written < 0)
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
/* write terminating NULL */
if (!g_output_stream_write (stream, "", 1, NULL, &error))
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
key = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
if (key == NULL)
{
deserialize_not_found (deserializer);
return;
}
file_transfer_portal_retrieve_files (key, portal_finish, deserializer);
gdk_content_deserializer_set_task_data (deserializer, key, g_free);
}
static void
portal_file_deserializer (GdkContentDeserializer *deserializer)
{
GOutputStream *output;
output = g_memory_output_stream_new_resizable ();
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),
portal_file_deserializer_finish,
deserializer);
g_object_unref (output);
}
#endif /* G_OS_UNIX */
static void
file_uri_deserializer_finish (GObject *source,
GAsyncResult *result,
@@ -965,13 +876,7 @@ init (void)
g_slist_free (formats);
#ifdef G_OS_UNIX
gboolean has_portal = file_transfer_portal_available ();
if (has_portal)
gdk_content_register_deserializer ("application/vnd.portal.files",
GDK_TYPE_FILE_LIST,
portal_file_deserializer,
NULL,
NULL);
file_transfer_portal_register ();
#endif
gdk_content_register_deserializer ("text/uri-list",
@@ -980,15 +885,6 @@ init (void)
NULL,
NULL);
#ifdef G_OS_UNIX
if (has_portal)
gdk_content_register_deserializer ("application/vnd.portal.files",
G_TYPE_FILE,
portal_file_deserializer,
NULL,
NULL);
#endif
gdk_content_register_deserializer ("text/uri-list",
G_TYPE_FILE,
file_uri_deserializer,

View File

@@ -348,7 +348,7 @@ 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: data that gets passed to @func
* @data: (closure): data that gets passed to @func
*
* Create a content provider that provides data that is provided via a callback.
*

View File

@@ -703,65 +703,6 @@ file_serializer_finish (GObject *source,
gdk_content_serializer_return_success (serializer);
}
#ifdef G_OS_UNIX
static void
portal_ready (GObject *object,
GAsyncResult *result,
gpointer serializer)
{
GError *error = NULL;
char *key;
if (!file_transfer_portal_register_files_finish (result, &key, &error))
{
gdk_content_serializer_return_error (serializer, error);
return;
}
g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
key,
strlen (key) + 1,
gdk_content_serializer_get_priority (serializer),
gdk_content_serializer_get_cancellable (serializer),
file_serializer_finish,
serializer);
gdk_content_serializer_set_task_data (serializer, key, g_free);
}
static void
portal_file_serializer (GdkContentSerializer *serializer)
{
GFile *file;
const GValue *value;
GPtrArray *files;
files = g_ptr_array_new_with_free_func (g_free);
value = gdk_content_serializer_get_value (serializer);
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
file = g_value_get_object (gdk_content_serializer_get_value (serializer));
if (file)
g_ptr_array_add (files, g_file_get_path (file));
g_ptr_array_add (files, NULL);
}
else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
{
GSList *l;
for (l = g_value_get_boxed (value); l; l = l->next)
g_ptr_array_add (files, g_file_get_path (l->data));
g_ptr_array_add (files, NULL);
}
/* this call doesn't copy the strings, so keep the array around until the registration is done */
file_transfer_portal_register_files ((const char **)files->pdata, TRUE, portal_ready, serializer);
gdk_content_serializer_set_task_data (serializer, files, (GDestroyNotify)g_ptr_array_unref);
}
#endif /* G_OS_UNIX */
static void
file_uri_serializer (GdkContentSerializer *serializer)
{
@@ -967,14 +908,7 @@ init (void)
g_slist_free (formats);
#ifdef G_OS_UNIX
gboolean has_portal = file_transfer_portal_available ();
if (has_portal)
gdk_content_register_serializer (G_TYPE_FILE,
"application/vnd.portal.files",
portal_file_serializer,
NULL,
NULL);
file_transfer_portal_register ();
#endif
gdk_content_register_serializer (G_TYPE_FILE,
@@ -988,15 +922,6 @@ init (void)
NULL,
NULL);
#ifdef G_OS_UNIX
if (has_portal)
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"application/vnd.portal.files",
portal_file_serializer,
NULL,
NULL);
#endif
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"text/uri-list",
file_uri_serializer,

View File

@@ -1003,7 +1003,7 @@ gdk_drop_emit_drop_event (GdkDrop *self,
/**
* gdk_drop_has_value:
* @drop: a #GdkDrop
* @self: a #GdkDrop
* @type: the type to check
*
* Returns whether calling gdk_drop_read_value_async() for @type
@@ -1012,13 +1012,13 @@ gdk_drop_emit_drop_event (GdkDrop *self,
* Returns: %TRUE if the data can be deserialized to the given type
*/
gboolean
gdk_drop_has_value (GdkDrop *drop,
gdk_drop_has_value (GdkDrop *self,
GType type)
{
GdkContentFormats *formats;
gboolean ret;
formats = gdk_content_formats_ref (gdk_drop_get_formats (drop));
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);

View File

@@ -649,46 +649,94 @@ gdk_frame_clock_get_refresh_info (GdkFrameClock *frame_clock,
void
_gdk_frame_clock_emit_flush_events (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[FLUSH_EVENTS], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::flush-events", "");
}
void
_gdk_frame_clock_emit_before_paint (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[BEFORE_PAINT], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::before-paint", "");
}
void
_gdk_frame_clock_emit_update (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[UPDATE], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::update", "");
}
void
_gdk_frame_clock_emit_layout (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[LAYOUT], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::layout", "");
}
void
_gdk_frame_clock_emit_paint (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[PAINT], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::paint", "");
}
void
_gdk_frame_clock_emit_after_paint (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[AFTER_PAINT], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::after-paint", "");
}
void
_gdk_frame_clock_emit_resume_events (GdkFrameClock *frame_clock)
{
guint64 before = g_get_monotonic_time ();
g_signal_emit (frame_clock, signals[RESUME_EVENTS], 0);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000,
(g_get_monotonic_time () - before) * 1000,
"frameclock ::resume-events", "");
}
#ifdef G_ENABLE_DEBUG
static gint64
guess_refresh_interval (GdkFrameClock *frame_clock)
{
@@ -758,34 +806,17 @@ frame_clock_get_fps (GdkFrameClock *frame_clock)
return ((double) end_counter - start_counter) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
}
#endif
void
_gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *clock,
GdkFrameTimings *timings)
{
#ifdef G_ENABLE_DEBUG
gdk_profiler_add_mark (timings->frame_time * 1000,
(timings->frame_end_time - timings->frame_time) * 1000,
"frame", "");
if (timings->layout_start_time != 0)
gdk_profiler_add_mark (timings->layout_start_time * 1000,
(timings->paint_start_time - timings->layout_start_time) * 1000,
"layout", "");
if (timings->paint_start_time != 0)
gdk_profiler_add_mark (timings->paint_start_time * 1000,
(timings->frame_end_time - timings->paint_start_time) * 1000,
"paint", "");
if (timings->presentation_time != 0)
gdk_profiler_add_mark (timings->presentation_time * 1000,
0,
"presentation", "");
gdk_profiler_set_counter (fps_counter,
timings->frame_end_time * 1000,
timings->presentation_time * 1000,
frame_clock_get_fps (clock));
#endif
}

View File

@@ -42,9 +42,7 @@ struct _GdkFrameClockIdlePrivate
gint64 frame_time;
gint64 min_next_frame_time;
gint64 sleep_serial;
#ifdef G_ENABLE_DEBUG
gint64 freeze_time;
#endif
guint flush_idle_id;
guint paint_idle_id;
@@ -319,6 +317,7 @@ gdk_frame_clock_paint_idle (void *data)
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
gboolean skip_to_resume_events;
GdkFrameTimings *timings = NULL;
gint64 before = g_get_monotonic_time ();
priv->paint_idle_id = 0;
priv->in_paint_idle = TRUE;
@@ -409,13 +408,13 @@ gdk_frame_clock_paint_idle (void *data)
{
int iter;
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
if (GDK_DEBUG_CHECK (FRAMES))
{
if (priv->phase != GDK_FRAME_CLOCK_PHASE_LAYOUT &&
(priv->requested & GDK_FRAME_CLOCK_PHASE_LAYOUT))
timings->layout_start_time = g_get_monotonic_time ();
}
#endif /* G_ENABLE_DEBUG */
#endif
priv->phase = GDK_FRAME_CLOCK_PHASE_LAYOUT;
/* We loop in the layout phase, because we don't want to progress
@@ -439,13 +438,13 @@ gdk_frame_clock_paint_idle (void *data)
if (priv->freeze_count == 0)
{
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
if (GDK_DEBUG_CHECK (FRAMES))
{
if (priv->phase != GDK_FRAME_CLOCK_PHASE_PAINT &&
(priv->requested & GDK_FRAME_CLOCK_PHASE_PAINT))
timings->paint_start_time = g_get_monotonic_time ();
}
#endif /* G_ENABLE_DEBUG */
#endif
priv->phase = GDK_FRAME_CLOCK_PHASE_PAINT;
if (priv->requested & GDK_FRAME_CLOCK_PHASE_PAINT)
@@ -466,7 +465,7 @@ gdk_frame_clock_paint_idle (void *data)
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
}
#ifdef G_ENABLE_DEBUG
if (GDK_DEBUG_CHECK (FRAMES) || gdk_profiler_is_running ())
if (GDK_DEBUG_CHECK (FRAMES))
timings->frame_end_time = g_get_monotonic_time ();
#endif /* G_ENABLE_DEBUG */
G_GNUC_FALLTHROUGH;
@@ -502,6 +501,9 @@ gdk_frame_clock_paint_idle (void *data)
if (priv->freeze_count == 0)
priv->sleep_serial = get_sleep_serial ();
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "frameclock", "paint_idle");
return FALSE;
}
@@ -561,13 +563,11 @@ gdk_frame_clock_idle_freeze (GdkFrameClock *clock)
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
#ifdef G_ENABLE_DEBUG
if (priv->freeze_count == 0)
{
if (gdk_profiler_is_running ())
priv->freeze_time = g_get_monotonic_time ();
}
#endif
priv->freeze_count++;
maybe_stop_idle (clock_idle);
@@ -594,7 +594,6 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock)
priv->sleep_serial = get_sleep_serial ();
#ifdef G_ENABLE_DEBUG
if (gdk_profiler_is_running ())
{
if (priv->freeze_time != 0)
@@ -602,11 +601,10 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock)
gint64 thaw_time = g_get_monotonic_time ();
gdk_profiler_add_mark (priv->freeze_time * 1000,
(thaw_time - priv->freeze_time) * 1000,
"freeze", "");
"frameclock freeze", "");
priv->freeze_time = 0;
}
}
#endif
}
}

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(),

View File

@@ -4005,7 +4005,6 @@ rewrite_event_for_toplevel (GdkEvent *event)
g_set_object (&event->any.surface, surface);
}
#ifdef G_ENABLE_DEBUG
static void
add_event_mark (GdkEvent *event,
gint64 time,
@@ -4072,6 +4071,9 @@ add_event_mark (GdkEvent *event,
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
message = g_strdup ("");
break;
case GDK_TOUCHPAD_SWIPE:
case GDK_TOUCHPAD_PINCH:
case GDK_SCROLL:
@@ -4113,14 +4115,11 @@ add_event_mark (GdkEvent *event,
g_free (message);
}
#endif
gboolean
gdk_surface_handle_event (GdkEvent *event)
{
#ifdef G_ENABLE_DEBUG
gint64 begin_time = g_get_monotonic_time ();
#endif
gboolean handled = FALSE;
if (check_autohide (event))
@@ -4139,10 +4138,8 @@ gdk_surface_handle_event (GdkEvent *event)
g_signal_emit (gdk_event_get_surface (event), signals[EVENT], 0, event, &handled);
}
#ifdef G_ENABLE_DEBUG
if (gdk_profiler_is_running ())
add_event_mark (event, begin_time, g_get_monotonic_time () - begin_time);
#endif
return handled;
}

View File

@@ -0,0 +1,12 @@
wayland_cursor_sources = files([
'wayland-cursor.c',
'xcursor.c',
'os-compatibility.c'
])
libwayland_cursor = static_library('wayland+cursor',
sources: wayland_cursor_sources,
include_directories: [ confinc, ],
dependencies: [ glib_dep, ],
c_args: common_cflags,
link_args: common_ldflags)

View File

@@ -0,0 +1,173 @@
/*
* Copyright © 2012 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define HAVE_MEMFD_CREATE
#ifdef HAVE_MEMFD_CREATE
#include <sys/mman.h>
#endif
#include "os-compatibility.h"
#ifndef HAVE_MKOSTEMP
static int
set_cloexec_or_close(int fd)
{
long flags;
if (fd == -1)
return -1;
flags = fcntl(fd, F_GETFD);
if (flags == -1)
goto err;
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
goto err;
return fd;
err:
close(fd);
return -1;
}
#endif
static int
create_tmpfile_cloexec(char *tmpname)
{
int fd;
#ifdef HAVE_MKOSTEMP
fd = mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0)
unlink(tmpname);
#else
fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd);
unlink(tmpname);
}
#endif
return fd;
}
/*
* Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set
* CLOEXEC. The file is immediately suitable for mmap()'ing
* the given size at offset zero.
*
* The file should not have a permanent backing store like a disk,
* but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
*
* The file name is deleted from the file system.
*
* The file is suitable for buffer sharing between processes by
* transmitting the file descriptor over Unix sockets using the
* SCM_RIGHTS methods.
*
* If the C library implements posix_fallocate(), it is used to
* guarantee that disk space is available for the file at the
* given size. If disk space is insufficent, errno is set to ENOSPC.
* If posix_fallocate() is not supported, program may receive
* SIGBUS on accessing mmap()'ed file contents instead.
*
* If the C library implements memfd_create(), it is used to create the
* file purely in memory, without any backing file name on the file
* system, and then sealing off the possibility of shrinking it. This
* can then be checked before accessing mmap()'ed file contents, to
* make sure SIGBUS can't happen. It also avoids requiring
* XDG_RUNTIME_DIR.
*/
int
os_create_anonymous_file(off_t size)
{
static const char template[] = "/wayland-cursor-shared-XXXXXX";
const char *path;
char *name;
int fd;
int ret;
#ifdef HAVE_MEMFD_CREATE
fd = memfd_create("wayland-cursor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd >= 0) {
/* We can add this seal before calling posix_fallocate(), as
* the file is currently zero-sized anyway.
*
* There is also no need to check for the return value, we
* couldn't do anything with it anyway.
*/
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
} else
#endif
{
path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
name = malloc(strlen(path) + sizeof(template));
if (!name)
return -1;
strcpy(name, path);
strcat(name, template);
fd = create_tmpfile_cloexec(name);
free(name);
if (fd < 0)
return -1;
}
#ifdef HAVE_POSIX_FALLOCATE
ret = posix_fallocate(fd, 0, size);
if (ret != 0) {
close(fd);
errno = ret;
return -1;
}
#else
ret = ftruncate(fd, size);
if (ret < 0) {
close(fd);
return -1;
}
#endif
return fd;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright © 2012 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef OS_COMPATIBILITY_H
#define OS_COMPATIBILITY_H
#include <sys/types.h>
int
os_create_anonymous_file(off_t size);
#endif /* OS_COMPATIBILITY_H */

View File

@@ -0,0 +1,385 @@
/*
* Copyright © 2012 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
#include "xcursor.h"
#include "wayland-cursor.h"
#include "wayland-client.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <os-compatibility.h>
#include <glib.h>
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
struct shm_pool {
struct wl_shm_pool *pool;
int fd;
unsigned int size;
unsigned int used;
char *data;
};
static struct shm_pool *
shm_pool_create(struct wl_shm *shm, int size)
{
struct shm_pool *pool;
pool = malloc(sizeof *pool);
if (!pool)
return NULL;
pool->fd = os_create_anonymous_file (size);
if (pool->fd < 0)
goto err_free;
pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
pool->fd, 0);
if (pool->data == MAP_FAILED)
goto err_close;
pool->pool = wl_shm_create_pool(shm, pool->fd, size);
pool->size = size;
pool->used = 0;
return pool;
err_close:
close(pool->fd);
err_free:
free(pool);
return NULL;
}
static int
shm_pool_resize(struct shm_pool *pool, int size)
{
if (ftruncate(pool->fd, size) < 0)
return 0;
#ifdef HAVE_POSIX_FALLOCATE
errno = posix_fallocate(pool->fd, 0, size);
if (errno != 0)
return 0;
#endif
wl_shm_pool_resize(pool->pool, size);
munmap(pool->data, pool->size);
pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
pool->fd, 0);
if (pool->data == (void *)-1)
return 0;
pool->size = size;
return 1;
}
static int
shm_pool_allocate(struct shm_pool *pool, int size)
{
int offset;
if (pool->used + size > pool->size)
if (!shm_pool_resize(pool, 2 * pool->size + size))
return -1;
offset = pool->used;
pool->used += size;
return offset;
}
static void
shm_pool_destroy(struct shm_pool *pool)
{
munmap(pool->data, pool->size);
wl_shm_pool_destroy(pool->pool);
close(pool->fd);
free(pool);
}
struct wl_cursor_theme {
unsigned int cursor_count;
struct wl_cursor **cursors;
struct wl_shm *shm;
struct shm_pool *pool;
int size;
char *path;
};
struct cursor_image {
struct wl_cursor_image image;
struct wl_cursor_theme *theme;
struct wl_buffer *buffer;
int offset; /* data offset of this image in the shm pool */
};
struct cursor {
struct wl_cursor cursor;
uint32_t total_delay; /* length of the animation in ms */
};
/** Get an shm buffer for a cursor image
*
* \param image The cursor image
* \return An shm buffer for the cursor image. The user should not destroy
* the returned buffer.
*/
struct wl_buffer *
wl_cursor_image_get_buffer(struct wl_cursor_image *_img)
{
struct cursor_image *image = (struct cursor_image *) _img;
struct wl_cursor_theme *theme = image->theme;
if (!image->buffer) {
image->buffer =
wl_shm_pool_create_buffer(theme->pool->pool,
image->offset,
_img->width, _img->height,
_img->width * 4,
WL_SHM_FORMAT_ARGB8888);
};
return image->buffer;
}
static void
wl_cursor_image_destroy(struct wl_cursor_image *_img)
{
struct cursor_image *image = (struct cursor_image *) _img;
if (image->buffer)
wl_buffer_destroy(image->buffer);
free(image);
}
static void
wl_cursor_destroy(struct wl_cursor *cursor)
{
unsigned int i;
for (i = 0; i < cursor->image_count; i++)
wl_cursor_image_destroy(cursor->images[i]);
free(cursor->images);
free(cursor->name);
free(cursor);
}
static struct wl_cursor *
wl_cursor_create_from_xcursor_images(XcursorImages *images,
struct wl_cursor_theme *theme,
const char *name,
unsigned int load_size)
{
struct cursor *cursor;
struct cursor_image *image;
int i, size;
cursor = malloc(sizeof *cursor);
if (!cursor)
return NULL;
cursor->cursor.images =
malloc(images->nimage * sizeof cursor->cursor.images[0]);
if (!cursor->cursor.images) {
free(cursor);
return NULL;
}
cursor->cursor.name = strdup(name);
cursor->cursor.size = load_size;
cursor->total_delay = 0;
for (i = 0; i < images->nimage; i++) {
image = malloc(sizeof *image);
if (image == NULL)
break;
image->theme = theme;
image->buffer = NULL;
image->image.width = images->images[i]->width;
image->image.height = images->images[i]->height;
image->image.hotspot_x = images->images[i]->xhot;
image->image.hotspot_y = images->images[i]->yhot;
image->image.delay = images->images[i]->delay;
size = image->image.width * image->image.height * 4;
image->offset = shm_pool_allocate(theme->pool, size);
if (image->offset < 0) {
free(image);
break;
}
/* copy pixels to shm pool */
memcpy(theme->pool->data + image->offset,
images->images[i]->pixels, size);
cursor->total_delay += image->image.delay;
cursor->cursor.images[i] = (struct wl_cursor_image *) image;
}
cursor->cursor.image_count = i;
if (cursor->cursor.image_count == 0) {
free(cursor->cursor.name);
free(cursor->cursor.images);
free(cursor);
return NULL;
}
return &cursor->cursor;
}
static void
load_cursor(struct wl_cursor_theme *theme, const char *name, unsigned int size)
{
XcursorImages *images;
struct wl_cursor *cursor;
char *path;
path = g_strconcat (theme->path, "/", name, NULL);
images = xcursor_load_images (path, size);
g_free (path);
if (!images)
return;
cursor = wl_cursor_create_from_xcursor_images(images, theme, name, size);
if (cursor) {
theme->cursor_count++;
theme->cursors =
realloc(theme->cursors,
theme->cursor_count * sizeof theme->cursors[0]);
if (theme->cursors == NULL) {
theme->cursor_count--;
free(cursor);
} else {
theme->cursors[theme->cursor_count - 1] = cursor;
}
}
xcursor_images_destroy (images);
}
/** Load a cursor theme to memory shared with the compositor
*
* \param name The name of the cursor theme to load. If %NULL, the default
* theme will be loaded.
* \param size Desired size of the cursor images.
* \param shm The compositor's shm interface.
*
* \return An object representing the theme that should be destroyed with
* wl_cursor_theme_destroy() or %NULL on error. If no theme with the given
* name exists, a default theme will be loaded.
*/
struct wl_cursor_theme *
wl_cursor_theme_create(const char *path, int size, struct wl_shm *shm)
{
struct wl_cursor_theme *theme;
theme = malloc(sizeof *theme);
if (!theme)
return NULL;
theme->path = strdup (path);
theme->size = size;
theme->cursor_count = 0;
theme->cursors = NULL;
theme->pool = shm_pool_create(shm, size * size * 4);
if (!theme->pool) {
free (theme->path);
free (theme);
return NULL;
}
return theme;
}
/** Destroys a cursor theme object
*
* \param theme The cursor theme to be destroyed
*/
void
wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
{
unsigned int i;
for (i = 0; i < theme->cursor_count; i++)
wl_cursor_destroy(theme->cursors[i]);
shm_pool_destroy(theme->pool);
free(theme->cursors);
free(theme->path);
free(theme);
}
/** Get the cursor for a given name from a cursor theme
*
* \param theme The cursor theme
* \param name Name of the desired cursor
* \return The theme's cursor of the given name or %NULL if there is no
* such cursor
*/
struct wl_cursor *
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int scale)
{
unsigned int i;
unsigned int size;
size = theme->size * scale;
for (i = 0; i < theme->cursor_count; i++) {
if (size == theme->cursors[i]->size &&
strcmp(name, theme->cursors[i]->name) == 0)
return theme->cursors[i];
}
load_cursor (theme, name, size);
if (i < theme->cursor_count) {
if (size == theme->cursors[i]->size &&
strcmp (name, theme->cursors[theme->cursor_count - 1]->name) == 0)
return theme->cursors[theme->cursor_count - 1];
}
return NULL;
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright © 2012 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef WAYLAND_CURSOR_H
#define WAYLAND_CURSOR_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct wl_cursor_theme;
struct wl_buffer;
struct wl_shm;
struct wl_cursor_image {
uint32_t width; /* actual width */
uint32_t height; /* actual height */
uint32_t hotspot_x; /* hot spot x (must be inside image) */
uint32_t hotspot_y; /* hot spot y (must be inside image) */
uint32_t delay; /* animation delay to next frame (ms) */
};
struct wl_cursor {
unsigned int image_count;
struct wl_cursor_image **images;
char *name;
unsigned int size;
};
struct wl_cursor_theme *
wl_cursor_theme_create(const char *name, int size, struct wl_shm *shm);
void
wl_cursor_theme_destroy(struct wl_cursor_theme *theme);
struct wl_cursor *
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int scale);
struct wl_buffer *
wl_cursor_image_get_buffer(struct wl_cursor_image *image);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,612 @@
/*
* Copyright © 2002 Keith Packard
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "xcursor.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
/*
* From libXcursor/include/X11/extensions/Xcursor.h
*/
#define XcursorTrue 1
#define XcursorFalse 0
/*
* Cursor files start with a header. The header
* contains a magic number, a version number and a
* table of contents which has type and offset information
* for the remaining tables in the file.
*
* File minor versions increment for compatible changes
* File major versions increment for incompatible changes (never, we hope)
*
* Chunks of the same type are always upward compatible. Incompatible
* changes are made with new chunk types; the old data can remain under
* the old type. Upward compatible changes can add header data as the
* header lengths are specified in the file.
*
* File:
* FileHeader
* LISTofChunk
*
* FileHeader:
* CARD32 magic magic number
* CARD32 header bytes in file header
* CARD32 version file version
* CARD32 ntoc number of toc entries
* LISTofFileToc toc table of contents
*
* FileToc:
* CARD32 type entry type
* CARD32 subtype entry subtype (size for images)
* CARD32 position absolute file position
*/
#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */
/*
* Current Xcursor version number. Will be substituted by configure
* from the version in the libXcursor configure.ac file.
*/
#define XCURSOR_LIB_MAJOR 1
#define XCURSOR_LIB_MINOR 1
#define XCURSOR_LIB_REVISION 13
#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \
(XCURSOR_LIB_MINOR * 100) + \
(XCURSOR_LIB_REVISION))
/*
* This version number is stored in cursor files; changes to the
* file format require updating this version number
*/
#define XCURSOR_FILE_MAJOR 1
#define XCURSOR_FILE_MINOR 0
#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR))
#define XCURSOR_FILE_HEADER_LEN (4 * 4)
#define XCURSOR_FILE_TOC_LEN (3 * 4)
typedef struct _XcursorFileToc {
XcursorUInt type; /* chunk type */
XcursorUInt subtype; /* subtype (size for images) */
XcursorUInt position; /* absolute position in file */
} XcursorFileToc;
typedef struct _XcursorFileHeader {
XcursorUInt magic; /* magic number */
XcursorUInt header; /* byte length of header */
XcursorUInt version; /* file version number */
XcursorUInt ntoc; /* number of toc entries */
XcursorFileToc *tocs; /* table of contents */
} XcursorFileHeader;
/*
* The rest of the file is a list of chunks, each tagged by type
* and version.
*
* Chunk:
* ChunkHeader
* <extra type-specific header fields>
* <type-specific data>
*
* ChunkHeader:
* CARD32 header bytes in chunk header + type header
* CARD32 type chunk type
* CARD32 subtype chunk subtype
* CARD32 version chunk type version
*/
#define XCURSOR_CHUNK_HEADER_LEN (4 * 4)
typedef struct _XcursorChunkHeader {
XcursorUInt header; /* bytes in chunk header */
XcursorUInt type; /* chunk type */
XcursorUInt subtype; /* chunk subtype (size for images) */
XcursorUInt version; /* version of this type */
} XcursorChunkHeader;
/*
* Here's a list of the known chunk types
*/
/*
* Comments consist of a 4-byte length field followed by
* UTF-8 encoded text
*
* Comment:
* ChunkHeader header chunk header
* CARD32 length bytes in text
* LISTofCARD8 text UTF-8 encoded text
*/
#define XCURSOR_COMMENT_TYPE 0xfffe0001
#define XCURSOR_COMMENT_VERSION 1
#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4))
#define XCURSOR_COMMENT_COPYRIGHT 1
#define XCURSOR_COMMENT_LICENSE 2
#define XCURSOR_COMMENT_OTHER 3
#define XCURSOR_COMMENT_MAX_LEN 0x100000
typedef struct _XcursorComment {
XcursorUInt version;
XcursorUInt comment_type;
char *comment;
} XcursorComment;
/*
* Each cursor image occupies a separate image chunk.
* The length of the image header follows the chunk header
* so that future versions can extend the header without
* breaking older applications
*
* Image:
* ChunkHeader header chunk header
* CARD32 width actual width
* CARD32 height actual height
* CARD32 xhot hot spot x
* CARD32 yhot hot spot y
* CARD32 delay animation delay
* LISTofCARD32 pixels ARGB pixels
*/
#define XCURSOR_IMAGE_TYPE 0xfffd0002
#define XCURSOR_IMAGE_VERSION 1
#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
typedef struct _XcursorFile XcursorFile;
struct _XcursorFile {
void *closure;
int (*read) (XcursorFile *file, unsigned char *buf, int len);
int (*write) (XcursorFile *file, unsigned char *buf, int len);
int (*seek) (XcursorFile *file, long offset, int whence);
};
typedef struct _XcursorComments {
int ncomment; /* number of comments */
XcursorComment **comments; /* array of XcursorComment pointers */
} XcursorComments;
/*
* From libXcursor/src/file.c
*/
static XcursorImage *
XcursorImageCreate (int width, int height)
{
XcursorImage *image;
if (width < 0 || height < 0)
return NULL;
if (width > XCURSOR_IMAGE_MAX_SIZE || height > XCURSOR_IMAGE_MAX_SIZE)
return NULL;
image = malloc (sizeof (XcursorImage) +
width * height * sizeof (XcursorPixel));
if (!image)
return NULL;
image->version = XCURSOR_IMAGE_VERSION;
image->pixels = (XcursorPixel *) (image + 1);
image->size = width > height ? width : height;
image->width = width;
image->height = height;
image->delay = 0;
return image;
}
static void
XcursorImageDestroy (XcursorImage *image)
{
free (image);
}
static XcursorImages *
XcursorImagesCreate (int size)
{
XcursorImages *images;
images = malloc (sizeof (XcursorImages) +
size * sizeof (XcursorImage *));
if (!images)
return NULL;
images->nimage = 0;
images->images = (XcursorImage **) (images + 1);
images->name = NULL;
return images;
}
static void
XcursorImagesDestroy (XcursorImages *images)
{
int n;
if (!images)
return;
for (n = 0; n < images->nimage; n++)
XcursorImageDestroy (images->images[n]);
if (images->name)
free (images->name);
free (images);
}
static XcursorBool
_XcursorReadUInt (XcursorFile *file, XcursorUInt *u)
{
unsigned char bytes[4];
if (!file || !u)
return XcursorFalse;
if ((*file->read) (file, bytes, 4) != 4)
return XcursorFalse;
*u = ((bytes[0] << 0) |
(bytes[1] << 8) |
(bytes[2] << 16) |
(bytes[3] << 24));
return XcursorTrue;
}
static void
_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader)
{
free (fileHeader);
}
static XcursorFileHeader *
_XcursorFileHeaderCreate (int ntoc)
{
XcursorFileHeader *fileHeader;
if (ntoc > 0x10000)
return NULL;
fileHeader = malloc (sizeof (XcursorFileHeader) +
ntoc * sizeof (XcursorFileToc));
if (!fileHeader)
return NULL;
fileHeader->magic = XCURSOR_MAGIC;
fileHeader->header = XCURSOR_FILE_HEADER_LEN;
fileHeader->version = XCURSOR_FILE_VERSION;
fileHeader->ntoc = ntoc;
fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1);
return fileHeader;
}
static XcursorFileHeader *
_XcursorReadFileHeader (XcursorFile *file)
{
XcursorFileHeader head, *fileHeader;
XcursorUInt skip;
unsigned int n;
if (!file)
return NULL;
if (!_XcursorReadUInt (file, &head.magic))
return NULL;
if (head.magic != XCURSOR_MAGIC)
return NULL;
if (!_XcursorReadUInt (file, &head.header))
return NULL;
if (!_XcursorReadUInt (file, &head.version))
return NULL;
if (!_XcursorReadUInt (file, &head.ntoc))
return NULL;
skip = head.header - XCURSOR_FILE_HEADER_LEN;
if (skip)
if ((*file->seek) (file, skip, SEEK_CUR) == EOF)
return NULL;
fileHeader = _XcursorFileHeaderCreate (head.ntoc);
if (!fileHeader)
return NULL;
fileHeader->magic = head.magic;
fileHeader->header = head.header;
fileHeader->version = head.version;
fileHeader->ntoc = head.ntoc;
for (n = 0; n < fileHeader->ntoc; n++)
{
if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type))
break;
if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype))
break;
if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position))
break;
}
if (n != fileHeader->ntoc)
{
_XcursorFileHeaderDestroy (fileHeader);
return NULL;
}
return fileHeader;
}
static XcursorBool
_XcursorSeekToToc (XcursorFile *file,
XcursorFileHeader *fileHeader,
int toc)
{
if (!file || !fileHeader || \
(*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF)
return XcursorFalse;
return XcursorTrue;
}
static XcursorBool
_XcursorFileReadChunkHeader (XcursorFile *file,
XcursorFileHeader *fileHeader,
int toc,
XcursorChunkHeader *chunkHeader)
{
if (!file || !fileHeader || !chunkHeader)
return XcursorFalse;
if (!_XcursorSeekToToc (file, fileHeader, toc))
return XcursorFalse;
if (!_XcursorReadUInt (file, &chunkHeader->header))
return XcursorFalse;
if (!_XcursorReadUInt (file, &chunkHeader->type))
return XcursorFalse;
if (!_XcursorReadUInt (file, &chunkHeader->subtype))
return XcursorFalse;
if (!_XcursorReadUInt (file, &chunkHeader->version))
return XcursorFalse;
/* sanity check */
if (chunkHeader->type != fileHeader->tocs[toc].type ||
chunkHeader->subtype != fileHeader->tocs[toc].subtype)
return XcursorFalse;
return XcursorTrue;
}
#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a))
static XcursorDim
_XcursorFindBestSize (XcursorFileHeader *fileHeader,
XcursorDim size,
int *nsizesp)
{
unsigned int n;
int nsizes = 0;
XcursorDim bestSize = 0;
XcursorDim thisSize;
if (!fileHeader || !nsizesp)
return 0;
for (n = 0; n < fileHeader->ntoc; n++)
{
if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
continue;
thisSize = fileHeader->tocs[n].subtype;
if (!bestSize || dist (thisSize, size) < dist (bestSize, size))
{
bestSize = thisSize;
nsizes = 1;
}
else if (thisSize == bestSize)
nsizes++;
}
*nsizesp = nsizes;
return bestSize;
}
static int
_XcursorFindImageToc (XcursorFileHeader *fileHeader,
XcursorDim size,
int count)
{
unsigned int toc;
XcursorDim thisSize;
if (!fileHeader)
return 0;
for (toc = 0; toc < fileHeader->ntoc; toc++)
{
if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE)
continue;
thisSize = fileHeader->tocs[toc].subtype;
if (thisSize != size)
continue;
if (!count)
break;
count--;
}
if (toc == fileHeader->ntoc)
return -1;
return toc;
}
static XcursorImage *
_XcursorReadImage (XcursorFile *file,
XcursorFileHeader *fileHeader,
int toc)
{
XcursorChunkHeader chunkHeader;
XcursorImage head;
XcursorImage *image;
int n;
XcursorPixel *p;
if (!file || !fileHeader)
return NULL;
if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader))
return NULL;
if (!_XcursorReadUInt (file, &head.width))
return NULL;
if (!_XcursorReadUInt (file, &head.height))
return NULL;
if (!_XcursorReadUInt (file, &head.xhot))
return NULL;
if (!_XcursorReadUInt (file, &head.yhot))
return NULL;
if (!_XcursorReadUInt (file, &head.delay))
return NULL;
/* sanity check data */
if (head.width > XCURSOR_IMAGE_MAX_SIZE ||
head.height > XCURSOR_IMAGE_MAX_SIZE)
return NULL;
if (head.width == 0 || head.height == 0)
return NULL;
if (head.xhot > head.width || head.yhot > head.height)
return NULL;
/* Create the image and initialize it */
image = XcursorImageCreate (head.width, head.height);
if (image == NULL)
return NULL;
if (chunkHeader.version < image->version)
image->version = chunkHeader.version;
image->size = chunkHeader.subtype;
image->xhot = head.xhot;
image->yhot = head.yhot;
image->delay = head.delay;
n = image->width * image->height;
p = image->pixels;
while (n--)
{
if (!_XcursorReadUInt (file, p))
{
XcursorImageDestroy (image);
return NULL;
}
p++;
}
return image;
}
static XcursorImages *
XcursorXcFileLoadImages (XcursorFile *file, int size)
{
XcursorFileHeader *fileHeader;
XcursorDim bestSize;
int nsize;
XcursorImages *images;
int n;
int toc;
if (!file || size < 0)
return NULL;
fileHeader = _XcursorReadFileHeader (file);
if (!fileHeader)
return NULL;
bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize);
if (!bestSize)
{
_XcursorFileHeaderDestroy (fileHeader);
return NULL;
}
images = XcursorImagesCreate (nsize);
if (!images)
{
_XcursorFileHeaderDestroy (fileHeader);
return NULL;
}
for (n = 0; n < nsize; n++)
{
toc = _XcursorFindImageToc (fileHeader, bestSize, n);
if (toc < 0)
break;
images->images[images->nimage] = _XcursorReadImage (file, fileHeader,
toc);
if (!images->images[images->nimage])
break;
images->nimage++;
}
_XcursorFileHeaderDestroy (fileHeader);
if (images->nimage != nsize)
{
XcursorImagesDestroy (images);
images = NULL;
}
return images;
}
static int
_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len)
{
FILE *f = file->closure;
return fread (buf, 1, len, f);
}
static int
_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len)
{
FILE *f = file->closure;
return fwrite (buf, 1, len, f);
}
static int
_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence)
{
FILE *f = file->closure;
return fseek (f, offset, whence);
}
static void
_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file)
{
file->closure = stdfile;
file->read = _XcursorStdioFileRead;
file->write = _XcursorStdioFileWrite;
file->seek = _XcursorStdioFileSeek;
}
static XcursorImages *
XcursorFileLoadImages (FILE *file, int size)
{
XcursorFile f;
if (!file)
return NULL;
_XcursorStdioFileInitialize (file, &f);
return XcursorXcFileLoadImages (&f, size);
}
XcursorImages *
xcursor_load_images (const char *path, int size)
{
FILE *f;
XcursorImages *images;
f = fopen (path, "r");
if (!f)
return NULL;
images = XcursorFileLoadImages (f, size);
fclose (f);
return images;
}
void
xcursor_images_destroy (XcursorImages *images)
{
XcursorImagesDestroy (images);
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright © 2002 Keith Packard
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef XCURSOR_H
#define XCURSOR_H
typedef int XcursorBool;
typedef unsigned int XcursorUInt;
typedef XcursorUInt XcursorDim;
typedef XcursorUInt XcursorPixel;
typedef struct _XcursorImage {
XcursorUInt version; /* version of the image data */
XcursorDim size; /* nominal size for matching */
XcursorDim width; /* actual width */
XcursorDim height; /* actual height */
XcursorDim xhot; /* hot spot x (must be inside image) */
XcursorDim yhot; /* hot spot y (must be inside image) */
XcursorUInt delay; /* animation delay to next frame (ms) */
XcursorPixel *pixels; /* pointer to pixels */
} XcursorImage;
/*
* Other data structures exposed by the library API
*/
typedef struct _XcursorImages {
int nimage; /* number of images */
XcursorImage **images; /* array of XcursorImage pointers */
char *name; /* name used to load images */
} XcursorImages;
void
xcursor_images_destroy (XcursorImages *images);
XcursorImages *
xcursor_load_images (const char *path, int size);
#endif

View File

@@ -33,8 +33,7 @@
#include "gdkdisplay-wayland.h"
#include "gdkwayland.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <wayland-cursor.h>
#include "cursor/wayland-cursor.h"
static void
gdk_wayland_cursor_remove_from_cache (gpointer data, GObject *cursor)
@@ -119,11 +118,12 @@ name_fallback (const gchar *name)
static struct wl_cursor *
gdk_wayland_cursor_load_for_name (GdkWaylandDisplay *display_wayland,
struct wl_cursor_theme *theme,
int scale,
const char *name)
{
struct wl_cursor *c;
c = wl_cursor_theme_get_cursor (theme, name);
c = wl_cursor_theme_get_cursor (theme, name, scale);
if (!c)
{
const char *fallback;
@@ -131,7 +131,7 @@ gdk_wayland_cursor_load_for_name (GdkWaylandDisplay *display_wayland,
fallback = name_fallback (name);
if (fallback)
{
c = wl_cursor_theme_get_cursor (theme, fallback);
c = wl_cursor_theme_get_cursor (theme, fallback, scale);
}
}
@@ -172,7 +172,8 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
goto none;
c = gdk_wayland_cursor_load_for_name (display,
_gdk_wayland_display_get_scaled_cursor_theme (display, desired_scale),
_gdk_wayland_display_get_cursor_theme (display),
desired_scale,
gdk_cursor_get_name (cursor));
if (c)
{
@@ -270,7 +271,8 @@ _gdk_wayland_cursor_get_next_image_index (GdkWaylandDisplay *display,
}
c = gdk_wayland_cursor_load_for_name (display,
_gdk_wayland_display_get_scaled_cursor_theme (display, scale),
_gdk_wayland_display_get_cursor_theme (display),
scale,
gdk_cursor_get_name (cursor));
if (c)

View File

@@ -56,6 +56,8 @@
#define BTN_STYLUS3 0x149 /* Linux 4.15 */
#endif
#define GDK_SEAT_NOTE(seat,type,action) GDK_DISPLAY_NOTE(gdk_seat_get_display (GDK_SEAT (seat)),type,action)
typedef struct _GdkWaylandDevicePad GdkWaylandDevicePad;
typedef struct _GdkWaylandDevicePadClass GdkWaylandDevicePadClass;
@@ -1119,7 +1121,7 @@ data_offer_offer (void *data,
if (seat->pending_offer != offer)
{
GDK_DISPLAY_NOTE (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("%p: offer for unknown offer %p of %s",
seat, offer, type));
return;
@@ -1191,7 +1193,7 @@ data_device_data_offer (void *data,
{
GdkWaylandSeat *seat = data;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("data device data offer, data device %p, offer %p",
data_device, offer));
@@ -1228,13 +1230,13 @@ data_device_enter (void *data,
if (offer != seat->pending_offer)
{
GDK_DISPLAY_NOTE (gdk_seat_get_display (GDK_SEAT (seat)), EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("%p: enter event for unknown offer %p, expected %p",
seat, offer, seat->pending_offer));
return;
}
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("data device enter, data device %p serial %u, surface %p, x %f y %f, offer %p",
data_device, serial, surface, wl_fixed_to_double (x), wl_fixed_to_double (y), offer));
@@ -1274,7 +1276,7 @@ data_device_leave (void *data,
{
GdkWaylandSeat *seat = data;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("data device leave, data device %p", data_device));
if (seat->drop == NULL)
@@ -1300,7 +1302,7 @@ data_device_motion (void *data,
GdkWaylandSeat *seat = data;
int origin_x, origin_y;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("data device motion, data_device = %p, time = %d, x = %f, y = %f",
data_device, time, wl_fixed_to_double (x), wl_fixed_to_double (y)));
@@ -1327,7 +1329,7 @@ data_device_drop (void *data,
GdkWaylandSeat *seat = data;
int origin_x, origin_y;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("data device drop, data device %p", data_device));
gdk_surface_get_origin (gdk_drop_get_surface (seat->drop), &origin_x, &origin_y);
@@ -1573,7 +1575,7 @@ pointer_handle_enter (void *data,
&event->crossing.x_root,
&event->crossing.y_root);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("enter, seat %p surface %p",
seat, seat->pointer_info.focus));
@@ -1621,7 +1623,7 @@ pointer_handle_leave (void *data,
&event->crossing.x_root,
&event->crossing.y_root);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("leave, seat %p surface %p",
seat, seat->pointer_info.focus));
@@ -1667,7 +1669,7 @@ pointer_handle_motion (void *data,
&event->motion.x_root,
&event->motion.y_root);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("motion %f %f, seat %p state %d",
wl_fixed_to_double (sx), wl_fixed_to_double (sy),
seat, event->motion.state));
@@ -1740,7 +1742,7 @@ pointer_handle_button (void *data,
else
seat->pointer_info.button_modifiers &= ~modifier;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("button %d %s, seat %p state %d",
event->button.button,
state ? "press" : "release",
@@ -1798,7 +1800,7 @@ pointer_handle_axis (void *data,
seat->pointer_info.time = time;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("scroll, axis %s, value %f, seat %p",
get_axis_name (axis), wl_fixed_to_double (value) / 10.0,
seat));
@@ -1813,7 +1815,7 @@ pointer_handle_frame (void *data,
{
GdkWaylandSeat *seat = data;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("frame, seat %p", seat));
gdk_wayland_seat_flush_frame_event (seat);
@@ -1854,7 +1856,7 @@ pointer_handle_axis_source (void *data,
pointer_frame->source = source;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("axis source %s, seat %p", get_axis_source_name (source), seat));
}
@@ -1886,7 +1888,7 @@ pointer_handle_axis_stop (void *data,
pointer_frame->is_scroll_stop = TRUE;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("axis %s stop, seat %p", get_axis_name (axis), seat));
}
@@ -1914,7 +1916,7 @@ pointer_handle_axis_discrete (void *data,
g_return_if_reached ();
}
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("discrete scroll, axis %s, value %d, seat %p",
get_axis_name (axis), value, seat));
}
@@ -1970,7 +1972,7 @@ keyboard_handle_enter (void *data,
gdk_event_set_device (event, seat->master_keyboard);
gdk_event_set_source_device (event, seat->keyboard);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("focus in, seat %p surface %p",
seat, seat->keyboard_focus));
@@ -2011,7 +2013,7 @@ keyboard_handle_leave (void *data,
seat->keyboard_focus = NULL;
seat->repeat_key = 0;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("focus out, seat %p surface %p",
seat, event->any.surface));
@@ -2106,7 +2108,7 @@ deliver_key_event (GdkWaylandSeat *seat,
_gdk_wayland_display_deliver_event (seat->display, event);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("keyboard %s event%s, surface %p, code %d, sym %d, "
"mods 0x%x",
(state ? "press" : "release"),
@@ -2394,7 +2396,7 @@ touch_handle_down (void *data,
mimic_pointer_emulating_touch_info (seat->touch_master, touch);
}
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("touch begin %f %f", event->touch.x, event->touch.y));
_gdk_wayland_display_deliver_event (seat->display, event);
@@ -2417,7 +2419,7 @@ touch_handle_up (void *data,
touch = gdk_wayland_seat_get_touch (seat, id);
event = _create_touch_event (seat, touch, GDK_TOUCH_END, time);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("touch end %f %f", event->touch.x, event->touch.y));
_gdk_wayland_display_deliver_event (seat->display, event);
@@ -2449,7 +2451,7 @@ touch_handle_motion (void *data,
event = _create_touch_event (seat, touch, GDK_TOUCH_UPDATE, time);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("touch update %f %f", event->touch.x, event->touch.y));
_gdk_wayland_display_deliver_event (seat->display, event);
@@ -2486,7 +2488,7 @@ touch_handle_cancel (void *data,
g_hash_table_iter_remove (&iter);
}
GDK_DISPLAY_NOTE (wayland_seat->display, EVENTS, g_message ("touch cancel"));
GDK_SEAT_NOTE (wayland_seat, EVENTS, g_message ("touch cancel"));
}
static void
@@ -2522,7 +2524,7 @@ emit_gesture_swipe_event (GdkWaylandSeat *seat,
&event->touchpad_swipe.x_root,
&event->touchpad_swipe.y_root);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("swipe event %d, coords: %f %f, seat %p state %d",
event->any.type, event->touchpad_swipe.x,
event->touchpad_swipe.y, seat,
@@ -2625,7 +2627,7 @@ emit_gesture_pinch_event (GdkWaylandSeat *seat,
&event->touchpad_pinch.x_root,
&event->touchpad_pinch.y_root);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("pinch event %d, coords: %f %f, seat %p state %d",
event->any.type, event->touchpad_pinch.x,
event->touchpad_pinch.y, seat,
@@ -2951,7 +2953,7 @@ seat_handle_capabilities (void *data,
GdkWaylandSeat *seat = data;
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
GDK_DISPLAY_NOTE (seat->display, MISC,
GDK_SEAT_NOTE (seat, MISC,
g_message ("seat %p with %s%s%s", wl_seat,
(caps & WL_SEAT_CAPABILITY_POINTER) ? " pointer, " : "",
(caps & WL_SEAT_CAPABILITY_KEYBOARD) ? " keyboard, " : "",
@@ -3174,7 +3176,7 @@ seat_handle_name (void *data,
const char *name)
{
/* We don't care about the name. */
GDK_DISPLAY_NOTE (GDK_WAYLAND_SEAT (data)->display, MISC,
GDK_SEAT_NOTE (GDK_WAYLAND_SEAT (data), MISC,
g_message ("seat %p name %s", seat, name));
}
@@ -3488,7 +3490,7 @@ tablet_tool_handle_proximity_in (void *data,
gdk_wayland_surface_get_wl_output (surface));
pointer_surface_update_scale (tablet->master);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("proximity in, seat %p surface %p tool %d",
seat, tablet->pointer_info.focus,
gdk_device_tool_get_tool_type (tool->tool)));
@@ -3500,11 +3502,10 @@ tablet_tool_handle_proximity_out (void *data,
{
GdkWaylandTabletToolData *tool = data;
GdkWaylandTabletData *tablet = tool->current_tablet;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat);
GdkEvent *event;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
g_message ("proximity out, seat %p, tool %d", seat,
GDK_SEAT_NOTE (tool->seat, EVENTS,
g_message ("proximity out, seat %p, tool %d", tool->seat,
gdk_device_tool_get_tool_type (tool->tool)));
event = gdk_wayland_tablet_get_frame_event (tablet, GDK_PROXIMITY_OUT);
@@ -3600,7 +3601,7 @@ tablet_tool_handle_motion (void *data,
tablet->pointer_info.surface_x = wl_fixed_to_double (sx);
tablet->pointer_info.surface_y = wl_fixed_to_double (sy);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("tablet motion %f %f",
tablet->pointer_info.surface_x,
tablet->pointer_info.surface_y));
@@ -3633,7 +3634,7 @@ tablet_tool_handle_pressure (void *data,
_gdk_device_translate_axis (tablet->current_device, axis_index,
pressure, &tablet->axes[axis_index]);
GDK_DISPLAY_NOTE (GDK_WAYLAND_SEAT (tool->seat)->display, EVENTS,
GDK_SEAT_NOTE (tool->seat, EVENTS,
g_message ("tablet tool %d pressure %d",
gdk_device_tool_get_tool_type (tool->tool), pressure));
}
@@ -3650,7 +3651,7 @@ tablet_tool_handle_distance (void *data,
_gdk_device_translate_axis (tablet->current_device, axis_index,
distance, &tablet->axes[axis_index]);
GDK_DISPLAY_NOTE (GDK_WAYLAND_SEAT (tool->seat)->display, EVENTS,
GDK_SEAT_NOTE (tool->seat, EVENTS,
g_message ("tablet tool %d distance %d",
gdk_device_tool_get_tool_type (tool->tool), distance));
}
@@ -3673,7 +3674,7 @@ tablet_tool_handle_tilt (void *data,
wl_fixed_to_double (ytilt),
&tablet->axes[ytilt_axis_index]);
GDK_DISPLAY_NOTE (GDK_WAYLAND_SEAT (tool->seat)->display, EVENTS,
GDK_SEAT_NOTE (tool->seat, EVENTS,
g_message ("tablet tool %d tilt %f/%f",
gdk_device_tool_get_tool_type (tool->tool),
wl_fixed_to_double (xtilt), wl_fixed_to_double (ytilt)));
@@ -3728,7 +3729,7 @@ tablet_tool_handle_rotation (void *data,
wl_fixed_to_double (degrees),
&tablet->axes[axis_index]);
GDK_DISPLAY_NOTE (GDK_WAYLAND_SEAT (tool->seat)->display, EVENTS,
GDK_SEAT_NOTE (tool->seat, EVENTS,
g_message ("tablet tool %d rotation %f",
gdk_device_tool_get_tool_type (tool->tool),
wl_fixed_to_double (degrees)));
@@ -3746,7 +3747,7 @@ tablet_tool_handle_slider (void *data,
_gdk_device_translate_axis (tablet->current_device, axis_index,
position, &tablet->axes[axis_index]);
GDK_DISPLAY_NOTE (GDK_WAYLAND_SEAT (tool->seat)->display, EVENTS,
GDK_SEAT_NOTE (tool->seat, EVENTS,
g_message ("tablet tool %d slider %d",
gdk_device_tool_get_tool_type (tool->tool), position));
}
@@ -3762,7 +3763,7 @@ tablet_tool_handle_wheel (void *data,
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
GdkEvent *event;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("tablet tool %d wheel %d/%d",
gdk_device_tool_get_tool_type (tool->tool), degrees, clicks));
@@ -3792,10 +3793,9 @@ tablet_tool_handle_frame (void *data,
{
GdkWaylandTabletToolData *tool = data;
GdkWaylandTabletData *tablet = tool->current_tablet;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
GdkEvent *frame_event;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (tablet->seat, EVENTS,
g_message ("tablet frame, time %d", time));
frame_event = tablet->pointer_info.frame.event;
@@ -3838,10 +3838,8 @@ tablet_pad_ring_handle_source (void *data,
uint32_t source)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad ring handle source, ring = %p source = %d",
wp_tablet_pad_ring, source));
@@ -3854,10 +3852,8 @@ tablet_pad_ring_handle_angle (void *data,
wl_fixed_t angle)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad ring handle angle, ring = %p angle = %f",
wp_tablet_pad_ring, wl_fixed_to_double (angle)));
@@ -3869,10 +3865,8 @@ tablet_pad_ring_handle_stop (void *data,
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad ring handle stop, ring = %p", wp_tablet_pad_ring));
group->axis_tmp_info.is_stop = TRUE;
@@ -3888,7 +3882,7 @@ tablet_pad_ring_handle_frame (void *data,
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GdkEvent *event;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("tablet pad ring handle frame, ring = %p", wp_tablet_pad_ring));
event = gdk_event_new (GDK_PAD_RING);
@@ -3918,10 +3912,8 @@ tablet_pad_strip_handle_source (void *data,
uint32_t source)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad strip handle source, strip = %p source = %d",
wp_tablet_pad_strip, source));
@@ -3934,10 +3926,8 @@ tablet_pad_strip_handle_position (void *data,
uint32_t position)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad strip handle position, strip = %p position = %d",
wp_tablet_pad_strip, position));
@@ -3949,10 +3939,8 @@ tablet_pad_strip_handle_stop (void *data,
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad strip handle stop, strip = %p",
wp_tablet_pad_strip));
@@ -3969,7 +3957,7 @@ tablet_pad_strip_handle_frame (void *data,
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GdkEvent *event;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("tablet pad strip handle frame, strip = %p",
wp_tablet_pad_strip));
@@ -4001,11 +3989,9 @@ tablet_pad_group_handle_buttons (void *data,
struct wl_array *buttons)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
uint32_t *p;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad group handle buttons, pad group = %p, n_buttons = %" G_GSIZE_FORMAT,
wp_tablet_pad_group, buttons->size));
@@ -4023,10 +4009,8 @@ tablet_pad_group_handle_ring (void *data,
struct zwp_tablet_pad_ring_v2 *wp_tablet_pad_ring)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad group handle ring, pad group = %p, ring = %p",
wp_tablet_pad_group, wp_tablet_pad_ring));
@@ -4044,10 +4028,8 @@ tablet_pad_group_handle_strip (void *data,
struct zwp_tablet_pad_strip_v2 *wp_tablet_pad_strip)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad group handle strip, pad group = %p, strip = %p",
wp_tablet_pad_group, wp_tablet_pad_strip));
@@ -4065,10 +4047,8 @@ tablet_pad_group_handle_modes (void *data,
uint32_t modes)
{
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad group handle modes, pad group = %p, n_modes = %d",
wp_tablet_pad_group, modes));
@@ -4079,11 +4059,11 @@ static void
tablet_pad_group_handle_done (void *data,
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group)
{
#ifdef G_ENABLE_DEBUG
GdkWaylandTabletPadGroupData *group = data;
GdkWaylandTabletPadData *pad = group->pad;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
#endif
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (group->pad->seat, EVENTS,
g_message ("tablet pad group handle done, pad group = %p",
wp_tablet_pad_group));
}
@@ -4101,7 +4081,7 @@ tablet_pad_group_handle_mode (void *data,
GdkEvent *event;
guint n_group;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("tablet pad group handle mode, pad group = %p, mode = %d",
wp_tablet_pad_group, mode));
@@ -4137,9 +4117,8 @@ tablet_pad_handle_group (void *data,
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandTabletPadGroupData *group;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle group, pad group = %p, group = %p",
wp_tablet_pad_group, wp_tablet_pad_group));
@@ -4159,9 +4138,8 @@ tablet_pad_handle_path (void *data,
const char *path)
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle path, pad = %p, path = %s",
wp_tablet_pad, path));
@@ -4174,9 +4152,8 @@ tablet_pad_handle_buttons (void *data,
uint32_t buttons)
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle buttons, pad = %p, n_buttons = %d",
wp_tablet_pad, buttons));
@@ -4188,9 +4165,8 @@ tablet_pad_handle_done (void *data,
struct zwp_tablet_pad_v2 *wp_tablet_pad)
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle done, pad = %p", wp_tablet_pad));
pad->device =
@@ -4200,11 +4176,11 @@ tablet_pad_handle_done (void *data,
"input-source", GDK_SOURCE_TABLET_PAD,
"input-mode", GDK_MODE_SCREEN,
"display", gdk_seat_get_display (pad->seat),
"seat", seat,
"seat", pad->seat,
NULL);
_gdk_device_set_associated_device (pad->device, seat->master_keyboard);
gdk_seat_device_added (GDK_SEAT (seat), pad->device);
_gdk_device_set_associated_device (pad->device, GDK_WAYLAND_SEAT (pad->seat)->master_keyboard);
gdk_seat_device_added (GDK_SEAT (pad->seat), pad->device);
}
static void
@@ -4216,11 +4192,10 @@ tablet_pad_handle_button (void *data,
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandTabletPadGroupData *group;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GdkEvent *event;
gint n_group;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle button, pad = %p, button = %d, state = %d",
wp_tablet_pad, button, state));
@@ -4230,7 +4205,7 @@ tablet_pad_handle_button (void *data,
event = gdk_event_new (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ?
GDK_PAD_BUTTON_PRESS :
GDK_PAD_BUTTON_RELEASE);
g_set_object (&event->any.surface, seat->keyboard_focus);
g_set_object (&event->any.surface, GDK_WAYLAND_SEAT (pad->seat)->keyboard_focus);
event->pad_button.button = button;
event->pad_button.group = n_group;
event->pad_button.mode = group->current_mode;
@@ -4238,8 +4213,7 @@ tablet_pad_handle_button (void *data,
gdk_event_set_device (event, pad->device);
gdk_event_set_source_device (event, pad->device);
_gdk_wayland_display_deliver_event (gdk_seat_get_display (pad->seat),
event);
_gdk_wayland_display_deliver_event (gdk_seat_get_display (pad->seat), event);
}
static void
@@ -4250,10 +4224,9 @@ tablet_pad_handle_enter (void *data,
struct wl_surface *surface)
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle enter, pad = %p, tablet = %p surface = %p",
wp_tablet_pad, wp_tablet, surface));
@@ -4269,9 +4242,8 @@ tablet_pad_handle_leave (void *data,
struct wl_surface *surface)
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle leave, pad = %p, surface = %p",
wp_tablet_pad, surface));
@@ -4287,9 +4259,8 @@ tablet_pad_handle_removed (void *data,
struct zwp_tablet_pad_v2 *wp_tablet_pad)
{
GdkWaylandTabletPadData *pad = data;
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (pad->seat);
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (pad->seat, EVENTS,
g_message ("tablet pad handle removed, pad = %p", wp_tablet_pad));
/* Remove from the current tablet */
@@ -4461,7 +4432,7 @@ pointer_surface_enter (void *data,
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
GdkWaylandTabletData *tablet;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("pointer surface of seat %p entered output %p",
seat, output));
@@ -4490,7 +4461,7 @@ pointer_surface_leave (void *data,
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
GdkWaylandTabletData *tablet;
GDK_DISPLAY_NOTE (seat->display, EVENTS,
GDK_SEAT_NOTE (seat, EVENTS,
g_message ("pointer surface of seat %p left output %p",
seat, output));

View File

@@ -47,6 +47,7 @@
#include "gdkglcontext-wayland.h"
#include "gdkvulkancontext-wayland.h"
#include "gdkwaylandmonitor.h"
#include "gdkprofilerprivate.h"
#include <wayland/pointer-gestures-unstable-v1-client-protocol.h>
#include "tablet-unstable-v2-client-protocol.h"
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
@@ -725,7 +726,6 @@ static void
gdk_wayland_display_finalize (GObject *object)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object);
guint i;
_gdk_wayland_display_finalize_cursors (display_wayland);
@@ -733,13 +733,10 @@ gdk_wayland_display_finalize (GObject *object)
g_free (display_wayland->cursor_theme_name);
xkb_context_unref (display_wayland->xkb_context);
for (i = 0; i < GDK_WAYLAND_THEME_SCALES_COUNT; i++)
if (display_wayland->cursor_theme)
{
if (display_wayland->scaled_cursor_themes[i])
{
wl_cursor_theme_destroy (display_wayland->scaled_cursor_themes[i]);
display_wayland->scaled_cursor_themes[i] = NULL;
}
wl_cursor_theme_destroy (display_wayland->cursor_theme);
display_wayland->cursor_theme = NULL;
}
g_ptr_array_free (display_wayland->monitors, TRUE);
@@ -1059,6 +1056,33 @@ gdk_wayland_display_get_toplevel_surfaces (GdkDisplay *display)
return GDK_WAYLAND_DISPLAY (display)->toplevels;
}
static struct wl_cursor_theme *
get_cursor_theme (GdkWaylandDisplay *display_wayland,
const char *name,
int size)
{
const char * const *xdg_data_dirs;
struct wl_cursor_theme *theme = NULL;
int i;
xdg_data_dirs = g_get_system_data_dirs ();
for (i = 0; xdg_data_dirs[i]; i++)
{
char *path = g_build_filename (xdg_data_dirs[i], "icons", name, "cursors", NULL);
if (g_file_test (path, G_FILE_TEST_IS_DIR))
theme = wl_cursor_theme_create (path, size, display_wayland->shm);
g_free (path);
if (theme)
return theme;
}
/* This may fall back to builtin cursors */
return wl_cursor_theme_create ("/usr/share/icons/default/cursors", size, display_wayland->shm);
}
void
gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
const gchar *name,
@@ -1066,7 +1090,6 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY(display);
struct wl_cursor_theme *theme;
int i;
g_assert (display_wayland);
g_assert (display_wayland->shm);
@@ -1075,22 +1098,20 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
display_wayland->cursor_theme_size == size)
return;
theme = wl_cursor_theme_load (name, size, display_wayland->shm);
theme = get_cursor_theme (display_wayland, name, size);
if (theme == NULL)
{
g_warning ("Failed to load cursor theme %s", name);
return;
}
for (i = 0; i < GDK_WAYLAND_THEME_SCALES_COUNT; i++)
if (display_wayland->cursor_theme)
{
if (display_wayland->scaled_cursor_themes[i])
{
wl_cursor_theme_destroy (display_wayland->scaled_cursor_themes[i]);
display_wayland->scaled_cursor_themes[i] = NULL;
}
wl_cursor_theme_destroy (display_wayland->cursor_theme);
display_wayland->cursor_theme = NULL;
}
display_wayland->scaled_cursor_themes[0] = theme;
display_wayland->cursor_theme = theme;
if (display_wayland->cursor_theme_name != NULL)
g_free (display_wayland->cursor_theme_name);
display_wayland->cursor_theme_name = g_strdup (name);
@@ -1098,31 +1119,11 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
}
struct wl_cursor_theme *
_gdk_wayland_display_get_scaled_cursor_theme (GdkWaylandDisplay *display_wayland,
guint scale)
_gdk_wayland_display_get_cursor_theme (GdkWaylandDisplay *display_wayland)
{
struct wl_cursor_theme *theme;
g_assert (display_wayland->cursor_theme_name);
g_assert (scale <= GDK_WAYLAND_MAX_THEME_SCALE);
g_assert (scale >= 1);
theme = display_wayland->scaled_cursor_themes[scale - 1];
if (!theme)
{
theme = wl_cursor_theme_load (display_wayland->cursor_theme_name,
display_wayland->cursor_theme_size * scale,
display_wayland->shm);
if (theme == NULL)
{
g_warning ("Failed to load cursor theme %s with scale %u",
display_wayland->cursor_theme_name, scale);
return NULL;
}
display_wayland->scaled_cursor_themes[scale - 1] = theme;
}
return theme;
return display_wayland->cursor_theme;
}
static void
@@ -1131,6 +1132,7 @@ _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *display_wayland)
guint size;
const gchar *name;
GValue v = G_VALUE_INIT;
gint64 before = g_get_monotonic_time ();
g_assert (display_wayland);
g_assert (display_wayland->shm);
@@ -1150,6 +1152,12 @@ _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *display_wayland)
gdk_wayland_display_set_cursor_theme (GDK_DISPLAY (display_wayland), name, size);
g_value_unset (&v);
if (gdk_profiler_is_running ())
{
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "wayland", "load cursor theme");
}
}
guint32
@@ -2307,10 +2315,11 @@ xdg_output_handle_description (void *data,
struct zxdg_output_v1 *xdg_output,
const char *description)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
GDK_NOTE (MISC,
g_message ("handle description xdg-output %d", monitor->id));
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
g_message ("handle description xdg-output %d", monitor->id);
});
}
static const struct zxdg_output_v1_listener xdg_output_listener = {

View File

@@ -26,7 +26,6 @@
#include <stdint.h>
#include <wayland-client.h>
#include <wayland-cursor.h>
#include <wayland-egl.h>
#include <gdk/wayland/tablet-unstable-v2-client-protocol.h>
#include <gdk/wayland/gtk-shell-client-protocol.h>
@@ -45,6 +44,7 @@
#include "gdkdisplayprivate.h"
#include "gdkwaylanddevice.h"
#include "cursor/wayland-cursor.h"
#include <epoxy/egl.h>
@@ -126,7 +126,7 @@ struct _GdkWaylandDisplay
GList *current_popups;
struct wl_cursor_theme *scaled_cursor_themes[GDK_WAYLAND_THEME_SCALES_COUNT];
struct wl_cursor_theme *cursor_theme;
gchar *cursor_theme_name;
int cursor_theme_size;
GHashTable *cursor_surface_cache;

View File

@@ -181,19 +181,17 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
gpointer user_data)
{
GdkWaylandDrop *wayland_drop = GDK_WAYLAND_DROP (drop);
GdkDisplay *display;
GInputStream *stream;
const char *mime_type;
int pipe_fd[2];
GError *error = NULL;
GTask *task;
display = gdk_drop_get_display (drop),
task = g_task_new (drop, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
g_task_set_source_tag (task, gdk_wayland_drop_read_async);
GDK_DISPLAY_NOTE (display, DND, char *s = gdk_content_formats_to_string (formats);
GDK_DISPLAY_NOTE (gdk_drop_get_display (drop), DND, char *s = gdk_content_formats_to_string (formats);
g_message ("%p: read for %s", drop, s);
g_free (s); );
mime_type = gdk_content_formats_match_mime_type (formats,

View File

@@ -31,6 +31,7 @@
#include "gdkinternals.h"
#include "gdksurfaceprivate.h"
#include "gdkprofilerprivate.h"
#include "gdkintl.h"
@@ -238,6 +239,7 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_request_frame (surface);
gdk_profiler_add_mark (g_get_monotonic_time () * 1000, 0, "wayland", "swap buffers");
if (display_wayland->have_egl_swap_buffers_with_damage)
{
int i, j, n_rects = cairo_region_num_rectangles (painted);

View File

@@ -57,8 +57,7 @@ gboolean _gdk_wayland_keymap_key_is_modifier (GdkKeymap *keymap,
void _gdk_wayland_display_init_cursors (GdkWaylandDisplay *display);
void _gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display);
struct wl_cursor_theme * _gdk_wayland_display_get_scaled_cursor_theme (GdkWaylandDisplay *display_wayland,
guint scale);
struct wl_cursor_theme * _gdk_wayland_display_get_cursor_theme (GdkWaylandDisplay *display_wayland);
void _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display,
guint *width,

View File

@@ -357,6 +357,7 @@ frame_callback (void *data,
GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
GdkFrameTimings *timings;
gdk_profiler_add_mark (g_get_monotonic_time () * 1000, 0, "wayland", "frame event");
GDK_DISPLAY_NOTE (GDK_DISPLAY (display_wayland), EVENTS, g_message ("frame %p", surface));
wl_callback_destroy (callback);
@@ -395,10 +396,10 @@ frame_callback (void *data,
#ifdef G_ENABLE_DEBUG
if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
_gdk_frame_clock_debug_print_timings (clock, timings);
#endif
if (gdk_profiler_is_running ())
_gdk_frame_clock_add_timings_to_profiler (clock, timings);
#endif
}
static const struct wl_callback_listener frame_listener = {
@@ -477,6 +478,7 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
* before we need to stage any changes, then we can take it back and
* use it again.
*/
gdk_profiler_add_mark (g_get_monotonic_time () * 1000, 0, "wayland", "surface commit");
wl_surface_commit (impl->display_server.wl_surface);
impl->pending_commit = FALSE;
@@ -1508,6 +1510,7 @@ gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG)
_gdk_wayland_screen_add_orphan_dialog (surface);
gdk_profiler_add_mark (g_get_monotonic_time () * 1000, 0, "wayland", "surface commit");
wl_surface_commit (impl->display_server.wl_surface);
}
@@ -2302,6 +2305,7 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface *surface,
}
}
gdk_profiler_add_mark (g_get_monotonic_time () * 1000, 0, "wayland", "surface commit");
wl_surface_commit (impl->display_server.wl_surface);
impl->popup_parent = parent;
@@ -4109,7 +4113,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

View File

@@ -1,3 +1,5 @@
subdir('cursor')
gdk_wayland_sources = files([
'gdkapplaunchcontext-wayland.c',
'gdkcairocontext-wayland.c',
@@ -33,7 +35,6 @@ gdk_wayland_deps = [
xkbdep,
wlclientdep,
wlprotocolsdep,
wlcursordep,
wlegldep,
]
@@ -105,4 +106,5 @@ libgdk_wayland = static_library('gdk-wayland',
'-DG_LOG_DOMAIN="Gdk"',
] + common_cflags,
link_args: common_ldflags,
dependencies: [ gdk_deps, gdk_wayland_deps, ])
link_with: [libwayland_cursor, ],
dependencies: [ gdk_deps, gdk_wayland_deps])

View File

@@ -65,16 +65,15 @@ print_atoms (GdkX11Clipboard *cb,
const Atom *atoms,
gsize n_atoms)
{
GdkDisplay *display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
GDK_DISPLAY_NOTE (display, CLIPBOARD,
GDK_DISPLAY_NOTE (gdk_clipboard_get_display (GDK_CLIPBOARD (cb)), CLIPBOARD, {
gsize i;
GdkDisplay *display = gdk_clipboard_get_display (GDK_CLIPBOARD (cb));
g_printerr ("%s: %s [ ", cb->selection, prefix);
for (i = 0; i < n_atoms; i++)
g_printerr ("%s%s", i > 0 ? ", " : "", gdk_x11_get_xatom_name_for_display (display , atoms[i]));
g_printerr (" ]\n");
);
});
}
static void
@@ -86,9 +85,7 @@ gdk_x11_clipboard_default_output_done (GObject *clipboard,
if (!gdk_clipboard_write_finish (GDK_CLIPBOARD (clipboard), result, &error))
{
GdkDisplay *display = gdk_clipboard_get_display (GDK_CLIPBOARD (clipboard));
GDK_DISPLAY_NOTE (display, CLIPBOARD,
GDK_DISPLAY_NOTE (gdk_clipboard_get_display (GDK_CLIPBOARD (clipboard)), CLIPBOARD,
g_printerr ("%s: failed to write stream: %s\n",
GDK_X11_CLIPBOARD (clipboard)->selection, error->message));
g_error_free (error);
@@ -440,16 +437,20 @@ gdk_x11_clipboard_xevent (GdkDisplay *display,
case SelectionRequest:
{
const char *target, *property;
#ifdef G_ENABLE_DEBUG
const char *target, *property;
#endif
if (xevent->xselectionrequest.selection != cb->xselection)
return FALSE;
#ifdef G_ENABLE_DEBUG
target = gdk_x11_get_xatom_name_for_display (display, xevent->xselectionrequest.target);
if (xevent->xselectionrequest.property == None)
property = target;
else
property = gdk_x11_get_xatom_name_for_display (display, xevent->xselectionrequest.property);
#endif
if (!gdk_clipboard_is_local (GDK_CLIPBOARD (cb)))
{

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;
@@ -1746,16 +1749,20 @@ gdk_x11_drag_xevent (GdkDisplay *display,
case SelectionRequest:
{
#ifdef G_ENABLE_DEBUG
const char *target, *property;
#endif
if (xevent->xselectionrequest.selection != xselection)
return FALSE;
#ifdef G_ENABLE_DEBUG
target = gdk_x11_get_xatom_name_for_display (display, xevent->xselectionrequest.target);
if (xevent->xselectionrequest.property == None)
property = target;
else
property = gdk_x11_get_xatom_name_for_display (display, xevent->xselectionrequest.property);
#endif
if (xevent->xselectionrequest.requestor == None)
{
@@ -1814,6 +1821,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 +2145,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);
}

View File

@@ -145,9 +145,9 @@ gdk_x11_drop_read_got_stream (GObject *source,
}
else
{
const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
#if 0
gsize i;
const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
for (i = 0; i < G_N_ELEMENTS (special_targets); i++)
{
@@ -166,7 +166,7 @@ gdk_x11_drop_read_got_stream (GObject *source,
#endif
GDK_NOTE (DND, g_printerr ("reading DND as %s now\n",
mime_type));
(const char *)((GSList *) g_task_get_task_data (task))->data));
g_task_return_pointer (task, stream, g_object_unref);
}
@@ -732,14 +732,14 @@ gdk_x11_drop_do_nothing (Window window,
gboolean success,
gpointer data)
{
#ifdef G_ENABLE_DEBUG
GdkDisplay *display = data;
if (!success)
{
GDK_DISPLAY_NOTE (display, DND,
g_message ("Send event to %lx failed",
window));
GDK_DISPLAY_NOTE (display, DND, g_message ("Send event to %lx failed", window));
}
#endif
}
static void

View File

@@ -535,17 +535,16 @@ transform_rect (GskGLRenderer *self,
RenderOpBuilder *builder,
const GskRoundedRect *rect)
{
const float scale = ops_get_scale (builder);
GskRoundedRect r;
int i;
ops_transform_bounds_modelview (builder, &rect->bounds, &r.bounds);
r.bounds.origin.x = builder->dx + rect->bounds.origin.x;
r.bounds.origin.y = builder->dy + rect->bounds.origin.y;
r.bounds.size = rect->bounds.size;
for (i = 0; i < 4; i ++)
{
r.corner[i].width = rect->corner[i].width * scale;
r.corner[i].height = rect->corner[i].height * scale;
}
r.corner[0] = rect->corner[0];
r.corner[1] = rect->corner[1];
r.corner[2] = rect->corner[2];
r.corner[3] = rect->corner[3];
return r;
}
@@ -745,25 +744,22 @@ render_border_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const float min_x = builder->dx + node->bounds.origin.x;
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const GdkRGBA *colors = gsk_border_node_peek_colors (node);
const GskRoundedRect *rounded_outline = gsk_border_node_peek_outline (node);
const float *og_widths = gsk_border_node_peek_widths (node);
GskRoundedRect outline;
float widths[4];
const float *widths = gsk_border_node_peek_widths (node);
int i;
struct {
float w;
float h;
} sizes[4];
if (og_widths[0] == og_widths[1] &&
og_widths[0] == og_widths[2] &&
og_widths[0] == og_widths[3] &&
if (widths[0] == widths[1] &&
widths[0] == widths[2] &&
widths[0] == widths[3] &&
gdk_rgba_equal (&colors[0], &colors[1]) &&
gdk_rgba_equal (&colors[0], &colors[2]) &&
gdk_rgba_equal (&colors[0], &colors[3]))
@@ -774,7 +770,7 @@ render_border_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = &colors[0];
op->outline = transform_rect (self, builder, rounded_outline);
op->spread = og_widths[0] * scale;
op->spread = widths[0];
op->offset[0] = 0;
op->offset[1] = 0;
@@ -782,9 +778,6 @@ render_border_node (GskGLRenderer *self,
return;
}
for (i = 0; i < 4; i ++)
widths[i] = og_widths[i];
/* Top left */
if (widths[3] > 0)
sizes[0].w = MAX (widths[3], rounded_outline->corner[0].width);
@@ -830,9 +823,6 @@ render_border_node (GskGLRenderer *self,
else
sizes[3].h = 0;
for (i = 0; i < 4; i ++)
widths[i] *= scale;
{
const GskQuadVertex side_data[4][6] = {
/* Top */
@@ -877,6 +867,7 @@ render_border_node (GskGLRenderer *self,
}
};
int indices[4] = { 0, 1, 2, 3 };
GskRoundedRect outline;
/* We sort them by color */
sort_border_sides (colors, indices);
@@ -1189,17 +1180,16 @@ render_rounded_clip_node (GskGLRenderer *self,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
GskRoundedRect child_clip = *gsk_rounded_clip_node_peek_clip (node);
GskRoundedRect transformed_clip;
const GskRoundedRect *clip = gsk_rounded_clip_node_peek_clip (node);
GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
GskRoundedRect transformed_clip;
gboolean need_offscreen;
int i;
if (node_is_invisible (child))
return;
transformed_clip = child_clip;
ops_transform_bounds_modelview (builder, &child_clip.bounds, &transformed_clip.bounds);
ops_transform_bounds_modelview (builder, &clip->bounds, &transformed_clip.bounds);
if (!ops_has_clip (builder))
need_offscreen = FALSE;
@@ -1215,8 +1205,8 @@ render_rounded_clip_node (GskGLRenderer *self,
* the new clip and add the render ops */
for (i = 0; i < 4; i ++)
{
transformed_clip.corner[i].width *= scale;
transformed_clip.corner[i].height *= scale;
transformed_clip.corner[i].width = clip->corner[i].width * scale;
transformed_clip.corner[i].height = clip->corner[i].height * scale;
}
ops_push_clip (builder, &transformed_clip);
@@ -1225,7 +1215,7 @@ render_rounded_clip_node (GskGLRenderer *self,
}
else
{
graphene_matrix_t scale_matrix;
GskRoundedRect scaled_clip;
gboolean is_offscreen;
TextureRegion region;
/* NOTE: We are *not* transforming the clip by the current modelview here.
@@ -1234,18 +1224,19 @@ render_rounded_clip_node (GskGLRenderer *self,
*
* We do, however, apply the scale factor to the child clip of course.
*/
graphene_matrix_init_scale (&scale_matrix, scale, scale, 1.0f);
graphene_matrix_transform_bounds (&scale_matrix, &child_clip.bounds, &child_clip.bounds);
scaled_clip.bounds.origin.x = clip->bounds.origin.x * scale;
scaled_clip.bounds.origin.y = clip->bounds.origin.y * scale;
scaled_clip.bounds.size.width = clip->bounds.size.width * scale;
scaled_clip.bounds.size.height = clip->bounds.size.height * scale;
/* Increase corner radius size by scale factor */
for (i = 0; i < 4; i ++)
{
child_clip.corner[i].width *= scale;
child_clip.corner[i].height *= scale;
scaled_clip.corner[i].width = clip->corner[i].width * scale;
scaled_clip.corner[i].height = clip->corner[i].height * scale;
}
ops_push_clip (builder, &child_clip);
ops_push_clip (builder, &scaled_clip);
if (!add_offscreen_ops (self, builder, &node->bounds,
child,
&region, &is_offscreen,
@@ -1455,6 +1446,9 @@ render_blur_node (GskGLRenderer *self,
GskRenderNode *child = gsk_blur_node_get_child (node);
TextureRegion blurred_region;
if (node_is_invisible (child))
return;
if (blur_radius <= 0)
{
gsk_gl_renderer_add_render_ops (self, child, builder);
@@ -1481,7 +1475,6 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const float blur_radius = gsk_inset_shadow_node_get_blur_radius (node);
const float dx = gsk_inset_shadow_node_get_dx (node);
const float dy = gsk_inset_shadow_node_get_dy (node);
@@ -1494,9 +1487,9 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = gsk_inset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node));
op->spread = spread * scale;
op->offset[0] = dx * scale;
op->offset[1] = dy * scale;
op->spread = spread;
op->offset[0] = dx;
op->offset[1] = dy;
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
@@ -1647,7 +1640,6 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const GskRoundedRect *outline = gsk_outset_shadow_node_peek_outline (node);
const float spread = gsk_outset_shadow_node_get_spread (node);
const float dx = gsk_outset_shadow_node_get_dx (node);
@@ -1658,13 +1650,14 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
op->color = gsk_outset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, outline);
op->spread = spread * scale;
op->offset[0] = dx * scale;
op->offset[1] = dy * scale;
op->spread = spread;
op->offset[0] = dx;
op->offset[1] = dy;
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
static GdkRGBA COLOR_WHITE = { 1, 1, 1, 1 };
static inline void
render_outset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
@@ -1717,7 +1710,6 @@ render_outset_shadow_node (GskGLRenderer *self,
cached_tid = gsk_gl_shadow_cache_get_texture_id (&self->shadow_cache,
self->gl_driver,
&scaled_outline,
color,
blur_radius);
if (cached_tid == 0)
@@ -1749,7 +1741,7 @@ render_outset_shadow_node (GskGLRenderer *self,
/* Draw outline */
ops_set_program (builder, &self->color_program);
ops_push_clip (builder, &scaled_outline);
ops_set_color (builder, color);
ops_set_color (builder, &COLOR_WHITE);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { 0, }, { 0, 1 }, },
{ { 0, texture_height }, { 0, 0 }, },
@@ -1776,7 +1768,6 @@ render_outset_shadow_node (GskGLRenderer *self,
gsk_gl_driver_mark_texture_permanent (self->gl_driver, blurred_texture_id);
gsk_gl_shadow_cache_commit (&self->shadow_cache,
&scaled_outline,
color,
blur_radius,
blurred_texture_id);
}
@@ -1786,6 +1777,7 @@ render_outset_shadow_node (GskGLRenderer *self,
}
ops_set_program (builder, &self->outset_shadow_program);
ops_set_color (builder, color);
ops_set_texture (builder, blurred_texture_id);
shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
@@ -2163,14 +2155,24 @@ render_cross_fade_node (GskGLRenderer *self,
start_node,
&start_region, &is_offscreen1,
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
g_assert_not_reached ();
{
gsk_gl_renderer_add_render_ops (self, end_node, builder);
return;
}
if (!add_offscreen_ops (self, builder,
&node->bounds,
end_node,
&end_region, &is_offscreen2,
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
g_assert_not_reached ();
{
load_vertex_data_with_region (ops_draw (builder, NULL),
node,
builder,
&start_region,
TRUE);
return;
}
ops_set_program (builder, &self->cross_fade_program);
@@ -2576,6 +2578,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
gboolean success = TRUE;
gsk_gl_shader_builder_init (&shader_builder,
"/org/gtk/libgsk/glsl/preamble.glsl",
"/org/gtk/libgsk/glsl/preamble.vs.glsl",
"/org/gtk/libgsk/glsl/preamble.fs.glsl");
@@ -2660,6 +2663,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow, outline_rect);
/* outset shadow */
INIT_PROGRAM_UNIFORM_LOCATION (outset_shadow, color);
INIT_PROGRAM_UNIFORM_LOCATION (outset_shadow, outline_rect);
/* unblurred outset shadow */
@@ -3484,7 +3488,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
gsk_profiler_push_samples (profiler);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (start_time, cpu_time, "render", "");
gdk_profiler_add_mark (start_time, cpu_time, "GL render", "");
#endif
}

View File

@@ -180,13 +180,15 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst)
{
graphene_rect_t r = *src;
g_assert (builder->mv_stack != NULL);
g_assert (builder->mv_stack->len >= 1);
gsk_transform_transform_bounds (builder->current_modelview, src, dst);
r.origin.x += builder->dx;
r.origin.y += builder->dy;
dst->origin.x += builder->dx * builder->scale_x;
dst->origin.y += builder->dy * builder->scale_y;
gsk_transform_transform_bounds (builder->current_modelview, &r, dst);
}
void

View File

@@ -73,6 +73,7 @@ struct _Program
int outline_rect_location;
} inset_shadow;
struct {
int color_location;
int outline_rect_location;
} outset_shadow;
struct {

View File

@@ -9,14 +9,17 @@
void
gsk_gl_shader_builder_init (GskGLShaderBuilder *self,
const char *common_preamble_resource_path,
const char *vs_preamble_resource_path,
const char *fs_preamble_resource_path)
{
memset (self, 0, sizeof (*self));
self->preamble = g_resources_lookup_data (common_preamble_resource_path, 0, NULL);
self->vs_preamble = g_resources_lookup_data (vs_preamble_resource_path, 0, NULL);
self->fs_preamble = g_resources_lookup_data (fs_preamble_resource_path, 0, NULL);
g_assert (self->preamble);
g_assert (self->vs_preamble);
g_assert (self->fs_preamble);
}
@@ -24,6 +27,7 @@ gsk_gl_shader_builder_init (GskGLShaderBuilder *self,
void
gsk_gl_shader_builder_finish (GskGLShaderBuilder *self)
{
g_bytes_unref (self->preamble);
g_bytes_unref (self->vs_preamble);
g_bytes_unref (self->fs_preamble);
}
@@ -102,13 +106,14 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
"#version %d\n", self->version);
vertex_id = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vertex_id, 7,
glShaderSource (vertex_id, 8,
(const char *[]) {
version_buffer,
self->debugging ? "#define GSK_DEBUG 1\n" : "",
self->legacy ? "#define GSK_LEGACY 1\n" : "",
self->gl3 ? "#define GSK_GL3 1\n" : "",
self->gles ? "#define GSK_GLES 1\n" : "",
g_bytes_get_data (self->preamble, NULL),
g_bytes_get_data (self->vs_preamble, NULL),
vertex_shader_start
},
@@ -119,6 +124,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
-1,
-1,
-1,
-1,
fragment_shader_start - vertex_shader_start
});
glCompileShader (vertex_id);
@@ -130,13 +136,14 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
}
fragment_id = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fragment_id, 7,
glShaderSource (fragment_id, 8,
(const char *[]) {
version_buffer,
self->debugging ? "#define GSK_DEBUG 1\n" : "",
self->legacy ? "#define GSK_LEGACY 1\n" : "",
self->gl3 ? "#define GSK_GL3 1\n" : "",
self->gles ? "#define GSK_GLES 1\n" : "",
g_bytes_get_data (self->preamble, NULL),
g_bytes_get_data (self->fs_preamble, NULL),
fragment_shader_start
},
@@ -148,6 +155,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
-1,
-1,
-1,
-1,
});
glCompileShader (fragment_id);

View File

@@ -8,6 +8,7 @@ G_BEGIN_DECLS
typedef struct
{
GBytes *preamble;
GBytes *vs_preamble;
GBytes *fs_preamble;
@@ -22,6 +23,7 @@ typedef struct
void gsk_gl_shader_builder_init (GskGLShaderBuilder *self,
const char *common_preamble_resource_path,
const char *vs_preamble_resource_path,
const char *fs_preamble_resource_path);
void gsk_gl_shader_builder_finish (GskGLShaderBuilder *self);

View File

@@ -7,14 +7,12 @@ typedef struct
{
GskRoundedRect outline;
float blur_radius;
GdkRGBA color;
} CacheKey;
typedef struct
{
GskRoundedRect outline;
float blur_radius;
GdkRGBA color;
int texture_id;
int unused_frames;
@@ -32,8 +30,7 @@ key_equal (const void *x,
graphene_size_equal (&a->outline.corner[1], &b->outline.corner[1]) &&
graphene_size_equal (&a->outline.corner[2], &b->outline.corner[2]) &&
graphene_size_equal (&a->outline.corner[3], &b->outline.corner[3]) &&
graphene_rect_equal (&a->outline.bounds, &b->outline.bounds) &&
gdk_rgba_equal (&a->color, &b->color);
graphene_rect_equal (&a->outline.bounds, &b->outline.bounds);
}
void
@@ -91,7 +88,6 @@ int
gsk_gl_shadow_cache_get_texture_id (GskGLShadowCache *self,
GskGLDriver *gl_driver,
const GskRoundedRect *shadow_rect,
const GdkRGBA *color,
float blur_radius)
{
CacheItem *item= NULL;
@@ -105,8 +101,8 @@ gsk_gl_shadow_cache_get_texture_id (GskGLShadowCache *self,
{
CacheItem *k = &g_array_index (self->textures, CacheItem, i);
if (key_equal (&(CacheKey){*shadow_rect, blur_radius, *color},
&(CacheKey){k->outline, k->blur_radius, k->color}))
if (key_equal (&(CacheKey){*shadow_rect, blur_radius},
&(CacheKey){k->outline, k->blur_radius}))
{
item = k;
break;
@@ -126,7 +122,6 @@ gsk_gl_shadow_cache_get_texture_id (GskGLShadowCache *self,
void
gsk_gl_shadow_cache_commit (GskGLShadowCache *self,
const GskRoundedRect *shadow_rect,
const GdkRGBA *color,
float blur_radius,
int texture_id)
{
@@ -140,7 +135,6 @@ gsk_gl_shadow_cache_commit (GskGLShadowCache *self,
item = &g_array_index (self->textures, CacheItem, self->textures->len - 1);
item->outline = *shadow_rect;
item->color = *color;
item->blur_radius = blur_radius;
item->unused_frames = 0;
item->texture_id = texture_id;

View File

@@ -21,11 +21,9 @@ void gsk_gl_shadow_cache_begin_frame (GskGLShadowCache *self,
int gsk_gl_shadow_cache_get_texture_id (GskGLShadowCache *self,
GskGLDriver *gl_driver,
const GskRoundedRect *shadow_rect,
const GdkRGBA *color,
float blur_radius);
void gsk_gl_shadow_cache_commit (GskGLShadowCache *self,
const GskRoundedRect *shadow_rect,
const GdkRGBA *color,
float blur_radius,
int texture_id);

View File

@@ -1773,6 +1773,62 @@ gsk_transform_transform_bounds (GskTransform *self,
}
}
/**
* gsk_transform_transform_point:
* @self: a #GskTransform
* @point: a #graphene_point_t
* @out_point: (out caller-allocates): return location for
* the transformed point
*
* Transforms a #graphene_point_t using the given transform @self.
*/
void
gsk_transform_transform_point (GskTransform *self,
const graphene_point_t *point,
graphene_point_t *out_point)
{
switch (gsk_transform_get_category (self))
{
case GSK_TRANSFORM_CATEGORY_IDENTITY:
*out_point = *point;
break;
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
{
float dx, dy;
gsk_transform_to_translate (self, &dx, &dy);
out_point->x = point->x + dx;
out_point->y = point->y + dy;
}
break;
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float dx, dy, scale_x, scale_y;
gsk_transform_to_affine (self, &scale_x, &scale_y, &dx, &dy);
out_point->x = (point->x * scale_x) + dx;
out_point->y = (point->y * scale_y) + dy;
}
break;
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
case GSK_TRANSFORM_CATEGORY_ANY:
case GSK_TRANSFORM_CATEGORY_3D:
case GSK_TRANSFORM_CATEGORY_2D:
default:
{
graphene_matrix_t mat;
gsk_transform_to_matrix (self, &mat);
graphene_matrix_transform_point (&mat, point, out_point);
}
break;
}
}
static guint
gsk_transform_parse_float (GtkCssParser *parser,
guint n,

View File

@@ -116,6 +116,11 @@ GDK_AVAILABLE_IN_ALL
void gsk_transform_transform_bounds (GskTransform *self,
const graphene_rect_t *rect,
graphene_rect_t *out_rect);
GDK_AVAILABLE_IN_ALL
void gsk_transform_transform_point (GskTransform *self,
const graphene_point_t *point,
graphene_point_t *out_point);
G_END_DECLS

View File

@@ -1,4 +1,5 @@
gsk_private_gl_shaders = [
'resources/glsl/preamble.glsl',
'resources/glsl/preamble.fs.glsl',
'resources/glsl/preamble.vs.glsl',
'resources/glsl/border.glsl',

View File

@@ -1,7 +1,11 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform vec4 u_widths;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -9,25 +13,32 @@ void main() {
final_color = u_color;
final_color.rgb *= final_color.a; // pre-multiply
final_color *= u_alpha;
RoundedRect outside = create_rect(u_outline_rect);
RoundedRect inside = rounded_rect_shrink (outside, u_widths);
rounded_rect_transform(outside, u_modelview);
rounded_rect_transform(inside, u_modelview);
rounded_rect_encode(outside, transformed_outside_outline);
rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
uniform vec4 u_widths;
uniform vec4[3] u_outline_rect;
_IN_ vec4 final_color;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec4 f = gl_FragCoord;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect outside = create_rect(u_outline_rect);
RoundedRect inside = rounded_rect_shrink (outside, u_widths);
float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
rounded_rect_coverage (inside, f.xy),
0.0, 1.0);
float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), f.xy) -
rounded_rect_coverage(decode_rect(transformed_inside_outline), f.xy),
0.0, 1.0);
setOutputColor(final_color * alpha);
}

View File

@@ -1,7 +1,12 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -9,26 +14,33 @@ void main() {
final_color = u_color;
final_color.rgb *= final_color.a;
final_color *= u_alpha;
RoundedRect outside = create_rect(u_outline_rect);
RoundedRect inside = rounded_rect_shrink(outside, vec4(u_spread));
rounded_rect_offset(inside, u_offset);
rounded_rect_transform(outside, u_modelview);
rounded_rect_transform(inside, u_modelview);
rounded_rect_encode(outside, transformed_outside_outline);
rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_IN_ vec4 final_color;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec4 f = gl_FragCoord;
vec4 color;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect outside = create_rect(u_outline_rect);
RoundedRect inside = rounded_rect_shrink(outside, vec4(u_spread));
color = final_color * clamp (rounded_rect_coverage (outside, f.xy) -
rounded_rect_coverage (inside, f.xy - u_offset),
0.0, 1.0);
setOutputColor(color);
float alpha = clamp (rounded_rect_coverage(decode_rect(transformed_outside_outline), f.xy) -
rounded_rect_coverage(decode_rect(transformed_inside_outline), f.xy),
0.0, 1.0);
setOutputColor(final_color * alpha);
}

View File

@@ -1,12 +1,28 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
final_color = u_color;
// pre-multiply
final_color.rgb *= final_color.a;
final_color *= u_alpha;
RoundedRect outline = create_rect(u_outline_rect);
rounded_rect_transform(outline, u_modelview);
rounded_rect_encode(outline, transformed_outline);
}
// FRAGMENT_SHADER:
uniform vec4[3] u_outline_rect;
_IN_ vec4 final_color;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outline;
void main() {
vec4 f = gl_FragCoord;
@@ -14,8 +30,10 @@ void main() {
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect outline = create_rect(u_outline_rect);
vec4 color = Texture(u_source, vUv);
color = color * (1.0 - clamp(rounded_rect_coverage(outline, f.xy), 0.0, 1.0));
setOutputColor(color * u_alpha);
float alpha = Texture(u_source, vUv).a;
alpha *= (1.0 - clamp(rounded_rect_coverage(decode_rect(transformed_outline), f.xy), 0.0, 1.0));
vec4 color = final_color * alpha;
setOutputColor(color);
}

View File

@@ -1,12 +1,3 @@
#ifdef GSK_GL3
precision highp float;
#endif
#ifdef GSK_GLES
precision highp float;
#endif
uniform sampler2D u_source;
uniform mat4 u_projection;
uniform mat4 u_modelview;
@@ -15,36 +6,23 @@ uniform vec4 u_viewport;
uniform vec4[3] u_clip_rect;
#if GSK_GLES
#define _OUT_ varying
#define _IN_ varying
#elif GSK_LEGACY
#define _OUT_ varying
#define _IN_ varying
_OUT_ vec4 outputColor;
#else
#define _OUT_ out
#define _IN_ in
_OUT_ vec4 outputColor;
#endif
_IN_ vec2 vUv;
struct RoundedRect
RoundedRect decode_rect(_ROUNDED_RECT_UNIFORM_ r)
{
vec4 bounds;
vec4 corner_widths;
vec4 corner_heights;
};
// Transform from a GskRoundedRect to a RoundedRect as we need it.
RoundedRect
create_rect(vec4 data[3])
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
vec4 widths = vec4(data[1].x, data[1].z, data[2].x, data[2].z);
vec4 heights = vec4(data[1].y, data[1].w, data[2].y, data[2].w);
return RoundedRect(bounds, widths, heights);
#if defined(GSK_GLES) || defined(GSK_LEGACY)
return RoundedRect(r[0], r[1], r[2]);
#else
return r;
#endif
}
float
@@ -73,15 +51,15 @@ rounded_rect_coverage (RoundedRect r, vec2 p)
p.x >= r.bounds.z || p.y >= r.bounds.w)
return 0.0;
vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
vec2 rad_tl = r.corner_points1.xy - r.bounds.xy;
vec2 rad_tr = r.corner_points1.zw - r.bounds.zy;
vec2 rad_br = r.corner_points2.xy - r.bounds.zw;
vec2 rad_bl = r.corner_points2.zw - r.bounds.xw;
vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x);
vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y);
vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
vec2 ref_tl = r.corner_points1.xy;
vec2 ref_tr = r.corner_points1.zw;
vec2 ref_br = r.corner_points2.xy;
vec2 ref_bl = r.corner_points2.zw;
float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
@@ -98,37 +76,8 @@ rounded_rect_coverage (RoundedRect r, vec2 p)
return 1.0 - dot(vec4(is_out), corner_coverages);
}
// amount is: top, right, bottom, left
RoundedRect
rounded_rect_shrink (RoundedRect r, vec4 amount)
{
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
vec4 new_widths = vec4(0);
vec4 new_heights = vec4(0);
// Left top
if (r.corner_widths.x > 0.0) new_widths.x = r.corner_widths.x - amount.w;
if (r.corner_heights.x > 0.0) new_heights.x = r.corner_heights.x - amount.x;
// Top right
if (r.corner_widths.y > 0.0) new_widths.y = r.corner_widths.y - amount.y;
if (r.corner_heights.y > 0.0) new_heights.y = r.corner_heights.y - amount.x;
// Bottom right
if (r.corner_widths.z > 0.0) new_widths.z = r.corner_widths.z - amount.y;
if (r.corner_heights.z > 0.0) new_heights.z = r.corner_heights.z - amount.z;
// Bottom left
if (r.corner_widths.w > 0.0) new_widths.w = r.corner_widths.w - amount.w;
if (r.corner_heights.w > 0.0) new_heights.w = r.corner_heights.w - amount.z;
return RoundedRect (new_bounds, new_widths, new_heights);
}
vec4 Texture(sampler2D sampler, vec2 texCoords) {
#if GSK_GLES
return texture2D(sampler, texCoords);
#elif GSK_LEGACY
#if defined(GSK_GLES) || defined(GSK_LEGACY)
return texture2D(sampler, texCoords);
#else
return texture(sampler, texCoords);
@@ -141,9 +90,10 @@ void setOutputColor(vec4 color) {
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
#if GSK_GLES
gl_FragColor = color * rounded_rect_coverage(create_rect(u_clip_rect), f.xy);
#elif GSK_LEGACY
// We do *NOT* transform the clip rect here since we already
// need to do that on the CPU.
#if defined(GSK_GLES) || defined(GSK_LEGACY)
gl_FragColor = color * rounded_rect_coverage(create_rect(u_clip_rect), f.xy);
#else
outputColor = color * rounded_rect_coverage(create_rect(u_clip_rect), f.xy);

View File

@@ -0,0 +1,37 @@
#ifndef GSK_LEGACY
precision highp float;
#endif
#if defined(GSK_GLES) || defined(GSK_LEGACY)
#define _OUT_ varying
#define _IN_ varying
#define _ROUNDED_RECT_UNIFORM_ vec4[3]
#else
#define _OUT_ out
#define _IN_ in
#define _ROUNDED_RECT_UNIFORM_ RoundedRect
#endif
struct RoundedRect
{
vec4 bounds;
// Look, arrays can't be in structs if you want to return the struct
// from a function in gles or whatever. Just kill me.
vec4 corner_points1; // xy = top left, zw = top right
vec4 corner_points2; // xy = bottom right, zw = bottom left
};
// Transform from a GskRoundedRect to a RoundedRect as we need it.
RoundedRect
create_rect(vec4[3] data)
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
return RoundedRect(bounds, corner_points1, corner_points2);
}

View File

@@ -2,26 +2,68 @@ uniform mat4 u_projection;
uniform mat4 u_modelview;
uniform float u_alpha;
#ifdef GSK_GLES
precision highp float;
#endif
#if GSK_GLES
#define _OUT_ varying
#define _IN_ varying
attribute vec2 aPosition;
attribute vec2 aUv;
_OUT_ vec2 vUv;
#elif GSK_LEGACY
#define _OUT_ varying
#define _IN_ varying
#if defined(GSK_GLES) || defined(GSK_LEGACY)
attribute vec2 aPosition;
attribute vec2 aUv;
_OUT_ vec2 vUv;
#else
#define _OUT_ out
#define _IN_ in
_IN_ vec2 aPosition;
_IN_ vec2 aUv;
_OUT_ vec2 vUv;
#endif
// amount is: top, right, bottom, left
RoundedRect
rounded_rect_shrink (RoundedRect r, vec4 amount)
{
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
vec4 new_corner_points1 = r.corner_points1;
vec4 new_corner_points2 = r.corner_points2;
if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
return RoundedRect (new_bounds, new_corner_points1, new_corner_points2);
}
void
rounded_rect_offset(inout RoundedRect r, vec2 offset)
{
r.bounds.xy += offset;
r.bounds.zw += offset;
r.corner_points1.xy += offset;
r.corner_points1.zw += offset;
r.corner_points2.xy += offset;
r.corner_points2.zw += offset;
}
void rounded_rect_transform(inout RoundedRect r, mat4 mat)
{
r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
}
#if defined(GSK_LEGACY)
// Can't have out or inout array parameters...
#define rounded_rect_encode(r, uni) uni[0] = r.bounds; uni[1] = r.corner_points1; uni[2] = r.corner_points2;
#else
void rounded_rect_encode(RoundedRect r, out _ROUNDED_RECT_UNIFORM_ out_r)
{
#if defined(GSK_GLES)
out_r[0] = r.bounds;
out_r[1] = r.corner_points1;
out_r[2] = r.corner_points2;
#else
out_r = r;
#endif
}
#endif

View File

@@ -1,7 +1,12 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -9,26 +14,33 @@ void main() {
final_color = u_color;
final_color.rgb *= final_color.a;
final_color *= u_alpha;
RoundedRect inside = create_rect(u_outline_rect);
RoundedRect outside = rounded_rect_shrink(inside, vec4(- u_spread));
rounded_rect_offset(outside, u_offset);
rounded_rect_transform(outside, u_modelview);
rounded_rect_transform(inside, u_modelview);
rounded_rect_encode(outside, transformed_outside_outline);
rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_IN_ vec4 final_color;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec4 f = gl_FragCoord;
vec4 color;
f.x += u_viewport.x;
f.y = (u_viewport.y + u_viewport.w) - f.y;
RoundedRect inside = create_rect(u_outline_rect);
RoundedRect outside = rounded_rect_shrink(inside, vec4(- u_spread));
color = final_color * clamp (rounded_rect_coverage (outside, f.xy - u_offset) -
rounded_rect_coverage (inside, f.xy),
0.0, 1.0);
setOutputColor(color);
float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), f.xy) -
rounded_rect_coverage(decode_rect(transformed_inside_outline), f.xy),
0.0, 1.0);
setOutputColor(final_color * alpha);
}

View File

@@ -17,6 +17,7 @@ def get_files(subdir,extension):
return sorted(filter(lambda x: x.endswith((extension)), os.listdir(os.path.join(srcdir,subdir))))
xml += '''
<file>theme/Empty/gtk.css</file>
<file>theme/Adwaita/gtk.css</file>
<file>theme/Adwaita/gtk-dark.css</file>
<file>theme/Adwaita/gtk-contained.css</file>

View File

@@ -38,7 +38,7 @@
#include "gtkmain.h"
#include "gtkrecentmanager.h"
#include "gtkaccelmapprivate.h"
#include "gtkicontheme.h"
#include "gtkiconthemeprivate.h"
#include "gtkbuilder.h"
#include "gtkshortcutswindow.h"
#include "gtkintl.h"
@@ -218,6 +218,7 @@ gtk_application_load_resources (GtkApplication *application)
iconspath = g_strconcat (base_path, "/icons/", NULL);
gtk_icon_theme_add_resource_path (default_theme, iconspath);
g_free (iconspath);
gtk_icon_theme_ensure_loaded (default_theme);
}
/* Load the menus */
@@ -297,17 +298,25 @@ gtk_application_startup (GApplication *g_application)
{
GtkApplication *application = GTK_APPLICATION (g_application);
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
gint64 before = g_get_monotonic_time ();
gint64 before2;
G_APPLICATION_CLASS (gtk_application_parent_class)->startup (g_application);
gtk_action_muxer_insert (priv->muxer, "app", G_ACTION_GROUP (application));
before2 = g_get_monotonic_time ();
gtk_init ();
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before2 * 1000, (g_get_monotonic_time () - before2) * 1000, "gtk init", NULL);
priv->impl = gtk_application_impl_new (application, gdk_display_get_default ());
gtk_application_impl_startup (priv->impl, priv->register_session);
gtk_application_load_resources (application);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "gtk application startup", NULL);
}
static void

View File

@@ -109,9 +109,6 @@ static void gtk_box_forall (GtkContainer *container,
GtkCallback callback,
gpointer callback_data);
static GType gtk_box_child_type (GtkContainer *container);
static GtkWidgetPath * gtk_box_get_path_for_child
(GtkContainer *container,
GtkWidget *child);
G_DEFINE_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_CONTAINER,
G_ADD_PRIVATE (GtkBox)
@@ -131,7 +128,6 @@ gtk_box_class_init (GtkBoxClass *class)
container_class->remove = gtk_box_remove;
container_class->forall = gtk_box_forall;
container_class->child_type = gtk_box_child_type;
container_class->get_path_for_child = gtk_box_get_path_for_child;
g_object_class_override_property (object_class,
PROP_ORIENTATION,
@@ -242,105 +238,6 @@ gtk_box_child_type (GtkContainer *container)
return GTK_TYPE_WIDGET;
}
typedef struct _CountingData CountingData;
struct _CountingData {
GtkWidget *widget;
gboolean found;
guint before;
guint after;
};
static void
count_widget_position (GtkWidget *widget,
gpointer data)
{
CountingData *count = data;
if (!_gtk_widget_get_visible (widget))
return;
if (count->widget == widget)
count->found = TRUE;
else if (count->found)
count->after++;
else
count->before++;
}
static gint
gtk_box_get_visible_position (GtkBox *box,
GtkWidget *child)
{
CountingData count = { child, FALSE, 0, 0 };
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
/* foreach iterates in visible order */
gtk_container_foreach (GTK_CONTAINER (box),
count_widget_position,
&count);
/* the child wasn't found, it's likely an internal child of some
* subclass, return -1 to indicate that there is no sibling relation
* to the regular box children
*/
if (!count.found)
return -1;
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (GTK_WIDGET (box)) == GTK_TEXT_DIR_RTL)
return count.after;
else
return count.before;
}
static GtkWidgetPath *
gtk_box_get_path_for_child (GtkContainer *container,
GtkWidget *child)
{
GtkWidgetPath *path, *sibling_path;
GtkBox *box = GTK_BOX (container);
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
GList *list, *children;
path = _gtk_widget_create_path (GTK_WIDGET (container));
if (_gtk_widget_get_visible (child))
{
gint position;
sibling_path = gtk_widget_path_new ();
/* get_children works in visible order */
children = gtk_container_get_children (container);
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
_gtk_widget_get_direction (GTK_WIDGET (box)) == GTK_TEXT_DIR_RTL)
children = g_list_reverse (children);
for (list = children; list; list = list->next)
{
if (!_gtk_widget_get_visible (list->data))
continue;
gtk_widget_path_append_for_widget (sibling_path, list->data);
}
g_list_free (children);
position = gtk_box_get_visible_position (box, child);
if (position >= 0)
gtk_widget_path_append_with_siblings (path, sibling_path, position);
else
gtk_widget_path_append_for_widget (path, child);
gtk_widget_path_unref (sibling_path);
}
else
gtk_widget_path_append_for_widget (path, child);
return path;
}
static void
gtk_box_init (GtkBox *box)
{

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,

View File

@@ -229,6 +229,7 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, "colorbutton");
}
static void

View File

@@ -115,9 +115,6 @@ static void gtk_container_children_callback (GtkWidget *widget,
gpointer client_data);
static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget *widget);
static GtkWidgetPath * gtk_container_real_get_path_for_child (GtkContainer *container,
GtkWidget *child);
/* GtkBuildable */
static void gtk_container_buildable_init (GtkBuildableIface *iface);
static GtkBuildableIface *parent_buildable_iface;
@@ -149,7 +146,6 @@ gtk_container_class_init (GtkContainerClass *class)
class->forall = NULL;
class->set_focus_child = gtk_container_real_set_focus_child;
class->child_type = NULL;
class->get_path_for_child = gtk_container_real_get_path_for_child;
container_signals[ADD] =
g_signal_new (I_("add"),
@@ -375,9 +371,7 @@ gtk_container_idle_sizer (GdkFrameClock *clock,
*/
if (gtk_widget_needs_allocate (GTK_WIDGET (container)))
{
if (GTK_IS_WINDOW (container))
gtk_window_check_resize (GTK_WINDOW (container));
else if (GTK_IS_ROOT (container))
if (GTK_IS_ROOT (container))
gtk_native_check_resize (GTK_NATIVE (container));
else
g_warning ("gtk_container_idle_sizer() called on a non-native non-window");
@@ -480,8 +474,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
@@ -651,18 +645,6 @@ gtk_container_real_set_focus_child (GtkContainer *container,
}
}
static GtkWidgetPath *
gtk_container_real_get_path_for_child (GtkContainer *container,
GtkWidget *child)
{
GtkWidgetPath *path;
path = _gtk_widget_create_path (GTK_WIDGET (container));
gtk_widget_path_append_for_widget (path, child);
return path;
}
static void
gtk_container_children_callback (GtkWidget *widget,
gpointer client_data)
@@ -783,35 +765,3 @@ gtk_container_get_focus_hadjustment (GtkContainer *container)
return hadjustment;
}
/**
* gtk_container_get_path_for_child:
* @container: a #GtkContainer
* @child: a child of @container
*
* Returns a newly created widget path representing all the widget hierarchy
* from the toplevel down to and including @child.
*
* Returns: A newly created #GtkWidgetPath
**/
GtkWidgetPath *
gtk_container_get_path_for_child (GtkContainer *container,
GtkWidget *child)
{
GtkWidgetPath *path;
g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
g_return_val_if_fail (container == (GtkContainer *) _gtk_widget_get_parent (child), NULL);
path = GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
if (gtk_widget_path_get_object_type (path) != G_OBJECT_TYPE (child))
{
g_critical ("%s %p returned a widget path for type %s, but child is %s",
G_OBJECT_TYPE_NAME (container),
container,
g_type_name (gtk_widget_path_get_object_type (path)),
G_OBJECT_TYPE_NAME (child));
}
return path;
}

View File

@@ -62,8 +62,6 @@ struct _GtkContainer
* @child_type: Returns the type of the children supported by the container.
* @set_child_property: Set a property on a child of container.
* @get_child_property: Get a property from a child of container.
* @get_path_for_child: Get path representing entire widget hierarchy
* from the toplevel down to and including @child.
*
* Base class for containers.
*/
@@ -83,8 +81,6 @@ struct _GtkContainerClass
void (*set_focus_child) (GtkContainer *container,
GtkWidget *child);
GType (*child_type) (GtkContainer *container);
GtkWidgetPath * (*get_path_for_child) (GtkContainer *container,
GtkWidget *child);
/*< private >*/
@@ -132,10 +128,6 @@ void gtk_container_forall (GtkContainer *container,
GtkCallback callback,
gpointer callback_data);
GDK_AVAILABLE_IN_ALL
GtkWidgetPath * gtk_container_get_path_for_child (GtkContainer *container,
GtkWidget *child);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkContainer, g_object_unref)
G_END_DECLS

View File

@@ -79,13 +79,13 @@ gtk_css_animated_style_is_static (GtkCssStyle *style)
return TRUE;
}
static GtkCssStyle *
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 animated->style;
return (GtkCssStaticStyle *)animated->style;
}
static void

View File

@@ -204,15 +204,15 @@ static GtkCssValue *
gtk_css_value_dimension_try_add (GtkCssValue *value1,
GtkCssValue *value2)
{
if (value1->unit != value2->unit)
return NULL;
if (value1->value == 0)
return _gtk_css_value_ref (value2);
if (value2->value == 0)
return _gtk_css_value_ref (value1);
if (value1->unit != value2->unit)
return NULL;
return gtk_css_dimension_value_new (value1->value + value2->value, value1->unit);
}
@@ -249,15 +249,6 @@ gtk_css_value_dimension_transition (GtkCssValue *start,
guint property_id,
double progress)
{
if (progress == 0)
return _gtk_css_value_ref (start);
if (progress == 1)
return _gtk_css_value_ref (end);
if (start == end)
return _gtk_css_value_ref (start);
if (start->unit != end->unit)
return NULL;

View File

@@ -91,20 +91,7 @@ static gboolean
gtk_css_value_icon_theme_equal (const GtkCssValue *value1,
const GtkCssValue *value2)
{
GtkIconTheme *theme1 = value1->icontheme;
GtkIconTheme *theme2 = value2->icontheme;
GtkIconTheme *default_theme;
if (theme1 == theme2)
return TRUE;
if (theme1 && theme2)
return FALSE;
default_theme = gtk_icon_theme_get_default ();
return theme1 == default_theme ||
theme2 == default_theme;
return FALSE;
}
static GtkCssValue *

View File

@@ -115,6 +115,12 @@ gtk_css_image_real_get_dynamic_image (GtkCssImage *image,
return g_object_ref (image);
}
static gboolean
gtk_css_image_real_is_computed (GtkCssImage *image)
{
return FALSE;
}
static void
_gtk_css_image_class_init (GtkCssImageClass *klass)
{
@@ -127,6 +133,7 @@ _gtk_css_image_class_init (GtkCssImageClass *klass)
klass->is_invalid = gtk_css_image_real_is_invalid;
klass->is_dynamic = gtk_css_image_real_is_dynamic;
klass->get_dynamic_image = gtk_css_image_real_get_dynamic_image;
klass->is_computed = gtk_css_image_real_is_computed;
}
static void
@@ -570,11 +577,5 @@ gtk_css_image_is_computed (GtkCssImage *image)
{
GtkCssImageClass *klass = GTK_CSS_IMAGE_GET_CLASS (image);
if (!klass->is_computed)
return FALSE;
if (gtk_css_image_is_dynamic (image))
return FALSE;
return klass->is_computed (image);
}

View File

@@ -70,15 +70,18 @@ gtk_css_image_fallback_snapshot (GtkCssImage *image,
if (fallback->used < 0)
{
GdkRGBA red = { 1, 0, 0, 1 };
const GdkRGBA *color;
if (fallback->color)
color = gtk_css_color_value_get_rgba (fallback->color);
{
const GdkRGBA *color = gtk_css_color_value_get_rgba (fallback->color);
if (!gdk_rgba_is_clear (color))
gtk_snapshot_append_color (snapshot, color,
&GRAPHENE_RECT_INIT (0, 0, width, height));
}
else
color = &red;
gtk_snapshot_append_color (snapshot, color, &GRAPHENE_RECT_INIT (0, 0, width, height));
{
gtk_snapshot_append_color (snapshot, &(GdkRGBA) {1, 0, 0, 1},
&GRAPHENE_RECT_INIT (0, 0, width, height));
}
}
else
gtk_css_image_snapshot (fallback->images[fallback->used], snapshot, width, height);

View File

@@ -94,21 +94,22 @@ gtk_css_image_icon_theme_snapshot (GtkCssImage *image,
if (symbolic)
{
const GdkRGBA *fg = &icon_theme->color;
const GdkRGBA *sc = &icon_theme->success;
const GdkRGBA *wc = &icon_theme->warning;
const GdkRGBA *ec = &icon_theme->error;
graphene_matrix_t matrix;
graphene_vec4_t offset;
GdkRGBA fg = icon_theme->color;
GdkRGBA sc = icon_theme->success;
GdkRGBA wc = icon_theme->warning;
GdkRGBA ec = icon_theme->error;
graphene_matrix_init_from_float (&matrix,
(float[16]) {
sc.red - fg.red, sc.green - fg.green, sc.blue - fg.blue, 0,
wc.red - fg.red, wc.green - fg.green, wc.blue - fg.blue, 0,
ec.red - fg.red, ec.green - fg.green, ec.blue - fg.blue, 0,
0, 0, 0, fg.alpha
sc->red - fg->red, sc->green - fg->green, sc->blue - fg->blue, 0,
wc->red - fg->red, wc->green - fg->green, wc->blue - fg->blue, 0,
ec->red - fg->red, ec->green - fg->green, ec->blue - fg->blue, 0,
0, 0, 0, fg->alpha
});
graphene_vec4_init (&offset, fg.red, fg.green, fg.blue, 0);
graphene_vec4_init (&offset, fg->red, fg->green, fg->blue, 0);
gtk_snapshot_push_color_matrix (snapshot, &matrix, &offset);
}

View File

@@ -495,26 +495,24 @@ gtk_css_image_linear_compute (GtkCssImage *image,
GtkCssStyle *parent_style)
{
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
gboolean changed = FALSE;
GtkCssImageLinearColorStop *stops;
GtkCssValue *computed_angle = NULL;
GtkCssImageLinear *copy;
guint i;
if (linear->angle)
{
computed_angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style);
changed |= (computed_angle != linear->angle);
}
copy = g_object_new (GTK_TYPE_CSS_IMAGE_LINEAR, NULL);
copy->repeating = linear->repeating;
copy->side = linear->side;
stops = g_alloca (sizeof (GtkCssImageLinearColorStop) * linear->n_stops);
if (linear->angle)
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style);
copy->n_stops = linear->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageLinearColorStop) * copy->n_stops);
for (i = 0; i < linear->n_stops; i++)
{
const GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
GtkCssImageLinearColorStop *scopy = &stops[i];
GtkCssImageLinearColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
changed |= (scopy->color != stop->color);
if (stop->offset)
{
@@ -526,30 +524,6 @@ gtk_css_image_linear_compute (GtkCssImage *image,
}
}
if (!changed)
{
if (computed_angle)
_gtk_css_value_unref (computed_angle);
for (i = 0; i < linear->n_stops; i ++)
{
_gtk_css_value_unref (stops[i].color);
if (stops[i].offset)
_gtk_css_value_unref (stops[i].offset);
}
return g_object_ref (image);
}
copy = g_object_new (GTK_TYPE_CSS_IMAGE_LINEAR, NULL);
copy->repeating = linear->repeating;
copy->side = linear->side;
copy->angle = computed_angle;
copy->n_stops = linear->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageLinearColorStop) * copy->n_stops);
memcpy (copy->color_stops, stops, sizeof (GtkCssImageLinearColorStop ) * linear->n_stops);
return GTK_CSS_IMAGE (copy);
}

View File

@@ -150,6 +150,14 @@ gtk_css_image_paintable_dispose (GObject *object)
G_OBJECT_CLASS (gtk_css_image_paintable_parent_class)->dispose (object);
}
static gboolean
gtk_css_image_paintable_is_computed (GtkCssImage *image)
{
GtkCssImagePaintable *self = GTK_CSS_IMAGE_PAINTABLE (image);
return (gdk_paintable_get_flags (self->paintable) & GDK_PAINTABLE_IMMUTABLE) == GDK_PAINTABLE_IMMUTABLE;
}
static void
gtk_css_image_paintable_class_init (GtkCssImagePaintableClass *klass)
{
@@ -164,6 +172,7 @@ gtk_css_image_paintable_class_init (GtkCssImagePaintableClass *klass)
image_class->compute = gtk_css_image_paintable_compute;
image_class->equal = gtk_css_image_paintable_equal;
image_class->is_dynamic = gtk_css_image_paintable_is_dynamic;
image_class->is_computed = gtk_css_image_paintable_is_computed;
image_class->get_dynamic_image = gtk_css_image_paintable_get_dynamic_image;
object_class->dispose = gtk_css_image_paintable_dispose;

View File

@@ -511,41 +511,34 @@ gtk_css_image_radial_compute (GtkCssImage *image,
GtkCssStyle *parent_style)
{
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
GtkCssValue *computed_position, *computed_size1 = NULL, *computed_size2 = NULL;
gboolean changed = FALSE;
GtkCssImageRadialColorStop *stops;
GtkCssImageRadial *copy;
guint i;
computed_position = _gtk_css_value_compute (radial->position, property_id, provider, style, parent_style);
changed |= (computed_position != radial->position);
copy = g_object_new (GTK_TYPE_CSS_IMAGE_RADIAL, NULL);
copy->repeating = radial->repeating;
copy->circle = radial->circle;
copy->size = radial->size;
copy->position = _gtk_css_value_compute (radial->position, property_id, provider, style, parent_style);
if (radial->sizes[0])
{
computed_size1 = _gtk_css_value_compute (radial->sizes[0], property_id, provider, style, parent_style);
changed |= (computed_size1 != radial->sizes[0]);
}
copy->sizes[0] = _gtk_css_value_compute (radial->sizes[0], property_id, provider, style, parent_style);
if (radial->sizes[1])
{
computed_size2 = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style);
changed |= (computed_size2 != radial->sizes[1]);
}
copy->sizes[1] = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style);
stops = g_alloca (sizeof (GtkCssImageRadialColorStop) * radial->n_stops);
copy->n_stops = radial->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageRadialColorStop) * copy->n_stops);
for (i = 0; i < radial->n_stops; i++)
{
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
GtkCssImageRadialColorStop *scopy = &stops[i];
GtkCssImageRadialColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
changed |= (scopy->color != stop->color);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
changed |= (scopy->offset != stop->offset);
}
else
{
@@ -553,33 +546,6 @@ gtk_css_image_radial_compute (GtkCssImage *image,
}
}
if (!changed)
{
_gtk_css_value_unref (computed_position);
if (computed_size1)
_gtk_css_value_unref (computed_size1);
if (computed_size2)
_gtk_css_value_unref (computed_size2);
for (i = 0; i < radial->n_stops; i ++)
{
_gtk_css_value_unref (stops[i].color);
if (stops[i].offset)
_gtk_css_value_unref (stops[i].offset);
}
return g_object_ref (image);
}
copy = g_object_new (GTK_TYPE_CSS_IMAGE_RADIAL, NULL);
copy->repeating = radial->repeating;
copy->circle = radial->circle;
copy->size = radial->size;
copy->n_stops = radial->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageRadialColorStop) * copy->n_stops);
memcpy (copy->color_stops, stops, sizeof (GtkCssImageRadialColorStop ) * radial->n_stops);
return GTK_CSS_IMAGE (copy);
}

View File

@@ -308,6 +308,15 @@ gtk_css_image_recolor_get_height (GtkCssImage *image)
return gdk_texture_get_height (recolor->texture);
}
static gboolean
gtk_css_image_recolor_is_computed (GtkCssImage *image)
{
GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image);
return recolor->texture &&
(!recolor->palette || gtk_css_value_is_computed (recolor->palette));
}
static void
_gtk_css_image_recolor_class_init (GtkCssImageRecolorClass *klass)
{
@@ -320,6 +329,7 @@ _gtk_css_image_recolor_class_init (GtkCssImageRecolorClass *klass)
image_class->snapshot = gtk_css_image_recolor_snapshot;
image_class->parse = gtk_css_image_recolor_parse;
image_class->print = gtk_css_image_recolor_print;
image_class->is_computed = gtk_css_image_recolor_is_computed;
object_class->dispose = gtk_css_image_recolor_dispose;
}

View File

@@ -203,6 +203,15 @@ gtk_css_image_scaled_parse (GtkCssImage *image,
return TRUE;
}
static gboolean
gtk_css_image_scaled_is_computed (GtkCssImage *image)
{
GtkCssImageScaled *self = GTK_CSS_IMAGE_SCALED (image);
return self->n_images == 1 &&
gtk_css_image_is_computed (self->images[0]);
}
static void
_gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass)
{
@@ -216,6 +225,7 @@ _gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass)
image_class->parse = gtk_css_image_scaled_parse;
image_class->compute = gtk_css_image_scaled_compute;
image_class->print = gtk_css_image_scaled_print;
image_class->is_computed = gtk_css_image_scaled_is_computed;
object_class->dispose = gtk_css_image_scaled_dispose;
}

View File

@@ -51,13 +51,20 @@ gtk_css_value_initial_compute (GtkCssValue *value,
case GTK_CSS_PROPERTY_DPI:
settings = gtk_style_provider_get_settings (provider);
if (settings)
return gtk_css_value_ref (gtk_settings_get_dpi_css_value (settings));
{
int dpi_int;
g_object_get (settings, "gtk-xft-dpi", &dpi_int, NULL);
if (dpi_int > 0.0)
return _gtk_css_number_value_new (dpi_int / 1024., GTK_CSS_NUMBER);
}
break;
case GTK_CSS_PROPERTY_FONT_FAMILY:
settings = gtk_style_provider_get_settings (provider);
if (settings)
return gtk_css_value_ref (gtk_settings_get_font_family_css_value (settings));
if (settings && gtk_settings_get_font_family (settings) != NULL)
return _gtk_css_string_value_new (gtk_settings_get_font_family (settings));
break;
default:

View File

@@ -76,40 +76,6 @@ _gtk_css_lookup_set (GtkCssLookup *lookup,
lookup->values[id].value = value;
lookup->values[id].section = section;
lookup->n_set_values ++;
}
/**
* _gtk_css_lookup_resolve:
* @lookup: the lookup
* @context: the context the values are resolved for
* @values: a new #GtkCssStyle to be filled with the new properties
*
* Resolves the current lookup into a styleproperties object. This is done
* by converting from the “winning declaration” to the “computed value”.
*
* XXX: This bypasses the notion of “specified value”. If this ever becomes
* an issue, go fix it.
**/
void
_gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProvider *provider,
GtkCssStaticStyle *style,
GtkCssStyle *parent_style)
{
guint i;
gtk_internal_return_if_fail (lookup != NULL);
gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
{
gtk_css_static_style_compute_value (style,
provider,
parent_style,
i,
lookup->values[i].value,
lookup->values[i].section);
}
if (section)
lookup->has_section = TRUE;
}

View File

@@ -37,6 +37,7 @@ typedef struct {
struct _GtkCssLookup {
guint n_set_values;
gboolean has_section;
GtkCssLookupValue values[GTK_CSS_PROPERTY_N_PROPERTIES];
};
@@ -49,10 +50,6 @@ void _gtk_css_lookup_set (GtkCssLookup
guint id,
GtkCssSection *section,
GtkCssValue *value);
void _gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProvider *provider,
GtkCssStaticStyle *style,
GtkCssStyle *parent_style);
G_END_DECLS

View File

@@ -22,7 +22,21 @@
#include "gtkcssnodedeclarationprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkwidgetpath.h"
#include "gtkprivate.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 */
@@ -58,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
@@ -172,7 +193,7 @@ 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,
@@ -245,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
@@ -356,7 +378,7 @@ 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,
@@ -376,243 +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 void
gtk_css_matcher_any_print (const GtkCssMatcher *matcher,
GString *string)
{
g_string_append (string, "ANY");
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_ANY = {
GTK_CSS_MATCHER_TYPE_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,
gtk_css_matcher_any_print
};
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)
{
gboolean ret = TRUE;
if (child->klass->type == GTK_CSS_MATCHER_TYPE_NODE)
{
ret = gtk_css_matcher_node_get_parent (matcher, child);
matcher->klass = child->klass;
}
else
_gtk_css_matcher_any_init (matcher);
return ret;
}
static gboolean
gtk_css_matcher_superset_get_previous (GtkCssMatcher *matcher,
const GtkCssMatcher *next)
{
gboolean ret = TRUE;
if (next->klass->type == GTK_CSS_MATCHER_TYPE_NODE)
{
ret = gtk_css_matcher_node_get_previous (matcher, next);
matcher->klass = next->klass;
}
else
_gtk_css_matcher_any_init (matcher);
return ret;
}
static GtkStateFlags
gtk_css_matcher_superset_get_state (const GtkCssMatcher *matcher)
{
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)
{
return TRUE;
}
static gboolean
gtk_css_matcher_superset_has_class (const GtkCssMatcher *matcher,
GQuark class_name)
{
return TRUE;
}
static gboolean
gtk_css_matcher_superset_has_id (const GtkCssMatcher *matcher,
const char *id)
{
return TRUE;
}
static gboolean
gtk_css_matcher_superset_has_position (const GtkCssMatcher *matcher,
gboolean forward,
int a,
int b)
{
return TRUE;
}
static void
gtk_css_matcher_superset_print (const GtkCssMatcher *matcher,
GString *string)
{
g_string_append (string, "SUPERSET(");
if (matcher->klass->type == GTK_CSS_MATCHER_TYPE_NODE)
gtk_css_node_print (matcher->node.node, 0, string, 0);
else
g_string_append (string, "...");
g_string_append (string, ")");
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_SUPERSET = {
0,
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,
gtk_css_matcher_superset_print
};
void
_gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
const GtkCssMatcher *subset,
GtkCssMatcherClass *klass,
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);
switch (subset->klass->type)
{
case GTK_CSS_MATCHER_TYPE_NODE:
matcher->node = subset->node;
break;
case GTK_CSS_MATCHER_TYPE_WIDGET_PATH:
matcher->path = subset->path;
break;
case GTK_CSS_MATCHER_TYPE_ANY:
break;
default:
g_assert_not_reached ();
break;
}
*klass = GTK_CSS_MATCHER_SUPERSET;
if (relevant & GTK_CSS_CHANGE_CLASS)
klass->has_class = subset->klass->has_class;
if (relevant & GTK_CSS_CHANGE_NAME)
klass->has_name = subset->klass->has_name;
if (relevant & GTK_CSS_CHANGE_NAME)
klass->has_id = subset->klass->has_id;
if (relevant & GTK_CSS_CHANGE_POSITION)
klass->has_position = subset->klass->has_position;
if (relevant & GTK_CSS_CHANGE_STATE)
klass->get_state = subset->klass->get_state;
matcher->klass = klass;
}
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);
}

View File

@@ -31,8 +31,7 @@ typedef struct _GtkCssMatcherClass GtkCssMatcherClass;
typedef enum {
GTK_CSS_MATCHER_TYPE_NODE,
GTK_CSS_MATCHER_TYPE_WIDGET_PATH,
GTK_CSS_MATCHER_TYPE_ANY
GTK_CSS_MATCHER_TYPE_WIDGET_PATH
} GtkCssMatcherType;
struct _GtkCssMatcherClass {
@@ -42,7 +41,8 @@ struct _GtkCssMatcherClass {
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,
@@ -86,11 +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,
GtkCssMatcherClass *klass,
GtkCssChange relevant);
void gtk_css_matcher_print (const GtkCssMatcher *matcher,
GString *string);
char * gtk_css_matcher_to_string (const GtkCssMatcher *matcher);
static inline gboolean
@@ -107,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
@@ -143,16 +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->type == GTK_CSS_MATCHER_TYPE_ANY;
}
void gtk_css_matcher_print (const GtkCssMatcher *matcher,
GString *string);
char * gtk_css_matcher_to_string (const GtkCssMatcher *matcher);
G_END_DECLS
#endif /* __GTK_CSS_MATCHER_PRIVATE_H__ */

View File

@@ -27,6 +27,7 @@
#include "gtksettingsprivate.h"
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
#include "gdkprofilerprivate.h"
/*
* CSS nodes are the backbone of the GtkStyleContext implementation and
@@ -88,6 +89,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 {
@@ -117,6 +123,11 @@ gtk_css_node_get_style_provider_or_null (GtkCssNode *cssnode)
return GTK_CSS_NODE_GET_CLASS (cssnode)->get_style_provider (cssnode);
}
static int invalidated_nodes;
static int created_styles;
static guint invalidated_nodes_counter;
static guint created_styles_counter;
static void
gtk_css_node_set_invalid (GtkCssNode *node,
gboolean invalid)
@@ -126,6 +137,9 @@ gtk_css_node_set_invalid (GtkCssNode *node,
node->invalid = invalid;
if (invalid)
invalidated_nodes++;
if (node->visible)
{
if (node->parent)
@@ -356,7 +370,7 @@ gtk_css_node_create_style (GtkCssNode *cssnode,
GtkCssMatcher matcher;
GtkCssStyle *parent;
GtkCssStyle *style;
gboolean compute_change;
GtkCssChange style_change;
decl = gtk_css_node_get_declaration (cssnode);
@@ -364,26 +378,30 @@ gtk_css_node_create_style (GtkCssNode *cssnode,
if (style)
return g_object_ref (style);
created_styles++;
parent = cssnode->parent ? cssnode->parent->style : NULL;
compute_change = change & GTK_CSS_RADICAL_CHANGE;
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,
compute_change);
style_change);
else
style = gtk_css_static_style_new_compute (gtk_css_node_get_style_provider (cssnode),
NULL,
parent,
compute_change);
if (!compute_change)
{
GtkCssStyle *old_style = gtk_css_style_get_static_style (cssnode->style);
((GtkCssStaticStyle *)style)->change = ((GtkCssStaticStyle *)old_style)->change;
}
style_change);
store_in_global_parent_cache (cssnode, decl, style);
@@ -420,7 +438,7 @@ gtk_css_node_real_update_style (GtkCssNode *cssnode,
{
GtkCssStyle *static_style, *new_static_style, *new_style;
static_style = gtk_css_style_get_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, change);
@@ -442,7 +460,7 @@ gtk_css_node_real_update_style (GtkCssNode *cssnode,
}
else if (static_style != style && (change & GTK_CSS_CHANGE_TIMESTAMP))
{
new_style = gtk_css_animated_style_new_advance ((GtkCssAnimatedStyle *)style,
new_style = gtk_css_animated_style_new_advance (GTK_CSS_ANIMATED_STYLE (style),
static_style,
timestamp);
}
@@ -488,18 +506,6 @@ gtk_css_node_real_init_matcher (GtkCssNode *cssnode,
return TRUE;
}
static GtkWidgetPath *
gtk_css_node_real_create_widget_path (GtkCssNode *cssnode)
{
return gtk_widget_path_new ();
}
static const GtkWidgetPath *
gtk_css_node_real_get_widget_path (GtkCssNode *cssnode)
{
return NULL;
}
static GtkStyleProvider *
gtk_css_node_real_get_style_provider (GtkCssNode *cssnode)
{
@@ -580,8 +586,6 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
klass->queue_validate = gtk_css_node_real_queue_validate;
klass->dequeue_validate = gtk_css_node_real_dequeue_validate;
klass->init_matcher = gtk_css_node_real_init_matcher;
klass->create_widget_path = gtk_css_node_real_create_widget_path;
klass->get_widget_path = gtk_css_node_real_get_widget_path;
klass->get_style_provider = gtk_css_node_real_get_style_provider;
klass->get_frame_clock = gtk_css_node_real_get_frame_clock;
@@ -658,6 +662,12 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
| G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, NUM_PROPERTIES, cssnode_properties);
if (invalidated_nodes_counter == 0)
{
invalidated_nodes_counter = gdk_profiler_define_int_counter ("invalidated-nodes", "CSS Node Invalidations");
created_styles_counter = gdk_profiler_define_int_counter ("created-styles", "CSS Style Creations");
}
}
static void
@@ -924,12 +934,17 @@ gtk_css_node_set_style (GtkCssNode *cssnode,
{
g_signal_emit (cssnode, cssnode_signals[STYLE_CHANGED], 0, &change);
}
else if (cssnode->style != style &&
(GTK_IS_CSS_ANIMATED_STYLE (cssnode->style) || GTK_IS_CSS_ANIMATED_STYLE (style)))
else if (GTK_IS_CSS_ANIMATED_STYLE (cssnode->style) || GTK_IS_CSS_ANIMATED_STYLE (style))
{
/* This is when animations are starting/stopping but they didn't change any CSS this frame */
g_set_object (&cssnode->style, style);
}
else if (gtk_css_static_style_get_change (gtk_css_style_get_static_style (cssnode->style)) !=
gtk_css_static_style_get_change (gtk_css_style_get_static_style (style)))
{
/* This is when we recomputed the change flags but the style didn't change */
g_set_object (&cssnode->style, style);
}
gtk_css_style_change_finish (&change);
@@ -1144,9 +1159,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]);
}
}
@@ -1346,10 +1382,24 @@ void
gtk_css_node_validate (GtkCssNode *cssnode)
{
gint64 timestamp;
gint64 before = g_get_monotonic_time ();
timestamp = gtk_css_node_get_timestamp (cssnode);
gtk_css_node_validate_internal (cssnode, timestamp);
if (cssnode->parent == NULL)
{
if (gdk_profiler_is_running ())
{
gint64 after = g_get_monotonic_time ();
gdk_profiler_add_mark (before * 1000, (after - before) * 1000, "css validation", "");
gdk_profiler_set_int_counter (invalidated_nodes_counter, after * 1000, invalidated_nodes);
gdk_profiler_set_int_counter (created_styles_counter, after * 1000, created_styles);
invalidated_nodes = 0;
created_styles = 0;
}
}
}
gboolean
@@ -1359,18 +1409,6 @@ gtk_css_node_init_matcher (GtkCssNode *cssnode,
return GTK_CSS_NODE_GET_CLASS (cssnode)->init_matcher (cssnode, matcher);
}
GtkWidgetPath *
gtk_css_node_create_widget_path (GtkCssNode *cssnode)
{
return GTK_CSS_NODE_GET_CLASS (cssnode)->create_widget_path (cssnode);
}
const GtkWidgetPath *
gtk_css_node_get_widget_path (GtkCssNode *cssnode)
{
return GTK_CSS_NODE_GET_CLASS (cssnode)->get_widget_path (cssnode);
}
GtkStyleProvider *
gtk_css_node_get_style_provider (GtkCssNode *cssnode)
{
@@ -1409,10 +1447,7 @@ gtk_css_node_print (GtkCssNode *cssnode,
GtkCssStyle *style = gtk_css_node_get_style (cssnode);
GtkCssChange change;
if (!GTK_IS_CSS_STATIC_STYLE (style))
style = GTK_CSS_ANIMATED_STYLE (style)->style;
change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
change = gtk_css_static_style_get_change (gtk_css_style_get_static_style (style));
g_string_append (string, " ");
gtk_css_change_print (change, string);
}

View File

@@ -431,6 +431,17 @@ gtk_css_node_declaration_add_to_widget_path (const GtkCssNodeDeclaration *decl,
gtk_widget_path_iter_set_state (path, pos, decl->state);
}
static int
cmpstr (gconstpointer a,
gconstpointer b,
gpointer data)
{
char **ap = (char **) a;
char **bp = (char **) b;
return g_ascii_strcasecmp (*ap, *bp);
}
/* Append the declaration to the string, in selector format */
void
gtk_css_node_declaration_print (const GtkCssNodeDeclaration *decl,
@@ -453,6 +464,7 @@ gtk_css_node_declaration_print (const GtkCssNodeDeclaration *decl,
};
const GQuark *classes;
guint i;
char **classnames;
if (decl->name)
g_string_append (string, decl->name);
@@ -466,11 +478,19 @@ gtk_css_node_declaration_print (const GtkCssNodeDeclaration *decl,
}
classes = get_classes (decl);
classnames = g_new (char *, decl->n_classes);
for (i = 0; i < decl->n_classes; i++)
classnames[i] = (char *)g_quark_to_string (classes[i]);
g_qsort_with_data (classnames, decl->n_classes, sizeof (char *), cmpstr, NULL);
for (i = 0; i < decl->n_classes; i++)
{
g_string_append_c (string, '.');
g_string_append (string, g_quark_to_string (classes[i]));
g_string_append (string, classnames[i]);
}
g_free (classnames);
for (i = 0; i < G_N_ELEMENTS (state_names); i++)
{

View File

@@ -78,8 +78,6 @@ struct _GtkCssNodeClass
gboolean (* init_matcher) (GtkCssNode *cssnode,
GtkCssMatcher *matcher);
GtkWidgetPath * (* create_widget_path) (GtkCssNode *cssnode);
const GtkWidgetPath * (* get_widget_path) (GtkCssNode *cssnode);
/* get style provider to use or NULL to use parent's */
GtkStyleProvider * (* get_style_provider) (GtkCssNode *cssnode);
/* get frame clock or NULL (only relevant for root node) */
@@ -157,8 +155,6 @@ void gtk_css_node_validate (GtkCssNode *
gboolean gtk_css_node_init_matcher (GtkCssNode *cssnode,
GtkCssMatcher *matcher);
GtkWidgetPath * gtk_css_node_create_widget_path (GtkCssNode *cssnode);
const GtkWidgetPath * gtk_css_node_get_widget_path (GtkCssNode *cssnode) G_GNUC_PURE;
GtkStyleProvider * gtk_css_node_get_style_provider (GtkCssNode *cssnode) G_GNUC_PURE;
void gtk_css_node_print (GtkCssNode *cssnode,

View File

@@ -59,37 +59,6 @@ gtk_css_path_node_real_init_matcher (GtkCssNode *node,
gtk_css_node_get_declaration (node));
}
static GtkWidgetPath *
gtk_css_path_node_real_create_widget_path (GtkCssNode *node)
{
GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node);
GtkWidgetPath *path;
guint length;
if (path_node->path == NULL)
path = gtk_widget_path_new ();
else
path = gtk_widget_path_copy (path_node->path);
length = gtk_widget_path_length (path);
if (length > 0)
{
gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (node),
path,
length - 1);
}
return path;
}
static const GtkWidgetPath *
gtk_css_path_node_real_get_widget_path (GtkCssNode *node)
{
GtkCssPathNode *path_node = GTK_CSS_PATH_NODE (node);
return path_node->path;
}
static GtkCssStyle *
gtk_css_path_node_update_style (GtkCssNode *cssnode,
GtkCssChange change,
@@ -122,8 +91,6 @@ gtk_css_path_node_class_init (GtkCssPathNodeClass *klass)
node_class->invalidate = gtk_css_path_node_invalidate;
node_class->update_style = gtk_css_path_node_update_style;
node_class->init_matcher = gtk_css_path_node_real_init_matcher;
node_class->create_widget_path = gtk_css_path_node_real_create_widget_path;
node_class->get_widget_path = gtk_css_path_node_real_get_widget_path;
node_class->get_style_provider = gtk_css_path_node_get_style_provider;
}

View File

@@ -42,6 +42,7 @@
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "gdk/gdkprofilerprivate.h"
#include <cairo-gobject.h>
/**
@@ -425,89 +426,6 @@ verify_tree_match_results (GtkCssProvider *provider,
#endif
}
static GtkCssChange
get_change (GtkCssProvider *provider,
const GtkCssMatcher *matcher)
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (provider);
GtkCssChange change = 0;
GPtrArray *tree_rules;
int i;
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, matcher);
if (tree_rules)
{
for (i = tree_rules->len - 1; i >= 0; i--)
{
GtkCssRuleset *ruleset;
ruleset = tree_rules->pdata[i];
change |= _gtk_css_selector_get_change (ruleset->selector);
}
g_ptr_array_free (tree_rules, TRUE);
}
return change;
}
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)
@@ -578,14 +496,7 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
}
if (change)
{
GtkCssMatcher change_matcher;
GtkCssMatcherClass matcher_class;
_gtk_css_matcher_superset_init (&change_matcher, matcher, &matcher_class, GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME);
*change = get_change (css_provider, &change_matcher);
}
*change = _gtk_css_selector_tree_get_change_all (priv->tree, matcher);
}
static void
@@ -771,6 +682,7 @@ parse_color_definition (GtkCssScanner *scanner)
GtkCssValue *color;
char *name;
if (!gtk_css_parser_try_at_keyword (scanner->parser, "define-color"))
return FALSE;
name = gtk_css_parser_consume_ident (scanner->parser);
@@ -1055,6 +967,7 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (css_provider);
GtkCssSelectorTreeBuilder *builder;
guint i;
gint64 before = g_get_monotonic_time ();
g_array_sort (priv->rulesets, gtk_css_provider_compare_rule);
@@ -1085,6 +998,9 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
ruleset->selector = NULL;
}
#endif
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "create selector tree", NULL);
}
static void
@@ -1093,6 +1009,8 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
GFile *file,
GBytes *bytes)
{
gint64 before = g_get_monotonic_time ();
if (bytes == NULL)
{
GError *load_error = NULL;
@@ -1139,6 +1057,13 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
g_bytes_unref (bytes);
}
if (gdk_profiler_is_running ())
{
char *uri = g_file_get_uri (file);
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "theme load", uri);
g_free (uri);
}
}
/**

View File

@@ -30,7 +30,22 @@
# include <intrin.h>
#endif
#define PRINT_TREE 1
/*
* @GTK_CSS_SELECTOR_CATEGORY_SIMPLE: A simple selector
* @GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL: A simple selector that matches
* what change tracking considers a "radical change"
* @GTK_CSS_SELECTOR_SIBLING: A selector matching siblings
* @GTK_CSS_SELECTOR_CATEGORY_PARENT: A selector matching a parent or other
* ancestor
*
* Categorize the selectors. This helps in various loops when matching.
*/
typedef enum {
GTK_CSS_SELECTOR_CATEGORY_SIMPLE,
GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL,
GTK_CSS_SELECTOR_CATEGORY_PARENT,
GTK_CSS_SELECTOR_CATEGORY_SIBLING,
} GtkCssSelectorCategory;
typedef struct _GtkCssSelectorClass GtkCssSelectorClass;
typedef gboolean (* GtkCssSelectorForeachFunc) (const GtkCssSelector *selector,
@@ -38,7 +53,8 @@ typedef gboolean (* GtkCssSelectorForeachFunc) (const GtkCssSelector *selector,
gpointer data);
struct _GtkCssSelectorClass {
const char *name;
const char *name;
GtkCssSelectorCategory category;
void (* print) (const GtkCssSelector *selector,
GString *string);
@@ -63,8 +79,6 @@ struct _GtkCssSelectorClass {
guint (* hash_one) (const GtkCssSelector *selector);
int (* compare_one) (const GtkCssSelector *a,
const GtkCssSelector *b);
guint is_simple :1;
};
typedef enum {
@@ -106,7 +120,6 @@ union _GtkCssSelector
struct _GtkCssSelectorTree
{
GtkCssSelector selector;
GtkCssChange change;
gint32 parent_offset;
gint32 previous_offset;
gint32 sibling_offset;
@@ -128,7 +141,7 @@ gtk_css_selector_hash_one (const GtkCssSelector *selector)
return GPOINTER_TO_UINT (selector->class) ^ selector->class->hash_one (selector);
}
static gpointer *
static inline gpointer *
gtk_css_selector_tree_get_matches (const GtkCssSelectorTree *tree)
{
if (tree->matches_offset == GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET)
@@ -173,14 +186,14 @@ gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
}
}
static gboolean
static inline gboolean
gtk_css_selector_match (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
return selector->class->match_one (selector, matcher);
}
static gboolean
static inline gboolean
gtk_css_selector_foreach (const GtkCssSelector *selector,
const GtkCssMatcher *matcher,
GtkCssSelectorForeachFunc func,
@@ -206,7 +219,7 @@ gtk_css_selector_previous (const GtkCssSelector *selector)
return selector->class ? selector : NULL;
}
static const GtkCssSelectorTree *
static inline const GtkCssSelectorTree *
gtk_css_selector_tree_at_offset (const GtkCssSelectorTree *tree,
gint32 offset)
{
@@ -216,19 +229,19 @@ gtk_css_selector_tree_at_offset (const GtkCssSelectorTree *tree,
return (GtkCssSelectorTree *) ((guint8 *)tree + offset);
}
static const GtkCssSelectorTree *
static inline const GtkCssSelectorTree *
gtk_css_selector_tree_get_parent (const GtkCssSelectorTree *tree)
{
return gtk_css_selector_tree_at_offset (tree, tree->parent_offset);
}
static const GtkCssSelectorTree *
static inline const GtkCssSelectorTree *
gtk_css_selector_tree_get_previous (const GtkCssSelectorTree *tree)
{
return gtk_css_selector_tree_at_offset (tree, tree->previous_offset);
}
static const GtkCssSelectorTree *
static inline const GtkCssSelectorTree *
gtk_css_selector_tree_get_sibling (const GtkCssSelectorTree *tree)
{
return gtk_css_selector_tree_at_offset (tree, tree->sibling_offset);
@@ -297,11 +310,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;
@@ -315,6 +323,7 @@ gtk_css_selector_descendant_get_change (const GtkCssSelector *selector, GtkCssCh
static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
"descendant",
GTK_CSS_SELECTOR_CATEGORY_PARENT,
gtk_css_selector_descendant_print,
gtk_css_selector_descendant_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -322,7 +331,6 @@ 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
};
/* CHILD */
@@ -356,6 +364,7 @@ gtk_css_selector_child_get_change (const GtkCssSelector *selector, GtkCssChange
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
"child",
GTK_CSS_SELECTOR_CATEGORY_PARENT,
gtk_css_selector_child_print,
gtk_css_selector_child_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -363,7 +372,6 @@ 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
};
/* SIBLING */
@@ -389,11 +397,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;
@@ -407,6 +410,7 @@ gtk_css_selector_sibling_get_change (const GtkCssSelector *selector, GtkCssChang
static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
"sibling",
GTK_CSS_SELECTOR_CATEGORY_SIBLING,
gtk_css_selector_sibling_print,
gtk_css_selector_sibling_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -414,7 +418,6 @@ 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
};
/* ADJACENT */
@@ -448,6 +451,7 @@ gtk_css_selector_adjacent_get_change (const GtkCssSelector *selector, GtkCssChan
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
"adjacent",
GTK_CSS_SELECTOR_CATEGORY_SIBLING,
gtk_css_selector_adjacent_print,
gtk_css_selector_adjacent_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -455,7 +459,6 @@ 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
};
/* SIMPLE SELECTOR DEFINE */
@@ -468,7 +471,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) \
@@ -520,6 +524,7 @@ gtk_css_selector_ ## n ## _add_specificity (const GtkCssSelector *selector, \
\
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
G_STRINGIFY(n), \
ignore_for_change ? GTK_CSS_SELECTOR_CATEGORY_SIMPLE : GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL, \
gtk_css_selector_ ## n ## _print, \
gtk_css_selector_default_foreach_matcher, \
match_func, \
@@ -527,11 +532,11 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
TRUE \
};\
\
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
"not_" G_STRINGIFY(n), \
ignore_for_change ? GTK_CSS_SELECTOR_CATEGORY_SIMPLE : GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL, \
gtk_css_selector_not_ ## n ## _print, \
gtk_css_selector_default_foreach_matcher, \
gtk_css_selector_not_ ## n ## _match_one, \
@@ -539,7 +544,6 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
TRUE \
};
/* ANY */
@@ -562,7 +566,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 */
@@ -595,7 +599,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 */
@@ -632,7 +636,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 */
@@ -669,7 +673,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)
@@ -714,7 +718,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
@@ -731,10 +735,33 @@ comp_pseudoclass_state (const GtkCssSelector *a,
return a->state.state - b->state.state;
}
#define GTK_CSS_CHANGE_PSEUDOCLASS_STATE GTK_CSS_CHANGE_STATE
static GtkCssChange
change_pseudoclass_state (const GtkCssSelector *selector)
{
GtkStateFlags states = selector->state.state;
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;
return change;
}
#define GTK_CSS_CHANGE_PSEUDOCLASS_STATE change_pseudoclass_state (selector)
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 */
@@ -888,7 +915,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 */
@@ -1292,7 +1319,7 @@ 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,
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = pseudo_classes[i].state_flag;
}
@@ -1737,6 +1764,23 @@ _gtk_css_selector_get_change (const GtkCssSelector *selector)
/******************** SelectorTree handling *****************/
static gboolean
gtk_css_selector_is_simple (const GtkCssSelector *selector)
{
switch (selector->class->category)
{
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE:
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL:
return TRUE;
case GTK_CSS_SELECTOR_CATEGORY_PARENT:
case GTK_CSS_SELECTOR_CATEGORY_SIBLING:
return FALSE;
default:
g_assert_not_reached ();
return FALSE;
}
}
static GHashTable *
gtk_css_selectors_count_initial_init (void)
{
@@ -1746,7 +1790,7 @@ gtk_css_selectors_count_initial_init (void)
static void
gtk_css_selectors_count_initial (const GtkCssSelector *selector, GHashTable *hash_one)
{
if (!selector->class->is_simple)
if (!gtk_css_selector_is_simple (selector))
{
guint count = GPOINTER_TO_INT (g_hash_table_lookup (hash_one, selector));
g_hash_table_replace (hash_one, (gpointer)selector, GUINT_TO_POINTER (count + 1));
@@ -1754,7 +1798,7 @@ gtk_css_selectors_count_initial (const GtkCssSelector *selector, GHashTable *has
}
for (;
selector && selector->class->is_simple;
selector && gtk_css_selector_is_simple (selector);
selector = gtk_css_selector_previous (selector))
{
guint count = GPOINTER_TO_INT (g_hash_table_lookup (hash_one, selector));
@@ -1765,11 +1809,11 @@ gtk_css_selectors_count_initial (const GtkCssSelector *selector, GHashTable *has
static gboolean
gtk_css_selectors_has_initial_selector (const GtkCssSelector *selector, const GtkCssSelector *initial)
{
if (!selector->class->is_simple)
if (!gtk_css_selector_is_simple (selector))
return gtk_css_selector_equal (selector, initial);
for (;
selector && selector->class->is_simple;
selector && gtk_css_selector_is_simple (selector);
selector = gtk_css_selector_previous (selector))
{
if (gtk_css_selector_equal (selector, initial))
@@ -1789,13 +1833,13 @@ gtk_css_selectors_skip_initial_selector (GtkCssSelector *selector, const GtkCssS
without losing any other selectors */
if (!gtk_css_selector_equal (selector, initial))
{
for (found = selector; found && found->class->is_simple; found = (GtkCssSelector *)gtk_css_selector_previous (found))
for (found = selector; found && gtk_css_selector_is_simple (found); found = (GtkCssSelector *)gtk_css_selector_previous (found))
{
if (gtk_css_selector_equal (found, initial))
break;
}
g_assert (found != NULL && found->class->is_simple);
g_assert (found != NULL && gtk_css_selector_is_simple (found));
tmp = *found;
*found = *selector;
@@ -1839,6 +1883,21 @@ _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
return array;
}
/* The code for collecting matches assumes that the name, id and classes
* of a node remain unchanged, and anything else can change. This needs to
* be kept in sync with the definition of 'radical change' in gtkcssnode.c.
*/
static gboolean
gtk_css_selector_match_for_change (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
if (selector->class->category != GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL)
return TRUE;
return selector->class->match_one (selector, matcher);
}
/* When checking for changes via the tree we need to know if a rule further
down the tree matched, because if so we need to add "our bit" to the
Change. For instance in a match like *.class:active we'll
@@ -1873,11 +1932,11 @@ 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)
return tree->change | GTK_CSS_CHANGE_GOT_MATCH;
if (!gtk_css_selector_is_simple (&tree->selector))
return gtk_css_selector_tree_collect_change (tree) | GTK_CSS_CHANGE_GOT_MATCH;
for (prev = gtk_css_selector_tree_get_previous (tree);
prev != NULL;
@@ -1914,16 +1973,12 @@ _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
}
#ifdef PRINT_TREE
static void
_gtk_css_selector_tree_print_recurse (const GtkCssSelectorTree *tree,
GString *str,
const char *prefix,
GHashTable *counts)
_gtk_css_selector_tree_print (const GtkCssSelectorTree *tree, GString *str, char *prefix)
{
gboolean first = TRUE;
int len, i;
int count;
gpointer *matches;
for (; tree != NULL; tree = gtk_css_selector_tree_get_sibling (tree), first = FALSE)
{
@@ -1947,12 +2002,18 @@ _gtk_css_selector_tree_print_recurse (const GtkCssSelectorTree *tree,
len = str->len;
tree->selector.class->print (&tree->selector, str);
matches = gtk_css_selector_tree_get_matches (tree);
if (matches)
{
int n;
for (n = 0; matches[n] != NULL; n++) ;
if (n == 1)
g_string_append (str, " (1 match)");
else
g_string_append_printf (str, " (%d matches)", n);
}
len = str->len - len;
count = GPOINTER_TO_INT (g_hash_table_lookup (counts, (gpointer)tree->selector.class->name));
count++;
g_hash_table_insert (counts, (gpointer)tree->selector.class->name, GINT_TO_POINTER (count));
if (gtk_css_selector_tree_get_previous (tree))
{
GString *prefix2 = g_string_new (prefix);
@@ -1964,35 +2025,13 @@ _gtk_css_selector_tree_print_recurse (const GtkCssSelectorTree *tree,
for (i = 0; i < len; i++)
g_string_append_c (prefix2, ' ');
_gtk_css_selector_tree_print_recurse (gtk_css_selector_tree_get_previous (tree), str, prefix2->str, counts);
_gtk_css_selector_tree_print (gtk_css_selector_tree_get_previous (tree), str, prefix2->str);
g_string_free (prefix2, TRUE);
}
else
g_string_append (str, "\n");
}
}
static void
_gtk_css_selector_tree_print (const GtkCssSelectorTree *tree, GString *str, const char *prefix)
{
GHashTable *counts;
GHashTableIter iter;
const char *key;
gpointer value;
counts = g_hash_table_new (g_str_hash, g_str_equal);
_gtk_css_selector_tree_print_recurse (tree, str, prefix, counts);
g_string_append (str, "\n\nSelector counts:\n");
g_hash_table_iter_init (&iter, counts);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, &value))
g_string_append_printf (str, "%-*s %4d\n", (int)strlen ("not_pseudoclass_position"), key, GPOINTER_TO_INT (value));
g_string_append (str, "\n");
g_hash_table_unref (counts);
}
#endif
void
@@ -2005,7 +2044,7 @@ _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
/* print name and * selector before others */
for (iter = tree;
iter && iter->selector.class->is_simple;
iter && gtk_css_selector_is_simple (&iter->selector);
iter = gtk_css_selector_tree_get_parent (iter))
{
if (iter->selector.class == &GTK_CSS_SELECTOR_NAME ||
@@ -2016,7 +2055,7 @@ _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
}
/* now print other simple selectors */
for (iter = tree;
iter && iter->selector.class->is_simple;
iter && gtk_css_selector_is_simple (&iter->selector);
iter = gtk_css_selector_tree_get_parent (iter))
{
if (iter->selector.class != &GTK_CSS_SELECTOR_NAME &&
@@ -2118,7 +2157,6 @@ subdivide_infos (GByteArray *array, GList *infos, gint32 parent_offset)
remaining = NULL;
tree = alloc_tree (array, &tree_offset);
tree->change = 0;
tree->parent_offset = parent_offset;
tree->selector = max_selector;
@@ -2228,20 +2266,6 @@ fixup_offsets (GtkCssSelectorTree *tree, guint8 *data)
}
}
static void
compute_change (GtkCssSelectorTree *tree)
{
for (; tree != NULL;
tree = (GtkCssSelectorTree *)gtk_css_selector_tree_get_sibling (tree))
{
GtkCssSelectorTree *prev = (GtkCssSelectorTree *)gtk_css_selector_tree_get_previous (tree);
tree->change = gtk_css_selector_tree_collect_change (tree);
compute_change (prev);
}
}
GtkCssSelectorTree *
_gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
{
@@ -2265,8 +2289,6 @@ _gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
fixup_offsets (tree, data);
compute_change (tree);
/* Convert offsets to final pointers */
for (l = builder->infos; l != NULL; l = l->next)
{

View File

@@ -172,16 +172,9 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
guint i, len;
ShadowValue *shadows;
if (start == end)
return _gtk_css_value_ref (start);
if (start->n_shadows != end->n_shadows)
return NULL;
/* catches the important case of 2 none shadows */
if (start == end)
return _gtk_css_value_ref (start);
if (start->n_shadows > end->n_shadows)
len = start->n_shadows;
else
@@ -198,7 +191,6 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
while (i--)
shadow_value_unref (&shadows[i]);
g_message ("NOPE. REturning NULL!");
return NULL;
}
}
@@ -215,7 +207,6 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
while (i--)
shadow_value_unref (&shadows[i]);
shadow_value_unref (&fill);
g_message ("NOPE2. REturning NULL!");
return NULL;
}
shadow_value_unref (&fill);
@@ -233,7 +224,6 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
while (i--)
shadow_value_unref (&shadows[i]);
shadow_value_unref (&fill);
g_message ("NOPE3. REturning NULL!");
return NULL;
}
shadow_value_unref (&fill);
@@ -297,6 +287,13 @@ static const GtkCssValueClass GTK_CSS_VALUE_SHADOW = {
gtk_css_value_shadow_print
};
static GtkCssValue none_singleton = { &GTK_CSS_VALUE_SHADOW, 1, TRUE, 0 };
GtkCssValue *
gtk_css_shadow_value_new_none (void)
{
return _gtk_css_value_ref (&none_singleton);
}
static GtkCssValue *
gtk_css_shadow_value_new (ShadowValue *shadows,
@@ -305,6 +302,9 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
GtkCssValue *retval;
guint i;
if (n_shadows == 0)
return gtk_css_shadow_value_new_none ();
retval = _gtk_css_value_alloc (&GTK_CSS_VALUE_SHADOW, sizeof (GtkCssValue) + sizeof (ShadowValue) * (n_shadows - 1));
retval->n_shadows = n_shadows;
@@ -329,14 +329,6 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
return retval;
}
static GtkCssValue none_singleton = { &GTK_CSS_VALUE_SHADOW, 1, TRUE, 0 };
GtkCssValue *
gtk_css_shadow_value_new_none (void)
{
return _gtk_css_value_ref (&none_singleton);
}
enum {
HOFFSET,
VOFFSET,

View File

@@ -1143,18 +1143,26 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
v = (* query_func) (GTK_CSS_PROPERTY_FONT_FAMILY, query_data);
if (v)
{
int i;
GString *s = g_string_new ("");
for (i = 0; i < _gtk_css_array_value_get_n_values (v); i++)
if (_gtk_css_array_value_get_n_values (v) > 1)
{
if (i > 0)
g_string_append (s, ",");
g_string_append (s, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, i)));
}
int i;
GString *s = g_string_new ("");
pango_font_description_set_family (description, s->str);
g_string_free (s, TRUE);
for (i = 0; i < _gtk_css_array_value_get_n_values (v); i++)
{
if (i > 0)
g_string_append (s, ",");
g_string_append (s, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, i)));
}
pango_font_description_set_family (description, s->str);
g_string_free (s, TRUE);
}
else
{
pango_font_description_set_family (description,
_gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, 0)));
}
}
v = (* query_func) (GTK_CSS_PROPERTY_FONT_SIZE, query_data);

View File

@@ -84,6 +84,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)
{
@@ -94,6 +100,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
@@ -108,34 +115,6 @@ maybe_unref_section (gpointer section)
gtk_css_section_unref (section);
}
static void
gtk_css_static_style_set_value (GtkCssStaticStyle *style,
guint id,
GtkCssValue *value,
GtkCssSection *section)
{
if (style->values[id])
_gtk_css_value_unref (style->values[id]);
style->values[id] = value;
if (style->sections && style->sections->len > id && g_ptr_array_index (style->sections, id))
{
gtk_css_section_unref (g_ptr_array_index (style->sections, id));
g_ptr_array_index (style->sections, id) = NULL;
}
if (section)
{
if (style->sections == NULL)
style->sections = g_ptr_array_new_with_free_func (maybe_unref_section);
if (style->sections->len <= id)
g_ptr_array_set_size (style->sections, id + 1);
g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
}
}
static GtkCssStyle *default_style;
static void
@@ -168,15 +147,128 @@ gtk_css_static_style_get_default (void)
return default_style;
}
G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_TOP_STYLE == GTK_CSS_PROPERTY_BORDER_TOP_WIDTH - 1);
G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE == GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH - 1);
G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE == GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH - 1);
G_STATIC_ASSERT (GTK_CSS_PROPERTY_BORDER_LEFT_STYLE == GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH - 1);
G_STATIC_ASSERT (GTK_CSS_PROPERTY_OUTLINE_STYLE == GTK_CSS_PROPERTY_OUTLINE_WIDTH - 1);
static inline gboolean
is_border_style_special_case (guint id)
{
switch (id)
{
case GTK_CSS_PROPERTY_BORDER_TOP_STYLE:
case GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE:
case GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE:
case GTK_CSS_PROPERTY_BORDER_LEFT_STYLE:
case GTK_CSS_PROPERTY_OUTLINE_STYLE:
return TRUE;
default:
return FALSE;
}
}
static void
gtk_css_static_style_compute_values (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
GtkCssStyle *parent_style,
GtkCssLookup *lookup)
{
GtkCssLookupValue *values = lookup->values;
guint id;
GtkCssValue **parent_values;
guint border_prop[] = {
GTK_CSS_PROPERTY_BORDER_TOP_STYLE,
GTK_CSS_PROPERTY_BORDER_LEFT_STYLE,
GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE,
GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE,
GTK_CSS_PROPERTY_OUTLINE_STYLE,
0
};
int b = 0;
if (GTK_IS_CSS_STATIC_STYLE (parent_style))
parent_values = GTK_CSS_STATIC_STYLE (parent_style)->values;
else
parent_values = NULL;
for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++)
{
GtkCssValue *specified = values[id].value;
/* http://www.w3.org/TR/css3-cascade/#cascade
* Then, for every element, the value for each property can be found
* by following this pseudo-algorithm:
* 1) Identify all declarations that apply to the element
*/
if (specified)
{
style->values[id] = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style);
/* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
if (id == border_prop[b])
{
b++;
/* We have them ordered in gtkcssstylepropertyimpl.c accordingly, so the
* border styles are computed before the border widths.
* Note that we rely on ..._WIDTH == ..._STYLE + 1 here.
*/
GtkBorderStyle border_style = _gtk_css_border_style_value_get (style->values[id]);
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
{
id++;
style->values[id] = gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
}
}
}
else if (parent_values && gtk_css_style_property_is_inherit (id))
{
style->values[id] = _gtk_css_value_ref (parent_values[id]);
/* the border properties are not inherit, so no need to check the special case here */
}
else if (parent_style && gtk_css_style_property_is_inherit (id))
{
style->values[id] = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id));
/* the border properties are not inherit, so no need to check the special case here */
}
else
{
style->values[id] = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style);
/* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
if (id == border_prop[b])
{
b++;
/* no need to check the value. The initial value of the border-style properties is none */
id++;
style->values[id] = gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
}
}
}
if (lookup->has_section)
{
style->sections = g_ptr_array_new_full (GTK_CSS_PROPERTY_N_PROPERTIES, maybe_unref_section);
for (id = 0; id < GTK_CSS_PROPERTY_N_PROPERTIES; id++)
{
GtkCssSection *section = values[id].section;
if (section)
g_ptr_array_index (style->sections, id) = gtk_css_section_ref (section);
}
}
}
GtkCssStyle *
gtk_css_static_style_new_compute (GtkStyleProvider *provider,
const GtkCssMatcher *matcher,
GtkCssStyle *parent,
gboolean compute_change)
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);
@@ -184,84 +276,19 @@ gtk_css_static_style_new_compute (GtkStyleProvider *provider,
gtk_style_provider_lookup (provider,
matcher,
&lookup,
compute_change ? &change : NULL);
change == 0 ? &change : NULL);
result = g_object_new (GTK_TYPE_CSS_STATIC_STYLE, NULL);
result->change = change;
_gtk_css_lookup_resolve (&lookup,
provider,
result,
parent);
gtk_css_static_style_compute_values (result, provider, parent, &lookup);
_gtk_css_lookup_destroy (&lookup);
return GTK_CSS_STYLE (result);
}
void
gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
GtkCssStyle *parent_style,
guint id,
GtkCssValue *specified,
GtkCssSection *section)
{
GtkCssValue *value;
GtkBorderStyle border_style;
gtk_internal_return_if_fail (id < GTK_CSS_PROPERTY_N_PROPERTIES);
/* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
switch (id)
{
/* We have them ordered in gtkcssstylepropertyimpl.c accordingly, so the
* border styles are already computed when we compute the border widths.
*
* Note that we rely on ..._STYLE == ..._WIDTH - 1 here.
*/
case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH:
case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH:
case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH:
case GTK_CSS_PROPERTY_OUTLINE_WIDTH:
border_style = _gtk_css_border_style_value_get (gtk_css_style_get_value ((GtkCssStyle *)style, id - 1));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
{
gtk_css_static_style_set_value (style, id, gtk_css_dimension_value_new (0, GTK_CSS_NUMBER), section);
return;
}
break;
default:
/* Go ahead */
break;
}
/* http://www.w3.org/TR/css3-cascade/#cascade
* Then, for every element, the value for each property can be found
* by following this pseudo-algorithm:
* 1) Identify all declarations that apply to the element
*/
if (specified)
{
value = _gtk_css_value_compute (specified, id, provider, (GtkCssStyle *)style, parent_style);
}
else if (parent_style && _gtk_css_style_property_is_inherit (_gtk_css_style_property_lookup_by_id (id)))
{
/* Just take the style from the parent */
value = _gtk_css_value_ref (gtk_css_style_get_value (parent_style, id));
}
else
{
value = _gtk_css_initial_value_new_compute (id, provider, (GtkCssStyle *)style, parent_style);
}
gtk_css_static_style_set_value (style, id, value, section);
}
GtkCssChange
gtk_css_static_style_get_change (GtkCssStaticStyle *style)
{

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
@@ -56,15 +55,7 @@ GtkCssStyle * gtk_css_static_style_get_default (void);
GtkCssStyle * gtk_css_static_style_new_compute (GtkStyleProvider *provider,
const GtkCssMatcher *matcher,
GtkCssStyle *parent,
gboolean compute_change);
void gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
GtkCssStyle *parent_style,
guint id,
GtkCssValue *specified,
GtkCssSection *section);
GtkCssChange change);
GtkCssChange gtk_css_static_style_get_change (GtkCssStaticStyle *style);
G_END_DECLS

View File

@@ -31,13 +31,13 @@
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtkcssstringvalueprivate.h"
#include "gtkcssfontvariationsvalueprivate.h"
#include "gtkcssfontfeaturesvalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkcsstransitionprivate.h"
#include "gtkstyleanimationprivate.h"
#include "gtkstylepropertyprivate.h"
#include "gtkstyleproviderprivate.h"
#include "gtksettings.h"
G_DEFINE_ABSTRACT_TYPE (GtkCssStyle, gtk_css_style, G_TYPE_OBJECT)
@@ -54,18 +54,11 @@ gtk_css_style_real_is_static (GtkCssStyle *style)
return TRUE;
}
static GtkCssStyle *
gtk_css_style_real_get_static_style (GtkCssStyle *style)
{
return style;
}
static void
gtk_css_style_class_init (GtkCssStyleClass *klass)
{
klass->get_section = gtk_css_style_real_get_section;
klass->is_static = gtk_css_style_real_is_static;
klass->get_static_style = gtk_css_style_real_get_static_style;
}
static void
@@ -97,7 +90,7 @@ gtk_css_style_is_static (GtkCssStyle *style)
return GTK_CSS_STYLE_GET_CLASS (style)->is_static (style);
}
GtkCssStyle *
GtkCssStaticStyle *
gtk_css_style_get_static_style (GtkCssStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
@@ -126,17 +119,11 @@ gtk_css_style_print (GtkCssStyle *style,
gboolean skip_initial)
{
guint i;
GtkCssStyle *default_style;
gboolean retval = FALSE;
g_return_val_if_fail (GTK_IS_CSS_STYLE (style), FALSE);
g_return_val_if_fail (string != NULL, FALSE);
default_style = gtk_css_static_style_get_default ();
if (style == default_style)
g_string_append_printf (string, "%*sDEFAULT STYLE\n", indent, "");
for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
{
GtkCssSection *section;
@@ -144,23 +131,13 @@ gtk_css_style_print (GtkCssStyle *style,
GtkCssValue *value;
const char *name;
value = gtk_css_style_get_value (style, i);
prop = _gtk_css_style_property_lookup_by_id (i);
if (skip_initial)
{
GtkCssValue *initial = _gtk_css_style_property_get_initial_value (prop);
GtkCssValue *computed = _gtk_css_value_compute (initial, i,
GTK_STYLE_PROVIDER (gtk_settings_get_default ()),
default_style,
default_style);
gboolean is_initial = _gtk_css_value_equal (value, computed);
gtk_css_value_unref (computed);
if (is_initial)
continue;
}
section = gtk_css_style_get_section (style, i);
if (!section && skip_initial)
continue;
prop = _gtk_css_style_property_lookup_by_id (i);
name = _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop));
value = gtk_css_style_get_value (style, i);
g_string_append_printf (string, "%*s%s: ", indent, "", name);
_gtk_css_value_print (value, string);
@@ -447,21 +424,53 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
return attrs;
}
static GtkCssValue *
query_func (guint id,
gpointer values)
{
return gtk_css_style_get_value (values, id);
}
PangoFontDescription *
gtk_css_style_get_pango_font (GtkCssStyle *style)
{
GtkStyleProperty *prop;
GValue value = { 0, };
PangoFontDescription *description;
GtkCssValue *v;
char *str;
prop = _gtk_style_property_lookup ("font");
_gtk_style_property_query (prop, &value, query_func, style);
description = pango_font_description_new ();
return (PangoFontDescription *)g_value_get_boxed (&value);
v = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_FAMILY);
if (_gtk_css_array_value_get_n_values (v) > 1)
{
int i;
GString *s = g_string_new ("");
for (i = 0; i < _gtk_css_array_value_get_n_values (v); i++)
{
if (i > 0)
g_string_append (s, ",");
g_string_append (s, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, i)));
}
pango_font_description_set_family (description, s->str);
g_string_free (s, TRUE);
}
else
{
pango_font_description_set_family (description,
_gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, 0)));
}
v = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_SIZE);
pango_font_description_set_absolute_size (description, round (_gtk_css_number_value_get (v, 100) * PANGO_SCALE));
v = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_STYLE);
pango_font_description_set_style (description, _gtk_css_font_style_value_get (v));
v = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_WEIGHT);
pango_font_description_set_weight (description, _gtk_css_number_value_get (v, 100));
v = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_STRETCH);
pango_font_description_set_stretch (description, _gtk_css_font_stretch_value_get (v));
v = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS);
str = gtk_css_font_variations_value_get_variations (v);
pango_font_description_set_variations (description, str);
g_free (str);
return description;
}

View File

@@ -57,7 +57,7 @@ struct _GtkCssStyleClass
/* TRUE if this style will require changes based on timestamp */
gboolean (* is_static) (GtkCssStyle *style);
GtkCssStyle * (* get_static_style) (GtkCssStyle *style);
GtkCssStaticStyle * (* get_static_style) (GtkCssStyle *style);
};
GType gtk_css_style_get_type (void) G_GNUC_CONST;
@@ -76,7 +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);
GtkCssStyle * gtk_css_style_get_static_style (GtkCssStyle *style);
GtkCssStaticStyle * gtk_css_style_get_static_style (GtkCssStyle *style);
G_END_DECLS

View File

@@ -66,6 +66,8 @@ typedef enum {
GTK_STYLE_PROPERTY_ANIMATED = (1 << 1),
} GtkStylePropertyFlags;
gboolean inherit_properties[ GTK_CSS_PROPERTY_N_PROPERTIES];
static void
gtk_css_style_property_register (const char * name,
guint expected_id,
@@ -96,6 +98,8 @@ gtk_css_style_property_register (const char * name,
_gtk_css_value_unref (initial_value);
inherit_properties[expected_id] = (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE;
g_assert (_gtk_css_style_property_get_id (node) == expected_id);
}
@@ -921,6 +925,10 @@ icon_theme_value_parse (GtkCssStyleProperty *property,
/*** REGISTRATION ***/
G_STATIC_ASSERT (GTK_CSS_PROPERTY_COLOR == 0);
G_STATIC_ASSERT (GTK_CSS_PROPERTY_DPI < GTK_CSS_PROPERTY_FONT_SIZE);
void
_gtk_css_style_property_init_properties (void)
{
@@ -932,7 +940,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_COLOR,
GDK_TYPE_RGBA,
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_CONTENT | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
GTK_CSS_AFFECTS_CONTENT | GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC,
color_parse,
color_query,
gtk_css_color_value_new_white ());
@@ -956,7 +964,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_THEME,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | GTK_CSS_AFFECTS_ICON_SIZE,
GTK_CSS_AFFECTS_ICON_TEXTURE,
icon_theme_value_parse,
NULL,
gtk_css_icon_theme_value_new (NULL));
@@ -964,7 +972,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_PALETTE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED | GTK_STYLE_PROPERTY_INHERIT,
GTK_CSS_AFFECTS_SYMBOLIC_ICON,
GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC,
icon_palette_parse,
NULL,
gtk_css_palette_value_new_default ());
@@ -1491,7 +1499,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_SOURCE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
GTK_CSS_AFFECTS_ICON_TEXTURE,
css_image_value_parse,
NULL,
_gtk_css_image_value_new (NULL));
@@ -1499,7 +1507,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_SIZE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_ICON_SIZE,
icon_size_parse,
NULL,
_gtk_css_number_value_new (16, GTK_CSS_PX));
@@ -1507,7 +1515,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_SHADOW,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
GTK_CSS_AFFECTS_ICON_REDRAW,
shadow_value_parse,
NULL,
gtk_css_shadow_value_new_none ());
@@ -1515,7 +1523,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_STYLE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | GTK_CSS_AFFECTS_ICON_SIZE,
GTK_CSS_AFFECTS_ICON_TEXTURE,
icon_style_parse,
NULL,
_gtk_css_icon_style_value_new (GTK_CSS_ICON_STYLE_REQUESTED));
@@ -1717,4 +1725,5 @@ _gtk_css_style_property_init_properties (void)
parse_font_variation_settings,
NULL,
gtk_css_font_variations_value_new_default ());
}

View File

@@ -80,6 +80,13 @@ void _gtk_css_style_property_print_value (GtkCssStyleProp
GtkCssValue *value,
GString *string);
extern gboolean inherit_properties[];
inline gboolean gtk_css_style_property_is_inherit (uint id)
{
return inherit_properties[id];
}
/* 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);

View File

@@ -22,36 +22,6 @@
G_DEFINE_TYPE (GtkCssTransientNode, gtk_css_transient_node, GTK_TYPE_CSS_NODE)
static GtkWidgetPath *
gtk_css_transient_node_create_widget_path (GtkCssNode *node)
{
GtkWidgetPath *result;
GtkCssNode *parent;
parent = gtk_css_node_get_parent (node);
if (parent == NULL)
result = gtk_widget_path_new ();
else
result = gtk_css_node_create_widget_path (parent);
gtk_widget_path_append_type (result, gtk_css_node_get_widget_type (node));
gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (node), result, -1);
return result;
}
static const GtkWidgetPath *
gtk_css_transient_node_get_widget_path (GtkCssNode *node)
{
GtkCssNode *parent;
parent = gtk_css_node_get_parent (node);
if (parent == NULL)
return NULL;
return gtk_css_node_get_widget_path (parent);
}
static GtkCssStyle *
gtk_css_transient_node_update_style (GtkCssNode *cssnode,
GtkCssChange change,
@@ -67,8 +37,6 @@ gtk_css_transient_node_class_init (GtkCssTransientNodeClass *klass)
{
GtkCssNodeClass *node_class = GTK_CSS_NODE_CLASS (klass);
node_class->create_widget_path = gtk_css_transient_node_create_widget_path;
node_class->get_widget_path = gtk_css_transient_node_get_widget_path;
node_class->update_style = gtk_css_transient_node_update_style;
}

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,7 +168,12 @@ 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_SIBLING_CLASS, "parent-sibling-" },
{ 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-class" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_NAME, "parent-sibling-name" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_ID, "parent-sibling-id" },
{ GTK_CSS_CHANGE_PARENT_SIBLING_FIRST_CHILD, "parent-sibling-first-child" },
@@ -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" },

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_NAME (1ULL << 37)
#define GTK_CSS_CHANGE_PARENT_SIBLING_ID (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:
@@ -99,13 +132,16 @@ typedef guint64 GtkCssChange;
* see @GTK_CSS_AFFECTS_TEXT.
* @GTK_CSS_AFFECTS_BACKGROUND: The background rendering is affected.
* @GTK_CSS_AFFECTS_BORDER: The border styling is affected.
* @GTK_CSS_AFFECTS_ICON_SIZE: Icon size is affected.
* @GTK_CSS_AFFECTS_TEXT_ATTRS: Text attributes are affected.
* @GTK_CSS_AFFECTS_TEXT_SIZE: Text size is affected.
* @GTK_CSS_AFFECTS_TEXT_CONTENT: Text rendering is affected, but size or
* attributes are not.
* @GTK_CSS_AFFECTS_ICON: Fullcolor icons and their rendering is affected.
* @GTK_CSS_AFFECTS_SYMBOLIC_ICON: Symbolic icons and their rendering is affected.
* @GTK_CSS_AFFECTS_ICON_SIZE: Icon size is affected.
* @GTK_CSS_AFFECTS_ICON_TEXTURE: The icon texture has changed and needs to be
* reloaded.
* @GTK_CSS_AFFECTS_ICON_REDRAW: Icons need to be redrawn (both symbolic and
* non-symbolic).
* @GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC: Symbolic icons need to be redrawn.
* @GTK_CSS_AFFECTS_OUTLINE: The outline styling is affected.
* @GTK_CSS_AFFECTS_SIZE: Changes in this property may have an effect
* on the allocated size of the element. Changes in these properties
@@ -121,26 +157,25 @@ typedef guint64 GtkCssChange;
* Note that multiple values can be set.
*/
typedef enum {
GTK_CSS_AFFECTS_CONTENT = (1 << 0),
GTK_CSS_AFFECTS_BACKGROUND = (1 << 1),
GTK_CSS_AFFECTS_BORDER = (1 << 2),
GTK_CSS_AFFECTS_ICON_SIZE = (1 << 3),
GTK_CSS_AFFECTS_TEXT_ATTRS = (1 << 4),
GTK_CSS_AFFECTS_TEXT_SIZE = (1 << 5),
GTK_CSS_AFFECTS_TEXT_CONTENT = (1 << 6),
GTK_CSS_AFFECTS_ICON = (1 << 7),
GTK_CSS_AFFECTS_SYMBOLIC_ICON = (1 << 8),
GTK_CSS_AFFECTS_OUTLINE = (1 << 9),
GTK_CSS_AFFECTS_SIZE = (1 << 10),
GTK_CSS_AFFECTS_POSTEFFECT = (1 << 11),
GTK_CSS_AFFECTS_TRANSFORM = (1 << 12),
GTK_CSS_AFFECTS_CONTENT = (1 << 0),
GTK_CSS_AFFECTS_BACKGROUND = (1 << 1),
GTK_CSS_AFFECTS_BORDER = (1 << 2),
GTK_CSS_AFFECTS_TEXT_ATTRS = (1 << 3),
GTK_CSS_AFFECTS_TEXT_SIZE = (1 << 4),
GTK_CSS_AFFECTS_TEXT_CONTENT = (1 << 5),
GTK_CSS_AFFECTS_ICON_SIZE = (1 << 6),
GTK_CSS_AFFECTS_ICON_TEXTURE = (1 << 7),
GTK_CSS_AFFECTS_ICON_REDRAW = (1 << 8),
GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC = (1 << 9),
GTK_CSS_AFFECTS_OUTLINE = (1 << 10),
GTK_CSS_AFFECTS_SIZE = (1 << 11),
GTK_CSS_AFFECTS_POSTEFFECT = (1 << 12),
GTK_CSS_AFFECTS_TRANSFORM = (1 << 13),
} GtkCssAffects;
#define GTK_CSS_AFFECTS_REDRAW (GTK_CSS_AFFECTS_CONTENT | \
GTK_CSS_AFFECTS_BACKGROUND | \
GTK_CSS_AFFECTS_BORDER | \
GTK_CSS_AFFECTS_ICON | \
GTK_CSS_AFFECTS_SYMBOLIC_ICON | \
GTK_CSS_AFFECTS_OUTLINE | \
GTK_CSS_AFFECTS_POSTEFFECT)

View File

@@ -29,7 +29,9 @@ struct _GtkCssValue {
G_DEFINE_BOXED_TYPE (GtkCssValue, _gtk_css_value, _gtk_css_value_ref, _gtk_css_value_unref)
#define CSS_VALUE_ACCOUNTING 1
#undef CSS_VALUE_ACCOUNTING
#ifdef CSS_VALUE_ACCOUNTING
static GHashTable *counters;
typedef struct
@@ -132,13 +134,13 @@ get_accounting_data (const char *class)
return c;
}
#endif
GtkCssValue *
_gtk_css_value_alloc (const GtkCssValueClass *klass,
gsize size)
{
GtkCssValue *value;
ValueAccounting *c;
value = g_slice_alloc0 (size);
@@ -146,9 +148,13 @@ _gtk_css_value_alloc (const GtkCssValueClass *klass,
value->ref_count = 1;
#ifdef CSS_VALUE_ACCOUNTING
c = get_accounting_data (klass->type_name);
c->all++;
c->alive++;
{
ValueAccounting *c;
c = get_accounting_data (klass->type_name);
c->all++;
c->alive++;
}
#endif
return value;
@@ -167,8 +173,6 @@ gtk_css_value_ref (GtkCssValue *value)
void
gtk_css_value_unref (GtkCssValue *value)
{
ValueAccounting *c;
if (value == NULL)
return;
@@ -177,8 +181,12 @@ gtk_css_value_unref (GtkCssValue *value)
return;
#ifdef CSS_VALUE_ACCOUNTING
c = get_accounting_data (value->class->type_name);
c->alive--;
{
ValueAccounting *c;
c = get_accounting_data (value->class->type_name);
c->alive--;
}
#endif
value->class->free (value);

View File

@@ -38,20 +38,6 @@ gtk_css_widget_node_finalize (GObject *object)
G_OBJECT_CLASS (gtk_css_widget_node_parent_class)->finalize (object);
}
static void
gtk_css_widget_node_style_changed (GtkCssNode *cssnode,
GtkCssStyleChange *change)
{
GtkCssWidgetNode *node;
node = GTK_CSS_WIDGET_NODE (cssnode);
if (node->widget)
gtk_widget_clear_path (node->widget);
GTK_CSS_NODE_CLASS (gtk_css_widget_node_parent_class)->style_changed (cssnode, change);
}
static gboolean
gtk_css_widget_node_queue_callback (GtkWidget *widget,
GdkFrameClock *frame_clock,
@@ -133,40 +119,6 @@ gtk_css_widget_node_init_matcher (GtkCssNode *node,
return GTK_CSS_NODE_CLASS (gtk_css_widget_node_parent_class)->init_matcher (node, matcher);
}
static GtkWidgetPath *
gtk_css_widget_node_create_widget_path (GtkCssNode *node)
{
GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
GtkWidgetPath *path;
guint length;
if (widget_node->widget == NULL)
path = gtk_widget_path_new ();
else
path = _gtk_widget_create_path (widget_node->widget);
length = gtk_widget_path_length (path);
if (length > 0)
{
gtk_css_node_declaration_add_to_widget_path (gtk_css_node_get_declaration (node),
path,
length - 1);
}
return path;
}
static const GtkWidgetPath *
gtk_css_widget_node_get_widget_path (GtkCssNode *node)
{
GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
if (widget_node->widget == NULL)
return NULL;
return gtk_widget_get_path (widget_node->widget);
}
static GtkStyleProvider *
gtk_css_widget_node_get_style_provider (GtkCssNode *node)
{
@@ -211,11 +163,8 @@ gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass)
node_class->queue_validate = gtk_css_widget_node_queue_validate;
node_class->dequeue_validate = gtk_css_widget_node_dequeue_validate;
node_class->init_matcher = gtk_css_widget_node_init_matcher;
node_class->create_widget_path = gtk_css_widget_node_create_widget_path;
node_class->get_widget_path = gtk_css_widget_node_get_widget_path;
node_class->get_style_provider = gtk_css_widget_node_get_style_provider;
node_class->get_frame_clock = gtk_css_widget_node_get_frame_clock;
node_class->style_changed = gtk_css_widget_node_style_changed;
}
static void

View File

@@ -475,7 +475,7 @@ gtk_drop_target_set_actions (GtkDropTarget *dest,
/**
* gtk_drop_target_get_actions:
* @dst: a #GtkDropTarget
* @dest: a #GtkDropTarget
*
* Gets the actions that this drop target supports.
*
@@ -514,7 +514,7 @@ gtk_drag_dest_hierarchy_changed (GtkWidget *widget,
*
* Returns the underlying #GtkDrop object for an ongoing drag.
*
* Returns: (nullable): the #GtkDrop of the current drag operation, or %NULL
* Returns: (nullable) (transfer none): the #GtkDrop of the current drag operation, or %NULL
*/
GdkDrop *
gtk_drop_target_get_drop (GtkDropTarget *dest)

View File

@@ -79,7 +79,7 @@ void gtk_drop_target_read_selection (GtkDropTarget *dest,
GdkAtom target,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
gpointer user_data);
GDK_AVAILABLE_IN_ALL
GtkSelectionData *gtk_drop_target_read_selection_finish
(GtkDropTarget *dest,

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