Compare commits
314 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ff7c86b65 | |||
| 79a0f183ec | |||
| e8c8be8e37 | |||
| bfc80c32ea | |||
| 5f48764ac8 | |||
| cc6fcbfc09 | |||
| ea7185bdb1 | |||
| 429dfcf483 | |||
| be3f352b59 | |||
| 5b8896f1db | |||
| 4e27de7df9 | |||
| 2712f536c2 | |||
| a1f7073ff5 | |||
| 9770872d12 | |||
| de24b4f91b | |||
| 650fd9c291 | |||
| b509809f34 | |||
| 60ff231fac | |||
| 958005317b | |||
| 15c36aaa1e | |||
| 482b73c376 | |||
| 4a8bf6e13d | |||
| 3e2e6633b0 | |||
| 4724f9907c | |||
| 26e84a7b8c | |||
| d5838f14f9 | |||
| 5c532104e4 | |||
| 2f42e1fb89 | |||
| b5200bd076 | |||
| aa5bd38137 | |||
| 0eba833595 | |||
| 1e0ea21297 | |||
| e91e75173d | |||
| 927fdb9a83 | |||
| 041f410838 | |||
| c71c8919fe | |||
| 3f28399f7d | |||
| 3c15fa96bc | |||
| 0a0a059397 | |||
| 18e83fe16d | |||
| 90d7ed5dd1 | |||
| 3c6e7569ff | |||
| 4e2ec2d68d | |||
| 1af72eac21 | |||
| 640273a0e2 | |||
| a14a0c6315 | |||
| 38481680e1 | |||
| 12a540c284 | |||
| 289bf078bf | |||
| 58ab9ddc40 | |||
| c78036fc51 | |||
| 120f2768e6 | |||
| 592b33cb48 | |||
| 7a9bc1f1d8 | |||
| 9cc6f3ee29 | |||
| 9efaa0b51d | |||
| f0967fa5e4 | |||
| f8529983f9 | |||
| 919c08d4fd | |||
| e9b06b6346 | |||
| 949c783187 | |||
| 814a4a781a | |||
| 676f875bf6 | |||
| 140c5c5333 | |||
| cebf2b2009 | |||
| 86b437a1b6 | |||
| 773ae0cd0f | |||
| 564793d5b5 | |||
| 9142aa0f51 | |||
| af9a578d68 | |||
| ecb072fdd0 | |||
| ef053ebb4a | |||
| 8d18d93742 | |||
| 10fcdd88e3 | |||
| 5d9509c51b | |||
| c9cac5fbc3 | |||
| aa9054a5f1 | |||
| 9ebf3fac73 | |||
| 569294070b | |||
| be35c46ce9 | |||
| dbbcb13721 | |||
| edeaf9c040 | |||
| 61f709811c | |||
| f7c4375509 | |||
| 52fb900ced | |||
| 031944ad30 | |||
| bf8b974f68 | |||
| 6ad2a049e7 | |||
| 3d85d53e5d | |||
| 094a346539 | |||
| 162814f969 | |||
| e39b5c99f1 | |||
| 8883243aaa | |||
| 89511eecf1 | |||
| 2c304ca80d | |||
| bf4102e664 | |||
| b86153cee3 | |||
| 7985d277b3 | |||
| 752da5c2a5 | |||
| de4b8d547b | |||
| 1048ad1a01 | |||
| 4d11158d97 | |||
| 293b81cad2 | |||
| 65c38111f9 | |||
| ec8db379a6 | |||
| 1484b4ae9f | |||
| 4cecbf1654 | |||
| 234ba90e2b | |||
| bdd2244f75 | |||
| cd7ec8ac92 | |||
| cc5edbbbb2 | |||
| 94d9e34dd3 | |||
| 3dbf5038fa | |||
| 456a2f3bcf | |||
| 8e1fa52d14 | |||
| cbf2feb633 | |||
| afe8ee501c | |||
| 4644dab081 | |||
| b37a69d76c | |||
| 51bc6ce2e4 | |||
| 988ebc2248 | |||
| 9f31e95420 | |||
| 3a076e26f7 | |||
| e3e85fc6f3 | |||
| ad3a35b4c5 | |||
| 454caa3eec | |||
| 0ffe67ffed | |||
| 8eb46bbfb2 | |||
| d8e8b3c235 | |||
| 79f273348d | |||
| fc99081658 | |||
| aba14e6a43 | |||
| 8ebcef97ff | |||
| 00956a3770 | |||
| 11f3b7730c | |||
| f63e6394ac | |||
| bbca4c38df | |||
| 28f5d26719 | |||
| bf2620f041 | |||
| 870b82b541 | |||
| 1635d9fb78 | |||
| 20fb155e8c | |||
| da59c77ae2 | |||
| 0d0bdaa02e | |||
| 04cf5044da | |||
| b005cd0bbd | |||
| f5379d2047 | |||
| 98c247ec29 | |||
| 38e2f9138d | |||
| 3cc7d9b8c0 | |||
| 1ac9400712 | |||
| 10d5705b70 | |||
| 2d0d579735 | |||
| ac0f524722 | |||
| 2cd0e5f60b | |||
| d83502d054 | |||
| 9e539a7f59 | |||
| c60247f51f | |||
| 06321511ad | |||
| 2e7923cad0 | |||
| 3c66c27caa | |||
| 7f4bd6917e | |||
| b89376da55 | |||
| a1dd6521e8 | |||
| 0088f840fe | |||
| 1b698c896e | |||
| 04000f28e7 | |||
| 976a05f6eb | |||
| b15902bf44 | |||
| 5ac7529771 | |||
| bbf68c0d9d | |||
| eeb3dd3511 | |||
| 7b0ce11e46 | |||
| 8ef1d6a49c | |||
| 7db60f958d | |||
| 30043e072e | |||
| 5ee7606779 | |||
| 25409c5a5a | |||
| 51122dd287 | |||
| ec9159f983 | |||
| f3d77d1c21 | |||
| 1258fcaaf4 | |||
| 00fd60aaa8 | |||
| c7a7d0582a | |||
| b6e7acfb90 | |||
| 40eae298d5 | |||
| 09a9131a10 | |||
| c93c9f5c2a | |||
| 7f08adc23e | |||
| f41012080f | |||
| 786e9d351c | |||
| 3d2cf97fbf | |||
| 1fe6fb6739 | |||
| 6710eb5eb3 | |||
| 80b1d55683 | |||
| 1cebc4316b | |||
| 20895d6f3f | |||
| 65a4118d50 | |||
| 4857829aaa | |||
| 2ea4574caf | |||
| 102b74f9eb | |||
| 8a0d4dfa94 | |||
| b4e645862a | |||
| ea48506a32 | |||
| 23f0a29260 | |||
| 9249717cf4 | |||
| 4196dfc374 | |||
| 23af707b41 | |||
| 421088c3a0 | |||
| 749f1a7c00 | |||
| 344f9fcf05 | |||
| 4c971cd4da | |||
| 43d553dcfb | |||
| 66264f9a3d | |||
| 269f369541 | |||
| 1973019962 | |||
| fe515c4c1c | |||
| 14f0a0addb | |||
| 64a2d0221c | |||
| 0ef91c3ba8 | |||
| 2adcb7be71 | |||
| a332f2402a | |||
| 131a61c51b | |||
| 39d5dd89c5 | |||
| 341efe9a40 | |||
| 5ed6f89b4a | |||
| 4d609149d2 | |||
| 0d790505aa | |||
| a486536925 | |||
| e808fb424a | |||
| 6c54abeca7 | |||
| d24b8a094c | |||
| c46391420f | |||
| 68df7527f7 | |||
| 5a3c3d8210 | |||
| 95ceb49770 | |||
| 0bde58ffd7 | |||
| ccd9827b63 | |||
| db189cfb9f | |||
| 7527f181d5 | |||
| c05b418512 | |||
| e97d996fe4 | |||
| 0537b167ca | |||
| 40446201ff | |||
| fff6b35821 | |||
| 75f2d7583f | |||
| 1fd8d3b487 | |||
| a1216599ff | |||
| 8fff0e0fdf | |||
| 439727a84a | |||
| 3a18a6dddf | |||
| d7050c63ae | |||
| b7c88ec87d | |||
| 5985b62f60 | |||
| e7c29b989c | |||
| 2100e427d9 | |||
| 2550d6dc63 | |||
| ca72fae884 | |||
| 4fc1af14a7 | |||
| 1a30ec6da6 | |||
| e77d519482 | |||
| 59806eee38 | |||
| 5968b10b0b | |||
| e6f0103940 | |||
| cbaad3dbd9 | |||
| ee43a6a603 | |||
| 1ac1147ecb | |||
| 1edbc1f1f9 | |||
| 146b4c93ba | |||
| 94f90f457a | |||
| 6b7d56ac49 | |||
| 1635d7be8c | |||
| 992cd088cf | |||
| f6010b2a59 | |||
| 9222a5fd6d | |||
| 6f7fb6ba5a | |||
| a57a144f8e | |||
| 7b47e3225b | |||
| 6aa893e091 | |||
| 5aa03bcb0d | |||
| d7060025e0 | |||
| 00883016af | |||
| f0d8b614d0 | |||
| ddbd574643 | |||
| 5ea3777599 | |||
| a3949763f2 | |||
| 1b961a9ae2 | |||
| d9f6b268d3 | |||
| 934b91f65f | |||
| c3050231d1 | |||
| 4d7a01562e | |||
| 650eed7f72 | |||
| ec8614e8e4 | |||
| cb41b96a9e | |||
| 872b46a527 | |||
| b1c8613dbe | |||
| de6cd4f0d2 | |||
| aec2fb939f | |||
| 69293db804 | |||
| 61a7ebf980 | |||
| f14762b026 | |||
| 187d261400 | |||
| e905f7ff7c | |||
| aefc630d29 | |||
| a5e929ce36 | |||
| 1641d365f5 | |||
| 07d9cd8efe | |||
| 29868b2a05 | |||
| 691b6b88ea | |||
| 2ee1a00177 | |||
| 144cf2d040 | |||
| e1a308d151 | |||
| 601dfeeff9 | |||
| 2c9f2325e2 |
+2
-2
@@ -22,9 +22,9 @@ stages:
|
||||
variables:
|
||||
COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false"
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dintrospection=enabled"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v26"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v27"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v25"
|
||||
|
||||
|
||||
@@ -65,13 +65,13 @@ RUN dnf -y install \
|
||||
libxslt \
|
||||
mesa-dri-drivers \
|
||||
mesa-libEGL-devel \
|
||||
mesa-libGLES-devel \
|
||||
mesa-libwayland-egl-devel \
|
||||
ninja-build \
|
||||
pango-devel \
|
||||
pcre-devel \
|
||||
pcre-static \
|
||||
python3 \
|
||||
python3-gobject \
|
||||
python3-jinja2 \
|
||||
python3-pip \
|
||||
python3-pygments \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v26
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v27
|
||||
|
||||
# Enable sudo for wheel users
|
||||
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
|
||||
|
||||
@@ -8,7 +8,8 @@ builddir=$1
|
||||
backend=$2
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0
|
||||
export G_SLICE=always-malloc
|
||||
|
||||
case "${backend}" in
|
||||
x11)
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<!--
|
||||
Please, read the CONTRIBUTING.md guide on how to file a new issue.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
## Steps to reproduce
|
||||
<!--
|
||||
Please, explain the sequence of actions necessary to reproduce the
|
||||
bug
|
||||
-->
|
||||
|
||||
1. ...
|
||||
2. ...
|
||||
@@ -32,5 +41,8 @@
|
||||
## Additional information
|
||||
<!--
|
||||
- Screenshots or screen recordings are useful for visual errors
|
||||
- Attaching a screenshot or a video without explaining the current
|
||||
behavior and the actions necessary to reproduce the bug will lead
|
||||
to the bug being closed
|
||||
- Please report any warning or message printed on the terminal
|
||||
-->
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
<!--
|
||||
Please, read the CONTRIBUTING.md guide on how to file a new issue.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
## Steps to reproduce
|
||||
<!--
|
||||
Please, explain the sequence of actions necessary to reproduce the
|
||||
crash
|
||||
-->
|
||||
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
+9178
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ import subprocess
|
||||
stylesheets = [ 'gtk/theme/Adwaita/Adwaita.css',
|
||||
'gtk/theme/Adwaita/Adwaita-dark.css',
|
||||
'gtk/theme/HighContrast/HighContrast.css',
|
||||
'gtk/theme/HighContrast/HighContrast-inverse.css' ]
|
||||
'gtk/theme/HighContrast/HighContrast-dark.css' ]
|
||||
|
||||
sourceroot = os.environ.get('MESON_SOURCE_ROOT')
|
||||
distroot = os.environ.get('MESON_DIST_ROOT')
|
||||
|
||||
@@ -279,11 +279,31 @@ drag_prepare_texture (GtkDragSource *source,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
GtkSnapshot *snapshot;
|
||||
double width, height;
|
||||
GskRenderNode *node;
|
||||
GskRenderer *renderer;
|
||||
GdkTexture *texture;
|
||||
GdkContentProvider *ret;
|
||||
|
||||
if (!GDK_IS_PAINTABLE (paintable))
|
||||
return NULL;
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
snapshot = gtk_snapshot_new ();
|
||||
width = gdk_paintable_get_intrinsic_width (paintable);
|
||||
height = gdk_paintable_get_intrinsic_height (paintable);
|
||||
gdk_paintable_snapshot (paintable, snapshot, width, height);
|
||||
node = gtk_snapshot_free_to_node (snapshot);
|
||||
|
||||
renderer = gtk_native_get_renderer (gtk_widget_get_native (widget));
|
||||
texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
ret = gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, texture);
|
||||
|
||||
g_object_unref (texture);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<property name="right-margin">20</property>
|
||||
<property name="top-margin">20</property>
|
||||
<property name="bottom-margin">20</property>
|
||||
<property name="monospace">1</property>
|
||||
<property name="buffer">
|
||||
<object class="GtkTextBuffer" id="buffer"/>
|
||||
</property>
|
||||
|
||||
@@ -700,6 +700,16 @@ out:
|
||||
g_free (source_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
dark_mode_cb (GtkToggleButton *button,
|
||||
GParamSpec *pspec,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
g_object_set (gtk_widget_get_settings (GTK_WIDGET (self)),
|
||||
"gtk-application-prefer-dark-theme", gtk_toggle_button_get_active (button),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_finalize (GObject *object)
|
||||
{
|
||||
@@ -814,6 +824,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
@@ -910,6 +921,26 @@ node_editor_window_init (NodeEditorWindow *self)
|
||||
self->text_buffer = gtk_text_buffer_new (self->tag_table);
|
||||
g_signal_connect (self->text_buffer, "changed", G_CALLBACK (text_changed), self);
|
||||
gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->text_view), self->text_buffer);
|
||||
|
||||
/* Default */
|
||||
gtk_text_buffer_set_text (self->text_buffer,
|
||||
"shadow {\n"
|
||||
" child: texture {\n"
|
||||
" bounds: 0 0 128 128;\n"
|
||||
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.Devel.svg\");\n"
|
||||
" }\n"
|
||||
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"transform {\n"
|
||||
" child: text {\n"
|
||||
" color: rgb(46,52,54);\n"
|
||||
" font: \"Cantarell Bold 11\";\n"
|
||||
" glyphs: \"GTK Node Editor\";\n"
|
||||
" offset: 8 14.418;\n"
|
||||
" }\n"
|
||||
" transform: translate(0, 140);\n"
|
||||
"}", -1);
|
||||
}
|
||||
|
||||
NodeEditorWindow *
|
||||
|
||||
@@ -139,6 +139,15 @@
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkToggleButton" id="dark_bg_button">
|
||||
<property name="valign">center</property>
|
||||
<property name="has-frame">0</property>
|
||||
<property name="icon-name">display-brightness-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Use a dark background</property>
|
||||
<signal name="notify::active" handler="dark_mode_cb" swapped="0"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
||||
@@ -18,9 +18,9 @@ Length
|
||||
Percentage
|
||||
: %, calc()
|
||||
Angle
|
||||
: deg | grad | turn, calc()
|
||||
: deg, grad, turn, calc()
|
||||
Time
|
||||
: s | ms, calc()
|
||||
: s, ms, calc()
|
||||
|
||||
Length values with the em or ex units are resolved using the font
|
||||
size value, unless they occur in setting the font-size itself, in
|
||||
@@ -32,7 +32,7 @@ not quite the same as the CSS definition of rem.
|
||||
The calc() notation adds considerable expressive power. There are limits
|
||||
on what types can be combined in such an expression (e.g. it does not make
|
||||
sense to add a number and a time). For the full details, see the
|
||||
[CSS3 VAlues and Units](https://www.w3.org/TR/css3-values/#calc-notation)
|
||||
[CSS3 Values and Units](https://www.w3.org/TR/css3-values/#calc-notation)
|
||||
spec.
|
||||
|
||||
A common pattern among shorthand properties (called 'four sides') is one
|
||||
@@ -80,6 +80,31 @@ and in some cases a number as arguments.
|
||||
|
||||
## Images
|
||||
|
||||
CSS allows to specify images in various forms, the most simple one being
|
||||
a url for an image file. Beyond that, images can be specified as
|
||||
|
||||
`linear-gradient(Angle, ColorStops)`
|
||||
`repeating-linear-gradient(Angle, ColorStops)`
|
||||
: creates a linear gradient.
|
||||
|
||||
`radial-gradient(Shape, ColorStops)`
|
||||
`repeating-radial-gradient(Shape, ColorStops)`
|
||||
: creates a radial gradient.
|
||||
|
||||
`conic-gradient(Angle, ColorStops)`
|
||||
: creates a conic gradient.
|
||||
|
||||
`cross-fade(Percentage Image,…)`
|
||||
: combines two or more images.
|
||||
|
||||
`image(Image,… Color)`
|
||||
: falls back to the first valid image, or to a solid color.
|
||||
|
||||
`filter(Image, Filters)`
|
||||
: applies filters to an image.
|
||||
|
||||
For more details, see [CSS Image Level 4](https://www.w3.org/TR/css-images-4/).
|
||||
|
||||
GTK extends the CSS syntax for images and also uses it for specifying icons.
|
||||
To load a themed icon, use
|
||||
|
||||
@@ -151,7 +176,7 @@ done with
|
||||
|caret-color|[CSS Basic User Interface Level 3](https://www.w3.org/TR/css3-ui/#caret-color) | CSS allows an auto value |
|
||||
|-gtk-secondary-caret-color|[Color](https://www.w3.org/TR/css-color-3/#valuea-def-color) | used for the secondary caret in bidirectional text |
|
||||
|letter-spacing| [CSS Text Level 3](https://www.w3.org/TR/css3-text/#letter-spacing) | |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | CSS allows overline |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | |
|
||||
|text-decoration-color| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-color-property) | |
|
||||
|text-decoration-style| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-style-property) | CSS allows dashed and dotted |
|
||||
|text-shadow| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-shadow-property) | |
|
||||
@@ -159,11 +184,12 @@ done with
|
||||
|-gtk-icon-source| [Image](https://www.w3.org/TR/css-backgrounds-3/#typedef-image), `builtin` or `none` | used for builtin icons in buttons and expanders |
|
||||
|-gtk-icon-size| [Length](https://www.w3.org/TR/css3-values/#length-value) | size used for builtin icons in buttons and expanders |
|
||||
|-gtk-icon-style| `requested`, `regular` or `symbolic` | preferred style for application-loaded icons |
|
||||
|-gtk-icon-transform| [Transform list](https://drafts.csswg.org/css-transforms-1/#typedef-transform-list) or `none` | applied to builtin and application-loaded icons |
|
||||
|-gtk-icon-transform| [Transform list](https://www.w3.org/TR/css-transforms-1/#typedef-transform-list) or `none` | applied to builtin and application-loaded icons |
|
||||
|-gtk-icon-palette| Color palette, as explained above | used to recolor symbolic icons |
|
||||
|-gtk-icon-shadow| [Shadow](https://www.w3.org/TR/css-backgrounds-3/#typedef-shadow) or `none` | applied to builtin and application-loaded icons |
|
||||
|-gtk-icon-filter| [Filter value list](https://www.w3.org/TR/filter-effects-1/#typedef-filter-value-list) or `none` | applied to builtin and application-loaded icons |
|
||||
|transform| [CSS Transforms Level 2](https://drafts.csswg.org/css-transforms-2/) | |
|
||||
|transform| [CSS Transforms Level 1](https://www.w3.org/TR/css-transforms-1/#transform-property) | |
|
||||
|transform-origin| [CSS Transforms Level 1](https://www.w3.org/TR/css-transforms-1/#transform-origin-property) | CSS allows specifying a z component|
|
||||
|min-width| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#min-width) | CSS allows percentages |
|
||||
|min-height| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#min-height) | CSS allows percentages |
|
||||
|margin-top| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#margin-top) | CSS allows percentages or auto |
|
||||
@@ -217,7 +243,7 @@ done with
|
||||
|background-size| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-size) | |
|
||||
|background-position| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-position) | |
|
||||
|background-repeat| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-repeat) | |
|
||||
|background-image| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-image) | not supported: urls without quotes, colors in crossfades |
|
||||
|background-image| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-image) | not supported: urls without quotes |
|
||||
|box-shadow| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#box-shadow) | |
|
||||
|background-blend-mode| [CSS Compositing and Blending Level 1](https://www.w3.org/TR/compositing-1/#propdef-background-blend-mode) | only affects multiple backgrounds |
|
||||
|background| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background) | |
|
||||
@@ -235,4 +261,4 @@ done with
|
||||
|animation-delay| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation-delay) | |
|
||||
|animation-fill-mode| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation-fill-mode) | |
|
||||
|animation| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation) | |
|
||||
|border-spacing| [CSS Table Level 3](https://www.w3.org/TR/css-tables-3/#border-spacing-property) | respected by GtkBox and GtkGrid |
|
||||
|border-spacing| [CSS Table Level 3](https://www.w3.org/TR/css-tables-3/#border-spacing-property) | respected by GtkBoxLayout, GtkGridLayout, GtkCenterLayout |
|
||||
|
||||
@@ -343,20 +343,19 @@ Many widgets, like buttons, do all their drawing themselves. You just tell
|
||||
them the label you want to see, and they figure out what font to use, draw
|
||||
the button outline and focus rectangle, etc. Sometimes, it is necessary to
|
||||
do some custom drawing. In that case, a GtkDrawingArea might be the right
|
||||
widget to use. It offers a canvas on which you can draw by connecting to
|
||||
the ::draw signal.
|
||||
widget to use. It offers a canvas on which you can draw by setting its
|
||||
draw function.
|
||||
|
||||
The contents of a widget often need to be partially or fully redrawn,
|
||||
e.g. when another window is moved and uncovers part of the widget, or
|
||||
when the window containing it is resized. It is also possible to explicitly
|
||||
cause part or all of the widget to be redrawn, by calling
|
||||
gtk_widget_queue_draw() or its variants. GTK takes care of most of the
|
||||
details by providing a ready-to-use cairo context to the ::draw signal
|
||||
handler.
|
||||
cause a widget to be redrawn, by calling gtk_widget_queue_draw(). GTK takes
|
||||
care of most of the details by providing a ready-to-use cairo context to the
|
||||
draw function.
|
||||
|
||||
The following example shows a ::draw signal handler. It is a bit more
|
||||
complicated than the previous examples, since it also demonstrates
|
||||
input event handling by means of event controllers.
|
||||
The following example shows how to use a draw function with GtkDrawingArea.
|
||||
It is a bit more complicated than the previous examples, since it also
|
||||
demonstrates input event handling with event controllers.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1831,7 +1831,6 @@ GtkIMContextSimple
|
||||
gtk_im_context_simple_new
|
||||
gtk_im_context_simple_add_table
|
||||
gtk_im_context_simple_add_compose_file
|
||||
GTK_MAX_COMPOSE_LEN
|
||||
<SUBSECTION Standard>
|
||||
GTK_IM_CONTEXT_SIMPLE
|
||||
GTK_IS_IM_CONTEXT_SIMPLE
|
||||
|
||||
@@ -1079,6 +1079,11 @@ that wants to override the default handling, you can provide an
|
||||
implementation of the default.activate action in your widgets' action
|
||||
groups.
|
||||
|
||||
### Stop using gtk_widget_grab_default()
|
||||
|
||||
The function gtk_widget_grab_default() has been removed. If you need
|
||||
to mark a widget as default, use gtk_window_set_default_widget() directly.
|
||||
|
||||
### Stop setting ::has-default and ::has-focus in .ui files
|
||||
|
||||
The special handling for the ::has-default and ::has-focus properties
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "exampleapp.h"
|
||||
#include "exampleappwin.h"
|
||||
|
||||
struct _ExampleAppWindow
|
||||
{
|
||||
GtkApplicationWindow parent;
|
||||
|
||||
GSettings *settings;
|
||||
GtkWidget *stack;
|
||||
GtkWidget *search;
|
||||
GtkWidget *searchbar;
|
||||
GtkWidget *searchentry;
|
||||
GtkWidget *gears;
|
||||
GtkWidget *sidebar;
|
||||
GtkWidget *words;
|
||||
GtkWidget *lines;
|
||||
GtkWidget *lines_label;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
static void
|
||||
search_text_changed (GtkEntry *entry,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
const char *text;
|
||||
GtkWidget *tab;
|
||||
GtkWidget *view;
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter start, match_start, match_end;
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
|
||||
if (text[0] == '\0')
|
||||
return;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
/* Very simple-minded search implementation */
|
||||
gtk_text_buffer_get_start_iter (buffer, &start);
|
||||
if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
|
||||
&match_start, &match_end, NULL))
|
||||
{
|
||||
gtk_text_buffer_select_range (buffer, &match_start, &match_end);
|
||||
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
|
||||
0.0, FALSE, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_word (GtkButton *button,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
const char *word;
|
||||
|
||||
word = gtk_button_get_label (button);
|
||||
gtk_editable_set_text (GTK_EDITABLE (win->searchentry), word);
|
||||
}
|
||||
|
||||
static void
|
||||
update_words (ExampleAppWindow *win)
|
||||
{
|
||||
GHashTable *strings;
|
||||
GHashTableIter iter;
|
||||
GtkWidget *tab, *view, *row;
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter start, end;
|
||||
char *word, *key;
|
||||
GtkWidget *child;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
gtk_text_buffer_get_start_iter (buffer, &start);
|
||||
while (!gtk_text_iter_is_end (&start))
|
||||
{
|
||||
while (!gtk_text_iter_starts_word (&start))
|
||||
{
|
||||
if (!gtk_text_iter_forward_char (&start))
|
||||
goto done;
|
||||
}
|
||||
end = start;
|
||||
if (!gtk_text_iter_forward_word_end (&end))
|
||||
goto done;
|
||||
word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||
g_hash_table_add (strings, g_utf8_strdown (word, -1));
|
||||
g_free (word);
|
||||
start = end;
|
||||
}
|
||||
|
||||
done:
|
||||
while ((child = gtk_widget_get_first_child (win->words)))
|
||||
gtk_list_box_remove (GTK_LIST_BOX (win->words), child);
|
||||
|
||||
g_hash_table_iter_init (&iter, strings);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
|
||||
{
|
||||
row = gtk_button_new_with_label (key);
|
||||
g_signal_connect (row, "clicked",
|
||||
G_CALLBACK (find_word), win);
|
||||
gtk_box_append (GTK_BOX (win->words), row);
|
||||
}
|
||||
|
||||
g_hash_table_unref (strings);
|
||||
}
|
||||
|
||||
static void
|
||||
update_lines (ExampleAppWindow *win)
|
||||
{
|
||||
GtkWidget *tab, *view;
|
||||
GtkTextBuffer *buffer;
|
||||
int count;
|
||||
char *lines;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
count = gtk_text_buffer_get_line_count (buffer);
|
||||
lines = g_strdup_printf ("%d", count);
|
||||
gtk_label_set_text (GTK_LABEL (win->lines), lines);
|
||||
g_free (lines);
|
||||
}
|
||||
|
||||
static void
|
||||
visible_child_changed (GObject *stack,
|
||||
GParamSpec *pspec,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
if (gtk_widget_in_destruction (GTK_WIDGET (stack)))
|
||||
return;
|
||||
|
||||
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (win->searchbar), FALSE);
|
||||
update_words (win);
|
||||
update_lines (win);
|
||||
}
|
||||
|
||||
static void
|
||||
words_changed (GObject *sidebar,
|
||||
GParamSpec *pspec,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
update_words (win);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_window_init (ExampleAppWindow *win)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GMenuModel *menu;
|
||||
GAction *action;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (win));
|
||||
win->settings = g_settings_new ("org.gtk.exampleapp");
|
||||
|
||||
g_settings_bind (win->settings, "transition",
|
||||
win->stack, "transition-type",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_settings_bind (win->settings, "show-words",
|
||||
win->sidebar, "reveal-child",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_object_bind_property (win->search, "active",
|
||||
win->searchbar, "search-mode-enabled",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
|
||||
g_signal_connect (win->sidebar, "notify::reveal-child",
|
||||
G_CALLBACK (words_changed), win);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
|
||||
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
|
||||
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
|
||||
g_object_unref (builder);
|
||||
|
||||
action = g_settings_create_action (win->settings, "show-words");
|
||||
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||
g_object_unref (action);
|
||||
|
||||
action = (GAction*) g_property_action_new ("show-lines", win->lines, "visible");
|
||||
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||
g_object_unref (action);
|
||||
|
||||
g_object_bind_property (win->lines, "visible",
|
||||
win->lines_label, "visible",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
g_object_set (gtk_settings_get_default (), "gtk-shell-shows-app-menu", FALSE, NULL);
|
||||
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_window_dispose (GObject *object)
|
||||
{
|
||||
ExampleAppWindow *win;
|
||||
|
||||
win = EXAMPLE_APP_WINDOW (object);
|
||||
|
||||
g_clear_object (&win->settings);
|
||||
|
||||
G_OBJECT_CLASS (example_app_window_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_window_class_init (ExampleAppWindowClass *class)
|
||||
{
|
||||
G_OBJECT_CLASS (class)->dispose = example_app_window_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||
"/org/gtk/exampleapp/window.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines_label);
|
||||
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), visible_child_changed);
|
||||
}
|
||||
|
||||
ExampleAppWindow *
|
||||
example_app_window_new (ExampleApp *app)
|
||||
{
|
||||
return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
example_app_window_open (ExampleAppWindow *win,
|
||||
GFile *file)
|
||||
{
|
||||
char *basename;
|
||||
GtkWidget *scrolled, *view;
|
||||
char *contents;
|
||||
gsize length;
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextTag *tag;
|
||||
GtkTextIter start_iter, end_iter;
|
||||
|
||||
basename = g_file_get_basename (file);
|
||||
|
||||
scrolled = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_hexpand (scrolled, TRUE);
|
||||
gtk_widget_set_vexpand (scrolled, TRUE);
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
|
||||
gtk_stack_add_titled (GTK_STACK (win->stack), scrolled, basename, basename);
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
|
||||
{
|
||||
gtk_text_buffer_set_text (buffer, contents, length);
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
|
||||
g_settings_bind (win->settings, "font",
|
||||
tag, "font",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
gtk_text_buffer_get_start_iter (buffer, &start_iter);
|
||||
gtk_text_buffer_get_end_iter (buffer, &end_iter);
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter);
|
||||
|
||||
g_free (basename);
|
||||
|
||||
gtk_widget_set_sensitive (win->search, TRUE);
|
||||
|
||||
update_words (win);
|
||||
update_lines (win);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ stash_desktop_startup_notification_id (void)
|
||||
if (!g_utf8_validate (desktop_startup_id, -1, NULL))
|
||||
g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
|
||||
else
|
||||
startup_notification_id = g_strdup (desktop_startup_id ? desktop_startup_id : "");
|
||||
startup_notification_id = g_strdup (desktop_startup_id);
|
||||
}
|
||||
|
||||
/* Clear the environment variable so it won't be inherited by
|
||||
|
||||
+29
-6
@@ -92,6 +92,7 @@ enum {
|
||||
PROP_MAPPED,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_SCALE_FACTOR,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
@@ -551,6 +552,13 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SCALE_FACTOR] =
|
||||
g_param_spec_int ("scale-factor",
|
||||
P_("Scale factor"),
|
||||
P_("Scale factor"),
|
||||
1, G_MAXINT, 1,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, properties);
|
||||
|
||||
/**
|
||||
@@ -782,6 +790,10 @@ gdk_surface_get_property (GObject *object,
|
||||
g_value_set_int (value, surface->height);
|
||||
break;
|
||||
|
||||
case PROP_SCALE_FACTOR:
|
||||
g_value_set_int (value, gdk_surface_get_scale_factor (surface));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -2545,8 +2557,7 @@ gdk_surface_get_frame_clock (GdkSurface *surface)
|
||||
* value can be used to determine whether to use a pixel resource
|
||||
* with higher resolution data.
|
||||
*
|
||||
* The scale of a surface may change during runtime, if this happens
|
||||
* a configure event will be sent to the toplevel surface.
|
||||
* The scale of a surface may change during runtime.
|
||||
*
|
||||
* Returns: the scale factor
|
||||
*/
|
||||
@@ -2949,8 +2960,8 @@ gdk_surface_request_motion (GdkSurface *surface)
|
||||
* gdk_surface_translate_coordinates:
|
||||
* @from: the origin surface
|
||||
* @to: the target surface
|
||||
* @x: coordinates to translate
|
||||
* @y: coordinates to translate
|
||||
* @x: (inout): coordinates to translate
|
||||
* @y: (inout): coordinates to translate
|
||||
*
|
||||
* Translates the given coordinates from being
|
||||
* relative to the @from surface to being relative
|
||||
@@ -2969,9 +2980,18 @@ gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
double *x,
|
||||
double *y)
|
||||
{
|
||||
double in_x, in_y, out_x, out_y;
|
||||
int x1, y1, x2, y2;
|
||||
GdkSurface *f, *t;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (from), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (to), FALSE);
|
||||
g_return_val_if_fail (x != NULL, FALSE);
|
||||
g_return_val_if_fail (y != NULL, FALSE);
|
||||
|
||||
in_x = *x;
|
||||
in_y = *y;
|
||||
|
||||
x1 = 0;
|
||||
y1 = 0;
|
||||
f = from;
|
||||
@@ -2995,8 +3015,11 @@ gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
if (f != t)
|
||||
return FALSE;
|
||||
|
||||
*x += x1 - x2;
|
||||
*y += y1 - y2;
|
||||
out_x = in_x + (x1 - x2);
|
||||
out_y = in_y + (y1 - y2);
|
||||
|
||||
*x = out_x;
|
||||
*y = out_y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -149,12 +149,6 @@ gdk_toplevel_size_validate (GdkToplevelSize *size)
|
||||
{
|
||||
int geometry_width, geometry_height;
|
||||
|
||||
if (size->min_width > size->bounds_width ||
|
||||
size->min_height > size->bounds_height)
|
||||
g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds bounds (%d, %d)",
|
||||
size->min_width, size->min_height,
|
||||
size->bounds_width, size->bounds_height);
|
||||
|
||||
geometry_width = size->width;
|
||||
geometry_height = size->height;
|
||||
if (size->shadow.is_valid)
|
||||
@@ -162,15 +156,4 @@ gdk_toplevel_size_validate (GdkToplevelSize *size)
|
||||
geometry_width -= size->shadow.left + size->shadow.right;
|
||||
geometry_height -= size->shadow.top + size->shadow.bottom;
|
||||
}
|
||||
if (geometry_width > size->bounds_width ||
|
||||
geometry_height > size->bounds_height)
|
||||
g_warning ("GdkToplevelSize: geometry size (%d, %d) exceeds bounds (%d, %d)",
|
||||
size->width, size->height,
|
||||
size->bounds_width, size->bounds_height);
|
||||
|
||||
if (size->min_width > size->width ||
|
||||
size->min_height > size->height)
|
||||
g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds size (%d, %d)",
|
||||
size->min_width, size->min_height,
|
||||
size->width, size->height);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,14 @@
|
||||
*/
|
||||
#define GDK_VERSION_4_0 (G_ENCODE_VERSION (4, 0))
|
||||
|
||||
/**
|
||||
* GDK_VERSION_4_2:
|
||||
*
|
||||
* A macro that evaluates to the 4.2 version of GDK, in a format
|
||||
* that can be used by the C pre-processor.
|
||||
*/
|
||||
#define GDK_VERSION_4_2 (G_ENCODE_VERSION (4, 2))
|
||||
|
||||
|
||||
/* evaluates to the current stable version; for development cycles,
|
||||
* this means the next stable target, with a hard backstop to the
|
||||
@@ -175,4 +183,19 @@
|
||||
# define GDK_DEPRECATED_IN_4_0_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
|
||||
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_4_2
|
||||
# define GDK_AVAILABLE_IN_4_2 GDK_UNAVAILABLE(4, 2)
|
||||
#else
|
||||
# define GDK_AVAILABLE_IN_4_2 _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_2
|
||||
# define GDK_DEPRECATED_IN_4_2 GDK_DEPRECATED
|
||||
# define GDK_DEPRECATED_IN_4_2_FOR(f) GDK_DEPRECATED_FOR(f)
|
||||
#else
|
||||
# define GDK_DEPRECATED_IN_4_2 _GDK_EXTERN
|
||||
# define GDK_DEPRECATED_IN_4_2_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#endif /* __GDK_VERSION_MACROS_H__ */
|
||||
|
||||
@@ -547,6 +547,20 @@ _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
|
||||
_gdk_macos_display_clear_sorting (self);
|
||||
}
|
||||
|
||||
/* Raises a transient window.
|
||||
*/
|
||||
static void
|
||||
raise_transient (GdkMacosSurface *surface)
|
||||
{
|
||||
GdkMacosSurface *parent_surface = GDK_MACOS_SURFACE (GDK_SURFACE (surface)->transient_for);
|
||||
|
||||
NSWindow *parent = _gdk_macos_surface_get_native (parent_surface);
|
||||
NSWindow *window = _gdk_macos_surface_get_native (surface);
|
||||
|
||||
[parent removeChildWindow:window];
|
||||
[parent addChildWindow:window ordered:NSWindowAbove];
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface)
|
||||
@@ -559,6 +573,9 @@ _gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
|
||||
|
||||
g_queue_push_head_link (&self->main_surfaces, &surface->main);
|
||||
|
||||
if (GDK_SURFACE (surface)->transient_for)
|
||||
raise_transient (surface);
|
||||
|
||||
_gdk_macos_display_clear_sorting (self);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
#define MIN_SYSTEM_BELL_DELAY_MS 20
|
||||
|
||||
#define GTK_SHELL1_VERSION 3
|
||||
#define GTK_SHELL1_VERSION 4
|
||||
#define OUTPUT_VERSION_WITH_DONE 2
|
||||
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
|
||||
|
||||
@@ -1350,21 +1350,23 @@ _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display,
|
||||
data->buffer = NULL;
|
||||
data->scale = scale;
|
||||
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width*scale);
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width * scale);
|
||||
|
||||
data->pool = create_shm_pool (display->shm,
|
||||
height*scale*stride,
|
||||
height * scale * stride,
|
||||
&data->buf_length,
|
||||
&data->buf);
|
||||
if (G_UNLIKELY (data->pool == NULL))
|
||||
g_error ("Unable to create shared memory pool");
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data->buf,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
width*scale,
|
||||
height*scale,
|
||||
width * scale,
|
||||
height * scale,
|
||||
stride);
|
||||
|
||||
data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
|
||||
width*scale, height*scale,
|
||||
width * scale, height * scale,
|
||||
stride, WL_SHM_FORMAT_ARGB8888);
|
||||
|
||||
cairo_surface_set_user_data (surface, &gdk_wayland_shm_surface_cairo_key,
|
||||
|
||||
@@ -389,10 +389,13 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
|
||||
int scale)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
gboolean width_changed, height_changed, scale_changed;
|
||||
|
||||
if ((surface->width == width) &&
|
||||
(surface->height == height) &&
|
||||
(impl->scale == scale))
|
||||
width_changed = surface->width != width;
|
||||
height_changed = surface->height != height;
|
||||
scale_changed = impl->scale != scale;
|
||||
|
||||
if (!width_changed && !height_changed && !scale_changed)
|
||||
return;
|
||||
|
||||
surface->width = width;
|
||||
@@ -405,6 +408,13 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
|
||||
wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
|
||||
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
|
||||
if (width_changed)
|
||||
g_object_notify (G_OBJECT (surface), "width");
|
||||
if (height_changed)
|
||||
g_object_notify (G_OBJECT (surface), "height");
|
||||
if (scale_changed)
|
||||
g_object_notify (G_OBJECT (surface), "scale-factor");
|
||||
}
|
||||
|
||||
static const char *
|
||||
@@ -2213,6 +2223,24 @@ gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel)
|
||||
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
|
||||
|
||||
g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
|
||||
|
||||
if (!display_wayland->server_decoration_manager)
|
||||
return;
|
||||
impl->display_server.server_decoration =
|
||||
org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
|
||||
impl->display_server.wl_surface);
|
||||
if (impl->display_server.server_decoration)
|
||||
org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
|
||||
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel)
|
||||
{
|
||||
@@ -2939,7 +2967,11 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
|
||||
|
||||
if (impl->display_server.gtk_surface)
|
||||
{
|
||||
gtk_surface1_destroy (impl->display_server.gtk_surface);
|
||||
if (display_wayland->gtk_shell_version >=
|
||||
GTK_SURFACE1_RELEASE_SINCE_VERSION)
|
||||
gtk_surface1_release (impl->display_server.gtk_surface);
|
||||
else
|
||||
gtk_surface1_destroy (impl->display_server.gtk_surface);
|
||||
impl->display_server.gtk_surface = NULL;
|
||||
impl->application.was_set = FALSE;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ void gdk_wayland_toplevel_set_dbus_properties (GdkTopl
|
||||
const char *unique_bus_name);
|
||||
|
||||
void gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel);
|
||||
|
||||
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<protocol name="gtk">
|
||||
|
||||
<interface name="gtk_shell1" version="3">
|
||||
<interface name="gtk_shell1" version="4">
|
||||
<description summary="gtk specific extensions">
|
||||
gtk_shell is a protocol extension providing additional features for
|
||||
clients implementing it.
|
||||
@@ -35,7 +35,7 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="gtk_surface1" version="3">
|
||||
<interface name="gtk_surface1" version="4">
|
||||
<request name="set_dbus_properties">
|
||||
<arg name="application_id" type="string" allow-null="true"/>
|
||||
<arg name="app_menu_path" type="string" allow-null="true"/>
|
||||
@@ -82,6 +82,9 @@
|
||||
<request name="request_focus" since="3">
|
||||
<arg name="startup_id" type="string" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
<request name="release" type="destructor" since="4"/>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
|
||||
@@ -31,46 +31,6 @@
|
||||
|
||||
G_DEFINE_TYPE (GdkWin32CairoContext, gdk_win32_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
|
||||
|
||||
static cairo_surface_t *
|
||||
create_cairo_surface_for_layered_window (GdkWin32Surface *impl,
|
||||
int width,
|
||||
int height,
|
||||
int scale)
|
||||
{
|
||||
if (width > impl->dib_width ||
|
||||
height > impl->dib_height)
|
||||
{
|
||||
cairo_surface_t *new_cache;
|
||||
|
||||
impl->dib_width = MAX (impl->dib_width, MAX (width, 1));
|
||||
impl->dib_height = MAX (impl->dib_height, MAX (height, 1));
|
||||
/* Create larger cache surface, copy old cache surface over it */
|
||||
new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
|
||||
impl->dib_width,
|
||||
impl->dib_height);
|
||||
|
||||
if (impl->cache_surface)
|
||||
{
|
||||
cairo_t *cr = cairo_create (new_cache);
|
||||
cairo_set_source_surface (cr, impl->cache_surface, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_flush (new_cache);
|
||||
|
||||
cairo_surface_destroy (impl->cache_surface);
|
||||
}
|
||||
|
||||
impl->cache_surface = new_cache;
|
||||
|
||||
cairo_surface_set_device_scale (impl->cache_surface,
|
||||
scale,
|
||||
scale);
|
||||
}
|
||||
|
||||
return cairo_surface_reference (impl->cache_surface);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
create_cairo_surface_for_surface (GdkSurface *surface,
|
||||
int scale)
|
||||
@@ -114,22 +74,11 @@ gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
width = MAX (width, 1);
|
||||
height = MAX (height, 1);
|
||||
|
||||
if (self->layered)
|
||||
self->window_surface = create_cairo_surface_for_layered_window (impl, width, height, scale);
|
||||
else
|
||||
self->window_surface = create_cairo_surface_for_surface (surface, scale);
|
||||
self->window_surface = create_cairo_surface_for_surface (surface, scale);
|
||||
|
||||
if (self->layered ||
|
||||
!self->double_buffered)
|
||||
{
|
||||
/* Layered windows paint on the window_surface (which is itself
|
||||
* an in-memory cache that the window maintains, since layered windows
|
||||
* do not support incremental redraws.
|
||||
* Non-double-buffered windows paint on the window surface directly
|
||||
* as well.
|
||||
*/
|
||||
self->paint_surface = cairo_surface_reference (self->window_surface);
|
||||
}
|
||||
if (!self->double_buffered)
|
||||
/* Non-double-buffered windows paint on the window surface directly */
|
||||
self->paint_surface = cairo_surface_reference (self->window_surface);
|
||||
else
|
||||
{
|
||||
if (width > self->db_width ||
|
||||
@@ -153,11 +102,10 @@ gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
}
|
||||
|
||||
/* Clear the paint region.
|
||||
* For non-double-buffered and for layered rendering we must
|
||||
* clear it, otherwise semi-transparent pixels will "add up"
|
||||
* with each repaint.
|
||||
* For double-buffered rendering we must clear the old pixels
|
||||
* from the DB cache surface that we're going to use as a buffer.
|
||||
* For non-double-buffered rendering we must clear it, otherwise
|
||||
* semi-transparent pixels will "add up" with each repaint.
|
||||
* We must also clear the old pixels from the DB cache surface
|
||||
* that we're going to use as a buffer.
|
||||
*/
|
||||
cr = cairo_create (self->paint_surface);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 00);
|
||||
@@ -184,12 +132,10 @@ gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
|
||||
* to be here.
|
||||
*/
|
||||
|
||||
/* Layered windows have their own, special copying section
|
||||
* further down. For double-buffered windows we need to blit
|
||||
/* For double-buffered windows we need to blit
|
||||
* the DB buffer contents into the window itself.
|
||||
*/
|
||||
if (!self->layered &&
|
||||
self->double_buffered)
|
||||
if (self->double_buffered)
|
||||
{
|
||||
cairo_t *cr;
|
||||
|
||||
@@ -207,18 +153,6 @@ gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
cairo_surface_flush (self->window_surface);
|
||||
|
||||
/* Update layered window, updating its contents, size and position
|
||||
* in one call.
|
||||
*/
|
||||
if (self->layered)
|
||||
{
|
||||
RECT client_rect;
|
||||
|
||||
/* Get the position/size of the window that GDK wants. */
|
||||
_gdk_win32_get_window_client_area_rect (surface, scale, &client_rect);
|
||||
_gdk_win32_update_layered_window_from_cache (surface, &client_rect, TRUE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->paint_surface, cairo_surface_destroy);
|
||||
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
|
||||
}
|
||||
|
||||
@@ -44,10 +44,6 @@ struct _GdkWin32CairoContext
|
||||
* code that is unaffected by this flag.
|
||||
*/
|
||||
guint double_buffered : 1;
|
||||
/* Re-set to the same value as GdkSurfaceImplWin32->layered
|
||||
* every frame (since layeredness can change at runtime).
|
||||
*/
|
||||
guint layered : 1;
|
||||
|
||||
/* The a surface for double-buffering. We keep it
|
||||
* around between repaints, and only re-allocate it
|
||||
@@ -56,12 +52,11 @@ struct _GdkWin32CairoContext
|
||||
int db_width;
|
||||
int db_height;
|
||||
|
||||
/* Surface for the window DC (in non-layered mode).
|
||||
* A reference of the cache surface (in layered mode). */
|
||||
/* Surface for the window DC */
|
||||
cairo_surface_t *window_surface;
|
||||
/* A reference to db_surface (when double-buffering).
|
||||
* When not using double-buffering or in layered mode
|
||||
* this is a reference to window_surface.
|
||||
* When not using double-buffering this is a reference
|
||||
* to window_surface.
|
||||
*/
|
||||
cairo_surface_t *paint_surface;
|
||||
};
|
||||
|
||||
@@ -2113,7 +2113,6 @@ gdk_drag_anim_timeout (gpointer data)
|
||||
(drag->start_y - drag->util_data.last_y) * t -
|
||||
drag->hot_y);
|
||||
gdk_win32_surface_move (drag->drag_surface, x, y);
|
||||
gdk_win32_surface_set_opacity (drag->drag_surface, 1.0 - f);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -1495,15 +1495,6 @@ handle_dpi_changed (GdkSurface *window,
|
||||
|
||||
monitor = gdk_display_get_monitor_at_surface (display, window);
|
||||
gdk_monitor_set_scale_factor (monitor, impl->surface_scale);
|
||||
|
||||
if (impl->layered)
|
||||
{
|
||||
/* We only need to set the cairo surface device scale here ourselves for layered windows */
|
||||
if (impl->cache_surface != NULL)
|
||||
cairo_surface_set_device_scale (impl->cache_surface,
|
||||
impl->surface_scale,
|
||||
impl->surface_scale);
|
||||
}
|
||||
}
|
||||
|
||||
_gdk_win32_adjust_client_rect (window, rect);
|
||||
|
||||
@@ -88,19 +88,6 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (surface != NULL)
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
if (impl->suppress_layered > 0)
|
||||
impl->suppress_layered--;
|
||||
|
||||
/* If we don't have any surface that forces layered windows off,
|
||||
* trigger update_style_bits() to enable layered windows again
|
||||
*/
|
||||
if (impl->suppress_layered == 0)
|
||||
_gdk_win32_surface_update_style_bits (surface);
|
||||
}
|
||||
G_OBJECT_CLASS (gdk_win32_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -1001,17 +988,6 @@ gdk_win32_gl_context_realize (GdkGLContext *context,
|
||||
/* set whether we are using GLES */
|
||||
gdk_gl_context_set_use_es (context, use_es);
|
||||
|
||||
/* OpenGL does not work with WS_EX_LAYERED enabled, so we need to
|
||||
* disable WS_EX_LAYERED when we acquire a valid HGLRC
|
||||
*/
|
||||
impl->suppress_layered++;
|
||||
|
||||
/* if this is the first time a GL context is acquired for the surface,
|
||||
* disable layered windows by triggering update_style_bits()
|
||||
*/
|
||||
if (impl->suppress_layered == 1)
|
||||
_gdk_win32_surface_update_style_bits (surface);
|
||||
|
||||
/* Ensure that any other context is created with a legacy bit set */
|
||||
gdk_gl_context_set_is_legacy (context, legacy_bit);
|
||||
|
||||
|
||||
@@ -351,7 +351,6 @@ _gdk_win32_surface_exstyle_to_string (LONG style)
|
||||
BIT (CONTEXTHELP);
|
||||
BIT (CONTROLPARENT);
|
||||
BIT (DLGMODALFRAME);
|
||||
BIT (LAYERED);
|
||||
BIT (LAYOUTRTL);
|
||||
BIT (LEFTSCROLLBAR);
|
||||
BIT (MDICHILD);
|
||||
|
||||
+14
-184
@@ -275,7 +275,6 @@ _gdk_win32_adjust_client_rect (GdkSurface *window,
|
||||
gboolean
|
||||
_gdk_win32_surface_enable_transparency (GdkSurface *window)
|
||||
{
|
||||
GdkWin32Surface *impl;
|
||||
DWM_BLURBEHIND blur_behind;
|
||||
HRGN empty_region;
|
||||
HRESULT call_result;
|
||||
@@ -284,12 +283,6 @@ _gdk_win32_surface_enable_transparency (GdkSurface *window)
|
||||
if (window == NULL || GDK_SURFACE_HWND (window) == NULL)
|
||||
return FALSE;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
/* layered windows don't need blurbehind for transparency */
|
||||
if (impl->layered)
|
||||
return TRUE;
|
||||
|
||||
if (!gdk_display_is_composited (gdk_surface_get_display (window)))
|
||||
return FALSE;
|
||||
|
||||
@@ -526,9 +519,6 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
impl->layered = FALSE;
|
||||
impl->layered_opacity = 1.0;
|
||||
|
||||
impl->surface_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
|
||||
impl->unscaled_width = width * impl->surface_scale;
|
||||
impl->unscaled_height = height * impl->surface_scale;
|
||||
@@ -1761,11 +1751,6 @@ update_single_bit (LONG *style,
|
||||
* Returns TRUE if window has no decorations.
|
||||
* Usually it means CSD windows, because GTK
|
||||
* calls gdk_surface_set_decorations (window, 0);
|
||||
* This is used to decide whether a toplevel should
|
||||
* be made layered, thus it
|
||||
* only returns TRUE for toplevels (until GTK minimal
|
||||
* system requirements are lifted to Windows 8 or newer,
|
||||
* because only toplevels can be layered).
|
||||
*/
|
||||
gboolean
|
||||
_gdk_win32_surface_lacks_wm_decorations (GdkSurface *window)
|
||||
@@ -1859,27 +1844,6 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window)
|
||||
new_exstyle &= ~WS_EX_TOOLWINDOW;
|
||||
}
|
||||
|
||||
/* We can get away with using layered windows
|
||||
* only when no decorations are needed. It can mean
|
||||
* CSD or borderless non-CSD windows (tooltips?).
|
||||
*
|
||||
* If this window cannot use layered windows, disable it always.
|
||||
* This currently applies to windows using OpenGL, which
|
||||
* does not work with layered windows.
|
||||
*/
|
||||
if (impl->suppress_layered == 0)
|
||||
{
|
||||
if (_gdk_win32_surface_lacks_wm_decorations (window))
|
||||
impl->layered = g_strcmp0 (g_getenv ("GDK_WIN32_LAYERED"), "0") != 0;
|
||||
}
|
||||
else
|
||||
impl->layered = FALSE;
|
||||
|
||||
if (impl->layered)
|
||||
new_exstyle |= WS_EX_LAYERED;
|
||||
else
|
||||
new_exstyle &= ~WS_EX_LAYERED;
|
||||
|
||||
if (get_effective_window_decorations (window, &decorations))
|
||||
{
|
||||
all = (decorations & GDK_DECOR_ALL);
|
||||
@@ -3811,67 +3775,6 @@ gdk_win32_get_window_size_and_position_from_client_rect (GdkSurface *window,
|
||||
window_size->cy = window_rect->bottom - window_rect->top;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_update_layered_window_from_cache (GdkSurface *surface,
|
||||
RECT *client_rect,
|
||||
gboolean do_move,
|
||||
gboolean do_resize,
|
||||
gboolean do_paint)
|
||||
{
|
||||
POINT window_position;
|
||||
SIZE window_size;
|
||||
BLENDFUNCTION blender;
|
||||
HDC hdc;
|
||||
SIZE *window_size_ptr;
|
||||
POINT source_point = { 0, 0 };
|
||||
POINT *source_point_ptr;
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
gdk_win32_get_window_size_and_position_from_client_rect (surface,
|
||||
client_rect,
|
||||
&window_size,
|
||||
&window_position);
|
||||
|
||||
blender.BlendOp = AC_SRC_OVER;
|
||||
blender.BlendFlags = 0;
|
||||
blender.AlphaFormat = AC_SRC_ALPHA;
|
||||
blender.SourceConstantAlpha = impl->layered_opacity * 255;
|
||||
|
||||
/* Strictly speaking, we don't need to supply hdc, source_point and
|
||||
* window_size to just move the window. However, without these arguments
|
||||
* the window moves but does not update its contents on Windows 7 when
|
||||
* desktop composition is off. This forces us to provide hdc and
|
||||
* source_point. window_size is here to avoid the function
|
||||
* inexplicably failing with error 317.
|
||||
*/
|
||||
hdc = cairo_win32_surface_get_dc (impl->cache_surface);
|
||||
window_size_ptr = &window_size;
|
||||
source_point_ptr = &source_point;
|
||||
|
||||
if (gdk_display_is_composited (gdk_surface_get_display (surface)))
|
||||
{
|
||||
if (!do_paint)
|
||||
hdc = NULL;
|
||||
if (!do_resize)
|
||||
window_size_ptr = NULL;
|
||||
if (!do_move)
|
||||
source_point_ptr = NULL;
|
||||
}
|
||||
|
||||
/* Don't use UpdateLayeredWindow on minimized windows */
|
||||
if (IsIconic (GDK_SURFACE_HWND (surface)))
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (surface),
|
||||
SWP_NOZORDER_SPECIFIED,
|
||||
window_position.x, window_position.y,
|
||||
window_size.cx, window_size.cy,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
|
||||
else
|
||||
API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (surface), NULL,
|
||||
&window_position, window_size_ptr,
|
||||
hdc, source_point_ptr,
|
||||
0, &blender, ULW_ALPHA));
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
|
||||
int x,
|
||||
@@ -4058,30 +3961,23 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
|
||||
(rect.left != new_rect.left ||
|
||||
rect.top != new_rect.top))
|
||||
{
|
||||
SIZE window_size;
|
||||
POINT window_position;
|
||||
|
||||
context->native_move_resize_pending = FALSE;
|
||||
|
||||
gdk_surface_request_layout (window);
|
||||
|
||||
if (impl->layered)
|
||||
{
|
||||
_gdk_win32_update_layered_window_from_cache (window, &new_rect, TRUE, FALSE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE window_size;
|
||||
POINT window_position;
|
||||
gdk_win32_get_window_size_and_position_from_client_rect (window,
|
||||
&new_rect,
|
||||
&window_size,
|
||||
&window_position);
|
||||
|
||||
gdk_win32_get_window_size_and_position_from_client_rect (window,
|
||||
&new_rect,
|
||||
&window_size,
|
||||
&window_position);
|
||||
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
SWP_NOZORDER_SPECIFIED,
|
||||
window_position.x, window_position.y,
|
||||
0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
|
||||
}
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
SWP_NOZORDER_SPECIFIED,
|
||||
window_position.x, window_position.y,
|
||||
0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
|
||||
}
|
||||
|
||||
if (context->op == GDK_WIN32_DRAGOP_RESIZE ||
|
||||
@@ -4355,61 +4251,6 @@ gdk_win32_surface_lookup_for_display (GdkDisplay *display,
|
||||
return (GdkSurface*) gdk_win32_handle_table_lookup (anid);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_surface_set_opacity (GdkSurface *window,
|
||||
double opacity)
|
||||
{
|
||||
LONG exstyle;
|
||||
typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
|
||||
PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (window));
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (window))
|
||||
return;
|
||||
|
||||
if (opacity < 0)
|
||||
opacity = 0;
|
||||
else if (opacity > 1)
|
||||
opacity = 1;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
if (impl->layered)
|
||||
{
|
||||
if (impl->layered_opacity != opacity)
|
||||
{
|
||||
RECT window_rect;
|
||||
|
||||
impl->layered_opacity = opacity;
|
||||
|
||||
_gdk_win32_get_window_client_area_rect (window, impl->surface_scale, &window_rect);
|
||||
_gdk_win32_update_layered_window_from_cache (window, &window_rect, TRUE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
|
||||
|
||||
if (!(exstyle & WS_EX_LAYERED))
|
||||
SetWindowLong (GDK_SURFACE_HWND (window),
|
||||
GWL_EXSTYLE,
|
||||
exstyle | WS_EX_LAYERED);
|
||||
|
||||
setLayeredWindowAttributes =
|
||||
(PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
|
||||
|
||||
if (setLayeredWindowAttributes)
|
||||
{
|
||||
API_CALL (setLayeredWindowAttributes, (GDK_SURFACE_HWND (window),
|
||||
0,
|
||||
opacity * 0xff,
|
||||
LWA_ALPHA));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_win32_surface_is_win32 (GdkSurface *window)
|
||||
{
|
||||
@@ -4489,9 +4330,6 @@ GtkShowWindow (GdkSurface *window,
|
||||
if (IsWindowVisible (hwnd))
|
||||
break;
|
||||
|
||||
if ((WS_EX_LAYERED & GetWindowLongPtr (hwnd, GWL_EXSTYLE)) != WS_EX_LAYERED)
|
||||
break;
|
||||
|
||||
/* Window was hidden, will be shown. Erase it, GDK will repaint soon,
|
||||
* but not soon enough, so it's possible to see old content before
|
||||
* the next redraw, unless we erase the window first.
|
||||
@@ -5275,7 +5113,6 @@ gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
|
||||
RECT
|
||||
gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
|
||||
{
|
||||
GdkWin32CairoContext *cairo_ctx = NULL;
|
||||
GdkSurface *surface;
|
||||
GdkWin32Surface *impl;
|
||||
int scale;
|
||||
@@ -5285,23 +5122,16 @@ gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
|
||||
impl = GDK_WIN32_SURFACE (surface);
|
||||
scale = gdk_surface_get_scale_factor (surface);
|
||||
|
||||
if (GDK_IS_WIN32_CAIRO_CONTEXT (draw_context))
|
||||
{
|
||||
cairo_ctx = GDK_WIN32_CAIRO_CONTEXT (draw_context);
|
||||
cairo_ctx->layered = impl->layered;
|
||||
}
|
||||
|
||||
gdk_win32_surface_get_queued_window_rect (surface, scale, &queued_window_rect);
|
||||
|
||||
/* Apply queued resizes for non-double-buffered and non-layered windows
|
||||
/* Apply queued resizes for non-double-buffered windows
|
||||
* before painting them (we paint on the window DC directly,
|
||||
* it must have the right size).
|
||||
* Due to some poorly-undetstood issue delayed
|
||||
* resizing of double-buffered windows can produce weird
|
||||
* artefacts, so these are also resized before we paint.
|
||||
*/
|
||||
if (impl->drag_move_resize_context.native_move_resize_pending &&
|
||||
(cairo_ctx == NULL || !cairo_ctx->layered))
|
||||
if (impl->drag_move_resize_context.native_move_resize_pending)
|
||||
{
|
||||
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
|
||||
gdk_win32_surface_apply_queued_move_resize (surface, queued_window_rect);
|
||||
|
||||
@@ -277,13 +277,6 @@ struct _GdkWin32Surface
|
||||
guint zero_shadow : 1;
|
||||
guint inhibit_configure : 1;
|
||||
|
||||
/* Set to TRUE if window is using true layered mode adjustments
|
||||
* via UpdateLayeredWindow().
|
||||
* Layered windows that get SetLayeredWindowAttributes() called
|
||||
* on them are not true layered windows.
|
||||
*/
|
||||
guint layered : 1;
|
||||
|
||||
/* If TRUE, the @temp_styles is set to the styles that were temporarily
|
||||
* added to this window.
|
||||
*/
|
||||
@@ -309,12 +302,6 @@ struct _GdkWin32Surface
|
||||
int dib_width;
|
||||
int dib_height;
|
||||
|
||||
/* If the client wants uniformly-transparent window,
|
||||
* we remember the opacity value here and apply it
|
||||
* during UpdateLayredWindow() call, for layered windows.
|
||||
*/
|
||||
double layered_opacity;
|
||||
|
||||
HDC hdc;
|
||||
int hdc_count;
|
||||
HBITMAP saved_dc_bitmap; /* Original bitmap for dc */
|
||||
@@ -340,9 +327,6 @@ struct _GdkWin32Surface
|
||||
/* Enable all decorations? */
|
||||
gboolean decorate_all;
|
||||
|
||||
/* No. of windows to force layered windows off */
|
||||
guint suppress_layered;
|
||||
|
||||
/* Temporary styles that this window got for the purpose of
|
||||
* handling WM_SYSMENU.
|
||||
* They are removed at the first opportunity (usually WM_INITMENU).
|
||||
@@ -382,11 +366,6 @@ int _gdk_win32_surface_get_scale_factor (GdkSurface *window);
|
||||
void _gdk_win32_get_window_client_area_rect (GdkSurface *window,
|
||||
int scale,
|
||||
RECT *rect);
|
||||
void _gdk_win32_update_layered_window_from_cache (GdkSurface *window,
|
||||
RECT *client_rect,
|
||||
gboolean do_move,
|
||||
gboolean do_resize,
|
||||
gboolean do_paint);
|
||||
|
||||
void gdk_win32_surface_move (GdkSurface *surface,
|
||||
int x,
|
||||
|
||||
@@ -63,12 +63,6 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
|
||||
NULL,
|
||||
surface);
|
||||
|
||||
if (result == VK_SUCCESS)
|
||||
win32_surface->suppress_layered ++;
|
||||
|
||||
if (win32_surface->suppress_layered == 1)
|
||||
_gdk_win32_surface_update_style_bits (window);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+46
-5
@@ -39,6 +39,7 @@
|
||||
#include "gdkscreen-x11.h"
|
||||
#include "gdkselectioninputstream-x11.h"
|
||||
#include "gdkselectionoutputstream-x11.h"
|
||||
#include "gdktextlistconverter-x11.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
@@ -103,6 +104,49 @@ static const struct {
|
||||
|
||||
G_DEFINE_TYPE (GdkX11Drop, gdk_x11_drop, GDK_TYPE_DROP)
|
||||
|
||||
static GInputStream *
|
||||
text_list_convert (GdkDisplay *display,
|
||||
GInputStream *stream,
|
||||
const char *encoding,
|
||||
int format)
|
||||
{
|
||||
GInputStream *converter_stream;
|
||||
GConverter *converter;
|
||||
|
||||
converter = gdk_x11_text_list_converter_to_utf8_new (display, encoding, format);
|
||||
converter_stream = g_converter_input_stream_new (stream, converter);
|
||||
|
||||
g_object_unref (converter);
|
||||
g_object_unref (stream);
|
||||
|
||||
return converter_stream;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
no_convert (GdkDisplay *display,
|
||||
GInputStream *stream,
|
||||
const char *encoding,
|
||||
int format)
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *x_target;
|
||||
const char *mime_type;
|
||||
GInputStream * (* convert) (GdkDisplay *, GInputStream *, const char *, int);
|
||||
const char *type;
|
||||
int format;
|
||||
} special_targets[] = {
|
||||
{ "UTF8_STRING", "text/plain;charset=utf-8", no_convert, "UTF8_STRING", 8 },
|
||||
{ "COMPOUND_TEXT", "text/plain;charset=utf-8", text_list_convert, "COMPOUND_TEXT", 8 },
|
||||
{ "TEXT", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 },
|
||||
{ "STRING", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 },
|
||||
{ "TARGETS", NULL, NULL, "ATOM", 32 },
|
||||
{ "TIMESTAMP", NULL, NULL, "INTEGER", 32 },
|
||||
{ "SAVE_TARGETS", NULL, NULL, "NULL", 32 }
|
||||
};
|
||||
|
||||
static void
|
||||
gdk_x11_drop_read_got_stream (GObject *source,
|
||||
GAsyncResult *res,
|
||||
@@ -145,9 +189,9 @@ gdk_x11_drop_read_got_stream (GObject *source,
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
gsize i;
|
||||
const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
|
||||
GdkDrop *drop = GDK_DROP (g_task_get_source_object (task));
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (special_targets); i++)
|
||||
{
|
||||
@@ -155,15 +199,12 @@ gdk_x11_drop_read_got_stream (GObject *source,
|
||||
{
|
||||
g_assert (special_targets[i].mime_type != NULL);
|
||||
|
||||
GDK_DISPLAY_NOTE (CLIPBOARD, g_printerr ("%s: reading with converter from %s to %s\n",
|
||||
cb->selection, mime_type, special_targets[i].mime_type));
|
||||
mime_type = g_intern_string (special_targets[i].mime_type);
|
||||
g_task_set_task_data (task, g_slist_prepend (NULL, (gpointer) mime_type), (GDestroyNotify) g_slist_free);
|
||||
stream = special_targets[i].convert (cb, stream, type, format);
|
||||
stream = special_targets[i].convert (gdk_drop_get_display (drop), stream, type, format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GDK_NOTE (DND, g_printerr ("reading DND as %s now\n",
|
||||
(const char *)((GSList *) g_task_get_task_data (task))->data));
|
||||
|
||||
@@ -1383,7 +1383,7 @@ gdk_x11_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
|
||||
tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
|
||||
group, state,
|
||||
level, effective_group);
|
||||
effective_group, level);
|
||||
}
|
||||
|
||||
if (consumed_modifiers)
|
||||
|
||||
@@ -2013,6 +2013,8 @@ _gdk_x11_surface_set_surface_scale (GdkSurface *surface,
|
||||
surface->height * impl->surface_scale);
|
||||
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
|
||||
g_object_notify (G_OBJECT (surface), "scale-factor");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -149,10 +149,10 @@ render_glyph (GlyphCacheKey *key,
|
||||
glyph_info.glyph = key->data.glyph;
|
||||
glyph_info.geometry.width = value->draw_width * 1024;
|
||||
if (glyph_info.glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
||||
glyph_info.geometry.x_offset = 0;
|
||||
glyph_info.geometry.x_offset = 250 * key->data.xshift;
|
||||
else
|
||||
glyph_info.geometry.x_offset = - value->draw_x * 1024;
|
||||
glyph_info.geometry.y_offset = - value->draw_y * 1024;
|
||||
glyph_info.geometry.x_offset = 250 * key->data.xshift - value->draw_x * 1024;
|
||||
glyph_info.geometry.y_offset = 250 * key->data.yshift - value->draw_y * 1024;
|
||||
|
||||
glyph_string.num_glyphs = 1;
|
||||
glyph_string.glyphs = &glyph_info;
|
||||
|
||||
+57
-56
@@ -1452,6 +1452,7 @@ render_linear_gradient_node (GskGLRenderer *self,
|
||||
ops_set_linear_gradient (builder,
|
||||
n_color_stops,
|
||||
stops,
|
||||
gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE,
|
||||
builder->dx + start->x,
|
||||
builder->dy + start->y,
|
||||
builder->dx + end->x,
|
||||
@@ -1485,6 +1486,7 @@ render_radial_gradient_node (GskGLRenderer *self,
|
||||
ops_set_radial_gradient (builder,
|
||||
n_color_stops,
|
||||
stops,
|
||||
gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE,
|
||||
builder->dx + center->x,
|
||||
builder->dy + center->y,
|
||||
start, end,
|
||||
@@ -1510,7 +1512,7 @@ render_conic_gradient_node (GskGLRenderer *self,
|
||||
{
|
||||
const GskColorStop *stops = gsk_conic_gradient_node_get_color_stops (node, NULL);
|
||||
const graphene_point_t *center = gsk_conic_gradient_node_get_center (node);
|
||||
const float rotation = gsk_conic_gradient_node_get_rotation (node);
|
||||
const float angle = gsk_conic_gradient_node_get_angle (node);
|
||||
|
||||
ops_set_program (builder, &self->programs->conic_gradient_program);
|
||||
ops_set_conic_gradient (builder,
|
||||
@@ -1518,7 +1520,7 @@ render_conic_gradient_node (GskGLRenderer *self,
|
||||
stops,
|
||||
builder->dx + center->x,
|
||||
builder->dy + center->y,
|
||||
rotation);
|
||||
angle);
|
||||
|
||||
load_vertex_data (ops_draw (builder, NULL), &node->bounds, builder);
|
||||
}
|
||||
@@ -1554,7 +1556,7 @@ rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
|
||||
MAX (rounded->corner[GSK_CORNER_BOTTOM_LEFT].height,
|
||||
rounded->corner[GSK_CORNER_BOTTOM_RIGHT].height);
|
||||
|
||||
return graphene_rect_contains_rect (&inner, rect);
|
||||
return _graphene_rect_contains_rect (&inner, rect);
|
||||
}
|
||||
|
||||
/* Current clip is NOT rounded but new one is definitely! */
|
||||
@@ -1644,8 +1646,8 @@ render_clipped_child (GskGLRenderer *self,
|
||||
/* well fuck */
|
||||
const float scale_x = builder->scale_x;
|
||||
const float scale_y = builder->scale_y;
|
||||
const GskRoundedRect scaled_clip = GSK_ROUNDED_RECT_INIT (clip->origin.x * scale_x,
|
||||
clip->origin.y * scale_y,
|
||||
const GskRoundedRect scaled_clip = GSK_ROUNDED_RECT_INIT ((builder->dx + clip->origin.x) * scale_x,
|
||||
(builder->dy + clip->origin.y) * scale_y,
|
||||
clip->size.width * scale_x,
|
||||
clip->size.height * scale_y);
|
||||
gboolean is_offscreen;
|
||||
@@ -1746,7 +1748,6 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
GskRoundedRect scaled_clip;
|
||||
gboolean is_offscreen;
|
||||
TextureRegion region;
|
||||
/* NOTE: We are *not* transforming the clip by the current modelview here.
|
||||
@@ -1755,19 +1756,7 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
*
|
||||
* We do, however, apply the scale factor to the child clip of course.
|
||||
*/
|
||||
scaled_clip.bounds.origin.x = clip->bounds.origin.x * scale_x;
|
||||
scaled_clip.bounds.origin.y = clip->bounds.origin.y * scale_y;
|
||||
scaled_clip.bounds.size.width = clip->bounds.size.width * scale_x;
|
||||
scaled_clip.bounds.size.height = clip->bounds.size.height * scale_y;
|
||||
|
||||
/* Increase corner radius size by scale factor */
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
scaled_clip.corner[i].width = clip->corner[i].width * scale_x;
|
||||
scaled_clip.corner[i].height = clip->corner[i].height * scale_y;
|
||||
}
|
||||
|
||||
ops_push_clip (builder, &scaled_clip);
|
||||
ops_push_clip (builder, &transformed_clip);
|
||||
if (!add_offscreen_ops (self, builder, &node->bounds,
|
||||
child,
|
||||
®ion, &is_offscreen,
|
||||
@@ -1779,7 +1768,8 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
ops_set_program (builder, &self->programs->blit_program);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
|
||||
load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
load_vertex_data_with_region (ops_draw (builder, NULL), &node->bounds, builder,
|
||||
®ion, is_offscreen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3053,14 +3043,19 @@ apply_linear_gradient_op (const Program *program,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform2f (program->linear_gradient.start_point_location, op->start_point[0], op->start_point[1]);
|
||||
glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]);
|
||||
glUniform4f (program->linear_gradient.points_location,
|
||||
op->start_point[0], op->start_point[1],
|
||||
op->end_point[0] - op->start_point[0], op->end_point[1] - op->start_point[1]);
|
||||
glUniform1i (program->linear_gradient.repeat_location, op->repeat);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_radial_gradient_op (const Program *program,
|
||||
const OpRadialGradient *op)
|
||||
{
|
||||
float scale;
|
||||
float bias;
|
||||
|
||||
OP_PRINT (" -> Radial gradient");
|
||||
if (op->n_color_stops.send)
|
||||
glUniform1i (program->radial_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||
@@ -3070,16 +3065,23 @@ apply_radial_gradient_op (const Program *program,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform1f (program->radial_gradient.start_location, op->start);
|
||||
glUniform1f (program->radial_gradient.end_location, op->end);
|
||||
glUniform2f (program->radial_gradient.radius_location, op->radius[0], op->radius[1]);
|
||||
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
|
||||
scale = 1.0f / (op->end - op->start);
|
||||
bias = -op->start * scale;
|
||||
|
||||
glUniform1i (program->radial_gradient.repeat_location, op->repeat);
|
||||
glUniform2f (program->radial_gradient.range_location, scale, bias);
|
||||
glUniform4f (program->radial_gradient.geometry_location,
|
||||
op->center[0], op->center[1],
|
||||
1.0f / op->radius[0], 1.0f / op->radius[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_conic_gradient_op (const Program *program,
|
||||
const OpConicGradient *op)
|
||||
{
|
||||
float bias;
|
||||
float scale;
|
||||
|
||||
OP_PRINT (" -> Conic gradient");
|
||||
if (op->n_color_stops.send)
|
||||
glUniform1i (program->conic_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||
@@ -3089,8 +3091,9 @@ apply_conic_gradient_op (const Program *program,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform1f (program->conic_gradient.rotation_location, op->rotation);
|
||||
glUniform2f (program->conic_gradient.center_location, op->center[0], op->center[1]);
|
||||
scale = 0.5f * M_1_PI;
|
||||
bias = op->angle * scale + 2.0f;
|
||||
glUniform4f (program->conic_gradient.geometry_location, op->center[0], op->center[1], scale, bias);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -3380,22 +3383,20 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
/* linear gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, start_point);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, end_point);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, repeat);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, points);
|
||||
|
||||
/* radial gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, center);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, start);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, repeat);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, geometry);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, range);
|
||||
|
||||
/* conic gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, center);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, rotation);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, geometry);
|
||||
|
||||
/* blur */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
|
||||
@@ -3741,10 +3742,12 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
break;
|
||||
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
render_linear_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
render_radial_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
@@ -3811,8 +3814,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
render_gl_shader_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
{
|
||||
@@ -3830,9 +3831,9 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
gboolean *is_offscreen,
|
||||
guint flags)
|
||||
{
|
||||
float width, height;
|
||||
const float dx = builder->dx;
|
||||
const float dy = builder->dy;
|
||||
float scaled_width, scaled_height;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
int render_target;
|
||||
@@ -3888,8 +3889,6 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
width = bounds->size.width;
|
||||
height = bounds->size.height;
|
||||
scale_x = builder->scale_x;
|
||||
scale_y = builder->scale_y;
|
||||
|
||||
@@ -3900,23 +3899,23 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
{
|
||||
const int max_texture_size = gsk_gl_driver_get_max_texture_size (self->gl_driver);
|
||||
|
||||
width = ceilf (width * scale_x);
|
||||
if (width > max_texture_size)
|
||||
scaled_width = ceilf (bounds->size.width * scale_x);
|
||||
if (scaled_width > max_texture_size)
|
||||
{
|
||||
scale_x *= (float)max_texture_size / width;
|
||||
width = max_texture_size;
|
||||
scale_x *= (float)max_texture_size / scaled_width;
|
||||
scaled_width = max_texture_size;
|
||||
}
|
||||
|
||||
height = ceilf (height * scale_y);
|
||||
if (height > max_texture_size)
|
||||
scaled_height = ceilf (bounds->size.height * scale_y);
|
||||
if (scaled_height > max_texture_size)
|
||||
{
|
||||
scale_y *= (float)max_texture_size / height;
|
||||
height = max_texture_size;
|
||||
scale_y *= (float)max_texture_size / scaled_height;
|
||||
scaled_height = max_texture_size;
|
||||
}
|
||||
}
|
||||
|
||||
gsk_gl_driver_create_render_target (self->gl_driver,
|
||||
width, height,
|
||||
scaled_width, scaled_height,
|
||||
filter, filter,
|
||||
&texture_id, &render_target);
|
||||
if (gdk_gl_context_has_debug (self->gl_context))
|
||||
@@ -3931,9 +3930,11 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
render_target);
|
||||
}
|
||||
|
||||
viewport = GRAPHENE_RECT_INIT (bounds->origin.x * scale_x,
|
||||
bounds->origin.y * scale_y,
|
||||
width, height);
|
||||
ops_transform_bounds_modelview (builder, bounds, &viewport);
|
||||
/* Code above will scale the size with the scale we use in the render ops,
|
||||
* but for the viewport size, we need our own size limited by the texture size */
|
||||
viewport.size.width = scaled_width;
|
||||
viewport.size.height = scaled_height;
|
||||
|
||||
init_projection_matrix (&item_proj, &viewport);
|
||||
prev_render_target = ops_set_render_target (builder, render_target);
|
||||
@@ -3945,8 +3946,8 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
if (flags & RESET_CLIP)
|
||||
ops_push_clip (builder, &GSK_ROUNDED_RECT_INIT_FROM_RECT (viewport));
|
||||
|
||||
builder->dx = 0;
|
||||
builder->dy = 0;
|
||||
builder->dx = dx;
|
||||
builder->dy = dy;
|
||||
|
||||
prev_opacity = ops_set_opacity (builder, 1.0);
|
||||
|
||||
@@ -3961,7 +3962,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
g_type_name_from_instance ((GTypeInstance *) child_node),
|
||||
child_node,
|
||||
k ++),
|
||||
width, height);
|
||||
scaled_width, scaled_height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -859,6 +859,7 @@ void
|
||||
ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float start_x,
|
||||
float start_y,
|
||||
float end_x,
|
||||
@@ -912,6 +913,7 @@ ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
sizeof (GskColorStop) * real_n_color_stops);
|
||||
}
|
||||
|
||||
op->repeat = repeat;
|
||||
op->start_point[0] = start_x;
|
||||
op->start_point[1] = start_y;
|
||||
op->end_point[0] = end_x;
|
||||
@@ -922,6 +924,7 @@ void
|
||||
ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
@@ -945,6 +948,7 @@ ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
op->radius[1] = vradius;
|
||||
op->start = start;
|
||||
op->end = end;
|
||||
op->repeat = repeat;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -953,7 +957,7 @@ ops_set_conic_gradient (RenderOpBuilder *self,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float rotation)
|
||||
float angle)
|
||||
{
|
||||
const guint real_n_color_stops = MIN (GL_MAX_GRADIENT_STOPS, n_color_stops);
|
||||
OpConicGradient *op;
|
||||
@@ -967,6 +971,6 @@ ops_set_conic_gradient (RenderOpBuilder *self,
|
||||
op->color_stops.send = true;
|
||||
op->center[0] = center_x;
|
||||
op->center[1] = center_y;
|
||||
op->rotation = rotation;
|
||||
op->angle = angle;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,22 +118,20 @@ struct _Program
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int start_point_location;
|
||||
int end_point_location;
|
||||
int points_location;
|
||||
int repeat_location;
|
||||
} linear_gradient;
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int center_location;
|
||||
int start_location;
|
||||
int end_location;
|
||||
int radius_location;
|
||||
int geometry_location;
|
||||
int range_location;
|
||||
int repeat_location;
|
||||
} radial_gradient;
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int center_location;
|
||||
int rotation_location;
|
||||
int geometry_location;
|
||||
} conic_gradient;
|
||||
struct {
|
||||
int blur_radius_location;
|
||||
@@ -319,6 +317,7 @@ void ops_set_unblurred_outset_shadow (RenderOpBuilder *se
|
||||
void ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float start_x,
|
||||
float start_y,
|
||||
float end_x,
|
||||
@@ -326,6 +325,7 @@ void ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
void ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
@@ -337,7 +337,7 @@ void ops_set_conic_gradient (RenderOpBuilder *self,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float rotation);
|
||||
float angle);
|
||||
|
||||
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES]);
|
||||
|
||||
@@ -64,8 +64,10 @@ prepend_line_numbers (char *code,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_shader_error (int shader_id,
|
||||
GError **error)
|
||||
check_shader_error (int shader_id,
|
||||
int shader_type,
|
||||
const char *resource_path,
|
||||
GError **error)
|
||||
{
|
||||
int status;
|
||||
int log_len;
|
||||
@@ -91,7 +93,9 @@ check_shader_error (int shader_id,
|
||||
prepend_line_numbers (code, s);
|
||||
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
"Compilation failure in shader.\nSource Code: %s\n\nError Message:\n%s\n\n",
|
||||
"Compilation failure in %s shader %s.\nSource Code:\n%s\n\nError Message:\n%s\n\n",
|
||||
(shader_type == GL_FRAGMENT_SHADER ? "fragment" : "vertex"),
|
||||
resource_path,
|
||||
s->str,
|
||||
buffer);
|
||||
|
||||
@@ -184,7 +188,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
|
||||
});
|
||||
glCompileShader (vertex_id);
|
||||
|
||||
if (!check_shader_error (vertex_id, error))
|
||||
if (!check_shader_error (vertex_id, GL_VERTEX_SHADER, resource_path, error))
|
||||
{
|
||||
glDeleteShader (vertex_id);
|
||||
goto out;
|
||||
@@ -218,7 +222,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
|
||||
});
|
||||
glCompileShader (fragment_id);
|
||||
|
||||
if (!check_shader_error (fragment_id, error))
|
||||
if (!check_shader_error (fragment_id, GL_FRAGMENT_SHADER, resource_path, error))
|
||||
{
|
||||
glDeleteShader (fragment_id);
|
||||
goto out;
|
||||
@@ -230,7 +234,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
|
||||
glAttachShader (program_id, vertex_id);
|
||||
glAttachShader (program_id, fragment_id);
|
||||
glBindAttribLocation (program_id, 0, "aPosition");
|
||||
glBindAttribLocation (program_id, 1, "vUv");
|
||||
glBindAttribLocation (program_id, 1, "aUv");
|
||||
glLinkProgram (program_id);
|
||||
glDetachShader (program_id, vertex_id);
|
||||
glDetachShader (program_id, fragment_id);
|
||||
|
||||
+3
-1
@@ -146,6 +146,7 @@ typedef struct
|
||||
IntUniformValue n_color_stops;
|
||||
float start_point[2];
|
||||
float end_point[2];
|
||||
gboolean repeat;
|
||||
} OpLinearGradient;
|
||||
|
||||
typedef struct
|
||||
@@ -156,6 +157,7 @@ typedef struct
|
||||
float end;
|
||||
float radius[2];
|
||||
float center[2];
|
||||
gboolean repeat;
|
||||
} OpRadialGradient;
|
||||
|
||||
typedef struct
|
||||
@@ -163,7 +165,7 @@ typedef struct
|
||||
ColorStopUniformValue color_stops;
|
||||
IntUniformValue n_color_stops;
|
||||
float center[2];
|
||||
float rotation;
|
||||
float angle;
|
||||
} OpConicGradient;
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -257,6 +257,8 @@ const graphene_point_t * gsk_conic_gradient_node_get_center (GskRenderNo
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_conic_gradient_node_get_rotation (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_conic_gradient_node_get_angle (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gsize gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GskColorStop * gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
|
||||
|
||||
@@ -782,6 +782,7 @@ struct _GskConicGradientNode
|
||||
|
||||
graphene_point_t center;
|
||||
float rotation;
|
||||
float angle;
|
||||
|
||||
gsize n_stops;
|
||||
GskColorStop *stops;
|
||||
@@ -1023,6 +1024,12 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
|
||||
self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
|
||||
memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
|
||||
|
||||
self->angle = 90.f - self->rotation;
|
||||
self->angle = G_PI * self->angle / 180.f;
|
||||
self->angle = fmodf (self->angle, 2.f * G_PI);
|
||||
if (self->angle < 0.f)
|
||||
self->angle += 2.f * G_PI;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1095,6 +1102,26 @@ gsk_conic_gradient_node_get_rotation (GskRenderNode *node)
|
||||
return self->rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_conic_gradient_node_get_angle:
|
||||
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
|
||||
*
|
||||
* Retrieves the angle for the gradient in radians, normalized in [0, 2 * PI]
|
||||
*
|
||||
* The angle is starting at the top and going clockwise, as expressed
|
||||
* in the css specification:
|
||||
* angle = 90 - gsk_conic_gradient_node_get_rotation()
|
||||
*
|
||||
* Returns: the angle for the gradient
|
||||
*/
|
||||
float
|
||||
gsk_conic_gradient_node_get_angle (GskRenderNode *node)
|
||||
{
|
||||
GskConicGradientNode *self = (GskConicGradientNode *) node;
|
||||
|
||||
return self->angle;
|
||||
}
|
||||
|
||||
/*** GSK_BORDER_NODE ***/
|
||||
|
||||
/**
|
||||
|
||||
@@ -689,14 +689,16 @@ create_ascii_glyphs (PangoFont *font)
|
||||
for (i = MIN_ASCII_GLYPH; i < MAX_ASCII_GLYPH; i++)
|
||||
{
|
||||
const char text[2] = { i, 0 };
|
||||
PangoShapeFlags flags = 0;
|
||||
|
||||
pango_shape_with_flags (text,
|
||||
1,
|
||||
text,
|
||||
1,
|
||||
if (cairo_version () < CAIRO_VERSION_ENCODE (1, 17, 4))
|
||||
flags = PANGO_SHAPE_ROUND_POSITIONS;
|
||||
|
||||
pango_shape_with_flags (text, 1,
|
||||
text, 1,
|
||||
¬_a_hack,
|
||||
glyph_string,
|
||||
PANGO_SHAPE_ROUND_POSITIONS);
|
||||
flags);
|
||||
|
||||
if (glyph_string->num_glyphs != 1)
|
||||
{
|
||||
|
||||
@@ -1,34 +1,17 @@
|
||||
// VERTEX_SHADER
|
||||
uniform vec2 u_center;
|
||||
uniform float u_rotation;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec4 u_geometry;
|
||||
|
||||
const float PI = 3.1415926535897932384626433832795;
|
||||
|
||||
_OUT_ vec2 center;
|
||||
_OUT_ float rotation;
|
||||
_OUT_ vec4 color_stops[6];
|
||||
_OUT_ float color_offsets[6];
|
||||
_NOPERSPECTIVE_ _OUT_ vec2 coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
|
||||
|
||||
// The -90 is because conics point to the top by default
|
||||
rotation = mod (u_rotation - 90.0, 360.0);
|
||||
if (rotation < 0.0)
|
||||
rotation += 360.0;
|
||||
rotation = PI / 180.0 * rotation;
|
||||
vec2 mv0 = u_modelview[0].xy;
|
||||
vec2 mv1 = u_modelview[1].xy;
|
||||
vec2 offset = aPosition - u_geometry.xy;
|
||||
|
||||
center = (u_modelview * vec4(u_center, 0, 1)).xy;
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
coord = vec2(dot(mv0, offset),
|
||||
dot(mv1, offset));
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
@@ -38,32 +21,53 @@ uniform int u_num_color_stops;
|
||||
uniform highp int u_num_color_stops; // Why? Because it works like this.
|
||||
#endif
|
||||
|
||||
const float PI = 3.1415926535897932384626433832795;
|
||||
uniform vec4 u_geometry;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
|
||||
_IN_ vec2 center;
|
||||
_IN_ float rotation;
|
||||
_IN_ vec4 color_stops[6];
|
||||
_IN_ float color_offsets[6];
|
||||
_NOPERSPECTIVE_ _IN_ vec2 coord;
|
||||
|
||||
float get_offset(int index) {
|
||||
return u_color_stops[5 * index];
|
||||
}
|
||||
|
||||
vec4 get_color(int index) {
|
||||
int base = 5 * index + 1;
|
||||
|
||||
return vec4(u_color_stops[base],
|
||||
u_color_stops[base + 1],
|
||||
u_color_stops[base + 2],
|
||||
u_color_stops[base + 3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Position relative to center
|
||||
vec2 pos = gsk_get_frag_coord() - center;
|
||||
|
||||
// direction of point in range [-PI, PI]
|
||||
float angle = atan (pos.y, pos.x);
|
||||
// rotate, it's now [-2 * PI, PI]
|
||||
angle -= rotation;
|
||||
vec2 pos = floor(coord);
|
||||
float angle = atan(pos.y, pos.x);
|
||||
|
||||
// fract() does the modulo here, so now we have progress
|
||||
// into the current conic
|
||||
float offset = fract (angle / 2.0 / PI + 2.0);
|
||||
float offset = fract(angle * u_geometry.z + u_geometry.w);
|
||||
|
||||
vec4 color = color_stops[0];
|
||||
for (int i = 1; i < u_num_color_stops; i ++) {
|
||||
if (offset >= color_offsets[i - 1]) {
|
||||
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
|
||||
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
|
||||
if (offset < get_offset(0)) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
return;
|
||||
}
|
||||
|
||||
int n = u_num_color_stops - 1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float curr_offset = get_offset(i);
|
||||
float next_offset = get_offset(i + 1);
|
||||
|
||||
if (offset >= curr_offset && offset < next_offset) {
|
||||
float f = (offset - curr_offset) / (next_offset - curr_offset);
|
||||
vec4 curr_color = gsk_premultiply(get_color(i));
|
||||
vec4 next_color = gsk_premultiply(get_color(i + 1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
|
||||
}
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
// VERTEX_SHADER
|
||||
uniform vec2 u_start_point;
|
||||
uniform vec2 u_end_point;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec4 u_points;
|
||||
|
||||
_OUT_ vec2 startPoint;
|
||||
_OUT_ vec2 endPoint;
|
||||
_OUT_ float maxDist;
|
||||
_OUT_ vec2 gradient;
|
||||
_OUT_ float gradientLength;
|
||||
_OUT_ vec4 color_stops[6];
|
||||
_OUT_ float color_offsets[6];
|
||||
_NOPERSPECTIVE_ _OUT_ vec4 info;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
|
||||
|
||||
startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
|
||||
endPoint = (u_modelview * vec4(u_end_point, 0, 1)).xy;
|
||||
maxDist = length(endPoint - startPoint);
|
||||
vec2 mv0 = u_modelview[0].xy;
|
||||
vec2 mv1 = u_modelview[1].xy;
|
||||
vec2 offset = aPosition - u_points.xy;
|
||||
vec2 coord = vec2(dot(mv0, offset),
|
||||
dot(mv1, offset));
|
||||
|
||||
// Gradient direction
|
||||
gradient = endPoint - startPoint;
|
||||
gradientLength = length(gradient);
|
||||
// Original equation:
|
||||
// VS | maxDist = length(end - start);
|
||||
// VS | gradient = end - start;
|
||||
// VS | gradientLength = length(gradient);
|
||||
// FS | pos = frag_coord - start
|
||||
// FS | proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient
|
||||
// FS | offset = length(proj) / maxDist
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
// Simplified formula derivation:
|
||||
// 1. Notice that maxDist = gradientLength:
|
||||
// offset = length(proj) / gradientLength
|
||||
// 2. Let gnorm = gradient / gradientLength, then:
|
||||
// proj = (dot(gnorm * gradientLength, pos) / (gradientLength * gradientLength)) * (gnorm * gradientLength) =
|
||||
// = dot(gnorm, pos) * gnorm
|
||||
// 3. Since gnorm is unit length then:
|
||||
// length(proj) = length(dot(gnorm, pos) * gnorm) = dot(gnorm, pos)
|
||||
// 4. We can avoid the FS division by passing a scaled pos from the VS:
|
||||
// offset = dot(gnorm, pos) / gradientLength = dot(gnorm, pos / gradientLength)
|
||||
// 5. 1.0 / length(gradient) is inversesqrt(dot(gradient, gradient)) in GLSL
|
||||
vec2 gradient = vec2(dot(mv0, u_points.zw),
|
||||
dot(mv1, u_points.zw));
|
||||
float rcp_gradient_length = inversesqrt(dot(gradient, gradient));
|
||||
|
||||
info = rcp_gradient_length * vec4(coord, gradient);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
@@ -39,32 +45,51 @@ uniform int u_num_color_stops;
|
||||
uniform highp int u_num_color_stops; // Why? Because it works like this.
|
||||
#endif
|
||||
|
||||
_IN_ vec2 startPoint;
|
||||
_IN_ vec2 endPoint;
|
||||
_IN_ float maxDist;
|
||||
_IN_ vec2 gradient;
|
||||
_IN_ float gradientLength;
|
||||
_IN_ vec4 color_stops[6];
|
||||
_IN_ float color_offsets[6];
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform bool u_repeat;
|
||||
|
||||
_NOPERSPECTIVE_ _IN_ vec4 info;
|
||||
|
||||
float get_offset(int index) {
|
||||
return u_color_stops[5 * index];
|
||||
}
|
||||
|
||||
vec4 get_color(int index) {
|
||||
int base = 5 * index + 1;
|
||||
|
||||
return vec4(u_color_stops[base],
|
||||
u_color_stops[base + 1],
|
||||
u_color_stops[base + 2],
|
||||
u_color_stops[base + 3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Position relative to startPoint
|
||||
vec2 pos = gsk_get_frag_coord() - startPoint;
|
||||
float offset = dot(info.xy, info.zw);
|
||||
|
||||
// Current pixel, projected onto the line between the start point and the end point
|
||||
// The projection will be relative to the start point!
|
||||
vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;
|
||||
if (u_repeat) {
|
||||
offset = fract(offset);
|
||||
}
|
||||
|
||||
// Offset of the current pixel
|
||||
float offset = length(proj) / maxDist;
|
||||
if (offset < get_offset(0)) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 color = color_stops[0];
|
||||
for (int i = 1; i < u_num_color_stops; i ++) {
|
||||
if (offset >= color_offsets[i - 1]) {
|
||||
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
|
||||
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
|
||||
int n = u_num_color_stops - 1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float curr_offset = get_offset(i);
|
||||
float next_offset = get_offset(i + 1);
|
||||
|
||||
if (offset >= curr_offset && offset < next_offset) {
|
||||
float f = (offset - curr_offset) / (next_offset - curr_offset);
|
||||
vec4 curr_color = gsk_premultiply(get_color(i));
|
||||
vec4 next_color = gsk_premultiply(get_color(i + 1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@ precision highp float;
|
||||
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
||||
#define _OUT_ varying
|
||||
#define _IN_ varying
|
||||
#define _NOPERSPECTIVE_
|
||||
#define _GSK_ROUNDED_RECT_UNIFORM_ vec4[3]
|
||||
#else
|
||||
#define _OUT_ out
|
||||
#define _IN_ in
|
||||
#define _NOPERSPECTIVE_ noperspective
|
||||
#define _GSK_ROUNDED_RECT_UNIFORM_ GskRoundedRect
|
||||
#endif
|
||||
|
||||
@@ -39,3 +41,11 @@ gsk_create_rect(vec4[3] data)
|
||||
vec4 gsk_premultiply(vec4 c) {
|
||||
return vec4(c.rgb * c.a, c.a);
|
||||
}
|
||||
|
||||
vec4 gsk_scaled_premultiply(vec4 c, float s) {
|
||||
// Fast version of gsk_premultiply(c) * s
|
||||
// 4 muls instead of 7
|
||||
float a = s * c.a;
|
||||
|
||||
return vec4(c.rgb * a, a);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,18 @@
|
||||
// VERTEX_SHADER
|
||||
uniform float u_start;
|
||||
uniform float u_end;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec2 u_radius;
|
||||
uniform vec2 u_center;
|
||||
uniform vec4 u_geometry;
|
||||
|
||||
_OUT_ vec2 center;
|
||||
_OUT_ vec4 color_stops[6];
|
||||
_OUT_ float color_offsets[6];
|
||||
_OUT_ float start;
|
||||
_OUT_ float end;
|
||||
_NOPERSPECTIVE_ _OUT_ vec2 coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
|
||||
|
||||
center = (u_modelview * vec4(u_center, 0, 1)).xy;
|
||||
start = u_start;
|
||||
end = u_end;
|
||||
vec2 mv0 = u_modelview[0].xy;
|
||||
vec2 mv1 = u_modelview[1].xy;
|
||||
vec2 offset = aPosition - u_geometry.xy;
|
||||
vec2 dir = vec2(dot(mv0, offset),
|
||||
dot(mv1, offset));
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
coord = dir * u_geometry.zw;
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
@@ -35,50 +22,53 @@ uniform int u_num_color_stops;
|
||||
uniform highp int u_num_color_stops;
|
||||
#endif
|
||||
|
||||
uniform vec2 u_radius;
|
||||
uniform float u_end;
|
||||
uniform bool u_repeat;
|
||||
uniform vec2 u_range;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
|
||||
_IN_ vec2 center;
|
||||
_IN_ vec4 color_stops[6];
|
||||
_IN_ float color_offsets[6];
|
||||
_IN_ float start;
|
||||
_IN_ float end;
|
||||
_NOPERSPECTIVE_ _IN_ vec2 coord;
|
||||
|
||||
// The offsets in the color stops are relative to the
|
||||
// start and end values of the gradient.
|
||||
float abs_offset(float offset) {
|
||||
return start + ((end - start) * offset);
|
||||
float get_offset(int index) {
|
||||
return u_color_stops[5 * index];
|
||||
}
|
||||
|
||||
vec4 get_color(int index) {
|
||||
int base = 5 * index + 1;
|
||||
|
||||
return vec4(u_color_stops[base],
|
||||
u_color_stops[base + 1],
|
||||
u_color_stops[base + 2],
|
||||
u_color_stops[base + 3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 pixel = gsk_get_frag_coord();
|
||||
vec2 rel = (center - pixel) / (u_radius);
|
||||
float d = sqrt(dot(rel, rel));
|
||||
// Reverse scale
|
||||
float offset = length(coord) * u_range.x + u_range.y;
|
||||
|
||||
if (d < abs_offset (color_offsets[0])) {
|
||||
gskSetOutputColor(color_stops[0] * u_alpha);
|
||||
if (u_repeat) {
|
||||
offset = fract(offset);
|
||||
}
|
||||
|
||||
if (offset < get_offset(0)) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
return;
|
||||
}
|
||||
|
||||
if (d > end) {
|
||||
gskSetOutputColor(color_stops[u_num_color_stops - 1] * u_alpha);
|
||||
return;
|
||||
}
|
||||
int n = u_num_color_stops - 1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float curr_offset = get_offset(i);
|
||||
float next_offset = get_offset(i + 1);
|
||||
|
||||
vec4 color = vec4(0, 0, 0, 0);
|
||||
for (int i = 1; i < u_num_color_stops; i++) {
|
||||
float last_offset = abs_offset(color_offsets[i - 1]);
|
||||
float this_offset = abs_offset(color_offsets[i]);
|
||||
if (offset >= curr_offset && offset < next_offset) {
|
||||
float f = (offset - curr_offset) / (next_offset - curr_offset);
|
||||
vec4 curr_color = gsk_premultiply(get_color(i));
|
||||
vec4 next_color = gsk_premultiply(get_color(i + 1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
|
||||
// We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
|
||||
// We now need to map `d` between those two offsets and simply mix linearly between them
|
||||
if (d >= last_offset && d <= this_offset) {
|
||||
float f = (d - last_offset) / (this_offset - last_offset);
|
||||
|
||||
color = mix(color_stops[i - 1], color_stops[i], f);
|
||||
break;
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
|
||||
}
|
||||
|
||||
@@ -718,7 +718,7 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
for (gsize r = 0; r < regions[i].height; i++)
|
||||
for (gsize r = 0; r < regions[i].height; r++)
|
||||
memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width * 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,11 +51,36 @@ any license fees or royalties.</description>
|
||||
<gnome:userid>matthiasc</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Tim Janik</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:timj@gtk.org"/>
|
||||
<gnome:userid>timj</gnome:userid>
|
||||
<foaf:name>Emmanuele Bassi</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:ebassi@gnome.org"/>
|
||||
<gnome:userid>ebassi</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Timm Baeder</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:mail@baedert.org"/>
|
||||
<gnome:userid>baedert</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Benjamin Otte</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:otte@gnome.org"/>
|
||||
<gnome:userid>otte</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Carlos Garnacho</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:carlosg@gnome.org"/>
|
||||
<gnome:userid>carlosg</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
|
||||
@@ -68,10 +68,8 @@ action_handle_method (GtkAtSpiContext *self,
|
||||
|
||||
g_variant_get (parameters, "(i)", &idx);
|
||||
|
||||
const Action *action = &actions[idx];
|
||||
|
||||
if (idx >= 0 && idx < n_actions)
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->name));
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].name));
|
||||
else
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_IO_ERROR,
|
||||
@@ -129,10 +127,8 @@ action_handle_method (GtkAtSpiContext *self,
|
||||
|
||||
g_variant_get (parameters, "(i)", &idx);
|
||||
|
||||
const Action *action = &actions[idx];
|
||||
|
||||
if (idx >= 0 && idx < n_actions)
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->keybinding));
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].keybinding));
|
||||
else
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_IO_ERROR,
|
||||
|
||||
@@ -58,6 +58,9 @@ struct _GtkAtSpiCache
|
||||
|
||||
/* HashTable<GtkAtSpiContext, str> */
|
||||
GHashTable *contexts_to_path;
|
||||
|
||||
/* Re-entrancy guard */
|
||||
gboolean in_get_items;
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -250,10 +253,17 @@ handle_cache_method (GDBusConnection *connection,
|
||||
{
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(" GET_ITEMS_SIGNATURE ")"));
|
||||
|
||||
/* Prevent the emission os signals while collecting accessible
|
||||
* objects as the result of walking the accessible tree
|
||||
*/
|
||||
self->in_get_items = TRUE;
|
||||
|
||||
g_variant_builder_open (&builder, G_VARIANT_TYPE (GET_ITEMS_SIGNATURE));
|
||||
collect_cached_objects (self, &builder);
|
||||
g_variant_builder_close (&builder);
|
||||
|
||||
self->in_get_items = FALSE;
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
|
||||
}
|
||||
}
|
||||
@@ -371,7 +381,11 @@ gtk_at_spi_cache_add_context (GtkAtSpiCache *self,
|
||||
|
||||
GTK_NOTE (A11Y, g_message ("Adding context '%s' to cache", path_key));
|
||||
|
||||
emit_add_accessible (self, context);
|
||||
/* GetItems is safe from re-entrancy, but we still don't want to
|
||||
* emit an unnecessary signal while we're collecting ATContexts
|
||||
*/
|
||||
if (!self->in_get_items)
|
||||
emit_add_accessible (self, context);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -63,17 +63,12 @@ xml += '\n'
|
||||
for f in get_files('theme/HighContrast/assets', '.svg'):
|
||||
xml += ' <file>theme/HighContrast/assets/{0}</file>\n'.format(f)
|
||||
|
||||
for f in get_files('gesture', '.symbolic.png'):
|
||||
xml += ' <file alias=\'icons/64x64/actions/{0}\'>gesture/{0}</file>\n'.format(f)
|
||||
|
||||
xml += '\n'
|
||||
|
||||
for f in get_files('ui', '.ui'):
|
||||
xml += ' <file preprocess=\'xml-stripblanks\'>ui/{0}</file>\n'.format(f)
|
||||
|
||||
xml += '\n'
|
||||
|
||||
for s in ['16x16', '24x24', '32x32', '48x48', 'scalable']:
|
||||
for s in ['16x16', '32x32', '64x64', 'scalable']:
|
||||
for c in ['actions', 'categories', 'emblems', 'emotes', 'devices', 'mimetypes', 'places', 'status']:
|
||||
icons_dir = 'icons/{0}/{1}'.format(s,c)
|
||||
if os.path.exists(os.path.join(srcdir,icons_dir)):
|
||||
@@ -86,7 +81,6 @@ for f in get_files('inspector', '.ui'):
|
||||
xml += ' <file preprocess=\'xml-stripblanks\'>inspector/{0}</file>\n'.format(f)
|
||||
|
||||
xml += '''
|
||||
<file>inspector/logo.png</file>
|
||||
<file>inspector/inspector.css</file>
|
||||
<file>emoji/en.data</file>
|
||||
</gresource>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
The catalog in this directory defines some widgets that are private
|
||||
to GTK and is needed to edit .ui files defining composite classes
|
||||
in GTK.
|
||||
|
||||
In order to edit any composite classes in GTK, startup Glade
|
||||
in the following way, example:
|
||||
|
||||
cd /path/to/gtk/
|
||||
GLADE_CATALOG_SEARCH_PATH=`pwd`/gtk/glade glade gtk/ui/gtkfilechooserwidget.ui
|
||||
|
||||
Documentation for updating this catalog can be found here:
|
||||
https://developer.gnome.org/gladeui/stable/
|
||||
|
||||
Note also that when including private GTK widgets as components, it is
|
||||
important to call g_type_ensure () to register the type explicitly
|
||||
before calling gtk_container_init_template(), otherwise GtkBuilder will
|
||||
not be able to properly load the type.
|
||||
@@ -1,33 +0,0 @@
|
||||
<glade-catalog name="gtkprivate"
|
||||
version="3.96"
|
||||
depends="gtk4"
|
||||
library="gtk-4">
|
||||
<init-function>gtk_glade_catalog_init</init-function>
|
||||
|
||||
<glade-widget-classes>
|
||||
<!-- base GTK private widgets -->
|
||||
<glade-widget-class name="GtkPathBar" generic-name="pathbar" title="Path Bar" icon-name="widget-gtk-toolbar"/>
|
||||
<glade-widget-class name="GtkColorEditor" generic-name="coloreditor" title="Color Editor" icon-name="widget-gtk-colorselection"/>
|
||||
<glade-widget-class name="GtkColorSwatch" generic-name="colorswatch" title="Color Swatch" icon-name="widget-gtk-colorselection"/>
|
||||
<glade-widget-class name="GtkColorPlane" generic-name="colorplane" title="Color Plane" icon-name="widget-gtk-colorselection"/>
|
||||
<glade-widget-class name="GtkColorScale" generic-name="colorscale" title="Color Scale" icon-name="widget-gtk-colorselection"/>
|
||||
|
||||
<!-- gtkunixprint private widgets -->
|
||||
<glade-widget-class name="GtkPrinterOptionWidget" generic-name="printeroptionwidget" title="Printer Option Widget"
|
||||
icon-name="widget-gtk-frame">
|
||||
<properties>
|
||||
<property id="orientation" default="GTK_ORIENTATION_HORIZONTAL"/>
|
||||
<property id="size" disabled="True"/>
|
||||
</properties>
|
||||
</glade-widget-class>
|
||||
</glade-widget-classes>
|
||||
|
||||
<glade-widget-group name="gtk-private" title="Private GTK Classes">
|
||||
<glade-widget-class-ref name="GtkPathBar"/>
|
||||
<glade-widget-class-ref name="GtkColorEditor"/>
|
||||
<glade-widget-class-ref name="GtkColorSwatch"/>
|
||||
<glade-widget-class-ref name="GtkColorPlane"/>
|
||||
<glade-widget-class-ref name="GtkColorScale"/>
|
||||
<glade-widget-class-ref name="GtkPrinterOptionWidget"/>
|
||||
</glade-widget-group>
|
||||
</glade-catalog>
|
||||
@@ -315,6 +315,17 @@ stack_visible_child_notify (GtkStack *stack,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_about_dialog_map (GtkWidget *widget)
|
||||
{
|
||||
GtkAboutDialog *about = GTK_ABOUT_DIALOG (widget);
|
||||
|
||||
if (gtk_widget_get_visible (about->stack_switcher))
|
||||
gtk_widget_grab_focus (gtk_widget_get_first_child (about->stack_switcher));
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_about_dialog_parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_about_dialog_class_init (GtkAboutDialogClass *klass)
|
||||
{
|
||||
@@ -329,6 +340,8 @@ gtk_about_dialog_class_init (GtkAboutDialogClass *klass)
|
||||
|
||||
object_class->finalize = gtk_about_dialog_finalize;
|
||||
|
||||
widget_class->map = gtk_about_dialog_map;
|
||||
|
||||
klass->activate_link = gtk_about_dialog_activate_link;
|
||||
|
||||
/**
|
||||
|
||||
+7
-5
@@ -496,12 +496,12 @@ gtk_accessible_update_relation_value (GtkAccessible *self,
|
||||
GtkAccessibleRelation relations[],
|
||||
const GValue values[])
|
||||
{
|
||||
GtkATContext *context;
|
||||
|
||||
g_return_if_fail (GTK_IS_ACCESSIBLE (self));
|
||||
g_return_if_fail (n_relations > 0);
|
||||
|
||||
GtkATContext *context = gtk_accessible_get_at_context (self);
|
||||
if (context == NULL)
|
||||
return;
|
||||
context = gtk_accessible_get_at_context (self);
|
||||
|
||||
for (int i = 0; i < n_relations; i++)
|
||||
{
|
||||
@@ -520,13 +520,15 @@ gtk_accessible_update_relation_value (GtkAccessible *self,
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_at_context_set_accessible_relation (context, relation, real_value);
|
||||
if (context)
|
||||
gtk_at_context_set_accessible_relation (context, relation, real_value);
|
||||
|
||||
if (real_value != NULL)
|
||||
gtk_accessible_value_unref (real_value);
|
||||
}
|
||||
|
||||
gtk_at_context_update (context);
|
||||
if (context)
|
||||
gtk_at_context_update (context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
#include "gtkprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -25,9 +25,9 @@
|
||||
#include "gtkorientable.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkboxlayout
|
||||
|
||||
+24
-20
@@ -260,7 +260,7 @@ typedef struct
|
||||
char *domain;
|
||||
GHashTable *objects;
|
||||
GSList *delayed_properties;
|
||||
GSList *signals;
|
||||
GPtrArray *signals;
|
||||
GSList *bindings;
|
||||
char *filename;
|
||||
char *resource_prefix;
|
||||
@@ -375,8 +375,8 @@ gtk_builder_finalize (GObject *object)
|
||||
#endif
|
||||
|
||||
g_hash_table_destroy (priv->objects);
|
||||
|
||||
g_slist_free_full (priv->signals, (GDestroyNotify)_free_signal_info);
|
||||
if (priv->signals)
|
||||
g_ptr_array_free (priv->signals, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (gtk_builder_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -527,19 +527,21 @@ static void
|
||||
gtk_builder_get_parameters (GtkBuilder *builder,
|
||||
GType object_type,
|
||||
const char *object_name,
|
||||
GSList *properties,
|
||||
GPtrArray *properties,
|
||||
GParamFlags filter_flags,
|
||||
ObjectProperties *parameters,
|
||||
ObjectProperties *filtered_parameters)
|
||||
{
|
||||
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
|
||||
GSList *l;
|
||||
DelayedProperty *property;
|
||||
GError *error = NULL;
|
||||
|
||||
for (l = properties; l; l = l->next)
|
||||
if (!properties)
|
||||
return;
|
||||
|
||||
for (guint i = 0; i < properties->len; i++)
|
||||
{
|
||||
PropertyInfo *prop = (PropertyInfo*)l->data;
|
||||
PropertyInfo *prop = g_ptr_array_index (properties, i);
|
||||
const char *property_name = g_intern_string (prop->pspec->name);
|
||||
GValue property_value = G_VALUE_INIT;
|
||||
|
||||
@@ -1018,12 +1020,14 @@ _gtk_builder_add (GtkBuilder *builder,
|
||||
|
||||
void
|
||||
_gtk_builder_add_signals (GtkBuilder *builder,
|
||||
GSList *signals)
|
||||
GPtrArray *signals)
|
||||
{
|
||||
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
|
||||
|
||||
priv->signals = g_slist_concat (priv->signals,
|
||||
g_slist_copy (signals));
|
||||
if (G_UNLIKELY (!priv->signals))
|
||||
priv->signals = g_ptr_array_new_with_free_func ((GDestroyNotify)_free_signal_info);
|
||||
|
||||
g_ptr_array_extend_and_steal (priv->signals, signals);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1851,18 +1855,17 @@ gtk_builder_connect_signals (GtkBuilder *builder,
|
||||
GError **error)
|
||||
{
|
||||
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
|
||||
GSList *l;
|
||||
GObject *object;
|
||||
GObject *connect_object;
|
||||
gboolean result = FALSE;
|
||||
gboolean result = TRUE;
|
||||
|
||||
if (!priv->signals)
|
||||
if (!priv->signals ||
|
||||
priv->signals->len == 0)
|
||||
return TRUE;
|
||||
|
||||
priv->signals = g_slist_reverse (priv->signals);
|
||||
for (l = priv->signals; l; l = l->next)
|
||||
for (guint i = 0; i < priv->signals->len; i++)
|
||||
{
|
||||
SignalInfo *signal = (SignalInfo*)l->data;
|
||||
SignalInfo *signal = g_ptr_array_index (priv->signals, i);
|
||||
GClosure *closure;
|
||||
|
||||
g_assert (signal != NULL);
|
||||
@@ -1895,7 +1898,10 @@ gtk_builder_connect_signals (GtkBuilder *builder,
|
||||
error);
|
||||
|
||||
if (closure == NULL)
|
||||
break;
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
g_signal_connect_closure_by_id (object,
|
||||
signal->id,
|
||||
@@ -1903,10 +1909,8 @@ gtk_builder_connect_signals (GtkBuilder *builder,
|
||||
closure,
|
||||
signal->flags & G_CONNECT_AFTER ? TRUE : FALSE);
|
||||
}
|
||||
if (l == NULL)
|
||||
result = TRUE;
|
||||
|
||||
g_slist_free_full (priv->signals, (GDestroyNotify)_free_signal_info);
|
||||
g_ptr_array_free (priv->signals, TRUE);
|
||||
priv->signals = NULL;
|
||||
|
||||
return result;
|
||||
|
||||
+51
-30
@@ -32,7 +32,8 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
const GtkBuildableParser *last_parser;
|
||||
gpointer last_user_data;
|
||||
int last_depth;
|
||||
@@ -41,9 +42,8 @@ typedef struct {
|
||||
static void
|
||||
pop_subparser_stack (GtkBuildableParseContext *context)
|
||||
{
|
||||
GtkBuildableParserStack *stack =
|
||||
&g_array_index (context->subparser_stack, GtkBuildableParserStack,
|
||||
context->subparser_stack->len - 1);
|
||||
GtkBuildableParserStack *stack = &g_array_index (context->subparser_stack, GtkBuildableParserStack,
|
||||
context->subparser_stack->len - 1);
|
||||
|
||||
context->awaiting_pop = TRUE;
|
||||
context->held_user_data = context->user_data;
|
||||
@@ -57,15 +57,17 @@ pop_subparser_stack (GtkBuildableParseContext *context)
|
||||
static void
|
||||
possibly_finish_subparser (GtkBuildableParseContext *context)
|
||||
{
|
||||
if (context->subparser_stack->len > 0)
|
||||
{
|
||||
GtkBuildableParserStack *stack =
|
||||
&g_array_index (context->subparser_stack, GtkBuildableParserStack,
|
||||
context->subparser_stack->len - 1);
|
||||
GtkBuildableParserStack *stack;
|
||||
|
||||
if (stack->last_depth == context->tag_stack->len)
|
||||
pop_subparser_stack (context);
|
||||
}
|
||||
if (!context->subparser_stack ||
|
||||
context->subparser_stack->len == 0)
|
||||
return;
|
||||
|
||||
stack = &g_array_index (context->subparser_stack, GtkBuildableParserStack,
|
||||
context->subparser_stack->len - 1);
|
||||
|
||||
if (stack->last_depth == context->tag_stack->len)
|
||||
pop_subparser_stack (context);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -128,6 +130,9 @@ proxy_error (GMarkupParseContext *gm_context,
|
||||
|
||||
/* report the error all the way up to free all the user-data */
|
||||
|
||||
if (!context->subparser_stack)
|
||||
return;
|
||||
|
||||
while (context->subparser_stack->len > 0)
|
||||
{
|
||||
pop_subparser_stack (context);
|
||||
@@ -157,7 +162,7 @@ gtk_buildable_parse_context_init (GtkBuildableParseContext *context,
|
||||
context->parser = parser;
|
||||
context->user_data = user_data;
|
||||
|
||||
context->subparser_stack = g_array_new (FALSE, FALSE, sizeof (GtkBuildableParserStack));
|
||||
context->subparser_stack = NULL;
|
||||
context->tag_stack = g_ptr_array_new ();
|
||||
context->held_user_data = NULL;
|
||||
context->awaiting_pop = FALSE;
|
||||
@@ -166,7 +171,9 @@ gtk_buildable_parse_context_init (GtkBuildableParseContext *context,
|
||||
static void
|
||||
gtk_buildable_parse_context_free (GtkBuildableParseContext *context)
|
||||
{
|
||||
g_array_unref (context->subparser_stack);
|
||||
if (context->subparser_stack)
|
||||
g_array_unref (context->subparser_stack);
|
||||
|
||||
g_ptr_array_unref (context->tag_stack);
|
||||
}
|
||||
|
||||
@@ -245,6 +252,9 @@ gtk_buildable_parse_context_push (GtkBuildableParseContext *context,
|
||||
context->parser = parser;
|
||||
context->user_data = user_data;
|
||||
|
||||
if (!context->subparser_stack)
|
||||
context->subparser_stack = g_array_new (FALSE, FALSE, sizeof (GtkBuildableParserStack));
|
||||
|
||||
g_array_append_val (context->subparser_stack, stack);
|
||||
}
|
||||
|
||||
@@ -461,8 +471,6 @@ builder_construct (ParserData *data,
|
||||
if (object_info->object && object_info->applied_properties)
|
||||
return object_info->object;
|
||||
|
||||
object_info->properties = g_slist_reverse (object_info->properties);
|
||||
|
||||
if (object_info->object == NULL)
|
||||
{
|
||||
object = _gtk_builder_construct (data->builder, object_info, error);
|
||||
@@ -789,19 +797,21 @@ free_object_info (ObjectInfo *info)
|
||||
{
|
||||
/* Do not free the signal items, which GtkBuilder takes ownership of */
|
||||
g_type_class_unref (info->oclass);
|
||||
g_slist_free (info->signals);
|
||||
g_slist_free_full (info->properties, (GDestroyNotify)free_property_info);
|
||||
if (info->signals)
|
||||
g_ptr_array_free (info->signals, TRUE);
|
||||
if (info->properties)
|
||||
g_ptr_array_free (info->properties, TRUE);
|
||||
g_free (info->constructor);
|
||||
g_free (info->id);
|
||||
g_slice_free (ObjectInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_child (ParserData *data,
|
||||
const char *element_name,
|
||||
parse_child (ParserData *data,
|
||||
const char *element_name,
|
||||
const char **names,
|
||||
const char **values,
|
||||
GError **error)
|
||||
GError **error)
|
||||
|
||||
{
|
||||
ObjectInfo* object_info;
|
||||
@@ -1697,7 +1707,6 @@ parse_custom (GtkBuildableParseContext *context,
|
||||
ObjectInfo* object_info = (ObjectInfo*)parent_info;
|
||||
if (!object_info->object)
|
||||
{
|
||||
object_info->properties = g_slist_reverse (object_info->properties);
|
||||
object_info->object = _gtk_builder_construct (data->builder,
|
||||
object_info,
|
||||
error);
|
||||
@@ -1875,7 +1884,10 @@ end_element (GtkBuildableParseContext *context,
|
||||
g_string_assign (prop_info->text, translated);
|
||||
}
|
||||
|
||||
object_info->properties = g_slist_prepend (object_info->properties, prop_info);
|
||||
if (G_UNLIKELY (!object_info->properties))
|
||||
object_info->properties = g_ptr_array_new_with_free_func ((GDestroyNotify)free_property_info);
|
||||
|
||||
g_ptr_array_add (object_info->properties, prop_info);
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
@@ -1943,8 +1955,13 @@ end_element (GtkBuildableParseContext *context,
|
||||
|
||||
if (GTK_IS_BUILDABLE (object_info->object) &&
|
||||
GTK_BUILDABLE_GET_IFACE (object_info->object)->parser_finished)
|
||||
data->finalizers = g_slist_prepend (data->finalizers, object_info->object);
|
||||
_gtk_builder_add_signals (data->builder, object_info->signals);
|
||||
g_ptr_array_add (data->finalizers, object_info->object);
|
||||
|
||||
if (object_info->signals)
|
||||
{
|
||||
_gtk_builder_add_signals (data->builder, object_info->signals);
|
||||
object_info->signals = NULL;
|
||||
}
|
||||
|
||||
free_object_info (object_info);
|
||||
}
|
||||
@@ -1962,7 +1979,11 @@ end_element (GtkBuildableParseContext *context,
|
||||
ObjectInfo *object_info = (ObjectInfo*)state_peek_info (data, CommonInfo);
|
||||
g_assert (object_info != NULL);
|
||||
signal_info->object_name = g_strdup (object_info->id);
|
||||
object_info->signals = g_slist_prepend (object_info->signals, signal_info);
|
||||
|
||||
if (G_UNLIKELY (!object_info->signals))
|
||||
object_info->signals = g_ptr_array_new ();
|
||||
|
||||
g_ptr_array_add (object_info->signals, signal_info);
|
||||
}
|
||||
else if (strcmp (element_name, "constant") == 0 ||
|
||||
strcmp (element_name, "closure") == 0 ||
|
||||
@@ -2154,6 +2175,7 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
|
||||
data.object_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify)g_free, NULL);
|
||||
data.stack = g_ptr_array_new ();
|
||||
data.finalizers = g_ptr_array_new ();
|
||||
|
||||
if (requested_objs)
|
||||
{
|
||||
@@ -2193,10 +2215,9 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
|
||||
}
|
||||
|
||||
/* Common parser_finished, for all created objects */
|
||||
data.finalizers = g_slist_reverse (data.finalizers);
|
||||
for (l = data.finalizers; l; l = l->next)
|
||||
for (guint i = 0; i < data.finalizers->len; i++)
|
||||
{
|
||||
GtkBuildable *buildable = (GtkBuildable*)l->data;
|
||||
GtkBuildable *buildable = g_ptr_array_index (data.finalizers, i);
|
||||
|
||||
gtk_buildable_parser_finished (GTK_BUILDABLE (buildable), builder);
|
||||
if (_gtk_builder_lookup_failed (builder, error))
|
||||
@@ -2206,10 +2227,10 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
|
||||
out:
|
||||
|
||||
g_slist_free_full (data.custom_finalizers, (GDestroyNotify)free_subparser);
|
||||
g_slist_free (data.finalizers);
|
||||
g_free (data.domain);
|
||||
g_hash_table_destroy (data.object_ids);
|
||||
g_ptr_array_free (data.stack, TRUE);
|
||||
g_ptr_array_free (data.finalizers, TRUE);
|
||||
gtk_buildable_parse_context_free (&data.ctx);
|
||||
|
||||
/* restore the original domain */
|
||||
|
||||
@@ -46,9 +46,11 @@ typedef struct {
|
||||
GObjectClass *oclass;
|
||||
char *id;
|
||||
char *constructor;
|
||||
GSList *properties;
|
||||
GSList *signals;
|
||||
|
||||
GPtrArray *properties;
|
||||
GPtrArray *signals;
|
||||
GSList *bindings;
|
||||
|
||||
GObject *object;
|
||||
CommonInfo *parent;
|
||||
gboolean applied_properties;
|
||||
@@ -177,7 +179,7 @@ typedef struct {
|
||||
SubParser *subparser;
|
||||
GtkBuildableParseContext ctx;
|
||||
const char *filename;
|
||||
GSList *finalizers;
|
||||
GPtrArray *finalizers;
|
||||
GSList *custom_finalizers;
|
||||
|
||||
const char **requested_objects; /* NULL if all the objects are requested */
|
||||
@@ -218,7 +220,7 @@ void _gtk_builder_add_object (GtkBuilder *builder,
|
||||
void _gtk_builder_add (GtkBuilder *builder,
|
||||
ChildInfo *child_info);
|
||||
void _gtk_builder_add_signals (GtkBuilder *builder,
|
||||
GSList *signals);
|
||||
GPtrArray *signals);
|
||||
gboolean _gtk_builder_finish (GtkBuilder *builder,
|
||||
GError **error);
|
||||
void _free_signal_info (SignalInfo *info,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkbuiltiniconprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
@@ -80,10 +80,11 @@ gtk_builtin_icon_measure (GtkWidget *widget,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkCssValue *icon_size;
|
||||
GtkCssStyle *style;
|
||||
|
||||
icon_size = _gtk_style_context_peek_property (gtk_widget_get_style_context (widget), GTK_CSS_PROPERTY_ICON_SIZE);
|
||||
*minimum = *natural = _gtk_css_number_value_get (icon_size, 100);
|
||||
style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
|
||||
|
||||
*minimum = *natural = _gtk_css_number_value_get (style->icon->icon_size, 100);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -310,14 +310,10 @@ click_pressed_cb (GtkGestureClick *gesture,
|
||||
{
|
||||
GtkButton *button = GTK_BUTTON (widget);
|
||||
GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
|
||||
GdkEventSequence *sequence;
|
||||
|
||||
if (gtk_widget_get_focus_on_click (widget) && !gtk_widget_has_focus (widget))
|
||||
gtk_widget_grab_focus (widget);
|
||||
|
||||
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
||||
gtk_gesture_set_sequence_state (GTK_GESTURE (gesture), sequence, GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
|
||||
if (!priv->activate_timeout)
|
||||
priv->button_down = TRUE;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,6 @@
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkrendericonprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkgestureclick.h"
|
||||
#include "gtkgesturedrag.h"
|
||||
|
||||
+11
-28
@@ -20,6 +20,7 @@
|
||||
#include "gtkcellrenderertoggle.h"
|
||||
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcsstransientnodeprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
@@ -126,26 +127,12 @@ gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle)
|
||||
priv->active = FALSE;
|
||||
priv->radio = FALSE;
|
||||
|
||||
priv->cssnode = gtk_css_node_new ();
|
||||
gtk_css_node_set_name (priv->cssnode, g_quark_from_static_string ("check"));
|
||||
|
||||
g_object_set (celltoggle, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
|
||||
gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (celltoggle), 2, 2);
|
||||
|
||||
priv->inconsistent = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cell_renderer_toggle_dispose (GObject *object)
|
||||
{
|
||||
GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
|
||||
GtkCellRendererTogglePrivate *priv = gtk_cell_renderer_toggle_get_instance_private (celltoggle);
|
||||
|
||||
g_clear_object (&priv->cssnode);
|
||||
|
||||
G_OBJECT_CLASS (gtk_cell_renderer_toggle_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
gtk_cell_renderer_toggle_get_request_mode (GtkCellRenderer *cell)
|
||||
{
|
||||
@@ -196,7 +183,6 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
|
||||
|
||||
object_class->get_property = gtk_cell_renderer_toggle_get_property;
|
||||
object_class->set_property = gtk_cell_renderer_toggle_set_property;
|
||||
object_class->dispose = gtk_cell_renderer_toggle_dispose;
|
||||
|
||||
cell_class->get_request_mode = gtk_cell_renderer_toggle_get_request_mode;
|
||||
cell_class->get_preferred_width = gtk_cell_renderer_toggle_get_preferred_width;
|
||||
@@ -356,29 +342,30 @@ gtk_cell_renderer_toggle_new (void)
|
||||
|
||||
static GtkStyleContext *
|
||||
gtk_cell_renderer_toggle_save_context (GtkCellRendererToggle *cell,
|
||||
GtkWidget *widget)
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkCellRendererTogglePrivate *priv = gtk_cell_renderer_toggle_get_instance_private (cell);
|
||||
GtkStyleContext *context;
|
||||
GtkCssNode *cssnode;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_css_node_set_parent (priv->cssnode, gtk_widget_get_css_node (widget));
|
||||
gtk_style_context_save_to_node (context, priv->cssnode);
|
||||
cssnode = gtk_css_transient_node_new (gtk_widget_get_css_node (widget));
|
||||
if (priv->radio)
|
||||
gtk_css_node_set_name (cssnode, g_quark_from_static_string ("radio"));
|
||||
else
|
||||
gtk_css_node_set_name (cssnode, g_quark_from_static_string ("check"));
|
||||
gtk_style_context_save_to_node (context, cssnode);
|
||||
g_object_unref (cssnode);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
static void
|
||||
gtk_cell_renderer_toggle_restore_context (GtkCellRendererToggle *cell,
|
||||
GtkStyleContext *context)
|
||||
{
|
||||
GtkCellRendererTogglePrivate *priv = gtk_cell_renderer_toggle_get_instance_private (cell);
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
gtk_css_node_set_parent (priv->cssnode, NULL);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -564,10 +551,6 @@ gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
|
||||
g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
|
||||
|
||||
priv->radio = radio;
|
||||
if (radio)
|
||||
gtk_css_node_set_name (priv->cssnode, g_quark_from_static_string ("radio"));
|
||||
else
|
||||
gtk_css_node_set_name (priv->cssnode, g_quark_from_static_string ("check"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
#include "gtklayoutchild.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkcenterlayout
|
||||
@@ -58,12 +58,13 @@ G_DEFINE_TYPE (GtkCenterLayout, gtk_center_layout, GTK_TYPE_LAYOUT_MANAGER)
|
||||
|
||||
static int
|
||||
get_spacing (GtkCenterLayout *self,
|
||||
GtkStyleContext *style_context)
|
||||
GtkCssNode *node)
|
||||
{
|
||||
GtkCssStyle *style = gtk_css_node_get_style (node);
|
||||
GtkCssValue *border_spacing;
|
||||
int css_spacing;
|
||||
|
||||
border_spacing = _gtk_style_context_peek_property (style_context, GTK_CSS_PROPERTY_BORDER_SPACING);
|
||||
border_spacing = style->size->border_spacing;
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
css_spacing = _gtk_css_position_value_get_x (border_spacing, 100);
|
||||
else
|
||||
@@ -226,7 +227,7 @@ gtk_center_layout_measure_orientation (GtkCenterLayout *self,
|
||||
int spacing;
|
||||
int i;
|
||||
|
||||
spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
|
||||
spacing = get_spacing (self, gtk_widget_get_css_node (widget));
|
||||
|
||||
for (i = 0; i < 3; i ++)
|
||||
{
|
||||
@@ -386,7 +387,7 @@ gtk_center_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
int i;
|
||||
int spacing;
|
||||
|
||||
spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
|
||||
spacing = get_spacing (self, gtk_widget_get_css_node (widget));
|
||||
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
|
||||
+53
-3
@@ -34,7 +34,8 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkshortcuttrigger.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkmodelbuttonprivate.h"
|
||||
|
||||
@@ -94,6 +95,7 @@ enum {
|
||||
|
||||
enum {
|
||||
TOGGLED,
|
||||
ACTIVATE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@@ -276,8 +278,6 @@ click_pressed_cb (GtkGestureClick *gesture,
|
||||
{
|
||||
if (gtk_widget_get_focus_on_click (widget) && !gtk_widget_has_focus (widget))
|
||||
gtk_widget_grab_focus (widget);
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -293,6 +293,8 @@ click_released_cb (GtkGestureClick *gesture,
|
||||
if (priv->active && (priv->group_prev || priv->group_next))
|
||||
return;
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
|
||||
gtk_check_button_set_active (self, !priv->active);
|
||||
|
||||
if (priv->action_helper)
|
||||
@@ -442,11 +444,26 @@ gtk_check_button_focus (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_check_button_real_activate (GtkCheckButton *check_button)
|
||||
{
|
||||
gtk_check_button_set_active (check_button,
|
||||
!gtk_check_button_get_active (check_button));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_check_button_class_init (GtkCheckButtonClass *class)
|
||||
{
|
||||
const guint activate_keyvals[] = {
|
||||
GDK_KEY_space,
|
||||
GDK_KEY_KP_Space,
|
||||
GDK_KEY_Return,
|
||||
GDK_KEY_ISO_Enter,
|
||||
GDK_KEY_KP_Enter
|
||||
};
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GtkShortcutAction *activate_action;
|
||||
|
||||
object_class->dispose = gtk_check_button_dispose;
|
||||
object_class->set_property = gtk_check_button_set_property;
|
||||
@@ -454,6 +471,8 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
|
||||
|
||||
widget_class->focus = gtk_check_button_focus;
|
||||
|
||||
class->activate = gtk_check_button_real_activate;
|
||||
|
||||
props[PROP_ACTIVE] =
|
||||
g_param_spec_boolean ("active",
|
||||
P_("Active"),
|
||||
@@ -507,6 +526,37 @@ gtk_check_button_class_init (GtkCheckButtonClass *class)
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GtkCheckButton::activate:
|
||||
* @widget: the object which received the signal.
|
||||
*
|
||||
* The ::activate signal on GtkCheckButton is an action signal and
|
||||
* emitting it causes the button to animate press then release.
|
||||
* Applications should never connect to this signal, but use the
|
||||
* #GtkCheckButton::toggled signal.
|
||||
*/
|
||||
signals[ACTIVATE] =
|
||||
g_signal_new (I_ ("activate"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GtkCheckButtonClass, activate),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
gtk_widget_class_set_activate_signal (widget_class, signals[ACTIVATE]);
|
||||
|
||||
activate_action = gtk_signal_action_new ("activate");
|
||||
for (guint i = 0; i < G_N_ELEMENTS (activate_keyvals); i++)
|
||||
{
|
||||
GtkShortcut *activate_shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (activate_keyvals[i], 0),
|
||||
g_object_ref (activate_action));
|
||||
|
||||
gtk_widget_class_add_shortcut (widget_class, activate_shortcut);
|
||||
g_object_unref (activate_shortcut);
|
||||
}
|
||||
g_object_unref (activate_action);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
|
||||
gtk_widget_class_set_css_name (widget_class, I_("checkbutton"));
|
||||
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_CHECKBOX);
|
||||
|
||||
@@ -56,9 +56,10 @@ struct _GtkCheckButtonClass
|
||||
GtkWidgetClass parent_class;
|
||||
|
||||
void (* toggled) (GtkCheckButton *check_button);
|
||||
void (* activate) (GtkCheckButton *check_button);
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[8];
|
||||
gpointer padding[7];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "gtkpopovermenu.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtknative.h"
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkgesturedrag.h"
|
||||
#include "gtkeventcontrollermotion.h"
|
||||
#include "gtkdragsource.h"
|
||||
#include "gtkdragsourceprivate.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkgestureclick.h"
|
||||
|
||||
@@ -1128,7 +1128,7 @@ header_drag_update (GtkGestureDrag *gesture,
|
||||
|
||||
if (!self->in_column_resize && !self->in_column_reorder)
|
||||
{
|
||||
if (gtk_drag_check_threshold (GTK_WIDGET (self), 0, 0, offset_x, 0))
|
||||
if (gtk_drag_check_threshold_double (GTK_WIDGET (self), 0, 0, offset_x, 0))
|
||||
{
|
||||
GtkColumnViewColumn *column;
|
||||
GtkWidget *header;
|
||||
|
||||
+10
-10
@@ -28,7 +28,7 @@
|
||||
#include "gtklabel.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkbox.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtkbuiltiniconprivate.h"
|
||||
#include "gtkgestureclick.h"
|
||||
#include "gtkpopovermenu.h"
|
||||
#include "gtknative.h"
|
||||
@@ -266,7 +266,7 @@ gtk_column_view_title_init (GtkColumnViewTitle *self)
|
||||
self->title = gtk_label_new (NULL);
|
||||
gtk_box_append (GTK_BOX (self->box), self->title);
|
||||
|
||||
self->sort = gtk_image_new ();
|
||||
self->sort = gtk_builtin_icon_new ("sort-indicator");
|
||||
gtk_box_append (GTK_BOX (self->box), self->sort);
|
||||
|
||||
gesture = gtk_gesture_click_new ();
|
||||
@@ -308,15 +308,15 @@ gtk_column_view_title_update (GtkColumnViewTitle *self)
|
||||
active = gtk_column_view_sorter_get_sort_column (view_sorter, &inverted);
|
||||
|
||||
gtk_widget_show (self->sort);
|
||||
if (self->column == active)
|
||||
{
|
||||
if (inverted)
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->sort), "pan-down-symbolic");
|
||||
else
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->sort), "pan-up-symbolic");
|
||||
}
|
||||
gtk_widget_remove_css_class (self->sort, "ascending");
|
||||
gtk_widget_remove_css_class (self->sort, "descending");
|
||||
gtk_widget_remove_css_class (self->sort, "unsorted");
|
||||
if (self->column != active)
|
||||
gtk_widget_add_css_class (self->sort, "unsorted");
|
||||
else if (inverted)
|
||||
gtk_widget_add_css_class (self->sort, "descending");
|
||||
else
|
||||
gtk_image_clear (GTK_IMAGE (self->sort));
|
||||
gtk_widget_add_css_class (self->sort, "ascending");
|
||||
}
|
||||
else
|
||||
gtk_widget_hide (self->sort);
|
||||
|
||||
+567
-177
@@ -26,16 +26,17 @@
|
||||
#include "gtkcomposetable.h"
|
||||
#include "gtkimcontextsimple.h"
|
||||
|
||||
#include "gtkimcontextsimpleprivate.h"
|
||||
|
||||
|
||||
#define GTK_COMPOSE_TABLE_MAGIC "GtkComposeTable"
|
||||
#define GTK_COMPOSE_TABLE_VERSION (1)
|
||||
#define GTK_COMPOSE_TABLE_VERSION (2)
|
||||
|
||||
/* Maximum length of sequences we parse */
|
||||
|
||||
#define MAX_COMPOSE_LEN 20
|
||||
|
||||
typedef struct {
|
||||
gunichar *sequence;
|
||||
gunichar value[2];
|
||||
char *comment;
|
||||
gunichar *sequence;
|
||||
char *value;
|
||||
} GtkComposeData;
|
||||
|
||||
|
||||
@@ -43,7 +44,7 @@ static void
|
||||
gtk_compose_data_free (GtkComposeData *compose_data)
|
||||
{
|
||||
g_free (compose_data->sequence);
|
||||
g_free (compose_data->comment);
|
||||
g_free (compose_data->value);
|
||||
g_slice_free (GtkComposeData, compose_data);
|
||||
}
|
||||
|
||||
@@ -76,58 +77,82 @@ parse_compose_value (GtkComposeData *compose_data,
|
||||
const char *val,
|
||||
const char *line)
|
||||
{
|
||||
char **words = g_strsplit (val, "\"", 3);
|
||||
gunichar uch;
|
||||
char *word;
|
||||
const char *p;
|
||||
gsize len;
|
||||
GString *value;
|
||||
gunichar ch;
|
||||
char *endp;
|
||||
|
||||
if (g_strv_length (words) < 3)
|
||||
len = strlen (val);
|
||||
if (val[0] != '"' || val[len - 1] != '"')
|
||||
{
|
||||
g_warning ("Need to double-quote the value: %s: %s", val, line);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uch = g_utf8_get_char (words[1]);
|
||||
word = g_strndup (val + 1, len - 2);
|
||||
|
||||
if (uch == 0)
|
||||
{
|
||||
g_warning ("Invalid value: %s: %s", val, line);
|
||||
goto fail;
|
||||
}
|
||||
else if (uch == '\\')
|
||||
{
|
||||
uch = words[1][1];
|
||||
value = g_string_new ("");
|
||||
|
||||
/* The escaped string "\"" is separated with '\\' and '"'. */
|
||||
if (uch == '\0' && words[2][0] == '"')
|
||||
uch = '"';
|
||||
/* The escaped octal */
|
||||
else if (uch >= '0' && uch <= '8')
|
||||
uch = g_ascii_strtoll(words[1] + 1, NULL, 8);
|
||||
/* If we need to handle other escape sequences. */
|
||||
else if (uch != '\\')
|
||||
p = word;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '\\')
|
||||
{
|
||||
g_warning ("Invalid escape sequence: %s: %s", val, line);
|
||||
if (p[1] == '"')
|
||||
{
|
||||
g_string_append_c (value, '"');
|
||||
p += 2;
|
||||
}
|
||||
else if (p[1] == '\\')
|
||||
{
|
||||
g_string_append_c (value, '\\');
|
||||
p += 2;
|
||||
}
|
||||
else if (p[1] >= '0' && p[1] < '8')
|
||||
{
|
||||
ch = g_ascii_strtoll (p + 1, &endp, 8);
|
||||
if (ch == 0)
|
||||
{
|
||||
g_warning ("Invalid escape sequence: %s: %s", val, line);
|
||||
goto fail;
|
||||
}
|
||||
g_string_append_unichar (value, ch);
|
||||
p = endp;
|
||||
}
|
||||
else if (p[1] == 'x' || p[1] == 'X')
|
||||
{
|
||||
ch = g_ascii_strtoll (p + 2, &endp, 16);
|
||||
if (ch == 0)
|
||||
{
|
||||
g_warning ("Invalid escape sequence: %s: %s", val, line);
|
||||
goto fail;
|
||||
}
|
||||
g_string_append_unichar (value, ch);
|
||||
p = endp;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Invalid escape sequence: %s: %s", val, line);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = g_utf8_get_char (p);
|
||||
g_string_append_unichar (value, ch);
|
||||
p = g_utf8_next_char (p);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_utf8_get_char (g_utf8_next_char (words[1])) > 0)
|
||||
{
|
||||
g_warning ("GTK supports to output one char only: %s: %s", val, line);
|
||||
goto fail;
|
||||
}
|
||||
compose_data->value = g_string_free (value, FALSE);
|
||||
|
||||
compose_data->value[1] = uch;
|
||||
|
||||
if (uch == '"')
|
||||
compose_data->comment = g_strdup (g_strstrip (words[2] + 1));
|
||||
else
|
||||
compose_data->comment = g_strdup (g_strstrip (words[2]));
|
||||
|
||||
g_strfreev (words);
|
||||
g_free (word);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
g_strfreev (words);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -189,10 +214,10 @@ parse_compose_sequence (GtkComposeData *compose_data,
|
||||
}
|
||||
|
||||
g_strfreev (words);
|
||||
if (0 == n || n >= GTK_MAX_COMPOSE_LEN)
|
||||
if (0 == n || n > MAX_COMPOSE_LEN)
|
||||
{
|
||||
g_warning ("The max number of sequences is %d: %s",
|
||||
GTK_MAX_COMPOSE_LEN, line);
|
||||
g_warning ("Suspicious compose sequence length (%d). Are you sure this is right?: %s",
|
||||
n, line);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -214,7 +239,10 @@ parse_compose_line (GList **compose_list,
|
||||
return;
|
||||
|
||||
if (g_str_has_prefix (line, "include "))
|
||||
return;
|
||||
{
|
||||
g_warning ("include in Compose files not supported: %s", line);
|
||||
return;
|
||||
}
|
||||
|
||||
components = g_strsplit (line, ":", 2);
|
||||
|
||||
@@ -244,6 +272,8 @@ fail:
|
||||
gtk_compose_data_free (compose_data);
|
||||
}
|
||||
|
||||
extern const GtkComposeTableCompact gtk_compose_table_compact;
|
||||
|
||||
static GList *
|
||||
gtk_compose_list_parse_file (const char *compose_file)
|
||||
{
|
||||
@@ -279,18 +309,19 @@ gtk_compose_list_check_duplicated (GList *compose_list)
|
||||
|
||||
for (list = compose_list; list != NULL; list = list->next)
|
||||
{
|
||||
static guint16 keysyms[GTK_MAX_COMPOSE_LEN + 1];
|
||||
static guint16 keysyms[MAX_COMPOSE_LEN + 1];
|
||||
int i;
|
||||
int n_compose = 0;
|
||||
gboolean compose_finish;
|
||||
gunichar output_char;
|
||||
char buf[8] = { 0, };
|
||||
|
||||
compose_data = list->data;
|
||||
|
||||
for (i = 0; i < GTK_MAX_COMPOSE_LEN + 1; i++)
|
||||
for (i = 0; i < MAX_COMPOSE_LEN + 1; i++)
|
||||
keysyms[i] = 0;
|
||||
|
||||
for (i = 0; i < GTK_MAX_COMPOSE_LEN + 1; i++)
|
||||
for (i = 0; i < MAX_COMPOSE_LEN + 1; i++)
|
||||
{
|
||||
gunichar codepoint = compose_data->sequence[i];
|
||||
keysyms[i] = (guint16) codepoint;
|
||||
@@ -301,20 +332,21 @@ gtk_compose_list_check_duplicated (GList *compose_list)
|
||||
n_compose++;
|
||||
}
|
||||
|
||||
if (gtk_check_compact_table (>k_compose_table_compact,
|
||||
keysyms,
|
||||
n_compose,
|
||||
&compose_finish,
|
||||
NULL,
|
||||
&output_char) &&
|
||||
if (gtk_compose_table_compact_check (>k_compose_table_compact,
|
||||
keysyms, n_compose,
|
||||
&compose_finish,
|
||||
NULL,
|
||||
&output_char) &&
|
||||
compose_finish)
|
||||
{
|
||||
if (compose_data->value[1] == output_char)
|
||||
g_unichar_to_utf8 (output_char, buf);
|
||||
if (strcmp (compose_data->value, buf) == 0)
|
||||
removed_list = g_list_prepend (removed_list, compose_data);
|
||||
}
|
||||
else if (gtk_check_algorithmically (keysyms, n_compose, &output_char))
|
||||
{
|
||||
if (compose_data->value[1] == output_char)
|
||||
g_unichar_to_utf8 (output_char, buf);
|
||||
if (strcmp (compose_data->value, buf) == 0)
|
||||
removed_list = g_list_prepend (removed_list, compose_data);
|
||||
}
|
||||
}
|
||||
@@ -343,7 +375,7 @@ gtk_compose_list_check_uint16 (GList *compose_list)
|
||||
int i;
|
||||
|
||||
compose_data = list->data;
|
||||
for (i = 0; i < GTK_MAX_COMPOSE_LEN; i++)
|
||||
for (i = 0; i < MAX_COMPOSE_LEN; i++)
|
||||
{
|
||||
gunichar codepoint = compose_data->sequence[i];
|
||||
|
||||
@@ -384,7 +416,7 @@ gtk_compose_list_format_for_gtk (GList *compose_list,
|
||||
for (list = compose_list; list != NULL; list = list->next)
|
||||
{
|
||||
compose_data = list->data;
|
||||
for (i = 0; i < GTK_MAX_COMPOSE_LEN + 1; i++)
|
||||
for (i = 0; i < MAX_COMPOSE_LEN + 1; i++)
|
||||
{
|
||||
codepoint = compose_data->sequence[i];
|
||||
if (codepoint == 0)
|
||||
@@ -401,17 +433,6 @@ gtk_compose_list_format_for_gtk (GList *compose_list,
|
||||
if (p_n_index_stride)
|
||||
*p_n_index_stride = max_compose_len + 2;
|
||||
|
||||
for (list = compose_list; list != NULL; list = list->next)
|
||||
{
|
||||
compose_data = list->data;
|
||||
codepoint = compose_data->value[1];
|
||||
if (codepoint > 0xffff)
|
||||
{
|
||||
compose_data->value[0] = codepoint / 0x10000;
|
||||
compose_data->value[1] = codepoint - codepoint / 0x10000 * 0x10000;
|
||||
}
|
||||
}
|
||||
|
||||
return compose_list;
|
||||
}
|
||||
|
||||
@@ -436,61 +457,6 @@ gtk_compose_data_compare (gpointer a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_compose_list_print (GList *compose_list,
|
||||
int max_compose_len,
|
||||
int n_index_stride)
|
||||
{
|
||||
GList *list;
|
||||
int i, j;
|
||||
GtkComposeData *compose_data;
|
||||
int total_size = 0;
|
||||
gunichar upper;
|
||||
gunichar lower;
|
||||
const char *comment;
|
||||
const char *keyval;
|
||||
|
||||
for (list = compose_list; list != NULL; list = list->next)
|
||||
{
|
||||
compose_data = list->data;
|
||||
g_printf (" ");
|
||||
|
||||
for (i = 0; i < max_compose_len; i++)
|
||||
{
|
||||
if (compose_data->sequence[i] == 0)
|
||||
{
|
||||
for (j = i; j < max_compose_len; j++)
|
||||
{
|
||||
if (j == max_compose_len - 1)
|
||||
g_printf ("0,\n");
|
||||
else
|
||||
g_printf ("0, ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
keyval = gdk_keyval_name (compose_data->sequence[i]);
|
||||
if (i == max_compose_len - 1)
|
||||
g_printf ("%s,\n", keyval ? keyval : "(null)");
|
||||
else
|
||||
g_printf ("%s, ", keyval ? keyval : "(null)");
|
||||
}
|
||||
upper = compose_data->value[0];
|
||||
lower = compose_data->value[1];
|
||||
comment = compose_data->comment;
|
||||
|
||||
if (list == g_list_last (compose_list))
|
||||
g_printf (" %#06X, %#06X /* %s */\n", upper, lower, comment);
|
||||
else
|
||||
g_printf (" %#06X, %#06X, /* %s */\n", upper, lower, comment);
|
||||
|
||||
total_size += n_index_stride;
|
||||
}
|
||||
|
||||
g_printerr ("TOTAL_SIZE: %d\nMAX_COMPOSE_LEN: %d\nN_INDEX_STRIDE: %d\n",
|
||||
total_size, max_compose_len, n_index_stride);
|
||||
}
|
||||
|
||||
/* Implemented from g_str_hash() */
|
||||
static guint32
|
||||
gtk_compose_table_data_hash (gconstpointer v, int length)
|
||||
@@ -546,6 +512,7 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
|
||||
guint16 max_seq_len = compose_table->max_seq_len;
|
||||
guint16 index_stride = max_seq_len + 2;
|
||||
guint16 n_seqs = compose_table->n_seqs;
|
||||
guint16 n_chars = compose_table->n_chars;
|
||||
guint32 i;
|
||||
|
||||
g_return_val_if_fail (compose_table != NULL, NULL);
|
||||
@@ -553,44 +520,34 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
|
||||
g_return_val_if_fail (index_stride > 0, NULL);
|
||||
|
||||
length = strlen (header);
|
||||
total_length = length + sizeof (guint16) * (3 + index_stride * n_seqs);
|
||||
total_length = length + sizeof (guint16) * (4 + index_stride * n_seqs) + n_chars;
|
||||
if (count)
|
||||
*count = total_length;
|
||||
|
||||
p = contents = g_slice_alloc (total_length);
|
||||
p = contents = g_malloc (total_length);
|
||||
|
||||
memcpy (p, header, length);
|
||||
p += length;
|
||||
|
||||
/* Copy by byte for endian */
|
||||
#define BYTE_COPY_FROM_BUF(element) \
|
||||
bytes = GUINT16_TO_BE ((element)); \
|
||||
memcpy (p, &bytes, length); \
|
||||
p += length; \
|
||||
if (p - contents > total_length) \
|
||||
{ \
|
||||
g_warning ("data size %lld is bigger than %" G_GSIZE_FORMAT, \
|
||||
(long long) (p - contents), total_length); \
|
||||
g_free (contents); \
|
||||
if (count) \
|
||||
{ \
|
||||
*count = 0; \
|
||||
} \
|
||||
return NULL; \
|
||||
}
|
||||
#define APPEND_GUINT16(elt) \
|
||||
bytes = GUINT16_TO_BE (elt); \
|
||||
memcpy (p, &bytes, sizeof (guint16)); \
|
||||
p += sizeof (guint16);
|
||||
|
||||
length = sizeof (guint16);
|
||||
|
||||
BYTE_COPY_FROM_BUF (version);
|
||||
BYTE_COPY_FROM_BUF (max_seq_len);
|
||||
BYTE_COPY_FROM_BUF (n_seqs);
|
||||
APPEND_GUINT16 (version);
|
||||
APPEND_GUINT16 (max_seq_len);
|
||||
APPEND_GUINT16 (n_seqs);
|
||||
APPEND_GUINT16 (n_chars);
|
||||
|
||||
for (i = 0; i < (guint32) index_stride * n_seqs; i++)
|
||||
{
|
||||
BYTE_COPY_FROM_BUF (compose_table->data[i]);
|
||||
APPEND_GUINT16 (compose_table->data[i]);
|
||||
}
|
||||
|
||||
#undef BYTE_COPY_FROM_BUF
|
||||
if (compose_table->n_chars > 0)
|
||||
memcpy (p, compose_table->char_data, compose_table->n_chars);
|
||||
|
||||
#undef APPEND_GUINT16
|
||||
|
||||
return contents;
|
||||
}
|
||||
@@ -614,16 +571,17 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
GStatBuf original_buf;
|
||||
GStatBuf cache_buf;
|
||||
gsize total_length;
|
||||
gsize length;
|
||||
GError *error = NULL;
|
||||
guint16 bytes;
|
||||
guint16 version;
|
||||
guint16 max_seq_len;
|
||||
guint16 index_stride;
|
||||
guint16 n_seqs;
|
||||
guint16 n_chars;
|
||||
guint32 i;
|
||||
guint16 *gtk_compose_seqs = NULL;
|
||||
GtkComposeTable *retval;
|
||||
char *char_data = NULL;
|
||||
|
||||
hash = g_str_hash (compose_file);
|
||||
if ((path = gtk_compose_hash_get_cache_path (hash)) == NULL)
|
||||
@@ -642,16 +600,10 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
goto out_load_cache;
|
||||
}
|
||||
|
||||
/* Copy by byte for endian */
|
||||
#define BYTE_COPY_TO_BUF(element) \
|
||||
memcpy (&bytes, p, length); \
|
||||
element = GUINT16_FROM_BE (bytes); \
|
||||
p += length; \
|
||||
if (p - contents > total_length) \
|
||||
{ \
|
||||
g_warning ("Broken cache content %s in %s", path, #element); \
|
||||
goto out_load_cache; \
|
||||
}
|
||||
#define GET_GUINT16(elt) \
|
||||
memcpy (&bytes, p, sizeof (guint16)); \
|
||||
elt = GUINT16_FROM_BE (bytes); \
|
||||
p += sizeof (guint16);
|
||||
|
||||
p = contents;
|
||||
if (g_ascii_strncasecmp (p, GTK_COMPOSE_TABLE_MAGIC,
|
||||
@@ -660,6 +612,7 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
g_warning ("The file is not a GtkComposeTable cache file %s", path);
|
||||
goto out_load_cache;
|
||||
}
|
||||
|
||||
p += strlen (GTK_COMPOSE_TABLE_MAGIC);
|
||||
if (p - contents > total_length)
|
||||
{
|
||||
@@ -667,9 +620,7 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
goto out_load_cache;
|
||||
}
|
||||
|
||||
length = sizeof (guint16);
|
||||
|
||||
BYTE_COPY_TO_BUF (version);
|
||||
GET_GUINT16 (version);
|
||||
if (version != GTK_COMPOSE_TABLE_VERSION)
|
||||
{
|
||||
g_warning ("cache version is different %u != %u",
|
||||
@@ -677,8 +628,9 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
goto out_load_cache;
|
||||
}
|
||||
|
||||
BYTE_COPY_TO_BUF (max_seq_len);
|
||||
BYTE_COPY_TO_BUF (n_seqs);
|
||||
GET_GUINT16 (max_seq_len);
|
||||
GET_GUINT16 (n_seqs);
|
||||
GET_GUINT16 (n_chars);
|
||||
|
||||
if (max_seq_len == 0 || n_seqs == 0)
|
||||
{
|
||||
@@ -691,13 +643,22 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
|
||||
for (i = 0; i < (guint32) index_stride * n_seqs; i++)
|
||||
{
|
||||
BYTE_COPY_TO_BUF (gtk_compose_seqs[i]);
|
||||
GET_GUINT16 (gtk_compose_seqs[i]);
|
||||
}
|
||||
|
||||
if (n_chars > 0)
|
||||
{
|
||||
char_data = g_new (char, n_chars + 1);
|
||||
memcpy (char_data, p, n_chars);
|
||||
char_data[n_chars] = '\0';
|
||||
}
|
||||
|
||||
retval = g_new0 (GtkComposeTable, 1);
|
||||
retval->data = gtk_compose_seqs;
|
||||
retval->max_seq_len = max_seq_len;
|
||||
retval->n_seqs = n_seqs;
|
||||
retval->char_data = char_data;
|
||||
retval->n_chars = n_chars;
|
||||
retval->id = hash;
|
||||
|
||||
g_free (contents);
|
||||
@@ -705,10 +666,11 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
|
||||
return retval;
|
||||
|
||||
#undef BYTE_COPY_TO_BUF
|
||||
#undef GET_GUINT16
|
||||
|
||||
out_load_cache:
|
||||
g_free (gtk_compose_seqs);
|
||||
g_free (char_data);
|
||||
g_free (contents);
|
||||
g_free (path);
|
||||
return NULL;
|
||||
@@ -739,7 +701,7 @@ gtk_compose_table_save_cache (GtkComposeTable *compose_table)
|
||||
}
|
||||
|
||||
out_save_cache:
|
||||
g_slice_free1 (length, contents);
|
||||
g_free (contents);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
@@ -756,6 +718,8 @@ gtk_compose_table_new_with_list (GList *compose_list,
|
||||
GList *list;
|
||||
GtkComposeData *compose_data;
|
||||
GtkComposeTable *retval = NULL;
|
||||
gunichar codepoint;
|
||||
GString *char_data;
|
||||
|
||||
g_return_val_if_fail (compose_list != NULL, NULL);
|
||||
|
||||
@@ -763,6 +727,8 @@ gtk_compose_table_new_with_list (GList *compose_list,
|
||||
|
||||
gtk_compose_seqs = g_new0 (guint16, length * n_index_stride);
|
||||
|
||||
char_data = g_string_new ("");
|
||||
|
||||
for (list = compose_list; list != NULL; list = list->next)
|
||||
{
|
||||
compose_data = list->data;
|
||||
@@ -776,8 +742,24 @@ gtk_compose_table_new_with_list (GList *compose_list,
|
||||
}
|
||||
gtk_compose_seqs[n++] = (guint16) compose_data->sequence[i];
|
||||
}
|
||||
gtk_compose_seqs[n++] = (guint16) compose_data->value[0];
|
||||
gtk_compose_seqs[n++] = (guint16) compose_data->value[1];
|
||||
|
||||
if (g_utf8_strlen (compose_data->value, -1) > 1)
|
||||
{
|
||||
if (char_data->len > 0)
|
||||
g_string_append_c (char_data, 0);
|
||||
|
||||
codepoint = char_data->len | (1 << 31);
|
||||
|
||||
g_string_append (char_data, compose_data->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
codepoint = g_utf8_get_char (compose_data->value);
|
||||
g_assert ((codepoint & (1 << 31)) == 0);
|
||||
}
|
||||
|
||||
gtk_compose_seqs[n++] = (codepoint & 0xffff0000) >> 16;
|
||||
gtk_compose_seqs[n++] = codepoint & 0xffff;
|
||||
}
|
||||
|
||||
retval = g_new0 (GtkComposeTable, 1);
|
||||
@@ -785,6 +767,8 @@ gtk_compose_table_new_with_list (GList *compose_list,
|
||||
retval->max_seq_len = max_compose_len;
|
||||
retval->n_seqs = length;
|
||||
retval->id = hash;
|
||||
retval->n_chars = char_data->len;
|
||||
retval->char_data = g_string_free (char_data, FALSE);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -816,9 +800,6 @@ gtk_compose_table_new_with_file (const char *compose_file)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_getenv ("GTK_COMPOSE_TABLE_PRINT") != NULL)
|
||||
gtk_compose_list_print (compose_list, max_compose_len, n_index_stride);
|
||||
|
||||
compose_table = gtk_compose_table_new_with_list (compose_list,
|
||||
max_compose_len,
|
||||
n_index_stride,
|
||||
@@ -841,9 +822,10 @@ gtk_compose_table_list_add_array (GSList *compose_tables,
|
||||
guint16 *gtk_compose_seqs = NULL;
|
||||
|
||||
g_return_val_if_fail (data != NULL, compose_tables);
|
||||
g_return_val_if_fail (max_seq_len <= GTK_MAX_COMPOSE_LEN, compose_tables);
|
||||
g_return_val_if_fail (max_seq_len >= 0, compose_tables);
|
||||
g_return_val_if_fail (n_seqs >= 0, compose_tables);
|
||||
|
||||
n_index_stride = MIN (max_seq_len, GTK_MAX_COMPOSE_LEN) + 2;
|
||||
n_index_stride = max_seq_len + 2;
|
||||
if (!g_size_checked_mul (&length, n_index_stride, n_seqs))
|
||||
{
|
||||
g_critical ("Overflow in the compose sequences");
|
||||
@@ -864,12 +846,14 @@ gtk_compose_table_list_add_array (GSList *compose_tables,
|
||||
compose_table->max_seq_len = max_seq_len;
|
||||
compose_table->n_seqs = n_seqs;
|
||||
compose_table->id = hash;
|
||||
compose_table->char_data = NULL;
|
||||
compose_table->n_chars = 0;
|
||||
|
||||
return g_slist_prepend (compose_tables, compose_table);
|
||||
}
|
||||
|
||||
GSList *
|
||||
gtk_compose_table_list_add_file (GSList *compose_tables,
|
||||
gtk_compose_table_list_add_file (GSList *compose_tables,
|
||||
const char *compose_file)
|
||||
{
|
||||
guint32 hash;
|
||||
@@ -891,3 +875,409 @@ gtk_compose_table_list_add_file (GSList *compose_tables,
|
||||
gtk_compose_table_save_cache (compose_table);
|
||||
return g_slist_prepend (compose_tables, compose_table);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_seq (const void *key, const void *value)
|
||||
{
|
||||
int i = 0;
|
||||
const guint16 *keysyms = key;
|
||||
const guint16 *seq = value;
|
||||
|
||||
while (keysyms[i])
|
||||
{
|
||||
if (keysyms[i] < seq[i])
|
||||
return -1;
|
||||
else if (keysyms[i] > seq[i])
|
||||
return 1;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_compose_table_check:
|
||||
* @table: the table to check
|
||||
* @compose_buffer: the key vals to match
|
||||
* @n_compose: number of non-zero key vals in @compose_buffer
|
||||
* @compose_finish: (out): return location for whether there may be longer matches
|
||||
* @compose_match: (out): return location for whether there is a match
|
||||
* @output: (out) (caller-allocates): return location for the match values
|
||||
*
|
||||
* Looks for matches for a key sequence in @table.
|
||||
*
|
||||
* Returns: %TRUE if there were any matches, %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
gtk_compose_table_check (const GtkComposeTable *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
GString *output)
|
||||
{
|
||||
int row_stride = table->max_seq_len + 2;
|
||||
guint16 *seq;
|
||||
|
||||
*compose_finish = FALSE;
|
||||
*compose_match = FALSE;
|
||||
|
||||
g_string_set_size (output, 0);
|
||||
|
||||
/* Will never match, if the sequence in the compose buffer is longer
|
||||
* than the sequences in the table. Further, compare_seq (key, val)
|
||||
* will overrun val if key is longer than val.
|
||||
*/
|
||||
if (n_compose > table->max_seq_len)
|
||||
return FALSE;
|
||||
|
||||
seq = bsearch (compose_buffer,
|
||||
table->data, table->n_seqs,
|
||||
sizeof (guint16) * row_stride,
|
||||
compare_seq);
|
||||
|
||||
if (seq)
|
||||
{
|
||||
guint16 *prev_seq;
|
||||
|
||||
/* Back up to the first sequence that matches to make sure
|
||||
* we find the exact match if there is one.
|
||||
*/
|
||||
while (seq > table->data)
|
||||
{
|
||||
prev_seq = seq - row_stride;
|
||||
if (compare_seq (compose_buffer, prev_seq) != 0)
|
||||
break;
|
||||
seq = prev_seq;
|
||||
}
|
||||
|
||||
if (n_compose == table->max_seq_len ||
|
||||
seq[n_compose] == 0) /* complete sequence */
|
||||
{
|
||||
guint16 *next_seq;
|
||||
gunichar value;
|
||||
|
||||
value = (seq[table->max_seq_len] << 16) | seq[table->max_seq_len + 1];
|
||||
if ((value & (1 << 31)) != 0)
|
||||
g_string_append (output, &table->char_data[value & ~(1 << 31)]);
|
||||
else
|
||||
g_string_append_unichar (output, value);
|
||||
|
||||
*compose_match = TRUE;
|
||||
|
||||
/* We found a tentative match. See if there are any longer
|
||||
* sequences containing this subsequence
|
||||
*/
|
||||
next_seq = seq + row_stride;
|
||||
if (next_seq < table->data + row_stride * table->n_seqs)
|
||||
{
|
||||
if (compare_seq (compose_buffer, next_seq) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*compose_finish = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_seq_index (const void *key, const void *value)
|
||||
{
|
||||
const guint16 *keysyms = key;
|
||||
const guint16 *seq = value;
|
||||
|
||||
if (keysyms[0] < seq[0])
|
||||
return -1;
|
||||
else if (keysyms[0] > seq[0])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
gunichar *output_char)
|
||||
{
|
||||
int row_stride;
|
||||
guint16 *seq_index;
|
||||
guint16 *seq;
|
||||
int i;
|
||||
gboolean match;
|
||||
gunichar value;
|
||||
|
||||
if (compose_finish)
|
||||
*compose_finish = FALSE;
|
||||
if (compose_match)
|
||||
*compose_match = FALSE;
|
||||
if (output_char)
|
||||
*output_char = 0;
|
||||
|
||||
/* Will never match, if the sequence in the compose buffer is longer
|
||||
* than the sequences in the table. Further, compare_seq (key, val)
|
||||
* will overrun val if key is longer than val.
|
||||
*/
|
||||
if (n_compose > table->max_seq_len)
|
||||
return FALSE;
|
||||
|
||||
seq_index = bsearch (compose_buffer,
|
||||
table->data,
|
||||
table->n_index_size,
|
||||
sizeof (guint16) * table->n_index_stride,
|
||||
compare_seq_index);
|
||||
|
||||
if (!seq_index)
|
||||
return FALSE;
|
||||
|
||||
if (n_compose == 1)
|
||||
return TRUE;
|
||||
|
||||
seq = NULL;
|
||||
match = FALSE;
|
||||
value = 0;
|
||||
|
||||
for (i = n_compose - 1; i < table->max_seq_len; i++)
|
||||
{
|
||||
row_stride = i + 1;
|
||||
|
||||
if (seq_index[i + 1] - seq_index[i] > 0)
|
||||
{
|
||||
seq = bsearch (compose_buffer + 1,
|
||||
table->data + seq_index[i],
|
||||
(seq_index[i + 1] - seq_index[i]) / row_stride,
|
||||
sizeof (guint16) * row_stride,
|
||||
compare_seq);
|
||||
|
||||
if (seq)
|
||||
{
|
||||
if (i == n_compose - 1)
|
||||
{
|
||||
value = seq[row_stride - 1];
|
||||
match = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output_char)
|
||||
*output_char = value;
|
||||
if (match)
|
||||
{
|
||||
if (compose_match)
|
||||
*compose_match = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
if (compose_match)
|
||||
*compose_match = TRUE;
|
||||
if (compose_finish)
|
||||
*compose_finish = TRUE;
|
||||
if (output_char)
|
||||
*output_char = value;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Checks if a keysym is a dead key.
|
||||
* Dead key keysym values are defined in ../gdk/gdkkeysyms.h and the
|
||||
* first is GDK_KEY_dead_grave. As X.Org is updated, more dead keys
|
||||
* are added and we need to update the upper limit.
|
||||
*/
|
||||
#define IS_DEAD_KEY(k) \
|
||||
((k) >= GDK_KEY_dead_grave && (k) <= GDK_KEY_dead_greek)
|
||||
|
||||
/* This function receives a sequence of Unicode characters and tries to
|
||||
* normalize it (NFC). We check for the case where the resulting string
|
||||
* has length 1 (single character).
|
||||
* NFC normalisation normally rearranges diacritic marks, unless these
|
||||
* belong to the same Canonical Combining Class.
|
||||
* If they belong to the same canonical combining class, we produce all
|
||||
* permutations of the diacritic marks, then attempt to normalize.
|
||||
*/
|
||||
static gboolean
|
||||
check_normalize_nfc (gunichar *combination_buffer,
|
||||
int n_compose)
|
||||
{
|
||||
gunichar *combination_buffer_temp;
|
||||
char *combination_utf8_temp = NULL;
|
||||
char *nfc_temp = NULL;
|
||||
int n_combinations;
|
||||
gunichar temp_swap;
|
||||
int i;
|
||||
|
||||
combination_buffer_temp = g_alloca (n_compose * sizeof (gunichar));
|
||||
|
||||
n_combinations = 1;
|
||||
|
||||
for (i = 1; i < n_compose; i++)
|
||||
n_combinations *= i;
|
||||
|
||||
/* Xorg reuses dead_tilde for the perispomeni diacritic mark.
|
||||
* We check if base character belongs to Greek Unicode block,
|
||||
* and if so, we replace tilde with perispomeni.
|
||||
*/
|
||||
if (combination_buffer[0] >= 0x390 && combination_buffer[0] <= 0x3FF)
|
||||
{
|
||||
for (i = 1; i < n_compose; i++ )
|
||||
if (combination_buffer[i] == 0x303)
|
||||
combination_buffer[i] = 0x342;
|
||||
}
|
||||
|
||||
memcpy (combination_buffer_temp, combination_buffer, n_compose * sizeof (gunichar) );
|
||||
|
||||
for (i = 0; i < n_combinations; i++)
|
||||
{
|
||||
g_unicode_canonical_ordering (combination_buffer_temp, n_compose);
|
||||
combination_utf8_temp = g_ucs4_to_utf8 (combination_buffer_temp, n_compose, NULL, NULL, NULL);
|
||||
nfc_temp = g_utf8_normalize (combination_utf8_temp, -1, G_NORMALIZE_NFC);
|
||||
|
||||
if (g_utf8_strlen (nfc_temp, -1) == 1)
|
||||
{
|
||||
memcpy (combination_buffer, combination_buffer_temp, n_compose * sizeof (gunichar) );
|
||||
|
||||
g_free (combination_utf8_temp);
|
||||
g_free (nfc_temp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_free (combination_utf8_temp);
|
||||
g_free (nfc_temp);
|
||||
|
||||
if (n_compose > 2)
|
||||
{
|
||||
temp_swap = combination_buffer_temp[i % (n_compose - 1) + 1];
|
||||
combination_buffer_temp[i % (n_compose - 1) + 1] = combination_buffer_temp[(i+1) % (n_compose - 1) + 1];
|
||||
combination_buffer_temp[(i+1) % (n_compose - 1) + 1] = temp_swap;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_check_algorithmically (const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gunichar *output_char)
|
||||
|
||||
{
|
||||
int i;
|
||||
gunichar *combination_buffer;
|
||||
char *combination_utf8, *nfc;
|
||||
|
||||
combination_buffer = alloca (sizeof (gunichar) * (n_compose + 1));
|
||||
|
||||
if (output_char)
|
||||
*output_char = 0;
|
||||
|
||||
for (i = 0; i < n_compose && IS_DEAD_KEY (compose_buffer[i]); i++)
|
||||
;
|
||||
if (i == n_compose)
|
||||
return TRUE;
|
||||
|
||||
if (i > 0 && i == n_compose - 1)
|
||||
{
|
||||
combination_buffer[0] = gdk_keyval_to_unicode (compose_buffer[i]);
|
||||
combination_buffer[n_compose] = 0;
|
||||
i--;
|
||||
while (i >= 0)
|
||||
{
|
||||
switch (compose_buffer[i])
|
||||
{
|
||||
#define CASE(keysym, unicode) \
|
||||
case GDK_KEY_dead_##keysym: combination_buffer[i+1] = unicode; break
|
||||
|
||||
CASE (grave, 0x0300);
|
||||
CASE (acute, 0x0301);
|
||||
CASE (circumflex, 0x0302);
|
||||
CASE (tilde, 0x0303); /* Also used with perispomeni, 0x342. */
|
||||
CASE (macron, 0x0304);
|
||||
CASE (breve, 0x0306);
|
||||
CASE (abovedot, 0x0307);
|
||||
CASE (diaeresis, 0x0308);
|
||||
CASE (abovering, 0x30A);
|
||||
CASE (hook, 0x0309);
|
||||
CASE (doubleacute, 0x030B);
|
||||
CASE (caron, 0x030C);
|
||||
CASE (cedilla, 0x0327);
|
||||
CASE (ogonek, 0x0328); /* Legacy use for dasia, 0x314.*/
|
||||
CASE (iota, 0x0345);
|
||||
CASE (voiced_sound, 0x3099); /* Per Markus Kuhn keysyms.txt file. */
|
||||
CASE (semivoiced_sound, 0x309A); /* Per Markus Kuhn keysyms.txt file. */
|
||||
CASE (belowdot, 0x0323);
|
||||
CASE (horn, 0x031B); /* Legacy use for psili, 0x313 (or 0x343). */
|
||||
CASE (stroke, 0x335);
|
||||
CASE (abovecomma, 0x0313); /* Equivalent to psili */
|
||||
CASE (abovereversedcomma, 0x0314); /* Equivalent to dasia */
|
||||
CASE (doublegrave, 0x30F);
|
||||
CASE (belowring, 0x325);
|
||||
CASE (belowmacron, 0x331);
|
||||
CASE (belowcircumflex, 0x32D);
|
||||
CASE (belowtilde, 0x330);
|
||||
CASE (belowbreve, 0x32e);
|
||||
CASE (belowdiaeresis, 0x324);
|
||||
CASE (invertedbreve, 0x32f);
|
||||
CASE (belowcomma, 0x326);
|
||||
CASE (lowline, 0x332);
|
||||
CASE (aboveverticalline, 0x30D);
|
||||
CASE (belowverticalline, 0x329);
|
||||
CASE (longsolidusoverlay, 0x338);
|
||||
CASE (a, 0x363);
|
||||
CASE (A, 0x363);
|
||||
CASE (e, 0x364);
|
||||
CASE (E, 0x364);
|
||||
CASE (i, 0x365);
|
||||
CASE (I, 0x365);
|
||||
CASE (o, 0x366);
|
||||
CASE (O, 0x366);
|
||||
CASE (u, 0x367);
|
||||
CASE (U, 0x367);
|
||||
CASE (small_schwa, 0x1DEA);
|
||||
CASE (capital_schwa, 0x1DEA);
|
||||
#undef CASE
|
||||
default:
|
||||
combination_buffer[i+1] = gdk_keyval_to_unicode (compose_buffer[i]);
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
||||
/* If the buffer normalizes to a single character, then modify the order
|
||||
* of combination_buffer accordingly, if necessary, and return TRUE.
|
||||
*/
|
||||
if (check_normalize_nfc (combination_buffer, n_compose))
|
||||
{
|
||||
combination_utf8 = g_ucs4_to_utf8 (combination_buffer, -1, NULL, NULL, NULL);
|
||||
nfc = g_utf8_normalize (combination_utf8, -1, G_NORMALIZE_NFC);
|
||||
|
||||
if (output_char)
|
||||
*output_char = g_utf8_get_char (nfc);
|
||||
|
||||
g_free (combination_utf8);
|
||||
g_free (nfc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
+28
-7
@@ -29,8 +29,10 @@ typedef struct _GtkComposeTableCompact GtkComposeTableCompact;
|
||||
struct _GtkComposeTable
|
||||
{
|
||||
guint16 *data;
|
||||
char *char_data;
|
||||
int max_seq_len;
|
||||
int n_seqs;
|
||||
int n_chars;
|
||||
guint32 id;
|
||||
};
|
||||
|
||||
@@ -42,13 +44,32 @@ struct _GtkComposeTableCompact
|
||||
int n_index_stride;
|
||||
};
|
||||
|
||||
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
|
||||
GSList *gtk_compose_table_list_add_array (GSList *compose_tables,
|
||||
const guint16 *data,
|
||||
int max_seq_len,
|
||||
int n_seqs);
|
||||
GSList *gtk_compose_table_list_add_file (GSList *compose_tables,
|
||||
const char *compose_file);
|
||||
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
|
||||
GSList * gtk_compose_table_list_add_array (GSList *compose_tables,
|
||||
const guint16 *data,
|
||||
int max_seq_len,
|
||||
int n_seqs);
|
||||
GSList * gtk_compose_table_list_add_file (GSList *compose_tables,
|
||||
const char *compose_file);
|
||||
|
||||
gboolean gtk_compose_table_check (const GtkComposeTable *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
GString *output);
|
||||
|
||||
gboolean gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
gunichar *output_char);
|
||||
|
||||
gboolean gtk_check_algorithmically (const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gunichar *output);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -440,6 +440,10 @@ gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *animated,
|
||||
unshare_other (animated);
|
||||
gtk_css_take_value (&style->other->transform, value);
|
||||
break;
|
||||
case GTK_CSS_PROPERTY_TRANSFORM_ORIGIN:
|
||||
unshare_other (animated);
|
||||
gtk_css_take_value (&style->other->transform_origin, value);
|
||||
break;
|
||||
case GTK_CSS_PROPERTY_MIN_WIDTH:
|
||||
unshare_size (animated);
|
||||
gtk_css_take_value (&style->size->min_width, value);
|
||||
|
||||
@@ -218,7 +218,7 @@ _gtk_css_border_value_parse (GtkCssParser *parser,
|
||||
}
|
||||
|
||||
result->is_computed = TRUE;
|
||||
for (; i < 4; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
if (result->values[i] && !gtk_css_value_is_computed (result->values[i]))
|
||||
{
|
||||
result->is_computed = FALSE;
|
||||
|
||||
+93
-51
@@ -545,57 +545,6 @@ _gtk_css_font_stretch_value_get (const GtkCssValue *value)
|
||||
return value->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,
|
||||
gtk_css_value_enum_transition,
|
||||
NULL,
|
||||
NULL,
|
||||
gtk_css_value_enum_print
|
||||
};
|
||||
|
||||
static GtkCssValue text_decoration_line_values[] = {
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
|
||||
{ >K_CSS_VALUE_TEXT_DECORATION_LINE, 1, TRUE, GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
|
||||
};
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
|
||||
{
|
||||
g_return_val_if_fail (line < G_N_ELEMENTS (text_decoration_line_values), NULL);
|
||||
|
||||
return _gtk_css_value_ref (&text_decoration_line_values[line]);
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (parser != NULL, NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
|
||||
{
|
||||
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
|
||||
return _gtk_css_value_ref (&text_decoration_line_values[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkTextDecorationLine
|
||||
_gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
|
||||
{
|
||||
g_return_val_if_fail (value->class == >K_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
|
||||
|
||||
return value->value;
|
||||
}
|
||||
|
||||
/* GtkTextDecorationStyle */
|
||||
|
||||
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
|
||||
@@ -1203,6 +1152,99 @@ gtk_css_value_flags_print (const FlagsValue *values,
|
||||
}
|
||||
}
|
||||
|
||||
/* GtkTextDecorationLine */
|
||||
|
||||
static FlagsValue text_decoration_line_values[] = {
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_NONE, "none" },
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE, "underline" },
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_OVERLINE, "overline" },
|
||||
{ GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH, "line-through" },
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_css_text_decoration_line_value_print (const GtkCssValue *value,
|
||||
GString *string)
|
||||
{
|
||||
gtk_css_value_flags_print (text_decoration_line_values,
|
||||
G_N_ELEMENTS (text_decoration_line_values),
|
||||
value, string);
|
||||
}
|
||||
|
||||
static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
|
||||
"GtkCssTextDecorationLine",
|
||||
gtk_css_value_enum_free,
|
||||
gtk_css_value_enum_compute,
|
||||
gtk_css_value_flags_equal,
|
||||
gtk_css_value_enum_transition,
|
||||
NULL,
|
||||
NULL,
|
||||
gtk_css_text_decoration_line_value_print
|
||||
};
|
||||
|
||||
static gboolean
|
||||
text_decoration_line_is_valid (GtkTextDecorationLine line)
|
||||
{
|
||||
if ((line & GTK_CSS_TEXT_DECORATION_LINE_NONE) &&
|
||||
(line != GTK_CSS_TEXT_DECORATION_LINE_NONE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line)
|
||||
{
|
||||
GtkCssValue *value;
|
||||
|
||||
if (!text_decoration_line_is_valid (line))
|
||||
return NULL;
|
||||
|
||||
value = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_TEXT_DECORATION_LINE);
|
||||
value->value = line;
|
||||
value->name = NULL;
|
||||
value->is_computed = TRUE;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
GtkTextDecorationLine
|
||||
_gtk_css_text_decoration_line_try_parse_one (GtkCssParser *parser,
|
||||
GtkTextDecorationLine base)
|
||||
{
|
||||
guint i;
|
||||
GtkTextDecorationLine value = 0;
|
||||
|
||||
g_return_val_if_fail (parser != NULL, 0);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
|
||||
{
|
||||
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
|
||||
{
|
||||
value = text_decoration_line_values[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (value == 0)
|
||||
return base; /* not parsing this value */
|
||||
|
||||
if ((base | value) == base)
|
||||
return 0; /* repeated value */
|
||||
|
||||
if (!text_decoration_line_is_valid (base | value))
|
||||
return 0; /* bad combination */
|
||||
|
||||
return base | value;
|
||||
}
|
||||
|
||||
GtkTextDecorationLine
|
||||
_gtk_css_text_decoration_line_value_get (const GtkCssValue *value)
|
||||
{
|
||||
g_return_val_if_fail (value->class == >K_CSS_VALUE_TEXT_DECORATION_LINE, GTK_CSS_TEXT_DECORATION_LINE_NONE);
|
||||
|
||||
return value->value;
|
||||
}
|
||||
|
||||
/* GtkCssFontVariantLigature */
|
||||
|
||||
static FlagsValue font_variant_ligature_values[] = {
|
||||
|
||||
@@ -54,11 +54,12 @@ GtkCssValue * _gtk_css_font_stretch_value_new (PangoStretch stretc
|
||||
GtkCssValue * _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser);
|
||||
PangoStretch _gtk_css_font_stretch_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line);
|
||||
GtkCssValue * _gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser);
|
||||
GtkTextDecorationLine _gtk_css_text_decoration_line_value_get (const GtkCssValue *value);
|
||||
GtkCssValue * _gtk_css_text_decoration_line_value_new (GtkTextDecorationLine line);
|
||||
GtkTextDecorationLine _gtk_css_text_decoration_line_try_parse_one (GtkCssParser *parser,
|
||||
GtkTextDecorationLine base);
|
||||
GtkTextDecorationLine _gtk_css_text_decoration_line_value_get (const GtkCssValue *value);
|
||||
|
||||
GtkCssValue * _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style);
|
||||
GtkCssValue * _gtk_css_text_decoration_style_value_new (GtkTextDecorationStyle style);
|
||||
GtkCssValue * _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser);
|
||||
GtkTextDecorationStyle _gtk_css_text_decoration_style_value_get (const GtkCssValue *value);
|
||||
|
||||
|
||||
+64
-20
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "gtkcssfiltervalueprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcssshadowvalueprivate.h"
|
||||
|
||||
typedef union _GtkCssFilter GtkCssFilter;
|
||||
|
||||
@@ -46,7 +47,7 @@ union _GtkCssFilter {
|
||||
struct {
|
||||
GtkCssFilterType type;
|
||||
GtkCssValue *value;
|
||||
} brightness, contrast, grayscale, hue_rotate, invert, opacity, saturate, sepia, blur;
|
||||
} blur, brightness, contrast, drop_shadow, grayscale, hue_rotate, invert, opacity, saturate, sepia;
|
||||
};
|
||||
|
||||
struct _GtkCssValue {
|
||||
@@ -90,8 +91,10 @@ gtk_css_filter_clear (GtkCssFilter *filter)
|
||||
case GTK_CSS_FILTER_BLUR:
|
||||
_gtk_css_value_unref (filter->blur.value);
|
||||
break;
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||
_gtk_css_value_unref (filter->drop_shadow.value);
|
||||
break;
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
@@ -131,8 +134,10 @@ gtk_css_filter_init_identity (GtkCssFilter *filter,
|
||||
case GTK_CSS_FILTER_BLUR:
|
||||
filter->blur.value = _gtk_css_number_value_new (0, GTK_CSS_PX);
|
||||
break;
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||
filter->drop_shadow.value = gtk_css_shadow_value_new_filter ();
|
||||
break;
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
@@ -347,8 +352,11 @@ gtk_css_filter_compute (GtkCssFilter *dest,
|
||||
dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style);
|
||||
return dest->blur.value == src->blur.value;
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||
dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style);
|
||||
return dest->drop_shadow.value == src->drop_shadow.value;
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
@@ -428,8 +436,10 @@ gtk_css_filter_equal (const GtkCssFilter *filter1,
|
||||
case GTK_CSS_FILTER_BLUR:
|
||||
return _gtk_css_value_equal (filter1->blur.value, filter2->blur.value);
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||
return _gtk_css_value_equal (filter1->drop_shadow.value, filter2->drop_shadow.value);
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
@@ -517,8 +527,11 @@ gtk_css_filter_transition (GtkCssFilter *result,
|
||||
result->blur.value = _gtk_css_value_transition (start->blur.value, end->blur.value, property_id, progress);
|
||||
break;
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||
result->drop_shadow.value = _gtk_css_value_transition (start->drop_shadow.value, end->drop_shadow.value, property_id, progress);
|
||||
break;
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
@@ -663,8 +676,13 @@ gtk_css_filter_print (const GtkCssFilter *filter,
|
||||
g_string_append (string, ")");
|
||||
break;
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
case GTK_CSS_FILTER_DROP_SHADOW:
|
||||
g_string_append (string, "drop-shadow(");
|
||||
_gtk_css_value_print (filter->drop_shadow.value, string);
|
||||
g_string_append (string, ")");
|
||||
break;
|
||||
|
||||
case GTK_CSS_FILTER_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
@@ -709,12 +727,12 @@ static GtkCssValue *
|
||||
gtk_css_filter_value_alloc (guint n_filters)
|
||||
{
|
||||
GtkCssValue *result;
|
||||
|
||||
|
||||
g_return_val_if_fail (n_filters > 0, NULL);
|
||||
|
||||
|
||||
result = _gtk_css_value_alloc (>K_CSS_VALUE_FILTER, sizeof (GtkCssValue) + sizeof (GtkCssFilter) * (n_filters - 1));
|
||||
result->n_filters = n_filters;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -737,7 +755,7 @@ gtk_css_filter_parse_number (GtkCssParser *parser,
|
||||
{
|
||||
GtkCssValue **values = data;
|
||||
|
||||
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
|
||||
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
|
||||
if (values[n] == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -751,7 +769,7 @@ gtk_css_filter_parse_length (GtkCssParser *parser,
|
||||
{
|
||||
GtkCssValue **values = data;
|
||||
|
||||
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
|
||||
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_POSITIVE_ONLY);
|
||||
if (values[n] == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -772,6 +790,20 @@ gtk_css_filter_parse_angle (GtkCssParser *parser,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_filter_parse_shadow (GtkCssParser *parser,
|
||||
guint n,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssValue **values = data;
|
||||
|
||||
values[n] = gtk_css_shadow_value_parse_filter (parser);
|
||||
if (values[n] == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_filter_value_parse (GtkCssParser *parser)
|
||||
{
|
||||
@@ -861,6 +893,14 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
|
||||
filter.type = GTK_CSS_FILTER_SEPIA;
|
||||
computed = computed && gtk_css_value_is_computed (filter.sepia.value);
|
||||
}
|
||||
else if (gtk_css_parser_has_function (parser, "drop-shadow"))
|
||||
{
|
||||
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_shadow, &filter.drop_shadow.value))
|
||||
goto fail;
|
||||
|
||||
filter.type = GTK_CSS_FILTER_DROP_SHADOW;
|
||||
computed = computed && gtk_css_value_is_computed (filter.drop_shadow.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
@@ -899,7 +939,6 @@ gtk_css_filter_value_push_snapshot (const GtkCssValue *filter,
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
int i, j;
|
||||
double radius;
|
||||
|
||||
if (gtk_css_filter_value_is_none (filter))
|
||||
return;
|
||||
@@ -909,16 +948,18 @@ gtk_css_filter_value_push_snapshot (const GtkCssValue *filter,
|
||||
{
|
||||
j = gtk_css_filter_value_compute_matrix (filter, i, &matrix, &offset);
|
||||
if (i < j)
|
||||
gtk_snapshot_push_color_matrix (snapshot,
|
||||
&matrix,
|
||||
&offset);
|
||||
gtk_snapshot_push_color_matrix (snapshot, &matrix, &offset);
|
||||
|
||||
if (j < filter->n_filters)
|
||||
{
|
||||
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR)
|
||||
{
|
||||
radius = _gtk_css_number_value_get (filter->filters[j].blur.value, 100.0);
|
||||
gtk_snapshot_push_blur (snapshot, radius);
|
||||
double std_dev = _gtk_css_number_value_get (filter->filters[j].blur.value, 100.0);
|
||||
gtk_snapshot_push_blur (snapshot, 2 * std_dev);
|
||||
}
|
||||
else if (filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW)
|
||||
{
|
||||
gtk_css_shadow_value_push_snapshot (filter->filters[j].drop_shadow.value, snapshot);
|
||||
}
|
||||
else
|
||||
g_warning ("Don't know how to handle filter type %d", filter->filters[j].type);
|
||||
@@ -942,15 +983,18 @@ gtk_css_filter_value_pop_snapshot (const GtkCssValue *filter,
|
||||
{
|
||||
for (j = i; j < filter->n_filters; j++)
|
||||
{
|
||||
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR)
|
||||
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR ||
|
||||
filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < j)
|
||||
gtk_snapshot_pop (snapshot);
|
||||
|
||||
if (j < filter->n_filters)
|
||||
if (filter->filters[j].type == GTK_CSS_FILTER_BLUR)
|
||||
gtk_snapshot_pop (snapshot);
|
||||
else if (filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW)
|
||||
gtk_css_shadow_value_pop_snapshot (filter->filters[j].drop_shadow.value, snapshot);
|
||||
|
||||
i = j + 1;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "gtk/gtkcssimageurlprivate.h"
|
||||
#include "gtk/gtkcssimagescaledprivate.h"
|
||||
#include "gtk/gtkcssimagerecolorprivate.h"
|
||||
#include "gtk/gtkcssimagefilterprivate.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (GtkCssImage, _gtk_css_image, G_TYPE_OBJECT)
|
||||
|
||||
@@ -524,6 +525,7 @@ gtk_css_image_get_parser_type (GtkCssParser *parser)
|
||||
{ "repeating-radial-gradient", _gtk_css_image_radial_get_type },
|
||||
{ "conic-gradient", gtk_css_image_conic_get_type },
|
||||
{ "cross-fade", gtk_css_image_cross_fade_get_type },
|
||||
{ "filter", gtk_css_image_filter_get_type },
|
||||
{ "image", _gtk_css_image_fallback_get_type }
|
||||
};
|
||||
guint i;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#include "gtkcssimagecrossfadeprivate.h"
|
||||
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcssimagefallbackprivate.h"
|
||||
#include "gtkcsscolorvalueprivate.h"
|
||||
|
||||
|
||||
typedef struct _CrossFadeEntry CrossFadeEntry;
|
||||
|
||||
@@ -308,8 +311,19 @@ parse_image (GtkCssParser *parser,
|
||||
{
|
||||
GtkCssImage **image = option_data;
|
||||
|
||||
*image = _gtk_css_image_new_parse (parser);
|
||||
if (*image == NULL)
|
||||
if (_gtk_css_image_can_parse (parser))
|
||||
*image = _gtk_css_image_new_parse (parser);
|
||||
else if (gtk_css_color_value_can_parse (parser))
|
||||
{
|
||||
GtkCssValue *color;
|
||||
|
||||
color = _gtk_css_color_value_parse (parser);
|
||||
if (color == NULL)
|
||||
return FALSE;
|
||||
|
||||
*image = _gtk_css_image_fallback_new_for_color (color);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@@ -325,7 +339,7 @@ gtk_css_image_cross_fade_parse_arg (GtkCssParser *parser,
|
||||
GtkCssImage *image = NULL;
|
||||
GtkCssParseOption options[] =
|
||||
{
|
||||
{ (void *) gtk_css_number_value_can_parse, parse_progress, &progress },
|
||||
{ (void *)gtk_css_number_value_can_parse, parse_progress, &progress },
|
||||
{ NULL, parse_image, &image },
|
||||
};
|
||||
|
||||
|
||||
@@ -148,11 +148,11 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
|
||||
GtkCssValue *computed_color = NULL;
|
||||
|
||||
if (fallback->color)
|
||||
computed_color= _gtk_css_value_compute (fallback->color,
|
||||
property_id,
|
||||
provider,
|
||||
style,
|
||||
parent_style);
|
||||
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 &&
|
||||
@@ -331,3 +331,14 @@ _gtk_css_image_fallback_init (GtkCssImageFallback *image_fallback)
|
||||
{
|
||||
image_fallback->used = -1;
|
||||
}
|
||||
|
||||
GtkCssImage *
|
||||
_gtk_css_image_fallback_new_for_color (GtkCssValue *color)
|
||||
{
|
||||
GtkCssImageFallback *image;
|
||||
|
||||
image = g_object_new (GTK_TYPE_CSS_IMAGE_FALLBACK, NULL);
|
||||
image->color = gtk_css_value_ref (color);
|
||||
|
||||
return (GtkCssImage *)image;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,9 @@ struct _GtkCssImageFallbackClass
|
||||
GtkCssImageClass parent_class;
|
||||
};
|
||||
|
||||
GType _gtk_css_image_fallback_get_type (void) G_GNUC_CONST;
|
||||
GType _gtk_css_image_fallback_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssImage *_gtk_css_image_fallback_new_for_color (GtkCssValue *color);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright © 2021 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gtkcssimagefilterprivate.h"
|
||||
|
||||
#include "gtkcssfiltervalueprivate.h"
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkCssImageFilter, gtk_css_image_filter, GTK_TYPE_CSS_IMAGE)
|
||||
|
||||
static int
|
||||
gtk_css_image_filter_get_width (GtkCssImage *image)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
return _gtk_css_image_get_width (self->image);
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_css_image_filter_get_height (GtkCssImage *image)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
return _gtk_css_image_get_height (self->image);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_filter_equal (GtkCssImage *image1,
|
||||
GtkCssImage *image2)
|
||||
{
|
||||
GtkCssImageFilter *filter1 = GTK_CSS_IMAGE_FILTER (image1);
|
||||
GtkCssImageFilter *filter2 = GTK_CSS_IMAGE_FILTER (image2);
|
||||
|
||||
return _gtk_css_image_equal (filter1->image, filter2->image) &&
|
||||
_gtk_css_value_equal (filter1->filter, filter2->filter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_filter_is_dynamic (GtkCssImage *image)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
return gtk_css_image_is_dynamic (self->image);
|
||||
}
|
||||
|
||||
static GtkCssImage *
|
||||
gtk_css_image_filter_get_dynamic_image (GtkCssImage *image,
|
||||
gint64 monotonic_time)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
return gtk_css_image_filter_new (gtk_css_image_get_dynamic_image (self->image, monotonic_time),
|
||||
self->filter);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_filter_snapshot (GtkCssImage *image,
|
||||
GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
gtk_css_filter_value_push_snapshot (self->filter, snapshot);
|
||||
gtk_css_image_snapshot (self->image, snapshot, width, height);
|
||||
gtk_css_filter_value_pop_snapshot (self->filter, snapshot);
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_css_image_filter_parse_arg (GtkCssParser *parser,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GtkCssImageFilter *self = data;
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case 0:
|
||||
self->image = _gtk_css_image_new_parse (parser);
|
||||
if (self->image == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
self->filter = gtk_css_filter_value_parse (parser);
|
||||
if (self->filter == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_filter_parse (GtkCssImage *image,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
if (!gtk_css_parser_has_function (parser, "filter"))
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Expected 'filter('");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gtk_css_parser_consume_function (parser, 2, 2, gtk_css_image_filter_parse_arg, image);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_filter_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
g_string_append (string, "filter(");
|
||||
_gtk_css_image_print (self->image, string);
|
||||
g_string_append (string, ",");
|
||||
_gtk_css_value_print (self->filter, string);
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
|
||||
static GtkCssImage *
|
||||
gtk_css_image_filter_compute (GtkCssImage *image,
|
||||
guint property_id,
|
||||
GtkStyleProvider *provider,
|
||||
GtkCssStyle *style,
|
||||
GtkCssStyle *parent_style)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
return gtk_css_image_filter_new (_gtk_css_image_compute (self->image, property_id, provider, style, parent_style),
|
||||
_gtk_css_value_compute (self->filter, property_id, provider, style, parent_style));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_filter_dispose (GObject *object)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (object);
|
||||
|
||||
g_clear_object (&self->image);
|
||||
g_clear_pointer (&self->filter, _gtk_css_value_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_css_image_filter_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_filter_is_computed (GtkCssImage *image)
|
||||
{
|
||||
GtkCssImageFilter *self = GTK_CSS_IMAGE_FILTER (image);
|
||||
|
||||
return gtk_css_image_is_computed (self->image) &&
|
||||
gtk_css_value_is_computed (self->filter);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_filter_class_init (GtkCssImageFilterClass *klass)
|
||||
{
|
||||
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
image_class->get_width = gtk_css_image_filter_get_width;
|
||||
image_class->get_height = gtk_css_image_filter_get_height;
|
||||
image_class->compute = gtk_css_image_filter_compute;
|
||||
image_class->equal = gtk_css_image_filter_equal;
|
||||
image_class->snapshot = gtk_css_image_filter_snapshot;
|
||||
image_class->is_dynamic = gtk_css_image_filter_is_dynamic;
|
||||
image_class->get_dynamic_image = gtk_css_image_filter_get_dynamic_image;
|
||||
image_class->parse = gtk_css_image_filter_parse;
|
||||
image_class->print = gtk_css_image_filter_print;
|
||||
image_class->is_computed = gtk_css_image_filter_is_computed;
|
||||
|
||||
object_class->dispose = gtk_css_image_filter_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_filter_init (GtkCssImageFilter *self)
|
||||
{
|
||||
}
|
||||
|
||||
GtkCssImage *
|
||||
gtk_css_image_filter_new (GtkCssImage *image,
|
||||
GtkCssValue *filter)
|
||||
{
|
||||
GtkCssImageFilter *self;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_CSS_IMAGE_FILTER, NULL);
|
||||
|
||||
self->image = g_object_ref (image);
|
||||
self->filter = gtk_css_value_ref (filter);
|
||||
|
||||
return GTK_CSS_IMAGE (self);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright © 2021 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_IMAGE_FILTER_PRIVATE_H__
|
||||
#define __GTK_CSS_IMAGE_FILTER_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssimageprivate.h"
|
||||
#include "gtk/gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_IMAGE_FILTER (gtk_css_image_filter_get_type ())
|
||||
#define GTK_CSS_IMAGE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_FILTER, GtkCssImageFilter))
|
||||
#define GTK_CSS_IMAGE_FILTER_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_FILTER, GtkCssImageFilterClass))
|
||||
#define GTK_IS_CSS_IMAGE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_FILTER))
|
||||
#define GTK_IS_CSS_IMAGE_FILTER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMAGE_FILTER))
|
||||
#define GTK_CSS_IMAGE_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMAGE_FILTER, GtkCssImageFilterClass))
|
||||
|
||||
typedef struct _GtkCssImageFilter GtkCssImageFilter;
|
||||
typedef struct _GtkCssImageFilterClass GtkCssImageFilterClass;
|
||||
|
||||
struct _GtkCssImageFilter
|
||||
{
|
||||
GtkCssImage parent;
|
||||
|
||||
GtkCssImage *image;
|
||||
GtkCssValue *filter;
|
||||
};
|
||||
|
||||
struct _GtkCssImageFilterClass
|
||||
{
|
||||
GtkCssImageClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_css_image_filter_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkCssImage * gtk_css_image_filter_new (GtkCssImage *image,
|
||||
GtkCssValue *filter);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_IMAGE_FILTER_PRIVATE_H__ */
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "gtkcssinheritvalueprivate.h"
|
||||
|
||||
#include "gtkcssinitialvalueprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkcssstyleprivate.h"
|
||||
|
||||
struct _GtkCssValue {
|
||||
GTK_CSS_VALUE_BASE
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "gtkcssshorthandpropertyprivate.h"
|
||||
#include "gtksettingsprivate.h"
|
||||
#include "gtkstyleprovider.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkstylepropertyprivate.h"
|
||||
#include "gtkstyleproviderprivate.h"
|
||||
#include "gtkmarshalers.h"
|
||||
|
||||
@@ -1073,11 +1073,8 @@ parse_n_plus_b (GtkCssParser *parser,
|
||||
*a = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_css_parser_error_syntax (parser, "Not a valid an+b type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
parse_a_n_plus_b (GtkCssParser *parser,
|
||||
int seen_sign,
|
||||
|
||||
+91
-32
@@ -25,7 +25,6 @@
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcsscolorvalueprivate.h"
|
||||
#include "gtksnapshotprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkpango.h"
|
||||
|
||||
#include "gsk/gskcairoblurprivate.h"
|
||||
@@ -45,12 +44,14 @@ typedef struct {
|
||||
|
||||
struct _GtkCssValue {
|
||||
GTK_CSS_VALUE_BASE
|
||||
guint is_filter : 1; /* values stored in radius are std_dev, for drop-shadow */
|
||||
guint n_shadows;
|
||||
ShadowValue shadows[1];
|
||||
};
|
||||
|
||||
static GtkCssValue * gtk_css_shadow_value_new (ShadowValue *shadows,
|
||||
guint n_shadows);
|
||||
guint n_shadows,
|
||||
gboolean is_filter);
|
||||
|
||||
static void
|
||||
shadow_value_for_transition (ShadowValue *result,
|
||||
@@ -134,7 +135,7 @@ gtk_css_value_shadow_compute (GtkCssValue *value,
|
||||
shadows[i].inset = shadow->inset;
|
||||
}
|
||||
|
||||
return gtk_css_shadow_value_new (shadows, value->n_shadows);
|
||||
return gtk_css_shadow_value_new (shadows, value->n_shadows, value->is_filter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -152,11 +153,11 @@ gtk_css_value_shadow_equal (const GtkCssValue *value1,
|
||||
const ShadowValue *shadow2 = &value2->shadows[i];
|
||||
|
||||
if (shadow1->inset != shadow2->inset ||
|
||||
_gtk_css_value_equal (shadow1->hoffset, shadow2->hoffset) ||
|
||||
_gtk_css_value_equal (shadow1->voffset, shadow2->voffset) ||
|
||||
_gtk_css_value_equal (shadow1->radius, shadow2->radius) ||
|
||||
_gtk_css_value_equal (shadow1->spread, shadow2->spread) ||
|
||||
_gtk_css_value_equal (shadow1->color, shadow2->color))
|
||||
!_gtk_css_value_equal (shadow1->hoffset, shadow2->hoffset) ||
|
||||
!_gtk_css_value_equal (shadow1->voffset, shadow2->voffset) ||
|
||||
!_gtk_css_value_equal (shadow1->radius, shadow2->radius) ||
|
||||
!_gtk_css_value_equal (shadow1->spread, shadow2->spread) ||
|
||||
!_gtk_css_value_equal (shadow1->color, shadow2->color))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -173,9 +174,6 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
|
||||
guint i, len;
|
||||
ShadowValue *shadows;
|
||||
|
||||
if (start->n_shadows != end->n_shadows)
|
||||
return NULL;
|
||||
|
||||
if (start->n_shadows > end->n_shadows)
|
||||
len = start->n_shadows;
|
||||
else
|
||||
@@ -231,7 +229,7 @@ gtk_css_value_shadow_transition (GtkCssValue *start,
|
||||
}
|
||||
}
|
||||
|
||||
return gtk_css_shadow_value_new (shadows, len);
|
||||
return gtk_css_shadow_value_new (shadows, len, start->is_filter);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -288,7 +286,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_SHADOW = {
|
||||
gtk_css_value_shadow_print
|
||||
};
|
||||
|
||||
static GtkCssValue shadow_none_singleton = { >K_CSS_VALUE_SHADOW, 1, TRUE, 0 };
|
||||
static GtkCssValue shadow_none_singleton = { >K_CSS_VALUE_SHADOW, 1, TRUE, FALSE, 0 };
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_shadow_value_new_none (void)
|
||||
@@ -298,7 +296,8 @@ gtk_css_shadow_value_new_none (void)
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_shadow_value_new (ShadowValue *shadows,
|
||||
guint n_shadows)
|
||||
guint n_shadows,
|
||||
gboolean is_filter)
|
||||
{
|
||||
GtkCssValue *retval;
|
||||
guint i;
|
||||
@@ -308,6 +307,7 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
|
||||
|
||||
retval = _gtk_css_value_alloc (>K_CSS_VALUE_SHADOW, sizeof (GtkCssValue) + sizeof (ShadowValue) * (n_shadows - 1));
|
||||
retval->n_shadows = n_shadows;
|
||||
retval->is_filter = is_filter;
|
||||
|
||||
memcpy (retval->shadows, shadows, sizeof (ShadowValue) * n_shadows);
|
||||
|
||||
@@ -330,6 +330,21 @@ gtk_css_shadow_value_new (ShadowValue *shadows,
|
||||
return retval;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_shadow_value_new_filter (void)
|
||||
{
|
||||
ShadowValue value;
|
||||
|
||||
value.inset = FALSE;
|
||||
value.hoffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||
value.voffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||
value.radius = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||
value.spread = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
|
||||
value.color = _gtk_css_color_value_new_current_color ();
|
||||
|
||||
return gtk_css_shadow_value_new (&value, 1, TRUE);
|
||||
}
|
||||
|
||||
enum {
|
||||
HOFFSET,
|
||||
VOFFSET,
|
||||
@@ -420,9 +435,9 @@ parse_color (GtkCssParser *parser,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gtk_css_shadow_value_parse_one (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode,
|
||||
ShadowValue *result)
|
||||
gtk_css_shadow_value_parse_one (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode,
|
||||
ShadowValue *result)
|
||||
{
|
||||
GtkCssValue *values[N_VALUES] = { NULL, };
|
||||
GtkCssValue *color = NULL;
|
||||
@@ -468,8 +483,8 @@ fail:
|
||||
|
||||
#define MAX_SHADOWS 64
|
||||
GtkCssValue *
|
||||
_gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode)
|
||||
gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode)
|
||||
{
|
||||
ShadowValue shadows[MAX_SHADOWS];
|
||||
int n_shadows = 0;
|
||||
@@ -479,7 +494,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
return gtk_css_shadow_value_new_none ();
|
||||
|
||||
do {
|
||||
if (_gtk_css_shadow_value_parse_one (parser, box_shadow_mode, &shadows[n_shadows]))
|
||||
if (gtk_css_shadow_value_parse_one (parser, box_shadow_mode, &shadows[n_shadows]))
|
||||
n_shadows++;
|
||||
|
||||
if (n_shadows > MAX_SHADOWS)
|
||||
@@ -489,7 +504,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
}
|
||||
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
|
||||
|
||||
return gtk_css_shadow_value_new (shadows, n_shadows);
|
||||
return gtk_css_shadow_value_new (shadows, n_shadows, FALSE);
|
||||
|
||||
fail:
|
||||
for (i = 0; i < n_shadows; i++)
|
||||
@@ -501,6 +516,17 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_shadow_value_parse_filter (GtkCssParser *parser)
|
||||
{
|
||||
ShadowValue shadow;
|
||||
|
||||
if (gtk_css_shadow_value_parse_one (parser, FALSE, &shadow))
|
||||
return gtk_css_shadow_value_new (&shadow, 1, TRUE);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_shadow_value_get_extents (const GtkCssValue *value,
|
||||
GtkBorder *border)
|
||||
@@ -516,6 +542,8 @@ gtk_css_shadow_value_get_extents (const GtkCssValue *value,
|
||||
|
||||
spread = _gtk_css_number_value_get (shadow->spread, 0);
|
||||
radius = _gtk_css_number_value_get (shadow->radius, 0);
|
||||
if (value->is_filter)
|
||||
radius = radius * 2;
|
||||
clip_radius = gsk_cairo_blur_compute_pixels (radius);
|
||||
hoffset = _gtk_css_number_value_get (shadow->hoffset, 0);
|
||||
voffset = _gtk_css_number_value_get (shadow->voffset, 0);
|
||||
@@ -533,6 +561,8 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *value,
|
||||
const GskRoundedRect *border_box)
|
||||
{
|
||||
guint i;
|
||||
double dx, dy, spread, radius;
|
||||
const GdkRGBA *color;
|
||||
|
||||
g_return_if_fail (value->class == >K_CSS_VALUE_SHADOW);
|
||||
|
||||
@@ -543,17 +573,20 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *value,
|
||||
if (shadow->inset)
|
||||
continue;
|
||||
|
||||
color = gtk_css_color_value_get_rgba (shadow->color);
|
||||
|
||||
/* We don't need to draw invisible shadows */
|
||||
if (gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color)))
|
||||
if (gdk_rgba_is_clear (color))
|
||||
continue;
|
||||
|
||||
gtk_snapshot_append_outset_shadow (snapshot,
|
||||
border_box,
|
||||
gtk_css_color_value_get_rgba (shadow->color),
|
||||
_gtk_css_number_value_get (shadow->hoffset, 0),
|
||||
_gtk_css_number_value_get (shadow->voffset, 0),
|
||||
_gtk_css_number_value_get (shadow->spread, 0),
|
||||
_gtk_css_number_value_get (shadow->radius, 0));
|
||||
dx = _gtk_css_number_value_get (shadow->hoffset, 0);
|
||||
dy = _gtk_css_number_value_get (shadow->voffset, 0);
|
||||
spread = _gtk_css_number_value_get (shadow->spread, 0);
|
||||
radius = _gtk_css_number_value_get (shadow->radius, 0);
|
||||
if (value->is_filter)
|
||||
radius = 2 * radius;
|
||||
|
||||
gtk_snapshot_append_outset_shadow (snapshot, border_box, color, dx, dy, spread, radius);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,15 +608,18 @@ gtk_css_shadow_value_snapshot_inset (const GtkCssValue *value,
|
||||
if (!shadow->inset)
|
||||
continue;
|
||||
|
||||
color = gtk_css_color_value_get_rgba (shadow->color);
|
||||
|
||||
/* We don't need to draw invisible shadows */
|
||||
if (gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color)))
|
||||
if (gdk_rgba_is_clear (color))
|
||||
continue;
|
||||
|
||||
dx = _gtk_css_number_value_get (shadow->hoffset, 0);
|
||||
dy = _gtk_css_number_value_get (shadow->voffset, 0);
|
||||
spread = _gtk_css_number_value_get (shadow->spread, 0);
|
||||
radius = _gtk_css_number_value_get (shadow->radius, 0);
|
||||
color = gtk_css_color_value_get_rgba (shadow->color);
|
||||
if (value->is_filter)
|
||||
radius = 2 * radius;
|
||||
|
||||
/* These are trivial to do with a color node */
|
||||
if (spread == 0 && radius == 0 &&
|
||||
@@ -679,7 +715,6 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
|
||||
gboolean need_shadow = FALSE;
|
||||
guint i;
|
||||
|
||||
/* TODO: We can save this as a flag once and then reuse it */
|
||||
for (i = 0; i < value->n_shadows; i++)
|
||||
{
|
||||
const ShadowValue *shadow = &value->shadows[i];
|
||||
@@ -703,6 +738,8 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
|
||||
shadows[i].dy = _gtk_css_number_value_get (shadow->voffset, 0);
|
||||
shadows[i].color = *gtk_css_color_value_get_rgba (shadow->color);
|
||||
shadows[i].radius = _gtk_css_number_value_get (shadow->radius, 0);
|
||||
if (value->is_filter)
|
||||
shadows[i].radius *= 2;
|
||||
}
|
||||
|
||||
gtk_snapshot_push_shadow (snapshot, shadows, value->n_shadows);
|
||||
@@ -710,3 +747,25 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
|
||||
|
||||
return need_shadow;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_shadow_value_pop_snapshot (const GtkCssValue *value,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
gboolean need_shadow = FALSE;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < value->n_shadows; i++)
|
||||
{
|
||||
const ShadowValue *shadow = &value->shadows[i];
|
||||
|
||||
if (!gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color)))
|
||||
{
|
||||
need_shadow = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_shadow)
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
@@ -34,10 +34,12 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * gtk_css_shadow_value_new_none (void);
|
||||
GtkCssValue * gtk_css_shadow_value_new_none (void);
|
||||
GtkCssValue * gtk_css_shadow_value_new_filter (void);
|
||||
|
||||
GtkCssValue * _gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
GtkCssValue * gtk_css_shadow_value_parse (GtkCssParser *parser,
|
||||
gboolean box_shadow_mode);
|
||||
GtkCssValue * gtk_css_shadow_value_parse_filter (GtkCssParser *parser);
|
||||
|
||||
void gtk_css_shadow_value_get_extents (const GtkCssValue *shadow,
|
||||
GtkBorder *border);
|
||||
@@ -53,6 +55,8 @@ gboolean gtk_css_shadow_value_is_none (const GtkCssValue
|
||||
|
||||
gboolean gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
|
||||
GtkSnapshot *snapshot);
|
||||
void gtk_css_shadow_value_pop_snapshot (const GtkCssValue *value,
|
||||
GtkSnapshot *snapshot);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -865,16 +865,26 @@ parse_text_decoration (GtkCssShorthandProperty *shorthand,
|
||||
GtkCssValue **values,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
GtkTextDecorationLine line = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (values[0] == NULL &&
|
||||
(values[0] = _gtk_css_text_decoration_line_value_try_parse (parser)))
|
||||
GtkTextDecorationLine parsed_line;
|
||||
|
||||
parsed_line = _gtk_css_text_decoration_line_try_parse_one (parser, line);
|
||||
|
||||
if (parsed_line == 0 && line != 0)
|
||||
{
|
||||
if (values[0] == NULL)
|
||||
return FALSE;
|
||||
gtk_css_parser_error_value (parser, "Invalid combination of text-decoration-line values");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (parsed_line != line)
|
||||
{
|
||||
line = parsed_line;
|
||||
}
|
||||
else if (values[1] == NULL &&
|
||||
(values[1] = _gtk_css_text_decoration_style_value_try_parse (parser)))
|
||||
(values[1] = _gtk_css_text_decoration_style_value_try_parse (parser)))
|
||||
{
|
||||
if (values[1] == NULL)
|
||||
return FALSE;
|
||||
@@ -895,6 +905,16 @@ parse_text_decoration (GtkCssShorthandProperty *shorthand,
|
||||
}
|
||||
while (!value_is_done_parsing (parser));
|
||||
|
||||
if (line != 0)
|
||||
{
|
||||
values[0] = _gtk_css_text_decoration_line_value_new (line);
|
||||
if (values[0] == NULL)
|
||||
{
|
||||
gtk_css_parser_error_value (parser, "Invalid combination of text-decoration-line values");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ static const int other_props[] = {
|
||||
GTK_CSS_PROPERTY_ICON_TRANSFORM,
|
||||
GTK_CSS_PROPERTY_ICON_FILTER,
|
||||
GTK_CSS_PROPERTY_TRANSFORM,
|
||||
GTK_CSS_PROPERTY_TRANSFORM_ORIGIN,
|
||||
GTK_CSS_PROPERTY_OPACITY,
|
||||
GTK_CSS_PROPERTY_FILTER,
|
||||
};
|
||||
@@ -593,6 +594,9 @@ gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle,
|
||||
case GTK_CSS_PROPERTY_TRANSFORM:
|
||||
gtk_css_take_value (&style->other->transform, value);
|
||||
break;
|
||||
case GTK_CSS_PROPERTY_TRANSFORM_ORIGIN:
|
||||
gtk_css_take_value (&style->other->transform_origin, value);
|
||||
break;
|
||||
case GTK_CSS_PROPERTY_MIN_WIDTH:
|
||||
gtk_css_take_value (&style->size->min_width, value);
|
||||
break;
|
||||
@@ -880,6 +884,7 @@ gtk_css_other_create_initial_values (void)
|
||||
values->icon_transform = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_TRANSFORM, NULL, NULL, NULL);
|
||||
values->icon_filter = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_ICON_FILTER, NULL, NULL, NULL);
|
||||
values->transform = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSFORM, NULL, NULL, NULL);
|
||||
values->transform_origin = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_TRANSFORM_ORIGIN, NULL, NULL, NULL);
|
||||
values->opacity = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_OPACITY, NULL, NULL, NULL);
|
||||
values->filter = _gtk_css_initial_value_new_compute (GTK_CSS_PROPERTY_FILTER, NULL, NULL, NULL);
|
||||
|
||||
|
||||
+20
-8
@@ -235,6 +235,8 @@ gtk_css_style_get_value (GtkCssStyle *style,
|
||||
return style->size->border_spacing;
|
||||
case GTK_CSS_PROPERTY_TRANSFORM:
|
||||
return style->other->transform;
|
||||
case GTK_CSS_PROPERTY_TRANSFORM_ORIGIN:
|
||||
return style->other->transform_origin;
|
||||
case GTK_CSS_PROPERTY_MIN_WIDTH:
|
||||
return style->size->min_width;
|
||||
case GTK_CSS_PROPERTY_MIN_HEIGHT:
|
||||
@@ -395,6 +397,12 @@ get_pango_underline_from_style (GtkTextDecorationStyle style)
|
||||
g_return_val_if_reached (PANGO_UNDERLINE_SINGLE);
|
||||
}
|
||||
|
||||
static PangoOverline
|
||||
get_pango_overline_from_style (GtkTextDecorationStyle style)
|
||||
{
|
||||
return PANGO_OVERLINE_SINGLE;
|
||||
}
|
||||
|
||||
static PangoAttrList *
|
||||
add_pango_attr (PangoAttrList *attrs,
|
||||
PangoAttribute *attr)
|
||||
@@ -443,25 +451,29 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
|
||||
? style->font_variant->text_decoration_color
|
||||
: style->core->color);
|
||||
|
||||
switch (decoration_line)
|
||||
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE)
|
||||
{
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE:
|
||||
attrs = add_pango_attr (attrs, pango_attr_underline_new (get_pango_underline_from_style (decoration_style)));
|
||||
if (!gdk_rgba_equal (color, decoration_color))
|
||||
attrs = add_pango_attr (attrs, pango_attr_underline_color_new (decoration_color->red * 65535. + 0.5,
|
||||
decoration_color->green * 65535. + 0.5,
|
||||
decoration_color->blue * 65535. + 0.5));
|
||||
break;
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH:
|
||||
}
|
||||
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_OVERLINE)
|
||||
{
|
||||
attrs = add_pango_attr (attrs, pango_attr_overline_new (get_pango_overline_from_style (decoration_style)));
|
||||
if (!gdk_rgba_equal (color, decoration_color))
|
||||
attrs = add_pango_attr (attrs, pango_attr_overline_color_new (decoration_color->red * 65535. + 0.5,
|
||||
decoration_color->green * 65535. + 0.5,
|
||||
decoration_color->blue * 65535. + 0.5));
|
||||
}
|
||||
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH)
|
||||
{
|
||||
attrs = add_pango_attr (attrs, pango_attr_strikethrough_new (TRUE));
|
||||
if (!gdk_rgba_equal (color, decoration_color))
|
||||
attrs = add_pango_attr (attrs, pango_attr_strikethrough_color_new (decoration_color->red * 65535. + 0.5,
|
||||
decoration_color->green * 65535. + 0.5,
|
||||
decoration_color->blue * 65535. + 0.5));
|
||||
break;
|
||||
case GTK_CSS_TEXT_DECORATION_LINE_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* letter-spacing */
|
||||
|
||||
@@ -208,6 +208,7 @@ struct _GtkCssOtherValues {
|
||||
GtkCssValue *icon_transform;
|
||||
GtkCssValue *icon_filter;
|
||||
GtkCssValue *transform;
|
||||
GtkCssValue *transform_origin;
|
||||
GtkCssValue *opacity;
|
||||
GtkCssValue *filter;
|
||||
};
|
||||
|
||||
@@ -317,14 +317,38 @@ parse_letter_spacing (GtkCssStyleProperty *property,
|
||||
return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
value_is_done_parsing (GtkCssParser *parser)
|
||||
{
|
||||
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
parse_text_decoration_line (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
GtkCssValue *value = _gtk_css_text_decoration_line_value_try_parse (parser);
|
||||
GtkCssValue *value = NULL;
|
||||
GtkTextDecorationLine line;
|
||||
|
||||
line = 0;
|
||||
do {
|
||||
GtkTextDecorationLine parsed;
|
||||
|
||||
parsed = _gtk_css_text_decoration_line_try_parse_one (parser, line);
|
||||
if (parsed == 0 || parsed == line)
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Not a valid value");
|
||||
return NULL;
|
||||
}
|
||||
line = parsed;
|
||||
} while (!value_is_done_parsing (parser));
|
||||
|
||||
value = _gtk_css_text_decoration_line_value_new (line);
|
||||
if (value == NULL)
|
||||
gtk_css_parser_error_syntax (parser, "unknown text decoration line value");
|
||||
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -353,15 +377,6 @@ parse_font_kerning (GtkCssStyleProperty *property,
|
||||
return value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
value_is_done_parsing (GtkCssParser *parser)
|
||||
{
|
||||
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
|
||||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
parse_font_variant_ligatures (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
@@ -497,14 +512,14 @@ static GtkCssValue *
|
||||
box_shadow_value_parse (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
return _gtk_css_shadow_value_parse (parser, TRUE);
|
||||
return gtk_css_shadow_value_parse (parser, TRUE);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
shadow_value_parse (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
return _gtk_css_shadow_value_parse (parser, FALSE);
|
||||
return gtk_css_shadow_value_parse (parser, FALSE);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
@@ -790,6 +805,13 @@ background_position_parse (GtkCssStyleProperty *property,
|
||||
return _gtk_css_array_value_parse (parser, _gtk_css_position_value_parse);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
transform_origin_parse (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
return _gtk_css_position_value_parse (parser);
|
||||
}
|
||||
|
||||
/*** REGISTRATION ***/
|
||||
|
||||
G_STATIC_ASSERT (GTK_CSS_PROPERTY_COLOR == 0);
|
||||
@@ -1248,6 +1270,13 @@ _gtk_css_style_property_init_properties (void)
|
||||
GTK_CSS_AFFECTS_TRANSFORM,
|
||||
transform_value_parse,
|
||||
_gtk_css_transform_value_new_none ());
|
||||
gtk_css_style_property_register ("transform-origin",
|
||||
GTK_CSS_PROPERTY_TRANSFORM_ORIGIN,
|
||||
GTK_STYLE_PROPERTY_ANIMATED,
|
||||
GTK_CSS_AFFECTS_TRANSFORM,
|
||||
transform_origin_parse,
|
||||
_gtk_css_position_value_new (_gtk_css_number_value_new (50, GTK_CSS_PERCENT),
|
||||
_gtk_css_number_value_new (50, GTK_CSS_PERCENT)));
|
||||
gtk_css_style_property_register ("min-width",
|
||||
GTK_CSS_PROPERTY_MIN_WIDTH,
|
||||
GTK_STYLE_PROPERTY_ANIMATED,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user