Compare commits

...

247 Commits

Author SHA1 Message Date
Matthias Clasen
8a14144658 Replace generic setter code
Instead of going through a big switch of all properties,
make the new_compute() functions for each values struct
directly set its members. This way, we can also avoid the
border-width special case for more properties.
2020-01-26 23:50:52 -05:00
Matthias Clasen
0ff6176525 Add some checking for the group splitup
Verify that we don't miss properties or have them
more than once.
2020-01-26 22:29:55 -05:00
Matthias Clasen
c30befed1e Add accounting for styles 2020-01-26 22:29:55 -05:00
Matthias Clasen
9d38806ced css: Split style into groups 2020-01-26 22:29:55 -05:00
Matthias Clasen
3cdde3fc4b css: Don't lose inset when computing shadows
This was showing up as reftest failures,
sporadically
2020-01-26 20:18:23 -05:00
Timm Bäder
05b9a99661 gsk: Remove some unused defines
These are from the GVariant days of render nodes.
2020-01-26 18:21:07 +01:00
Timm Bäder
a16e1cbf18 cssdimensionvalue: Remove an outdated comment
It's actually implemented in gtkcssdimensionvalue.c these days.
2020-01-26 18:21:07 +01:00
Timm Bäder
c7ea83cd82 cssboxes: Try to avoid doing work for rectangular boxes
Use the new gtk_css_dimension_value_is_zero() to check if we really need
to e.g. apply a border radius at all.
We compute css boxes a lot so this makes sense here, it especially shows
up during pick(), where we need the border box.
2020-01-26 18:21:07 +01:00
Timm Bäder
352c9ba42a dimensionvalue: Add gtk_css_{dimension,corner}_value_is_zero()
We can usually omit computations when the dimension value ends up being
zero anyway.
2020-01-26 18:21:07 +01:00
Timm Bäder
30b37dd7c5 widget: Restructure pick() a bit
Don't even invert transforms if we can do it easily ourselves. This also
fixes a small GtkTransform memory leak.
2020-01-26 18:21:07 +01:00
Timm Bäder
2e256986c3 renderbackground: Avoid unnecessary work in snapshot_background() 2020-01-26 18:21:07 +01:00
Timm Bäder
77e0d360ed Add pure and const annotations to various functions 2020-01-26 18:21:07 +01:00
Timm Bäder
942a93250a render: Remove gtk_render_background_get_clip 2020-01-26 18:21:07 +01:00
Timm Bäder
7ccd6597c3 Remove gtkutils{.c,private.h}
All but one functions are unused. Move the remaining one into
gtkmodules.c, its only caller.
2020-01-26 18:21:07 +01:00
Timm Bäder
355a417dba cssparser: make a few local variables const 2020-01-26 18:21:07 +01:00
Timm Bäder
36e3f4d902 cssprovider: Parse selectors without a GList
The maximum length of this list in Adwaita is 18, so use a generous
maximum length of 64 for the selector list of a ruleset.
2020-01-26 18:21:07 +01:00
Timm Bäder
69fe705d0d GtkCssImageUrl: Implement is_computed() 2020-01-26 18:21:07 +01:00
Timm Bäder
f62535affc gl renderer: Avoid some work when rendering border nodes 2020-01-26 18:21:07 +01:00
Timm Bäder
1a56a10fc1 cssimage: Add gtk_css_image_to_string()
In line with all the other _to_string() implementations
2020-01-26 18:21:07 +01:00
Timm Bäder
4287f0def4 window: Replace GtkStyleContext use to get surface transform
We have GtkCssBoxes for this these days.
2020-01-26 18:21:07 +01:00
Matthias Clasen
7bebc3e2b2 Revert "lookup stats"
This reverts commit 3d9e3390f1.
2020-01-25 23:49:33 -05:00
Matthias Clasen
b4e2df8fca Revert "css: Split style into groups"
This reverts commit 0df0de0b5d.
2020-01-25 23:49:17 -05:00
Matthias Clasen
0df0de0b5d css: Split style into groups 2020-01-25 23:47:02 -05:00
Matthias Clasen
53c22bf833 Adwaita: take out an unnecessary rule
The comment says setting caret-color to currentColor
shouldn't be necessary, and it is right.
2020-01-25 18:38:42 -05:00
Matthias Clasen
d8144ec497 Adwaita: drop the * 2020-01-25 18:20:40 -05:00
Matthias Clasen
3d9e3390f1 lookup stats 2020-01-25 18:20:26 -05:00
Matthias Clasen
03595f9567 Fix a scrollbar sizing issue
The recent Adwaita changes inadvertendly made scrollbars
resize on hover. Fix that, by reinstating some lost rules.
2020-01-25 15:05:14 -05:00
Matthias Clasen
64e026d0a9 Revert "Ensure icon themes are loaded with other themes"
This reverts commit 88d26b7549.

This change caused GtkShortcutWindow to not work anymore,
and we are fixing icon themes differently, anyway.
2020-01-25 14:32:01 -05:00
Matthias Clasen
0623b00512 Merge branch 'style-context-redux' into 'master'
Stop using GtkStyleContext internally

See merge request GNOME/gtk!1353
2020-01-25 19:29:20 +00:00
Matthias Clasen
ac902e697e popover: Stop using style context getters 2020-01-25 14:18:22 -05:00
Matthias Clasen
f1ff69963e drag icon: Stop using style context getters
Just go to the css node directly.
2020-01-25 14:18:22 -05:00
Matthias Clasen
731ae8f39e gskpango: Stop using style context getters
Just go to the css nodes directly.
2020-01-25 14:18:22 -05:00
Matthias Clasen
7da6fdc30e widget: Stop using style context internally 2020-01-25 11:05:27 -05:00
Matthias Clasen
a297129685 Add a profiler mark around renderer realization
This takes time that is worth calling out.
2020-01-25 01:28:24 -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
266 changed files with 11911 additions and 8759 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

@@ -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
@@ -4897,7 +4895,6 @@ gtk_border_free
<SUBSECTION>
gtk_render_arrow
gtk_render_background
gtk_render_background_get_clip
gtk_render_check
gtk_render_expander
gtk_render_focus

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
@@ -42,145 +46,6 @@
#include "filetransferportalprivate.h"
static GDBusProxy *file_transfer_proxy = NULL;
static gboolean done;
static guint timeout_id;
static void
got_proxy (GObject *source,
GAsyncResult *result,
gpointer data)
{
GError *error = NULL;
file_transfer_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
if (!file_transfer_proxy)
{
g_message ("failed to get file transfer portal proxy: %s", error->message);
g_error_free (error);
}
if (timeout_id)
{
g_source_remove (timeout_id);
timeout_id = 0;
}
done = TRUE;
g_main_context_wakeup (NULL);
}
static void
got_bus (GObject *source,
GAsyncResult *result,
gpointer data)
{
GDBusConnection **bus = data;
GError *error = NULL;
*bus = g_bus_get_finish (result, &error);
if (!*bus)
{
g_message ("failed to get session bus connection: %s", error->message);
g_error_free (error);
}
if (timeout_id)
{
g_source_remove (timeout_id);
timeout_id = 0;
}
done = TRUE;
g_main_context_wakeup (NULL);
}
static gboolean
give_up_on_proxy (gpointer data)
{
GCancellable *cancellable = data;
g_cancellable_cancel (cancellable);
timeout_id = 0;
done = TRUE;
g_main_context_wakeup (NULL);
return G_SOURCE_REMOVE;
}
static GDBusProxy *
ensure_file_transfer_portal (void)
{
if (file_transfer_proxy == NULL)
{
GCancellable *cancellable;
GDBusConnection *bus = NULL;
cancellable = g_cancellable_new ();
done = FALSE;
timeout_id = g_timeout_add (500, give_up_on_proxy, cancellable);
g_bus_get (G_BUS_TYPE_SESSION,
cancellable,
got_bus,
&bus);
while (!done)
g_main_context_iteration (NULL, TRUE);
if (bus)
{
done = FALSE;
timeout_id = g_timeout_add (500, give_up_on_proxy, cancellable);
g_dbus_proxy_new (bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
| G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.FileTransfer",
cancellable,
got_proxy,
NULL);
while (!done)
g_main_context_iteration (NULL, TRUE);
g_clear_object (&bus);
}
g_clear_object (&cancellable);
}
if (file_transfer_proxy)
{
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;
@@ -328,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");
@@ -354,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);
}
@@ -406,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");
@@ -423,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,
@@ -444,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

@@ -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

@@ -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

@@ -53,15 +53,15 @@ GDK_AVAILABLE_IN_ALL
void gdk_rgba_free (GdkRGBA *rgba);
GDK_AVAILABLE_IN_ALL
gboolean gdk_rgba_is_clear (const GdkRGBA *rgba);
gboolean gdk_rgba_is_clear (const GdkRGBA *rgba) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
gboolean gdk_rgba_is_opaque (const GdkRGBA *rgba);
gboolean gdk_rgba_is_opaque (const GdkRGBA *rgba) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
guint gdk_rgba_hash (gconstpointer p);
guint gdk_rgba_hash (gconstpointer p) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
gboolean gdk_rgba_equal (gconstpointer p1,
gconstpointer p2);
gconstpointer p2) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
gboolean gdk_rgba_parse (GdkRGBA *rgba,

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

@@ -51,9 +51,9 @@ GdkTexture * gdk_texture_new_from_file (GFile
GError **error);
GDK_AVAILABLE_IN_ALL
int gdk_texture_get_width (GdkTexture *texture);
int gdk_texture_get_width (GdkTexture *texture) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
int gdk_texture_get_height (GdkTexture *texture);
int gdk_texture_get_height (GdkTexture *texture) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
void gdk_texture_download (GdkTexture *texture,

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;

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

@@ -1749,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)
{

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

@@ -196,7 +196,7 @@ dump_node (GskRenderNode *node,
cairo_surface_destroy (surface);
}
static inline gboolean
static inline gboolean G_GNUC_PURE
node_is_invisible (const GskRenderNode *node)
{
return node->bounds.size.width == 0.0f ||
@@ -237,7 +237,7 @@ sort_border_sides (const GdkRGBA *colors,
}
}
static inline gboolean
static inline gboolean G_GNUC_PURE
color_matrix_modifies_alpha (GskRenderNode *node)
{
const graphene_matrix_t *matrix = gsk_color_matrix_node_peek_color_matrix (node);
@@ -261,7 +261,7 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
MAX (self->corner[2].height, self->corner[3].height)) * 2);
}
static inline gboolean
static inline gboolean G_GNUC_PURE
node_supports_transform (GskRenderNode *node)
{
/* Some nodes can't handle non-trivial transforms without being
@@ -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;
}
@@ -612,7 +611,7 @@ render_fallback_node (GskGLRenderer *self,
cairo_fill (cr);
cairo_restore (cr);
#if G_ENABLE_DEBUG
#ifdef G_ENABLE_DEBUG
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), FALLBACK))
{
cairo_move_to (cr, 0, 0);
@@ -745,25 +744,35 @@ 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 (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]))
{
OpShadow *op;
for (i = 0; i < 4; i ++)
widths[i] = og_widths[i];
ops_set_program (builder, &self->inset_shadow_program);
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = &colors[0];
op->outline = transform_rect (self, builder, rounded_outline);
op->spread = widths[0];
op->offset[0] = 0;
op->offset[1] = 0;
load_vertex_data (ops_draw (builder, NULL), node, builder);
return;
}
/* Top left */
if (widths[3] > 0)
@@ -810,10 +819,11 @@ render_border_node (GskGLRenderer *self,
else
sizes[3].h = 0;
for (i = 0; i < 4; i ++)
widths[i] *= scale;
{
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 GskQuadVertex side_data[4][6] = {
/* Top */
{
@@ -857,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);
@@ -1169,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;
@@ -1195,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);
@@ -1205,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.
@@ -1214,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,
@@ -1435,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);
@@ -1461,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);
@@ -1474,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);
}
@@ -1627,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);
@@ -1638,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,
@@ -1652,6 +1665,7 @@ render_outset_shadow_node (GskGLRenderer *self,
{
const float scale = ops_get_scale (builder);
const GskRoundedRect *outline = gsk_outset_shadow_node_peek_outline (node);
const GdkRGBA *color = gsk_outset_shadow_node_peek_color (node);
const float blur_radius = gsk_outset_shadow_node_get_blur_radius (node);
const float blur_extra = blur_radius * 3; /* 3 Because we use that in the shader as well */
const float spread = gsk_outset_shadow_node_get_spread (node);
@@ -1727,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, gsk_outset_shadow_node_peek_color (node));
ops_set_color (builder, &COLOR_WHITE);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { 0, }, { 0, 1 }, },
{ { 0, texture_height }, { 0, 0 }, },
@@ -1763,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);
@@ -2140,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);
@@ -2553,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");
@@ -2637,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 */
@@ -2746,6 +2773,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
GError **error)
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
gint64 before = g_get_monotonic_time ();
/* If we didn't get a GdkGLContext before realization, try creating
* one now, for our exclusive use.
@@ -2775,6 +2803,9 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
self->icon_cache = get_icon_cache_for_display (gdk_surface_get_display (surface), self->atlases);
gsk_gl_shadow_cache_init (&self->shadow_cache);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "gl renderer realize", NULL);
return TRUE;
}
@@ -3461,7 +3492,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

@@ -8,7 +8,7 @@ rect_equal (const graphene_rect_t *a,
return memcmp (a, b, sizeof (graphene_rect_t)) == 0;
}
static inline gboolean
static inline gboolean G_GNUC_PURE
rounded_rect_equal (const GskRoundedRect *r1,
const GskRoundedRect *r2)
{
@@ -31,7 +31,7 @@ rounded_rect_equal (const GskRoundedRect *r1,
return TRUE;
}
static inline gboolean
static inline gboolean G_GNUC_PURE
rounded_rect_corners_equal (const GskRoundedRect *r1,
const GskRoundedRect *r2)
{
@@ -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

@@ -25,12 +25,12 @@ key_equal (const void *x,
const CacheKey *a = x;
const CacheKey *b = y;
return graphene_size_equal (&a->outline.corner[0], &b->outline.corner[0]) &&
return a->blur_radius == b->blur_radius &&
graphene_size_equal (&a->outline.corner[0], &b->outline.corner[0]) &&
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) &&
a->blur_radius == b->blur_radius;
graphene_rect_equal (&a->outline.bounds, &b->outline.bounds);
}
void

View File

@@ -145,9 +145,9 @@ gsk_render_node_get_node_type (GskRenderNode *node)
return node->node_class->node_type;
}
static inline
G_GNUC_PURE static inline
GskRenderNodeType
_gsk_render_node_get_node_type (GskRenderNode *node)
_gsk_render_node_get_node_type (const GskRenderNode *node)
{
return node->node_class->node_type;
}
@@ -248,8 +248,8 @@ gsk_render_node_draw (GskRenderNode *node,
* Returns: %TRUE if @node1 and @node2 can be expected to be compared
**/
gboolean
gsk_render_node_can_diff (GskRenderNode *node1,
GskRenderNode *node2)
gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2)
{
if (node1 == node2)
return TRUE;
@@ -314,9 +314,6 @@ gsk_render_node_diff (GskRenderNode *node1,
return node1->node_class->diff (node1, node2, region);
}
#define GSK_RENDER_NODE_SERIALIZATION_VERSION 0
#define GSK_RENDER_NODE_SERIALIZATION_ID "GskRenderNode"
/**
* gsk_render_node_write_to_file:
* @node: a #GskRenderNode

View File

@@ -41,8 +41,8 @@ rectangle_init_from_graphene (cairo_rectangle_int_t *cairo,
}
static gboolean
gsk_render_node_can_diff_true (GskRenderNode *node1,
GskRenderNode *node2)
gsk_render_node_can_diff_true (const GskRenderNode *node1,
const GskRenderNode *node2)
{
return TRUE;
}
@@ -1707,8 +1707,8 @@ gsk_container_node_draw (GskRenderNode *node,
}
static gboolean
gsk_container_node_can_diff (GskRenderNode *node1,
GskRenderNode *node2)
gsk_container_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2)
{
return TRUE;
}
@@ -1726,7 +1726,7 @@ gsk_render_node_add_to_region (GskRenderNode *node,
static int
gsk_container_node_compare_func (gconstpointer elem1, gconstpointer elem2, gpointer data)
{
return gsk_render_node_can_diff ((GskRenderNode *) elem1, (GskRenderNode *) elem2) ? 0 : 1;
return gsk_render_node_can_diff ((const GskRenderNode *) elem1, (const GskRenderNode *) elem2) ? 0 : 1;
}
static void
@@ -1918,8 +1918,8 @@ gsk_transform_node_draw (GskRenderNode *node,
}
static gboolean
gsk_transform_node_can_diff (GskRenderNode *node1,
GskRenderNode *node2)
gsk_transform_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2)
{
GskTransformNode *self1 = (GskTransformNode *) node1;
GskTransformNode *self2 = (GskTransformNode *) node2;
@@ -2092,8 +2092,8 @@ gsk_debug_node_draw (GskRenderNode *node,
}
static gboolean
gsk_debug_node_can_diff (GskRenderNode *node1,
GskRenderNode *node2)
gsk_debug_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2)
{
GskDebugNode *self1 = (GskDebugNode *) node1;
GskDebugNode *self2 = (GskDebugNode *) node2;

View File

@@ -28,8 +28,8 @@ struct _GskRenderNodeClass
void (* finalize) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
cairo_t *cr);
gboolean (* can_diff) (GskRenderNode *node1,
GskRenderNode *node2);
gboolean (* can_diff) (const GskRenderNode *node1,
const GskRenderNode *node2);
void (* diff) (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
@@ -38,8 +38,8 @@ struct _GskRenderNodeClass
GskRenderNode * gsk_render_node_new (const GskRenderNodeClass *node_class,
gsize extra_size);
gboolean gsk_render_node_can_diff (GskRenderNode *node1,
GskRenderNode *node2);
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2) G_GNUC_PURE;
void gsk_render_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);

View File

@@ -98,16 +98,16 @@ GskRoundedRect * gsk_rounded_rect_shrink (GskRoundedRect
float left);
GDK_AVAILABLE_IN_ALL
gboolean gsk_rounded_rect_is_rectilinear (const GskRoundedRect *self);
gboolean gsk_rounded_rect_is_rectilinear (const GskRoundedRect *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
gboolean gsk_rounded_rect_contains_point (const GskRoundedRect *self,
const graphene_point_t *point);
const graphene_point_t *point) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
gboolean gsk_rounded_rect_contains_rect (const GskRoundedRect *self,
const graphene_rect_t *rect);
const graphene_rect_t *rect) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
gboolean gsk_rounded_rect_intersects_rect (const GskRoundedRect *self,
const graphene_rect_t *rect);
const graphene_rect_t *rect) G_GNUC_PURE;
G_END_DECLS

View File

@@ -15,7 +15,7 @@ void gsk_rounded_rect_to_float (const GskRounde
float rect[12]);
gboolean gsk_rounded_rect_equal (gconstpointer rect1,
gconstpointer rect2);
gconstpointer rect2) G_GNUC_PURE;
char * gsk_rounded_rect_to_string (const GskRoundedRect *self);

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

@@ -261,14 +261,14 @@ gtk_css_parser_get_end_location (GtkCssParser *self)
const GtkCssLocation *
gtk_css_parser_get_block_location (GtkCssParser *self)
{
GtkCssParserBlock *block;
const GtkCssParserBlock *block;
if (self->blocks->len == 0)
{
static const GtkCssLocation start_of_document = { 0, };
return &start_of_document;
}
block = &g_array_index (self->blocks, GtkCssParserBlock, self->blocks->len - 1);
return &block->start_location;
}
@@ -301,7 +301,7 @@ gtk_css_parser_peek_token (GtkCssParser *self)
if (self->blocks->len)
{
GtkCssParserBlock *block = &g_array_index (self->blocks, GtkCssParserBlock, self->blocks->len - 1);
const GtkCssParserBlock *block = &g_array_index (self->blocks, GtkCssParserBlock, self->blocks->len - 1);
if (gtk_css_token_is (&self->token, block->end_token) ||
gtk_css_token_is (&self->token, block->inherited_end_token) ||
gtk_css_token_is (&self->token, block->alternative_token))

View File

@@ -109,16 +109,16 @@ union _GtkCssToken {
void gtk_css_token_clear (GtkCssToken *token);
gboolean gtk_css_token_is_finite (const GtkCssToken *token);
gboolean gtk_css_token_is_finite (const GtkCssToken *token) G_GNUC_PURE;
gboolean gtk_css_token_is_preserved (const GtkCssToken *token,
GtkCssTokenType *out_closing);
GtkCssTokenType *out_closing) G_GNUC_PURE;
#define gtk_css_token_is(token, _type) ((token)->type == (_type))
gboolean gtk_css_token_is_ident (const GtkCssToken *token,
const char *ident);
const char *ident) G_GNUC_PURE;
gboolean gtk_css_token_is_function (const GtkCssToken *token,
const char *ident);
const char *ident) G_GNUC_PURE;
gboolean gtk_css_token_is_delim (const GtkCssToken *token,
gunichar delim);
gunichar delim) G_GNUC_PURE;
void gtk_css_token_print (const GtkCssToken *token,
GString *string);

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

@@ -23,9 +23,11 @@
#include "gsk/gskrendernodeprivate.h"
#include "gskpango.h"
#include "gtksnapshotprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtktextlayoutprivate.h"
#include "gtktextviewprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include <math.h>
@@ -307,7 +309,6 @@ static void
gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
PangoLayoutRun *run)
{
GtkStyleContext *context;
GskPangoRenderer *crenderer = GSK_PANGO_RENDERER (renderer);
GdkRGBA *bg_rgba = NULL;
GdkRGBA *fg_rgba = NULL;
@@ -320,8 +321,6 @@ gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
if (appearance == NULL)
return;
context = gtk_widget_get_style_context (crenderer->widget);
if (appearance->draw_bg && crenderer->state == GSK_PANGO_RENDERER_NORMAL)
bg_rgba = appearance->bg_rgba;
else
@@ -332,22 +331,21 @@ gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
if (crenderer->state == GSK_PANGO_RENDERER_SELECTED &&
GTK_IS_TEXT_VIEW (crenderer->widget))
{
GtkCssNode *selection_node;
GtkCssNode *node;
GtkCssValue *value;
selection_node = gtk_text_view_get_selection_node ((GtkTextView *)crenderer->widget);
gtk_style_context_save_to_node (context, selection_node);
gtk_style_context_get (context,
"color", &fg_rgba,
NULL);
gtk_style_context_restore (context);
node = gtk_text_view_get_selection_node ((GtkTextView *)crenderer->widget);
value = gtk_css_style_get_value (gtk_css_node_get_style (node), GTK_CSS_PROPERTY_COLOR);
fg_rgba = (GdkRGBA *)gtk_css_color_value_get_rgba (value);
}
else if (crenderer->state == GSK_PANGO_RENDERER_CURSOR && gtk_widget_has_focus (crenderer->widget))
{
gtk_style_context_get (context,
"background-color", &fg_rgba,
NULL);
GtkCssNode *node;
GtkCssValue *value;
node = gtk_widget_get_css_node (crenderer->widget);
value = gtk_css_style_get_value (gtk_css_node_get_style (node), GTK_CSS_PROPERTY_BACKGROUND_COLOR);
fg_rgba = (GdkRGBA *)gtk_css_color_value_get_rgba (value);
}
else
fg_rgba = appearance->fg_rgba;

View File

@@ -297,17 +297,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

@@ -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");
@@ -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,6 +79,15 @@ gtk_css_animated_style_is_static (GtkCssStyle *style)
return TRUE;
}
static GtkCssStaticStyle *
gtk_css_animated_style_get_static_style (GtkCssStyle *style)
{
/* This is called a lot, so we avoid a dynamic type check here */
GtkCssAnimatedStyle *animated = (GtkCssAnimatedStyle *) style;
return (GtkCssStaticStyle *)animated->style;
}
static void
gtk_css_animated_style_dispose (GObject *object)
{
@@ -123,6 +132,7 @@ gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass)
style_class->get_value = gtk_css_animated_style_get_value;
style_class->get_section = gtk_css_animated_style_get_section;
style_class->is_static = gtk_css_animated_style_is_static;
style_class->get_static_style = gtk_css_animated_style_get_static_style;
}
static void

View File

@@ -299,7 +299,7 @@ gtk_css_value_array_transition (GtkCssValue *start,
}
static gboolean
gtk_css_value_array_is_dynamic (GtkCssValue *value)
gtk_css_value_array_is_dynamic (const GtkCssValue *value)
{
guint i;
@@ -369,6 +369,7 @@ gtk_css_value_array_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_ARRAY = {
"GtkCssArrayValue",
gtk_css_value_array_free,
gtk_css_value_array_compute,
gtk_css_value_array_equal,
@@ -391,14 +392,28 @@ _gtk_css_array_value_new_from_array (GtkCssValue **values,
guint n_values)
{
GtkCssValue *result;
guint i;
g_return_val_if_fail (values != NULL, NULL);
g_return_val_if_fail (n_values > 0, NULL);
if (n_values == 1)
return values[0];
result = _gtk_css_value_alloc (&GTK_CSS_VALUE_ARRAY, sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (n_values - 1));
result->n_values = n_values;
memcpy (&result->values[0], values, sizeof (GtkCssValue *) * n_values);
result->is_computed = TRUE;
for (i = 0; i < n_values; i ++)
{
if (!gtk_css_value_is_computed (values[i]))
{
result->is_computed = FALSE;
break;
}
}
return result;
}
@@ -407,32 +422,38 @@ _gtk_css_array_value_parse (GtkCssParser *parser,
GtkCssValue *(* parse_func) (GtkCssParser *parser))
{
GtkCssValue *value, *result;
GPtrArray *values;
values = g_ptr_array_new ();
GtkCssValue *values[128];
guint n_values = 0;
guint i;
do {
value = parse_func (parser);
if (value == NULL)
{
g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
g_ptr_array_free (values, TRUE);
for (i = 0; i < n_values; i ++)
_gtk_css_value_unref (values[i]);
return NULL;
}
g_ptr_array_add (values, value);
values[n_values] = value;
n_values ++;
if (G_UNLIKELY (n_values > G_N_ELEMENTS (values)))
g_error ("Only %d elements in a css array are allowed", (int)G_N_ELEMENTS (values));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
result = _gtk_css_array_value_new_from_array ((GtkCssValue **) values->pdata, values->len);
g_ptr_array_free (values, TRUE);
result = _gtk_css_array_value_new_from_array (values, n_values);
return result;
}
GtkCssValue *
_gtk_css_array_value_get_nth (const GtkCssValue *value,
guint i)
_gtk_css_array_value_get_nth (GtkCssValue *value,
guint i)
{
if (value->class != &GTK_CSS_VALUE_ARRAY)
return value;
g_return_val_if_fail (value != NULL, NULL);
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_ARRAY, NULL);
g_return_val_if_fail (value->n_values > 0, NULL);
@@ -443,6 +464,9 @@ _gtk_css_array_value_get_nth (const GtkCssValue *value,
guint
_gtk_css_array_value_get_n_values (const GtkCssValue *value)
{
if (value->class != &GTK_CSS_VALUE_ARRAY)
return 1;
g_return_val_if_fail (value != NULL, 0);
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_ARRAY, 0);

View File

@@ -32,9 +32,9 @@ GtkCssValue * _gtk_css_array_value_new_from_array (GtkCssValue **
GtkCssValue * _gtk_css_array_value_parse (GtkCssParser *parser,
GtkCssValue * (* parse_func) (GtkCssParser *));
GtkCssValue * _gtk_css_array_value_get_nth (const GtkCssValue *value,
GtkCssValue * _gtk_css_array_value_get_nth (GtkCssValue *value,
guint i);
guint _gtk_css_array_value_get_n_values (const GtkCssValue *value);
guint _gtk_css_array_value_get_n_values (const GtkCssValue *value) G_GNUC_PURE;
G_END_DECLS

View File

@@ -153,6 +153,7 @@ gtk_css_value_bg_size_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_BG_SIZE = {
"GtkCssBgSizeValue",
gtk_css_value_bg_size_free,
gtk_css_value_bg_size_compute,
gtk_css_value_bg_size_equal,
@@ -162,9 +163,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_BG_SIZE = {
gtk_css_value_bg_size_print
};
static GtkCssValue auto_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, FALSE, FALSE, NULL, NULL };
static GtkCssValue cover_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, NULL, NULL };
static GtkCssValue contain_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, FALSE, TRUE, NULL, NULL };
static GtkCssValue auto_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, FALSE, NULL, NULL };
static GtkCssValue cover_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, TRUE, FALSE, NULL, NULL };
static GtkCssValue contain_singleton = { &GTK_CSS_VALUE_BG_SIZE, 1, TRUE, FALSE, TRUE, NULL, NULL };
GtkCssValue *
_gtk_css_bg_size_value_new (GtkCssValue *x,
@@ -178,6 +179,8 @@ _gtk_css_bg_size_value_new (GtkCssValue *x,
result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_BG_SIZE);
result->x = x;
result->y = y;
result->is_computed = (!x || gtk_css_value_is_computed (x)) &&
(!y || gtk_css_value_is_computed (y));
return result;
}

View File

@@ -140,6 +140,7 @@ gtk_css_value_border_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_BORDER = {
"GtkCssBorderValue",
gtk_css_value_border_free,
gtk_css_value_border_compute,
gtk_css_value_border_equal,
@@ -162,6 +163,10 @@ _gtk_css_border_value_new (GtkCssValue *top,
result->values[GTK_CSS_RIGHT] = right;
result->values[GTK_CSS_BOTTOM] = bottom;
result->values[GTK_CSS_LEFT] = left;
result->is_computed = (top && gtk_css_value_is_computed (top)) &&
(right && gtk_css_value_is_computed (right)) &&
(bottom && gtk_css_value_is_computed (bottom)) &&
(left && gtk_css_value_is_computed (left));
return result;
}
@@ -212,6 +217,14 @@ _gtk_css_border_value_parse (GtkCssParser *parser,
result->values[i] = _gtk_css_value_ref (result->values[(i - 1) >> 1]);
}
result->is_computed = TRUE;
for (; i < 4; i++)
if (result->values[i] && !gtk_css_value_is_computed (result->values[i]))
{
result->is_computed = FALSE;
break;
}
return result;
}

View File

@@ -23,6 +23,7 @@
#include "gtkcsscornervalueprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssdimensionvalueprivate.h"
#include "gtkwidgetprivate.h"
/* This file is included from gtkcssboxesprivate.h */
@@ -79,15 +80,50 @@ gtk_css_boxes_rect_grow (GskRoundedRect *dest,
int bottom_property,
int left_property)
{
double top = _gtk_css_number_value_get (gtk_css_style_get_value (style, top_property), 100);
double right = _gtk_css_number_value_get (gtk_css_style_get_value (style, right_property), 100);
double bottom = _gtk_css_number_value_get (gtk_css_style_get_value (style, bottom_property), 100);
double left = _gtk_css_number_value_get (gtk_css_style_get_value (style, left_property), 100);
GtkCssValue *top = gtk_css_style_get_value (style, top_property);
GtkCssValue *right = gtk_css_style_get_value (style, right_property);
GtkCssValue *bottom = gtk_css_style_get_value (style, bottom_property);
GtkCssValue *left = gtk_css_style_get_value (style, left_property);
dest->bounds.origin.x = src->bounds.origin.x - left;
dest->bounds.origin.y = src->bounds.origin.y - top;
dest->bounds.size.width = src->bounds.size.width + left + right;
dest->bounds.size.height = src->bounds.size.height + top + bottom;
if (gtk_css_dimension_value_is_zero (left))
{
dest->bounds.origin.x = src->bounds.origin.x;
if (gtk_css_dimension_value_is_zero (right))
dest->bounds.size.width = src->bounds.size.width;
else
dest->bounds.size.width = src->bounds.size.width + _gtk_css_number_value_get (right, 100);
}
else
{
const double left_value = _gtk_css_number_value_get (left, 100);
dest->bounds.origin.x = src->bounds.origin.x - left_value;
if (gtk_css_dimension_value_is_zero (right))
dest->bounds.size.width = src->bounds.size.width + left_value;
else
dest->bounds.size.width = src->bounds.size.width + left_value + _gtk_css_number_value_get (right, 100);
}
if (gtk_css_dimension_value_is_zero (top))
{
dest->bounds.origin.y = src->bounds.origin.y;
if (gtk_css_dimension_value_is_zero (bottom))
dest->bounds.size.height = src->bounds.size.height;
else
dest->bounds.size.height = src->bounds.size.height + _gtk_css_number_value_get (bottom, 100);
}
else
{
const double top_value = _gtk_css_number_value_get (top, 100);
dest->bounds.origin.y = src->bounds.origin.y - top_value;
if (gtk_css_dimension_value_is_zero (bottom))
dest->bounds.size.height = src->bounds.size.height + top_value;
else
dest->bounds.size.height = src->bounds.size.height + top_value + _gtk_css_number_value_get (bottom, 100);
}
}
static inline void
@@ -323,19 +359,38 @@ gtk_css_boxes_apply_border_radius (GskRoundedRect *box,
const GtkCssValue *bottom_right,
const GtkCssValue *bottom_left)
{
box->corner[GSK_CORNER_TOP_LEFT].width = _gtk_css_corner_value_get_x (top_left, box->bounds.size.width);
box->corner[GSK_CORNER_TOP_LEFT].height = _gtk_css_corner_value_get_y (top_left, box->bounds.size.height);
gboolean has_border_radius = FALSE;
box->corner[GSK_CORNER_TOP_RIGHT].width = _gtk_css_corner_value_get_x (top_right, box->bounds.size.width);
box->corner[GSK_CORNER_TOP_RIGHT].height = _gtk_css_corner_value_get_y (top_right, box->bounds.size.height);
if (!gtk_css_corner_value_is_zero (top_left))
{
box->corner[GSK_CORNER_TOP_LEFT].width = _gtk_css_corner_value_get_x (top_left, box->bounds.size.width);
box->corner[GSK_CORNER_TOP_LEFT].height = _gtk_css_corner_value_get_y (top_left, box->bounds.size.height);
has_border_radius = TRUE;
}
box->corner[GSK_CORNER_BOTTOM_RIGHT].width = _gtk_css_corner_value_get_x (bottom_right, box->bounds.size.width);
box->corner[GSK_CORNER_BOTTOM_RIGHT].height = _gtk_css_corner_value_get_y (bottom_right, box->bounds.size.height);
if (!gtk_css_corner_value_is_zero (top_right))
{
box->corner[GSK_CORNER_TOP_RIGHT].width = _gtk_css_corner_value_get_x (top_right, box->bounds.size.width);
box->corner[GSK_CORNER_TOP_RIGHT].height = _gtk_css_corner_value_get_y (top_right, box->bounds.size.height);
has_border_radius = TRUE;
}
box->corner[GSK_CORNER_BOTTOM_LEFT].width = _gtk_css_corner_value_get_x (bottom_left, box->bounds.size.width);
box->corner[GSK_CORNER_BOTTOM_LEFT].height = _gtk_css_corner_value_get_y (bottom_left, box->bounds.size.height);
if (!gtk_css_corner_value_is_zero (bottom_right))
{
box->corner[GSK_CORNER_BOTTOM_RIGHT].width = _gtk_css_corner_value_get_x (bottom_right, box->bounds.size.width);
box->corner[GSK_CORNER_BOTTOM_RIGHT].height = _gtk_css_corner_value_get_y (bottom_right, box->bounds.size.height);
has_border_radius = TRUE;
}
gtk_css_boxes_clamp_border_radius (box);
if (!gtk_css_corner_value_is_zero (bottom_left))
{
box->corner[GSK_CORNER_BOTTOM_LEFT].width = _gtk_css_corner_value_get_x (bottom_left, box->bounds.size.width);
box->corner[GSK_CORNER_BOTTOM_LEFT].height = _gtk_css_corner_value_get_y (bottom_left, box->bounds.size.height);
has_border_radius = TRUE;
}
if (has_border_radius)
gtk_css_boxes_clamp_border_radius (box);
}
/* NB: width and height must be >= 0 */

View File

@@ -211,8 +211,8 @@ gtk_css_value_calc_has_percent (const GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_calc_multiply (const GtkCssValue *value,
double factor)
gtk_css_value_calc_multiply (GtkCssValue *value,
double factor)
{
GtkCssValue *result;
gsize i;
@@ -245,6 +245,7 @@ gtk_css_value_calc_get_calc_term_order (const GtkCssValue *value)
static const GtkCssNumberValueClass GTK_CSS_VALUE_CALC = {
{
"GtkCssCalcValue",
gtk_css_value_calc_free,
gtk_css_value_calc_compute,
gtk_css_value_calc_equal,

View File

@@ -19,7 +19,6 @@
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkhslaprivate.h"
#include "gtkprivate.h"
@@ -45,6 +44,7 @@ struct _GtkCssValue
union
{
gchar *name;
GdkRGBA rgba;
struct
{
@@ -104,7 +104,7 @@ gtk_css_value_color_get_fallback (guint property_id,
case GTK_CSS_PROPERTY_TEXT_SHADOW:
case GTK_CSS_PROPERTY_ICON_SHADOW:
case GTK_CSS_PROPERTY_BOX_SHADOW:
return _gtk_css_rgba_value_new_transparent ();
return gtk_css_color_value_new_transparent ();
case GTK_CSS_PROPERTY_COLOR:
case GTK_CSS_PROPERTY_BACKGROUND_COLOR:
case GTK_CSS_PROPERTY_BORDER_TOP_COLOR:
@@ -125,7 +125,7 @@ gtk_css_value_color_get_fallback (guint property_id,
if (property_id < GTK_CSS_PROPERTY_N_PROPERTIES)
g_warning ("No fallback color defined for property '%s'",
_gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (property_id))));
return _gtk_css_rgba_value_new_transparent ();
return gtk_css_color_value_new_transparent ();
}
}
@@ -136,7 +136,7 @@ gtk_css_value_color_compute (GtkCssValue *value,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GtkCssValue *resolved, *current;
GtkCssValue *resolved;
/* The computed value of the currentColor keyword is the computed
* value of the color property. If the currentColor keyword is
@@ -144,20 +144,31 @@ gtk_css_value_color_compute (GtkCssValue *value,
*/
if (property_id == GTK_CSS_PROPERTY_COLOR)
{
GtkCssValue *current;
if (parent_style)
current = gtk_css_style_get_value (parent_style, GTK_CSS_PROPERTY_COLOR);
else
current = NULL;
resolved = _gtk_css_color_value_resolve (value,
provider,
current,
NULL);
}
else if (value->type == COLOR_TYPE_LITERAL)
{
resolved = _gtk_css_value_ref (value);
}
else
{
current = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_COLOR);
GtkCssValue *current = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_COLOR);
resolved = _gtk_css_color_value_resolve (value,
provider,
current,
NULL);
}
resolved = _gtk_css_color_value_resolve (value,
provider,
current,
NULL);
if (resolved == NULL)
return gtk_css_value_color_get_fallback (property_id, provider, style, parent_style);
@@ -175,7 +186,7 @@ gtk_css_value_color_equal (const GtkCssValue *value1,
switch (value1->type)
{
case COLOR_TYPE_LITERAL:
return _gtk_css_value_equal (value1->last_value, value2->last_value);
return gdk_rgba_equal (&value1->sym_col.rgba, &value2->sym_col.rgba);
case COLOR_TYPE_NAME:
return g_str_equal (value1->sym_col.name, value2->sym_col.name);
case COLOR_TYPE_SHADE:
@@ -216,7 +227,11 @@ gtk_css_value_color_print (const GtkCssValue *value,
switch (value->type)
{
case COLOR_TYPE_LITERAL:
_gtk_css_value_print (value->last_value, string);
{
char *s = gdk_rgba_to_string (&value->sym_col.rgba);
g_string_append (string, s);
g_free (s);
}
break;
case COLOR_TYPE_NAME:
g_string_append (string, "@");
@@ -269,6 +284,7 @@ gtk_css_value_color_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_COLOR = {
"GtkCssColorValue",
gtk_css_value_color_free,
gtk_css_value_color_compute,
gtk_css_value_color_equal,
@@ -278,6 +294,57 @@ static const GtkCssValueClass GTK_CSS_VALUE_COLOR = {
gtk_css_value_color_print
};
static void
apply_alpha (const GdkRGBA *in,
GdkRGBA *out,
double factor)
{
*out = *in;
out->alpha = CLAMP (in->alpha * factor, 0, 1);
}
static void
apply_shade (const GdkRGBA *in,
GdkRGBA *out,
double factor)
{
GtkHSLA hsla;
_gtk_hsla_init_from_rgba (&hsla, in);
_gtk_hsla_shade (&hsla, &hsla, factor);
_gdk_rgba_init_from_hsla (out, &hsla);
}
static inline double
transition (double start,
double end,
double progress)
{
return start + (end - start) * progress;
}
static void
apply_mix (const GdkRGBA *in1,
const GdkRGBA *in2,
GdkRGBA *out,
double factor)
{
out->alpha = CLAMP (transition (in1->alpha, in2->alpha, factor), 0, 1);
if (out->alpha <= 0.0)
{
out->red = out->green = out->blue = 0.0;
}
else
{
out->red = CLAMP (transition (in1->red * in1->alpha, in2->red * in2->alpha, factor), 0, 1) / out->alpha;
out->green = CLAMP (transition (in1->green * in1->alpha, in2->green * in2->alpha, factor), 0, 1) / out->alpha;
out->blue = CLAMP (transition (in1->blue * in1->alpha, in2->blue * in2->alpha, factor), 0, 1) / out->alpha;
}
}
GtkCssValue *
_gtk_css_color_value_resolve (GtkCssValue *color,
GtkStyleProvider *provider,
@@ -291,7 +358,7 @@ _gtk_css_color_value_resolve (GtkCssValue *color,
switch (color->type)
{
case COLOR_TYPE_LITERAL:
return _gtk_css_value_ref (color->last_value);
return _gtk_css_value_ref (color);
case COLOR_TYPE_NAME:
{
GtkCssValue *named;
@@ -314,66 +381,61 @@ _gtk_css_color_value_resolve (GtkCssValue *color,
break;
case COLOR_TYPE_SHADE:
{
GtkCssValue *val;
GtkHSLA hsla;
GdkRGBA shade;
const GdkRGBA *c;
GtkCssValue *val;
GdkRGBA shade;
val = _gtk_css_color_value_resolve (color->sym_col.shade.color, provider, current, cycle_list);
if (val == NULL)
return NULL;
val = _gtk_css_color_value_resolve (color->sym_col.shade.color, provider, current, cycle_list);
if (val == NULL)
return NULL;
c = gtk_css_color_value_get_rgba (val);
_gtk_hsla_init_from_rgba (&hsla, _gtk_css_rgba_value_get_rgba (val));
_gtk_hsla_shade (&hsla, &hsla, color->sym_col.shade.factor);
apply_shade (c, &shade, color->sym_col.shade.factor);
_gdk_rgba_init_from_hsla (&shade, &hsla);
_gtk_css_value_unref (val);
value = _gtk_css_rgba_value_new_from_rgba (&shade);
value = _gtk_css_color_value_new_literal (&shade);
_gtk_css_value_unref (val);
}
break;
case COLOR_TYPE_ALPHA:
{
GtkCssValue *val;
GdkRGBA alpha;
const GdkRGBA *c;
GtkCssValue *val;
GdkRGBA alpha;
val = _gtk_css_color_value_resolve (color->sym_col.alpha.color, provider, current, cycle_list);
if (val == NULL)
return NULL;
val = _gtk_css_color_value_resolve (color->sym_col.alpha.color, provider, current, cycle_list);
if (val == NULL)
return NULL;
c = gtk_css_color_value_get_rgba (val);
alpha = *_gtk_css_rgba_value_get_rgba (val);
alpha.alpha = CLAMP (alpha.alpha * color->sym_col.alpha.factor, 0, 1);
apply_alpha (c, &alpha, color->sym_col.alpha.factor);
_gtk_css_value_unref (val);
value = _gtk_css_rgba_value_new_from_rgba (&alpha);
value = _gtk_css_color_value_new_literal (&alpha);
_gtk_css_value_unref (val);
}
break;
case COLOR_TYPE_MIX:
{
GtkCssValue *val;
GdkRGBA color1, color2, res;
const GdkRGBA *color1, *color2;
GtkCssValue *val1, *val2;
GdkRGBA res;
val = _gtk_css_color_value_resolve (color->sym_col.mix.color1, provider, current, cycle_list);
if (val == NULL)
return NULL;
color1 = *_gtk_css_rgba_value_get_rgba (val);
_gtk_css_value_unref (val);
val1 = _gtk_css_color_value_resolve (color->sym_col.mix.color1, provider, current, cycle_list);
if (val1 == NULL)
return NULL;
color1 = gtk_css_color_value_get_rgba (val1);
val = _gtk_css_color_value_resolve (color->sym_col.mix.color2, provider, current, cycle_list);
if (val == NULL)
return NULL;
color2 = *_gtk_css_rgba_value_get_rgba (val);
_gtk_css_value_unref (val);
val2 = _gtk_css_color_value_resolve (color->sym_col.mix.color2, provider, current, cycle_list);
if (val2 == NULL)
return NULL;
color2 = gtk_css_color_value_get_rgba (val2);
res.red = CLAMP (color1.red + ((color2.red - color1.red) * color->sym_col.mix.factor), 0, 1);
res.green = CLAMP (color1.green + ((color2.green - color1.green) * color->sym_col.mix.factor), 0, 1);
res.blue = CLAMP (color1.blue + ((color2.blue - color1.blue) * color->sym_col.mix.factor), 0, 1);
res.alpha = CLAMP (color1.alpha + ((color2.alpha - color1.alpha) * color->sym_col.mix.factor), 0, 1);
apply_mix (color1, color2, &res, color->sym_col.mix.factor);
value =_gtk_css_rgba_value_new_from_rgba (&res);
value = _gtk_css_color_value_new_literal (&res);
_gtk_css_value_unref (val1);
_gtk_css_value_unref (val2);
}
break;
@@ -420,6 +482,24 @@ _gtk_css_color_value_resolve (GtkCssValue *color,
return value;
}
static GtkCssValue transparent_black_singleton = { &GTK_CSS_VALUE_COLOR, 1, TRUE, COLOR_TYPE_LITERAL, NULL,
.sym_col.rgba = {0, 0, 0, 0} };
static GtkCssValue white_singleton = { &GTK_CSS_VALUE_COLOR, 1, TRUE, COLOR_TYPE_LITERAL, NULL,
.sym_col.rgba = {1, 1, 1, 1} };
GtkCssValue *
gtk_css_color_value_new_transparent (void)
{
return _gtk_css_value_ref (&transparent_black_singleton);
}
GtkCssValue *
gtk_css_color_value_new_white (void)
{
return _gtk_css_value_ref (&white_singleton);
}
GtkCssValue *
_gtk_css_color_value_new_literal (const GdkRGBA *color)
{
@@ -427,9 +507,16 @@ _gtk_css_color_value_new_literal (const GdkRGBA *color)
g_return_val_if_fail (color != NULL, NULL);
if (gdk_rgba_equal (color, &white_singleton.sym_col.rgba))
return _gtk_css_value_ref (&white_singleton);
if (gdk_rgba_equal (color, &transparent_black_singleton.sym_col.rgba))
return _gtk_css_value_ref (&transparent_black_singleton);
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
value->type = COLOR_TYPE_LITERAL;
value->last_value = _gtk_css_rgba_value_new_from_rgba (color);
value->is_computed = TRUE;
value->sym_col.rgba = *color;
return value;
}
@@ -456,6 +543,15 @@ _gtk_css_color_value_new_shade (GtkCssValue *color,
gtk_internal_return_val_if_fail (color->class == &GTK_CSS_VALUE_COLOR, NULL);
if (color->type == COLOR_TYPE_LITERAL)
{
GdkRGBA c;
apply_shade (&color->sym_col.rgba, &c, factor);
return _gtk_css_color_value_new_literal (&c);
}
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
value->type = COLOR_TYPE_SHADE;
value->sym_col.shade.color = _gtk_css_value_ref (color);
@@ -472,6 +568,15 @@ _gtk_css_color_value_new_alpha (GtkCssValue *color,
gtk_internal_return_val_if_fail (color->class == &GTK_CSS_VALUE_COLOR, NULL);
if (color->type == COLOR_TYPE_LITERAL)
{
GdkRGBA c;
apply_alpha (&color->sym_col.rgba, &c, factor);
return _gtk_css_color_value_new_literal (&c);
}
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
value->type = COLOR_TYPE_ALPHA;
value->sym_col.alpha.color = _gtk_css_value_ref (color);
@@ -490,6 +595,17 @@ _gtk_css_color_value_new_mix (GtkCssValue *color1,
gtk_internal_return_val_if_fail (color1->class == &GTK_CSS_VALUE_COLOR, NULL);
gtk_internal_return_val_if_fail (color2->class == &GTK_CSS_VALUE_COLOR, NULL);
if (color1->type == COLOR_TYPE_LITERAL &&
color2->type == COLOR_TYPE_LITERAL)
{
GdkRGBA result;
apply_mix (&color1->sym_col.rgba, &color2->sym_col.rgba, &result, factor);
return _gtk_css_color_value_new_literal (&result);
}
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
value->type = COLOR_TYPE_MIX;
value->sym_col.mix.color1 = _gtk_css_value_ref (color1);
@@ -502,7 +618,7 @@ _gtk_css_color_value_new_mix (GtkCssValue *color1,
GtkCssValue *
_gtk_css_color_value_new_current_color (void)
{
static GtkCssValue current_color = { &GTK_CSS_VALUE_COLOR, 1, COLOR_TYPE_CURRENT_COLOR, NULL, };
static GtkCssValue current_color = { &GTK_CSS_VALUE_COLOR, 1, FALSE, COLOR_TYPE_CURRENT_COLOR, NULL, };
return _gtk_css_value_ref (&current_color);
}
@@ -665,3 +781,11 @@ _gtk_css_color_value_parse (GtkCssParser *parser)
return NULL;
}
const GdkRGBA *
gtk_css_color_value_get_rgba (const GtkCssValue *color)
{
g_assert (color->class == &GTK_CSS_VALUE_COLOR);
g_assert (color->type == COLOR_TYPE_LITERAL);
return &color->sym_col.rgba;
}

View File

@@ -24,16 +24,18 @@
G_BEGIN_DECLS
GtkCssValue * _gtk_css_color_value_new_literal (const GdkRGBA *color);
GtkCssValue * _gtk_css_color_value_new_name (const gchar *name);
GtkCssValue * gtk_css_color_value_new_transparent (void) G_GNUC_PURE;
GtkCssValue * gtk_css_color_value_new_white (void) G_GNUC_PURE;
GtkCssValue * _gtk_css_color_value_new_literal (const GdkRGBA *color) G_GNUC_PURE;
GtkCssValue * _gtk_css_color_value_new_name (const gchar *name) G_GNUC_PURE;
GtkCssValue * _gtk_css_color_value_new_shade (GtkCssValue *color,
gdouble factor);
gdouble factor) G_GNUC_PURE;
GtkCssValue * _gtk_css_color_value_new_alpha (GtkCssValue *color,
gdouble factor);
gdouble factor) G_GNUC_PURE;
GtkCssValue * _gtk_css_color_value_new_mix (GtkCssValue *color1,
GtkCssValue *color2,
gdouble factor);
GtkCssValue * _gtk_css_color_value_new_current_color (void);
gdouble factor) G_GNUC_PURE;
GtkCssValue * _gtk_css_color_value_new_current_color (void) G_GNUC_PURE;
gboolean gtk_css_color_value_can_parse (GtkCssParser *parser);
GtkCssValue * _gtk_css_color_value_parse (GtkCssParser *parser);
@@ -42,6 +44,7 @@ GtkCssValue * _gtk_css_color_value_resolve (GtkCssValue *color
GtkStyleProvider *provider,
GtkCssValue *current,
GSList *cycle_list);
const GdkRGBA * gtk_css_color_value_get_rgba (const GtkCssValue *color) G_GNUC_CONST;
G_END_DECLS

View File

@@ -18,8 +18,8 @@
#include "config.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssdimensionvalueprivate.h"
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
@@ -99,6 +99,7 @@ gtk_css_value_corner_print (const GtkCssValue *corner,
}
static const GtkCssValueClass GTK_CSS_VALUE_CORNER = {
"GtkCssCornerValue",
gtk_css_value_corner_free,
gtk_css_value_corner_compute,
gtk_css_value_corner_equal,
@@ -114,6 +115,12 @@ _gtk_css_corner_value_new (GtkCssValue *x,
{
GtkCssValue *result;
if (_gtk_css_value_equal (x, y))
{
_gtk_css_value_unref (y);
return x;
}
result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_CORNER);
result->x = x;
result->y = y;
@@ -155,6 +162,9 @@ double
_gtk_css_corner_value_get_x (const GtkCssValue *corner,
double one_hundred_percent)
{
if (corner->class != &GTK_CSS_VALUE_CORNER)
return _gtk_css_number_value_get (corner, one_hundred_percent);
g_return_val_if_fail (corner != NULL, 0.0);
g_return_val_if_fail (corner->class == &GTK_CSS_VALUE_CORNER, 0.0);
@@ -165,9 +175,21 @@ double
_gtk_css_corner_value_get_y (const GtkCssValue *corner,
double one_hundred_percent)
{
if (corner->class != &GTK_CSS_VALUE_CORNER)
return _gtk_css_number_value_get (corner, one_hundred_percent);
g_return_val_if_fail (corner != NULL, 0.0);
g_return_val_if_fail (corner->class == &GTK_CSS_VALUE_CORNER, 0.0);
return _gtk_css_number_value_get (corner->y, one_hundred_percent);
}
gboolean
gtk_css_corner_value_is_zero (const GtkCssValue *corner)
{
if (corner->class != &GTK_CSS_VALUE_CORNER)
return gtk_css_dimension_value_is_zero (corner);
return gtk_css_dimension_value_is_zero (corner->x) &&
gtk_css_dimension_value_is_zero (corner->y);
}

View File

@@ -30,9 +30,10 @@ GtkCssValue * _gtk_css_corner_value_new (GtkCssValue *x,
GtkCssValue * _gtk_css_corner_value_parse (GtkCssParser *parser);
double _gtk_css_corner_value_get_x (const GtkCssValue *corner,
double one_hundred_percent);
double one_hundred_percent) G_GNUC_PURE;
double _gtk_css_corner_value_get_y (const GtkCssValue *corner,
double one_hundred_percent);
double one_hundred_percent) G_GNUC_PURE;
gboolean gtk_css_corner_value_is_zero (const GtkCssValue *corner) G_GNUC_PURE;
G_END_DECLS

View File

@@ -66,40 +66,6 @@ gtk_css_value_dimension_compute (GtkCssValue *number,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GtkBorderStyle border_style;
/* special case according to http://dev.w3.org/csswg/css-backgrounds/#the-border-width */
switch (property_id)
{
case GTK_CSS_PROPERTY_BORDER_TOP_WIDTH:
border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_STYLE));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
break;
case GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH:
border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
break;
case GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH:
border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
break;
case GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH:
border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_STYLE));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
break;
case GTK_CSS_PROPERTY_OUTLINE_WIDTH:
border_style = _gtk_css_border_style_value_get(gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE));
if (border_style == GTK_BORDER_STYLE_NONE || border_style == GTK_BORDER_STYLE_HIDDEN)
return gtk_css_dimension_value_new (0, GTK_CSS_NUMBER);
break;
default:
break;
}
switch (number->unit)
{
default:
@@ -228,8 +194,8 @@ gtk_css_value_dimension_has_percent (const GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_dimension_multiply (const GtkCssValue *value,
double factor)
gtk_css_value_dimension_multiply (GtkCssValue *value,
double factor)
{
return gtk_css_dimension_value_new (value->value * factor, value->unit);
}
@@ -277,12 +243,25 @@ gtk_css_value_dimension_get_calc_term_order (const GtkCssValue *value)
return 1000 + order_per_unit[value->unit];
}
static GtkCssValue *
gtk_css_value_dimension_transition (GtkCssValue *start,
GtkCssValue *end,
guint property_id,
double progress)
{
if (start->unit != end->unit)
return NULL;
return gtk_css_dimension_value_new (start->value + (end->value - start->value) * progress, start->unit);
}
static const GtkCssNumberValueClass GTK_CSS_VALUE_DIMENSION = {
{
"GtkCssDimensionValue",
gtk_css_value_dimension_free,
gtk_css_value_dimension_compute,
gtk_css_value_dimension_equal,
gtk_css_number_value_transition,
gtk_css_value_dimension_transition,
NULL,
NULL,
gtk_css_value_dimension_print
@@ -300,35 +279,35 @@ gtk_css_dimension_value_new (double value,
GtkCssUnit unit)
{
static GtkCssValue number_singletons[] = {
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_NUMBER, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_NUMBER, 1 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_NUMBER, 96 }, /* DPI default */
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_NUMBER, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_NUMBER, 1 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_NUMBER, 96 }, /* DPI default */
};
static GtkCssValue px_singletons[] = {
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 1 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 2 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 3 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 4 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 8 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 16 }, /* Icon size default */
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 32 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PX, 64 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 1 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 2 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 3 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 4 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 8 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 16 }, /* Icon size default */
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 32 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PX, 64 },
};
static GtkCssValue percent_singletons[] = {
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PERCENT, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PERCENT, 50 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_PERCENT, 100 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_PERCENT, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, FALSE, GTK_CSS_PERCENT, 50 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, FALSE, GTK_CSS_PERCENT, 100 },
};
static GtkCssValue second_singletons[] = {
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_S, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_S, 1 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_S, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_S, 1 },
};
static GtkCssValue deg_singletons[] = {
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_DEG, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_DEG, 90 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_DEG, 180 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, GTK_CSS_DEG, 270 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_DEG, 0 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_DEG, 90 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_DEG, 180 },
{ &GTK_CSS_VALUE_DIMENSION.value_class, 1, TRUE, GTK_CSS_DEG, 270 },
};
GtkCssValue *result;
@@ -396,6 +375,11 @@ gtk_css_dimension_value_new (double value,
result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_DIMENSION.value_class);
result->unit = unit;
result->value = value;
result->is_computed = value == 0 ||
unit == GTK_CSS_NUMBER ||
unit == GTK_CSS_PX ||
unit == GTK_CSS_DEG ||
unit == GTK_CSS_S;
return result;
}
@@ -513,3 +497,14 @@ gtk_css_dimension_value_parse (GtkCssParser *parser,
return result;
}
gboolean
gtk_css_dimension_value_is_zero (const GtkCssValue *value)
{
if (!value)
return TRUE;
if (value->class != &GTK_CSS_VALUE_DIMENSION.value_class)
return FALSE;
return value->value == 0;
}

View File

@@ -26,10 +26,12 @@ G_BEGIN_DECLS
GtkCssValue * gtk_css_dimension_value_new (double value,
GtkCssUnit unit);
/* This function implemented in gtkcssparser.c */
GtkCssValue * gtk_css_dimension_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags);
gboolean gtk_css_dimension_value_is_zero (const GtkCssValue *value) G_GNUC_PURE;
G_END_DECLS
#endif /* __GTK_CSS_DIMENSION_VALUE_PRIVATE_H__ */

View File

@@ -135,6 +135,7 @@ gtk_css_value_ease_print (const GtkCssValue *ease,
}
static const GtkCssValueClass GTK_CSS_VALUE_EASE = {
"GtkCssEaseValue",
gtk_css_value_ease_free,
gtk_css_value_ease_compute,
gtk_css_value_ease_equal,
@@ -158,12 +159,13 @@ _gtk_css_ease_value_new_cubic_bezier (double x1,
g_return_val_if_fail (x2 <= 1.0, NULL);
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_EASE);
value->type = GTK_CSS_EASE_CUBIC_BEZIER;
value->u.cubic.x1 = x1;
value->u.cubic.y1 = y1;
value->u.cubic.x2 = x2;
value->u.cubic.y2 = y2;
value->is_computed = TRUE;
return value;
}
@@ -177,10 +179,11 @@ _gtk_css_ease_value_new_steps (guint n_steps,
g_return_val_if_fail (n_steps > 0, NULL);
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_EASE);
value->type = GTK_CSS_EASE_STEPS;
value->u.steps.steps = n_steps;
value->u.steps.start = start;
value->is_computed = TRUE;
return value;
}

View File

@@ -78,6 +78,7 @@ gtk_css_value_enum_print (const GtkCssValue *value,
/* GtkBorderStyle */
static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
"GtkCssBorderStyleValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -88,16 +89,16 @@ static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
};
static GtkCssValue border_style_values[] = {
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_NONE, "none" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_INSET, "inset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_OUTSET, "outset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_HIDDEN, "hidden" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOTTED, "dotted" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DASHED, "dashed" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_GROOVE, "groove" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_RIDGE, "ridge" }
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_NONE, "none" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_INSET, "inset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_OUTSET, "outset" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_HIDDEN, "hidden" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOTTED, "dotted" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DASHED, "dashed" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_GROOVE, "groove" },
{ &GTK_CSS_VALUE_BORDER_STYLE, 1, TRUE, GTK_BORDER_STYLE_RIDGE, "ridge" }
};
GtkCssValue *
@@ -135,6 +136,7 @@ _gtk_css_border_style_value_get (const GtkCssValue *value)
/* GtkCssBlendMode */
static const GtkCssValueClass GTK_CSS_VALUE_BLEND_MODE = {
"GtkCssBlendModeValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -145,22 +147,22 @@ static const GtkCssValueClass GTK_CSS_VALUE_BLEND_MODE = {
};
static GtkCssValue blend_mode_values[] = {
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_DEFAULT, "normal" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_MULTIPLY, "multiply" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_SCREEN, "screen" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_OVERLAY, "overlay" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_DARKEN, "darken" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_LIGHTEN, "lighten" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_COLOR_DODGE, "color-dodge" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_COLOR_BURN, "color-burn" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_HARD_LIGHT, "hard-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_SOFT_LIGHT, "soft-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_DIFFERENCE, "difference" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_EXCLUSION, "exclusion" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_COLOR, "color" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_HUE, "hue" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_SATURATION, "saturation" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DEFAULT, "normal" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_MULTIPLY, "multiply" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SCREEN, "screen" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_OVERLAY, "overlay" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DARKEN, "darken" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LIGHTEN, "lighten" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_DODGE, "color-dodge" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR_BURN, "color-burn" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HARD_LIGHT, "hard-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SOFT_LIGHT, "soft-light" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_DIFFERENCE, "difference" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_EXCLUSION, "exclusion" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_COLOR, "color" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_HUE, "hue" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_SATURATION, "saturation" },
{ &GTK_CSS_VALUE_BLEND_MODE, 1, TRUE, GSK_BLEND_MODE_LUMINOSITY, "luminosity" }
};
GtkCssValue *
@@ -285,6 +287,7 @@ gtk_css_value_font_size_compute (GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
"GtkCssFontSizeValue",
gtk_css_value_enum_free,
gtk_css_value_font_size_compute,
gtk_css_value_enum_equal,
@@ -295,15 +298,15 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
};
static GtkCssValue font_size_values[] = {
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_LARGER, "larger" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_SMALL, "small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_LARGE, "large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALLER, "smaller" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGER, "larger" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_SMALL, "xx-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_SMALL, "x-small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_SMALL, "small" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_MEDIUM, "medium" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_LARGE, "large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_X_LARGE, "x-large" },
{ &GTK_CSS_VALUE_FONT_SIZE, 1, FALSE, GTK_CSS_FONT_SIZE_XX_LARGE, "xx-large" }
};
GtkCssValue *
@@ -341,6 +344,7 @@ _gtk_css_font_size_value_get (const GtkCssValue *value)
/* PangoStyle */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
"GtkCssFontStyleValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -351,9 +355,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
};
static GtkCssValue font_style_values[] = {
{ &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_OBLIQUE, "oblique" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_ITALIC, "italic" }
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_OBLIQUE, "oblique" },
{ &GTK_CSS_VALUE_FONT_STYLE, 1, TRUE, PANGO_STYLE_ITALIC, "italic" }
};
GtkCssValue *
@@ -439,6 +443,7 @@ gtk_css_value_font_weight_compute (GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
"GtkCssFontWeightValue",
gtk_css_value_enum_free,
gtk_css_value_font_weight_compute,
gtk_css_value_enum_equal,
@@ -449,8 +454,8 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
};
static GtkCssValue font_weight_values[] = {
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, BOLDER, "bolder" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, LIGHTER, "lighter" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, BOLDER, "bolder" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, FALSE, LIGHTER, "lighter" },
};
GtkCssValue *
@@ -488,6 +493,7 @@ gtk_css_font_weight_value_get (const GtkCssValue *value)
/* PangoStretch */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_STRETCH = {
"GtkCssFontStretchValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -498,15 +504,15 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_STRETCH = {
};
static GtkCssValue font_stretch_values[] = {
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_CONDENSED, "condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_EXPANDED, "expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, PANGO_STRETCH_ULTRA_EXPANDED, "ultra-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_CONDENSED, "ultra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_CONDENSED, "extra-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_CONDENSED, "condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_CONDENSED, "semi-condensed" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_SEMI_EXPANDED, "semi-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXPANDED, "expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_EXTRA_EXPANDED, "extra-expanded" },
{ &GTK_CSS_VALUE_FONT_STRETCH, 1, TRUE, PANGO_STRETCH_ULTRA_EXPANDED, "ultra-expanded" },
};
GtkCssValue *
@@ -544,6 +550,7 @@ _gtk_css_font_stretch_value_get (const GtkCssValue *value)
/* GtkTextDecorationLine */
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
"GtkCssTextDecorationLineValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -554,9 +561,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
};
static GtkCssValue text_decoration_line_values[] = {
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
};
GtkCssValue *
@@ -594,6 +601,7 @@ _gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
/* GtkTextDecorationStyle */
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
"GtkCssTextDecorationStyleValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -604,9 +612,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
};
static GtkCssValue text_decoration_style_values[] = {
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, GTK_CSS_TEXT_DECORATION_STYLE_WAVY, "wavy" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_SOLID, "solid" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE, "double" },
{ &GTK_CSS_VALUE_TEXT_DECORATION_STYLE, 1, TRUE, GTK_CSS_TEXT_DECORATION_STYLE_WAVY, "wavy" },
};
GtkCssValue *
@@ -644,6 +652,7 @@ _gtk_css_text_decoration_style_value_get (const GtkCssValue *value)
/* GtkCssArea */
static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
"GtkCssAreaValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -654,9 +663,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
};
static GtkCssValue area_values[] = {
{ &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_BORDER_BOX, "border-box" },
{ &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
{ &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
{ &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_BORDER_BOX, "border-box" },
{ &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
{ &GTK_CSS_VALUE_AREA, 1, TRUE, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
};
GtkCssValue *
@@ -700,6 +709,7 @@ _gtk_css_area_value_get (const GtkCssValue *value)
/* GtkCssDirection */
static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
"GtkCssDirectionValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -710,10 +720,10 @@ static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
};
static GtkCssValue direction_values[] = {
{ &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_REVERSE, "reverse" },
{ &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
{ &GTK_CSS_VALUE_DIRECTION, 1, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_REVERSE, "reverse" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE, "alternate" },
{ &GTK_CSS_VALUE_DIRECTION, 1, TRUE, GTK_CSS_DIRECTION_ALTERNATE_REVERSE, "alternate-reverse" }
};
GtkCssValue *
@@ -760,6 +770,7 @@ _gtk_css_direction_value_get (const GtkCssValue *value)
/* GtkCssPlayState */
static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
"GtkCssPlayStateValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -770,8 +781,8 @@ static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
};
static GtkCssValue play_state_values[] = {
{ &GTK_CSS_VALUE_PLAY_STATE, 1, GTK_CSS_PLAY_STATE_RUNNING, "running" },
{ &GTK_CSS_VALUE_PLAY_STATE, 1, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
{ &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_RUNNING, "running" },
{ &GTK_CSS_VALUE_PLAY_STATE, 1, TRUE, GTK_CSS_PLAY_STATE_PAUSED, "paused" }
};
GtkCssValue *
@@ -815,6 +826,7 @@ _gtk_css_play_state_value_get (const GtkCssValue *value)
/* GtkCssFillMode */
static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
"GtkCssFillModeValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -825,10 +837,10 @@ static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
};
static GtkCssValue fill_mode_values[] = {
{ &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_NONE, "none" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_FORWARDS, "forwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_BACKWARDS, "backwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, GTK_CSS_FILL_BOTH, "both" }
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_NONE, "none" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_FORWARDS, "forwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BACKWARDS, "backwards" },
{ &GTK_CSS_VALUE_FILL_MODE, 1, TRUE, GTK_CSS_FILL_BOTH, "both" }
};
GtkCssValue *
@@ -872,6 +884,7 @@ _gtk_css_fill_mode_value_get (const GtkCssValue *value)
/* GtkCssIconStyle */
static const GtkCssValueClass GTK_CSS_VALUE_ICON_STYLE = {
"GtkCssIconStyleValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -882,9 +895,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_ICON_STYLE = {
};
static GtkCssValue icon_style_values[] = {
{ &GTK_CSS_VALUE_ICON_STYLE, 1, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, GTK_CSS_ICON_STYLE_SYMBOLIC, "symbolic" }
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REQUESTED, "requested" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_REGULAR, "regular" },
{ &GTK_CSS_VALUE_ICON_STYLE, 1, TRUE, GTK_CSS_ICON_STYLE_SYMBOLIC, "symbolic" }
};
GtkCssValue *
@@ -928,6 +941,7 @@ _gtk_css_icon_style_value_get (const GtkCssValue *value)
/* GtkCssFontKerning */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_KERNING = {
"GtkCssFontKerningValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -938,9 +952,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_KERNING = {
};
static GtkCssValue font_kerning_values[] = {
{ &GTK_CSS_VALUE_FONT_KERNING, 1, GTK_CSS_FONT_KERNING_AUTO, "auto" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, GTK_CSS_FONT_KERNING_NONE, "none" }
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_AUTO, "auto" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_KERNING, 1, TRUE, GTK_CSS_FONT_KERNING_NONE, "none" }
};
GtkCssValue *
@@ -984,6 +998,7 @@ _gtk_css_font_kerning_value_get (const GtkCssValue *value)
/* GtkCssFontVariantPos */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_POSITION = {
"GtkCssFontVariationPositionValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -994,9 +1009,9 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_POSITION = {
};
static GtkCssValue font_variant_position_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, GTK_CSS_FONT_VARIANT_POSITION_SUPER, "super" }
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUB, "sub" },
{ &GTK_CSS_VALUE_FONT_VARIANT_POSITION, 1, TRUE, GTK_CSS_FONT_VARIANT_POSITION_SUPER, "super" }
};
GtkCssValue *
@@ -1040,6 +1055,7 @@ _gtk_css_font_variant_position_value_get (const GtkCssValue *value)
/* GtkCssFontVariantCaps */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_CAPS = {
"GtkCssFontVariantCapsValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -1050,13 +1066,13 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_CAPS = {
};
static GtkCssValue font_variant_caps_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS, "titling-caps" }
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_SMALL_CAPS, "small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_SMALL_CAPS, "all-small-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_PETITE_CAPS, "petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_ALL_PETITE_CAPS, "all-petite-caps" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_UNICASE, "unicase" },
{ &GTK_CSS_VALUE_FONT_VARIANT_CAPS, 1, TRUE, GTK_CSS_FONT_VARIANT_CAPS_TITLING_CAPS, "titling-caps" }
};
GtkCssValue *
@@ -1100,6 +1116,7 @@ _gtk_css_font_variant_caps_value_get (const GtkCssValue *value)
/* GtkCssFontVariantAlternate */
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE = {
"GtkCssFontVariantAlternateValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_enum_equal,
@@ -1110,8 +1127,8 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE = {
};
static GtkCssValue font_variant_alternate_values[] = {
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS, "historical-forms" }
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE, 1, TRUE, GTK_CSS_FONT_VARIANT_ALTERNATE_HISTORICAL_FORMS, "historical-forms" }
};
GtkCssValue *
@@ -1213,6 +1230,7 @@ gtk_css_font_variant_ligature_value_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_LIGATURE = {
"GtkCssFontVariantLigatureValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
@@ -1253,6 +1271,7 @@ _gtk_css_font_variant_ligature_value_new (GtkCssFontVariantLigature ligatures)
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_LIGATURE);
value->value = ligatures;
value->name = NULL;
value->is_computed = TRUE;
return value;
}
@@ -1319,6 +1338,7 @@ gtk_css_font_variant_numeric_value_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_NUMERIC = {
"GtkCssFontVariantNumbericValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
@@ -1355,6 +1375,7 @@ _gtk_css_font_variant_numeric_value_new (GtkCssFontVariantNumeric numeric)
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_NUMERIC);
value->value = numeric;
value->name = NULL;
value->is_computed = TRUE;
return value;
}
@@ -1422,6 +1443,7 @@ gtk_css_font_variant_east_asian_value_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = {
"GtkCssFontVariantEastAsianValue",
gtk_css_value_enum_free,
gtk_css_value_enum_compute,
gtk_css_value_flags_equal,
@@ -1497,6 +1519,7 @@ _gtk_css_font_variant_east_asian_value_new (GtkCssFontVariantEastAsian east_asia
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN);
value->value = east_asian;
value->name = NULL;
value->is_computed = TRUE;
return value;
}

View File

@@ -693,6 +693,7 @@ gtk_css_value_filter_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FILTER = {
"GtkCssFilterValue",
gtk_css_value_filter_free,
gtk_css_value_filter_compute,
gtk_css_value_filter_equal,
@@ -702,7 +703,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FILTER = {
gtk_css_value_filter_print
};
static GtkCssValue none_singleton = { &GTK_CSS_VALUE_FILTER, 1, 0, { { GTK_CSS_FILTER_NONE } } };
static GtkCssValue none_singleton = { &GTK_CSS_VALUE_FILTER, 1, TRUE, 0, { { GTK_CSS_FILTER_NONE } } };
static GtkCssValue *
gtk_css_filter_value_alloc (guint n_filters)
@@ -777,6 +778,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
GtkCssValue *value;
GArray *array;
guint i;
gboolean computed = TRUE;
if (gtk_css_parser_try_ident (parser, "none"))
return gtk_css_filter_value_new_none ();
@@ -793,6 +795,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_BLUR;
computed = computed && gtk_css_value_is_computed (filter.blur.value);
}
else if (gtk_css_parser_has_function (parser, "brightness"))
{
@@ -800,6 +803,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_BRIGHTNESS;
computed = computed && gtk_css_value_is_computed (filter.brightness.value);
}
else if (gtk_css_parser_has_function (parser, "contrast"))
{
@@ -807,6 +811,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_CONTRAST;
computed = computed && gtk_css_value_is_computed (filter.contrast.value);
}
else if (gtk_css_parser_has_function (parser, "grayscale"))
{
@@ -814,13 +819,15 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_GRAYSCALE;
computed = computed && gtk_css_value_is_computed (filter.grayscale.value);
}
else if (gtk_css_parser_has_function (parser, "hue-rotate"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_angle, &filter.blur.value))
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_angle, &filter.hue_rotate.value))
goto fail;
filter.type = GTK_CSS_FILTER_HUE_ROTATE;
computed = computed && gtk_css_value_is_computed (filter.hue_rotate.value);
}
else if (gtk_css_parser_has_function (parser, "invert"))
{
@@ -828,6 +835,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_INVERT;
computed = computed && gtk_css_value_is_computed (filter.invert.value);
}
else if (gtk_css_parser_has_function (parser, "opacity"))
{
@@ -835,6 +843,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_OPACITY;
computed = computed && gtk_css_value_is_computed (filter.opacity.value);
}
else if (gtk_css_parser_has_function (parser, "saturate"))
{
@@ -842,6 +851,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_SATURATE;
computed = computed && gtk_css_value_is_computed (filter.saturate.value);
}
else if (gtk_css_parser_has_function (parser, "sepia"))
{
@@ -849,6 +859,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
goto fail;
filter.type = GTK_CSS_FILTER_SEPIA;
computed = computed && gtk_css_value_is_computed (filter.sepia.value);
}
else
{
@@ -866,6 +877,7 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
value = gtk_css_filter_value_alloc (array->len);
memcpy (value->filters, array->data, sizeof (GtkCssFilter) * array->len);
value->is_computed = computed;
g_array_free (array, TRUE);

View File

@@ -154,6 +154,7 @@ gtk_css_value_font_features_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_FEATURES = {
"GtkCssFontFeaturesValue",
gtk_css_value_font_features_free,
gtk_css_value_font_features_compute,
gtk_css_value_font_features_equal,
@@ -172,6 +173,7 @@ gtk_css_font_features_value_new_empty (void)
result->features = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify) _gtk_css_value_unref);
result->is_computed = TRUE;
return result;
}

View File

@@ -154,6 +154,7 @@ gtk_css_value_font_variations_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIATIONS = {
"GtkCssFontVariationsValue",
gtk_css_value_font_variations_free,
gtk_css_value_font_variations_compute,
gtk_css_value_font_variations_equal,
@@ -172,6 +173,7 @@ gtk_css_font_variations_value_new_empty (void)
result->axes = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify) _gtk_css_value_unref);
result->is_computed = TRUE;
return result;
}

View File

@@ -111,6 +111,7 @@ gtk_css_value_icon_theme_print (const GtkCssValue *icon_theme,
}
static const GtkCssValueClass GTK_CSS_VALUE_ICON_THEME = {
"GtkCssIconThemeValue",
gtk_css_value_icon_theme_free,
gtk_css_value_icon_theme_compute,
gtk_css_value_icon_theme_equal,
@@ -120,7 +121,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_ICON_THEME = {
gtk_css_value_icon_theme_print
};
static GtkCssValue default_icon_theme_value = { &GTK_CSS_VALUE_ICON_THEME, 1, NULL, 0 };
static GtkCssValue default_icon_theme_value = { &GTK_CSS_VALUE_ICON_THEME, 1, FALSE, NULL, 0 };
GtkCssValue *
gtk_css_icon_theme_value_new (GtkIconTheme *icontheme)

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
@@ -333,6 +340,17 @@ _gtk_css_image_print (GtkCssImage *image,
klass->print (image, string);
}
char *
gtk_css_image_to_string (GtkCssImage *image)
{
GString *str = g_string_new ("");
_gtk_css_image_print (image, str);
return g_string_free (str, FALSE);
}
/* Applies the algorithm outlined in
* http://dev.w3.org/csswg/css3-images/#default-sizing
*/
@@ -565,3 +583,10 @@ _gtk_css_image_new_parse (GtkCssParser *parser)
return image;
}
gboolean
gtk_css_image_is_computed (GtkCssImage *image)
{
GtkCssImageClass *klass = GTK_CSS_IMAGE_GET_CLASS (image);
return klass->is_computed (image);
}

View File

@@ -414,6 +414,22 @@ gtk_css_image_cross_fade_dispose (GObject *object)
G_OBJECT_CLASS (gtk_css_image_cross_fade_parent_class)->dispose (object);
}
static gboolean
gtk_css_image_cross_fade_is_computed (GtkCssImage *image)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
guint i;
for (i = 0; i < cross_fade->images->len; i++)
{
const CrossFadeEntry *entry = &g_array_index (cross_fade->images, CrossFadeEntry, i);
if (!gtk_css_image_is_computed (entry->image))
return FALSE;
}
return TRUE;
}
static void
gtk_css_image_cross_fade_class_init (GtkCssImageCrossFadeClass *klass)
{
@@ -429,6 +445,7 @@ gtk_css_image_cross_fade_class_init (GtkCssImageCrossFadeClass *klass)
image_class->get_dynamic_image = gtk_css_image_cross_fade_get_dynamic_image;
image_class->parse = gtk_css_image_cross_fade_parse;
image_class->print = gtk_css_image_cross_fade_print;
image_class->is_computed = gtk_css_image_cross_fade_is_computed;
object_class->dispose = gtk_css_image_cross_fade_dispose;
}

View File

@@ -21,7 +21,7 @@
#include "gtkcssimagefallbackprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkstyleproviderprivate.h"
@@ -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_rgba_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);
@@ -142,6 +145,20 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
if (fallback->used < 0)
{
GtkCssValue *computed_color = NULL;
if (fallback->color)
computed_color= _gtk_css_value_compute (fallback->color,
property_id,
provider,
style,
parent_style);
/* image($color) that didn't change */
if (computed_color && !fallback->images &&
computed_color == fallback->color)
return g_object_ref (image);
copy = g_object_new (_gtk_css_image_fallback_get_type (), NULL);
copy->n_images = fallback->n_images;
copy->images = g_new (GtkCssImage *, fallback->n_images);
@@ -160,14 +177,7 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
copy->used = i;
}
if (fallback->color)
copy->color = _gtk_css_value_compute (fallback->color,
property_id,
provider,
style,
parent_style);
else
copy->color = NULL;
copy->color = computed_color;
return GTK_CSS_IMAGE (copy);
}
@@ -263,6 +273,30 @@ gtk_css_image_fallback_equal (GtkCssImage *image1,
fallback2->images[fallback2->used]);
}
static gboolean
gtk_css_image_fallback_is_computed (GtkCssImage *image)
{
GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image);
if (fallback->used < 0)
{
guint i;
if (fallback->color && !fallback->images)
return gtk_css_value_is_computed (fallback->color);
for (i = 0; i < fallback->n_images; i++)
{
if (!gtk_css_image_is_computed (fallback->images[i]))
{
return FALSE;
}
}
}
return TRUE;
}
static void
_gtk_css_image_fallback_class_init (GtkCssImageFallbackClass *klass)
{
@@ -277,6 +311,7 @@ _gtk_css_image_fallback_class_init (GtkCssImageFallbackClass *klass)
image_class->compute = gtk_css_image_fallback_compute;
image_class->print = gtk_css_image_fallback_print;
image_class->equal = gtk_css_image_fallback_equal;
image_class->is_computed = gtk_css_image_fallback_is_computed;
object_class->dispose = gtk_css_image_fallback_dispose;
}

View File

@@ -24,7 +24,6 @@
#include <math.h>
#include "gtkcssiconthemevalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtksettingsprivate.h"
#include "gtksnapshot.h"
#include "gtkstyleproviderprivate.h"
@@ -95,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

@@ -25,7 +25,7 @@
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssprovider.h"
G_DEFINE_TYPE (GtkCssImageLinear, _gtk_css_image_linear, GTK_TYPE_CSS_IMAGE)
@@ -36,13 +36,13 @@ gtk_css_image_linear_get_repeating_start_end (GtkCssImageLinear *linear,
double *start,
double *end)
{
GtkCssImageLinearColorStop *stop;
const GtkCssImageLinearColorStop *stop;
double pos;
guint i;
g_assert (linear->repeating);
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, 0);
stop = &linear->color_stops[0];
if (stop->offset == NULL)
*start = 0;
else
@@ -50,9 +50,9 @@ gtk_css_image_linear_get_repeating_start_end (GtkCssImageLinear *linear,
*end = *start;
for (i = 0; i < linear->stops->len; i++)
for (i = 0; i < linear->n_stops; i++)
{
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
stop = &linear->color_stops[i];
if (stop->offset == NULL)
continue;
@@ -190,11 +190,10 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
{
/* repeating gradients with all color stops sharing the same offset
* get the color of the last color stop */
GtkCssImageLinearColorStop *stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop,
linear->stops->len - 1);
const GtkCssImageLinearColorStop *stop = &linear->color_stops[linear->n_stops - 1];
gtk_snapshot_append_color (snapshot,
_gtk_css_rgba_value_get_rgba (stop->color),
gtk_css_color_value_get_rgba (stop->color),
&GRAPHENE_RECT_INIT (0, 0, width, height));
return;
}
@@ -207,20 +206,18 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
offset = start;
last = -1;
stops = g_newa (GskColorStop, linear->stops->len);
stops = g_newa (GskColorStop, linear->n_stops);
for (i = 0; i < linear->stops->len; i++)
for (i = 0; i < linear->n_stops; i++)
{
GtkCssImageLinearColorStop *stop;
const GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
double pos, step;
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
if (stop->offset == NULL)
{
if (i == 0)
pos = 0.0;
else if (i + 1 == linear->stops->len)
else if (i + 1 == linear->n_stops)
pos = 1.0;
else
continue;
@@ -235,12 +232,12 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
step = (pos - offset) / (i - last);
for (last = last + 1; last <= i; last++)
{
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, last);
stop = &linear->color_stops[last];
offset += step;
stops[last].offset = (offset - start) / (end - start);
stops[last].color = *_gtk_css_rgba_value_get_rgba (stop->color);
stops[last].color = *gtk_css_color_value_get_rgba (stop->color);
}
offset = pos;
@@ -255,7 +252,7 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
&GRAPHENE_POINT_INIT (width / 2 + x * (start - 0.5), height / 2 + y * (start - 0.5)),
&GRAPHENE_POINT_INIT (width / 2 + x * (end - 0.5), height / 2 + y * (end - 0.5)),
stops,
linear->stops->len);
linear->n_stops);
}
else
{
@@ -265,13 +262,14 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
&GRAPHENE_POINT_INIT (width / 2 + x * (start - 0.5), height / 2 + y * (start - 0.5)),
&GRAPHENE_POINT_INIT (width / 2 + x * (end - 0.5), height / 2 + y * (end - 0.5)),
stops,
linear->stops->len);
linear->n_stops);
}
}
static guint
gtk_css_image_linear_parse_color_stop (GtkCssImageLinear *self,
GtkCssParser *parser)
GtkCssParser *parser,
GArray *stop_array)
{
GtkCssImageLinearColorStop stop;
@@ -295,14 +293,15 @@ gtk_css_image_linear_parse_color_stop (GtkCssImageLinear *self,
stop.offset = NULL;
}
g_array_append_val (self->stops, stop);
g_array_append_val (stop_array, stop);
return 1;
}
static guint
gtk_css_image_linear_parse_first_arg (GtkCssImageLinear *linear,
GtkCssParser *parser)
GtkCssParser *parser,
GArray *stop_array)
{
guint i;
@@ -363,31 +362,37 @@ gtk_css_image_linear_parse_first_arg (GtkCssImageLinear *linear,
linear->angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (linear->angle == NULL)
return 0;
return 1;
}
else
{
linear->side = 1 << GTK_CSS_BOTTOM;
if (!gtk_css_image_linear_parse_color_stop (linear, parser))
if (!gtk_css_image_linear_parse_color_stop (linear, parser, stop_array))
return 0;
return 2;
}
}
typedef struct
{
GtkCssImageLinear *self;
GArray *stop_array;
} ParseData;
static guint
gtk_css_image_linear_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
gpointer user_data)
{
GtkCssImageLinear *self = data;
ParseData *parse_data = user_data;
GtkCssImageLinear *self = parse_data->self;
if (arg == 0)
return gtk_css_image_linear_parse_first_arg (self, parser);
return gtk_css_image_linear_parse_first_arg (self, parser, parse_data->stop_array);
else
return gtk_css_image_linear_parse_color_stop (self, parser);
return gtk_css_image_linear_parse_color_stop (self, parser, parse_data->stop_array);
}
static gboolean
@@ -395,6 +400,8 @@ gtk_css_image_linear_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageLinear *self = GTK_CSS_IMAGE_LINEAR (image);
ParseData parse_data;
gboolean success;
if (gtk_css_parser_has_function (parser, "repeating-linear-gradient"))
self->repeating = TRUE;
@@ -406,7 +413,22 @@ gtk_css_image_linear_parse (GtkCssImage *image,
return FALSE;
}
return gtk_css_parser_consume_function (parser, 3, G_MAXUINT, gtk_css_image_linear_parse_arg, self);
parse_data.self = self;
parse_data.stop_array = g_array_new (TRUE, FALSE, sizeof (GtkCssImageLinearColorStop));
success = gtk_css_parser_consume_function (parser, 3, G_MAXUINT, gtk_css_image_linear_parse_arg, &parse_data);
if (!success)
{
g_array_free (parse_data.stop_array, TRUE);
}
else
{
self->n_stops = parse_data.stop_array->len;
self->color_stops = (GtkCssImageLinearColorStop *)g_array_free (parse_data.stop_array, FALSE);
}
return success;
}
static void
@@ -446,15 +468,13 @@ gtk_css_image_linear_print (GtkCssImage *image,
g_string_append (string, ", ");
}
for (i = 0; i < linear->stops->len; i++)
for (i = 0; i < linear->n_stops; i++)
{
GtkCssImageLinearColorStop *stop;
const GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
if (i > 0)
g_string_append (string, ", ");
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
_gtk_css_value_print (stop->color, string);
if (stop->offset)
@@ -463,7 +483,7 @@ gtk_css_image_linear_print (GtkCssImage *image,
_gtk_css_value_print (stop->offset, string);
}
}
g_string_append (string, ")");
}
@@ -484,17 +504,16 @@ gtk_css_image_linear_compute (GtkCssImage *image,
if (linear->angle)
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style);
g_array_set_size (copy->stops, linear->stops->len);
for (i = 0; i < linear->stops->len; i++)
{
GtkCssImageLinearColorStop *stop, *scopy;
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
scopy = &g_array_index (copy->stops, GtkCssImageLinearColorStop, i);
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 = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
@@ -528,7 +547,7 @@ gtk_css_image_linear_transition (GtkCssImage *start_image,
end = GTK_CSS_IMAGE_LINEAR (end_image);
if ((start->repeating != end->repeating)
|| (start->stops->len != end->stops->len))
|| (start->n_stops != end->n_stops))
return GTK_CSS_IMAGE_CLASS (_gtk_css_image_linear_parent_class)->transition (start_image, end_image, property_id, progress);
result = g_object_new (GTK_TYPE_CSS_IMAGE_LINEAR, NULL);
@@ -542,43 +561,45 @@ gtk_css_image_linear_transition (GtkCssImage *start_image,
result->angle = _gtk_css_value_transition (start->angle, end->angle, property_id, progress);
if (result->angle == NULL)
goto fail;
for (i = 0; i < start->stops->len; i++)
{
GtkCssImageLinearColorStop stop, *start_stop, *end_stop;
start_stop = &g_array_index (start->stops, GtkCssImageLinearColorStop, i);
end_stop = &g_array_index (end->stops, GtkCssImageLinearColorStop, i);
/* Maximum amountof stops */
result->color_stops = g_malloc (sizeof (GtkCssImageLinearColorStop) * start->n_stops);
result->n_stops = 0;
for (i = 0; i < start->n_stops; i++)
{
const GtkCssImageLinearColorStop *start_stop = &start->color_stops[i];
const GtkCssImageLinearColorStop *end_stop = &end->color_stops[i];
GtkCssImageLinearColorStop *stop = &result->color_stops[i];
if ((start_stop->offset != NULL) != (end_stop->offset != NULL))
goto fail;
if (start_stop->offset == NULL)
{
stop.offset = NULL;
stop->offset = NULL;
}
else
{
stop.offset = _gtk_css_value_transition (start_stop->offset,
end_stop->offset,
property_id,
progress);
if (stop.offset == NULL)
stop->offset = _gtk_css_value_transition (start_stop->offset,
end_stop->offset,
property_id,
progress);
if (stop->offset == NULL)
goto fail;
}
stop.color = _gtk_css_value_transition (start_stop->color,
end_stop->color,
property_id,
progress);
if (stop.color == NULL)
stop->color = _gtk_css_value_transition (start_stop->color,
end_stop->color,
property_id,
progress);
if (stop->color == NULL)
{
if (stop.offset)
_gtk_css_value_unref (stop.offset);
if (stop->offset)
_gtk_css_value_unref (stop->offset);
goto fail;
}
g_array_append_val (result->stops, stop);
result->n_stops ++;
}
return GTK_CSS_IMAGE (result);
@@ -599,15 +620,13 @@ gtk_css_image_linear_equal (GtkCssImage *image1,
if (linear1->repeating != linear2->repeating ||
linear1->side != linear2->side ||
(linear1->side == 0 && !_gtk_css_value_equal (linear1->angle, linear2->angle)) ||
linear1->stops->len != linear2->stops->len)
linear1->n_stops != linear2->n_stops)
return FALSE;
for (i = 0; i < linear1->stops->len; i++)
for (i = 0; i < linear1->n_stops; i++)
{
GtkCssImageLinearColorStop *stop1, *stop2;
stop1 = &g_array_index (linear1->stops, GtkCssImageLinearColorStop, i);
stop2 = &g_array_index (linear2->stops, GtkCssImageLinearColorStop, i);
const GtkCssImageLinearColorStop *stop1 = &linear1->color_stops[i];
const GtkCssImageLinearColorStop *stop2 = &linear2->color_stops[i];
if (!_gtk_css_value_equal0 (stop1->offset, stop2->offset) ||
!_gtk_css_value_equal (stop1->color, stop2->color))
@@ -621,12 +640,17 @@ static void
gtk_css_image_linear_dispose (GObject *object)
{
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (object);
guint i;
if (linear->stops)
for (i = 0; i < linear->n_stops; i ++)
{
g_array_free (linear->stops, TRUE);
linear->stops = NULL;
GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
_gtk_css_value_unref (stop->color);
if (stop->offset)
_gtk_css_value_unref (stop->offset);
}
g_free (linear->color_stops);
linear->side = 0;
if (linear->angle)
@@ -638,6 +662,35 @@ gtk_css_image_linear_dispose (GObject *object)
G_OBJECT_CLASS (_gtk_css_image_linear_parent_class)->dispose (object);
}
static gboolean
gtk_css_image_linear_is_computed (GtkCssImage *image)
{
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
guint i;
gboolean computed = TRUE;
computed = !linear->angle || gtk_css_value_is_computed (linear->angle);
for (i = 0; i < linear->n_stops; i ++)
{
const GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
if (stop->offset && !gtk_css_value_is_computed (stop->offset))
{
computed = FALSE;
break;
}
if (!gtk_css_value_is_computed (stop->color))
{
computed = FALSE;
break;
}
}
return computed;
}
static void
_gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass)
{
@@ -650,24 +703,13 @@ _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass)
image_class->compute = gtk_css_image_linear_compute;
image_class->equal = gtk_css_image_linear_equal;
image_class->transition = gtk_css_image_linear_transition;
image_class->is_computed = gtk_css_image_linear_is_computed;
object_class->dispose = gtk_css_image_linear_dispose;
}
static void
gtk_css_image_clear_color_stop (gpointer color_stop)
{
GtkCssImageLinearColorStop *stop = color_stop;
_gtk_css_value_unref (stop->color);
if (stop->offset)
_gtk_css_value_unref (stop->offset);
}
static void
_gtk_css_image_linear_init (GtkCssImageLinear *linear)
{
linear->stops = g_array_new (FALSE, FALSE, sizeof (GtkCssImageLinearColorStop));
g_array_set_clear_func (linear->stops, gtk_css_image_clear_color_stop);
}

View File

@@ -45,10 +45,12 @@ struct _GtkCssImageLinear
{
GtkCssImage parent;
guint side; /* side the gradient should go to or 0 for angle */
GtkCssValue *angle;
GArray *stops;
guint side; /* side the gradient should go to or 0 for angle */
guint repeating :1;
GtkCssValue *angle;
guint n_stops;
GtkCssImageLinearColorStop *color_stops;
};
struct _GtkCssImageLinearClass

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

@@ -89,6 +89,7 @@ struct _GtkCssImageClass
/* print to CSS */
void (* print) (GtkCssImage *image,
GString *string);
gboolean (* is_computed) (GtkCssImage *image);
};
GType _gtk_css_image_get_type (void) G_GNUC_CONST;
@@ -96,9 +97,9 @@ GType _gtk_css_image_get_type (void) G_GNUC_CONST;
gboolean _gtk_css_image_can_parse (GtkCssParser *parser);
GtkCssImage * _gtk_css_image_new_parse (GtkCssParser *parser);
int _gtk_css_image_get_width (GtkCssImage *image);
int _gtk_css_image_get_height (GtkCssImage *image);
double _gtk_css_image_get_aspect_ratio (GtkCssImage *image);
int _gtk_css_image_get_width (GtkCssImage *image) G_GNUC_PURE;
int _gtk_css_image_get_height (GtkCssImage *image) G_GNUC_PURE;
double _gtk_css_image_get_aspect_ratio (GtkCssImage *image) G_GNUC_PURE;
GtkCssImage * _gtk_css_image_compute (GtkCssImage *image,
guint property_id,
@@ -106,7 +107,7 @@ GtkCssImage * _gtk_css_image_compute (GtkCssImage *
GtkCssStyle *style,
GtkCssStyle *parent_style);
gboolean _gtk_css_image_equal (GtkCssImage *image1,
GtkCssImage *image2);
GtkCssImage *image2) G_GNUC_PURE;
GtkCssImage * _gtk_css_image_transition (GtkCssImage *start,
GtkCssImage *end,
guint property_id,
@@ -120,12 +121,13 @@ void gtk_css_image_snapshot (GtkCssImage *
GtkSnapshot *snapshot,
double width,
double height);
gboolean gtk_css_image_is_invalid (GtkCssImage *image);
gboolean gtk_css_image_is_dynamic (GtkCssImage *image);
gboolean gtk_css_image_is_invalid (GtkCssImage *image) G_GNUC_PURE;
gboolean gtk_css_image_is_dynamic (GtkCssImage *image) G_GNUC_PURE;
GtkCssImage * gtk_css_image_get_dynamic_image (GtkCssImage *image,
gint64 monotonic_time);
void _gtk_css_image_print (GtkCssImage *image,
GString *string);
char * gtk_css_image_to_string (GtkCssImage *image);
void _gtk_css_image_get_concrete_size (GtkCssImage *image,
double specified_width,
@@ -139,6 +141,8 @@ cairo_surface_t *
cairo_surface_t *target,
int surface_width,
int surface_height);
gboolean gtk_css_image_is_computed (GtkCssImage *image) G_GNUC_PURE;
G_END_DECLS

View File

@@ -26,7 +26,7 @@
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcsspositionvalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssprovider.h"
G_DEFINE_TYPE (GtkCssImageRadial, _gtk_css_image_radial, GTK_TYPE_CSS_IMAGE)
@@ -37,13 +37,13 @@ gtk_css_image_radial_get_start_end (GtkCssImageRadial *radial,
double *start,
double *end)
{
GtkCssImageRadialColorStop *stop;
const GtkCssImageRadialColorStop *stop;
double pos;
guint i;
if (radial->repeating)
{
stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, 0);
stop = &radial->color_stops[0];
if (stop->offset == NULL)
*start = 0;
else
@@ -51,9 +51,9 @@ gtk_css_image_radial_get_start_end (GtkCssImageRadial *radial,
*end = *start;
for (i = 0; i < radial->stops->len; i++)
for (i = 0; i < radial->n_stops; i++)
{
stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);
stop = &radial->color_stops[i];
if (stop->offset == NULL)
continue;
@@ -181,18 +181,16 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
offset = start;
last = -1;
for (i = 0; i < radial->stops->len; i++)
for (i = 0; i < radial->n_stops; i++)
{
GtkCssImageRadialColorStop *stop;
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
double pos, step;
stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);
if (stop->offset == NULL)
{
if (i == 0)
pos = 0.0;
else if (i + 1 == radial->stops->len)
else if (i + 1 == radial->n_stops)
pos = 1.0;
else
continue;
@@ -206,9 +204,9 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
{
const GdkRGBA *rgba;
stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, last);
stop = &radial->color_stops[last];
rgba = _gtk_css_rgba_value_get_rgba (stop->color);
rgba = gtk_css_color_value_get_rgba (stop->color);
offset += step;
cairo_pattern_add_color_stop_rgba (pattern,
@@ -235,7 +233,8 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
static guint
gtk_css_image_radial_parse_color_stop (GtkCssImageRadial *radial,
GtkCssParser *parser)
GtkCssParser *parser,
GArray *stop_array)
{
GtkCssImageRadialColorStop stop;
@@ -259,14 +258,15 @@ gtk_css_image_radial_parse_color_stop (GtkCssImageRadial *radial,
stop.offset = NULL;
}
g_array_append_val (radial->stops, stop);
g_array_append_val (stop_array, stop);
return 1;
}
static guint
gtk_css_image_radial_parse_first_arg (GtkCssImageRadial *radial,
GtkCssParser *parser)
GtkCssParser *parser,
GArray *stop_array)
{
gboolean has_shape = FALSE;
gboolean has_size = FALSE;
@@ -379,23 +379,30 @@ gtk_css_image_radial_parse_first_arg (GtkCssImageRadial *radial,
if (found_one)
return 1;
if (!gtk_css_image_radial_parse_color_stop (radial, parser))
if (!gtk_css_image_radial_parse_color_stop (radial, parser, stop_array))
return 0;
return 2;
}
typedef struct
{
GtkCssImageRadial *self;
GArray *stop_array;
} ParseData;
static guint
gtk_css_image_radial_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
gpointer user_data)
{
GtkCssImageRadial *self = data;
ParseData *parse_data = user_data;
GtkCssImageRadial *self = parse_data->self;
if (arg == 0)
return gtk_css_image_radial_parse_first_arg (self, parser);
return gtk_css_image_radial_parse_first_arg (self, parser, parse_data->stop_array);
else
return gtk_css_image_radial_parse_color_stop (self, parser);
return gtk_css_image_radial_parse_color_stop (self, parser, parse_data->stop_array);
}
@@ -404,6 +411,8 @@ gtk_css_image_radial_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageRadial *self = GTK_CSS_IMAGE_RADIAL (image);
ParseData parse_data;
gboolean success;
if (gtk_css_parser_has_function (parser, "repeating-radial-gradient"))
self->repeating = TRUE;
@@ -415,7 +424,22 @@ gtk_css_image_radial_parse (GtkCssImage *image,
return FALSE;
}
return gtk_css_parser_consume_function (parser, 3, G_MAXUINT, gtk_css_image_radial_parse_arg, self);
parse_data.self = self;
parse_data.stop_array = g_array_new (TRUE, FALSE, sizeof (GtkCssImageRadialColorStop));
success = gtk_css_parser_consume_function (parser, 3, G_MAXUINT, gtk_css_image_radial_parse_arg, &parse_data);
if (!success)
{
g_array_free (parse_data.stop_array, TRUE);
}
else
{
self->n_stops = parse_data.stop_array->len;
self->color_stops = (GtkCssImageRadialColorStop *)g_array_free (parse_data.stop_array, FALSE);
}
return success;
}
static void
@@ -460,15 +484,13 @@ gtk_css_image_radial_print (GtkCssImage *image,
g_string_append (string, ", ");
for (i = 0; i < radial->stops->len; i++)
for (i = 0; i < radial->n_stops; i++)
{
GtkCssImageRadialColorStop *stop;
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
if (i > 0)
g_string_append (string, ", ");
stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);
_gtk_css_value_print (stop->color, string);
if (stop->offset)
@@ -505,13 +527,12 @@ gtk_css_image_radial_compute (GtkCssImage *image,
if (radial->sizes[1])
copy->sizes[1] = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style);
g_array_set_size (copy->stops, radial->stops->len);
for (i = 0; i < radial->stops->len; i++)
copy->n_stops = radial->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageRadialColorStop) * copy->n_stops);
for (i = 0; i < radial->n_stops; i++)
{
GtkCssImageRadialColorStop *stop, *scopy;
stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i);
scopy = &g_array_index (copy->stops, GtkCssImageRadialColorStop, i);
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
GtkCssImageRadialColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
@@ -548,7 +569,7 @@ gtk_css_image_radial_transition (GtkCssImage *start_image,
end = GTK_CSS_IMAGE_RADIAL (end_image);
if (start->repeating != end->repeating ||
start->stops->len != end->stops->len ||
start->n_stops != end->n_stops ||
start->size != end->size ||
start->circle != end->circle)
return GTK_CSS_IMAGE_CLASS (_gtk_css_image_radial_parent_class)->transition (start_image, end_image, property_id, progress);
@@ -580,42 +601,43 @@ gtk_css_image_radial_transition (GtkCssImage *start_image,
else
result->sizes[1] = 0;
for (i = 0; i < start->stops->len; i++)
result->color_stops = g_malloc (sizeof (GtkCssImageRadialColorStop) * start->n_stops);
result->n_stops = 0;
for (i = 0; i < start->n_stops; i++)
{
GtkCssImageRadialColorStop stop, *start_stop, *end_stop;
start_stop = &g_array_index (start->stops, GtkCssImageRadialColorStop, i);
end_stop = &g_array_index (end->stops, GtkCssImageRadialColorStop, i);
const GtkCssImageRadialColorStop *start_stop = &start->color_stops[i];
const GtkCssImageRadialColorStop *end_stop = &end->color_stops[i];
GtkCssImageRadialColorStop *stop = &result->color_stops[i];
if ((start_stop->offset != NULL) != (end_stop->offset != NULL))
goto fail;
if (start_stop->offset == NULL)
{
stop.offset = NULL;
stop->offset = NULL;
}
else
{
stop.offset = _gtk_css_value_transition (start_stop->offset,
end_stop->offset,
property_id,
progress);
if (stop.offset == NULL)
stop->offset = _gtk_css_value_transition (start_stop->offset,
end_stop->offset,
property_id,
progress);
if (stop->offset == NULL)
goto fail;
}
stop.color = _gtk_css_value_transition (start_stop->color,
end_stop->color,
property_id,
progress);
if (stop.color == NULL)
stop->color = _gtk_css_value_transition (start_stop->color,
end_stop->color,
property_id,
progress);
if (stop->color == NULL)
{
if (stop.offset)
_gtk_css_value_unref (stop.offset);
if (stop->offset)
_gtk_css_value_unref (stop->offset);
goto fail;
}
g_array_append_val (result->stops, stop);
result->n_stops++;
}
return GTK_CSS_IMAGE (result);
@@ -640,15 +662,13 @@ gtk_css_image_radial_equal (GtkCssImage *image1,
(radial1->sizes[0] && radial2->sizes[0] && !_gtk_css_value_equal (radial1->sizes[0], radial2->sizes[0])) ||
((radial1->sizes[1] == NULL) != (radial2->sizes[1] == NULL)) ||
(radial1->sizes[1] && radial2->sizes[1] && !_gtk_css_value_equal (radial1->sizes[1], radial2->sizes[1])) ||
radial1->stops->len != radial2->stops->len)
radial1->n_stops != radial2->n_stops)
return FALSE;
for (i = 0; i < radial1->stops->len; i++)
for (i = 0; i < radial1->n_stops; i++)
{
GtkCssImageRadialColorStop *stop1, *stop2;
stop1 = &g_array_index (radial1->stops, GtkCssImageRadialColorStop, i);
stop2 = &g_array_index (radial2->stops, GtkCssImageRadialColorStop, i);
const GtkCssImageRadialColorStop *stop1 = &radial1->color_stops[i];
const GtkCssImageRadialColorStop *stop2 = &radial2->color_stops[i];
if (!_gtk_css_value_equal0 (stop1->offset, stop2->offset) ||
!_gtk_css_value_equal (stop1->color, stop2->color))
@@ -662,13 +682,17 @@ static void
gtk_css_image_radial_dispose (GObject *object)
{
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (object);
int i;
guint i;
if (radial->stops)
for (i = 0; i < radial->n_stops; i ++)
{
g_array_free (radial->stops, TRUE);
radial->stops = NULL;
GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
_gtk_css_value_unref (stop->color);
if (stop->offset)
_gtk_css_value_unref (stop->offset);
}
g_free (radial->color_stops);
if (radial->position)
{
@@ -686,6 +710,37 @@ gtk_css_image_radial_dispose (GObject *object)
G_OBJECT_CLASS (_gtk_css_image_radial_parent_class)->dispose (object);
}
static gboolean
gtk_css_image_radial_is_computed (GtkCssImage *image)
{
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
guint i;
gboolean computed = TRUE;
computed = computed && (!radial->position || gtk_css_value_is_computed (radial->position));
computed = computed && (!radial->sizes[0] || gtk_css_value_is_computed (radial->sizes[0]));
computed = computed && (!radial->sizes[1] || gtk_css_value_is_computed (radial->sizes[1]));
if (computed)
for (i = 0; i < radial->n_stops; i ++)
{
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
if (stop->offset && !gtk_css_value_is_computed (stop->offset))
{
computed = FALSE;
break;
}
if (!gtk_css_value_is_computed (stop->color))
{
computed = FALSE;
break;
}
}
return computed;
}
static void
_gtk_css_image_radial_class_init (GtkCssImageRadialClass *klass)
{
@@ -698,24 +753,13 @@ _gtk_css_image_radial_class_init (GtkCssImageRadialClass *klass)
image_class->compute = gtk_css_image_radial_compute;
image_class->transition = gtk_css_image_radial_transition;
image_class->equal = gtk_css_image_radial_equal;
image_class->is_computed = gtk_css_image_radial_is_computed;
object_class->dispose = gtk_css_image_radial_dispose;
}
static void
gtk_css_image_clear_color_stop (gpointer color_stop)
{
GtkCssImageRadialColorStop *stop = color_stop;
_gtk_css_value_unref (stop->color);
if (stop->offset)
_gtk_css_value_unref (stop->offset);
}
static void
_gtk_css_image_radial_init (GtkCssImageRadial *radial)
{
radial->stops = g_array_new (FALSE, FALSE, sizeof (GtkCssImageRadialColorStop));
g_array_set_clear_func (radial->stops, gtk_css_image_clear_color_stop);
}

View File

@@ -55,7 +55,8 @@ struct _GtkCssImageRadial
GtkCssValue *position;
GtkCssValue *sizes[2];
GArray *stops;
guint n_stops;
GtkCssImageRadialColorStop *color_stops;
GtkCssRadialSize size;
guint circle : 1;
guint repeating :1;

View File

@@ -22,7 +22,7 @@
#include "gtkcssimagerecolorprivate.h"
#include "gtkcssimageprivate.h"
#include "gtkcsspalettevalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkiconthemeprivate.h"
#include "gdkpixbufutilsprivate.h"
@@ -74,7 +74,7 @@ lookup_symbolic_colors (GtkCssStyle *style,
const GdkRGBA *lookup;
color = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_COLOR);
*color_out = *_gtk_css_rgba_value_get_rgba (color);
*color_out = *gtk_css_color_value_get_rgba (color);
lookup = gtk_css_palette_value_get_color (palette, "success");
if (lookup)
@@ -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

@@ -161,6 +161,12 @@ gtk_css_image_url_is_invalid (GtkCssImage *image)
return gtk_css_image_is_invalid (gtk_css_image_url_load_image (url, NULL));
}
static gboolean
gtk_css_image_url_is_computed (GtkCssImage *image)
{
return TRUE;
}
static gboolean
gtk_css_image_url_parse (GtkCssImage *image,
GtkCssParser *parser)
@@ -249,6 +255,7 @@ _gtk_css_image_url_class_init (GtkCssImageUrlClass *klass)
image_class->print = gtk_css_image_url_print;
image_class->equal = gtk_css_image_url_equal;
image_class->is_invalid = gtk_css_image_url_is_invalid;
image_class->is_computed = gtk_css_image_url_is_computed;
object_class->dispose = gtk_css_image_url_dispose;
}

View File

@@ -82,7 +82,7 @@ gtk_css_value_image_transition (GtkCssValue *start,
}
static gboolean
gtk_css_value_image_is_dynamic (GtkCssValue *value)
gtk_css_value_image_is_dynamic (const GtkCssValue *value)
{
GtkCssImage *image = _gtk_css_image_value_get_image (value);
@@ -123,6 +123,7 @@ gtk_css_value_image_print (const GtkCssValue *value,
}
static const GtkCssValueClass GTK_CSS_VALUE_IMAGE = {
"GtkCssImageValue",
gtk_css_value_image_free,
gtk_css_value_image_compute,
gtk_css_value_image_equal,
@@ -135,7 +136,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_IMAGE = {
GtkCssValue *
_gtk_css_image_value_new (GtkCssImage *image)
{
static GtkCssValue none_singleton = { &GTK_CSS_VALUE_IMAGE, 1, NULL };
static GtkCssValue none_singleton = { &GTK_CSS_VALUE_IMAGE, 1, TRUE, NULL };
GtkCssValue *value;
if (image == NULL)
@@ -143,6 +144,7 @@ _gtk_css_image_value_new (GtkCssImage *image)
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_IMAGE);
value->image = image;
value->is_computed = gtk_css_image_is_computed (image);
return value;
}

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