Compare commits
230 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd06452b0f | |||
| 4e166f39fe | |||
| 5f79958716 | |||
| aee0af34af | |||
| 7e32eb2e98 | |||
| 7ea7d5c390 | |||
| e3e9dda429 | |||
| a3ab25bf1d | |||
| 095dec9238 | |||
| 0e34365139 | |||
| 88a62564f1 | |||
| 6ac94dc5c3 | |||
| 5a9a0874bd | |||
| 91992111c3 | |||
| 120d874805 | |||
| 9454bad891 | |||
| 9cb410fd9b | |||
| 0f3fbed13c | |||
| 43ee9746bd | |||
| 7283c5c22f | |||
| 8b71fe4af6 | |||
| b627fb5970 | |||
| be3ad1ef99 | |||
| 54264a9f78 | |||
| 65380c66bd | |||
| 8c96991ce0 | |||
| 07a44993ac | |||
| 60d2d25463 | |||
| 907f99b176 | |||
| ce6aa73c64 | |||
| 257bef85d0 | |||
| a48df87a85 | |||
| fe4cd7cf0f | |||
| 229b34d478 | |||
| 1985f2c9ad | |||
| 01d57a7566 | |||
| 7a4b2c10c7 | |||
| 208b2d37b6 | |||
| ef98912779 | |||
| b1e3b18ede | |||
| 0194cadbc0 | |||
| b4dfc4adfc | |||
| fd556ec377 | |||
| 1dbc1d67f5 | |||
| 8790c83a76 | |||
| 6b202fb838 | |||
| f69476435f | |||
| 8df6e2cdaf | |||
| 2861ab38ac | |||
| 23c2122c13 | |||
| 5b83ffa4a0 | |||
| cf8e3157a7 | |||
| 7323172755 | |||
| cfee8f4b11 | |||
| 7ae099c94c | |||
| 42298d8ab1 | |||
| 68912698f1 | |||
| c8c56f8d42 | |||
| 7f48b5a05c | |||
| 1e5e977b37 | |||
| 62d44b6bc7 | |||
| 862afeffe0 | |||
| 92f9195015 | |||
| fc6e08082b | |||
| af7516b797 | |||
| 3f1821e372 | |||
| b569470b87 | |||
| f1a3235039 | |||
| 34e90005af | |||
| 4f1cc8ec6d | |||
| 5242205a65 | |||
| 59633a6781 | |||
| d82316edda | |||
| 0815640b22 | |||
| 26de2eae20 | |||
| 8fa358c4d4 | |||
| fc72449228 | |||
| 84a304e66e | |||
| ecf1b7c18a | |||
| a7c5b53f46 | |||
| 09736dde93 | |||
| 66c00dc9f3 | |||
| 3eacf8bd39 | |||
| 34e9ef9e78 | |||
| a5955106ea | |||
| ea0cfed735 | |||
| f312d1ee6a | |||
| 69b6f4cf4f | |||
| d7e1c377fe | |||
| cc17577763 | |||
| ef4ae61c66 | |||
| e04ea3f311 | |||
| 77a2cd4d8d | |||
| 0986981d1a | |||
| 913f850f83 | |||
| ed31da3730 | |||
| 428ff6c4ab | |||
| 53786841cc | |||
| 8f8ece44a8 | |||
| 41a892b958 | |||
| b494ed5876 | |||
| 7b589f991d | |||
| d83faf82d7 | |||
| cd46016238 | |||
| f2a3218455 | |||
| 85b1959714 | |||
| b23600ae4b | |||
| bdc43b8fca | |||
| da2ef6911f | |||
| 0626246367 | |||
| 0edfafdfdf | |||
| 1863b79fb3 | |||
| 9aa90f8df0 | |||
| 8080d9e7c1 | |||
| f432ee775f | |||
| 77f9cb11a9 | |||
| d92e3cb864 | |||
| 733fa156b9 | |||
| d181d53762 | |||
| 644e6f8ebe | |||
| 0b4c695d65 | |||
| 448287bd58 | |||
| 5e6aff69c6 | |||
| d88e616711 | |||
| 0e5c94a094 | |||
| bb0aeec99c | |||
| 880e3ef289 | |||
| 94a09263d7 | |||
| ab9106ac89 | |||
| ff6451a77e | |||
| 4f2d63b8ac | |||
| 81c97f0910 | |||
| d1b52cc292 | |||
| ddedb39329 | |||
| d45987e637 | |||
| b95eceea60 | |||
| 2774e80fc4 | |||
| 7c207c4868 | |||
| c6c8abcf21 | |||
| a59c967675 | |||
| c3329f5fcc | |||
| 4f06e46759 | |||
| 7e522a8c55 | |||
| d9447fd2e7 | |||
| 95214f3697 | |||
| fe64c998f8 | |||
| 84582ad762 | |||
| fcc7a58058 | |||
| 8a48becb7e | |||
| 465446430e | |||
| 4060c43ae7 | |||
| 4ec9a2a330 | |||
| 90c017a762 | |||
| e011434223 | |||
| b1ccb4103d | |||
| 8033809f8b | |||
| 66ba1f76ba | |||
| 0ca822c716 | |||
| 4ac288c1b4 | |||
| 64316ab185 | |||
| 4d90a693ae | |||
| 0c5f943783 | |||
| 42fc165b94 | |||
| 20a4e3f351 | |||
| f3f90e1d71 | |||
| b018da2acd | |||
| ab5f3f59ce | |||
| 0127217e10 | |||
| 16a476fe22 | |||
| c8ca6930c5 | |||
| c4f33f36de | |||
| 0543c48862 | |||
| fcb17a86e6 | |||
| 5633b5b637 | |||
| f7eaf69d67 | |||
| 32411943ea | |||
| 58fa5d7617 | |||
| f9ee1967f4 | |||
| 6a376f0a30 | |||
| 66826c26db | |||
| 8d1e37789e | |||
| 6c39a5946e | |||
| 2a98928286 | |||
| c7806eb908 | |||
| 9015734e65 | |||
| f5159e1ecb | |||
| aec2f50d82 | |||
| 74860f7602 | |||
| a9175e0c03 | |||
| e1c56555af | |||
| 24120c8fd0 | |||
| f284331f79 | |||
| a82de96e1a | |||
| eba9b116ed | |||
| 1f89b3c7df | |||
| c739b9fe7f | |||
| 556b729b97 | |||
| 9fd5558acd | |||
| b7422c0f62 | |||
| ace684c7ab | |||
| 752e704e99 | |||
| 8c7e13746b | |||
| c2311c7154 | |||
| 44fa748826 | |||
| dfed398371 | |||
| 962ba49a8e | |||
| 5811e443f8 | |||
| f55e1392d4 | |||
| 0fbe5ba40c | |||
| 980ea63d78 | |||
| dcc3533363 | |||
| 28964aa0a4 | |||
| 7fd8a0ac99 | |||
| d919ed4e4b | |||
| 61ec6fb5eb | |||
| 237eb8bb90 | |||
| ff57cd9331 | |||
| c97d02f487 | |||
| 36ced69ebf | |||
| 427a52a9ad | |||
| 9b5aee0d1b | |||
| 882387a62a | |||
| 73f7370ead | |||
| 8e9241f3ba | |||
| 3c67931f5f | |||
| ee06ac3ad2 | |||
| 19a8870f76 | |||
| 99a3a7e94e | |||
| a516441513 | |||
| 2f5278a139 |
+3
-1
@@ -219,11 +219,13 @@ macos:
|
|||||||
- if: $RUNNER == "macosintel"
|
- if: $RUNNER == "macosintel"
|
||||||
variables:
|
variables:
|
||||||
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
|
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
|
||||||
|
NINJA_PKG: $CI_API_V4_URL/projects/30745/packages/generic/ninja_macos/v1.11.1.1+9/ninja-1.11.1.1-cp38-cp38-macosx_11_0_x86_64.whl
|
||||||
when: manual
|
when: manual
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
- if: $RUNNER == "macosarm"
|
- if: $RUNNER == "macosarm"
|
||||||
variables:
|
variables:
|
||||||
SDKROOT: /opt/sdks/MacOSX11.3.sdk
|
SDKROOT: /opt/sdks/MacOSX11.3.sdk
|
||||||
|
NINJA_PKG: ninja==1.11.1.1
|
||||||
stage: build
|
stage: build
|
||||||
parallel:
|
parallel:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -246,7 +248,7 @@ macos:
|
|||||||
- curl -L $CI_API_V4_URL/projects/30437/packages/generic/pkgconfig/v0.29.2+10/pkg-config-0.29.2+10_$(uname -m).tar.xz | tar -C .venv -xJ
|
- curl -L $CI_API_V4_URL/projects/30437/packages/generic/pkgconfig/v0.29.2+10/pkg-config-0.29.2+10_$(uname -m).tar.xz | tar -C .venv -xJ
|
||||||
- curl -L $CI_API_V4_URL/projects/30438/packages/generic/bison/v3.8.2+3/bison-3.8.2+3_$(uname -m).tar.xz | tar -C .venv -xJ
|
- curl -L $CI_API_V4_URL/projects/30438/packages/generic/bison/v3.8.2+3/bison-3.8.2+3_$(uname -m).tar.xz | tar -C .venv -xJ
|
||||||
- source .venv/bin/activate
|
- source .venv/bin/activate
|
||||||
- pip3 install meson==1.3.2 ninja==1.11.1.1
|
- pip3 install meson==1.3.2 $NINJA_PKG
|
||||||
# We're not setting up ccache here on purpose as it accelerates the build
|
# We're not setting up ccache here on purpose as it accelerates the build
|
||||||
# so much that it triggers race conditions in the gobject-introspection
|
# so much that it triggers race conditions in the gobject-introspection
|
||||||
# subproject.
|
# subproject.
|
||||||
|
|||||||
@@ -1,11 +1,115 @@
|
|||||||
Overview of Changes in 4.13.9, xx-xx-xxxx
|
Overview of Changes in 4.14.1, xx-xx-xxxx
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
|
Overview of Changes in 4.14.0, 12-03-2024
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
Note: The new renderers and dmabuf support are using graphics drivers
|
Note: The new renderers and dmabuf support are using graphics drivers
|
||||||
in different ways than the old gl renderer, and trigger new driver bugs,
|
in different ways than the old gl renderer, and trigger new driver bugs,
|
||||||
(see for example https://gitlab.gnome.org/GNOME/gtk/-/issues/6418 and
|
(see for example https://gitlab.gnome.org/GNOME/gtk/-/issues/6418 and
|
||||||
https://gitlab.gnome.org/GNOME/gtk/-/issues/6388). Therefore, it is
|
https://gitlab.gnome.org/GNOME/gtk/-/issues/6388). Therefore, it is
|
||||||
recommended to use the latest mesa release (24.0) with the new renderers.
|
recommended to use the latest mesa release (24.x) with the new renderers.
|
||||||
|
|
||||||
|
* GtkTextView:
|
||||||
|
- Don't snapshot children twice
|
||||||
|
- Don't blink the cursor when hidden
|
||||||
|
|
||||||
|
* GtkEmojiChooser:
|
||||||
|
- Fix presentation selector handling
|
||||||
|
|
||||||
|
* GtkSnapshot:
|
||||||
|
- Fix wrong nodes with transformed shadows
|
||||||
|
|
||||||
|
* GtkIMContext:
|
||||||
|
- Make gtk_im_context_activate_osk public
|
||||||
|
|
||||||
|
* Accessibility:
|
||||||
|
- Implement get_contents_at for all our text widgets
|
||||||
|
- Add GtkAccessibleText.get_default_attributes
|
||||||
|
|
||||||
|
* GSK:
|
||||||
|
- Don't fall back to cairo for software rendering. gl+llvmpipe is better
|
||||||
|
- Round vertical glyph position to a device pixel position if the font is hinted
|
||||||
|
- Fix problems with clip handling
|
||||||
|
- Make vulkan and ngl match their font handling
|
||||||
|
- Fix some corner-cases with offloading and clips
|
||||||
|
- Fix problem with rendering of missing glyphs in hinted fonts
|
||||||
|
|
||||||
|
* MacOs:
|
||||||
|
- Implement cursor-from-texture
|
||||||
|
|
||||||
|
* Translation updates:
|
||||||
|
Basque
|
||||||
|
British English
|
||||||
|
French
|
||||||
|
Indonesian
|
||||||
|
Kazakh
|
||||||
|
Latvian
|
||||||
|
Lithuanian
|
||||||
|
Norwegian Bokmål
|
||||||
|
Slovenian
|
||||||
|
Spanish
|
||||||
|
Turkish
|
||||||
|
|
||||||
|
|
||||||
|
Overview of Changes in 4.13.9, 02-03-2024
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
* GtkEditable:
|
||||||
|
- Fix preconditions to be not too strict
|
||||||
|
|
||||||
|
* GtkEmojiChooser:
|
||||||
|
- Support search in the locale as well as in English
|
||||||
|
|
||||||
|
* GtkIconTheme:
|
||||||
|
- Make gtk_icon_paintable_new_for_file support symbolics
|
||||||
|
|
||||||
|
* GtkVideo:
|
||||||
|
- Fix a problem with cursor handling that could lead to crashes
|
||||||
|
|
||||||
|
* Accessibility:
|
||||||
|
- Fix GetCharacterAtOffset implementation
|
||||||
|
- Add a Terminal role
|
||||||
|
- Make TextCaretMoved match gtk3
|
||||||
|
- Support multiple levels of GtkEditable delegates
|
||||||
|
|
||||||
|
* GSK:
|
||||||
|
- Make the node parser more flexible for text nodes
|
||||||
|
- Change the way font scaling is handled to avoid clipping
|
||||||
|
- Fix handling of missing glyphs in the new renderers
|
||||||
|
|
||||||
|
* X11:
|
||||||
|
- Don't claim to support shadows without a compositor
|
||||||
|
|
||||||
|
* Wayland:
|
||||||
|
- Fix handling of output scales
|
||||||
|
|
||||||
|
* Tools:
|
||||||
|
- Add a compare command to gtk4-rendernode-tool
|
||||||
|
|
||||||
|
* Build:
|
||||||
|
- Fix some ubsan complaints
|
||||||
|
|
||||||
|
* Translation updates:
|
||||||
|
Basque
|
||||||
|
British English
|
||||||
|
Catalan
|
||||||
|
Finnish
|
||||||
|
Galician
|
||||||
|
Georgian
|
||||||
|
Hebrew
|
||||||
|
Indonesian
|
||||||
|
Kazakh
|
||||||
|
Latvian
|
||||||
|
Lithuanian
|
||||||
|
Persian
|
||||||
|
Polish
|
||||||
|
Russian
|
||||||
|
Slovenian
|
||||||
|
Spanish
|
||||||
|
Turkish
|
||||||
|
Ukrainian
|
||||||
|
|
||||||
|
|
||||||
Overview of Changes in 4.13.8, 20-02-2024
|
Overview of Changes in 4.13.8, 20-02-2024
|
||||||
|
|||||||
@@ -600,8 +600,8 @@ update_display (void)
|
|||||||
if (s->len > 0)
|
if (s->len > 0)
|
||||||
{
|
{
|
||||||
pango_font_description_set_variations (desc, s->str);
|
pango_font_description_set_variations (desc, s->str);
|
||||||
g_string_free (s, TRUE);
|
|
||||||
}
|
}
|
||||||
|
g_string_free (s, TRUE);
|
||||||
|
|
||||||
font_desc = pango_font_description_to_string (desc);
|
font_desc = pango_font_description_to_string (desc);
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ static gboolean gtk_shadertoy_tick (GtkWidget *widget,
|
|||||||
GtkWidget *
|
GtkWidget *
|
||||||
gtk_shadertoy_new (void)
|
gtk_shadertoy_new (void)
|
||||||
{
|
{
|
||||||
return g_object_new (gtk_shadertoy_get_type (), NULL);
|
return g_object_new (gtk_shadertoy_get_type (),
|
||||||
|
"allowed-apis", GDK_GL_API_GL,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ do_images (GtkWidget *do_widget)
|
|||||||
gicon = g_themed_icon_new_with_default_fallbacks ("battery-caution-charging-symbolic");
|
gicon = g_themed_icon_new_with_default_fallbacks ("battery-caution-charging-symbolic");
|
||||||
image = gtk_image_new_from_gicon (gicon);
|
image = gtk_image_new_from_gicon (gicon);
|
||||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||||
|
g_object_unref (gicon);
|
||||||
|
|
||||||
gtk_frame_set_child (GTK_FRAME (frame), image);
|
gtk_frame_set_child (GTK_FRAME (frame), image);
|
||||||
|
|
||||||
|
|||||||
@@ -322,12 +322,14 @@ stroke bounds of the path.
|
|||||||
|
|
||||||
### text
|
### text
|
||||||
|
|
||||||
| property | syntax | default | printed |
|
| property | syntax | default | printed |
|
||||||
| -------- | ------------------- | ------------------- | ----------- |
|
| ------------ | ------------------- | ------------------- | ----------- |
|
||||||
| color | `<color>` | black | non-default |
|
| color | `<color>` | black | non-default |
|
||||||
| font | `<string>` `<url>`? | "Cantarell 11" | always |
|
| font | `<string>` `<url>`? | "Cantarell 15px" | always |
|
||||||
| glyphs | `<glyphs>` | "Hello" | always |
|
| glyphs | `<glyphs>` | "Hello" | always |
|
||||||
| offset | `<point>` | 0 0 | non-default |
|
| offset | `<point>` | 0 0 | non-default |
|
||||||
|
| hint-style | `<hint style>` | slight | non-default |
|
||||||
|
| antialias | `<antialias>` | gray | non-default |
|
||||||
|
|
||||||
Creates a node like `gsk_text_node_new()` with the given properties.
|
Creates a node like `gsk_text_node_new()` with the given properties.
|
||||||
|
|
||||||
@@ -336,12 +338,15 @@ font that is specified in the string. It can be either a data url containing
|
|||||||
a base64-encoded font file, or a regular url that points to a font file.
|
a base64-encoded font file, or a regular url that points to a font file.
|
||||||
|
|
||||||
Glyphs can be specified as an ASCII string, or as a comma-separated list of
|
Glyphs can be specified as an ASCII string, or as a comma-separated list of
|
||||||
their glyph ID and advance width. Optionally, x and y offsets and flags can
|
their glyph IDs. Optionally, the advance width, x and y offsets and flags can
|
||||||
be specified as well, like this: 40 10 0 0 color.
|
be specified as well, like this: 40 10 0 0 color.
|
||||||
|
|
||||||
If the given font does not exist or the given glyphs are invalid for the given
|
If the given font does not exist or the given glyphs are invalid for the given
|
||||||
font, an error node will be returned.
|
font, an error node will be returned.
|
||||||
|
|
||||||
|
Possible values for hint-style are none, slight or full.
|
||||||
|
Possible value for antialias are none or gray.
|
||||||
|
|
||||||
### texture
|
### texture
|
||||||
|
|
||||||
| property | syntax | default | printed |
|
| property | syntax | default | printed |
|
||||||
|
|||||||
+3
-3
@@ -69,9 +69,9 @@ Image:
|
|||||||
4 CARD32 IMAGE_DATA_OFFSET
|
4 CARD32 IMAGE_DATA_OFFSET
|
||||||
|
|
||||||
ICON_FLAGS
|
ICON_FLAGS
|
||||||
HAS_SUFFIX_PNG 1
|
HAS_SUFFIX_XPM 1
|
||||||
HAS_SUFFIX_XPM 2
|
HAS_SUFFIX_SVG 2
|
||||||
HAS_SUFFIX_SVG 4
|
HAS_SUFFIX_PNG 4
|
||||||
HAS_ICON_FILE 8
|
HAS_ICON_FILE 8
|
||||||
|
|
||||||
ImageData:
|
ImageData:
|
||||||
|
|||||||
+4
-1
@@ -2037,9 +2037,12 @@ gdk_display_get_dmabuf_formats (GdkDisplay *display)
|
|||||||
GdkDebugFlags
|
GdkDebugFlags
|
||||||
gdk_display_get_debug_flags (GdkDisplay *display)
|
gdk_display_get_debug_flags (GdkDisplay *display)
|
||||||
{
|
{
|
||||||
|
if (display == NULL)
|
||||||
|
return _gdk_debug_flags;
|
||||||
|
|
||||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||||
|
|
||||||
return display ? priv->debug_flags : _gdk_debug_flags;
|
return priv->debug_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
+56
-29
@@ -79,14 +79,23 @@ static guint signals[LAST_SIGNAL];
|
|||||||
|
|
||||||
static guint fps_counter;
|
static guint fps_counter;
|
||||||
|
|
||||||
#define FRAME_HISTORY_MAX_LENGTH 128
|
/* 60Hz plus some extra for monotonic time inaccuracy */
|
||||||
|
#define FRAME_HISTORY_DEFAULT_LENGTH 64
|
||||||
|
|
||||||
|
#define frame_timings_unref(x) gdk_frame_timings_unref((GdkFrameTimings *) (x))
|
||||||
|
|
||||||
|
#define GDK_ARRAY_NAME timings
|
||||||
|
#define GDK_ARRAY_TYPE_NAME Timings
|
||||||
|
#define GDK_ARRAY_ELEMENT_TYPE GdkFrameTimings *
|
||||||
|
#define GDK_ARRAY_PREALLOC FRAME_HISTORY_DEFAULT_LENGTH
|
||||||
|
#define GDK_ARRAY_FREE_FUNC frame_timings_unref
|
||||||
|
#include "gdk/gdkarrayimpl.c"
|
||||||
|
|
||||||
struct _GdkFrameClockPrivate
|
struct _GdkFrameClockPrivate
|
||||||
{
|
{
|
||||||
gint64 frame_counter;
|
gint64 frame_counter;
|
||||||
int n_timings;
|
|
||||||
int current;
|
int current;
|
||||||
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
|
Timings timings;
|
||||||
int n_freeze_inhibitors;
|
int n_freeze_inhibitors;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,11 +108,8 @@ static void
|
|||||||
gdk_frame_clock_finalize (GObject *object)
|
gdk_frame_clock_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
|
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++)
|
timings_clear (&priv->timings);
|
||||||
if (priv->timings[i] != 0)
|
|
||||||
gdk_frame_timings_unref (priv->timings[i]);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@@ -257,7 +263,8 @@ gdk_frame_clock_init (GdkFrameClock *clock)
|
|||||||
clock->priv = priv = gdk_frame_clock_get_instance_private (clock);
|
clock->priv = priv = gdk_frame_clock_get_instance_private (clock);
|
||||||
|
|
||||||
priv->frame_counter = -1;
|
priv->frame_counter = -1;
|
||||||
priv->current = FRAME_HISTORY_MAX_LENGTH - 1;
|
priv->current = 0;
|
||||||
|
timings_init (&priv->timings);
|
||||||
|
|
||||||
if (fps_counter == 0)
|
if (fps_counter == 0)
|
||||||
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
|
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
|
||||||
@@ -416,7 +423,7 @@ gdk_frame_clock_get_frame_counter (GdkFrameClock *frame_clock)
|
|||||||
static inline gint64
|
static inline gint64
|
||||||
_gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
_gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||||
{
|
{
|
||||||
return frame_clock->priv->frame_counter + 1 - frame_clock->priv->n_timings;
|
return frame_clock->priv->frame_counter + 1 - timings_get_size (&frame_clock->priv->timings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -445,31 +452,44 @@ gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock)
|
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock,
|
||||||
|
gint64 monotonic_time)
|
||||||
{
|
{
|
||||||
GdkFrameClockPrivate *priv;
|
GdkFrameClockPrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||||
|
|
||||||
priv = frame_clock->priv;
|
priv = frame_clock->priv;
|
||||||
|
|
||||||
priv->frame_counter++;
|
priv->frame_counter++;
|
||||||
priv->current = (priv->current + 1) % FRAME_HISTORY_MAX_LENGTH;
|
|
||||||
|
|
||||||
/* Try to steal the previous frame timing instead of discarding
|
if (G_UNLIKELY (timings_get_size (&priv->timings) == 0))
|
||||||
* and allocating a new one.
|
timings_append (&priv->timings, _gdk_frame_timings_new (priv->frame_counter));
|
||||||
*/
|
|
||||||
if G_LIKELY (priv->n_timings == FRAME_HISTORY_MAX_LENGTH &&
|
|
||||||
_gdk_frame_timings_steal (priv->timings[priv->current],
|
|
||||||
priv->frame_counter))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (priv->n_timings < FRAME_HISTORY_MAX_LENGTH)
|
|
||||||
priv->n_timings++;
|
|
||||||
else
|
else
|
||||||
gdk_frame_timings_unref (priv->timings[priv->current]);
|
{
|
||||||
|
GdkFrameTimings *timings;
|
||||||
|
|
||||||
priv->timings[priv->current] = _gdk_frame_timings_new (priv->frame_counter);
|
priv->current = (priv->current + 1) % timings_get_size (&priv->timings);
|
||||||
|
|
||||||
|
timings = timings_get (&priv->timings, priv->current);
|
||||||
|
|
||||||
|
if (timings->frame_time + G_USEC_PER_SEC > monotonic_time)
|
||||||
|
{
|
||||||
|
/* Keep the timings, not a second old yet */
|
||||||
|
timings = _gdk_frame_timings_new (priv->frame_counter);
|
||||||
|
timings_splice (&priv->timings, priv->current, 0, FALSE, &timings, 1);
|
||||||
|
}
|
||||||
|
else if (_gdk_frame_timings_steal (timings, priv->frame_counter))
|
||||||
|
{
|
||||||
|
/* Stole the previous frame timing instead of discarding
|
||||||
|
* and allocating a new one, so nothing to do
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timings = _gdk_frame_timings_new (priv->frame_counter);
|
||||||
|
timings_splice (&priv->timings, priv->current, 1, FALSE, &timings, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GdkFrameTimings *
|
static inline GdkFrameTimings *
|
||||||
@@ -477,17 +497,21 @@ _gdk_frame_clock_get_timings (GdkFrameClock *frame_clock,
|
|||||||
gint64 frame_counter)
|
gint64 frame_counter)
|
||||||
{
|
{
|
||||||
GdkFrameClockPrivate *priv = frame_clock->priv;
|
GdkFrameClockPrivate *priv = frame_clock->priv;
|
||||||
int pos;
|
gsize size, pos;
|
||||||
|
|
||||||
if (frame_counter > priv->frame_counter)
|
if (frame_counter > priv->frame_counter)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (frame_counter <= priv->frame_counter - priv->n_timings)
|
size = timings_get_size (&priv->timings);
|
||||||
|
if (G_UNLIKELY (size == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pos = (priv->current - (priv->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
|
if (priv->frame_counter - frame_counter >= size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return priv->timings[pos];
|
pos = (priv->current - (priv->frame_counter - frame_counter) + size) % size;
|
||||||
|
|
||||||
|
return timings_get (&priv->timings, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -779,7 +803,10 @@ gdk_frame_clock_get_fps (GdkFrameClock *frame_clock)
|
|||||||
|
|
||||||
start_counter = _gdk_frame_clock_get_history_start (frame_clock);
|
start_counter = _gdk_frame_clock_get_history_start (frame_clock);
|
||||||
end_counter = _gdk_frame_clock_get_frame_counter (frame_clock);
|
end_counter = _gdk_frame_clock_get_frame_counter (frame_clock);
|
||||||
start = _gdk_frame_clock_get_timings (frame_clock, start_counter);
|
for (start = _gdk_frame_clock_get_timings (frame_clock, start_counter);
|
||||||
|
end_counter > start_counter && start != NULL && !gdk_frame_timings_get_complete (start);
|
||||||
|
start = _gdk_frame_clock_get_timings (frame_clock, start_counter))
|
||||||
|
start_counter++;
|
||||||
for (end = _gdk_frame_clock_get_timings (frame_clock, end_counter);
|
for (end = _gdk_frame_clock_get_timings (frame_clock, end_counter);
|
||||||
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
|
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
|
||||||
end = _gdk_frame_clock_get_timings (frame_clock, end_counter))
|
end = _gdk_frame_clock_get_timings (frame_clock, end_counter))
|
||||||
|
|||||||
@@ -192,6 +192,13 @@ compute_smooth_frame_time (GdkFrameClock *clock,
|
|||||||
* and new_frame_time >= old_frame_time. */
|
* and new_frame_time >= old_frame_time. */
|
||||||
frames_passed = (new_frame_time - smoothed_frame_time_base + frame_interval / 2) / frame_interval;
|
frames_passed = (new_frame_time - smoothed_frame_time_base + frame_interval / 2) / frame_interval;
|
||||||
|
|
||||||
|
if (frames_passed > 1)
|
||||||
|
gdk_profiler_add_markf ((smoothed_frame_time_base - (frame_interval * (frames_passed-1))) * 1000L,
|
||||||
|
frame_interval * (frames_passed-1) * 1000L,
|
||||||
|
"Dropped Frames",
|
||||||
|
"%u frames may have been dropped",
|
||||||
|
frames_passed-1);
|
||||||
|
|
||||||
/* We use an approximately whole number of frames in the future from
|
/* We use an approximately whole number of frames in the future from
|
||||||
* last smoothed frame time. This way we avoid minor jitter in the
|
* last smoothed frame time. This way we avoid minor jitter in the
|
||||||
* frame times making the animation speed uneven, but still animate
|
* frame times making the animation speed uneven, but still animate
|
||||||
@@ -548,7 +555,7 @@ gdk_frame_clock_paint_idle (void *data)
|
|||||||
priv->smoothed_frame_time_period = frame_interval;
|
priv->smoothed_frame_time_period = frame_interval;
|
||||||
priv->smoothed_frame_time_reported = priv->smoothed_frame_time_base;
|
priv->smoothed_frame_time_reported = priv->smoothed_frame_time_base;
|
||||||
|
|
||||||
_gdk_frame_clock_begin_frame (clock);
|
_gdk_frame_clock_begin_frame (clock, priv->frame_time);
|
||||||
/* Note "current" is different now so timings != prev_timings */
|
/* Note "current" is different now so timings != prev_timings */
|
||||||
timings = gdk_frame_clock_get_current_timings (clock);
|
timings = gdk_frame_clock_get_current_timings (clock);
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,8 @@ struct _GdkFrameTimings
|
|||||||
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
||||||
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
||||||
|
|
||||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
|
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock,
|
||||||
|
gint64 monotonic_time);
|
||||||
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
||||||
GdkFrameTimings *timings);
|
GdkFrameTimings *timings);
|
||||||
void _gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *frame_clock,
|
void _gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *frame_clock,
|
||||||
|
|||||||
+3
-2
@@ -658,6 +658,7 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
|||||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
|
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
|
||||||
|
|
||||||
if (priv->egl_context == NULL)
|
if (priv->egl_context == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -666,8 +667,6 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
|||||||
|
|
||||||
egl_surface = gdk_surface_get_egl_surface (surface);
|
egl_surface = gdk_surface_get_egl_surface (surface);
|
||||||
|
|
||||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "EGL swap buffers", NULL);
|
|
||||||
|
|
||||||
if (priv->eglSwapBuffersWithDamage)
|
if (priv->eglSwapBuffersWithDamage)
|
||||||
{
|
{
|
||||||
EGLint stack_rects[4 * 4]; /* 4 rects */
|
EGLint stack_rects[4 * 4]; /* 4 rects */
|
||||||
@@ -698,6 +697,8 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
|||||||
else
|
else
|
||||||
eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
|
eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
gdk_profiler_add_mark (begin_time, GDK_PROFILER_CURRENT_TIME - begin_time, "EGL swap buffers", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -260,6 +260,11 @@ gdk_vulkan_strerror (VkResult result)
|
|||||||
case VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
|
case VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
|
||||||
return "The provided binary shader code is not compatible with this device. (VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)";
|
return "The provided binary shader code is not compatible with this device. (VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)";
|
||||||
#endif
|
#endif
|
||||||
|
#if VK_HEADER_VERSION >= 274
|
||||||
|
case VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:
|
||||||
|
return "The specified Video Std parameters do not adhere to the syntactic or semantic requirements of the used video compression standard or implementation";
|
||||||
|
#endif
|
||||||
|
|
||||||
case VK_RESULT_MAX_ENUM:
|
case VK_RESULT_MAX_ENUM:
|
||||||
default:
|
default:
|
||||||
return "Unknown Vulkan error.";
|
return "Unknown Vulkan error.";
|
||||||
|
|||||||
@@ -214,22 +214,6 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)setFrame:(NSRect)frame display:(BOOL)display
|
|
||||||
{
|
|
||||||
NSRect contentRect = [self contentRectForFrameRect:frame];
|
|
||||||
GdkSurface *surface = GDK_SURFACE (gdk_surface);
|
|
||||||
gboolean maximized = (surface->state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0;
|
|
||||||
|
|
||||||
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, frame))
|
|
||||||
{
|
|
||||||
gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
|
|
||||||
_gdk_surface_update_size (surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
[super setFrame:frame display:display];
|
|
||||||
[[self contentView] setFrame:NSMakeRect (0, 0, contentRect.size.width, contentRect.size.height)];
|
|
||||||
}
|
|
||||||
|
|
||||||
-(id)initWithContentRect:(NSRect)contentRect
|
-(id)initWithContentRect:(NSRect)contentRect
|
||||||
styleMask:(NSWindowStyleMask)styleMask
|
styleMask:(NSWindowStyleMask)styleMask
|
||||||
backing:(NSBackingStoreType)backingType
|
backing:(NSBackingStoreType)backingType
|
||||||
@@ -387,12 +371,17 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
|
|
||||||
-(void)windowDidMove:(NSNotification *)notification
|
-(void)windowDidMove:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
|
if ([self isZoomed])
|
||||||
|
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
|
||||||
|
else
|
||||||
|
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
|
||||||
|
|
||||||
_gdk_macos_surface_configure ([self gdkSurface]);
|
_gdk_macos_surface_configure ([self gdkSurface]);
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)windowDidResize:(NSNotification *)notification
|
-(void)windowDidResize:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
_gdk_macos_surface_configure (gdk_surface);
|
[self windowDidMove: notification];
|
||||||
|
|
||||||
/* If we're using server-side decorations, this notification is coming
|
/* If we're using server-side decorations, this notification is coming
|
||||||
* in from a display-side change. We need to request a layout in
|
* in from a display-side change. We need to request a layout in
|
||||||
@@ -413,7 +402,6 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
|
|
||||||
-(void)beginManualMove
|
-(void)beginManualMove
|
||||||
{
|
{
|
||||||
gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
|
|
||||||
NSPoint initialMoveLocation;
|
NSPoint initialMoveLocation;
|
||||||
GdkPoint point;
|
GdkPoint point;
|
||||||
GdkMonitor *monitor;
|
GdkMonitor *monitor;
|
||||||
@@ -432,13 +420,6 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
|
|
||||||
initialMoveLocation = [NSEvent mouseLocation];
|
initialMoveLocation = [NSEvent mouseLocation];
|
||||||
|
|
||||||
if (maximized)
|
|
||||||
[self setFrame:NSMakeRect (initialMoveLocation.x - (int)lastUnmaximizedFrame.size.width/2,
|
|
||||||
initialMoveLocation.y,
|
|
||||||
lastUnmaximizedFrame.size.width,
|
|
||||||
lastUnmaximizedFrame.size.height)
|
|
||||||
display:YES];
|
|
||||||
|
|
||||||
_gdk_macos_display_from_display_coords ([self gdkDisplay],
|
_gdk_macos_display_from_display_coords ([self gdkDisplay],
|
||||||
initialMoveLocation.x,
|
initialMoveLocation.x,
|
||||||
initialMoveLocation.y,
|
initialMoveLocation.y,
|
||||||
@@ -781,43 +762,11 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implementing this method avoids new windows move around the screen. */
|
||||||
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
|
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
|
||||||
defaultFrame:(NSRect)newFrame
|
defaultFrame:(NSRect)newFrame
|
||||||
{
|
{
|
||||||
NSRect screenFrame = [[self screen] visibleFrame];
|
return newFrame;
|
||||||
GdkMacosSurface *surface = gdk_surface;
|
|
||||||
gboolean maximized = GDK_SURFACE (surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
|
|
||||||
|
|
||||||
if (!maximized)
|
|
||||||
return screenFrame;
|
|
||||||
else
|
|
||||||
return lastUnmaximizedFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(BOOL)windowShouldZoom:(NSWindow *)nsWindow
|
|
||||||
toFrame:(NSRect)newFrame
|
|
||||||
{
|
|
||||||
GdkMacosSurface *surface = gdk_surface;
|
|
||||||
GdkToplevelState state = GDK_SURFACE (surface)->state;
|
|
||||||
|
|
||||||
if (state & GDK_TOPLEVEL_STATE_MAXIMIZED)
|
|
||||||
{
|
|
||||||
lastMaximizedFrame = newFrame;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastUnmaximizedFrame = [nsWindow frame];
|
|
||||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
|
|
||||||
}
|
|
||||||
|
|
||||||
inMaximizeTransition = YES;
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)windowDidEndLiveResize:(NSNotification *)aNotification
|
|
||||||
{
|
|
||||||
inMaximizeTransition = NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
|
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
|
||||||
|
|||||||
@@ -49,10 +49,7 @@
|
|||||||
|
|
||||||
EdgeSnapping snapping;
|
EdgeSnapping snapping;
|
||||||
|
|
||||||
NSRect lastUnmaximizedFrame;
|
|
||||||
NSRect lastMaximizedFrame;
|
|
||||||
NSRect lastUnfullscreenFrame;
|
NSRect lastUnfullscreenFrame;
|
||||||
BOOL inMaximizeTransition;
|
|
||||||
BOOL inFullscreenTransition;
|
BOOL inFullscreenTransition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,57 @@ create_blank_cursor (void)
|
|||||||
return nscursor;
|
return nscursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NSCursor *
|
||||||
|
create_cursor_from_texture (GdkTexture *texture,
|
||||||
|
int x,
|
||||||
|
int y)
|
||||||
|
{
|
||||||
|
guint32 width;
|
||||||
|
guint32 height;
|
||||||
|
guchar *pixels;
|
||||||
|
gsize stride;
|
||||||
|
GdkTextureDownloader *downloader;
|
||||||
|
NSCursor *nscursor;
|
||||||
|
NSBitmapImageRep *nsbitmap;
|
||||||
|
NSImage *nsimage;
|
||||||
|
|
||||||
|
if (texture == NULL)
|
||||||
|
return create_blank_cursor ();
|
||||||
|
|
||||||
|
width = gdk_texture_get_width (texture);
|
||||||
|
height = gdk_texture_get_height (texture);
|
||||||
|
|
||||||
|
nsbitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||||
|
pixelsWide:width
|
||||||
|
pixelsHigh:height
|
||||||
|
bitsPerSample:8
|
||||||
|
samplesPerPixel:4
|
||||||
|
hasAlpha:YES
|
||||||
|
isPlanar:NO
|
||||||
|
colorSpaceName:NSDeviceRGBColorSpace
|
||||||
|
bytesPerRow:0
|
||||||
|
bitsPerPixel:0];
|
||||||
|
pixels = [nsbitmap bitmapData];
|
||||||
|
stride = [nsbitmap bytesPerRow];
|
||||||
|
|
||||||
|
downloader = gdk_texture_downloader_new (texture);
|
||||||
|
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED);
|
||||||
|
gdk_texture_downloader_download_into (downloader,
|
||||||
|
pixels,
|
||||||
|
stride);
|
||||||
|
gdk_texture_downloader_free (downloader);
|
||||||
|
|
||||||
|
nsimage = [[NSImage alloc] init];
|
||||||
|
[nsimage addRepresentation:nsbitmap];
|
||||||
|
[nsimage setSize:NSMakeSize(width, height)];
|
||||||
|
[nsbitmap release];
|
||||||
|
|
||||||
|
nscursor = [[NSCursor alloc] initWithImage:nsimage
|
||||||
|
hotSpot:NSMakePoint(x, y)];
|
||||||
|
[nsimage release];
|
||||||
|
return nscursor;
|
||||||
|
}
|
||||||
|
|
||||||
NSCursor *
|
NSCursor *
|
||||||
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
||||||
{
|
{
|
||||||
@@ -161,7 +212,17 @@ _gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
|||||||
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
|
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
|
||||||
|
|
||||||
if (cursor != NULL)
|
if (cursor != NULL)
|
||||||
name = gdk_cursor_get_name (cursor);
|
{
|
||||||
|
name = gdk_cursor_get_name (cursor);
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
nscursor = create_cursor_from_texture (gdk_cursor_get_texture (cursor),
|
||||||
|
gdk_cursor_get_hotspot_x (cursor),
|
||||||
|
gdk_cursor_get_hotspot_y (cursor));
|
||||||
|
return nscursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
goto load_cursor;
|
goto load_cursor;
|
||||||
|
|||||||
+110
-171
@@ -96,37 +96,26 @@ _gdk_macos_toplevel_surface_unminimize (GdkMacosToplevelSurface *self)
|
|||||||
[window deminiaturize:window];
|
[window deminiaturize:window];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
|
||||||
GdkToplevelLayout *layout)
|
|
||||||
{
|
{
|
||||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
|
||||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
|
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
|
||||||
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
|
|
||||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
|
||||||
GdkMonitor *monitor;
|
|
||||||
GdkToplevelSize size;
|
GdkToplevelSize size;
|
||||||
|
GdkDisplay *display;
|
||||||
|
GdkMonitor *monitor;
|
||||||
int bounds_width, bounds_height;
|
int bounds_width, bounds_height;
|
||||||
int width, height;
|
|
||||||
GdkGeometry geometry;
|
GdkGeometry geometry;
|
||||||
GdkSurfaceHints mask;
|
GdkSurfaceHints mask;
|
||||||
NSWindowStyleMask style_mask;
|
|
||||||
gboolean maximize;
|
|
||||||
gboolean fullscreen;
|
|
||||||
|
|
||||||
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
||||||
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
|
|
||||||
|
|
||||||
if (layout != self->layout)
|
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
|
||||||
{
|
return FALSE;
|
||||||
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
|
|
||||||
self->layout = gdk_toplevel_layout_copy (layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
_gdk_macos_toplevel_surface_attach_to_parent (self);
|
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
|
||||||
|
|
||||||
style_mask = [nswindow styleMask];
|
|
||||||
|
|
||||||
|
display = gdk_surface_get_display (surface);
|
||||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||||
|
|
||||||
if (monitor)
|
if (monitor)
|
||||||
@@ -144,58 +133,127 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
|
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
|
||||||
gdk_toplevel_notify_compute_size (toplevel, &size);
|
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
|
||||||
|
|
||||||
g_warn_if_fail (size.width > 0);
|
g_warn_if_fail (size.width > 0);
|
||||||
g_warn_if_fail (size.height > 0);
|
g_warn_if_fail (size.height > 0);
|
||||||
width = size.width;
|
|
||||||
height = size.height;
|
|
||||||
|
|
||||||
if (gdk_toplevel_layout_get_resizable (layout))
|
if (self->layout != NULL &&
|
||||||
|
gdk_toplevel_layout_get_resizable (self->layout))
|
||||||
{
|
{
|
||||||
geometry.min_width = size.min_width;
|
geometry.min_width = size.min_width;
|
||||||
geometry.min_height = size.min_height;
|
geometry.min_height = size.min_height;
|
||||||
mask = GDK_HINT_MIN_SIZE;
|
mask = GDK_HINT_MIN_SIZE;
|
||||||
|
|
||||||
/* Only set 'Resizable' mask to get native resize zones if the window is
|
|
||||||
* titled, otherwise we do this internally for CSD and do not need
|
|
||||||
* NSWindow to do it for us. Additionally, it can mess things up when
|
|
||||||
* doing a window resize since it can cause mouseDown to get passed
|
|
||||||
* through to the next window.
|
|
||||||
*/
|
|
||||||
if ((style_mask & NSWindowStyleMaskTitled) != 0)
|
|
||||||
style_mask |= NSWindowStyleMaskResizable;
|
|
||||||
else
|
|
||||||
style_mask &= ~NSWindowStyleMaskResizable;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
geometry.max_width = geometry.min_width = width;
|
geometry.max_width = geometry.min_width = size.width;
|
||||||
geometry.max_height = geometry.min_height = height;
|
geometry.max_height = geometry.min_height = size.height;
|
||||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
||||||
|
|
||||||
style_mask &= ~NSWindowStyleMaskResizable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style_mask != [nswindow styleMask])
|
|
||||||
[nswindow setStyleMask:style_mask];
|
|
||||||
|
|
||||||
if (size.shadow.is_valid)
|
if (size.shadow.is_valid)
|
||||||
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (surface),
|
_gdk_macos_surface_set_shadow (macos_surface,
|
||||||
size.shadow.top,
|
size.shadow.top,
|
||||||
size.shadow.right,
|
size.shadow.right,
|
||||||
size.shadow.bottom,
|
size.shadow.bottom,
|
||||||
size.shadow.left);
|
size.shadow.left);
|
||||||
|
|
||||||
_gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
|
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
|
||||||
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
|
|
||||||
|
|
||||||
GDK_DEBUG (MISC, "Resizing \"%s\" to %dx%d",
|
if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
|
||||||
GDK_MACOS_SURFACE (self)->title ?
|
GDK_TOPLEVEL_STATE_MAXIMIZED |
|
||||||
GDK_MACOS_SURFACE (self)->title :
|
GDK_TOPLEVEL_STATE_TILED |
|
||||||
"untitled",
|
GDK_TOPLEVEL_STATE_TOP_TILED |
|
||||||
width, height);
|
GDK_TOPLEVEL_STATE_RIGHT_TILED |
|
||||||
|
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
|
||||||
|
GDK_TOPLEVEL_STATE_LEFT_TILED |
|
||||||
|
GDK_TOPLEVEL_STATE_MINIMIZED) ||
|
||||||
|
[macos_surface->window inLiveResize])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
_gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
|
/* If we delayed a user resize until the beginning of the frame,
|
||||||
|
* apply it now so we can start processing updates for it.
|
||||||
|
*/
|
||||||
|
if (macos_surface->next_layout.width > 0 &&
|
||||||
|
macos_surface->next_layout.height > 0)
|
||||||
|
{
|
||||||
|
int root_x = macos_surface->next_layout.root_x;
|
||||||
|
int root_y = macos_surface->next_layout.root_y;
|
||||||
|
int width = macos_surface->next_layout.width;
|
||||||
|
int height = macos_surface->next_layout.height;
|
||||||
|
|
||||||
|
gdk_surface_constrain_size (&geometry, mask,
|
||||||
|
width, height,
|
||||||
|
&width, &height);
|
||||||
|
|
||||||
|
macos_surface->next_layout.width = 0;
|
||||||
|
macos_surface->next_layout.height = 0;
|
||||||
|
|
||||||
|
_gdk_macos_surface_move_resize (macos_surface,
|
||||||
|
root_x, root_y,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_surface_constrain_size (&geometry, mask,
|
||||||
|
size.width, size.height,
|
||||||
|
&size.width, &size.height);
|
||||||
|
|
||||||
|
if ((size.width != self->last_computed_width ||
|
||||||
|
size.height != self->last_computed_height) &&
|
||||||
|
(size.width != surface->width ||
|
||||||
|
size.height != surface->height))
|
||||||
|
{
|
||||||
|
self->last_computed_width = size.width;
|
||||||
|
self->last_computed_height = size.height;
|
||||||
|
|
||||||
|
_gdk_macos_surface_resize (macos_surface, size.width, size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||||
|
GdkToplevelLayout *layout)
|
||||||
|
{
|
||||||
|
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||||
|
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
|
||||||
|
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
|
||||||
|
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||||
|
NSWindowStyleMask style_mask;
|
||||||
|
gboolean maximize;
|
||||||
|
gboolean fullscreen;
|
||||||
|
|
||||||
|
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
||||||
|
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
|
||||||
|
|
||||||
|
if (layout != self->layout)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
|
||||||
|
self->layout = gdk_toplevel_layout_copy (layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
_gdk_macos_toplevel_surface_attach_to_parent (self);
|
||||||
|
_gdk_macos_toplevel_surface_compute_size (surface);
|
||||||
|
|
||||||
|
/* Only set 'Resizable' mask to get native resize zones if the window is
|
||||||
|
* titled, otherwise we do this internally for CSD and do not need
|
||||||
|
* NSWindow to do it for us. Additionally, it can mess things up when
|
||||||
|
* doing a window resize since it can cause mouseDown to get passed
|
||||||
|
* through to the next window.
|
||||||
|
*/
|
||||||
|
style_mask = [nswindow styleMask];
|
||||||
|
if (gdk_toplevel_layout_get_resizable (layout) &&
|
||||||
|
(style_mask & NSWindowStyleMaskTitled) != 0)
|
||||||
|
style_mask |= NSWindowStyleMaskResizable;
|
||||||
|
else
|
||||||
|
style_mask &= ~NSWindowStyleMaskResizable;
|
||||||
|
|
||||||
|
if (style_mask != [nswindow styleMask])
|
||||||
|
[nswindow setStyleMask:style_mask];
|
||||||
|
|
||||||
/* Maximized state */
|
/* Maximized state */
|
||||||
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
|
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
|
||||||
@@ -378,125 +436,6 @@ _gdk_macos_toplevel_surface_hide (GdkSurface *surface)
|
|||||||
GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->hide (surface);
|
GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->hide (surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
|
|
||||||
{
|
|
||||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
|
|
||||||
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
|
|
||||||
GdkToplevelSize size;
|
|
||||||
GdkDisplay *display;
|
|
||||||
GdkMonitor *monitor;
|
|
||||||
int bounds_width, bounds_height;
|
|
||||||
GdkGeometry geometry;
|
|
||||||
GdkSurfaceHints mask;
|
|
||||||
|
|
||||||
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
|
||||||
|
|
||||||
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
|
|
||||||
|
|
||||||
display = gdk_surface_get_display (surface);
|
|
||||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
|
||||||
|
|
||||||
if (monitor)
|
|
||||||
{
|
|
||||||
GdkRectangle workarea;
|
|
||||||
|
|
||||||
gdk_macos_monitor_get_workarea (monitor, &workarea);
|
|
||||||
bounds_width = workarea.width;
|
|
||||||
bounds_height = workarea.height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bounds_width = G_MAXINT;
|
|
||||||
bounds_height = G_MAXINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
|
|
||||||
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
|
|
||||||
|
|
||||||
g_warn_if_fail (size.width > 0);
|
|
||||||
g_warn_if_fail (size.height > 0);
|
|
||||||
|
|
||||||
if (self->layout != NULL &&
|
|
||||||
gdk_toplevel_layout_get_resizable (self->layout))
|
|
||||||
{
|
|
||||||
geometry.min_width = size.min_width;
|
|
||||||
geometry.min_height = size.min_height;
|
|
||||||
mask = GDK_HINT_MIN_SIZE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
geometry.max_width = geometry.min_width = size.width;
|
|
||||||
geometry.max_height = geometry.min_height = size.height;
|
|
||||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size.shadow.is_valid)
|
|
||||||
_gdk_macos_surface_set_shadow (macos_surface,
|
|
||||||
size.shadow.top,
|
|
||||||
size.shadow.right,
|
|
||||||
size.shadow.bottom,
|
|
||||||
size.shadow.left);
|
|
||||||
|
|
||||||
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
|
|
||||||
|
|
||||||
if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
|
|
||||||
GDK_TOPLEVEL_STATE_MAXIMIZED |
|
|
||||||
GDK_TOPLEVEL_STATE_TILED |
|
|
||||||
GDK_TOPLEVEL_STATE_TOP_TILED |
|
|
||||||
GDK_TOPLEVEL_STATE_RIGHT_TILED |
|
|
||||||
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
|
|
||||||
GDK_TOPLEVEL_STATE_LEFT_TILED |
|
|
||||||
GDK_TOPLEVEL_STATE_MINIMIZED) ||
|
|
||||||
[macos_surface->window inLiveResize])
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* If we delayed a user resize until the beginning of the frame,
|
|
||||||
* apply it now so we can start processing updates for it.
|
|
||||||
*/
|
|
||||||
if (macos_surface->next_layout.width > 0 &&
|
|
||||||
macos_surface->next_layout.height > 0)
|
|
||||||
{
|
|
||||||
int root_x = macos_surface->next_layout.root_x;
|
|
||||||
int root_y = macos_surface->next_layout.root_y;
|
|
||||||
int width = macos_surface->next_layout.width;
|
|
||||||
int height = macos_surface->next_layout.height;
|
|
||||||
|
|
||||||
gdk_surface_constrain_size (&geometry, mask,
|
|
||||||
width, height,
|
|
||||||
&width, &height);
|
|
||||||
|
|
||||||
macos_surface->next_layout.width = 0;
|
|
||||||
macos_surface->next_layout.height = 0;
|
|
||||||
|
|
||||||
_gdk_macos_surface_move_resize (macos_surface,
|
|
||||||
root_x, root_y,
|
|
||||||
width, height);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gdk_surface_constrain_size (&geometry, mask,
|
|
||||||
size.width, size.height,
|
|
||||||
&size.width, &size.height);
|
|
||||||
|
|
||||||
if ((size.width != self->last_computed_width ||
|
|
||||||
size.height != self->last_computed_height) &&
|
|
||||||
(size.width != surface->width ||
|
|
||||||
size.height != surface->height))
|
|
||||||
{
|
|
||||||
self->last_computed_width = size.width;
|
|
||||||
self->last_computed_height = size.height;
|
|
||||||
|
|
||||||
_gdk_macos_surface_resize (macos_surface, size.width, size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gdk_macos_toplevel_surface_request_layout (GdkSurface *surface)
|
_gdk_macos_toplevel_surface_request_layout (GdkSurface *surface)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -201,17 +201,23 @@ get_egl_window_size (GdkSurface *surface,
|
|||||||
|
|
||||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_NO_FRACTIONAL))
|
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_NO_FRACTIONAL))
|
||||||
{
|
{
|
||||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Using integer scale %d for EGL window", gdk_fractional_scale_to_int (&impl->scale));
|
|
||||||
|
|
||||||
*width = surface->width * gdk_fractional_scale_to_int (&impl->scale);
|
*width = surface->width * gdk_fractional_scale_to_int (&impl->scale);
|
||||||
*height = surface->height * gdk_fractional_scale_to_int (&impl->scale);
|
*height = surface->height * gdk_fractional_scale_to_int (&impl->scale);
|
||||||
|
|
||||||
|
GDK_DISPLAY_DEBUG (display, OPENGL, "Using integer scale %d for EGL window (%d %d => %d %d)",
|
||||||
|
gdk_fractional_scale_to_int (&impl->scale),
|
||||||
|
surface->width, surface->height,
|
||||||
|
*width, *height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Using fractional scale %g for EGL window", gdk_fractional_scale_to_double (&impl->scale));
|
|
||||||
|
|
||||||
*width = gdk_fractional_scale_scale (&impl->scale, surface->width),
|
*width = gdk_fractional_scale_scale (&impl->scale, surface->width),
|
||||||
*height = gdk_fractional_scale_scale (&impl->scale, surface->height);
|
*height = gdk_fractional_scale_scale (&impl->scale, surface->height);
|
||||||
|
|
||||||
|
GDK_DISPLAY_DEBUG (display, OPENGL, "Using fractional scale %g for EGL window (%d %d => %d %d)",
|
||||||
|
gdk_fractional_scale_to_double (&impl->scale),
|
||||||
|
surface->width, surface->height,
|
||||||
|
*width, *height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -458,6 +458,49 @@ gdk_wayland_toplevel_compute_size (GdkSurface *surface)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
has_per_edge_tiling_info (GdkToplevelState state)
|
||||||
|
{
|
||||||
|
return state & (GDK_TOPLEVEL_STATE_TOP_TILED |
|
||||||
|
GDK_TOPLEVEL_STATE_RIGHT_TILED |
|
||||||
|
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
|
||||||
|
GDK_TOPLEVEL_STATE_LEFT_TILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkToplevelState
|
||||||
|
infer_edge_constraints (GdkToplevelState state)
|
||||||
|
{
|
||||||
|
if (state & (GDK_TOPLEVEL_STATE_MAXIMIZED | GDK_TOPLEVEL_STATE_FULLSCREEN))
|
||||||
|
return state;
|
||||||
|
|
||||||
|
if (!(state & GDK_TOPLEVEL_STATE_TILED) || !has_per_edge_tiling_info (state))
|
||||||
|
return state |
|
||||||
|
GDK_TOPLEVEL_STATE_TOP_RESIZABLE |
|
||||||
|
GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE |
|
||||||
|
GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE |
|
||||||
|
GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
|
||||||
|
|
||||||
|
if (!(state & GDK_TOPLEVEL_STATE_TOP_TILED))
|
||||||
|
state |= GDK_TOPLEVEL_STATE_TOP_RESIZABLE;
|
||||||
|
if (!(state & GDK_TOPLEVEL_STATE_RIGHT_TILED))
|
||||||
|
state |= GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE;
|
||||||
|
if (!(state & GDK_TOPLEVEL_STATE_BOTTOM_TILED))
|
||||||
|
state |= GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE;
|
||||||
|
if (!(state & GDK_TOPLEVEL_STATE_LEFT_TILED))
|
||||||
|
state |= GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
supports_native_edge_constraints (GdkWaylandToplevel*toplevel)
|
||||||
|
{
|
||||||
|
struct gtk_surface1 *gtk_surface = toplevel->display_server.gtk_surface;
|
||||||
|
if (!gtk_surface)
|
||||||
|
return FALSE;
|
||||||
|
return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
||||||
{
|
{
|
||||||
@@ -475,6 +518,9 @@ gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
|||||||
new_state = wayland_toplevel->pending.state;
|
new_state = wayland_toplevel->pending.state;
|
||||||
wayland_toplevel->pending.state = 0;
|
wayland_toplevel->pending.state = 0;
|
||||||
|
|
||||||
|
if (!supports_native_edge_constraints (wayland_toplevel))
|
||||||
|
new_state = infer_edge_constraints (new_state);
|
||||||
|
|
||||||
is_resizing = wayland_toplevel->pending.is_resizing;
|
is_resizing = wayland_toplevel->pending.is_resizing;
|
||||||
wayland_toplevel->pending.is_resizing = FALSE;
|
wayland_toplevel->pending.is_resizing = FALSE;
|
||||||
|
|
||||||
@@ -1990,13 +2036,7 @@ gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
|||||||
static gboolean
|
static gboolean
|
||||||
gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||||
{
|
{
|
||||||
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
|
return TRUE;
|
||||||
struct gtk_surface1 *gtk_surface = wayland_toplevel->display_server.gtk_surface;
|
|
||||||
|
|
||||||
if (!gtk_surface)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2667,7 +2707,7 @@ gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
|
|||||||
g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
|
g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
|
||||||
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
|
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
|
||||||
|
|
||||||
if (!display_wayland->xdg_importer)
|
if (!display_wayland->xdg_importer && !display_wayland->xdg_importer_v2)
|
||||||
{
|
{
|
||||||
g_warning ("Server is missing xdg_foreign support");
|
g_warning ("Server is missing xdg_foreign support");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -3015,6 +3015,8 @@ gdk_x11_display_init_gl_backend (GdkX11Display *self,
|
|||||||
|
|
||||||
self->egl_version = epoxy_egl_version (egl_display);
|
self->egl_version = epoxy_egl_version (egl_display);
|
||||||
|
|
||||||
|
XFree (visinfo);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-2
@@ -1,5 +1,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gdk/gdkprofilerprivate.h>
|
||||||
|
|
||||||
#include "gskglbufferprivate.h"
|
#include "gskglbufferprivate.h"
|
||||||
|
|
||||||
struct _GskGLBuffer
|
struct _GskGLBuffer
|
||||||
@@ -14,6 +16,9 @@ struct _GskGLBuffer
|
|||||||
|
|
||||||
G_DEFINE_TYPE (GskGLBuffer, gsk_gl_buffer, GSK_TYPE_GPU_BUFFER)
|
G_DEFINE_TYPE (GskGLBuffer, gsk_gl_buffer, GSK_TYPE_GPU_BUFFER)
|
||||||
|
|
||||||
|
static guint profiler_buffer_uploads_id;
|
||||||
|
static gint64 profiler_buffer_uploads;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_buffer_finalize (GObject *object)
|
gsk_gl_buffer_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -34,13 +39,19 @@ gsk_gl_buffer_map (GskGpuBuffer *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_buffer_unmap (GskGpuBuffer *buffer)
|
gsk_gl_buffer_unmap (GskGpuBuffer *buffer,
|
||||||
|
gsize used)
|
||||||
{
|
{
|
||||||
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
|
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
|
||||||
|
|
||||||
|
if (used == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
gsk_gl_buffer_bind (self);
|
gsk_gl_buffer_bind (self);
|
||||||
|
|
||||||
glBufferSubData (self->target, 0, gsk_gpu_buffer_get_size (buffer), self->data);
|
profiler_buffer_uploads += used;
|
||||||
|
glBufferSubData (self->target, 0, used, self->data);
|
||||||
|
gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -53,6 +64,8 @@ gsk_gl_buffer_class_init (GskGLBufferClass *klass)
|
|||||||
buffer_class->unmap = gsk_gl_buffer_unmap;
|
buffer_class->unmap = gsk_gl_buffer_unmap;
|
||||||
|
|
||||||
gobject_class->finalize = gsk_gl_buffer_finalize;
|
gobject_class->finalize = gsk_gl_buffer_finalize;
|
||||||
|
|
||||||
|
profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "gdk/gdkdisplayprivate.h"
|
#include "gdk/gdkdisplayprivate.h"
|
||||||
#include "gdk/gdkglcontextprivate.h"
|
#include "gdk/gdkglcontextprivate.h"
|
||||||
|
#include "gdk/gdkprofilerprivate.h"
|
||||||
|
|
||||||
#include <glib/gi18n-lib.h>
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
@@ -473,6 +474,7 @@ gsk_gl_device_load_program (GskGLDevice *self,
|
|||||||
guint n_external_textures,
|
guint n_external_textures,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
|
||||||
GLuint vertex_shader_id, fragment_shader_id, program_id;
|
GLuint vertex_shader_id, fragment_shader_id, program_id;
|
||||||
GLint link_status;
|
GLint link_status;
|
||||||
|
|
||||||
@@ -527,6 +529,11 @@ gsk_gl_device_load_program (GskGLDevice *self,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdk_profiler_end_markf (begin_time,
|
||||||
|
"Compile Program",
|
||||||
|
"name=%s id=%u frag=%u vert=%u",
|
||||||
|
op_class->shader_name, program_id, fragment_shader_id, vertex_shader_id);
|
||||||
|
|
||||||
return program_id;
|
return program_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,9 @@ gsk_gpu_buffer_map (GskGpuBuffer *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsk_gpu_buffer_unmap (GskGpuBuffer *self)
|
gsk_gpu_buffer_unmap (GskGpuBuffer *self,
|
||||||
|
gsize size)
|
||||||
{
|
{
|
||||||
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self);
|
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ struct _GskGpuBufferClass
|
|||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
guchar * (* map) (GskGpuBuffer *self);
|
guchar * (* map) (GskGpuBuffer *self);
|
||||||
void (* unmap) (GskGpuBuffer *self);
|
void (* unmap) (GskGpuBuffer *self,
|
||||||
|
gsize used);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gsk_gpu_buffer_get_type (void) G_GNUC_CONST;
|
GType gsk_gpu_buffer_get_type (void) G_GNUC_CONST;
|
||||||
@@ -34,7 +35,8 @@ void gsk_gpu_buffer_setup (GskGpuB
|
|||||||
gsize gsk_gpu_buffer_get_size (GskGpuBuffer *self);
|
gsize gsk_gpu_buffer_get_size (GskGpuBuffer *self);
|
||||||
|
|
||||||
guchar * gsk_gpu_buffer_map (GskGpuBuffer *self);
|
guchar * gsk_gpu_buffer_map (GskGpuBuffer *self);
|
||||||
void gsk_gpu_buffer_unmap (GskGpuBuffer *self);
|
void gsk_gpu_buffer_unmap (GskGpuBuffer *self,
|
||||||
|
gsize used);
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuBuffer, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuBuffer, g_object_unref)
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ gsk_gpu_clip_init_rect (GskGpuClip *clip,
|
|||||||
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
|
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gpu_clip_init_rounded_rect (GskGpuClip *self,
|
||||||
|
const GskRoundedRect *rect)
|
||||||
|
{
|
||||||
|
self->type = GSK_GPU_CLIP_ROUNDED;
|
||||||
|
gsk_rounded_rect_init_copy (&self->rect, rect);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsk_gpu_clip_init_copy (GskGpuClip *self,
|
gsk_gpu_clip_init_copy (GskGpuClip *self,
|
||||||
const GskGpuClip *src)
|
const GskGpuClip *src)
|
||||||
@@ -129,6 +137,13 @@ gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GSK_GPU_CLIP_NONE:
|
case GSK_GPU_CLIP_NONE:
|
||||||
|
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
|
||||||
|
if (gsk_gpu_clip_init_after_intersection (dest, res))
|
||||||
|
break;
|
||||||
|
/* XXX: This may grow the bounds quite substantially */
|
||||||
|
gsk_gpu_clip_init_rounded_rect (dest, rounded);
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_GPU_CLIP_CONTAINED:
|
case GSK_GPU_CLIP_CONTAINED:
|
||||||
case GSK_GPU_CLIP_RECT:
|
case GSK_GPU_CLIP_RECT:
|
||||||
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
|
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ typedef enum {
|
|||||||
GSK_GPU_CLIP_ALL_CLIPPED,
|
GSK_GPU_CLIP_ALL_CLIPPED,
|
||||||
/* No clipping is necessary, but the clip rect is set
|
/* No clipping is necessary, but the clip rect is set
|
||||||
* to the actual bounds of the underlying framebuffer
|
* to the actual bounds of the underlying framebuffer
|
||||||
|
* or handled via the scissor.
|
||||||
*/
|
*/
|
||||||
GSK_GPU_CLIP_NONE,
|
GSK_GPU_CLIP_NONE,
|
||||||
/* The clip exists outside the rect, so clipping must
|
/* The clip exists outside the rect, so clipping must
|
||||||
|
|||||||
+45
-127
@@ -33,37 +33,6 @@ typedef struct _GskGpuCachedGlyph GskGpuCachedGlyph;
|
|||||||
typedef struct _GskGpuCachedTexture GskGpuCachedTexture;
|
typedef struct _GskGpuCachedTexture GskGpuCachedTexture;
|
||||||
typedef struct _GskGpuDevicePrivate GskGpuDevicePrivate;
|
typedef struct _GskGpuDevicePrivate GskGpuDevicePrivate;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PangoFont *font;
|
|
||||||
float scale;
|
|
||||||
} FontCacheKey;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PangoGlyph glyph;
|
|
||||||
GskGpuGlyphLookupFlags flags;
|
|
||||||
} GlyphCacheKey;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FontCacheKey key;
|
|
||||||
|
|
||||||
GHashTable *cache;
|
|
||||||
} FontGlyphCache;
|
|
||||||
|
|
||||||
static void
|
|
||||||
font_glyph_cache_free (gpointer data)
|
|
||||||
{
|
|
||||||
FontGlyphCache *cache = data;
|
|
||||||
|
|
||||||
g_object_unref (cache->key.font);
|
|
||||||
g_hash_table_unref (cache->cache);
|
|
||||||
g_free (cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FontGlyphCache no_font_cache = {
|
|
||||||
.key = { .font = NULL, .scale = -1 },
|
|
||||||
.cache = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GskGpuDevicePrivate
|
struct _GskGpuDevicePrivate
|
||||||
{
|
{
|
||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
@@ -76,7 +45,6 @@ struct _GskGpuDevicePrivate
|
|||||||
|
|
||||||
GHashTable *texture_cache;
|
GHashTable *texture_cache;
|
||||||
GHashTable *glyph_cache;
|
GHashTable *glyph_cache;
|
||||||
FontGlyphCache *last_font_cache;
|
|
||||||
|
|
||||||
GskGpuCachedAtlas *current_atlas;
|
GskGpuCachedAtlas *current_atlas;
|
||||||
|
|
||||||
@@ -101,15 +69,14 @@ struct _GskGpuCachedClass
|
|||||||
struct _GskGpuCached
|
struct _GskGpuCached
|
||||||
{
|
{
|
||||||
const GskGpuCachedClass *class;
|
const GskGpuCachedClass *class;
|
||||||
|
|
||||||
GskGpuCachedAtlas *atlas;
|
GskGpuCachedAtlas *atlas;
|
||||||
GskGpuCached *next;
|
GskGpuCached *next;
|
||||||
GskGpuCached *prev;
|
GskGpuCached *prev;
|
||||||
|
|
||||||
gint64 timestamp;
|
gint64 timestamp;
|
||||||
|
gboolean stale;
|
||||||
unsigned int stale : 1;
|
guint pixels; /* For glyphs and textures, pixels. For atlases, dead pixels */
|
||||||
unsigned int pixels : 31; /* For glyphs and textures, pixels. For atlases, dead pixels */
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -394,8 +361,10 @@ struct _GskGpuCachedGlyph
|
|||||||
{
|
{
|
||||||
GskGpuCached parent;
|
GskGpuCached parent;
|
||||||
|
|
||||||
FontGlyphCache *font_cache;
|
PangoFont *font;
|
||||||
GlyphCacheKey glyph_key;
|
PangoGlyph glyph;
|
||||||
|
GskGpuGlyphLookupFlags flags;
|
||||||
|
float scale;
|
||||||
|
|
||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
graphene_rect_t bounds;
|
graphene_rect_t bounds;
|
||||||
@@ -408,17 +377,10 @@ gsk_gpu_cached_glyph_free (GskGpuDevice *device,
|
|||||||
{
|
{
|
||||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
|
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
|
||||||
GskGpuCachedGlyph *self = (GskGpuCachedGlyph *) cached;
|
GskGpuCachedGlyph *self = (GskGpuCachedGlyph *) cached;
|
||||||
FontGlyphCache *font_cache;
|
|
||||||
|
|
||||||
font_cache = self->font_cache;
|
g_hash_table_remove (priv->glyph_cache, self);
|
||||||
g_hash_table_remove (font_cache->cache, self);
|
|
||||||
if (g_hash_table_size (font_cache->cache) == 0)
|
|
||||||
{
|
|
||||||
if (priv->last_font_cache == font_cache)
|
|
||||||
priv->last_font_cache = &no_font_cache;
|
|
||||||
g_hash_table_remove (priv->glyph_cache, font_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
g_object_unref (self->font);
|
||||||
g_object_unref (self->image);
|
g_object_unref (self->image);
|
||||||
|
|
||||||
g_free (self);
|
g_free (self);
|
||||||
@@ -441,35 +403,15 @@ gsk_gpu_cached_glyph_should_collect (GskGpuDevice *device,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
|
||||||
gsk_gpu_cached_font_hash (gconstpointer data)
|
|
||||||
{
|
|
||||||
const FontGlyphCache *cache = data;
|
|
||||||
const FontCacheKey *key = &cache->key;
|
|
||||||
|
|
||||||
return GPOINTER_TO_UINT (key->font) ^ ((guint) key->scale * PANGO_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gsk_gpu_cached_font_equal (gconstpointer v1,
|
|
||||||
gconstpointer v2)
|
|
||||||
{
|
|
||||||
const FontGlyphCache *c1 = v1;
|
|
||||||
const FontCacheKey *key1 = &c1->key;
|
|
||||||
const FontGlyphCache *c2 = v2;
|
|
||||||
const FontCacheKey *key2 = &c2->key;
|
|
||||||
|
|
||||||
return key1->font == key2->font &&
|
|
||||||
key1->scale == key2->scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
gsk_gpu_cached_glyph_hash (gconstpointer data)
|
gsk_gpu_cached_glyph_hash (gconstpointer data)
|
||||||
{
|
{
|
||||||
const GskGpuCachedGlyph *glyph = data;
|
const GskGpuCachedGlyph *glyph = data;
|
||||||
const GlyphCacheKey *key = &glyph->glyph_key;
|
|
||||||
|
|
||||||
return key->glyph ^ (key->flags << 24);
|
return GPOINTER_TO_UINT (glyph->font) ^
|
||||||
|
glyph->glyph ^
|
||||||
|
(glyph->flags << 24) ^
|
||||||
|
((guint) glyph->scale * PANGO_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -478,11 +420,11 @@ gsk_gpu_cached_glyph_equal (gconstpointer v1,
|
|||||||
{
|
{
|
||||||
const GskGpuCachedGlyph *glyph1 = v1;
|
const GskGpuCachedGlyph *glyph1 = v1;
|
||||||
const GskGpuCachedGlyph *glyph2 = v2;
|
const GskGpuCachedGlyph *glyph2 = v2;
|
||||||
const GlyphCacheKey *key1 = &glyph1->glyph_key;
|
|
||||||
const GlyphCacheKey *key2 = &glyph2->glyph_key;
|
|
||||||
|
|
||||||
return key1->glyph == key2->glyph &&
|
return glyph1->font == glyph2->font
|
||||||
key1->flags == key2->flags;
|
&& glyph1->glyph == glyph2->glyph
|
||||||
|
&& glyph1->flags == glyph2->flags
|
||||||
|
&& glyph1->scale == glyph2->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
|
static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
|
||||||
@@ -681,13 +623,10 @@ gsk_gpu_device_init (GskGpuDevice *self)
|
|||||||
{
|
{
|
||||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||||
|
|
||||||
priv->glyph_cache = g_hash_table_new_full (gsk_gpu_cached_font_hash,
|
priv->glyph_cache = g_hash_table_new (gsk_gpu_cached_glyph_hash,
|
||||||
gsk_gpu_cached_font_equal,
|
gsk_gpu_cached_glyph_equal);
|
||||||
NULL,
|
|
||||||
font_glyph_cache_free);
|
|
||||||
priv->texture_cache = g_hash_table_new (g_direct_hash,
|
priv->texture_cache = g_hash_table_new (g_direct_hash,
|
||||||
g_direct_equal);
|
g_direct_equal);
|
||||||
priv->last_font_cache = &no_font_cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -951,18 +890,16 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
|||||||
GskGpuGlyphLookupFlags flags,
|
GskGpuGlyphLookupFlags flags,
|
||||||
float scale,
|
float scale,
|
||||||
graphene_rect_t *out_bounds,
|
graphene_rect_t *out_bounds,
|
||||||
graphene_point_t *out_origin,
|
graphene_point_t *out_origin)
|
||||||
PangoFont **out_scaled_font)
|
|
||||||
{
|
{
|
||||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||||
FontGlyphCache font_lookup = {
|
GskGpuCachedGlyph lookup = {
|
||||||
.key = { .font = font, .scale = scale }
|
.font = font,
|
||||||
|
.glyph = glyph,
|
||||||
|
.flags = flags,
|
||||||
|
.scale = scale
|
||||||
};
|
};
|
||||||
GskGpuCachedGlyph glyph_lookup = {
|
GskGpuCachedGlyph *cache;
|
||||||
.glyph_key = { .glyph = glyph, .flags = flags }
|
|
||||||
};
|
|
||||||
FontGlyphCache *font_cache = NULL;
|
|
||||||
GskGpuCachedGlyph *cache = NULL;
|
|
||||||
PangoRectangle ink_rect;
|
PangoRectangle ink_rect;
|
||||||
graphene_rect_t rect;
|
graphene_rect_t rect;
|
||||||
graphene_point_t origin;
|
graphene_point_t origin;
|
||||||
@@ -971,43 +908,22 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
|||||||
float subpixel_x, subpixel_y;
|
float subpixel_x, subpixel_y;
|
||||||
PangoFont *scaled_font;
|
PangoFont *scaled_font;
|
||||||
|
|
||||||
if (priv->last_font_cache->key.font == font &&
|
cache = g_hash_table_lookup (priv->glyph_cache, &lookup);
|
||||||
priv->last_font_cache->key.scale == scale)
|
if (cache)
|
||||||
font_cache = priv->last_font_cache;
|
|
||||||
else
|
|
||||||
font_cache = g_hash_table_lookup (priv->glyph_cache, &font_lookup);
|
|
||||||
|
|
||||||
if (font_cache)
|
|
||||||
{
|
{
|
||||||
cache = g_hash_table_lookup (font_cache->cache, &glyph_lookup);
|
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
||||||
if (cache)
|
|
||||||
{
|
|
||||||
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
|
||||||
|
|
||||||
*out_bounds = cache->bounds;
|
*out_bounds = cache->bounds;
|
||||||
*out_origin = cache->origin;
|
*out_origin = cache->origin;
|
||||||
|
return cache->image;
|
||||||
priv->last_font_cache = font_cache;
|
|
||||||
|
|
||||||
return cache->image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
font_cache = g_new (FontGlyphCache, 1);
|
|
||||||
font_cache->key.font = g_object_ref (font);
|
|
||||||
font_cache->key.scale = scale;
|
|
||||||
font_cache->cache = g_hash_table_new (gsk_gpu_cached_glyph_hash,
|
|
||||||
gsk_gpu_cached_glyph_equal);
|
|
||||||
g_hash_table_insert (priv->glyph_cache, font_cache, font_cache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->last_font_cache = font_cache;
|
/* Note: we want to scale the font to the required size *and* ensure that
|
||||||
|
* metrics hinting is off. The latter is necessary since pango lets metrics
|
||||||
if (*out_scaled_font)
|
* hinting influence the rendering of hexboxes, and we get bad outcomes if
|
||||||
scaled_font = *out_scaled_font;
|
* that happens.
|
||||||
else
|
*/
|
||||||
scaled_font = gsk_get_scaled_font (font, scale);
|
scaled_font = gsk_reload_font (font, scale, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_STYLE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT);
|
||||||
|
|
||||||
subpixel_x = (flags & 3) / 4.f;
|
subpixel_x = (flags & 3) / 4.f;
|
||||||
subpixel_y = ((flags >> 2) & 3) / 4.f;
|
subpixel_y = ((flags >> 2) & 3) / 4.f;
|
||||||
@@ -1037,9 +953,10 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
|||||||
cache = gsk_gpu_cached_new (self, &GSK_GPU_CACHED_GLYPH_CLASS, NULL);
|
cache = gsk_gpu_cached_new (self, &GSK_GPU_CACHED_GLYPH_CLASS, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache->font_cache = font_cache;
|
cache->font = g_object_ref (font);
|
||||||
cache->glyph_key.glyph = glyph;
|
cache->glyph = glyph;
|
||||||
cache->glyph_key.flags = flags;
|
cache->flags = flags;
|
||||||
|
cache->scale = scale;
|
||||||
cache->bounds = rect;
|
cache->bounds = rect;
|
||||||
cache->image = image;
|
cache->image = image;
|
||||||
cache->origin = GRAPHENE_POINT_INIT (- origin.x + subpixel_x,
|
cache->origin = GRAPHENE_POINT_INIT (- origin.x + subpixel_x,
|
||||||
@@ -1059,12 +976,13 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
|||||||
&GRAPHENE_POINT_INIT (cache->origin.x + padding,
|
&GRAPHENE_POINT_INIT (cache->origin.x + padding,
|
||||||
cache->origin.y + padding));
|
cache->origin.y + padding));
|
||||||
|
|
||||||
g_hash_table_insert (font_cache->cache, cache, cache);
|
g_hash_table_insert (priv->glyph_cache, cache, cache);
|
||||||
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
||||||
|
|
||||||
*out_bounds = cache->bounds;
|
*out_bounds = cache->bounds;
|
||||||
*out_origin = cache->origin;
|
*out_origin = cache->origin;
|
||||||
*out_scaled_font = scaled_font;
|
|
||||||
|
g_object_unref (scaled_font);
|
||||||
|
|
||||||
return cache->image;
|
return cache->image;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,7 @@ GskGpuImage * gsk_gpu_device_lookup_glyph_image (GskGpuD
|
|||||||
GskGpuGlyphLookupFlags flags,
|
GskGpuGlyphLookupFlags flags,
|
||||||
float scale,
|
float scale,
|
||||||
graphene_rect_t *out_bounds,
|
graphene_rect_t *out_bounds,
|
||||||
graphene_point_t *out_origin,
|
graphene_point_t *out_origin);
|
||||||
PangoFont **out_scaled_font);
|
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuDevice, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuDevice, g_object_unref)
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
|
|||||||
bytes,
|
bytes,
|
||||||
stride);
|
stride);
|
||||||
g_bytes_unref (bytes);
|
g_bytes_unref (bytes);
|
||||||
gsk_gpu_buffer_unmap (self->buffer);
|
gsk_gpu_buffer_unmap (self->buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GskGpuOp *
|
static GskGpuOp *
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
|
|||||||
if (priv->vertex_buffer_data)
|
if (priv->vertex_buffer_data)
|
||||||
{
|
{
|
||||||
memcpy (new_data, priv->vertex_buffer_data, old_size);
|
memcpy (new_data, priv->vertex_buffer_data, old_size);
|
||||||
gsk_gpu_buffer_unmap (priv->vertex_buffer);
|
gsk_gpu_buffer_unmap (priv->vertex_buffer, old_size);
|
||||||
}
|
}
|
||||||
g_object_unref (priv->vertex_buffer);
|
g_object_unref (priv->vertex_buffer);
|
||||||
priv->vertex_buffer = new_buffer;
|
priv->vertex_buffer = new_buffer;
|
||||||
@@ -434,7 +434,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->vertex_buffer_used = size_needed;
|
priv->vertex_buffer_used = size_needed;
|
||||||
|
|
||||||
return size_needed - size;
|
return size_needed - size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +480,7 @@ gsk_gpu_frame_write_storage_buffer (GskGpuFrame *self,
|
|||||||
{
|
{
|
||||||
g_assert (offset > 0);
|
g_assert (offset > 0);
|
||||||
|
|
||||||
gsk_gpu_buffer_unmap (priv->storage_buffer);
|
gsk_gpu_buffer_unmap (priv->storage_buffer, 0);
|
||||||
g_clear_object (&priv->storage_buffer);
|
g_clear_object (&priv->storage_buffer);
|
||||||
priv->storage_buffer_data = 0;
|
priv->storage_buffer_data = 0;
|
||||||
priv->storage_buffer_used = 0;
|
priv->storage_buffer_used = 0;
|
||||||
@@ -591,14 +591,14 @@ gsk_gpu_frame_submit (GskGpuFrame *self)
|
|||||||
|
|
||||||
if (priv->vertex_buffer)
|
if (priv->vertex_buffer)
|
||||||
{
|
{
|
||||||
gsk_gpu_buffer_unmap (priv->vertex_buffer);
|
gsk_gpu_buffer_unmap (priv->vertex_buffer, priv->vertex_buffer_used);
|
||||||
priv->vertex_buffer_data = NULL;
|
priv->vertex_buffer_data = NULL;
|
||||||
priv->vertex_buffer_used = 0;
|
priv->vertex_buffer_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->storage_buffer_data)
|
if (priv->storage_buffer_data)
|
||||||
{
|
{
|
||||||
gsk_gpu_buffer_unmap (priv->storage_buffer);
|
gsk_gpu_buffer_unmap (priv->storage_buffer, priv->storage_buffer_used);
|
||||||
priv->storage_buffer_data = NULL;
|
priv->storage_buffer_data = NULL;
|
||||||
priv->storage_buffer_used = 0;
|
priv->storage_buffer_used = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+122
-81
@@ -36,10 +36,12 @@
|
|||||||
#include "gskdebugprivate.h"
|
#include "gskdebugprivate.h"
|
||||||
#include "gskpath.h"
|
#include "gskpath.h"
|
||||||
#include "gskrectprivate.h"
|
#include "gskrectprivate.h"
|
||||||
|
#include "gskvec2private.h"
|
||||||
#include "gskrendernodeprivate.h"
|
#include "gskrendernodeprivate.h"
|
||||||
#include "gskroundedrectprivate.h"
|
#include "gskroundedrectprivate.h"
|
||||||
#include "gskstrokeprivate.h"
|
#include "gskstrokeprivate.h"
|
||||||
#include "gsktransformprivate.h"
|
#include "gsktransformprivate.h"
|
||||||
|
#include "gskprivate.h"
|
||||||
|
|
||||||
#include "gdk/gdkrgbaprivate.h"
|
#include "gdk/gdkrgbaprivate.h"
|
||||||
#include "gdk/gdksubsurfaceprivate.h"
|
#include "gdk/gdksubsurfaceprivate.h"
|
||||||
@@ -183,20 +185,20 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
|
|||||||
{
|
{
|
||||||
float scale_x = viewport->size.width / width;
|
float scale_x = viewport->size.width / width;
|
||||||
float scale_y = viewport->size.height / height;
|
float scale_y = viewport->size.height / height;
|
||||||
gsk_gpu_clip_init_rect (&self->clip,
|
gsk_gpu_clip_init_empty (&self->clip,
|
||||||
&GRAPHENE_RECT_INIT (
|
&GRAPHENE_RECT_INIT (
|
||||||
scale_x * clip->x,
|
scale_x * clip->x,
|
||||||
scale_y * clip->y,
|
scale_y * clip->y,
|
||||||
scale_x * clip->width,
|
scale_x * clip->width,
|
||||||
scale_y * clip->height
|
scale_y * clip->height
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
self->modelview = NULL;
|
self->modelview = NULL;
|
||||||
gsk_gpu_image_get_projection_matrix (target, &self->projection);
|
gsk_gpu_image_get_projection_matrix (target, &self->projection);
|
||||||
graphene_vec2_init (&self->scale,
|
gsk_vec2_init (&self->scale,
|
||||||
width / viewport->size.width,
|
width / viewport->size.width,
|
||||||
height / viewport->size.height);
|
height / viewport->size.height);
|
||||||
self->offset = GRAPHENE_POINT_INIT (-viewport->origin.x,
|
self->offset = GRAPHENE_POINT_INIT (-viewport->origin.x,
|
||||||
-viewport->origin.y);
|
-viewport->origin.y);
|
||||||
self->opacity = 1.0;
|
self->opacity = 1.0;
|
||||||
@@ -318,8 +320,8 @@ rect_round_to_pixels (const graphene_rect_t *src,
|
|||||||
{
|
{
|
||||||
float x, y, xscale, yscale, inv_xscale, inv_yscale;
|
float x, y, xscale, yscale, inv_xscale, inv_yscale;
|
||||||
|
|
||||||
xscale = graphene_vec2_get_x (pixel_scale);
|
xscale = gsk_vec2_get_x (pixel_scale);
|
||||||
yscale = graphene_vec2_get_y (pixel_scale);
|
yscale = gsk_vec2_get_y (pixel_scale);
|
||||||
inv_xscale = 1.0f / xscale;
|
inv_xscale = 1.0f / xscale;
|
||||||
inv_yscale = 1.0f / yscale;
|
inv_yscale = 1.0f / yscale;
|
||||||
|
|
||||||
@@ -344,8 +346,8 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
|
|||||||
|
|
||||||
area.x = 0;
|
area.x = 0;
|
||||||
area.y = 0;
|
area.y = 0;
|
||||||
area.width = ceilf (graphene_vec2_get_x (scale) * viewport->size.width - EPSILON);
|
area.width = ceilf (gsk_vec2_get_x (scale) * viewport->size.width - EPSILON);
|
||||||
area.height = ceilf (graphene_vec2_get_y (scale) * viewport->size.height - EPSILON);
|
area.height = ceilf (gsk_vec2_get_y (scale) * viewport->size.height - EPSILON);
|
||||||
|
|
||||||
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
|
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
|
||||||
FALSE,
|
FALSE,
|
||||||
@@ -628,8 +630,8 @@ gsk_gpu_node_processor_rect_is_integer (GskGpuNodeProcessor *self,
|
|||||||
cairo_rectangle_int_t *int_rect)
|
cairo_rectangle_int_t *int_rect)
|
||||||
{
|
{
|
||||||
graphene_rect_t transformed_rect;
|
graphene_rect_t transformed_rect;
|
||||||
float scale_x = graphene_vec2_get_x (&self->scale);
|
float scale_x = gsk_vec2_get_x (&self->scale);
|
||||||
float scale_y = graphene_vec2_get_y (&self->scale);
|
float scale_y = gsk_vec2_get_y (&self->scale);
|
||||||
|
|
||||||
switch (gsk_transform_get_category (self->modelview))
|
switch (gsk_transform_get_category (self->modelview))
|
||||||
{
|
{
|
||||||
@@ -1029,7 +1031,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
|
|||||||
|
|
||||||
gsk_gpu_node_processor_sync_globals (&other, 0);
|
gsk_gpu_node_processor_sync_globals (&other, 0);
|
||||||
|
|
||||||
graphene_vec2_init (&direction, blur_radius, 0.0f);
|
gsk_vec2_init (&direction, blur_radius, 0.0f);
|
||||||
gsk_gpu_blur_op (other.frame,
|
gsk_gpu_blur_op (other.frame,
|
||||||
gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &intermediate_rect),
|
gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &intermediate_rect),
|
||||||
source_desc,
|
source_desc,
|
||||||
@@ -1043,7 +1045,7 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
|
|||||||
|
|
||||||
real_offset = GRAPHENE_POINT_INIT (self->offset.x + shadow_offset->x,
|
real_offset = GRAPHENE_POINT_INIT (self->offset.x + shadow_offset->x,
|
||||||
self->offset.y + shadow_offset->y);
|
self->offset.y + shadow_offset->y);
|
||||||
graphene_vec2_init (&direction, 0.0f, blur_radius);
|
gsk_vec2_init (&direction, 0.0f, blur_radius);
|
||||||
intermediate_descriptor = gsk_gpu_node_processor_add_image (self, intermediate, GSK_GPU_SAMPLER_TRANSPARENT);
|
intermediate_descriptor = gsk_gpu_node_processor_add_image (self, intermediate, GSK_GPU_SAMPLER_TRANSPARENT);
|
||||||
if (shadow_color)
|
if (shadow_color)
|
||||||
{
|
{
|
||||||
@@ -1327,7 +1329,7 @@ gsk_gpu_node_processor_add_node_clipped (GskGpuNodeProcessor *self,
|
|||||||
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
|
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (self->clip.type == GSK_GPU_CLIP_RECT &&
|
else if ((self->clip.type == GSK_GPU_CLIP_RECT || self->clip.type == GSK_GPU_CLIP_CONTAINED) &&
|
||||||
gsk_rect_contains_rect (&self->clip.rect.bounds, &clip))
|
gsk_rect_contains_rect (&self->clip.rect.bounds, &clip))
|
||||||
{
|
{
|
||||||
self->clip.type = GSK_GPU_CLIP_NONE;
|
self->clip.type = GSK_GPU_CLIP_NONE;
|
||||||
@@ -1580,8 +1582,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
|||||||
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
|
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
|
||||||
self->offset.x = (self->offset.x + dx) / scale_x;
|
self->offset.x = (self->offset.x + dx) / scale_x;
|
||||||
self->offset.y = (self->offset.y + dy) / scale_y;
|
self->offset.y = (self->offset.y + dy) / scale_y;
|
||||||
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
gsk_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||||
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
gsk_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||||
self->modelview = gsk_transform_scale (self->modelview,
|
self->modelview = gsk_transform_scale (self->modelview,
|
||||||
scale_x / fabs (scale_x),
|
scale_x / fabs (scale_x),
|
||||||
scale_y / fabs (scale_y));
|
scale_y / fabs (scale_y));
|
||||||
@@ -1610,7 +1612,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
|||||||
inverse = gsk_transform_invert (gsk_transform_ref (clip_transform));
|
inverse = gsk_transform_invert (gsk_transform_ref (clip_transform));
|
||||||
gsk_transform_transform_bounds (inverse, &old_clip.rect.bounds, &new_bounds);
|
gsk_transform_transform_bounds (inverse, &old_clip.rect.bounds, &new_bounds);
|
||||||
gsk_transform_unref (inverse);
|
gsk_transform_unref (inverse);
|
||||||
gsk_gpu_clip_init_contained (&self->clip, &new_bounds);
|
gsk_gpu_clip_init_empty (&self->clip, &new_bounds);
|
||||||
}
|
}
|
||||||
else if (!gsk_gpu_clip_transform (&self->clip, &old_clip, clip_transform, &child->bounds))
|
else if (!gsk_gpu_clip_transform (&self->clip, &old_clip, clip_transform, &child->bounds))
|
||||||
{
|
{
|
||||||
@@ -1641,17 +1643,20 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
|||||||
old_modelview = gsk_transform_ref (self->modelview);
|
old_modelview = gsk_transform_ref (self->modelview);
|
||||||
|
|
||||||
self->modelview = gsk_transform_scale (self->modelview,
|
self->modelview = gsk_transform_scale (self->modelview,
|
||||||
graphene_vec2_get_x (&self->scale),
|
gsk_vec2_get_x (&self->scale),
|
||||||
graphene_vec2_get_y (&self->scale));
|
gsk_vec2_get_y (&self->scale));
|
||||||
self->modelview = gsk_transform_transform (self->modelview, clip_transform);
|
self->modelview = gsk_transform_transform (self->modelview, clip_transform);
|
||||||
gsk_transform_unref (clip_transform);
|
gsk_transform_unref (clip_transform);
|
||||||
|
|
||||||
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
|
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
|
||||||
|
|
||||||
old_pixels = graphene_vec2_get_x (&old_scale) * graphene_vec2_get_y (&old_scale) *
|
old_pixels = MAX (gsk_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
|
||||||
old_clip.rect.bounds.size.width * old_clip.rect.bounds.size.height;
|
gsk_vec2_get_y (&old_scale) * old_clip.rect.bounds.size.height);
|
||||||
new_pixels = scale_x * scale_y * self->clip.rect.bounds.size.width * self->clip.rect.bounds.size.height;
|
new_pixels = MAX (scale_x * self->clip.rect.bounds.size.width,
|
||||||
if (new_pixels > 2 * old_pixels)
|
scale_y * self->clip.rect.bounds.size.height);
|
||||||
|
|
||||||
|
/* Check that our offscreen doesn't get too big. 1.5 ~ sqrt(2) */
|
||||||
|
if (new_pixels > 1.5 * old_pixels)
|
||||||
{
|
{
|
||||||
float forced_downscale = 2 * old_pixels / new_pixels;
|
float forced_downscale = 2 * old_pixels / new_pixels;
|
||||||
scale_x *= forced_downscale;
|
scale_x *= forced_downscale;
|
||||||
@@ -1659,7 +1664,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
|
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
|
||||||
graphene_vec2_init (&self->scale, scale_x, scale_y);
|
gsk_vec2_init (&self->scale, scale_x, scale_y);
|
||||||
self->offset = *graphene_point_zero ();
|
self->offset = *graphene_point_zero ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1731,8 +1736,8 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
|
|||||||
self->bounds.size.width *= inv_sx;
|
self->bounds.size.width *= inv_sx;
|
||||||
self->bounds.size.height *= inv_sy;
|
self->bounds.size.height *= inv_sy;
|
||||||
self->offset = GRAPHENE_POINT_INIT (0, 0);
|
self->offset = GRAPHENE_POINT_INIT (0, 0);
|
||||||
graphene_vec2_init (&self->scale, fabs (sx), fabs (sy));
|
gsk_vec2_init (&self->scale, fabs (sx), fabs (sy));
|
||||||
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
gsk_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1816,8 +1821,8 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scale_x = graphene_vec2_get_x (&self->scale);
|
scale_x = gsk_vec2_get_x (&self->scale);
|
||||||
scale_y = graphene_vec2_get_y (&self->scale);
|
scale_y = gsk_vec2_get_y (&self->scale);
|
||||||
clipped = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
|
clipped = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
|
||||||
int_clipped.width / scale_x, int_clipped.height / scale_y);
|
int_clipped.width / scale_x, int_clipped.height / scale_y);
|
||||||
shader_clip = gsk_gpu_clip_get_shader_clip (&self->clip, graphene_point_zero(), &clipped);
|
shader_clip = gsk_gpu_clip_get_shader_clip (&self->clip, graphene_point_zero(), &clipped);
|
||||||
@@ -1944,8 +1949,8 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
||||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
|
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_vec2_get_x (&self->scale) ||
|
||||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
|
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_vec2_get_y (&self->scale)))
|
||||||
{
|
{
|
||||||
guint32 descriptor;
|
guint32 descriptor;
|
||||||
|
|
||||||
@@ -2011,8 +2016,8 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
||||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
|
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_vec2_get_x (&self->scale) ||
|
||||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
|
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_vec2_get_y (&self->scale)))
|
||||||
{
|
{
|
||||||
image = gsk_gpu_node_processor_ensure_image (self->frame,
|
image = gsk_gpu_node_processor_ensure_image (self->frame,
|
||||||
image,
|
image,
|
||||||
@@ -2055,8 +2060,8 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
|||||||
guint32 descriptor;
|
guint32 descriptor;
|
||||||
gboolean need_mipmap, need_offscreen;
|
gboolean need_mipmap, need_offscreen;
|
||||||
|
|
||||||
need_offscreen = self->modelview != NULL ||
|
need_offscreen = self->modelview != NULL ||
|
||||||
!graphene_vec2_equal (&self->scale, graphene_vec2_one ());
|
gsk_vec2_equal (&self->scale, graphene_vec2_one ());
|
||||||
if (need_offscreen)
|
if (need_offscreen)
|
||||||
{
|
{
|
||||||
GskGpuImage *offscreen;
|
GskGpuImage *offscreen;
|
||||||
@@ -2992,15 +2997,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
|||||||
GskGpuDevice *device;
|
GskGpuDevice *device;
|
||||||
const PangoGlyphInfo *glyphs;
|
const PangoGlyphInfo *glyphs;
|
||||||
PangoFont *font;
|
PangoFont *font;
|
||||||
PangoFont *scaled_font = NULL;
|
|
||||||
graphene_point_t offset;
|
graphene_point_t offset;
|
||||||
guint i, num_glyphs;
|
guint i, num_glyphs;
|
||||||
float scale, inv_scale;
|
float scale, inv_scale;
|
||||||
GdkRGBA color;
|
GdkRGBA color;
|
||||||
gboolean glyph_align;
|
gboolean glyph_align;
|
||||||
GskGpuImage *last_image;
|
gboolean hinting;
|
||||||
guint32 descriptor = 0;
|
|
||||||
GskGpuClip old_clip;
|
|
||||||
|
|
||||||
if (self->opacity < 1.0 &&
|
if (self->opacity < 1.0 &&
|
||||||
gsk_text_node_has_color_glyphs (node))
|
gsk_text_node_has_color_glyphs (node))
|
||||||
@@ -3009,13 +3011,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
|
|
||||||
if (gsk_gpu_clip_contains_rect (&self->clip, &self->offset, &node->bounds))
|
|
||||||
gsk_gpu_clip_init_contained (&self->clip, &node->bounds);
|
|
||||||
|
|
||||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN) &&
|
|
||||||
gsk_transform_get_category (self->modelview) >= GSK_TRANSFORM_CATEGORY_2D;
|
|
||||||
device = gsk_gpu_frame_get_device (self->frame);
|
device = gsk_gpu_frame_get_device (self->frame);
|
||||||
|
|
||||||
color = *gsk_text_node_get_color (node);
|
color = *gsk_text_node_get_color (node);
|
||||||
color.alpha *= self->opacity;
|
color.alpha *= self->opacity;
|
||||||
num_glyphs = gsk_text_node_get_num_glyphs (node);
|
num_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||||
@@ -3025,23 +3022,37 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
|||||||
offset.x += self->offset.x;
|
offset.x += self->offset.x;
|
||||||
offset.y += self->offset.y;
|
offset.y += self->offset.y;
|
||||||
|
|
||||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
scale = MAX (gsk_vec2_get_x (&self->scale), gsk_vec2_get_y (&self->scale));
|
||||||
inv_scale = 1.f / scale;
|
inv_scale = 1.f / scale;
|
||||||
|
|
||||||
last_image = NULL;
|
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||||
|
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||||
|
|
||||||
for (i = 0; i < num_glyphs; i++)
|
for (i = 0; i < num_glyphs; i++)
|
||||||
{
|
{
|
||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
graphene_rect_t glyph_bounds, glyph_tex_rect;
|
graphene_rect_t glyph_bounds, glyph_tex_rect;
|
||||||
graphene_point_t glyph_offset, glyph_origin;
|
graphene_point_t glyph_offset, glyph_origin;
|
||||||
|
guint32 descriptor;
|
||||||
GskGpuGlyphLookupFlags flags;
|
GskGpuGlyphLookupFlags flags;
|
||||||
|
|
||||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||||
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||||
if (glyph_align)
|
|
||||||
|
if (hinting && glyph_align)
|
||||||
{
|
{
|
||||||
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
/* Force glyph_origin.y to be device pixel aligned.
|
||||||
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
|
* The hinter expects that.
|
||||||
|
*/
|
||||||
|
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||||
|
flags = ((int) glyph_origin.x & 3);
|
||||||
|
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||||
|
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||||
|
}
|
||||||
|
else if (glyph_align)
|
||||||
|
{
|
||||||
|
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||||
|
glyph_origin.y = floor (glyph_origin.y * scale * 4 + .5);
|
||||||
flags = ((int) glyph_origin.x & 3) |
|
flags = ((int) glyph_origin.x & 3) |
|
||||||
(((int) glyph_origin.y & 3) << 2);
|
(((int) glyph_origin.y & 3) << 2);
|
||||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||||
@@ -3049,6 +3060,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
glyph_origin.x = floor (glyph_origin.x * scale + .5) * inv_scale;
|
||||||
|
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3059,19 +3072,20 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
|||||||
flags,
|
flags,
|
||||||
scale,
|
scale,
|
||||||
&glyph_bounds,
|
&glyph_bounds,
|
||||||
&glyph_offset,
|
&glyph_offset);
|
||||||
&scaled_font);
|
|
||||||
|
|
||||||
gsk_rect_scale (&GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv_scale, inv_scale, &glyph_tex_rect);
|
glyph_tex_rect = GRAPHENE_RECT_INIT (-glyph_bounds.origin.x * inv_scale,
|
||||||
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
|
-glyph_bounds.origin.y * inv_scale,
|
||||||
|
gsk_gpu_image_get_width (image) * inv_scale,
|
||||||
|
gsk_gpu_image_get_height (image) * inv_scale);
|
||||||
|
glyph_bounds = GRAPHENE_RECT_INIT (0,
|
||||||
|
0,
|
||||||
|
glyph_bounds.size.width * inv_scale,
|
||||||
|
glyph_bounds.size.height * inv_scale);
|
||||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||||
|
|
||||||
if (image != last_image)
|
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||||
{
|
|
||||||
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
|
||||||
last_image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glyphs[i].attr.is_color)
|
if (glyphs[i].attr.is_color)
|
||||||
gsk_gpu_texture_op (self->frame,
|
gsk_gpu_texture_op (self->frame,
|
||||||
@@ -3093,10 +3107,6 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
|||||||
|
|
||||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_object (&scaled_font);
|
|
||||||
|
|
||||||
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -3106,13 +3116,14 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
|||||||
GskGpuDevice *device;
|
GskGpuDevice *device;
|
||||||
const PangoGlyphInfo *glyphs;
|
const PangoGlyphInfo *glyphs;
|
||||||
PangoFont *font;
|
PangoFont *font;
|
||||||
PangoFont *scaled_font = NULL;
|
|
||||||
guint num_glyphs;
|
guint num_glyphs;
|
||||||
gsize i;
|
gsize i;
|
||||||
float scale, inv_scale;
|
float scale, inv_scale;
|
||||||
guint32 tex_id;
|
guint32 tex_id;
|
||||||
GskGpuImage *last_image;
|
GskGpuImage *last_image;
|
||||||
graphene_point_t offset;
|
graphene_point_t offset;
|
||||||
|
gboolean glyph_align;
|
||||||
|
gboolean hinting;
|
||||||
|
|
||||||
if (gsk_text_node_has_color_glyphs (node))
|
if (gsk_text_node_has_color_glyphs (node))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -3125,40 +3136,72 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
|||||||
offset.x += self->offset.x;
|
offset.x += self->offset.x;
|
||||||
offset.y += self->offset.y;
|
offset.y += self->offset.y;
|
||||||
|
|
||||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
scale = MAX (gsk_vec2_get_x (&self->scale), gsk_vec2_get_y (&self->scale));
|
||||||
inv_scale = 1.f / scale;
|
inv_scale = 1.f / scale;
|
||||||
|
|
||||||
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_GLYPHS);
|
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_GLYPHS);
|
||||||
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
|
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
|
||||||
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
|
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
|
||||||
|
|
||||||
|
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||||
|
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||||
|
|
||||||
last_image = NULL;
|
last_image = NULL;
|
||||||
for (i = 0; i < num_glyphs; i++)
|
for (i = 0; i < num_glyphs; i++)
|
||||||
{
|
{
|
||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
graphene_rect_t glyph_bounds;
|
graphene_rect_t glyph_bounds;
|
||||||
graphene_point_t glyph_offset;
|
graphene_point_t glyph_offset, glyph_origin;
|
||||||
|
GskGpuGlyphLookupFlags flags;
|
||||||
|
|
||||||
|
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||||
|
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||||
|
|
||||||
|
if (hinting && glyph_align)
|
||||||
|
{
|
||||||
|
/* Force glyph_origin.y to be device pixel aligned.
|
||||||
|
* The hinter expects that.
|
||||||
|
*/
|
||||||
|
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||||
|
flags = ((int) glyph_origin.x & 3);
|
||||||
|
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||||
|
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
|
||||||
|
}
|
||||||
|
else if (glyph_align)
|
||||||
|
{
|
||||||
|
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||||
|
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
|
||||||
|
flags = ((int) glyph_origin.x & 3) |
|
||||||
|
(((int) glyph_origin.y & 3) << 2);
|
||||||
|
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||||
|
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glyph_origin.x = roundf (glyph_origin.x * scale) * inv_scale;
|
||||||
|
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||||
self->frame,
|
self->frame,
|
||||||
font,
|
font,
|
||||||
glyphs[i].glyph,
|
glyphs[i].glyph,
|
||||||
0,
|
flags,
|
||||||
scale,
|
scale,
|
||||||
&glyph_bounds,
|
&glyph_bounds,
|
||||||
&glyph_offset,
|
&glyph_offset);
|
||||||
&scaled_font);
|
|
||||||
|
|
||||||
if (image != last_image)
|
if (image != last_image)
|
||||||
{
|
{
|
||||||
if (!gsk_gpu_pattern_writer_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT, &tex_id))
|
if (!gsk_gpu_pattern_writer_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT, &tex_id))
|
||||||
break;
|
return FALSE;
|
||||||
|
|
||||||
last_image = image;
|
last_image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||||
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||||
|
|
||||||
gsk_gpu_pattern_writer_append_uint (self, tex_id);
|
gsk_gpu_pattern_writer_append_uint (self, tex_id);
|
||||||
gsk_gpu_pattern_writer_append_rect (self,
|
gsk_gpu_pattern_writer_append_rect (self,
|
||||||
@@ -3168,7 +3211,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
|||||||
glyph_bounds.size.width * inv_scale,
|
glyph_bounds.size.width * inv_scale,
|
||||||
glyph_bounds.size.height * inv_scale
|
glyph_bounds.size.height * inv_scale
|
||||||
),
|
),
|
||||||
&glyph_offset);
|
&glyph_origin);
|
||||||
gsk_gpu_pattern_writer_append_rect (self,
|
gsk_gpu_pattern_writer_append_rect (self,
|
||||||
&GRAPHENE_RECT_INIT (
|
&GRAPHENE_RECT_INIT (
|
||||||
- glyph_bounds.origin.x * inv_scale,
|
- glyph_bounds.origin.x * inv_scale,
|
||||||
@@ -3176,14 +3219,12 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
|||||||
gsk_gpu_image_get_width (image) * inv_scale,
|
gsk_gpu_image_get_width (image) * inv_scale,
|
||||||
gsk_gpu_image_get_height (image) * inv_scale
|
gsk_gpu_image_get_height (image) * inv_scale
|
||||||
),
|
),
|
||||||
&glyph_offset);
|
&glyph_origin);
|
||||||
|
|
||||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_object (&scaled_font);
|
return TRUE;
|
||||||
|
|
||||||
return i == num_glyphs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "gdk/gdkglcontextprivate.h"
|
#include "gdk/gdkglcontextprivate.h"
|
||||||
#include "gsk/gskdebugprivate.h"
|
#include "gsk/gskdebugprivate.h"
|
||||||
|
#include "gskvec2private.h"
|
||||||
|
|
||||||
static GskGpuOp *
|
static GskGpuOp *
|
||||||
gsk_gpu_upload_op_gl_command_with_area (GskGpuOp *op,
|
gsk_gpu_upload_op_gl_command_with_area (GskGpuOp *op,
|
||||||
@@ -110,8 +111,8 @@ gsk_gpu_upload_op_vk_command_with_area (GskGpuOp *op,
|
|||||||
data = gsk_gpu_buffer_map (*buffer);
|
data = gsk_gpu_buffer_map (*buffer);
|
||||||
|
|
||||||
draw_func (op, data, stride);
|
draw_func (op, data, stride);
|
||||||
|
|
||||||
gsk_gpu_buffer_unmap (*buffer);
|
gsk_gpu_buffer_unmap (*buffer, area->height * stride);
|
||||||
|
|
||||||
vkCmdPipelineBarrier (state->vk_command_buffer,
|
vkCmdPipelineBarrier (state->vk_command_buffer,
|
||||||
VK_PIPELINE_STAGE_HOST_BIT,
|
VK_PIPELINE_STAGE_HOST_BIT,
|
||||||
@@ -465,8 +466,8 @@ gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
|
|||||||
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
|
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
|
||||||
FALSE,
|
FALSE,
|
||||||
GDK_MEMORY_DEFAULT,
|
GDK_MEMORY_DEFAULT,
|
||||||
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
|
ceil (gsk_vec2_get_x (scale) * viewport->size.width),
|
||||||
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
|
ceil (gsk_vec2_get_y (scale) * viewport->size.height));
|
||||||
self->viewport = *viewport;
|
self->viewport = *viewport;
|
||||||
self->func = func;
|
self->func = func;
|
||||||
self->user_data = user_data;
|
self->user_data = user_data;
|
||||||
@@ -531,6 +532,7 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
|||||||
GskGpuUploadGlyphOp *self = (GskGpuUploadGlyphOp *) op;
|
GskGpuUploadGlyphOp *self = (GskGpuUploadGlyphOp *) op;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
PangoRectangle ink_rect = { 0, };
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data (data,
|
surface = cairo_image_surface_create_for_data (data,
|
||||||
CAIRO_FORMAT_ARGB32,
|
CAIRO_FORMAT_ARGB32,
|
||||||
@@ -552,12 +554,19 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
|||||||
/* Draw glyph */
|
/* Draw glyph */
|
||||||
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
||||||
|
|
||||||
|
/* The pango code for drawing hex boxes uses the glyph width */
|
||||||
|
if (self->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
||||||
|
pango_font_get_glyph_extents (self->font, self->glyph, &ink_rect, NULL);
|
||||||
|
|
||||||
pango_cairo_show_glyph_string (cr,
|
pango_cairo_show_glyph_string (cr,
|
||||||
self->font,
|
self->font,
|
||||||
&(PangoGlyphString) {
|
&(PangoGlyphString) {
|
||||||
.num_glyphs = 1,
|
.num_glyphs = 1,
|
||||||
.glyphs = (PangoGlyphInfo[1]) { {
|
.glyphs = (PangoGlyphInfo[1]) { {
|
||||||
.glyph = self->glyph
|
.glyph = self->glyph,
|
||||||
|
.geometry = {
|
||||||
|
.width = ink_rect.width,
|
||||||
|
}
|
||||||
} }
|
} }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ gsk_vulkan_buffer_map (GskGpuBuffer *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_vulkan_buffer_unmap (GskGpuBuffer *buffer)
|
gsk_vulkan_buffer_unmap (GskGpuBuffer *buffer,
|
||||||
|
gsize size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+144
-48
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
#include <pango/pangoft2.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
@@ -21,51 +22,106 @@ gsk_ensure_resources (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*< private >
|
/*< private >
|
||||||
* gsk_get_scaled_font:
|
* gsk_reload_font:
|
||||||
* @font: a `PangoFont`
|
* @font: a `PangoFont`
|
||||||
* @scale: the scale
|
* @scale: the scale to apply
|
||||||
|
* @hint_metris: hint metrics to use or `CAIRO_HINT_METRICS_DEFAILT` to keep the
|
||||||
|
* hint metrics of the font unchanged
|
||||||
|
* @hint_style: hint style to use or `CAIRO_HINT_STYLE_DEFAULT` to keep the
|
||||||
|
* hint style of @font unchanged
|
||||||
|
* @antialias: antialiasing to use, or `CAIRO_ANTIALIAS_DEFAULT` to keep the
|
||||||
|
* antialias option of @font unchanged
|
||||||
*
|
*
|
||||||
* Returns a font that is just like @font, at a size that
|
* Returns a font that is just like @font, but uses the
|
||||||
* is multiplied by @scale.
|
* given scale and hinting options for its glyphs and metrics.
|
||||||
*
|
*
|
||||||
* Returns: (transfer full): a scaled version of @font
|
* Returns: (transfer full): the modified `PangoFont`
|
||||||
*/
|
*/
|
||||||
PangoFont *
|
PangoFont *
|
||||||
gsk_get_scaled_font (PangoFont *font,
|
gsk_reload_font (PangoFont *font,
|
||||||
float scale)
|
float scale,
|
||||||
|
cairo_hint_metrics_t hint_metrics,
|
||||||
|
cairo_hint_style_t hint_style,
|
||||||
|
cairo_antialias_t antialias)
|
||||||
{
|
{
|
||||||
if (scale == 1.0)
|
cairo_font_options_t *options;
|
||||||
return g_object_ref (font);
|
cairo_scaled_font_t *sf;
|
||||||
|
static PangoContext *context = NULL;
|
||||||
|
#if !PANGO_VERSION_CHECK (1, 52, 0)
|
||||||
|
PangoFontDescription *desc;
|
||||||
|
FcPattern *pattern;
|
||||||
|
double dpi;
|
||||||
|
int size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* These requests often come in sequentially so keep the result
|
||||||
|
* around and re-use it if everything matches.
|
||||||
|
*/
|
||||||
|
static PangoFont *last_font;
|
||||||
|
static float last_scale;
|
||||||
|
static cairo_hint_metrics_t last_hint_metrics;
|
||||||
|
static cairo_hint_style_t last_hint_style;
|
||||||
|
static cairo_antialias_t last_antialias;
|
||||||
|
static PangoFont *last_result;
|
||||||
|
|
||||||
|
if (last_result != NULL &&
|
||||||
|
last_font == font &&
|
||||||
|
last_scale == scale &&
|
||||||
|
last_hint_metrics == hint_metrics &&
|
||||||
|
last_hint_style == hint_style &&
|
||||||
|
last_antialias == antialias)
|
||||||
|
return g_object_ref (last_result);
|
||||||
|
|
||||||
|
last_scale = scale;
|
||||||
|
last_hint_metrics = hint_metrics;
|
||||||
|
last_hint_style = hint_style;
|
||||||
|
last_antialias = antialias;
|
||||||
|
|
||||||
|
g_set_object (&last_font, font);
|
||||||
|
g_clear_object (&last_result);
|
||||||
|
|
||||||
|
options = cairo_font_options_create ();
|
||||||
|
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||||
|
cairo_scaled_font_get_font_options (sf, options);
|
||||||
|
|
||||||
|
if (hint_metrics == CAIRO_HINT_METRICS_DEFAULT)
|
||||||
|
hint_metrics = cairo_font_options_get_hint_metrics (options);
|
||||||
|
|
||||||
|
if (hint_style == CAIRO_HINT_STYLE_DEFAULT)
|
||||||
|
hint_style = cairo_font_options_get_hint_style (options);
|
||||||
|
|
||||||
|
if (antialias == CAIRO_ANTIALIAS_DEFAULT)
|
||||||
|
antialias = cairo_font_options_get_antialias (options);
|
||||||
|
|
||||||
|
if (1.0 == scale &&
|
||||||
|
cairo_font_options_get_hint_metrics (options) == hint_metrics &&
|
||||||
|
cairo_font_options_get_hint_style (options) == hint_style &&
|
||||||
|
cairo_font_options_get_antialias (options) == antialias &&
|
||||||
|
cairo_font_options_get_subpixel_order (options) == CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
||||||
|
{
|
||||||
|
last_result = g_object_ref (font);
|
||||||
|
cairo_font_options_destroy (options);
|
||||||
|
return g_object_ref (font);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_font_options_set_hint_metrics (options, hint_metrics);
|
||||||
|
cairo_font_options_set_hint_style (options, hint_style);
|
||||||
|
cairo_font_options_set_antialias (options, antialias);
|
||||||
|
cairo_font_options_set_subpixel_order (options, CAIRO_SUBPIXEL_ORDER_DEFAULT);
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
context = pango_context_new ();
|
||||||
|
|
||||||
|
pango_cairo_context_set_font_options (context, options);
|
||||||
|
cairo_font_options_destroy (options);
|
||||||
|
|
||||||
#if PANGO_VERSION_CHECK (1, 52, 0)
|
#if PANGO_VERSION_CHECK (1, 52, 0)
|
||||||
return pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, NULL, NULL);
|
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, context, NULL);
|
||||||
#else
|
#else
|
||||||
GHashTable *fonts;
|
|
||||||
int key;
|
|
||||||
PangoFont *font2;
|
|
||||||
PangoFontDescription *desc;
|
|
||||||
int size;
|
|
||||||
PangoFontMap *fontmap;
|
|
||||||
PangoContext *context;
|
|
||||||
cairo_scaled_font_t *sf;
|
|
||||||
cairo_font_options_t *options;
|
|
||||||
|
|
||||||
key = (int) roundf (scale * PANGO_SCALE);
|
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
|
||||||
|
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultMatch)
|
||||||
fonts = (GHashTable *) g_object_get_data (G_OBJECT (font), "gsk-scaled-fonts");
|
pango_cairo_context_set_resolution (context, dpi);
|
||||||
|
|
||||||
if (fonts)
|
|
||||||
{
|
|
||||||
font2 = g_hash_table_lookup (fonts, GINT_TO_POINTER (key));
|
|
||||||
if (font2)
|
|
||||||
return g_object_ref (font2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fonts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
|
||||||
g_object_set_data_full (G_OBJECT (font), "gsk-scaled-fonts",
|
|
||||||
fonts, (GDestroyNotify) g_hash_table_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
desc = pango_font_describe (font);
|
desc = pango_font_describe (font);
|
||||||
size = pango_font_description_get_size (desc);
|
size = pango_font_description_get_size (desc);
|
||||||
@@ -73,24 +129,64 @@ gsk_get_scaled_font (PangoFont *font,
|
|||||||
if (pango_font_description_get_size_is_absolute (desc))
|
if (pango_font_description_get_size_is_absolute (desc))
|
||||||
pango_font_description_set_absolute_size (desc, size * scale);
|
pango_font_description_set_absolute_size (desc, size * scale);
|
||||||
else
|
else
|
||||||
pango_font_description_set_size (desc, (int) roundf (size * scale));
|
pango_font_description_set_size (desc, (int) floor (size * scale + .5));
|
||||||
|
|
||||||
fontmap = pango_font_get_font_map (font);
|
last_result = pango_font_map_load_font (pango_font_get_font_map (font), context, desc);
|
||||||
context = pango_font_map_create_context (fontmap);
|
pango_font_description_free (desc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return g_object_ref (last_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gsk_get_unhinted_glyph_string_extents:
|
||||||
|
* @glyphs: a `PangoGlyphString`
|
||||||
|
* @font: a `PangoFont`
|
||||||
|
* @ink_rect: (out): rectangle used to store the extents of the glyph string as drawn
|
||||||
|
*
|
||||||
|
* Compute the ink extents of a glyph string.
|
||||||
|
*
|
||||||
|
* This is like [method@Pango.GlyphString.extents], but it
|
||||||
|
* ignores hinting of the font.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoRectangle *ink_rect)
|
||||||
|
{
|
||||||
|
PangoFont *unhinted;
|
||||||
|
|
||||||
|
unhinted = gsk_reload_font (font,
|
||||||
|
1.0,
|
||||||
|
CAIRO_HINT_METRICS_OFF,
|
||||||
|
CAIRO_HINT_STYLE_NONE,
|
||||||
|
CAIRO_ANTIALIAS_DEFAULT);
|
||||||
|
|
||||||
|
pango_glyph_string_extents (glyphs, unhinted, ink_rect, NULL);
|
||||||
|
|
||||||
|
g_object_unref (unhinted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gsk_font_get_hint_style:
|
||||||
|
* @font: a `PangoFont`
|
||||||
|
*
|
||||||
|
* Get the hint style from the cairo font options.
|
||||||
|
*
|
||||||
|
* Returns: the hint style
|
||||||
|
*/
|
||||||
|
cairo_hint_style_t
|
||||||
|
gsk_font_get_hint_style (PangoFont *font)
|
||||||
|
{
|
||||||
|
cairo_scaled_font_t *sf;
|
||||||
|
cairo_font_options_t *options;
|
||||||
|
cairo_hint_style_t style;
|
||||||
|
|
||||||
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||||
options = cairo_font_options_create ();
|
options = cairo_font_options_create ();
|
||||||
cairo_scaled_font_get_font_options (sf, options);
|
cairo_scaled_font_get_font_options (sf, options);
|
||||||
pango_cairo_context_set_font_options (context, options);
|
style = cairo_font_options_get_hint_style (options);
|
||||||
cairo_font_options_destroy (options);
|
cairo_font_options_destroy (options);
|
||||||
|
|
||||||
font2 = pango_font_map_load_font (fontmap, context, desc);
|
return style;
|
||||||
|
|
||||||
pango_font_description_free (desc);
|
|
||||||
g_object_unref (context);
|
|
||||||
|
|
||||||
g_hash_table_insert (fonts, GINT_TO_POINTER (key), font2);
|
|
||||||
|
|
||||||
return g_object_ref (font2);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -2,13 +2,23 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <pango/pango.h>
|
#include <pango/pango.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void gsk_ensure_resources (void);
|
void gsk_ensure_resources (void);
|
||||||
|
|
||||||
PangoFont *gsk_get_scaled_font (PangoFont *font,
|
PangoFont *gsk_reload_font (PangoFont *font,
|
||||||
float scale);
|
float scale,
|
||||||
|
cairo_hint_metrics_t hint_metrics,
|
||||||
|
cairo_hint_style_t hint_style,
|
||||||
|
cairo_antialias_t antialias);
|
||||||
|
|
||||||
|
void gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoRectangle *ink_rect);
|
||||||
|
|
||||||
|
cairo_hint_style_t gsk_font_get_hint_style (PangoFont *font);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|||||||
@@ -688,9 +688,6 @@ get_renderer_for_vulkan (GdkSurface *surface)
|
|||||||
static GType
|
static GType
|
||||||
get_renderer_for_gles2 (GdkSurface *surface)
|
get_renderer_for_gles2 (GdkSurface *surface)
|
||||||
{
|
{
|
||||||
if (gl_software_rendering (surface))
|
|
||||||
return G_TYPE_INVALID;
|
|
||||||
|
|
||||||
return GSK_TYPE_GL_RENDERER;
|
return GSK_TYPE_GL_RENDERER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-7
@@ -31,6 +31,7 @@
|
|||||||
#include "gskroundedrectprivate.h"
|
#include "gskroundedrectprivate.h"
|
||||||
#include "gskstrokeprivate.h"
|
#include "gskstrokeprivate.h"
|
||||||
#include "gsktransformprivate.h"
|
#include "gsktransformprivate.h"
|
||||||
|
#include "gskprivate.h"
|
||||||
|
|
||||||
#include "gdk/gdkmemoryformatprivate.h"
|
#include "gdk/gdkmemoryformatprivate.h"
|
||||||
#include "gdk/gdkprivate.h"
|
#include "gdk/gdkprivate.h"
|
||||||
@@ -3473,7 +3474,7 @@ gsk_transform_node_draw (GskRenderNode *node,
|
|||||||
* (like when flipping an axis at the point where scale == 0)
|
* (like when flipping an axis at the point where scale == 0)
|
||||||
* and just means that nothing should be drawn.
|
* and just means that nothing should be drawn.
|
||||||
* But Cairo throws lots of ugly errors instead of silently
|
* But Cairo throws lots of ugly errors instead of silently
|
||||||
* going on. So We silently go on.
|
* going on. So we silently go on.
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5791,6 +5792,12 @@ gsk_text_node_class_init (gpointer g_class,
|
|||||||
node_class->diff = gsk_text_node_diff;
|
node_class->diff = gsk_text_node_diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
pango_units_to_float (int i)
|
||||||
|
{
|
||||||
|
return (float) i / PANGO_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_text_node_new:
|
* gsk_text_node_new:
|
||||||
* @font: the `PangoFont` containing the glyphs
|
* @font: the `PangoFont` containing the glyphs
|
||||||
@@ -5817,8 +5824,7 @@ gsk_text_node_new (PangoFont *font,
|
|||||||
PangoGlyphInfo *glyph_infos;
|
PangoGlyphInfo *glyph_infos;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
|
gsk_get_unhinted_glyph_string_extents (glyphs, font, &ink_rect);
|
||||||
pango_extents_to_pixels (&ink_rect, NULL);
|
|
||||||
|
|
||||||
/* Don't create nodes with empty bounds */
|
/* Don't create nodes with empty bounds */
|
||||||
if (ink_rect.width == 0 || ink_rect.height == 0)
|
if (ink_rect.width == 0 || ink_rect.height == 0)
|
||||||
@@ -5855,10 +5861,10 @@ gsk_text_node_new (PangoFont *font,
|
|||||||
self->num_glyphs = n;
|
self->num_glyphs = n;
|
||||||
|
|
||||||
gsk_rect_init (&node->bounds,
|
gsk_rect_init (&node->bounds,
|
||||||
offset->x + ink_rect.x,
|
offset->x + pango_units_to_float (ink_rect.x),
|
||||||
offset->y + ink_rect.y,
|
offset->y + pango_units_to_float (ink_rect.y),
|
||||||
ink_rect.width,
|
pango_units_to_float (ink_rect.width),
|
||||||
ink_rect.height);
|
pango_units_to_float (ink_rect.height));
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
+188
-77
@@ -30,6 +30,7 @@
|
|||||||
#include "gskstroke.h"
|
#include "gskstroke.h"
|
||||||
#include "gsktransformprivate.h"
|
#include "gsktransformprivate.h"
|
||||||
#include "gskenumtypes.h"
|
#include "gskenumtypes.h"
|
||||||
|
#include "gskprivate.h"
|
||||||
|
|
||||||
#include "gdk/gdkrgbaprivate.h"
|
#include "gdk/gdkrgbaprivate.h"
|
||||||
#include "gdk/gdktextureprivate.h"
|
#include "gdk/gdktextureprivate.h"
|
||||||
@@ -46,7 +47,9 @@
|
|||||||
#include <cairo-script-interpreter.h>
|
#include <cairo-script-interpreter.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cairo-gobject.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
|
||||||
#ifdef HAVE_PANGOFT
|
#ifdef HAVE_PANGOFT
|
||||||
#include <pango/pangofc-fontmap.h>
|
#include <pango/pangofc-fontmap.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -86,6 +89,39 @@ context_finish (Context *context)
|
|||||||
g_clear_object (&context->fontmap);
|
g_clear_object (&context->fontmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_enum (GtkCssParser *parser,
|
||||||
|
GType type,
|
||||||
|
gpointer out_value)
|
||||||
|
{
|
||||||
|
GEnumClass *class;
|
||||||
|
GEnumValue *v;
|
||||||
|
char *enum_name;
|
||||||
|
|
||||||
|
enum_name = gtk_css_parser_consume_ident (parser);
|
||||||
|
if (enum_name == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
class = g_type_class_ref (type);
|
||||||
|
|
||||||
|
v = g_enum_get_value_by_nick (class, enum_name);
|
||||||
|
if (v == NULL)
|
||||||
|
{
|
||||||
|
gtk_css_parser_error_value (parser, "Unknown value \"%s\" for enum \"%s\"",
|
||||||
|
enum_name, g_type_name (type));
|
||||||
|
g_free (enum_name);
|
||||||
|
g_type_class_unref (class);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(int*)out_value = v->value;
|
||||||
|
|
||||||
|
g_free (enum_name);
|
||||||
|
g_type_class_unref (class);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_rect (GtkCssParser *parser,
|
parse_rect (GtkCssParser *parser,
|
||||||
Context *context,
|
Context *context,
|
||||||
@@ -1182,6 +1218,8 @@ clear_font (gpointer inout_font)
|
|||||||
g_clear_object ((PangoFont **) inout_font);
|
g_clear_object ((PangoFont **) inout_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GLYPH_NEEDS_WIDTH (1 << 15)
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_glyphs (GtkCssParser *parser,
|
parse_glyphs (GtkCssParser *parser,
|
||||||
Context *context,
|
Context *context,
|
||||||
@@ -1208,6 +1246,7 @@ parse_glyphs (GtkCssParser *parser,
|
|||||||
gtk_css_parser_error_value (parser, "Unsupported character %d in string", i);
|
gtk_css_parser_error_value (parser, "Unsupported character %d in string", i);
|
||||||
}
|
}
|
||||||
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + s[i];
|
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + s[i];
|
||||||
|
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||||
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
|
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
|
||||||
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
|
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
|
||||||
}
|
}
|
||||||
@@ -1216,14 +1255,22 @@ parse_glyphs (GtkCssParser *parser,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!gtk_css_parser_consume_integer (parser, &i) ||
|
if (!gtk_css_parser_consume_integer (parser, &i))
|
||||||
!gtk_css_parser_consume_number (parser, &d))
|
|
||||||
{
|
{
|
||||||
pango_glyph_string_free (glyph_string);
|
pango_glyph_string_free (glyph_string);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
gi.glyph = i;
|
gi.glyph = i;
|
||||||
gi.geometry.width = (int) (d * PANGO_SCALE);
|
|
||||||
|
if (gtk_css_parser_has_number (parser))
|
||||||
|
{
|
||||||
|
gtk_css_parser_consume_number (parser, &d);
|
||||||
|
gi.geometry.width = (int) (d * PANGO_SCALE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
if (gtk_css_parser_has_number (parser))
|
if (gtk_css_parser_has_number (parser))
|
||||||
{
|
{
|
||||||
@@ -2193,23 +2240,36 @@ unpack_glyphs (PangoFont *font,
|
|||||||
|
|
||||||
for (i = 0; i < glyphs->num_glyphs; i++)
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
{
|
{
|
||||||
PangoGlyph glyph = glyphs->glyphs[i].glyph;
|
PangoGlyphInfo *gi = &glyphs->glyphs[i];
|
||||||
|
|
||||||
if (glyph < PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH ||
|
if (((*(unsigned int *) &gi->attr) & GLYPH_NEEDS_WIDTH) == 0)
|
||||||
glyph >= PANGO_GLYPH_INVALID_INPUT)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
glyph = glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
|
*(unsigned int *) &gi->attr &= ~GLYPH_NEEDS_WIDTH;
|
||||||
|
|
||||||
if (ascii == NULL)
|
if (gi->glyph >= PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH &&
|
||||||
|
gi->glyph < PANGO_GLYPH_INVALID_INPUT)
|
||||||
{
|
{
|
||||||
ascii = create_ascii_glyphs (font);
|
PangoGlyph idx = gi->glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
|
||||||
if (ascii == NULL)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
glyphs->glyphs[i].glyph = ascii->glyphs[glyph].glyph;
|
if (ascii == NULL)
|
||||||
glyphs->glyphs[i].geometry.width = ascii->glyphs[glyph].geometry.width;
|
{
|
||||||
|
ascii = create_ascii_glyphs (font);
|
||||||
|
if (ascii == NULL)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gi->glyph = ascii->glyphs[idx].glyph;
|
||||||
|
gi->geometry.width = ascii->glyphs[idx].geometry.width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PangoRectangle ink_rect;
|
||||||
|
|
||||||
|
pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL);
|
||||||
|
|
||||||
|
gi->geometry.width = ink_rect.width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&ascii, pango_glyph_string_free);
|
g_clear_pointer (&ascii, pango_glyph_string_free);
|
||||||
@@ -2217,6 +2277,45 @@ unpack_glyphs (PangoFont *font,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_hint_style (GtkCssParser *parser,
|
||||||
|
Context *context,
|
||||||
|
gpointer out)
|
||||||
|
{
|
||||||
|
if (!parse_enum (parser, CAIRO_GOBJECT_TYPE_HINT_STYLE, out))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (*(cairo_hint_style_t *) out != CAIRO_HINT_STYLE_NONE &&
|
||||||
|
*(cairo_hint_style_t *) out != CAIRO_HINT_STYLE_SLIGHT &&
|
||||||
|
*(cairo_hint_style_t *) out != CAIRO_HINT_STYLE_FULL)
|
||||||
|
{
|
||||||
|
gtk_css_parser_error_value (parser, "Unsupported value for enum \"%s\"",
|
||||||
|
g_type_name (CAIRO_GOBJECT_TYPE_HINT_STYLE));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_antialias (GtkCssParser *parser,
|
||||||
|
Context *context,
|
||||||
|
gpointer out)
|
||||||
|
{
|
||||||
|
if (!parse_enum (parser, CAIRO_GOBJECT_TYPE_ANTIALIAS, out))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (*(cairo_antialias_t *) out != CAIRO_ANTIALIAS_NONE &&
|
||||||
|
*(cairo_antialias_t *) out != CAIRO_ANTIALIAS_GRAY)
|
||||||
|
{
|
||||||
|
gtk_css_parser_error_value (parser, "Unsupported value for enum \"%s\"",
|
||||||
|
g_type_name (CAIRO_GOBJECT_TYPE_ANTIALIAS));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static GskRenderNode *
|
static GskRenderNode *
|
||||||
parse_text_node (GtkCssParser *parser,
|
parse_text_node (GtkCssParser *parser,
|
||||||
Context *context)
|
Context *context)
|
||||||
@@ -2225,11 +2324,16 @@ parse_text_node (GtkCssParser *parser,
|
|||||||
graphene_point_t offset = GRAPHENE_POINT_INIT (0, 0);
|
graphene_point_t offset = GRAPHENE_POINT_INIT (0, 0);
|
||||||
GdkRGBA color = GDK_RGBA("000000");
|
GdkRGBA color = GDK_RGBA("000000");
|
||||||
PangoGlyphString *glyphs = NULL;
|
PangoGlyphString *glyphs = NULL;
|
||||||
|
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_SLIGHT;
|
||||||
|
cairo_antialias_t antialias = CAIRO_ANTIALIAS_GRAY;
|
||||||
|
PangoFont *hinted;
|
||||||
const Declaration declarations[] = {
|
const Declaration declarations[] = {
|
||||||
{ "font", parse_font, clear_font, &font },
|
{ "font", parse_font, clear_font, &font },
|
||||||
{ "offset", parse_point, NULL, &offset },
|
{ "offset", parse_point, NULL, &offset },
|
||||||
{ "color", parse_color, NULL, &color },
|
{ "color", parse_color, NULL, &color },
|
||||||
{ "glyphs", parse_glyphs, clear_glyphs, &glyphs }
|
{ "glyphs", parse_glyphs, clear_glyphs, &glyphs },
|
||||||
|
{ "hint-style", parse_hint_style, NULL, &hint_style },
|
||||||
|
{ "antialias", parse_antialias, NULL, &antialias },
|
||||||
};
|
};
|
||||||
GskRenderNode *result;
|
GskRenderNode *result;
|
||||||
|
|
||||||
@@ -2237,10 +2341,14 @@ parse_text_node (GtkCssParser *parser,
|
|||||||
|
|
||||||
if (font == NULL)
|
if (font == NULL)
|
||||||
{
|
{
|
||||||
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 11", TRUE);
|
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 15px", TRUE);
|
||||||
g_assert (font);
|
g_assert (font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hinted = gsk_reload_font (font, 1.0, CAIRO_HINT_METRICS_OFF, hint_style, antialias);
|
||||||
|
g_object_unref (font);
|
||||||
|
font = hinted;
|
||||||
|
|
||||||
if (!glyphs)
|
if (!glyphs)
|
||||||
{
|
{
|
||||||
const char *text = "Hello";
|
const char *text = "Hello";
|
||||||
@@ -2252,6 +2360,7 @@ parse_text_node (GtkCssParser *parser,
|
|||||||
for (i = 0; i < strlen (text); i++)
|
for (i = 0; i < strlen (text); i++)
|
||||||
{
|
{
|
||||||
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + text[i];
|
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + text[i];
|
||||||
|
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||||
glyphs->glyphs[i] = gi;
|
glyphs->glyphs[i] = gi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2429,39 +2538,6 @@ clear_dash (gpointer inout_array)
|
|||||||
g_clear_pointer ((GArray **) inout_array, g_array_unref);
|
g_clear_pointer ((GArray **) inout_array, g_array_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
parse_enum (GtkCssParser *parser,
|
|
||||||
GType type,
|
|
||||||
gpointer out_value)
|
|
||||||
{
|
|
||||||
GEnumClass *class;
|
|
||||||
GEnumValue *v;
|
|
||||||
char *enum_name;
|
|
||||||
|
|
||||||
enum_name = gtk_css_parser_consume_ident (parser);
|
|
||||||
if (enum_name == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
class = g_type_class_ref (type);
|
|
||||||
|
|
||||||
v = g_enum_get_value_by_nick (class, enum_name);
|
|
||||||
if (v == NULL)
|
|
||||||
{
|
|
||||||
gtk_css_parser_error_value (parser, "Unknown value \"%s\" for enum \"%s\"",
|
|
||||||
enum_name, g_type_name (type));
|
|
||||||
g_free (enum_name);
|
|
||||||
g_type_class_unref (class);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*(int*)out_value = v->value;
|
|
||||||
|
|
||||||
g_free (enum_name);
|
|
||||||
g_type_class_unref (class);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_fill_rule (GtkCssParser *parser,
|
parse_fill_rule (GtkCssParser *parser,
|
||||||
Context *context,
|
Context *context,
|
||||||
@@ -3248,6 +3324,33 @@ append_string_param (Printer *p,
|
|||||||
g_string_append_c (p->str, '\n');
|
g_string_append_c (p->str, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
enum_to_nick (GType type,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
GEnumClass *class;
|
||||||
|
GEnumValue *v;
|
||||||
|
|
||||||
|
class = g_type_class_ref (type);
|
||||||
|
v = g_enum_get_value (class, value);
|
||||||
|
g_type_class_unref (class);
|
||||||
|
|
||||||
|
return v->value_nick;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_enum_param (Printer *p,
|
||||||
|
const char *param_name,
|
||||||
|
GType type,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
_indent (p);
|
||||||
|
g_string_append_printf (p->str, "%s: ", param_name);
|
||||||
|
g_string_append (p->str, enum_to_nick (type, value));
|
||||||
|
g_string_append_c (p->str, ';');
|
||||||
|
g_string_append_c (p->str, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_vec4_param (Printer *p,
|
append_vec4_param (Printer *p,
|
||||||
const char *param_name,
|
const char *param_name,
|
||||||
@@ -3471,7 +3574,7 @@ gsk_text_node_serialize_font (GskRenderNode *node,
|
|||||||
PangoFontDescription *desc;
|
PangoFontDescription *desc;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
desc = pango_font_describe (font);
|
desc = pango_font_describe_with_absolute_size (font);
|
||||||
s = pango_font_description_to_string (desc);
|
s = pango_font_description_to_string (desc);
|
||||||
g_string_append_printf (p->str, "\"%s\"", s);
|
g_string_append_printf (p->str, "\"%s\"", s);
|
||||||
g_free (s);
|
g_free (s);
|
||||||
@@ -3515,6 +3618,37 @@ gsk_text_node_serialize_font (GskRenderNode *node,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_text_node_serialize_font_options (GskRenderNode *node,
|
||||||
|
Printer *p)
|
||||||
|
{
|
||||||
|
PangoFont *font = gsk_text_node_get_font (node);
|
||||||
|
cairo_scaled_font_t *sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||||
|
cairo_font_options_t *options;
|
||||||
|
cairo_hint_style_t hint_style;
|
||||||
|
cairo_antialias_t antialias;
|
||||||
|
|
||||||
|
options = cairo_font_options_create ();
|
||||||
|
cairo_scaled_font_get_font_options (sf, options);
|
||||||
|
hint_style = cairo_font_options_get_hint_style (options);
|
||||||
|
antialias = cairo_font_options_get_antialias (options);
|
||||||
|
cairo_font_options_destroy (options);
|
||||||
|
|
||||||
|
/* medium and full are identical in the absence of subpixel modes */
|
||||||
|
if (hint_style == CAIRO_HINT_STYLE_MEDIUM)
|
||||||
|
hint_style = CAIRO_HINT_STYLE_FULL;
|
||||||
|
|
||||||
|
if (hint_style == CAIRO_HINT_STYLE_NONE ||
|
||||||
|
hint_style == CAIRO_HINT_STYLE_FULL)
|
||||||
|
append_enum_param (p, "hint-style", CAIRO_GOBJECT_TYPE_HINT_STYLE, hint_style);
|
||||||
|
|
||||||
|
/* CAIRO_ANTIALIAS_NONE is the only value we ever emit here, since gray is the default,
|
||||||
|
* and we don't accept any other values.
|
||||||
|
*/
|
||||||
|
if (antialias == CAIRO_ANTIALIAS_NONE)
|
||||||
|
append_enum_param (p, "antialias", CAIRO_GOBJECT_TYPE_ANTIALIAS, antialias);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||||
GString *p)
|
GString *p)
|
||||||
@@ -3596,33 +3730,6 @@ gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
|||||||
pango_glyph_string_free (ascii);
|
pango_glyph_string_free (ascii);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
enum_to_nick (GType type,
|
|
||||||
int value)
|
|
||||||
{
|
|
||||||
GEnumClass *class;
|
|
||||||
GEnumValue *v;
|
|
||||||
|
|
||||||
class = g_type_class_ref (type);
|
|
||||||
v = g_enum_get_value (class, value);
|
|
||||||
g_type_class_unref (class);
|
|
||||||
|
|
||||||
return v->value_nick;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
append_enum_param (Printer *p,
|
|
||||||
const char *param_name,
|
|
||||||
GType type,
|
|
||||||
int value)
|
|
||||||
{
|
|
||||||
_indent (p);
|
|
||||||
g_string_append_printf (p->str, "%s: ", param_name);
|
|
||||||
g_string_append (p->str, enum_to_nick (type, value));
|
|
||||||
g_string_append_c (p->str, ';');
|
|
||||||
g_string_append_c (p->str, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_path_param (Printer *p,
|
append_path_param (Printer *p,
|
||||||
const char *param_name,
|
const char *param_name,
|
||||||
@@ -4087,6 +4194,8 @@ render_node_print (Printer *p,
|
|||||||
if (!graphene_point_equal (offset, graphene_point_zero ()))
|
if (!graphene_point_equal (offset, graphene_point_zero ()))
|
||||||
append_point_param (p, "offset", offset);
|
append_point_param (p, "offset", offset);
|
||||||
|
|
||||||
|
gsk_text_node_serialize_font_options (node, p);
|
||||||
|
|
||||||
end_node (p);
|
end_node (p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4357,6 +4466,8 @@ render_node_print (Printer *p,
|
|||||||
start_node (p, "subsurface", node_name);
|
start_node (p, "subsurface", node_name);
|
||||||
|
|
||||||
append_node_param (p, "child", gsk_subsurface_node_get_child (node));
|
append_node_param (p, "child", gsk_subsurface_node_get_child (node));
|
||||||
|
|
||||||
|
end_node (p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <graphene.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
gsk_vec2_get_x (const graphene_vec2_t *v)
|
||||||
|
{
|
||||||
|
return graphene_simd4f_get_x (v->__graphene_private_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
gsk_vec2_get_y (const graphene_vec2_t *v)
|
||||||
|
{
|
||||||
|
return graphene_simd4f_get_y (v->__graphene_private_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline graphene_vec2_t *
|
||||||
|
gsk_vec2_init (graphene_vec2_t *v,
|
||||||
|
float x,
|
||||||
|
float y)
|
||||||
|
{
|
||||||
|
v->__graphene_private_value = graphene_simd4f_init (x, y, 0.f, 0.f);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gsk_vec2_multiply (const graphene_vec2_t *a,
|
||||||
|
const graphene_vec2_t *b,
|
||||||
|
graphene_vec2_t *res)
|
||||||
|
{
|
||||||
|
res->__graphene_private_value = graphene_simd4f_mul (a->__graphene_private_value,
|
||||||
|
b->__graphene_private_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
gsk_vec2_equal (const graphene_vec2_t *v1,
|
||||||
|
const graphene_vec2_t *v2)
|
||||||
|
{
|
||||||
|
return graphene_simd4f_cmp_eq (v1->__graphene_private_value, v2->__graphene_private_value);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "gtkatspicontextprivate.h"
|
#include "gtkatspicontextprivate.h"
|
||||||
|
|
||||||
#include "gtkaccessibleprivate.h"
|
#include "gtkaccessibleprivate.h"
|
||||||
#include "gtkaccessibletext-private.h"
|
#include "gtkaccessibletextprivate.h"
|
||||||
|
|
||||||
#include "gtkatspiactionprivate.h"
|
#include "gtkatspiactionprivate.h"
|
||||||
#include "gtkatspieditabletextprivate.h"
|
#include "gtkatspieditabletextprivate.h"
|
||||||
@@ -771,7 +771,7 @@ emit_text_selection_changed (GtkAtSpiContext *self,
|
|||||||
"org.a11y.atspi.Event.Object",
|
"org.a11y.atspi.Event.Object",
|
||||||
"TextCaretMoved",
|
"TextCaretMoved",
|
||||||
g_variant_new ("(siiva{sv})",
|
g_variant_new ("(siiva{sv})",
|
||||||
"", cursor_position, 0, g_variant_new_string (""), NULL),
|
"", cursor_position, 0, g_variant_new_int32 (0), NULL),
|
||||||
NULL);
|
NULL);
|
||||||
else
|
else
|
||||||
g_dbus_connection_emit_signal (self->connection,
|
g_dbus_connection_emit_signal (self->connection,
|
||||||
@@ -1590,7 +1590,7 @@ gtk_at_spi_context_update_caret_position (GtkATContext *context)
|
|||||||
"",
|
"",
|
||||||
(int) offset,
|
(int) offset,
|
||||||
0,
|
0,
|
||||||
g_variant_new_string (""),
|
g_variant_new_int32 (0),
|
||||||
NULL),
|
NULL),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,8 +418,8 @@ gtk_at_spi_socket_embed (GtkAtSpiSocket *self,
|
|||||||
* usually done through a side channel with the remote side, for
|
* usually done through a side channel with the remote side, for
|
||||||
* example using sockets, or reading the output of a subprocess.
|
* example using sockets, or reading the output of a subprocess.
|
||||||
*
|
*
|
||||||
* The remote accessible object at @object_path must be a must
|
* The remote accessible object at @object_path must support
|
||||||
* have an `org.a11y.atspi.Socket` interface with the `Embedded()`
|
* the `org.a11y.atspi.Socket` interface with the `Embedded()`
|
||||||
* method.
|
* method.
|
||||||
*
|
*
|
||||||
* This constructor can fail, most notably if the accessibility
|
* This constructor can fail, most notably if the accessibility
|
||||||
@@ -463,7 +463,7 @@ gtk_at_spi_socket_get_bus_name (GtkAtSpiSocket *self)
|
|||||||
* gtk_at_spi_socket_get_object_path:
|
* gtk_at_spi_socket_get_object_path:
|
||||||
* @self: a #GtkAtSpiSocket
|
* @self: a #GtkAtSpiSocket
|
||||||
*
|
*
|
||||||
* Retrieves the object path of the remove accessible object that
|
* Retrieves the object path of the remote accessible object that
|
||||||
* the socket is connected to.
|
* the socket is connected to.
|
||||||
*
|
*
|
||||||
* Returns: (transfer none): the object path of the socket remote
|
* Returns: (transfer none): the object path of the socket remote
|
||||||
|
|||||||
+102
-27
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "a11y/atspi/atspi-text.h"
|
#include "a11y/atspi/atspi-text.h"
|
||||||
|
|
||||||
|
#include "gtkaccessibletextprivate.h"
|
||||||
#include "gtkatcontextprivate.h"
|
#include "gtkatcontextprivate.h"
|
||||||
#include "gtkdebug.h"
|
#include "gtkdebug.h"
|
||||||
#include "gtkeditable.h"
|
#include "gtkeditable.h"
|
||||||
@@ -41,7 +42,6 @@
|
|||||||
#include "gtkspinbuttonprivate.h"
|
#include "gtkspinbuttonprivate.h"
|
||||||
#include "gtktextbufferprivate.h"
|
#include "gtktextbufferprivate.h"
|
||||||
#include "gtktextviewprivate.h"
|
#include "gtktextviewprivate.h"
|
||||||
#include "gtkaccessibletext-private.h"
|
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
@@ -222,19 +222,72 @@ accessible_text_handle_method (GDBusConnection *connection,
|
|||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
gboolean include_defaults = FALSE;
|
||||||
|
int offset;
|
||||||
|
gsize n_ranges = 0;
|
||||||
|
GtkAccessibleTextRange *ranges = NULL;
|
||||||
|
int start, end;
|
||||||
|
char **attr_names = NULL;
|
||||||
|
char **attr_values = NULL;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||||
|
|
||||||
|
res = gtk_accessible_text_get_attributes_run (accessible_text,
|
||||||
|
offset,
|
||||||
|
include_defaults,
|
||||||
|
&n_ranges,
|
||||||
|
&ranges,
|
||||||
|
&attr_names,
|
||||||
|
&attr_values);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
/* No attributes */
|
||||||
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, 0, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; attr_names[i] != NULL; i++)
|
||||||
|
g_variant_builder_add (&builder, "{ss}", attr_names[i], attr_values[i]);
|
||||||
|
|
||||||
|
start = 0;
|
||||||
|
end = G_MAXINT;
|
||||||
|
for (unsigned i = 0; i < n_ranges; i++)
|
||||||
|
{
|
||||||
|
start = MAX (start, ranges[i].start);
|
||||||
|
end = MIN (end, start + ranges[i].length);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||||
|
|
||||||
|
g_clear_pointer (&ranges, g_free);
|
||||||
|
g_strfreev (attr_names);
|
||||||
|
g_strfreev (attr_values);
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
||||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
char **names, **values;
|
||||||
|
|
||||||
|
gtk_accessible_text_get_default_attributes (accessible_text, &names, &values);
|
||||||
|
|
||||||
|
for (unsigned i = 0; names[i] != NULL; i++)
|
||||||
|
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||||
|
|
||||||
|
g_strfreev (names);
|
||||||
|
g_strfreev (values);
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
||||||
{
|
{
|
||||||
gsize n_ranges;
|
gsize n_ranges;
|
||||||
GtkAccessibleTextRange *ranges = NULL;
|
GtkAccessibleTextRange *ranges = NULL;
|
||||||
|
|
||||||
gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges);
|
if (!gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges))
|
||||||
|
n_ranges = 0;
|
||||||
|
|
||||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", (int)n_ranges));
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", (int)n_ranges));
|
||||||
|
|
||||||
@@ -248,7 +301,8 @@ accessible_text_handle_method (GDBusConnection *connection,
|
|||||||
|
|
||||||
g_variant_get (parameters, "(i)", &num);
|
g_variant_get (parameters, "(i)", &num);
|
||||||
|
|
||||||
gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges);
|
if (!gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges))
|
||||||
|
n_ranges = 0;
|
||||||
|
|
||||||
if (num < 0 || num >= n_ranges)
|
if (num < 0 || num >= n_ranges)
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Not a valid selection: %d", num);
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Not a valid selection: %d", num);
|
||||||
@@ -1056,15 +1110,20 @@ gtk_editable_get_text_widget (GtkWidget *widget)
|
|||||||
{
|
{
|
||||||
if (GTK_IS_EDITABLE (widget))
|
if (GTK_IS_EDITABLE (widget))
|
||||||
{
|
{
|
||||||
GtkEditable *delegate;
|
GtkEditable *editable;
|
||||||
|
guint redirects = 0;
|
||||||
|
|
||||||
delegate = gtk_editable_get_delegate (GTK_EDITABLE (widget));
|
editable = GTK_EDITABLE (widget);
|
||||||
|
|
||||||
if (GTK_IS_TEXT (delegate))
|
do {
|
||||||
return GTK_TEXT (delegate);
|
if (GTK_IS_TEXT (editable))
|
||||||
|
return GTK_TEXT (editable);
|
||||||
|
|
||||||
if (GTK_IS_TEXT (widget))
|
if (++redirects >= 6)
|
||||||
return GTK_TEXT (widget);
|
g_assert_not_reached ();
|
||||||
|
|
||||||
|
editable = gtk_editable_get_delegate (editable);
|
||||||
|
} while (editable != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1609,63 +1668,79 @@ text_view_handle_method (GDBusConnection *connection,
|
|||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetAttributes") == 0)
|
else if (g_strcmp0 (method_name, "GetAttributes") == 0)
|
||||||
{
|
{
|
||||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
|
||||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
GHashTable *attrs;
|
||||||
|
GHashTableIter iter;
|
||||||
int offset;
|
int offset;
|
||||||
int start, end;
|
int start, end;
|
||||||
|
gpointer key, value;
|
||||||
|
|
||||||
g_variant_get (parameters, "(i)", &offset);
|
g_variant_get (parameters, "(i)", &offset);
|
||||||
|
|
||||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, FALSE, &start, &end);
|
||||||
|
g_hash_table_iter_init (&iter, attrs);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
|
g_variant_builder_add (&builder, "{ss}", key, value != NULL ? value : "");
|
||||||
|
|
||||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||||
|
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||||
{
|
{
|
||||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
|
||||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
|
||||||
int offset;
|
int offset;
|
||||||
const char *name;
|
const char *name;
|
||||||
int start, end;
|
int start, end;
|
||||||
GVariant *attrs;
|
|
||||||
const char *val;
|
const char *val;
|
||||||
|
GHashTable *attrs;
|
||||||
|
|
||||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||||
|
|
||||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, FALSE, &start, &end);
|
||||||
|
val = g_hash_table_lookup (attrs, name);
|
||||||
attrs = g_variant_builder_end (&builder);
|
if (val == NULL)
|
||||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
|
||||||
val = "";
|
val = "";
|
||||||
|
|
||||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||||
g_variant_unref (attrs);
|
g_hash_table_unref (attrs);
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||||
{
|
{
|
||||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
|
||||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||||
int offset;
|
int offset;
|
||||||
gboolean include_defaults;
|
gboolean include_defaults;
|
||||||
int start, end;
|
int start, end;
|
||||||
|
GHashTable *attrs;
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
|
||||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||||
|
|
||||||
if (include_defaults)
|
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, include_defaults, &start, &end);
|
||||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), &builder);
|
g_hash_table_iter_init (&iter, attrs);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
g_variant_builder_add (&builder, "{ss}", key, value != NULL ? value : "");
|
||||||
|
|
||||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||||
|
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
||||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||||
{
|
{
|
||||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
GHashTable *attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
|
||||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), &builder);
|
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), attrs);
|
||||||
|
g_hash_table_iter_init (&iter, attrs);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
|
g_variant_builder_add (&builder, "{ss}", key, value != NULL ? value : "");
|
||||||
|
|
||||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||||
|
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
}
|
}
|
||||||
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,101 +23,6 @@
|
|||||||
#include "gtktextviewprivate.h"
|
#include "gtktextviewprivate.h"
|
||||||
#include "gtkpangoprivate.h"
|
#include "gtkpangoprivate.h"
|
||||||
|
|
||||||
void
|
|
||||||
gtk_text_view_add_default_attributes (GtkTextView *view,
|
|
||||||
GVariantBuilder *builder)
|
|
||||||
{
|
|
||||||
GtkTextAttributes *text_attrs;
|
|
||||||
PangoFontDescription *font;
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
text_attrs = gtk_text_view_get_default_attributes (view);
|
|
||||||
|
|
||||||
font = text_attrs->font;
|
|
||||||
|
|
||||||
if (font)
|
|
||||||
{
|
|
||||||
char **names, **values;
|
|
||||||
|
|
||||||
gtk_pango_get_font_attributes (font, &names, &values);
|
|
||||||
|
|
||||||
for (unsigned i = 0; names[i] != NULL; i++)
|
|
||||||
g_variant_builder_add (builder, "{ss}", names[i], values[i]);
|
|
||||||
|
|
||||||
g_strfreev (names);
|
|
||||||
g_strfreev (values);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_variant_builder_add (builder, "{ss}", "justification",
|
|
||||||
gtk_justification_to_string (text_attrs->justification));
|
|
||||||
g_variant_builder_add (builder, "{ss}", "direction",
|
|
||||||
gtk_text_direction_to_string (text_attrs->direction));
|
|
||||||
g_variant_builder_add (builder, "{ss}", "wrap-mode",
|
|
||||||
gtk_wrap_mode_to_string (text_attrs->wrap_mode));
|
|
||||||
g_variant_builder_add (builder, "{ss}", "editable",
|
|
||||||
text_attrs->editable ? "true" : "false");
|
|
||||||
g_variant_builder_add (builder, "{ss}", "invisible",
|
|
||||||
text_attrs->invisible ? "true" : "false");
|
|
||||||
g_variant_builder_add (builder, "{ss}", "bg-full-height",
|
|
||||||
text_attrs->bg_full_height ? "true" : "false");
|
|
||||||
g_variant_builder_add (builder, "{ss}", "strikethrough",
|
|
||||||
text_attrs->appearance.strikethrough ? "true" : "false");
|
|
||||||
g_variant_builder_add (builder, "{ss}", "underline",
|
|
||||||
pango_underline_to_string (text_attrs->appearance.underline));
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%u,%u,%u",
|
|
||||||
(guint)(text_attrs->appearance.bg_rgba->red * 65535),
|
|
||||||
(guint)(text_attrs->appearance.bg_rgba->green * 65535),
|
|
||||||
(guint)(text_attrs->appearance.bg_rgba->blue * 65535));
|
|
||||||
g_variant_builder_add (builder, "{ss}", "bg-color", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%u,%u,%u",
|
|
||||||
(guint)(text_attrs->appearance.fg_rgba->red * 65535),
|
|
||||||
(guint)(text_attrs->appearance.fg_rgba->green * 65535),
|
|
||||||
(guint)(text_attrs->appearance.fg_rgba->blue * 65535));
|
|
||||||
g_variant_builder_add (builder, "{ss}", "bg-color", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%g", text_attrs->font_scale);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "scale", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup ((gchar *)(text_attrs->language));
|
|
||||||
g_variant_builder_add (builder, "{ss}", "language", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->appearance.rise);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "rise", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->pixels_inside_wrap);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "pixels-inside-wrap", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->pixels_below_lines);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "pixels-below-lines", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->pixels_above_lines);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "pixels-above-lines", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->indent);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "indent", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->left_margin);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "left-margin", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
value = g_strdup_printf ("%i", text_attrs->right_margin);
|
|
||||||
g_variant_builder_add (builder, "{ss}", "right-margin", value);
|
|
||||||
g_free (value);
|
|
||||||
|
|
||||||
gtk_text_attributes_unref (text_attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
gtk_text_view_get_text_before (GtkTextView *view,
|
gtk_text_view_get_text_before (GtkTextView *view,
|
||||||
int offset,
|
int offset,
|
||||||
|
|||||||
@@ -23,9 +23,6 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void gtk_text_view_add_default_attributes (GtkTextView *view,
|
|
||||||
GVariantBuilder *builder);
|
|
||||||
|
|
||||||
char *gtk_text_view_get_text_before (GtkTextView *view,
|
char *gtk_text_view_get_text_before (GtkTextView *view,
|
||||||
int offset,
|
int offset,
|
||||||
AtspiTextBoundaryType boundary_type,
|
AtspiTextBoundaryType boundary_type,
|
||||||
|
|||||||
@@ -370,6 +370,7 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object,
|
|||||||
else
|
else
|
||||||
texture = NULL;
|
texture = NULL;
|
||||||
take_image_definition (cellpixbuf, gtk_image_definition_new_paintable (GDK_PAINTABLE (texture)));
|
take_image_definition (cellpixbuf, gtk_image_definition_new_paintable (GDK_PAINTABLE (texture)));
|
||||||
|
g_clear_object (&texture);
|
||||||
break;
|
break;
|
||||||
case PROP_PIXBUF_EXPANDER_OPEN:
|
case PROP_PIXBUF_EXPANDER_OPEN:
|
||||||
g_clear_object (&priv->pixbuf_expander_open);
|
g_clear_object (&priv->pixbuf_expander_open);
|
||||||
|
|||||||
Binary file not shown.
@@ -24,9 +24,14 @@
|
|||||||
|
|
||||||
/* The format of the generated data is: a(aussasasu).
|
/* The format of the generated data is: a(aussasasu).
|
||||||
* Each member of the array has the following fields:
|
* Each member of the array has the following fields:
|
||||||
* au - sequence of unicode codepoints. If the
|
* au - sequence of unicode codepoints, including the emoji presentation
|
||||||
* sequence contains a 0, it marks the point
|
* selector (FE0F) where necessary. skin tone variations are represented
|
||||||
* where skin tone modifiers should be inserted
|
* with either the first tone code point (1F3FB) or 0. the choice indicates
|
||||||
|
* the handling of the generic sequence (i.e., no tone), which may have a
|
||||||
|
* default text presentation and thus require the emoji presentation
|
||||||
|
* selector (unlike sequences with a tone, which are always presented as
|
||||||
|
* emojis). 0 indicates the text case, that is, replace this code point
|
||||||
|
* with FE0F, while 1F3FB indicates this code point should be omitted.
|
||||||
* s - name in english, e.g. "man worker"
|
* s - name in english, e.g. "man worker"
|
||||||
* s - name in locale
|
* s - name in locale
|
||||||
* as - keywords in english, e.g. "man", "worker"
|
* as - keywords in english, e.g. "man", "worker"
|
||||||
@@ -48,7 +53,8 @@
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
parse_code (GVariantBuilder *b,
|
parse_code (GVariantBuilder *b,
|
||||||
const char *code)
|
const char *code,
|
||||||
|
gboolean needs_presentation_selector)
|
||||||
{
|
{
|
||||||
g_auto(GStrv) strv = NULL;
|
g_auto(GStrv) strv = NULL;
|
||||||
int j;
|
int j;
|
||||||
@@ -66,11 +72,31 @@ parse_code (GVariantBuilder *b,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (0x1f3fb <= u && u <= 0x1f3ff)
|
if (0x1f3fb <= u && u <= 0x1f3ff)
|
||||||
g_variant_builder_add (b, "u", 0);
|
{
|
||||||
|
if (needs_presentation_selector)
|
||||||
|
{
|
||||||
|
if (strv[j+1])
|
||||||
|
{
|
||||||
|
g_error ("unexpected inner skin tone in default-text generic sequence: %s\n", code);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
g_variant_builder_add (b, "u", 0);
|
||||||
|
needs_presentation_selector = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_variant_builder_add (b, "u", 0x1f3fb);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
g_variant_builder_add (b, "u", u);
|
{
|
||||||
|
g_variant_builder_add (b, "u", u);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needs_presentation_selector)
|
||||||
|
g_variant_builder_add (b, "u", 0xfe0f);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +146,6 @@ main (int argc, char *argv[])
|
|||||||
array_en = json_node_get_array (root_en);
|
array_en = json_node_get_array (root_en);
|
||||||
length_en = json_array_get_length (array_en);
|
length_en = json_array_get_length (array_en);
|
||||||
|
|
||||||
|
|
||||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)"));
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)"));
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
@@ -133,13 +158,21 @@ main (int argc, char *argv[])
|
|||||||
const char *name;
|
const char *name;
|
||||||
const char *name_en;
|
const char *name_en;
|
||||||
char *code;
|
char *code;
|
||||||
|
const char *text;
|
||||||
|
gboolean needs_presentation_selector;
|
||||||
|
|
||||||
if (!json_object_has_member (obj, "group"))
|
if (!json_object_has_member (obj, "group"))
|
||||||
continue;
|
continue;
|
||||||
if (!json_object_has_member (obj_en, "group"))
|
if (!json_object_has_member (obj_en, "group"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
group = json_object_get_int_member (obj, "group");
|
group = json_object_get_int_member (obj, "group");
|
||||||
name = json_object_get_string_member (obj, "label");
|
name = json_object_get_string_member (obj, "label");
|
||||||
name_en = json_object_get_string_member (obj_en, "label");
|
name_en = json_object_get_string_member (obj_en, "label");
|
||||||
|
|
||||||
|
if (g_str_has_suffix (name_en, "skin tone"))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (json_object_has_member (obj, "skins") && json_object_has_member (obj_en, "skins"))
|
if (json_object_has_member (obj, "skins") && json_object_has_member (obj_en, "skins"))
|
||||||
{
|
{
|
||||||
JsonArray *a2 = json_object_get_array_member (obj, "skins");
|
JsonArray *a2 = json_object_get_array_member (obj, "skins");
|
||||||
@@ -151,9 +184,12 @@ main (int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
|
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
|
||||||
}
|
}
|
||||||
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
|
|
||||||
|
|
||||||
if (!parse_code (&b1, code))
|
text = json_object_get_string_member (obj, "text");
|
||||||
|
needs_presentation_selector = *text != '\0' && json_object_get_int_member (obj, "type") == 0;
|
||||||
|
|
||||||
|
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
|
||||||
|
if (!parse_code (&b1, code, needs_presentation_selector))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));
|
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+167
-1
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "gtkaccessibletext-private.h"
|
#include "gtkaccessibletextprivate.h"
|
||||||
|
|
||||||
#include "gtkatcontextprivate.h"
|
#include "gtkatcontextprivate.h"
|
||||||
|
|
||||||
@@ -63,6 +63,15 @@ gtk_accessible_text_default_get_attributes (GtkAccessibleText *self,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_accessible_text_default_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
*attribute_names = NULL;
|
||||||
|
*attribute_values = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_accessible_text_default_init (GtkAccessibleTextInterface *iface)
|
gtk_accessible_text_default_init (GtkAccessibleTextInterface *iface)
|
||||||
{
|
{
|
||||||
@@ -71,6 +80,7 @@ gtk_accessible_text_default_init (GtkAccessibleTextInterface *iface)
|
|||||||
iface->get_caret_position = gtk_accessible_text_default_get_caret_position;
|
iface->get_caret_position = gtk_accessible_text_default_get_caret_position;
|
||||||
iface->get_selection = gtk_accessible_text_default_get_selection;
|
iface->get_selection = gtk_accessible_text_default_get_selection;
|
||||||
iface->get_attributes = gtk_accessible_text_default_get_attributes;
|
iface->get_attributes = gtk_accessible_text_default_get_attributes;
|
||||||
|
iface->get_default_attributes = gtk_accessible_text_default_get_default_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GBytes *
|
static GBytes *
|
||||||
@@ -155,12 +165,16 @@ gtk_accessible_text_get_contents_at (GtkAccessibleText *self,
|
|||||||
unsigned int *start,
|
unsigned int *start,
|
||||||
unsigned int *end)
|
unsigned int *end)
|
||||||
{
|
{
|
||||||
|
static const char empty[] = {0};
|
||||||
GBytes *bytes;
|
GBytes *bytes;
|
||||||
|
|
||||||
g_return_val_if_fail (GTK_IS_ACCESSIBLE_TEXT (self), NULL);
|
g_return_val_if_fail (GTK_IS_ACCESSIBLE_TEXT (self), NULL);
|
||||||
|
|
||||||
bytes = GTK_ACCESSIBLE_TEXT_GET_IFACE (self)->get_contents_at (self, offset, granularity, start, end);
|
bytes = GTK_ACCESSIBLE_TEXT_GET_IFACE (self)->get_contents_at (self, offset, granularity, start, end);
|
||||||
|
|
||||||
|
if (bytes == NULL)
|
||||||
|
return g_bytes_new_static (empty, sizeof empty);
|
||||||
|
|
||||||
return nul_terminate_contents (bytes);
|
return nul_terminate_contents (bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +274,158 @@ gtk_accessible_text_get_attributes (GtkAccessibleText *self,
|
|||||||
attribute_values);
|
attribute_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gtk_accessible_text_get_default_attributes:
|
||||||
|
* @self: the accessible object
|
||||||
|
* @attribute_names: (out) (array zero-terminated=1) (element-type utf8) (optional) (transfer full):
|
||||||
|
* the names of the attributes inside the accessible object
|
||||||
|
* @attribute_values: (out) (array zero-terminated=1) (element-type utf8) (optional) (transfer full):
|
||||||
|
* the values of the attributes inside the accessible object
|
||||||
|
*
|
||||||
|
* Retrieves the default text attributes inside the accessible object.
|
||||||
|
*
|
||||||
|
* Each attribute is composed by:
|
||||||
|
*
|
||||||
|
* - a name, typically in the form of a reverse DNS identifier
|
||||||
|
* - a value
|
||||||
|
*
|
||||||
|
* If this function returns true, `n_attributes` will be set to a value
|
||||||
|
* greater than or equal to one, @ranges will be set to a newly
|
||||||
|
* allocated array of [struct#Gtk.AccessibleTextRange] which should
|
||||||
|
* be freed with g_free(), @attribute_names and @attribute_values
|
||||||
|
* will be set to string arrays that should be freed with g_strfreev().
|
||||||
|
*
|
||||||
|
* Since: 4.14
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gtk_accessible_text_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GTK_IS_ACCESSIBLE_TEXT (self));
|
||||||
|
|
||||||
|
GTK_ACCESSIBLE_TEXT_GET_IFACE (self)->get_default_attributes (self,
|
||||||
|
attribute_names,
|
||||||
|
attribute_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gtk_accessible_text_get_attributes_run:
|
||||||
|
* @self: the accessible object
|
||||||
|
* @offset: the offset, in characters
|
||||||
|
* @include_defaults: whether to include the default attributes in the
|
||||||
|
* returned array
|
||||||
|
* @n_ranges: (out): the number of attributes
|
||||||
|
* @ranges: (out) (array length=n_attributes) (optional): the ranges of the attributes
|
||||||
|
* inside the accessible object
|
||||||
|
* @attribute_names: (out) (array zero-terminated=1) (element-type utf8) (optional) (transfer full):
|
||||||
|
* the names of the attributes inside the accessible object
|
||||||
|
* @attribute_values: (out) (array zero-terminated=1) (element-type utf8) (optional) (transfer full):
|
||||||
|
* the values of the attributes inside the accessible object
|
||||||
|
*
|
||||||
|
* Retrieves the text attributes inside the accessible object.
|
||||||
|
*
|
||||||
|
* Each attribute is composed by:
|
||||||
|
*
|
||||||
|
* - a range
|
||||||
|
* - a name, typically in the form of a reverse DNS identifier
|
||||||
|
* - a value
|
||||||
|
*
|
||||||
|
* If this function returns true, `n_ranges` will be set to a value
|
||||||
|
* greater than or equal to one, @ranges will be set to a newly
|
||||||
|
* allocated array of [struct#Gtk.AccessibleTextRange] which should
|
||||||
|
* be freed with g_free(), @attribute_names and @attribute_values
|
||||||
|
* will be set to string arrays that should be freed with g_strfreev().
|
||||||
|
*
|
||||||
|
* Returns: true if the accessible object has at least an attribute,
|
||||||
|
* and false otherwise
|
||||||
|
*
|
||||||
|
* Since: 4.14
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gtk_accessible_text_get_attributes_run (GtkAccessibleText *self,
|
||||||
|
unsigned int offset,
|
||||||
|
gboolean include_defaults,
|
||||||
|
gsize *n_ranges,
|
||||||
|
GtkAccessibleTextRange **ranges,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
GHashTable *attrs;
|
||||||
|
GHashTableIter attr_iter;
|
||||||
|
gpointer key, value;
|
||||||
|
char **attr_names, **attr_values;
|
||||||
|
gboolean res;
|
||||||
|
GStrvBuilder *names_builder;
|
||||||
|
GStrvBuilder *values_builder;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_ACCESSIBLE_TEXT (self), FALSE);
|
||||||
|
|
||||||
|
attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
|
if (include_defaults)
|
||||||
|
{
|
||||||
|
gtk_accessible_text_get_default_attributes (self,
|
||||||
|
&attr_names,
|
||||||
|
&attr_values);
|
||||||
|
|
||||||
|
for (unsigned i = 0; attr_names[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
g_hash_table_insert (attrs,
|
||||||
|
g_steal_pointer (&attr_names[i]),
|
||||||
|
g_steal_pointer (&attr_values[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (attr_names);
|
||||||
|
g_free (attr_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = gtk_accessible_text_get_attributes (self,
|
||||||
|
offset,
|
||||||
|
n_ranges,
|
||||||
|
ranges,
|
||||||
|
&attr_names,
|
||||||
|
&attr_values);
|
||||||
|
|
||||||
|
/* If there are no attributes, we can bail out early */
|
||||||
|
if (!res && !include_defaults)
|
||||||
|
{
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
|
*attribute_names = NULL;
|
||||||
|
*attribute_values = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The text attributes override the default ones */
|
||||||
|
for (unsigned i = 0; i < *n_ranges; i++)
|
||||||
|
{
|
||||||
|
g_hash_table_insert (attrs,
|
||||||
|
g_steal_pointer (&attr_names[i]),
|
||||||
|
g_steal_pointer (&attr_values[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (attr_names);
|
||||||
|
g_free (attr_values);
|
||||||
|
|
||||||
|
names_builder = g_strv_builder_new ();
|
||||||
|
values_builder = g_strv_builder_new ();
|
||||||
|
g_hash_table_iter_init (&attr_iter, attrs);
|
||||||
|
while (g_hash_table_iter_next (&attr_iter, &key, &value))
|
||||||
|
{
|
||||||
|
g_strv_builder_add (names_builder, key);
|
||||||
|
g_strv_builder_add (values_builder, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
*attribute_names = g_strv_builder_end (names_builder);
|
||||||
|
*attribute_values = g_strv_builder_end (values_builder);
|
||||||
|
|
||||||
|
g_strv_builder_unref (names_builder);
|
||||||
|
g_strv_builder_unref (values_builder);
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gtk_accessible_text_update_caret_position:
|
* gtk_accessible_text_update_caret_position:
|
||||||
* @self: the accessible object
|
* @self: the accessible object
|
||||||
|
|||||||
@@ -228,6 +228,33 @@ struct _GtkAccessibleTextInterface
|
|||||||
GtkAccessibleTextRange **ranges,
|
GtkAccessibleTextRange **ranges,
|
||||||
char ***attribute_names,
|
char ***attribute_names,
|
||||||
char ***attribute_values);
|
char ***attribute_values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GtkAccessibleTextInterface::get_default_attributes:
|
||||||
|
* @self: the accessible object
|
||||||
|
* @attribute_names: (out) (array zero-terminated=1) (optional) (transfer full): the
|
||||||
|
* names of the default attributes inside the accessible object
|
||||||
|
* @attribute_values: (out) (array zero-terminated=1) (optional) (transfer full): the
|
||||||
|
* values of the default attributes inside the accessible object
|
||||||
|
*
|
||||||
|
* Retrieves the default text attributes inside the accessible object.
|
||||||
|
*
|
||||||
|
* Each attribute is composed by:
|
||||||
|
*
|
||||||
|
* - a name
|
||||||
|
* - a value
|
||||||
|
*
|
||||||
|
* It is left to the implementation to determine the serialization format
|
||||||
|
* of the value to a string.
|
||||||
|
*
|
||||||
|
* GTK provides support for various text attribute names and values, but
|
||||||
|
* implementations of this interface are free to add their own attributes.
|
||||||
|
*
|
||||||
|
* Since: 4.14
|
||||||
|
*/
|
||||||
|
void (* get_default_attributes) (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values);
|
||||||
};
|
};
|
||||||
|
|
||||||
GDK_AVAILABLE_IN_4_14
|
GDK_AVAILABLE_IN_4_14
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* gtkaccessibletext-private.h: Private definitions for GtkAccessibleText
|
/* gtkaccessibletextprivate.h: Private definitions for GtkAccessibleText
|
||||||
*
|
*
|
||||||
* SPDX-FileCopyrightText: 2023 Emmanuele Bassi
|
* SPDX-FileCopyrightText: 2023 Emmanuele Bassi
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
@@ -37,4 +37,19 @@ gtk_accessible_text_get_attributes (GtkAccessibleText *self,
|
|||||||
GtkAccessibleTextRange **ranges,
|
GtkAccessibleTextRange **ranges,
|
||||||
char ***attribute_names,
|
char ***attribute_names,
|
||||||
char ***attribute_values);
|
char ***attribute_values);
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_accessible_text_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_accessible_text_get_attributes_run (GtkAccessibleText *self,
|
||||||
|
unsigned int offset,
|
||||||
|
gboolean include_defaults,
|
||||||
|
gsize *n_ranges,
|
||||||
|
GtkAccessibleTextRange **ranges,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
+19
-3
@@ -1390,9 +1390,25 @@ gtk_at_context_get_text_accumulate (GtkATContext *self,
|
|||||||
{
|
{
|
||||||
const char *text = gtk_widget_get_tooltip_text (GTK_WIDGET (self->accessible));
|
const char *text = gtk_widget_get_tooltip_text (GTK_WIDGET (self->accessible));
|
||||||
if (text && not_just_space (text))
|
if (text && not_just_space (text))
|
||||||
if (!check_duplicates || ((property == GTK_ACCESSIBLE_PROPERTY_LABEL && strcmp(text, gtk_at_context_get_description_internal (self, FALSE)) != 0)
|
{
|
||||||
|| (property == GTK_ACCESSIBLE_PROPERTY_DESCRIPTION && strcmp(text, gtk_at_context_get_name_internal (self, FALSE)) != 0)))
|
gboolean append = !check_duplicates;
|
||||||
append_with_space (res, text);
|
|
||||||
|
if (!append)
|
||||||
|
{
|
||||||
|
char *description = gtk_at_context_get_description_internal (self, FALSE);
|
||||||
|
char *name = gtk_at_context_get_name_internal (self, FALSE);
|
||||||
|
|
||||||
|
append =
|
||||||
|
(property == GTK_ACCESSIBLE_PROPERTY_LABEL && strcmp (text, description) != 0) ||
|
||||||
|
(property == GTK_ACCESSIBLE_PROPERTY_DESCRIPTION && strcmp (text, name) != 0);
|
||||||
|
|
||||||
|
g_free (description);
|
||||||
|
g_free (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
append_with_space (res, text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+53
-3
@@ -99,9 +99,7 @@
|
|||||||
* Objects are described by `<object>` elements, which can contain
|
* Objects are described by `<object>` elements, which can contain
|
||||||
* `<property>` elements to set properties, `<signal>` elements which
|
* `<property>` elements to set properties, `<signal>` elements which
|
||||||
* connect signals to handlers, and `<child>` elements, which describe
|
* connect signals to handlers, and `<child>` elements, which describe
|
||||||
* child objects (most often widgets inside a container, but also e.g.
|
* child objects.
|
||||||
* actions in an action group, or columns in a tree model). A `<child>`
|
|
||||||
* element contains an `<object>` element which describes the child object.
|
|
||||||
*
|
*
|
||||||
* Typically, the specific kind of object represented by an `<object>`
|
* Typically, the specific kind of object represented by an `<object>`
|
||||||
* element is specified by the “class” attribute. If the type has not
|
* element is specified by the “class” attribute. If the type has not
|
||||||
@@ -173,6 +171,53 @@
|
|||||||
* exception to this rule is that an object has to be constructed before
|
* exception to this rule is that an object has to be constructed before
|
||||||
* it can be used as the value of a construct-only property.
|
* it can be used as the value of a construct-only property.
|
||||||
*
|
*
|
||||||
|
* ### Child objects
|
||||||
|
*
|
||||||
|
* Many widgets have properties for child widgets, such as
|
||||||
|
* [property@Gtk.Expander:child]. In this case, the preferred way to
|
||||||
|
* specify the child widget in a ui file is to simply set the property:
|
||||||
|
*
|
||||||
|
* ```xml
|
||||||
|
* <object class="GtkExpander">
|
||||||
|
* <property name="child">
|
||||||
|
* <object class="GtkLabel">
|
||||||
|
* ...
|
||||||
|
* </object>
|
||||||
|
* </property>
|
||||||
|
* </object>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Generic containers that can contain an arbitrary number of children,
|
||||||
|
* such as [class@Gtk.Box] instead use the `<child>` element. A `<child>`
|
||||||
|
* element contains an `<object>` element which describes the child object.
|
||||||
|
* Most often, child objects are widgets inside a container, but they can
|
||||||
|
* also be, e.g., actions in an action group, or columns in a tree model.
|
||||||
|
*
|
||||||
|
* Any object type that implements the [iface@Gtk.Buildable] interface can
|
||||||
|
* specify how children may be added to it. Since many objects and widgets that
|
||||||
|
* are included with GTK already implement the `GtkBuildable` interface,
|
||||||
|
* typically child objects can be added using the `<child>` element without
|
||||||
|
* having to be concerned about the underlying implementation.
|
||||||
|
*
|
||||||
|
* See the [`GtkWidget` documentation](class.Widget.html#gtkwidget-as-gtkbuildable)
|
||||||
|
* for many examples of using `GtkBuilder` with widgets, including setting
|
||||||
|
* child objects using the `<child>` element.
|
||||||
|
*
|
||||||
|
* A noteworthy special case to the general rule that only objects implementing
|
||||||
|
* `GtkBuildable` may specify how to handle the `<child>` element is that
|
||||||
|
* `GtkBuilder` provides special support for adding objects to a
|
||||||
|
* [class@Gio.ListStore] by using the `<child>` element. For instance:
|
||||||
|
*
|
||||||
|
* ```xml
|
||||||
|
* <object class="GListStore">
|
||||||
|
* <property name="item-type">MyObject</property>
|
||||||
|
* <child>
|
||||||
|
* <object class="MyObject" />
|
||||||
|
* </child>
|
||||||
|
* ...
|
||||||
|
* </object>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* ### Property bindings
|
* ### Property bindings
|
||||||
*
|
*
|
||||||
* It is also possible to bind a property value to another object's
|
* It is also possible to bind a property value to another object's
|
||||||
@@ -208,6 +253,11 @@
|
|||||||
* For more information, see the documentation of the
|
* For more information, see the documentation of the
|
||||||
* [method@GObject.Object.bind_property] method.
|
* [method@GObject.Object.bind_property] method.
|
||||||
*
|
*
|
||||||
|
* Please note that another way to set up bindings between objects in .ui files
|
||||||
|
* is to use the `GtkExpression` methodology. See the
|
||||||
|
* [`GtkExpression` documentation](class.Expression.html#gtkexpression-in-ui-files)
|
||||||
|
* for more information.
|
||||||
|
*
|
||||||
* ### Internal children
|
* ### Internal children
|
||||||
*
|
*
|
||||||
* Sometimes it is necessary to refer to widgets which have implicitly
|
* Sometimes it is necessary to refer to widgets which have implicitly
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ gtk_emoji_chooser_finalize (GObject *object)
|
|||||||
g_source_remove (chooser->populate_idle);
|
g_source_remove (chooser->populate_idle);
|
||||||
|
|
||||||
g_clear_pointer (&chooser->data, g_variant_unref);
|
g_clear_pointer (&chooser->data, g_variant_unref);
|
||||||
|
g_clear_pointer (&chooser->iter, g_variant_iter_free);
|
||||||
g_clear_object (&chooser->settings);
|
g_clear_object (&chooser->settings);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_emoji_chooser_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gtk_emoji_chooser_parent_class)->finalize (object);
|
||||||
@@ -448,7 +449,7 @@ static gboolean
|
|||||||
has_variations (GVariant *emoji_data)
|
has_variations (GVariant *emoji_data)
|
||||||
{
|
{
|
||||||
GVariant *codes;
|
GVariant *codes;
|
||||||
int i;
|
gsize i;
|
||||||
gboolean has_variations;
|
gboolean has_variations;
|
||||||
|
|
||||||
has_variations = FALSE;
|
has_variations = FALSE;
|
||||||
@@ -457,7 +458,7 @@ has_variations (GVariant *emoji_data)
|
|||||||
{
|
{
|
||||||
gunichar code;
|
gunichar code;
|
||||||
g_variant_get_child (codes, i, "u", &code);
|
g_variant_get_child (codes, i, "u", &code);
|
||||||
if (code == 0)
|
if (code == 0 || code == 0x1f3fb)
|
||||||
{
|
{
|
||||||
has_variations = TRUE;
|
has_variations = TRUE;
|
||||||
break;
|
break;
|
||||||
@@ -570,15 +571,14 @@ add_emoji (GtkWidget *box,
|
|||||||
{
|
{
|
||||||
g_variant_get_child (codes, i, "u", &code);
|
g_variant_get_child (codes, i, "u", &code);
|
||||||
if (code == 0)
|
if (code == 0)
|
||||||
|
code = modifier != 0 ? modifier : 0xfe0f;
|
||||||
|
if (code == 0x1f3fb)
|
||||||
code = modifier;
|
code = modifier;
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
p += g_unichar_to_utf8 (code, p);
|
p += g_unichar_to_utf8 (code, p);
|
||||||
}
|
}
|
||||||
g_variant_unref (codes);
|
g_variant_unref (codes);
|
||||||
|
|
||||||
if (code != 0xFE0F && code != 0xFE0E)
|
|
||||||
p += g_unichar_to_utf8 (0xFE0F, p); /* Append a variation selector, if there isn't one already */
|
|
||||||
|
|
||||||
p[0] = 0;
|
p[0] = 0;
|
||||||
|
|
||||||
label = gtk_label_new (text);
|
label = gtk_label_new (text);
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ has_variations (GVariant *emoji_data)
|
|||||||
{
|
{
|
||||||
gunichar code;
|
gunichar code;
|
||||||
g_variant_get_child (codes, i, "u", &code);
|
g_variant_get_child (codes, i, "u", &code);
|
||||||
if (code == 0)
|
if (code == 0 || code == 0x1f3fb)
|
||||||
{
|
{
|
||||||
has_variations = TRUE;
|
has_variations = TRUE;
|
||||||
break;
|
break;
|
||||||
@@ -438,12 +438,13 @@ get_text (GVariant *emoji_data,
|
|||||||
|
|
||||||
g_variant_get_child (codes, i, "u", &code);
|
g_variant_get_child (codes, i, "u", &code);
|
||||||
if (code == 0)
|
if (code == 0)
|
||||||
|
code = modifier != 0 ? modifier : 0xfe0f;
|
||||||
|
if (code == 0x1f3fb)
|
||||||
code = modifier;
|
code = modifier;
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
p += g_unichar_to_utf8 (code, p);
|
p += g_unichar_to_utf8 (code, p);
|
||||||
}
|
}
|
||||||
g_variant_unref (codes);
|
g_variant_unref (codes);
|
||||||
p += g_unichar_to_utf8 (0xFE0F, p); /* U+FE0F is the Emoji variation selector */
|
|
||||||
p[0] = 0;
|
p[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-3
@@ -150,9 +150,10 @@
|
|||||||
* <constant type='gchararray'>Hello, world</constant>
|
* <constant type='gchararray'>Hello, world</constant>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* To create a closure expression, use the `<closure>` element. The `type` and `function`
|
* To create a closure expression, use the `<closure>` element. The `function`
|
||||||
* attributes specify what function to use for the closure, the content of the element
|
* attribute specifies what function to use for the closure, and the `type`
|
||||||
* contains the expressions for the parameters. For instance:
|
* attribute specifies its return type. The content of the element contains the
|
||||||
|
* expressions for the parameters. For instance:
|
||||||
*
|
*
|
||||||
* ```xml
|
* ```xml
|
||||||
* <closure type='gchararray' function='combine_args_somehow'>
|
* <closure type='gchararray' function='combine_args_somehow'>
|
||||||
@@ -160,6 +161,22 @@
|
|||||||
* <lookup type='GFile' name='size'>myfile</lookup>
|
* <lookup type='GFile' name='size'>myfile</lookup>
|
||||||
* </closure>
|
* </closure>
|
||||||
* ```
|
* ```
|
||||||
|
*
|
||||||
|
* To create a property binding, use the `<binding>` element in place of where a
|
||||||
|
* `<property>` tag would ordinarily be used. The `name` and `object` attributes are
|
||||||
|
* supported. The `name` attribute is required, and pertains to the applicable property
|
||||||
|
* name. The `object` attribute is optional. If provided, it will use the specified object
|
||||||
|
* as the `this` object when the expression is evaluated. Here is an example in which the
|
||||||
|
* `label` property of a `GtkLabel` is bound to the `string` property of another arbitrary
|
||||||
|
* object:
|
||||||
|
*
|
||||||
|
* ```xml
|
||||||
|
* <object class='GtkLabel'>
|
||||||
|
* <binding name='label'>
|
||||||
|
* <lookup name='string'>some_other_object</lookup>
|
||||||
|
* </binding>
|
||||||
|
* </object>
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _WeakRefGuard WeakRefGuard;
|
typedef struct _WeakRefGuard WeakRefGuard;
|
||||||
|
|||||||
@@ -708,6 +708,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry)
|
|||||||
old_file_part = chooser_entry->file_part;
|
old_file_part = chooser_entry->file_part;
|
||||||
|
|
||||||
text = gtk_file_chooser_entry_get_completion_text (chooser_entry);
|
text = gtk_file_chooser_entry_get_completion_text (chooser_entry);
|
||||||
|
g_return_if_fail (text != NULL);
|
||||||
|
|
||||||
last_slash = strrchr (text, G_DIR_SEPARATOR);
|
last_slash = strrchr (text, G_DIR_SEPARATOR);
|
||||||
if (last_slash)
|
if (last_slash)
|
||||||
|
|||||||
@@ -2232,6 +2232,7 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
|
|||||||
attr->start_index = 0;
|
attr->start_index = 0;
|
||||||
attr->end_index = strlen (input);
|
attr->end_index = strlen (input);
|
||||||
pango_attr_list_insert (attrs, attr);
|
pango_attr_list_insert (attrs, attr);
|
||||||
|
g_free (str);
|
||||||
str = g_strconcat (item->name, " 1", NULL);
|
str = g_strconcat (item->name, " 1", NULL);
|
||||||
attr = pango_attr_font_features_new (str);
|
attr = pango_attr_font_features_new (str);
|
||||||
attr->start_index = strlen (input) + strlen (" → ");
|
attr->start_index = strlen (input) + strlen (" → ");
|
||||||
@@ -2241,6 +2242,7 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
|
|||||||
attr->start_index = strlen (input) + strlen (" → ");
|
attr->start_index = strlen (input) + strlen (" → ");
|
||||||
attr->end_index = attr->start_index + strlen (input);
|
attr->end_index = attr->start_index + strlen (input);
|
||||||
pango_attr_list_insert (attrs, attr);
|
pango_attr_list_insert (attrs, attr);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
gtk_label_set_text (GTK_LABEL (item->example), text);
|
gtk_label_set_text (GTK_LABEL (item->example), text);
|
||||||
gtk_label_set_attributes (GTK_LABEL (item->example), attrs);
|
gtk_label_set_attributes (GTK_LABEL (item->example), attrs);
|
||||||
|
|||||||
+24
-6
@@ -18,7 +18,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "gtkimcontext.h"
|
#include "gtkimcontext.h"
|
||||||
#include "gtkimcontextprivate.h"
|
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtktypebuiltins.h"
|
#include "gtktypebuiltins.h"
|
||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
@@ -1007,11 +1006,30 @@ gtk_im_context_set_property (GObject *obj,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/**
|
||||||
gtk_im_context_activate_osk (GtkIMContext *context)
|
* gtk_im_context_activate_osk:
|
||||||
|
* @context: a `GtkIMContext`
|
||||||
|
* @event: (nullable): a [class@Gdk.Event]
|
||||||
|
*
|
||||||
|
* Requests the platform to show an on-screen keyboard for user input.
|
||||||
|
*
|
||||||
|
* This method will return %TRUE if this request was actually performed
|
||||||
|
* to the platform, other environmental factors may result in an on-screen
|
||||||
|
* keyboard effectively not showing up.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if an on-screen keyboard could be requested to the platform.
|
||||||
|
*
|
||||||
|
* Since: 4.14
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
gtk_im_context_activate_osk (GtkIMContext *context,
|
||||||
|
GdkEvent *event)
|
||||||
{
|
{
|
||||||
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
|
g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
|
||||||
|
g_return_val_if_fail (!event || GDK_IS_EVENT (event), FALSE);
|
||||||
|
|
||||||
if (GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk)
|
if (!GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk_with_event)
|
||||||
GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk (context);
|
return FALSE;
|
||||||
|
|
||||||
|
return GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk_with_event (context, event);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -96,9 +96,10 @@ struct _GtkIMContextClass
|
|||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
void (* activate_osk) (GtkIMContext *context);
|
void (* activate_osk) (GtkIMContext *context);
|
||||||
|
gboolean (* activate_osk_with_event) (GtkIMContext *context,
|
||||||
|
GdkEvent *event);
|
||||||
|
|
||||||
/* Padding for future expansion */
|
/* Padding for future expansion */
|
||||||
void (*_gtk_reserved1) (void);
|
|
||||||
void (*_gtk_reserved2) (void);
|
void (*_gtk_reserved2) (void);
|
||||||
void (*_gtk_reserved3) (void);
|
void (*_gtk_reserved3) (void);
|
||||||
void (*_gtk_reserved4) (void);
|
void (*_gtk_reserved4) (void);
|
||||||
@@ -168,6 +169,10 @@ gboolean gtk_im_context_delete_surrounding (GtkIMContext *context,
|
|||||||
int offset,
|
int offset,
|
||||||
int n_chars);
|
int n_chars);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_4_14
|
||||||
|
gboolean gtk_im_context_activate_osk (GtkIMContext *context,
|
||||||
|
GdkEvent *event);
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkIMContext, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkIMContext, g_object_unref)
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
/* GTK - The GIMP Toolkit
|
|
||||||
* Copyright (C) 2022 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "gtkimcontext.h"
|
|
||||||
|
|
||||||
void gtk_im_context_activate_osk (GtkIMContext *context);
|
|
||||||
|
|
||||||
@@ -71,10 +71,6 @@ struct _GtkIMContextWayland
|
|||||||
GtkIMContextSimple parent_instance;
|
GtkIMContextSimple parent_instance;
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
|
|
||||||
GtkGesture *gesture;
|
|
||||||
double press_x;
|
|
||||||
double press_y;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char *text;
|
char *text;
|
||||||
int cursor_idx;
|
int cursor_idx;
|
||||||
@@ -521,7 +517,6 @@ gtk_im_context_wayland_finalize (GObject *object)
|
|||||||
gtk_im_context_wayland_focus_out (GTK_IM_CONTEXT (context));
|
gtk_im_context_wayland_focus_out (GTK_IM_CONTEXT (context));
|
||||||
|
|
||||||
g_clear_object (&context->widget);
|
g_clear_object (&context->widget);
|
||||||
g_clear_object (&context->gesture);
|
|
||||||
g_free (context->surrounding.text);
|
g_free (context->surrounding.text);
|
||||||
g_free (context->current_preedit.text);
|
g_free (context->current_preedit.text);
|
||||||
g_free (context->pending_preedit.text);
|
g_free (context->pending_preedit.text);
|
||||||
@@ -530,50 +525,6 @@ gtk_im_context_wayland_finalize (GObject *object)
|
|||||||
G_OBJECT_CLASS (gtk_im_context_wayland_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gtk_im_context_wayland_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pressed_cb (GtkGestureClick *gesture,
|
|
||||||
int n_press,
|
|
||||||
double x,
|
|
||||||
double y,
|
|
||||||
GtkIMContextWayland *context)
|
|
||||||
{
|
|
||||||
if (n_press == 1)
|
|
||||||
{
|
|
||||||
context->press_x = x;
|
|
||||||
context->press_y = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
released_cb (GtkGestureClick *gesture,
|
|
||||||
int n_press,
|
|
||||||
double x,
|
|
||||||
double y,
|
|
||||||
GtkIMContextWayland *context)
|
|
||||||
{
|
|
||||||
GtkIMContextWaylandGlobal *global;
|
|
||||||
GtkInputHints hints;
|
|
||||||
|
|
||||||
global = gtk_im_context_wayland_get_global (context);
|
|
||||||
if (global == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_object_get (context, "input-hints", &hints, NULL);
|
|
||||||
|
|
||||||
if (global->focused &&
|
|
||||||
n_press == 1 &&
|
|
||||||
(hints & GTK_INPUT_HINT_INHIBIT_OSK) == 0 &&
|
|
||||||
!gtk_drag_check_threshold_double (context->widget,
|
|
||||||
context->press_x,
|
|
||||||
context->press_y,
|
|
||||||
x, y))
|
|
||||||
{
|
|
||||||
zwp_text_input_v3_enable (global->text_input);
|
|
||||||
notify_im_change (GTK_IM_CONTEXT_WAYLAND (context),
|
|
||||||
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_OTHER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
|
gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
|
||||||
GtkWidget *widget)
|
GtkWidget *widget)
|
||||||
@@ -586,34 +537,7 @@ gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
|
|||||||
if (context_wayland->widget)
|
if (context_wayland->widget)
|
||||||
gtk_im_context_wayland_focus_out (context);
|
gtk_im_context_wayland_focus_out (context);
|
||||||
|
|
||||||
if (context_wayland->widget && context_wayland->gesture)
|
|
||||||
{
|
|
||||||
gtk_widget_remove_controller (context_wayland->widget,
|
|
||||||
GTK_EVENT_CONTROLLER (context_wayland->gesture));
|
|
||||||
context_wayland->gesture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_set_object (&context_wayland->widget, widget);
|
g_set_object (&context_wayland->widget, widget);
|
||||||
|
|
||||||
if (widget &&
|
|
||||||
!GTK_IS_TEXT (widget) &&
|
|
||||||
!GTK_IS_TEXT_VIEW (widget))
|
|
||||||
{
|
|
||||||
GtkGesture *gesture;
|
|
||||||
|
|
||||||
gesture = gtk_gesture_click_new ();
|
|
||||||
gtk_event_controller_set_static_name (GTK_EVENT_CONTROLLER (gesture), "wayland-im-context-click");
|
|
||||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
|
|
||||||
GTK_PHASE_CAPTURE);
|
|
||||||
g_signal_connect (gesture, "pressed",
|
|
||||||
G_CALLBACK (pressed_cb), context);
|
|
||||||
g_signal_connect (gesture, "released",
|
|
||||||
G_CALLBACK (released_cb), context);
|
|
||||||
|
|
||||||
gtk_widget_add_controller (context_wayland->widget,
|
|
||||||
GTK_EVENT_CONTROLLER (gesture));
|
|
||||||
context_wayland->gesture = gesture;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -847,9 +771,6 @@ gtk_im_context_wayland_focus_in (GtkIMContext *context)
|
|||||||
if (!global->text_input)
|
if (!global->text_input)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (self->gesture)
|
|
||||||
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (self->gesture));
|
|
||||||
|
|
||||||
if (global->focused)
|
if (global->focused)
|
||||||
enable (self, global);
|
enable (self, global);
|
||||||
}
|
}
|
||||||
@@ -884,7 +805,6 @@ gtk_im_context_wayland_set_cursor_location (GtkIMContext *context,
|
|||||||
GdkRectangle *rect)
|
GdkRectangle *rect)
|
||||||
{
|
{
|
||||||
GtkIMContextWayland *context_wayland;
|
GtkIMContextWayland *context_wayland;
|
||||||
int side;
|
|
||||||
|
|
||||||
context_wayland = GTK_IM_CONTEXT_WAYLAND (context);
|
context_wayland = GTK_IM_CONTEXT_WAYLAND (context);
|
||||||
|
|
||||||
@@ -894,20 +814,6 @@ gtk_im_context_wayland_set_cursor_location (GtkIMContext *context,
|
|||||||
context_wayland->cursor_rect.height == rect->height)
|
context_wayland->cursor_rect.height == rect->height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Reset the gesture if the cursor changes too far (eg. clicking
|
|
||||||
* between disjoint positions in the text).
|
|
||||||
*
|
|
||||||
* Still Allow some jittering (a square almost double the cursor rect height
|
|
||||||
* on either side) as clicking on the exact same position between characters
|
|
||||||
* is hard.
|
|
||||||
*/
|
|
||||||
side = context_wayland->cursor_rect.height;
|
|
||||||
|
|
||||||
if (context_wayland->gesture &&
|
|
||||||
(ABS (rect->x - context_wayland->cursor_rect.x) >= side ||
|
|
||||||
ABS (rect->y - context_wayland->cursor_rect.y) >= side))
|
|
||||||
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (context_wayland->gesture));
|
|
||||||
|
|
||||||
context_wayland->cursor_rect = *rect;
|
context_wayland->cursor_rect = *rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -974,18 +880,20 @@ gtk_im_context_wayland_commit (GtkIMContext *context,
|
|||||||
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD);
|
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
gtk_im_context_wayland_activate_osk (GtkIMContext *context)
|
gtk_im_context_wayland_activate_osk_with_event (GtkIMContext *context,
|
||||||
|
GdkEvent *event)
|
||||||
{
|
{
|
||||||
GtkIMContextWaylandGlobal *global;
|
GtkIMContextWaylandGlobal *global;
|
||||||
|
|
||||||
global = gtk_im_context_wayland_get_global (GTK_IM_CONTEXT_WAYLAND (context));
|
global = gtk_im_context_wayland_get_global (GTK_IM_CONTEXT_WAYLAND (context));
|
||||||
if (global == NULL)
|
if (global == NULL)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
zwp_text_input_v3_enable (global->text_input);
|
zwp_text_input_v3_enable (global->text_input);
|
||||||
notify_im_change (GTK_IM_CONTEXT_WAYLAND (context),
|
notify_im_change (GTK_IM_CONTEXT_WAYLAND (context),
|
||||||
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_OTHER);
|
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_OTHER);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1007,7 +915,7 @@ gtk_im_context_wayland_class_init (GtkIMContextWaylandClass *klass)
|
|||||||
im_context_class->set_surrounding_with_selection = gtk_im_context_wayland_set_surrounding;
|
im_context_class->set_surrounding_with_selection = gtk_im_context_wayland_set_surrounding;
|
||||||
im_context_class->get_surrounding_with_selection = gtk_im_context_wayland_get_surrounding;
|
im_context_class->get_surrounding_with_selection = gtk_im_context_wayland_get_surrounding;
|
||||||
im_context_class->commit = gtk_im_context_wayland_commit;
|
im_context_class->commit = gtk_im_context_wayland_commit;
|
||||||
im_context_class->activate_osk = gtk_im_context_wayland_activate_osk;
|
im_context_class->activate_osk_with_event = gtk_im_context_wayland_activate_osk_with_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
#include "gtkimcontextprivate.h"
|
|
||||||
#include "gtkimmulticontext.h"
|
#include "gtkimmulticontext.h"
|
||||||
#include "gtkimmoduleprivate.h"
|
#include "gtkimmoduleprivate.h"
|
||||||
#include "gtklabel.h"
|
#include "gtklabel.h"
|
||||||
@@ -106,7 +105,8 @@ static gboolean gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *
|
|||||||
int offset,
|
int offset,
|
||||||
int n_chars,
|
int n_chars,
|
||||||
GtkIMMulticontext *multicontext);
|
GtkIMMulticontext *multicontext);
|
||||||
static void gtk_im_multicontext_activate_osk (GtkIMContext *context);
|
static gboolean gtk_im_multicontext_activate_osk_with_event (GtkIMContext *context,
|
||||||
|
GdkEvent *event);
|
||||||
|
|
||||||
static void propagate_purpose (GtkIMMulticontext *context);
|
static void propagate_purpose (GtkIMMulticontext *context);
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
|
|||||||
im_context_class->set_use_preedit = gtk_im_multicontext_set_use_preedit;
|
im_context_class->set_use_preedit = gtk_im_multicontext_set_use_preedit;
|
||||||
im_context_class->set_surrounding_with_selection = gtk_im_multicontext_set_surrounding_with_selection;
|
im_context_class->set_surrounding_with_selection = gtk_im_multicontext_set_surrounding_with_selection;
|
||||||
im_context_class->get_surrounding_with_selection = gtk_im_multicontext_get_surrounding_with_selection;
|
im_context_class->get_surrounding_with_selection = gtk_im_multicontext_get_surrounding_with_selection;
|
||||||
im_context_class->activate_osk = gtk_im_multicontext_activate_osk;
|
im_context_class->activate_osk_with_event = gtk_im_multicontext_activate_osk_with_event;
|
||||||
|
|
||||||
gobject_class->finalize = gtk_im_multicontext_finalize;
|
gobject_class->finalize = gtk_im_multicontext_finalize;
|
||||||
}
|
}
|
||||||
@@ -516,14 +516,17 @@ gtk_im_multicontext_set_surrounding_with_selection (GtkIMContext *context,
|
|||||||
gtk_im_context_set_surrounding_with_selection (delegate, text, len, cursor_index, anchor_index);
|
gtk_im_context_set_surrounding_with_selection (delegate, text, len, cursor_index, anchor_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
gtk_im_multicontext_activate_osk (GtkIMContext *context)
|
gtk_im_multicontext_activate_osk_with_event (GtkIMContext *context,
|
||||||
|
GdkEvent *event)
|
||||||
{
|
{
|
||||||
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
|
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
|
||||||
GtkIMContext *delegate = gtk_im_multicontext_get_delegate (multicontext);
|
GtkIMContext *delegate = gtk_im_multicontext_get_delegate (multicontext);
|
||||||
|
|
||||||
if (delegate)
|
if (delegate)
|
||||||
gtk_im_context_activate_osk (delegate);
|
return gtk_im_context_activate_osk (delegate, event);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
+30
-1
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "gtkinscriptionprivate.h"
|
#include "gtkinscriptionprivate.h"
|
||||||
|
|
||||||
#include "gtkaccessibletext-private.h"
|
#include "gtkaccessibletextprivate.h"
|
||||||
#include "gtkcssnodeprivate.h"
|
#include "gtkcssnodeprivate.h"
|
||||||
#include "gtkcssstylechangeprivate.h"
|
#include "gtkcssstylechangeprivate.h"
|
||||||
#include "gtkpangoprivate.h"
|
#include "gtkpangoprivate.h"
|
||||||
@@ -1363,6 +1363,19 @@ gtk_inscription_accessible_text_get_contents (GtkAccessibleText *self,
|
|||||||
return g_bytes_new_take (string, size);
|
return g_bytes_new_take (string, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
gtk_inscription_accessible_text_get_contents_at (GtkAccessibleText *self,
|
||||||
|
unsigned int offset,
|
||||||
|
GtkAccessibleTextGranularity granularity,
|
||||||
|
unsigned int *start,
|
||||||
|
unsigned int *end)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_inscription_get_layout (GTK_INSCRIPTION (self));
|
||||||
|
char *string = gtk_pango_get_string_at (layout, offset, granularity, start, end);
|
||||||
|
|
||||||
|
return g_bytes_new_take (string, strlen (string));
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
gtk_inscription_accessible_text_get_caret_position (GtkAccessibleText *self)
|
gtk_inscription_accessible_text_get_caret_position (GtkAccessibleText *self)
|
||||||
{
|
{
|
||||||
@@ -1408,13 +1421,29 @@ gtk_inscription_accessible_text_get_attributes (GtkAccessibleText *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_inscription_accessible_text_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_inscription_get_layout (GTK_INSCRIPTION (self));
|
||||||
|
char **names, **values;
|
||||||
|
|
||||||
|
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||||
|
|
||||||
|
*attribute_names = names;
|
||||||
|
*attribute_values = values;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_inscription_accessible_text_init (GtkAccessibleTextInterface *iface)
|
gtk_inscription_accessible_text_init (GtkAccessibleTextInterface *iface)
|
||||||
{
|
{
|
||||||
iface->get_contents = gtk_inscription_accessible_text_get_contents;
|
iface->get_contents = gtk_inscription_accessible_text_get_contents;
|
||||||
|
iface->get_contents_at = gtk_inscription_accessible_text_get_contents_at;
|
||||||
iface->get_caret_position = gtk_inscription_accessible_text_get_caret_position;
|
iface->get_caret_position = gtk_inscription_accessible_text_get_caret_position;
|
||||||
iface->get_selection = gtk_inscription_accessible_text_get_selection;
|
iface->get_selection = gtk_inscription_accessible_text_get_selection;
|
||||||
iface->get_attributes = gtk_inscription_accessible_text_get_attributes;
|
iface->get_attributes = gtk_inscription_accessible_text_get_attributes;
|
||||||
|
iface->get_default_attributes = gtk_inscription_accessible_text_get_default_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|||||||
+26
-11
@@ -26,37 +26,36 @@
|
|||||||
|
|
||||||
#include "gtklabelprivate.h"
|
#include "gtklabelprivate.h"
|
||||||
|
|
||||||
|
#include "gtkaccessibletextprivate.h"
|
||||||
#include "gtkbuildable.h"
|
#include "gtkbuildable.h"
|
||||||
|
#include "gtkcsscolorvalueprivate.h"
|
||||||
|
#include "gtkdragsourceprivate.h"
|
||||||
|
#include "gtkdragicon.h"
|
||||||
#include "gtkeventcontrollermotion.h"
|
#include "gtkeventcontrollermotion.h"
|
||||||
#include "gtkeventcontrollerfocus.h"
|
#include "gtkeventcontrollerfocus.h"
|
||||||
#include "gtkfilelauncher.h"
|
#include "gtkfilelauncher.h"
|
||||||
#include "gtkgesturedrag.h"
|
#include "gtkgesturedrag.h"
|
||||||
#include "gtkgestureclick.h"
|
#include "gtkgestureclick.h"
|
||||||
#include "gtkgesturesingle.h"
|
#include "gtkgesturesingle.h"
|
||||||
|
#include "gtkjoinedmenuprivate.h"
|
||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
|
#include "gtknative.h"
|
||||||
#include "gtknotebook.h"
|
#include "gtknotebook.h"
|
||||||
#include "gtkpangoprivate.h"
|
#include "gtkpangoprivate.h"
|
||||||
|
#include "gtkpopovermenu.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
|
#include "gtkrenderbackgroundprivate.h"
|
||||||
|
#include "gtkrenderborderprivate.h"
|
||||||
|
#include "gtkrenderlayoutprivate.h"
|
||||||
#include "gtkshortcut.h"
|
#include "gtkshortcut.h"
|
||||||
#include "gtkshortcutcontroller.h"
|
#include "gtkshortcutcontroller.h"
|
||||||
#include "gtkshortcuttrigger.h"
|
#include "gtkshortcuttrigger.h"
|
||||||
#include "gtksnapshot.h"
|
#include "gtksnapshot.h"
|
||||||
#include "gtkrenderbackgroundprivate.h"
|
|
||||||
#include "gtkrenderborderprivate.h"
|
|
||||||
#include "gtkrenderlayoutprivate.h"
|
|
||||||
#include "gtktextutilprivate.h"
|
#include "gtktextutilprivate.h"
|
||||||
#include "gtktooltip.h"
|
#include "gtktooltip.h"
|
||||||
#include "gtktypebuiltins.h"
|
#include "gtktypebuiltins.h"
|
||||||
#include "gtkurilauncher.h"
|
#include "gtkurilauncher.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkwidgetprivate.h"
|
||||||
#include "gtkpopovermenu.h"
|
|
||||||
#include "gtknative.h"
|
|
||||||
#include "gtkdragsourceprivate.h"
|
|
||||||
#include "gtkdragicon.h"
|
|
||||||
#include "gtkcsscolorvalueprivate.h"
|
|
||||||
#include "gtkjoinedmenuprivate.h"
|
|
||||||
#include "gtkaccessibletext-private.h"
|
|
||||||
#include "gtkpangoprivate.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -1524,6 +1523,7 @@ gtk_label_dispose (GObject *object)
|
|||||||
GtkLabel *self = GTK_LABEL (object);
|
GtkLabel *self = GTK_LABEL (object);
|
||||||
|
|
||||||
gtk_label_set_mnemonic_widget (self, NULL);
|
gtk_label_set_mnemonic_widget (self, NULL);
|
||||||
|
gtk_label_clear_select_info (self);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_label_parent_class)->dispose (object);
|
G_OBJECT_CLASS (gtk_label_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@@ -6134,6 +6134,20 @@ gtk_label_accessible_text_get_selection (GtkAccessibleText *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_label_accessible_text_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (self));
|
||||||
|
char **names, **values;
|
||||||
|
|
||||||
|
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||||
|
|
||||||
|
*attribute_names = names;
|
||||||
|
*attribute_values = values;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gtk_label_accessible_text_get_attributes (GtkAccessibleText *self,
|
gtk_label_accessible_text_get_attributes (GtkAccessibleText *self,
|
||||||
unsigned int offset,
|
unsigned int offset,
|
||||||
@@ -6173,6 +6187,7 @@ gtk_label_accessible_text_init (GtkAccessibleTextInterface *iface)
|
|||||||
iface->get_caret_position = gtk_label_accessible_text_get_caret_position;
|
iface->get_caret_position = gtk_label_accessible_text_get_caret_position;
|
||||||
iface->get_selection = gtk_label_accessible_text_get_selection;
|
iface->get_selection = gtk_label_accessible_text_get_selection;
|
||||||
iface->get_attributes = gtk_label_accessible_text_get_attributes;
|
iface->get_attributes = gtk_label_accessible_text_get_attributes;
|
||||||
|
iface->get_default_attributes = gtk_label_accessible_text_get_default_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|||||||
@@ -886,6 +886,14 @@ gesture_drag_begin_cb (GtkGestureDrag *gesture,
|
|||||||
GdkDevice *device;
|
GdkDevice *device;
|
||||||
gboolean is_touch;
|
gboolean is_touch;
|
||||||
|
|
||||||
|
/* Only drag the handle when it's visible */
|
||||||
|
if (!gtk_widget_get_child_visible (paned->handle_widget))
|
||||||
|
{
|
||||||
|
gtk_gesture_set_state (GTK_GESTURE (gesture),
|
||||||
|
GTK_EVENT_SEQUENCE_DENIED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
||||||
event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
|
event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
|
||||||
device = gdk_event_get_device (event);
|
device = gdk_event_get_device (event);
|
||||||
|
|||||||
@@ -473,6 +473,8 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
|
|||||||
*
|
*
|
||||||
* The purpose for the `GtkSearchEntry` input used to alter the
|
* The purpose for the `GtkSearchEntry` input used to alter the
|
||||||
* behaviour of input methods.
|
* behaviour of input methods.
|
||||||
|
*
|
||||||
|
* Since: 4.14
|
||||||
*/
|
*/
|
||||||
props[PROP_INPUT_PURPOSE] =
|
props[PROP_INPUT_PURPOSE] =
|
||||||
g_param_spec_enum ("input-purpose", NULL, NULL,
|
g_param_spec_enum ("input-purpose", NULL, NULL,
|
||||||
@@ -485,6 +487,8 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
|
|||||||
*
|
*
|
||||||
* The hints about input for the `GtkSearchEntry` used to alter the
|
* The hints about input for the `GtkSearchEntry` used to alter the
|
||||||
* behaviour of input methods.
|
* behaviour of input methods.
|
||||||
|
*
|
||||||
|
* Since: 4.14
|
||||||
*/
|
*/
|
||||||
props[PROP_INPUT_HINTS] =
|
props[PROP_INPUT_HINTS] =
|
||||||
g_param_spec_flags ("input-hints", NULL, NULL,
|
g_param_spec_flags ("input-hints", NULL, NULL,
|
||||||
|
|||||||
+6
-31
@@ -475,6 +475,9 @@ gtk_settings_class_init (GtkSettingsClass *class)
|
|||||||
* The type of subpixel antialiasing to use.
|
* The type of subpixel antialiasing to use.
|
||||||
*
|
*
|
||||||
* The possible values are none, rgb, bgr, vrgb, vbgr.
|
* The possible values are none, rgb, bgr, vrgb, vbgr.
|
||||||
|
*
|
||||||
|
* Note that GSK does not support subpixel antialiasing, and this
|
||||||
|
* setting has no effect on font rendering in GTK.
|
||||||
*/
|
*/
|
||||||
pspecs[PROP_XFT_RGBA] = g_param_spec_string ("gtk-xft-rgba", NULL, NULL,
|
pspecs[PROP_XFT_RGBA] = g_param_spec_string ("gtk-xft-rgba", NULL, NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -1421,8 +1424,6 @@ settings_update_font_options (GtkSettings *settings)
|
|||||||
cairo_hint_style_t hint_style;
|
cairo_hint_style_t hint_style;
|
||||||
int antialias;
|
int antialias;
|
||||||
cairo_antialias_t antialias_mode;
|
cairo_antialias_t antialias_mode;
|
||||||
char *rgba_str;
|
|
||||||
cairo_subpixel_order_t subpixel_order;
|
|
||||||
gboolean hint_font_metrics;
|
gboolean hint_font_metrics;
|
||||||
|
|
||||||
if (settings->font_options)
|
if (settings->font_options)
|
||||||
@@ -1432,7 +1433,6 @@ settings_update_font_options (GtkSettings *settings)
|
|||||||
"gtk-xft-antialias", &antialias,
|
"gtk-xft-antialias", &antialias,
|
||||||
"gtk-xft-hinting", &hinting,
|
"gtk-xft-hinting", &hinting,
|
||||||
"gtk-xft-hintstyle", &hint_style_str,
|
"gtk-xft-hintstyle", &hint_style_str,
|
||||||
"gtk-xft-rgba", &rgba_str,
|
|
||||||
"gtk-hint-font-metrics", &hint_font_metrics,
|
"gtk-hint-font-metrics", &hint_font_metrics,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
@@ -1466,35 +1466,10 @@ settings_update_font_options (GtkSettings *settings)
|
|||||||
|
|
||||||
cairo_font_options_set_hint_style (settings->font_options, hint_style);
|
cairo_font_options_set_hint_style (settings->font_options, hint_style);
|
||||||
|
|
||||||
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
|
||||||
if (rgba_str)
|
|
||||||
{
|
|
||||||
if (strcmp (rgba_str, "rgb") == 0)
|
|
||||||
subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
|
|
||||||
else if (strcmp (rgba_str, "bgr") == 0)
|
|
||||||
subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
|
|
||||||
else if (strcmp (rgba_str, "vrgb") == 0)
|
|
||||||
subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
|
|
||||||
else if (strcmp (rgba_str, "vbgr") == 0)
|
|
||||||
subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (rgba_str);
|
|
||||||
|
|
||||||
cairo_font_options_set_subpixel_order (settings->font_options, subpixel_order);
|
|
||||||
|
|
||||||
antialias_mode = CAIRO_ANTIALIAS_DEFAULT;
|
|
||||||
if (antialias == 0)
|
if (antialias == 0)
|
||||||
{
|
antialias_mode = CAIRO_ANTIALIAS_NONE;
|
||||||
antialias_mode = CAIRO_ANTIALIAS_NONE;
|
else
|
||||||
}
|
antialias_mode = CAIRO_ANTIALIAS_GRAY;
|
||||||
else if (antialias == 1)
|
|
||||||
{
|
|
||||||
if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
|
||||||
antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL;
|
|
||||||
else
|
|
||||||
antialias_mode = CAIRO_ANTIALIAS_GRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_font_options_set_antialias (settings->font_options, antialias_mode);
|
cairo_font_options_set_antialias (settings->font_options, antialias_mode);
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-22
@@ -747,12 +747,18 @@ gtk_graphene_rect_scale_affine (const graphene_rect_t *rect,
|
|||||||
graphene_rect_normalize (res);
|
graphene_rect_normalize (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ENSURE_POSITIVE_SCALE = (1 << 0),
|
||||||
|
ENSURE_UNIFORM_SCALE = (1 << 1),
|
||||||
|
} GtkEnsureFlags;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_snapshot_ensure_affine (GtkSnapshot *snapshot,
|
gtk_snapshot_ensure_affine_with_flags (GtkSnapshot *snapshot,
|
||||||
float *scale_x,
|
GtkEnsureFlags flags,
|
||||||
float *scale_y,
|
float *scale_x,
|
||||||
float *dx,
|
float *scale_y,
|
||||||
float *dy)
|
float *dx,
|
||||||
|
float *dy)
|
||||||
{
|
{
|
||||||
const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot);
|
const GtkSnapshotState *state = gtk_snapshot_get_current_state (snapshot);
|
||||||
|
|
||||||
@@ -765,7 +771,8 @@ gtk_snapshot_ensure_affine (GtkSnapshot *snapshot,
|
|||||||
else if (gsk_transform_get_category (state->transform) == GSK_TRANSFORM_CATEGORY_2D_AFFINE)
|
else if (gsk_transform_get_category (state->transform) == GSK_TRANSFORM_CATEGORY_2D_AFFINE)
|
||||||
{
|
{
|
||||||
gsk_transform_to_affine (state->transform, scale_x, scale_y, dx, dy);
|
gsk_transform_to_affine (state->transform, scale_x, scale_y, dx, dy);
|
||||||
if (*scale_x < 0.0 || *scale_y < 0.0)
|
if (((flags & ENSURE_POSITIVE_SCALE) && (*scale_x < 0.0 || *scale_y < 0.0)) ||
|
||||||
|
((flags & ENSURE_UNIFORM_SCALE) && (*scale_x != *scale_y)))
|
||||||
{
|
{
|
||||||
gtk_snapshot_autopush_transform (snapshot);
|
gtk_snapshot_autopush_transform (snapshot);
|
||||||
state = gtk_snapshot_get_current_state (snapshot);
|
state = gtk_snapshot_get_current_state (snapshot);
|
||||||
@@ -778,6 +785,19 @@ gtk_snapshot_ensure_affine (GtkSnapshot *snapshot,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_snapshot_ensure_affine (GtkSnapshot *snapshot,
|
||||||
|
float *scale_x,
|
||||||
|
float *scale_y,
|
||||||
|
float *dx,
|
||||||
|
float *dy)
|
||||||
|
{
|
||||||
|
gtk_snapshot_ensure_affine_with_flags (snapshot,
|
||||||
|
ENSURE_POSITIVE_SCALE,
|
||||||
|
scale_x, scale_y,
|
||||||
|
dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_snapshot_ensure_translate (GtkSnapshot *snapshot,
|
gtk_snapshot_ensure_translate (GtkSnapshot *snapshot,
|
||||||
float *dx,
|
float *dx,
|
||||||
@@ -1377,11 +1397,19 @@ gtk_snapshot_push_shadow (GtkSnapshot *snapshot,
|
|||||||
const GskShadow *shadow,
|
const GskShadow *shadow,
|
||||||
gsize n_shadows)
|
gsize n_shadows)
|
||||||
{
|
{
|
||||||
const GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
|
|
||||||
GtkSnapshotState *state;
|
GtkSnapshotState *state;
|
||||||
|
GskTransform *transform;
|
||||||
|
float scale_x, scale_y, dx, dy;
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
gtk_snapshot_ensure_affine_with_flags (snapshot,
|
||||||
|
ENSURE_POSITIVE_SCALE | ENSURE_UNIFORM_SCALE,
|
||||||
|
&scale_x, &scale_y,
|
||||||
|
&dx, &dy);
|
||||||
|
transform = gsk_transform_scale (gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (dx, dy)), scale_x, scale_y);
|
||||||
|
|
||||||
state = gtk_snapshot_push_state (snapshot,
|
state = gtk_snapshot_push_state (snapshot,
|
||||||
current_state->transform,
|
transform,
|
||||||
gtk_snapshot_collect_shadow,
|
gtk_snapshot_collect_shadow,
|
||||||
gtk_snapshot_clear_shadow);
|
gtk_snapshot_clear_shadow);
|
||||||
|
|
||||||
@@ -1390,13 +1418,23 @@ gtk_snapshot_push_shadow (GtkSnapshot *snapshot,
|
|||||||
{
|
{
|
||||||
state->data.shadow.shadows = NULL;
|
state->data.shadow.shadows = NULL;
|
||||||
memcpy (&state->data.shadow.a_shadow, shadow, sizeof (GskShadow));
|
memcpy (&state->data.shadow.a_shadow, shadow, sizeof (GskShadow));
|
||||||
|
state->data.shadow.a_shadow.dx *= scale_x;
|
||||||
|
state->data.shadow.a_shadow.dy *= scale_y;
|
||||||
|
state->data.shadow.a_shadow.radius *= scale_x;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state->data.shadow.shadows = g_malloc (sizeof (GskShadow) * n_shadows);
|
state->data.shadow.shadows = g_malloc (sizeof (GskShadow) * n_shadows);
|
||||||
memcpy (state->data.shadow.shadows, shadow, sizeof (GskShadow) * n_shadows);
|
memcpy (state->data.shadow.shadows, shadow, sizeof (GskShadow) * n_shadows);
|
||||||
|
for (i = 0; i < n_shadows; i++)
|
||||||
|
{
|
||||||
|
state->data.shadow.shadows[i].dx *= scale_x;
|
||||||
|
state->data.shadow.shadows[i].dy *= scale_y;
|
||||||
|
state->data.shadow.shadows[i].radius *= scale_x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gsk_transform_unref (transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GskRenderNode *
|
static GskRenderNode *
|
||||||
@@ -2389,7 +2427,7 @@ gtk_snapshot_append_linear_gradient (GtkSnapshot *snapshot,
|
|||||||
{
|
{
|
||||||
GskRenderNode *node;
|
GskRenderNode *node;
|
||||||
graphene_rect_t real_bounds;
|
graphene_rect_t real_bounds;
|
||||||
float dx, dy;
|
float scale_x, scale_y, dx, dy;
|
||||||
const GdkRGBA *first_color;
|
const GdkRGBA *first_color;
|
||||||
gboolean need_gradient = FALSE;
|
gboolean need_gradient = FALSE;
|
||||||
|
|
||||||
@@ -2399,8 +2437,11 @@ gtk_snapshot_append_linear_gradient (GtkSnapshot *snapshot,
|
|||||||
g_return_if_fail (stops != NULL);
|
g_return_if_fail (stops != NULL);
|
||||||
g_return_if_fail (n_stops > 1);
|
g_return_if_fail (n_stops > 1);
|
||||||
|
|
||||||
gtk_snapshot_ensure_translate (snapshot, &dx, &dy);
|
gtk_snapshot_ensure_affine_with_flags (snapshot,
|
||||||
graphene_rect_offset_r (bounds, dx, dy, &real_bounds);
|
ENSURE_POSITIVE_SCALE | ENSURE_UNIFORM_SCALE,
|
||||||
|
&scale_x, &scale_y,
|
||||||
|
&dx, &dy);
|
||||||
|
gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
|
||||||
|
|
||||||
first_color = &stops[0].color;
|
first_color = &stops[0].color;
|
||||||
for (gsize i = 0; i < n_stops; i ++)
|
for (gsize i = 0; i < n_stops; i ++)
|
||||||
@@ -2416,10 +2457,10 @@ gtk_snapshot_append_linear_gradient (GtkSnapshot *snapshot,
|
|||||||
{
|
{
|
||||||
graphene_point_t real_start_point, real_end_point;
|
graphene_point_t real_start_point, real_end_point;
|
||||||
|
|
||||||
real_start_point.x = start_point->x + dx;
|
real_start_point.x = scale_x * start_point->x + dx;
|
||||||
real_start_point.y = start_point->y + dy;
|
real_start_point.y = scale_y * start_point->y + dy;
|
||||||
real_end_point.x = end_point->x + dx;
|
real_end_point.x = scale_x * end_point->x + dx;
|
||||||
real_end_point.y = end_point->y + dy;
|
real_end_point.y = scale_y * end_point->y + dy;
|
||||||
|
|
||||||
node = gsk_linear_gradient_node_new (&real_bounds,
|
node = gsk_linear_gradient_node_new (&real_bounds,
|
||||||
&real_start_point,
|
&real_start_point,
|
||||||
@@ -2456,7 +2497,7 @@ gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot *snapshot,
|
|||||||
{
|
{
|
||||||
GskRenderNode *node;
|
GskRenderNode *node;
|
||||||
graphene_rect_t real_bounds;
|
graphene_rect_t real_bounds;
|
||||||
float dx, dy;
|
float scale_x, scale_y, dx, dy;
|
||||||
gboolean need_gradient = FALSE;
|
gboolean need_gradient = FALSE;
|
||||||
const GdkRGBA *first_color;
|
const GdkRGBA *first_color;
|
||||||
|
|
||||||
@@ -2466,8 +2507,8 @@ gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot *snapshot,
|
|||||||
g_return_if_fail (stops != NULL);
|
g_return_if_fail (stops != NULL);
|
||||||
g_return_if_fail (n_stops > 1);
|
g_return_if_fail (n_stops > 1);
|
||||||
|
|
||||||
gtk_snapshot_ensure_translate (snapshot, &dx, &dy);
|
gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
|
||||||
graphene_rect_offset_r (bounds, dx, dy, &real_bounds);
|
gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &real_bounds);
|
||||||
|
|
||||||
first_color = &stops[0].color;
|
first_color = &stops[0].color;
|
||||||
for (gsize i = 0; i < n_stops; i ++)
|
for (gsize i = 0; i < n_stops; i ++)
|
||||||
@@ -2483,10 +2524,10 @@ gtk_snapshot_append_repeating_linear_gradient (GtkSnapshot *snapshot,
|
|||||||
{
|
{
|
||||||
graphene_point_t real_start_point, real_end_point;
|
graphene_point_t real_start_point, real_end_point;
|
||||||
|
|
||||||
real_start_point.x = start_point->x + dx;
|
real_start_point.x = scale_x * start_point->x + dx;
|
||||||
real_start_point.y = start_point->y + dy;
|
real_start_point.y = scale_y * start_point->y + dy;
|
||||||
real_end_point.x = end_point->x + dx;
|
real_end_point.x = scale_x * end_point->x + dx;
|
||||||
real_end_point.y = end_point->y + dy;
|
real_end_point.y = scale_y * end_point->y + dy;
|
||||||
|
|
||||||
node = gsk_repeating_linear_gradient_node_new (&real_bounds,
|
node = gsk_repeating_linear_gradient_node_new (&real_bounds,
|
||||||
&real_start_point,
|
&real_start_point,
|
||||||
|
|||||||
+1
-3
@@ -518,12 +518,10 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
|
|||||||
* on_output (GtkSpinButton *spin,
|
* on_output (GtkSpinButton *spin,
|
||||||
* gpointer data)
|
* gpointer data)
|
||||||
* {
|
* {
|
||||||
* GtkAdjustment *adjustment;
|
|
||||||
* char *text;
|
* char *text;
|
||||||
* int value;
|
* int value;
|
||||||
*
|
*
|
||||||
* adjustment = gtk_spin_button_get_adjustment (spin);
|
* value = gtk_spin_button_get_value_as_int (spin);
|
||||||
* value = (int)gtk_adjustment_get_value (adjustment);
|
|
||||||
* text = g_strdup_printf ("%02d", value);
|
* text = g_strdup_printf ("%02d", value);
|
||||||
* gtk_editable_set_text (GTK_EDITABLE (spin), text):
|
* gtk_editable_set_text (GTK_EDITABLE (spin), text):
|
||||||
* g_free (text);
|
* g_free (text);
|
||||||
|
|||||||
@@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
#include "gtkatcontextprivate.h"
|
#include "gtkatcontextprivate.h"
|
||||||
#include "gtkaccessibleprivate.h"
|
#include "gtkaccessibleprivate.h"
|
||||||
|
#include "gtkaccessibletextprivate.h"
|
||||||
#include "gtkdebug.h"
|
#include "gtkdebug.h"
|
||||||
#include "gtkenums.h"
|
#include "gtkenums.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtktypebuiltins.h"
|
#include "gtktypebuiltins.h"
|
||||||
#include "gtkaccessibletext-private.h"
|
|
||||||
|
|
||||||
struct _GtkTestATContext
|
struct _GtkTestATContext
|
||||||
{
|
{
|
||||||
|
|||||||
+41
-11
@@ -23,8 +23,9 @@
|
|||||||
|
|
||||||
#include "gtktextprivate.h"
|
#include "gtktextprivate.h"
|
||||||
|
|
||||||
#include "gtkaccessibletext-private.h"
|
#include "gtkaccessibletextprivate.h"
|
||||||
#include "gtkactionable.h"
|
#include "gtkactionable.h"
|
||||||
|
#include "gtkactionmuxerprivate.h"
|
||||||
#include "gtkadjustment.h"
|
#include "gtkadjustment.h"
|
||||||
#include "gtkbox.h"
|
#include "gtkbox.h"
|
||||||
#include "gtkbutton.h"
|
#include "gtkbutton.h"
|
||||||
@@ -43,22 +44,22 @@
|
|||||||
#include "gtkgestureclick.h"
|
#include "gtkgestureclick.h"
|
||||||
#include "gtkgesturesingle.h"
|
#include "gtkgesturesingle.h"
|
||||||
#include "gtkimageprivate.h"
|
#include "gtkimageprivate.h"
|
||||||
#include "gtkimcontextprivate.h"
|
|
||||||
#include "gtkimcontextsimple.h"
|
#include "gtkimcontextsimple.h"
|
||||||
#include "gtkimmulticontext.h"
|
#include "gtkimmulticontext.h"
|
||||||
#include <glib/gi18n-lib.h>
|
#include "gtkjoinedmenuprivate.h"
|
||||||
#include "gtklabel.h"
|
#include "gtklabel.h"
|
||||||
#include "gtkmagnifierprivate.h"
|
#include "gtkmagnifierprivate.h"
|
||||||
#include "gtkmain.h"
|
#include "gtkmain.h"
|
||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
|
#include "gtknative.h"
|
||||||
#include "gtkpangoprivate.h"
|
#include "gtkpangoprivate.h"
|
||||||
#include "gtkpopovermenu.h"
|
#include "gtkpopovermenu.h"
|
||||||
#include "gtkprivate.h"
|
#include "gtkprivate.h"
|
||||||
#include "gtksettings.h"
|
|
||||||
#include "gtksnapshot.h"
|
|
||||||
#include "gtkrenderbackgroundprivate.h"
|
#include "gtkrenderbackgroundprivate.h"
|
||||||
#include "gtkrenderborderprivate.h"
|
#include "gtkrenderborderprivate.h"
|
||||||
#include "gtkrenderlayoutprivate.h"
|
#include "gtkrenderlayoutprivate.h"
|
||||||
|
#include "gtksettings.h"
|
||||||
|
#include "gtksnapshot.h"
|
||||||
#include "gtktexthandleprivate.h"
|
#include "gtktexthandleprivate.h"
|
||||||
#include "gtktexthistoryprivate.h"
|
#include "gtktexthistoryprivate.h"
|
||||||
#include "gtktextutilprivate.h"
|
#include "gtktextutilprivate.h"
|
||||||
@@ -66,15 +67,13 @@
|
|||||||
#include "gtktypebuiltins.h"
|
#include "gtktypebuiltins.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkwidgetprivate.h"
|
||||||
#include "gtkwindow.h"
|
#include "gtkwindow.h"
|
||||||
#include "gtknative.h"
|
|
||||||
#include "gtkactionmuxerprivate.h"
|
|
||||||
#include "gtkjoinedmenuprivate.h"
|
|
||||||
#include "deprecated/gtkrender.h"
|
#include "deprecated/gtkrender.h"
|
||||||
#include "gtkaccessibletext-private.h"
|
|
||||||
#include "a11y/gtkatspipangoprivate.h"
|
#include "a11y/gtkatspipangoprivate.h"
|
||||||
|
|
||||||
#include <cairo-gobject.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <cairo-gobject.h>
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkText:
|
* GtkText:
|
||||||
@@ -2927,11 +2926,13 @@ gtk_text_click_gesture_released (GtkGestureClick *gesture,
|
|||||||
GtkText *self)
|
GtkText *self)
|
||||||
{
|
{
|
||||||
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
|
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
|
||||||
|
GdkEvent *event =
|
||||||
|
gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture));
|
||||||
|
|
||||||
if (n_press == 1 &&
|
if (n_press == 1 &&
|
||||||
!priv->in_drag &&
|
!priv->in_drag &&
|
||||||
priv->current_pos == priv->selection_bound)
|
priv->current_pos == priv->selection_bound)
|
||||||
gtk_im_context_activate_osk (priv->im_context);
|
gtk_im_context_activate_osk (priv->im_context, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@@ -7472,6 +7473,19 @@ gtk_text_accessible_text_get_contents (GtkAccessibleText *self,
|
|||||||
return g_bytes_new_take (string, size);
|
return g_bytes_new_take (string, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
gtk_text_accessible_text_get_contents_at (GtkAccessibleText *self,
|
||||||
|
unsigned int offset,
|
||||||
|
GtkAccessibleTextGranularity granularity,
|
||||||
|
unsigned int *start,
|
||||||
|
unsigned int *end)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_text_get_layout (GTK_TEXT (self));
|
||||||
|
char *string = gtk_pango_get_string_at (layout, offset, granularity, start, end);
|
||||||
|
|
||||||
|
return g_bytes_new_take (string, strlen (string));
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
gtk_text_accessible_text_get_caret_position (GtkAccessibleText *self)
|
gtk_text_accessible_text_get_caret_position (GtkAccessibleText *self)
|
||||||
{
|
{
|
||||||
@@ -7527,13 +7541,29 @@ gtk_text_accessible_text_get_attributes (GtkAccessibleText *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_text_accessible_text_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_text_get_layout (GTK_TEXT (self));
|
||||||
|
char **names, **values;
|
||||||
|
|
||||||
|
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||||
|
|
||||||
|
*attribute_names = names;
|
||||||
|
*attribute_values = values;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_text_accessible_text_init (GtkAccessibleTextInterface *iface)
|
gtk_text_accessible_text_init (GtkAccessibleTextInterface *iface)
|
||||||
{
|
{
|
||||||
iface->get_contents = gtk_text_accessible_text_get_contents;
|
iface->get_contents = gtk_text_accessible_text_get_contents;
|
||||||
|
iface->get_contents_at = gtk_text_accessible_text_get_contents_at;
|
||||||
iface->get_caret_position = gtk_text_accessible_text_get_caret_position;
|
iface->get_caret_position = gtk_text_accessible_text_get_caret_position;
|
||||||
iface->get_selection = gtk_text_accessible_text_get_selection;
|
iface->get_selection = gtk_text_accessible_text_get_selection;
|
||||||
iface->get_attributes = gtk_text_accessible_text_get_attributes;
|
iface->get_attributes = gtk_text_accessible_text_get_attributes;
|
||||||
|
iface->get_default_attributes = gtk_text_accessible_text_get_default_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set foldmethod=marker expandtab: */
|
/* vim:set foldmethod=marker expandtab: */
|
||||||
|
|||||||
+80
-61
@@ -5189,27 +5189,27 @@ gtk_wrap_mode_to_string (GtkWrapMode wrap_mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*< private >
|
/*< private >
|
||||||
* gtk_text_buffer_get_run_attributes:
|
* gtk_text_buffer_add_run_attributes:
|
||||||
* @buffer: the buffer to serialize
|
* @buffer: the buffer to serialize
|
||||||
* @builder: the target `GVariant` builder
|
|
||||||
* @offset: the offset into the text buffer
|
* @offset: the offset into the text buffer
|
||||||
|
* @attributes: a hash table of serialized text attributes
|
||||||
* @start_offset: (out): the start offset for the attributes run
|
* @start_offset: (out): the start offset for the attributes run
|
||||||
* @end_offset: (out): the end offset for the attributes run
|
* @end_offset: (out): the end offset for the attributes run
|
||||||
*
|
*
|
||||||
* Serializes the attributes inside a text buffer at the given offset.
|
* Serializes the attributes inside a text buffer at the given offset.
|
||||||
*
|
*
|
||||||
* All attributes are serializes as a dictionary of string keys
|
* All attributes are serialized as key/value string pairs inside the
|
||||||
* and string values, `a{ss}`.
|
* provided @attributes dictionary.
|
||||||
*
|
*
|
||||||
* The serialization format is private to GTK and should not be
|
* The serialization format is private to GTK and should not be
|
||||||
* considered stable.
|
* considered stable.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
gtk_text_buffer_add_run_attributes (GtkTextBuffer *buffer,
|
||||||
GVariantBuilder *builder,
|
int offset,
|
||||||
int offset,
|
GHashTable *attributes,
|
||||||
int *start_offset,
|
int *start_offset,
|
||||||
int *end_offset)
|
int *end_offset)
|
||||||
{
|
{
|
||||||
GtkTextIter iter;
|
GtkTextIter iter;
|
||||||
GSList *tags, *temp_tags;
|
GSList *tags, *temp_tags;
|
||||||
@@ -5240,7 +5240,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"style", &style,
|
"style", &style,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "style", pango_style_to_string (style));
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("style"),
|
||||||
|
g_strdup (pango_style_to_string (style)));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5256,7 +5258,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"variant", &variant,
|
"variant", &variant,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "variant", pango_variant_to_string (variant));
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("variant"),
|
||||||
|
g_strdup (pango_variant_to_string (variant)));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5272,7 +5276,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"stretch", &stretch,
|
"stretch", &stretch,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "stretch", pango_stretch_to_string (stretch));
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("stretch"),
|
||||||
|
g_strdup (pango_stretch_to_string (stretch)));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5288,7 +5294,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"justification", &justification,
|
"justification", &justification,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "justification", gtk_justification_to_string (justification));
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("justification"),
|
||||||
|
g_strdup (gtk_justification_to_string (justification)));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5303,7 +5311,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
if (direction != GTK_TEXT_DIR_NONE)
|
if (direction != GTK_TEXT_DIR_NONE)
|
||||||
{
|
{
|
||||||
val_set = TRUE;
|
val_set = TRUE;
|
||||||
g_variant_builder_add (builder, "{ss}", "direction", gtk_text_direction_to_string (direction));
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("direction"),
|
||||||
|
g_strdup (gtk_text_direction_to_string (direction)));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5320,7 +5330,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"wrap-mode", &wrap_mode,
|
"wrap-mode", &wrap_mode,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "wrap-mode", gtk_wrap_mode_to_string (wrap_mode));
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("wrap-mode"),
|
||||||
|
g_strdup (gtk_wrap_mode_to_string (wrap_mode)));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5342,8 +5354,8 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
(guint) rgba->green * 65535,
|
(guint) rgba->green * 65535,
|
||||||
(guint) rgba->blue * 65535);
|
(guint) rgba->blue * 65535);
|
||||||
gdk_rgba_free (rgba);
|
gdk_rgba_free (rgba);
|
||||||
g_variant_builder_add (builder, "{ss}", "fg-color", value);
|
|
||||||
g_free (value);
|
g_hash_table_insert (attributes, g_strdup ("fg-color"), value);
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5366,8 +5378,8 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
(guint) rgba->green * 65535,
|
(guint) rgba->green * 65535,
|
||||||
(guint) rgba->blue * 65535);
|
(guint) rgba->blue * 65535);
|
||||||
gdk_rgba_free (rgba);
|
gdk_rgba_free (rgba);
|
||||||
g_variant_builder_add (builder, "{ss}", "bg-color", value);
|
|
||||||
g_free (value);
|
g_hash_table_insert (attributes, g_strdup ("bg-color"), value);
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5384,8 +5396,8 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
g_object_get (tag, "family", &value, NULL);
|
g_object_get (tag, "family", &value, NULL);
|
||||||
g_variant_builder_add (builder, "{ss}", "family-name", value);
|
|
||||||
g_free (value);
|
g_hash_table_insert (attributes, g_strdup ("family-name"), value);
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5402,8 +5414,7 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
g_object_get (tag, "language", &value, NULL);
|
g_object_get (tag, "language", &value, NULL);
|
||||||
g_variant_builder_add (builder, "{ss}", "language", value);
|
g_hash_table_insert (attributes, g_strdup ("language"), value);
|
||||||
g_free (value);
|
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5422,10 +5433,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
|
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value;
|
g_hash_table_insert (attributes,
|
||||||
value = g_strdup_printf ("%d", weight);
|
g_strdup ("weight"),
|
||||||
g_variant_builder_add (builder, "{ss}", "weight", value);
|
g_strdup_printf ("%d", weight));
|
||||||
g_free (value);
|
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5452,9 +5462,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
}
|
}
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%g", scale);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "scale", value);
|
g_strdup ("scale"),
|
||||||
g_free (value);
|
g_strdup_printf ("%g", scale));
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
|
|
||||||
@@ -5470,9 +5480,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", size);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "size", value);
|
g_strdup ("size"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", size));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5489,7 +5499,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"strikethrough", &strikethrough,
|
"strikethrough", &strikethrough,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "strikethrough", strikethrough ? "true" : "false");
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("strikethrough"),
|
||||||
|
strikethrough ? g_strdup ("true") : g_strdup ("false"));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5505,8 +5517,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"underline", &underline,
|
"underline", &underline,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "underline",
|
g_hash_table_insert (attributes,
|
||||||
pango_underline_to_string (underline));
|
g_strdup ("underline"),
|
||||||
|
g_strdup (pango_underline_to_string (underline)));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5523,9 +5536,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", rise);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "rise", value);
|
g_strdup ("rise"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", rise));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5542,7 +5555,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"background-full-height", &bg_full_height,
|
"background-full-height", &bg_full_height,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "bg-full-height", bg_full_height ? "true" : "false");
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("bg-full-height"),
|
||||||
|
bg_full_height ? g_strdup ("true") : g_strdup ("false"));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5559,9 +5574,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", pixels);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "pixels-inside-wrap", value);
|
g_strdup ("pixels-inside-wrap"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", pixels));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5579,9 +5594,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", pixels);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "pixels-below-lines", value);
|
g_strdup ("pixels-below-lines"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", pixels));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5599,9 +5614,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", pixels);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "pixels-above-lines", value);
|
g_strdup ("pixels-above-lines"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", pixels));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5618,7 +5633,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"editable", &editable,
|
"editable", &editable,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "editable", editable ? "true" : "false");
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("editable"),
|
||||||
|
editable ? g_strdup ("true") : g_strdup ("false"));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
@@ -5634,12 +5651,14 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
"invisible", &invisible,
|
"invisible", &invisible,
|
||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
g_variant_builder_add (builder, "{ss}", "invisible", invisible ? "true" : "false");
|
g_hash_table_insert (attributes,
|
||||||
|
g_strdup ("invisible"),
|
||||||
|
invisible ? g_strdup ("true") : g_strdup ("false"));
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
val_set = FALSE;
|
val_set = FALSE;
|
||||||
|
|
||||||
temp_tags = tags;
|
temp_tags = tags;
|
||||||
while (temp_tags && !val_set)
|
while (temp_tags && !val_set)
|
||||||
{
|
{
|
||||||
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
|
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
|
||||||
@@ -5651,9 +5670,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", indent);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "indent", value);
|
g_strdup ("indent"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", indent));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5671,9 +5690,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", margin);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "right-margin", value);
|
g_strdup ("right-margin"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", margin));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
@@ -5691,9 +5710,9 @@ gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
|||||||
NULL);
|
NULL);
|
||||||
if (val_set)
|
if (val_set)
|
||||||
{
|
{
|
||||||
char *value = g_strdup_printf ("%i", margin);
|
g_hash_table_insert (attributes,
|
||||||
g_variant_builder_add (builder, "{ss}", "left-margin", value);
|
g_strdup ("left-margin"),
|
||||||
g_free (value);
|
g_strdup_printf ("%i", margin));
|
||||||
}
|
}
|
||||||
temp_tags = temp_tags->next;
|
temp_tags = temp_tags->next;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,10 @@ const char *gtk_justification_to_string (GtkJustification just);
|
|||||||
const char *gtk_text_direction_to_string (GtkTextDirection direction);
|
const char *gtk_text_direction_to_string (GtkTextDirection direction);
|
||||||
const char *gtk_wrap_mode_to_string (GtkWrapMode wrap_mode);
|
const char *gtk_wrap_mode_to_string (GtkWrapMode wrap_mode);
|
||||||
|
|
||||||
void gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
|
void gtk_text_buffer_add_run_attributes (GtkTextBuffer *buffer,
|
||||||
GVariantBuilder *builder,
|
|
||||||
int offset,
|
int offset,
|
||||||
|
GHashTable *attributes,
|
||||||
int *start_offset,
|
int *start_offset,
|
||||||
int *end_offset);
|
int *end_offset);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ struct _GtkTextLineDisplayCache
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GQueue purge_in_idle;
|
||||||
|
static guint purge_in_idle_source;
|
||||||
|
|
||||||
#if DEBUG_LINE_DISPLAY_CACHE
|
#if DEBUG_LINE_DISPLAY_CACHE
|
||||||
# define STAT_ADD(val,n) ((val) += n)
|
# define STAT_ADD(val,n) ((val) += n)
|
||||||
# define STAT_INC(val) STAT_ADD(val,1)
|
# define STAT_INC(val) STAT_ADD(val,1)
|
||||||
@@ -78,7 +81,7 @@ gtk_text_line_display_cache_new (void)
|
|||||||
GtkTextLineDisplayCache *ret;
|
GtkTextLineDisplayCache *ret;
|
||||||
|
|
||||||
ret = g_new0 (GtkTextLineDisplayCache, 1);
|
ret = g_new0 (GtkTextLineDisplayCache, 1);
|
||||||
ret->sorted_by_line = g_sequence_new ((GDestroyNotify)gtk_text_line_display_unref);
|
ret->sorted_by_line = g_sequence_new (NULL);
|
||||||
ret->line_to_display = g_hash_table_new (NULL, NULL);
|
ret->line_to_display = g_hash_table_new (NULL, NULL);
|
||||||
ret->mru_size = DEFAULT_MRU_SIZE;
|
ret->mru_size = DEFAULT_MRU_SIZE;
|
||||||
|
|
||||||
@@ -98,6 +101,8 @@ gtk_text_line_display_cache_free (GtkTextLineDisplayCache *cache)
|
|||||||
|
|
||||||
gtk_text_line_display_cache_invalidate (cache);
|
gtk_text_line_display_cache_invalidate (cache);
|
||||||
|
|
||||||
|
g_assert (g_sequence_get_begin_iter (cache->sorted_by_line) == g_sequence_get_end_iter (cache->sorted_by_line));
|
||||||
|
|
||||||
g_clear_pointer (&cache->evict_source, g_source_destroy);
|
g_clear_pointer (&cache->evict_source, g_source_destroy);
|
||||||
g_clear_pointer (&cache->sorted_by_line, g_sequence_free);
|
g_clear_pointer (&cache->sorted_by_line, g_sequence_free);
|
||||||
g_clear_pointer (&cache->line_to_display, g_hash_table_unref);
|
g_clear_pointer (&cache->line_to_display, g_hash_table_unref);
|
||||||
@@ -211,6 +216,31 @@ gtk_text_line_display_cache_take_display (GtkTextLineDisplayCache *cache,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
purge_text_line_display_in_idle (gpointer data)
|
||||||
|
{
|
||||||
|
GQueue q = purge_in_idle;
|
||||||
|
|
||||||
|
purge_in_idle.head = NULL;
|
||||||
|
purge_in_idle.tail = NULL;
|
||||||
|
purge_in_idle.length = 0;
|
||||||
|
|
||||||
|
while (q.head)
|
||||||
|
{
|
||||||
|
GtkTextLineDisplay *display = q.head->data;
|
||||||
|
g_queue_unlink (&q, &display->mru_link);
|
||||||
|
gtk_text_line_display_unref (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (purge_in_idle.head == NULL)
|
||||||
|
{
|
||||||
|
purge_in_idle_source = 0;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gtk_text_line_display_cache_invalidate_display:
|
* gtk_text_line_display_cache_invalidate_display:
|
||||||
* @cache: a GtkTextLineDisplayCache
|
* @cache: a GtkTextLineDisplayCache
|
||||||
@@ -250,7 +280,28 @@ gtk_text_line_display_cache_invalidate_display (GtkTextLineDisplayCache *cache,
|
|||||||
g_queue_unlink (&cache->mru, &display->mru_link);
|
g_queue_unlink (&cache->mru, &display->mru_link);
|
||||||
|
|
||||||
if (iter != NULL)
|
if (iter != NULL)
|
||||||
g_sequence_remove (iter);
|
{
|
||||||
|
g_sequence_remove (iter);
|
||||||
|
|
||||||
|
g_queue_push_head_link (&purge_in_idle, &display->mru_link);
|
||||||
|
|
||||||
|
/* Purging a lot of GtkTextLineDisplay while processing a frame
|
||||||
|
* can increase the chances that we miss our frame deadline. Instead
|
||||||
|
* defer that work to right after the frame has completed. This can
|
||||||
|
* help situations where we have large, zoomed out TextView like
|
||||||
|
* those used in an overview map.
|
||||||
|
*/
|
||||||
|
if G_UNLIKELY (purge_in_idle_source == 0)
|
||||||
|
{
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
purge_in_idle_source = g_idle_add_full (G_PRIORITY_LOW,
|
||||||
|
purge_text_line_display_in_idle,
|
||||||
|
NULL, NULL);
|
||||||
|
source = g_main_context_find_source_by_id (NULL, purge_in_idle_source);
|
||||||
|
g_source_set_static_name (source, "[gtk+ line-display-cache-gc]");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STAT_INC (cache->inval);
|
STAT_INC (cache->inval);
|
||||||
|
|||||||
+281
-59
@@ -29,41 +29,39 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
|
#include "gtkaccessibletextprivate.h"
|
||||||
#include "gtkadjustmentprivate.h"
|
#include "gtkadjustmentprivate.h"
|
||||||
#include "gtkcsscolorvalueprivate.h"
|
#include "gtkcsscolorvalueprivate.h"
|
||||||
|
#include "gtkcssenumvalueprivate.h"
|
||||||
|
#include "gtkcsslineheightvalueprivate.h"
|
||||||
#include "gtkdebug.h"
|
#include "gtkdebug.h"
|
||||||
#include "gtkdragsourceprivate.h"
|
#include "gtkdragsourceprivate.h"
|
||||||
#include "gtkdropcontrollermotion.h"
|
#include "gtkdropcontrollermotion.h"
|
||||||
#include <glib/gi18n-lib.h>
|
#include "gtkemojichooser.h"
|
||||||
|
#include "gtkimmulticontext.h"
|
||||||
|
#include "gtkjoinedmenuprivate.h"
|
||||||
|
#include "gtkmagnifierprivate.h"
|
||||||
#include "gtkmain.h"
|
#include "gtkmain.h"
|
||||||
#include "gtkmarshalers.h"
|
#include "gtkmarshalers.h"
|
||||||
#include "gtkrenderbackgroundprivate.h"
|
|
||||||
#include "gtksettings.h"
|
|
||||||
#include "gtktextiterprivate.h"
|
|
||||||
#include "gtkimcontextprivate.h"
|
|
||||||
#include "gtkimmulticontext.h"
|
|
||||||
#include "gtkprivate.h"
|
|
||||||
#include "gtktextutilprivate.h"
|
|
||||||
#include "gtktextbufferprivate.h"
|
|
||||||
#include "gtkwidgetprivate.h"
|
|
||||||
#include "gtkwindow.h"
|
|
||||||
#include "gtkscrollable.h"
|
|
||||||
#include "gtktypebuiltins.h"
|
|
||||||
#include "gtktextviewchildprivate.h"
|
|
||||||
#include "gtktexthandleprivate.h"
|
|
||||||
#include "gtkpopover.h"
|
|
||||||
#include "gtkmagnifierprivate.h"
|
|
||||||
#include "gtkemojichooser.h"
|
|
||||||
#include "gtkpangoprivate.h"
|
|
||||||
#include "gtknative.h"
|
#include "gtknative.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkpangoprivate.h"
|
||||||
#include "gtkjoinedmenuprivate.h"
|
|
||||||
#include "gtkcsslineheightvalueprivate.h"
|
|
||||||
#include "gtkcssenumvalueprivate.h"
|
|
||||||
#include "gtksnapshot.h"
|
|
||||||
#include "gtkrenderbackgroundprivate.h"
|
#include "gtkrenderbackgroundprivate.h"
|
||||||
#include "gtkrenderborderprivate.h"
|
#include "gtkrenderborderprivate.h"
|
||||||
#include "gtkaccessibletext-private.h"
|
#include "gtkscrollable.h"
|
||||||
|
#include "gtksettings.h"
|
||||||
|
#include "gtksnapshot.h"
|
||||||
|
#include "gtktextiterprivate.h"
|
||||||
|
#include "gtktexthandleprivate.h"
|
||||||
|
#include "gtktextviewchildprivate.h"
|
||||||
|
#include "gtkpopover.h"
|
||||||
|
#include "gtkprivate.h"
|
||||||
|
#include "gtktextbufferprivate.h"
|
||||||
|
#include "gtktextutilprivate.h"
|
||||||
|
#include "gtktypebuiltins.h"
|
||||||
|
#include "gtkwidgetprivate.h"
|
||||||
|
#include "gtkwindow.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GtkTextView:
|
* GtkTextView:
|
||||||
@@ -831,6 +829,17 @@ add_move_binding (GtkWidgetClass *widget_class,
|
|||||||
"(iib)", step, count, TRUE);
|
"(iib)", step, count, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_text_view_notify (GObject *object,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
if (pspec->name == I_("has-focus"))
|
||||||
|
gtk_text_view_check_cursor_blink (GTK_TEXT_VIEW (object));
|
||||||
|
|
||||||
|
if (G_OBJECT_CLASS (gtk_text_view_parent_class)->notify)
|
||||||
|
G_OBJECT_CLASS (gtk_text_view_parent_class)->notify (object, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_text_view_class_init (GtkTextViewClass *klass)
|
gtk_text_view_class_init (GtkTextViewClass *klass)
|
||||||
{
|
{
|
||||||
@@ -843,6 +852,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
|
|||||||
gobject_class->get_property = gtk_text_view_get_property;
|
gobject_class->get_property = gtk_text_view_get_property;
|
||||||
gobject_class->finalize = gtk_text_view_finalize;
|
gobject_class->finalize = gtk_text_view_finalize;
|
||||||
gobject_class->dispose = gtk_text_view_dispose;
|
gobject_class->dispose = gtk_text_view_dispose;
|
||||||
|
gobject_class->notify = gtk_text_view_notify;
|
||||||
|
|
||||||
widget_class->realize = gtk_text_view_realize;
|
widget_class->realize = gtk_text_view_realize;
|
||||||
widget_class->unrealize = gtk_text_view_unrealize;
|
widget_class->unrealize = gtk_text_view_unrealize;
|
||||||
@@ -5765,6 +5775,8 @@ gtk_text_view_click_gesture_released (GtkGestureClick *gesture,
|
|||||||
double y,
|
double y,
|
||||||
GtkTextView *text_view)
|
GtkTextView *text_view)
|
||||||
{
|
{
|
||||||
|
GdkEvent *event =
|
||||||
|
gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture));
|
||||||
GtkTextViewPrivate *priv = text_view->priv;
|
GtkTextViewPrivate *priv = text_view->priv;
|
||||||
GtkTextBuffer *buffer;
|
GtkTextBuffer *buffer;
|
||||||
GtkTextIter start, end;
|
GtkTextIter start, end;
|
||||||
@@ -5774,7 +5786,7 @@ gtk_text_view_click_gesture_released (GtkGestureClick *gesture,
|
|||||||
|
|
||||||
if (gtk_text_iter_compare (&start, &end) == 0 &&
|
if (gtk_text_iter_compare (&start, &end) == 0 &&
|
||||||
gtk_text_iter_can_insert (&start, priv->editable))
|
gtk_text_iter_can_insert (&start, priv->editable))
|
||||||
gtk_im_context_activate_osk (priv->im_context);
|
gtk_im_context_activate_osk (priv->im_context, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -6070,28 +6082,35 @@ gtk_text_view_remove (GtkTextView *text_view,
|
|||||||
static gboolean
|
static gboolean
|
||||||
cursor_blinks (GtkTextView *text_view)
|
cursor_blinks (GtkTextView *text_view)
|
||||||
{
|
{
|
||||||
GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (text_view));
|
GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (text_view));
|
||||||
gboolean blink;
|
|
||||||
|
|
||||||
#ifdef DEBUG_VALIDATION_AND_SCROLLING
|
#ifdef DEBUG_VALIDATION_AND_SCROLLING
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_object_get (settings, "gtk-cursor-blink", &blink, NULL);
|
if (gtk_widget_get_mapped (GTK_WIDGET (text_view)) &&
|
||||||
|
gtk_window_is_active (GTK_WINDOW (root)) &&
|
||||||
if (!blink)
|
gtk_widget_has_focus (GTK_WIDGET (text_view)))
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (text_view->priv->editable)
|
|
||||||
{
|
{
|
||||||
GtkTextMark *insert;
|
GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (text_view));
|
||||||
GtkTextIter iter;
|
gboolean blink;
|
||||||
|
|
||||||
insert = gtk_text_buffer_get_insert (get_buffer (text_view));
|
g_object_get (settings, "gtk-cursor-blink", &blink, NULL);
|
||||||
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert);
|
|
||||||
|
|
||||||
if (gtk_text_iter_editable (&iter, text_view->priv->editable))
|
if (!blink)
|
||||||
return blink;
|
return FALSE;
|
||||||
|
|
||||||
|
if (text_view->priv->editable)
|
||||||
|
{
|
||||||
|
GtkTextMark *insert;
|
||||||
|
GtkTextIter iter;
|
||||||
|
|
||||||
|
insert = gtk_text_buffer_get_insert (get_buffer (text_view));
|
||||||
|
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert);
|
||||||
|
|
||||||
|
if (gtk_text_iter_editable (&iter, text_view->priv->editable))
|
||||||
|
return blink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -10383,6 +10402,39 @@ gtk_text_view_accessible_text_get_contents (GtkAccessibleText *self,
|
|||||||
return g_bytes_new_take (string, strlen (string) + 1);
|
return g_bytes_new_take (string, strlen (string) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
gtk_text_view_accessible_text_get_contents_at (GtkAccessibleText *self,
|
||||||
|
unsigned int offset,
|
||||||
|
GtkAccessibleTextGranularity granularity,
|
||||||
|
unsigned int *start,
|
||||||
|
unsigned int *end)
|
||||||
|
{
|
||||||
|
GtkTextViewPrivate *priv = GTK_TEXT_VIEW (self)->priv;
|
||||||
|
GtkTextLayout *text_layout = priv->layout;
|
||||||
|
GtkTextBuffer *text_buffer;
|
||||||
|
GtkTextIter iter;
|
||||||
|
GtkTextLine *line;
|
||||||
|
PangoLayout *line_layout;
|
||||||
|
char *string;
|
||||||
|
unsigned int line_start, line_end, line_offset;
|
||||||
|
|
||||||
|
text_buffer = gtk_text_layout_get_buffer (text_layout);
|
||||||
|
|
||||||
|
gtk_text_buffer_get_iter_at_offset (text_buffer, &iter, offset);
|
||||||
|
line = _gtk_text_iter_get_text_line (&iter);
|
||||||
|
line_offset = gtk_text_iter_get_offset (&iter) - gtk_text_iter_get_line_offset (&iter);
|
||||||
|
|
||||||
|
line_layout = gtk_text_layout_get_line_display (text_layout, line, FALSE)->layout;
|
||||||
|
string = gtk_pango_get_string_at (line_layout, offset - line_offset, granularity, &line_start, &line_end);
|
||||||
|
|
||||||
|
if (start != NULL)
|
||||||
|
*start = line_offset + line_start;
|
||||||
|
if (end != NULL)
|
||||||
|
*end = line_offset + line_end;
|
||||||
|
|
||||||
|
return g_bytes_new_take (string, strlen (string));
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
gtk_text_view_accessible_text_get_caret_position (GtkAccessibleText *self)
|
gtk_text_view_accessible_text_get_caret_position (GtkAccessibleText *self)
|
||||||
{
|
{
|
||||||
@@ -10406,7 +10458,10 @@ gtk_text_view_accessible_text_get_selection (GtkAccessibleText *self,
|
|||||||
int start, end;
|
int start, end;
|
||||||
|
|
||||||
if (!gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
|
if (!gtk_text_buffer_get_selection_bounds (buffer, &start_iter, &end_iter))
|
||||||
return FALSE;
|
{
|
||||||
|
*n_ranges = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
start = gtk_text_iter_get_offset (&start_iter);
|
start = gtk_text_iter_get_offset (&start_iter);
|
||||||
end = gtk_text_iter_get_offset (&end_iter);
|
end = gtk_text_iter_get_offset (&end_iter);
|
||||||
@@ -10429,49 +10484,216 @@ gtk_text_view_accessible_text_get_attributes (GtkAccessibleText *self,
|
|||||||
char ***attribute_values)
|
char ***attribute_values)
|
||||||
{
|
{
|
||||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self));
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self));
|
||||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
GHashTable *attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
guint n_attrs, i;
|
||||||
int start, end;
|
int start, end;
|
||||||
|
|
||||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
gtk_text_buffer_add_run_attributes (buffer, offset, attrs, &start, &end);
|
||||||
|
|
||||||
GVariant *v = g_variant_builder_end (&builder);
|
n_attrs = g_hash_table_size (attrs);
|
||||||
unsigned n = g_variant_n_children (v);
|
if (n_attrs == 0)
|
||||||
if (n == 0)
|
|
||||||
{
|
{
|
||||||
g_variant_unref (v);
|
g_hash_table_unref (attrs);
|
||||||
|
*n_ranges = 0;
|
||||||
|
*ranges = NULL;
|
||||||
|
*attribute_names = NULL;
|
||||||
|
*attribute_values = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*n_ranges = n;
|
*n_ranges = n_attrs;
|
||||||
*ranges = g_new (GtkAccessibleTextRange, n);
|
*ranges = g_new (GtkAccessibleTextRange, n_attrs);
|
||||||
*attribute_names = g_new (char *, n + 1);
|
*attribute_names = g_new (char *, n_attrs + 1);
|
||||||
*attribute_values = g_new (char *, n + 1);
|
*attribute_values = g_new (char *, n_attrs + 1);
|
||||||
|
|
||||||
for (int i = 0; i < n; i++)
|
i = 0;
|
||||||
|
g_hash_table_iter_init (&iter, attrs);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
{
|
{
|
||||||
char *name, *value;
|
|
||||||
|
|
||||||
((*ranges)[i]).start = start;
|
((*ranges)[i]).start = start;
|
||||||
((*ranges)[i]).length = end - start;
|
((*ranges)[i]).length = end - start;
|
||||||
|
|
||||||
g_variant_get_child (v, i, "{ss}", &name, &value);
|
(*attribute_names)[i] = g_strdup (key);
|
||||||
(*attribute_names)[i] = g_steal_pointer (&name);
|
(*attribute_values)[i] = g_strdup (value);
|
||||||
(*attribute_values)[i] = g_steal_pointer (&value);
|
|
||||||
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*attribute_names)[n] = NULL;
|
(*attribute_names)[n_attrs] = NULL;
|
||||||
(*attribute_values)[n] = NULL;
|
(*attribute_values)[n_attrs] = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_text_view_add_default_attributes (GtkTextView *view,
|
||||||
|
GHashTable *attributes)
|
||||||
|
{
|
||||||
|
GtkTextAttributes *text_attrs;
|
||||||
|
PangoFontDescription *font;
|
||||||
|
|
||||||
|
text_attrs = gtk_text_view_get_default_attributes (view);
|
||||||
|
|
||||||
|
font = text_attrs->font;
|
||||||
|
|
||||||
|
if (font)
|
||||||
|
{
|
||||||
|
char **names, **values;
|
||||||
|
|
||||||
|
gtk_pango_get_font_attributes (font, &names, &values);
|
||||||
|
|
||||||
|
for (unsigned i = 0; names[i] != NULL; i++)
|
||||||
|
g_hash_table_insert (attributes,
|
||||||
|
g_steal_pointer (&names[i]),
|
||||||
|
g_steal_pointer (&values[i]));
|
||||||
|
|
||||||
|
g_free (names);
|
||||||
|
g_free (values);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_STR_ATTR(ht,name,value) \
|
||||||
|
g_hash_table_insert ((ht), g_strdup ((name)), g_strdup ((value)))
|
||||||
|
|
||||||
|
#define ADD_BOOL_ATTR(ht,name,value) \
|
||||||
|
g_hash_table_insert ((ht), g_strdup ((name)), (value) ? g_strdup ("true") : g_strdup ("false"))
|
||||||
|
|
||||||
|
#define ADD_COLOR_ATTR(ht,name,color) G_STMT_START { \
|
||||||
|
char *__value = g_strdup_printf ("%u,%u,%u", \
|
||||||
|
(guint) ((color)->red * 65535), \
|
||||||
|
(guint) ((color)->green * 65535), \
|
||||||
|
(guint) ((color)->blue * 65535)); \
|
||||||
|
g_hash_table_insert (ht, g_strdup (name), __value); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define ADD_FLOAT_ATTR(ht,name,value) G_STMT_START { \
|
||||||
|
char *__value = g_strdup_printf ("%g", (value)); \
|
||||||
|
g_hash_table_insert (ht, g_strdup (name), __value); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define ADD_INT_ATTR(ht,name,value) G_STMT_START { \
|
||||||
|
char *__value = g_strdup_printf ("%i", (value)); \
|
||||||
|
g_hash_table_insert (ht, g_strdup (name), __value); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
ADD_STR_ATTR (attributes, "justification", gtk_justification_to_string (text_attrs->justification));
|
||||||
|
ADD_STR_ATTR (attributes, "direction", gtk_text_direction_to_string (text_attrs->direction));
|
||||||
|
ADD_STR_ATTR (attributes, "wrap-mode", gtk_wrap_mode_to_string (text_attrs->wrap_mode));
|
||||||
|
ADD_STR_ATTR (attributes, "underline", pango_underline_to_string (text_attrs->appearance.underline));
|
||||||
|
|
||||||
|
ADD_BOOL_ATTR (attributes, "editable", text_attrs->editable);
|
||||||
|
ADD_BOOL_ATTR (attributes, "invisible", text_attrs->invisible);
|
||||||
|
ADD_BOOL_ATTR (attributes, "bg-full-height", text_attrs->bg_full_height);
|
||||||
|
ADD_BOOL_ATTR (attributes, "strikethrough", text_attrs->appearance.strikethrough);
|
||||||
|
|
||||||
|
ADD_COLOR_ATTR (attributes, "bg-color", text_attrs->appearance.bg_rgba);
|
||||||
|
ADD_COLOR_ATTR (attributes, "fg-color", text_attrs->appearance.fg_rgba);
|
||||||
|
|
||||||
|
ADD_FLOAT_ATTR (attributes, "scale", text_attrs->font_scale);
|
||||||
|
|
||||||
|
ADD_STR_ATTR (attributes, "language", (const char *) text_attrs->language);
|
||||||
|
|
||||||
|
ADD_INT_ATTR (attributes, "rise", text_attrs->appearance.rise);
|
||||||
|
ADD_INT_ATTR (attributes, "pixels-inside-wrap", text_attrs->pixels_inside_wrap);
|
||||||
|
ADD_INT_ATTR (attributes, "pixels-below-lines", text_attrs->pixels_below_lines);
|
||||||
|
ADD_INT_ATTR (attributes, "pixels-above-lines", text_attrs->pixels_above_lines);
|
||||||
|
ADD_INT_ATTR (attributes, "indent", text_attrs->indent);
|
||||||
|
ADD_INT_ATTR (attributes, "left-margin", text_attrs->left_margin);
|
||||||
|
ADD_INT_ATTR (attributes, "right-margin", text_attrs->right_margin);
|
||||||
|
|
||||||
|
#undef ADD_STR_ATTR
|
||||||
|
#undef ADD_BOOL_ATTR
|
||||||
|
#undef ADD_COLOR_ATTR
|
||||||
|
#undef ADD_FLOAT_ATTR
|
||||||
|
#undef ADD_INT_ATTR
|
||||||
|
|
||||||
|
gtk_text_attributes_unref (text_attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*< private >
|
||||||
|
* gtk_text_view_get_attributes_run:
|
||||||
|
* @self: a text view
|
||||||
|
* @offset: the offset, in characters
|
||||||
|
* @include_defaults: whether the default attributes should be included
|
||||||
|
* @start: (out): the beginning of the run, in characters
|
||||||
|
* @end: (out): the end of the run, in characters
|
||||||
|
*
|
||||||
|
* Retrieves the text attributes at the given offset.
|
||||||
|
*
|
||||||
|
* The serialization format is private to GTK, but conforms to the AT-SPI
|
||||||
|
* text attributes for default attribute names.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full) (element-type utf8,utf8): a dictionary of
|
||||||
|
* text attributes
|
||||||
|
*/
|
||||||
|
GHashTable *
|
||||||
|
gtk_text_view_get_attributes_run (GtkTextView *self,
|
||||||
|
int offset,
|
||||||
|
gboolean include_defaults,
|
||||||
|
int *start,
|
||||||
|
int *end)
|
||||||
|
{
|
||||||
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer (self);
|
||||||
|
GHashTable *attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
|
if (include_defaults)
|
||||||
|
gtk_text_view_add_default_attributes (self, attrs);
|
||||||
|
|
||||||
|
gtk_text_buffer_add_run_attributes (buffer, offset, attrs, start, end);
|
||||||
|
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_text_view_accessible_text_get_default_attributes (GtkAccessibleText *self,
|
||||||
|
char ***attribute_names,
|
||||||
|
char ***attribute_values)
|
||||||
|
{
|
||||||
|
GHashTable *attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
guint n_attrs, i;
|
||||||
|
|
||||||
|
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (self), attrs);
|
||||||
|
|
||||||
|
n_attrs = g_hash_table_size (attrs);
|
||||||
|
if (n_attrs == 0)
|
||||||
|
{
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
|
*attribute_names = NULL;
|
||||||
|
*attribute_values = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*attribute_names = g_new (char *, n_attrs + 1);
|
||||||
|
*attribute_values = g_new (char *, n_attrs + 1);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
g_hash_table_iter_init (&iter, attrs);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
|
{
|
||||||
|
(*attribute_names)[i] = g_strdup (key);
|
||||||
|
(*attribute_values)[i] = g_strdup (value);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*attribute_names)[n_attrs] = NULL;
|
||||||
|
(*attribute_values)[n_attrs] = NULL;
|
||||||
|
|
||||||
|
g_hash_table_unref (attrs);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_text_view_accessible_text_init (GtkAccessibleTextInterface *iface)
|
gtk_text_view_accessible_text_init (GtkAccessibleTextInterface *iface)
|
||||||
{
|
{
|
||||||
iface->get_contents = gtk_text_view_accessible_text_get_contents;
|
iface->get_contents = gtk_text_view_accessible_text_get_contents;
|
||||||
|
iface->get_contents_at = gtk_text_view_accessible_text_get_contents_at;
|
||||||
iface->get_caret_position = gtk_text_view_accessible_text_get_caret_position;
|
iface->get_caret_position = gtk_text_view_accessible_text_get_caret_position;
|
||||||
iface->get_selection = gtk_text_view_accessible_text_get_selection;
|
iface->get_selection = gtk_text_view_accessible_text_get_selection;
|
||||||
iface->get_attributes = gtk_text_view_accessible_text_get_attributes;
|
iface->get_attributes = gtk_text_view_accessible_text_get_attributes;
|
||||||
|
iface->get_default_attributes = gtk_text_view_accessible_text_get_default_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|||||||
@@ -254,8 +254,6 @@ gtk_text_view_child_snapshot (GtkWidget *widget,
|
|||||||
GtkTextViewChild *self = GTK_TEXT_VIEW_CHILD (widget);
|
GtkTextViewChild *self = GTK_TEXT_VIEW_CHILD (widget);
|
||||||
const GList *iter;
|
const GList *iter;
|
||||||
|
|
||||||
GTK_WIDGET_CLASS (gtk_text_view_child_parent_class)->snapshot (widget, snapshot);
|
|
||||||
|
|
||||||
if (self->child)
|
if (self->child)
|
||||||
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ GtkTextAttributes * gtk_text_view_get_default_attributes (GtkTextView *text_view
|
|||||||
|
|
||||||
GtkEventController *gtk_text_view_get_key_controller (GtkTextView *text_view);
|
GtkEventController *gtk_text_view_get_key_controller (GtkTextView *text_view);
|
||||||
|
|
||||||
|
GHashTable * gtk_text_view_get_attributes_run (GtkTextView *self,
|
||||||
|
int offset,
|
||||||
|
gboolean include_defaults,
|
||||||
|
int *start,
|
||||||
|
int *end);
|
||||||
|
void gtk_text_view_add_default_attributes (GtkTextView *view,
|
||||||
|
GHashTable *attributes);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user