Compare commits
7 Commits
gpu-desc-n
...
glyph-cach
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c476c45007 | ||
|
|
5d05270ca7 | ||
|
|
34fb85afd1 | ||
|
|
05bc4a86c7 | ||
|
|
93302cc42d | ||
|
|
976f45e614 | ||
|
|
befccc943a |
@@ -219,13 +219,11 @@ macos:
|
||||
- if: $RUNNER == "macosintel"
|
||||
variables:
|
||||
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
|
||||
allow_failure: true
|
||||
- if: $RUNNER == "macosarm"
|
||||
variables:
|
||||
SDKROOT: /opt/sdks/MacOSX11.3.sdk
|
||||
NINJA_PKG: ninja==1.11.1.1
|
||||
stage: build
|
||||
parallel:
|
||||
matrix:
|
||||
@@ -248,7 +246,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/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
|
||||
- pip3 install meson==1.3.2 $NINJA_PKG
|
||||
- pip3 install meson==1.3.2 ninja==1.11.1.1
|
||||
# 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
|
||||
# subproject.
|
||||
|
||||
108
NEWS
108
NEWS
@@ -1,115 +1,11 @@
|
||||
Overview of Changes in 4.14.1, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
|
||||
Overview of Changes in 4.14.0, 12-03-2024
|
||||
Overview of Changes in 4.13.9, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Note: The new renderers and dmabuf support are using graphics drivers
|
||||
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
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/issues/6388). Therefore, it is
|
||||
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
|
||||
recommended to use the latest mesa release (24.0) with the new renderers.
|
||||
|
||||
|
||||
Overview of Changes in 4.13.8, 20-02-2024
|
||||
|
||||
@@ -600,8 +600,8 @@ update_display (void)
|
||||
if (s->len > 0)
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
@@ -116,9 +116,7 @@ static gboolean gtk_shadertoy_tick (GtkWidget *widget,
|
||||
GtkWidget *
|
||||
gtk_shadertoy_new (void)
|
||||
{
|
||||
return g_object_new (gtk_shadertoy_get_type (),
|
||||
"allowed-apis", GDK_GL_API_GL,
|
||||
NULL);
|
||||
return g_object_new (gtk_shadertoy_get_type (), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -354,7 +354,6 @@ do_images (GtkWidget *do_widget)
|
||||
gicon = g_themed_icon_new_with_default_fallbacks ("battery-caution-charging-symbolic");
|
||||
image = gtk_image_new_from_gicon (gicon);
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
g_object_unref (gicon);
|
||||
|
||||
gtk_frame_set_child (GTK_FRAME (frame), image);
|
||||
|
||||
|
||||
@@ -322,14 +322,12 @@ stroke bounds of the path.
|
||||
|
||||
### text
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| ------------ | ------------------- | ------------------- | ----------- |
|
||||
| color | `<color>` | black | non-default |
|
||||
| font | `<string>` `<url>`? | "Cantarell 15px" | always |
|
||||
| glyphs | `<glyphs>` | "Hello" | always |
|
||||
| offset | `<point>` | 0 0 | non-default |
|
||||
| hint-style | `<hint style>` | slight | non-default |
|
||||
| antialias | `<antialias>` | gray | non-default |
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ------------------- | ------------------- | ----------- |
|
||||
| color | `<color>` | black | non-default |
|
||||
| font | `<string>` `<url>`? | "Cantarell 11" | always |
|
||||
| glyphs | `<glyphs>` | "Hello" | always |
|
||||
| offset | `<point>` | 0 0 | non-default |
|
||||
|
||||
Creates a node like `gsk_text_node_new()` with the given properties.
|
||||
|
||||
@@ -338,15 +336,12 @@ 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.
|
||||
|
||||
Glyphs can be specified as an ASCII string, or as a comma-separated list of
|
||||
their glyph IDs. Optionally, the advance width, x and y offsets and flags can
|
||||
their glyph ID and advance width. Optionally, x and y offsets and flags can
|
||||
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
|
||||
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
|
||||
|
||||
| property | syntax | default | printed |
|
||||
|
||||
@@ -69,9 +69,9 @@ Image:
|
||||
4 CARD32 IMAGE_DATA_OFFSET
|
||||
|
||||
ICON_FLAGS
|
||||
HAS_SUFFIX_XPM 1
|
||||
HAS_SUFFIX_SVG 2
|
||||
HAS_SUFFIX_PNG 4
|
||||
HAS_SUFFIX_PNG 1
|
||||
HAS_SUFFIX_XPM 2
|
||||
HAS_SUFFIX_SVG 4
|
||||
HAS_ICON_FILE 8
|
||||
|
||||
ImageData:
|
||||
|
||||
@@ -2037,12 +2037,9 @@ gdk_display_get_dmabuf_formats (GdkDisplay *display)
|
||||
GdkDebugFlags
|
||||
gdk_display_get_debug_flags (GdkDisplay *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return _gdk_debug_flags;
|
||||
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
return priv->debug_flags;
|
||||
return display ? priv->debug_flags : _gdk_debug_flags;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -79,23 +79,14 @@ static guint signals[LAST_SIGNAL];
|
||||
|
||||
static guint fps_counter;
|
||||
|
||||
/* 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"
|
||||
#define FRAME_HISTORY_MAX_LENGTH 128
|
||||
|
||||
struct _GdkFrameClockPrivate
|
||||
{
|
||||
gint64 frame_counter;
|
||||
int n_timings;
|
||||
int current;
|
||||
Timings timings;
|
||||
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
|
||||
int n_freeze_inhibitors;
|
||||
};
|
||||
|
||||
@@ -108,8 +99,11 @@ static void
|
||||
gdk_frame_clock_finalize (GObject *object)
|
||||
{
|
||||
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
|
||||
int i;
|
||||
|
||||
timings_clear (&priv->timings);
|
||||
for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++)
|
||||
if (priv->timings[i] != 0)
|
||||
gdk_frame_timings_unref (priv->timings[i]);
|
||||
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -263,8 +257,7 @@ gdk_frame_clock_init (GdkFrameClock *clock)
|
||||
clock->priv = priv = gdk_frame_clock_get_instance_private (clock);
|
||||
|
||||
priv->frame_counter = -1;
|
||||
priv->current = 0;
|
||||
timings_init (&priv->timings);
|
||||
priv->current = FRAME_HISTORY_MAX_LENGTH - 1;
|
||||
|
||||
if (fps_counter == 0)
|
||||
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
|
||||
@@ -423,7 +416,7 @@ gdk_frame_clock_get_frame_counter (GdkFrameClock *frame_clock)
|
||||
static inline gint64
|
||||
_gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||
{
|
||||
return frame_clock->priv->frame_counter + 1 - timings_get_size (&frame_clock->priv->timings);
|
||||
return frame_clock->priv->frame_counter + 1 - frame_clock->priv->n_timings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,44 +445,31 @@ gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock,
|
||||
gint64 monotonic_time)
|
||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
priv = frame_clock->priv;
|
||||
|
||||
priv->frame_counter++;
|
||||
priv->current = (priv->current + 1) % FRAME_HISTORY_MAX_LENGTH;
|
||||
|
||||
if (G_UNLIKELY (timings_get_size (&priv->timings) == 0))
|
||||
timings_append (&priv->timings, _gdk_frame_timings_new (priv->frame_counter));
|
||||
/* Try to steal the previous frame timing instead of discarding
|
||||
* and allocating a new one.
|
||||
*/
|
||||
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
|
||||
{
|
||||
GdkFrameTimings *timings;
|
||||
gdk_frame_timings_unref (priv->timings[priv->current]);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
priv->timings[priv->current] = _gdk_frame_timings_new (priv->frame_counter);
|
||||
}
|
||||
|
||||
static inline GdkFrameTimings *
|
||||
@@ -497,21 +477,17 @@ _gdk_frame_clock_get_timings (GdkFrameClock *frame_clock,
|
||||
gint64 frame_counter)
|
||||
{
|
||||
GdkFrameClockPrivate *priv = frame_clock->priv;
|
||||
gsize size, pos;
|
||||
int pos;
|
||||
|
||||
if (frame_counter > priv->frame_counter)
|
||||
return NULL;
|
||||
|
||||
size = timings_get_size (&priv->timings);
|
||||
if (G_UNLIKELY (size == 0))
|
||||
if (frame_counter <= priv->frame_counter - priv->n_timings)
|
||||
return NULL;
|
||||
|
||||
if (priv->frame_counter - frame_counter >= size)
|
||||
return NULL;
|
||||
pos = (priv->current - (priv->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
|
||||
|
||||
pos = (priv->current - (priv->frame_counter - frame_counter) + size) % size;
|
||||
|
||||
return timings_get (&priv->timings, pos);
|
||||
return priv->timings[pos];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -803,10 +779,7 @@ gdk_frame_clock_get_fps (GdkFrameClock *frame_clock)
|
||||
|
||||
start_counter = _gdk_frame_clock_get_history_start (frame_clock);
|
||||
end_counter = _gdk_frame_clock_get_frame_counter (frame_clock);
|
||||
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++;
|
||||
start = _gdk_frame_clock_get_timings (frame_clock, start_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 = _gdk_frame_clock_get_timings (frame_clock, end_counter))
|
||||
|
||||
@@ -192,13 +192,6 @@ compute_smooth_frame_time (GdkFrameClock *clock,
|
||||
* and new_frame_time >= old_frame_time. */
|
||||
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
|
||||
* last smoothed frame time. This way we avoid minor jitter in the
|
||||
* frame times making the animation speed uneven, but still animate
|
||||
@@ -555,7 +548,7 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
priv->smoothed_frame_time_period = frame_interval;
|
||||
priv->smoothed_frame_time_reported = priv->smoothed_frame_time_base;
|
||||
|
||||
_gdk_frame_clock_begin_frame (clock, priv->frame_time);
|
||||
_gdk_frame_clock_begin_frame (clock);
|
||||
/* Note "current" is different now so timings != prev_timings */
|
||||
timings = gdk_frame_clock_get_current_timings (clock);
|
||||
|
||||
|
||||
@@ -106,8 +106,7 @@ struct _GdkFrameTimings
|
||||
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
||||
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock,
|
||||
gint64 monotonic_time);
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
||||
GdkFrameTimings *timings);
|
||||
void _gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *frame_clock,
|
||||
|
||||
@@ -658,7 +658,6 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
EGLSurface egl_surface;
|
||||
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (priv->egl_context == NULL)
|
||||
return;
|
||||
@@ -667,6 +666,8 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
egl_surface = gdk_surface_get_egl_surface (surface);
|
||||
|
||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "EGL swap buffers", NULL);
|
||||
|
||||
if (priv->eglSwapBuffersWithDamage)
|
||||
{
|
||||
EGLint stack_rects[4 * 4]; /* 4 rects */
|
||||
@@ -697,8 +698,6 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
else
|
||||
eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
|
||||
#endif
|
||||
|
||||
gdk_profiler_add_mark (begin_time, GDK_PROFILER_CURRENT_TIME - begin_time, "EGL swap buffers", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -260,11 +260,6 @@ gdk_vulkan_strerror (VkResult result)
|
||||
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)";
|
||||
#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:
|
||||
default:
|
||||
return "Unknown Vulkan error.";
|
||||
|
||||
@@ -214,6 +214,22 @@ 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
|
||||
styleMask:(NSWindowStyleMask)styleMask
|
||||
backing:(NSBackingStoreType)backingType
|
||||
@@ -371,17 +387,12 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
-(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]);
|
||||
}
|
||||
|
||||
-(void)windowDidResize:(NSNotification *)notification
|
||||
{
|
||||
[self windowDidMove: notification];
|
||||
_gdk_macos_surface_configure (gdk_surface);
|
||||
|
||||
/* If we're using server-side decorations, this notification is coming
|
||||
* in from a display-side change. We need to request a layout in
|
||||
@@ -402,6 +413,7 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
-(void)beginManualMove
|
||||
{
|
||||
gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
|
||||
NSPoint initialMoveLocation;
|
||||
GdkPoint point;
|
||||
GdkMonitor *monitor;
|
||||
@@ -420,6 +432,13 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
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],
|
||||
initialMoveLocation.x,
|
||||
initialMoveLocation.y,
|
||||
@@ -762,11 +781,43 @@ typedef NSString *CALayerContentsGravity;
|
||||
return rect;
|
||||
}
|
||||
|
||||
/* Implementing this method avoids new windows move around the screen. */
|
||||
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
|
||||
defaultFrame:(NSRect)newFrame
|
||||
{
|
||||
return newFrame;
|
||||
NSRect screenFrame = [[self screen] visibleFrame];
|
||||
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
|
||||
|
||||
@@ -49,7 +49,10 @@
|
||||
|
||||
EdgeSnapping snapping;
|
||||
|
||||
NSRect lastUnmaximizedFrame;
|
||||
NSRect lastMaximizedFrame;
|
||||
NSRect lastUnfullscreenFrame;
|
||||
BOOL inMaximizeTransition;
|
||||
BOOL inFullscreenTransition;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,57 +151,6 @@ create_blank_cursor (void)
|
||||
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 *
|
||||
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
||||
{
|
||||
@@ -212,17 +161,7 @@ _gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
||||
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
|
||||
|
||||
if (cursor != NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
name = gdk_cursor_get_name (cursor);
|
||||
|
||||
if (name == NULL)
|
||||
goto load_cursor;
|
||||
|
||||
@@ -96,26 +96,37 @@ _gdk_macos_toplevel_surface_unminimize (GdkMacosToplevelSurface *self)
|
||||
[window deminiaturize:window];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
GdkToplevelLayout *layout)
|
||||
{
|
||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
|
||||
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
|
||||
GdkToplevelSize size;
|
||||
GdkDisplay *display;
|
||||
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);
|
||||
GdkMonitor *monitor;
|
||||
GdkToplevelSize size;
|
||||
int bounds_width, bounds_height;
|
||||
int width, height;
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
NSWindowStyleMask style_mask;
|
||||
gboolean maximize;
|
||||
gboolean fullscreen;
|
||||
|
||||
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
||||
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
|
||||
|
||||
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
|
||||
return FALSE;
|
||||
if (layout != self->layout)
|
||||
{
|
||||
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
|
||||
self->layout = gdk_toplevel_layout_copy (layout);
|
||||
}
|
||||
|
||||
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
|
||||
_gdk_macos_toplevel_surface_attach_to_parent (self);
|
||||
|
||||
style_mask = [nswindow styleMask];
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||
|
||||
if (monitor)
|
||||
@@ -133,127 +144,58 @@ _gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
|
||||
}
|
||||
|
||||
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
|
||||
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
|
||||
|
||||
gdk_toplevel_notify_compute_size (toplevel, &size);
|
||||
g_warn_if_fail (size.width > 0);
|
||||
g_warn_if_fail (size.height > 0);
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
|
||||
if (self->layout != NULL &&
|
||||
gdk_toplevel_layout_get_resizable (self->layout))
|
||||
if (gdk_toplevel_layout_get_resizable (layout))
|
||||
{
|
||||
geometry.min_width = size.min_width;
|
||||
geometry.min_height = size.min_height;
|
||||
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
|
||||
{
|
||||
geometry.max_width = geometry.min_width = size.width;
|
||||
geometry.max_height = geometry.min_height = size.height;
|
||||
geometry.max_width = geometry.min_width = width;
|
||||
geometry.max_height = geometry.min_height = height;
|
||||
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)
|
||||
_gdk_macos_surface_set_shadow (macos_surface,
|
||||
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (surface),
|
||||
size.shadow.top,
|
||||
size.shadow.right,
|
||||
size.shadow.bottom,
|
||||
size.shadow.left);
|
||||
|
||||
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
|
||||
_gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
|
||||
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
|
||||
|
||||
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;
|
||||
GDK_DEBUG (MISC, "Resizing \"%s\" to %dx%d",
|
||||
GDK_MACOS_SURFACE (self)->title ?
|
||||
GDK_MACOS_SURFACE (self)->title :
|
||||
"untitled",
|
||||
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];
|
||||
_gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
|
||||
|
||||
/* Maximized state */
|
||||
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
|
||||
@@ -436,6 +378,125 @@ _gdk_macos_toplevel_surface_hide (GdkSurface *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
|
||||
_gdk_macos_toplevel_surface_request_layout (GdkSurface *surface)
|
||||
{
|
||||
|
||||
@@ -201,23 +201,17 @@ get_egl_window_size (GdkSurface *surface,
|
||||
|
||||
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);
|
||||
*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
|
||||
{
|
||||
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),
|
||||
*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,49 +458,6 @@ gdk_wayland_toplevel_compute_size (GdkSurface *surface)
|
||||
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
|
||||
gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
||||
{
|
||||
@@ -518,9 +475,6 @@ gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
||||
new_state = wayland_toplevel->pending.state;
|
||||
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;
|
||||
wayland_toplevel->pending.is_resizing = FALSE;
|
||||
|
||||
@@ -2036,7 +1990,13 @@ gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
static gboolean
|
||||
gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
{
|
||||
return TRUE;
|
||||
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
|
||||
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
|
||||
@@ -2707,7 +2667,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_DISPLAY (display), FALSE);
|
||||
|
||||
if (!display_wayland->xdg_importer && !display_wayland->xdg_importer_v2)
|
||||
if (!display_wayland->xdg_importer)
|
||||
{
|
||||
g_warning ("Server is missing xdg_foreign support");
|
||||
return FALSE;
|
||||
|
||||
@@ -3015,8 +3015,6 @@ gdk_x11_display_init_gl_backend (GdkX11Display *self,
|
||||
|
||||
self->egl_version = epoxy_egl_version (egl_display);
|
||||
|
||||
XFree (visinfo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
|
||||
#include "gskglbufferprivate.h"
|
||||
|
||||
struct _GskGLBuffer
|
||||
@@ -16,9 +14,6 @@ struct _GskGLBuffer
|
||||
|
||||
G_DEFINE_TYPE (GskGLBuffer, gsk_gl_buffer, GSK_TYPE_GPU_BUFFER)
|
||||
|
||||
static guint profiler_buffer_uploads_id;
|
||||
static gint64 profiler_buffer_uploads;
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_finalize (GObject *object)
|
||||
{
|
||||
@@ -39,19 +34,13 @@ gsk_gl_buffer_map (GskGpuBuffer *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_unmap (GskGpuBuffer *buffer,
|
||||
gsize used)
|
||||
gsk_gl_buffer_unmap (GskGpuBuffer *buffer)
|
||||
{
|
||||
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
|
||||
|
||||
if (used == 0)
|
||||
return;
|
||||
|
||||
gsk_gl_buffer_bind (self);
|
||||
|
||||
profiler_buffer_uploads += used;
|
||||
glBufferSubData (self->target, 0, used, self->data);
|
||||
gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads);
|
||||
glBufferSubData (self->target, 0, gsk_gpu_buffer_get_size (buffer), self->data);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -64,8 +53,6 @@ gsk_gl_buffer_class_init (GskGLBufferClass *klass)
|
||||
buffer_class->unmap = gsk_gl_buffer_unmap;
|
||||
|
||||
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
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "gskglbufferprivate.h"
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
|
||||
struct _GskGLDescriptors
|
||||
{
|
||||
GskGpuDescriptors parent_instance;
|
||||
@@ -14,12 +13,16 @@ struct _GskGLDescriptors
|
||||
guint n_external;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK_TYPE_GPU_DESCRIPTORS)
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
gsk_gl_descriptors_finalize (GObject *object)
|
||||
{
|
||||
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (desc);
|
||||
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (object);
|
||||
|
||||
g_object_unref (self->device);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -69,24 +72,33 @@ gsk_gl_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GskGpuDescriptorsClass GSK_GL_DESCRIPTORS_CLASS =
|
||||
static void
|
||||
gsk_gl_descriptors_class_init (GskGLDescriptorsClass *klass)
|
||||
{
|
||||
.finalize = gsk_gl_descriptors_finalize,
|
||||
.add_image = gsk_gl_descriptors_add_image,
|
||||
.add_buffer = gsk_gl_descriptors_add_buffer,
|
||||
};
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_gl_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_gl_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_gl_descriptors_add_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_init (GskGLDescriptors *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskGpuDescriptors *
|
||||
gsk_gl_descriptors_new (GskGLDevice *device)
|
||||
{
|
||||
GskGpuDescriptors *desc;
|
||||
GskGLDescriptors *self;
|
||||
|
||||
desc = gsk_gpu_descriptors_new ((GskGpuDescriptorsClass *) &GSK_GL_DESCRIPTORS_CLASS,
|
||||
sizeof (GskGLDescriptors));
|
||||
self = g_object_new (GSK_TYPE_GL_DESCRIPTORS, NULL);
|
||||
|
||||
GSK_GL_DESCRIPTORS (desc)->device = g_object_ref (device);
|
||||
self->device = g_object_ref (device);
|
||||
|
||||
return desc;
|
||||
return GSK_GPU_DESCRIPTORS (self);
|
||||
}
|
||||
|
||||
guint
|
||||
@@ -98,7 +110,7 @@ gsk_gl_descriptors_get_n_external (GskGLDescriptors *self)
|
||||
void
|
||||
gsk_gl_descriptors_use (GskGLDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptors *desc = &self->parent_instance;
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
gsize i, ext, n_textures;
|
||||
|
||||
n_textures = 16 - 3 * self->n_external;
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskGLDescriptors GskGLDescriptors;
|
||||
|
||||
#define GSK_GL_DESCRIPTORS(d) ((GskGLDescriptors *) (d))
|
||||
#define GSK_TYPE_GL_DESCRIPTORS (gsk_gl_descriptors_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK, GL_DESCRIPTORS, GskGpuDescriptors)
|
||||
|
||||
GskGpuDescriptors * gsk_gl_descriptors_new (GskGLDevice *device);
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdkprofilerprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
@@ -474,7 +473,6 @@ gsk_gl_device_load_program (GskGLDevice *self,
|
||||
guint n_external_textures,
|
||||
GError **error)
|
||||
{
|
||||
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
|
||||
GLuint vertex_shader_id, fragment_shader_id, program_id;
|
||||
GLint link_status;
|
||||
|
||||
@@ -529,11 +527,6 @@ gsk_gl_device_load_program (GskGLDevice *self,
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,9 +45,8 @@ gsk_gpu_buffer_map (GskGpuBuffer *self)
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_buffer_unmap (GskGpuBuffer *self,
|
||||
gsize size)
|
||||
gsk_gpu_buffer_unmap (GskGpuBuffer *self)
|
||||
{
|
||||
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self, size);
|
||||
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ struct _GskGpuBufferClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
guchar * (* map) (GskGpuBuffer *self);
|
||||
void (* unmap) (GskGpuBuffer *self,
|
||||
gsize used);
|
||||
void (* unmap) (GskGpuBuffer *self);
|
||||
};
|
||||
|
||||
GType gsk_gpu_buffer_get_type (void) G_GNUC_CONST;
|
||||
@@ -35,8 +34,7 @@ void gsk_gpu_buffer_setup (GskGpuB
|
||||
gsize gsk_gpu_buffer_get_size (GskGpuBuffer *self);
|
||||
|
||||
guchar * gsk_gpu_buffer_map (GskGpuBuffer *self);
|
||||
void gsk_gpu_buffer_unmap (GskGpuBuffer *self,
|
||||
gsize used);
|
||||
void gsk_gpu_buffer_unmap (GskGpuBuffer *self);
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuBuffer, g_object_unref)
|
||||
|
||||
@@ -30,14 +30,6 @@ gsk_gpu_clip_init_rect (GskGpuClip *clip,
|
||||
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
|
||||
gsk_gpu_clip_init_copy (GskGpuClip *self,
|
||||
const GskGpuClip *src)
|
||||
@@ -137,13 +129,6 @@ gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
|
||||
break;
|
||||
|
||||
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_RECT:
|
||||
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
|
||||
|
||||
@@ -16,7 +16,6 @@ typedef enum {
|
||||
GSK_GPU_CLIP_ALL_CLIPPED,
|
||||
/* No clipping is necessary, but the clip rect is set
|
||||
* to the actual bounds of the underlying framebuffer
|
||||
* or handled via the scissor.
|
||||
*/
|
||||
GSK_GPU_CLIP_NONE,
|
||||
/* The clip exists outside the rect, so clipping must
|
||||
|
||||
@@ -52,39 +52,43 @@ gsk_gpu_buffer_entry_clear (gpointer data)
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
typedef struct _GskGpuDescriptorsPrivate GskGpuDescriptorsPrivate;
|
||||
|
||||
struct _GskGpuDescriptorsPrivate
|
||||
{
|
||||
GskGpuImageEntries images;
|
||||
GskGpuBufferEntries buffers;
|
||||
};
|
||||
|
||||
static inline GskGpuDescriptorsPrivate *
|
||||
gsk_gpu_descriptors_get_instance_private (GskGpuDescriptors *self)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuDescriptors, gsk_gpu_descriptors, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gsk_gpu_descriptors_finalize (GObject *object)
|
||||
{
|
||||
return (GskGpuDescriptorsPrivate *) (((guchar *)self) - sizeof (GskGpuDescriptorsPrivate));
|
||||
GskGpuDescriptors *self = GSK_GPU_DESCRIPTORS (object);
|
||||
GskGpuDescriptorsPrivate *priv = gsk_gpu_descriptors_get_instance_private (self);
|
||||
|
||||
gsk_gpu_image_entries_clear (&priv->images);
|
||||
gsk_gpu_buffer_entries_clear (&priv->buffers);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gpu_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/* Just for subclasses */
|
||||
GskGpuDescriptors *
|
||||
gsk_gpu_descriptors_new (GskGpuDescriptorsClass *desc_class,
|
||||
gsize child_size)
|
||||
static void
|
||||
gsk_gpu_descriptors_class_init (GskGpuDescriptorsClass *klass)
|
||||
{
|
||||
GskGpuDescriptors *self;
|
||||
GskGpuDescriptorsPrivate *priv;
|
||||
guchar *data;
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
data = g_new0 (guchar, child_size + sizeof (GskGpuDescriptorsPrivate));
|
||||
object_class->finalize = gsk_gpu_descriptors_finalize;
|
||||
}
|
||||
|
||||
priv = (GskGpuDescriptorsPrivate *) data;
|
||||
self = (GskGpuDescriptors *) (data + sizeof (GskGpuDescriptorsPrivate));
|
||||
|
||||
self->ref_count = 1;
|
||||
self->desc_class = desc_class;
|
||||
static void
|
||||
gsk_gpu_descriptors_init (GskGpuDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptorsPrivate *priv = gsk_gpu_descriptors_get_instance_private (self);
|
||||
|
||||
gsk_gpu_image_entries_init (&priv->images);
|
||||
gsk_gpu_buffer_entries_init (&priv->buffers);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
gsize
|
||||
@@ -185,7 +189,7 @@ gsk_gpu_descriptors_add_image (GskGpuDescriptors *self,
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->desc_class->add_image (self, image, sampler, &descriptor))
|
||||
if (!GSK_GPU_DESCRIPTORS_GET_CLASS (self)->add_image (self, image, sampler, &descriptor))
|
||||
return FALSE;
|
||||
|
||||
gsk_gpu_image_entries_append (&priv->images,
|
||||
@@ -220,7 +224,7 @@ gsk_gpu_descriptors_add_buffer (GskGpuDescriptors *self,
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->desc_class->add_buffer (self, buffer, &descriptor))
|
||||
if (!GSK_GPU_DESCRIPTORS_GET_CLASS (self)->add_buffer (self, buffer, &descriptor))
|
||||
return FALSE;
|
||||
|
||||
gsk_gpu_buffer_entries_append (&priv->buffers,
|
||||
@@ -234,28 +238,3 @@ gsk_gpu_descriptors_add_buffer (GskGpuDescriptors *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GskGpuDescriptors *
|
||||
gsk_gpu_descriptors_ref (GskGpuDescriptors *self)
|
||||
{
|
||||
self->ref_count++;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_descriptors_unref (GskGpuDescriptors *self)
|
||||
{
|
||||
self->ref_count--;
|
||||
|
||||
if (self->ref_count == 0)
|
||||
{
|
||||
GskGpuDescriptorsPrivate *priv = gsk_gpu_descriptors_get_instance_private (self);
|
||||
|
||||
self->desc_class->finalize (self);
|
||||
|
||||
gsk_gpu_image_entries_clear (&priv->images);
|
||||
gsk_gpu_buffer_entries_clear (&priv->buffers);
|
||||
|
||||
g_free (priv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,23 +4,24 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskGpuDescriptors GskGpuDescriptors;
|
||||
typedef struct _GskGpuDescriptorsClass GskGpuDescriptorsClass;
|
||||
typedef struct _GskGpuDescriptorsPrivate GskGpuDescriptorsPrivate;
|
||||
#define GSK_TYPE_GPU_DESCRIPTORS (gsk_gpu_descriptors_get_type ())
|
||||
#define GSK_GPU_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSK_TYPE_GPU_DESCRIPTORS, GskGpuDescriptors))
|
||||
#define GSK_GPU_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSK_TYPE_GPU_DESCRIPTORS, GskGpuDescriptorsClass))
|
||||
#define GSK_IS_GPU_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSK_TYPE_GPU_DESCRIPTORS))
|
||||
#define GSK_IS_GPU_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSK_TYPE_GPU_DESCRIPTORS))
|
||||
#define GSK_GPU_DESCRIPTORS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSK_TYPE_GPU_DESCRIPTORS, GskGpuDescriptorsClass))
|
||||
|
||||
#define GSK_GPU_DESCRIPTORS(d) ((GskGpuDescriptors *) (d))
|
||||
typedef struct _GskGpuDescriptorsClass GskGpuDescriptorsClass;
|
||||
|
||||
struct _GskGpuDescriptors
|
||||
{
|
||||
GskGpuDescriptorsClass *desc_class;
|
||||
int ref_count;
|
||||
|
||||
GskGpuDescriptorsPrivate *priv;
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _GskGpuDescriptorsClass
|
||||
{
|
||||
void (* finalize) (GskGpuDescriptors *self);
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* add_image) (GskGpuDescriptors *self,
|
||||
GskGpuImage *image,
|
||||
GskGpuSampler sampler,
|
||||
@@ -30,8 +31,7 @@ struct _GskGpuDescriptorsClass
|
||||
guint32 *out_id);
|
||||
};
|
||||
|
||||
GskGpuDescriptors * gsk_gpu_descriptors_ref (GskGpuDescriptors *self);
|
||||
void gsk_gpu_descriptors_unref (GskGpuDescriptors *self);
|
||||
GType gsk_gpu_descriptors_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gsize gsk_gpu_descriptors_get_n_images (GskGpuDescriptors *self);
|
||||
gsize gsk_gpu_descriptors_get_n_buffers (GskGpuDescriptors *self);
|
||||
@@ -55,8 +55,7 @@ gboolean gsk_gpu_descriptors_add_buffer (GskGpuD
|
||||
GskGpuBuffer *buffer,
|
||||
guint32 *out_descriptor);
|
||||
|
||||
GskGpuDescriptors *gsk_gpu_descriptors_new (GskGpuDescriptorsClass *desc_class,
|
||||
gsize child_size);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuDescriptors, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -33,6 +33,37 @@ typedef struct _GskGpuCachedGlyph GskGpuCachedGlyph;
|
||||
typedef struct _GskGpuCachedTexture GskGpuCachedTexture;
|
||||
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
|
||||
{
|
||||
GdkDisplay *display;
|
||||
@@ -45,6 +76,7 @@ struct _GskGpuDevicePrivate
|
||||
|
||||
GHashTable *texture_cache;
|
||||
GHashTable *glyph_cache;
|
||||
FontGlyphCache *last_font_cache;
|
||||
|
||||
GskGpuCachedAtlas *current_atlas;
|
||||
|
||||
@@ -69,14 +101,15 @@ struct _GskGpuCachedClass
|
||||
struct _GskGpuCached
|
||||
{
|
||||
const GskGpuCachedClass *class;
|
||||
|
||||
GskGpuCachedAtlas *atlas;
|
||||
GskGpuCached *next;
|
||||
GskGpuCached *prev;
|
||||
|
||||
gint64 timestamp;
|
||||
gboolean stale;
|
||||
guint pixels; /* For glyphs and textures, pixels. For atlases, dead pixels */
|
||||
|
||||
unsigned int stale : 1;
|
||||
unsigned int pixels : 31; /* For glyphs and textures, pixels. For atlases, dead pixels */
|
||||
|
||||
};
|
||||
|
||||
static inline void
|
||||
@@ -361,10 +394,8 @@ struct _GskGpuCachedGlyph
|
||||
{
|
||||
GskGpuCached parent;
|
||||
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
float scale;
|
||||
FontGlyphCache *font_cache;
|
||||
GlyphCacheKey glyph_key;
|
||||
|
||||
GskGpuImage *image;
|
||||
graphene_rect_t bounds;
|
||||
@@ -377,10 +408,17 @@ gsk_gpu_cached_glyph_free (GskGpuDevice *device,
|
||||
{
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (device);
|
||||
GskGpuCachedGlyph *self = (GskGpuCachedGlyph *) cached;
|
||||
FontGlyphCache *font_cache;
|
||||
|
||||
g_hash_table_remove (priv->glyph_cache, self);
|
||||
font_cache = self->font_cache;
|
||||
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_free (self);
|
||||
@@ -403,15 +441,35 @@ gsk_gpu_cached_glyph_should_collect (GskGpuDevice *device,
|
||||
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
|
||||
gsk_gpu_cached_glyph_hash (gconstpointer data)
|
||||
{
|
||||
const GskGpuCachedGlyph *glyph = data;
|
||||
const GlyphCacheKey *key = &glyph->glyph_key;
|
||||
|
||||
return GPOINTER_TO_UINT (glyph->font) ^
|
||||
glyph->glyph ^
|
||||
(glyph->flags << 24) ^
|
||||
((guint) glyph->scale * PANGO_SCALE);
|
||||
return key->glyph ^ (key->flags << 24);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -420,11 +478,11 @@ gsk_gpu_cached_glyph_equal (gconstpointer v1,
|
||||
{
|
||||
const GskGpuCachedGlyph *glyph1 = v1;
|
||||
const GskGpuCachedGlyph *glyph2 = v2;
|
||||
const GlyphCacheKey *key1 = &glyph1->glyph_key;
|
||||
const GlyphCacheKey *key2 = &glyph2->glyph_key;
|
||||
|
||||
return glyph1->font == glyph2->font
|
||||
&& glyph1->glyph == glyph2->glyph
|
||||
&& glyph1->flags == glyph2->flags
|
||||
&& glyph1->scale == glyph2->scale;
|
||||
return key1->glyph == key2->glyph &&
|
||||
key1->flags == key2->flags;
|
||||
}
|
||||
|
||||
static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
|
||||
@@ -623,10 +681,13 @@ gsk_gpu_device_init (GskGpuDevice *self)
|
||||
{
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||
|
||||
priv->glyph_cache = g_hash_table_new (gsk_gpu_cached_glyph_hash,
|
||||
gsk_gpu_cached_glyph_equal);
|
||||
priv->glyph_cache = g_hash_table_new_full (gsk_gpu_cached_font_hash,
|
||||
gsk_gpu_cached_font_equal,
|
||||
NULL,
|
||||
font_glyph_cache_free);
|
||||
priv->texture_cache = g_hash_table_new (g_direct_hash,
|
||||
g_direct_equal);
|
||||
priv->last_font_cache = &no_font_cache;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -890,16 +951,18 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
GskGpuGlyphLookupFlags flags,
|
||||
float scale,
|
||||
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);
|
||||
GskGpuCachedGlyph lookup = {
|
||||
.font = font,
|
||||
.glyph = glyph,
|
||||
.flags = flags,
|
||||
.scale = scale
|
||||
FontGlyphCache font_lookup = {
|
||||
.key = { .font = font, .scale = scale }
|
||||
};
|
||||
GskGpuCachedGlyph *cache;
|
||||
GskGpuCachedGlyph glyph_lookup = {
|
||||
.glyph_key = { .glyph = glyph, .flags = flags }
|
||||
};
|
||||
FontGlyphCache *font_cache = NULL;
|
||||
GskGpuCachedGlyph *cache = NULL;
|
||||
PangoRectangle ink_rect;
|
||||
graphene_rect_t rect;
|
||||
graphene_point_t origin;
|
||||
@@ -908,22 +971,43 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
float subpixel_x, subpixel_y;
|
||||
PangoFont *scaled_font;
|
||||
|
||||
cache = g_hash_table_lookup (priv->glyph_cache, &lookup);
|
||||
if (cache)
|
||||
{
|
||||
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
||||
if (priv->last_font_cache->key.font == font &&
|
||||
priv->last_font_cache->key.scale == scale)
|
||||
font_cache = priv->last_font_cache;
|
||||
else
|
||||
font_cache = g_hash_table_lookup (priv->glyph_cache, &font_lookup);
|
||||
|
||||
*out_bounds = cache->bounds;
|
||||
*out_origin = cache->origin;
|
||||
return cache->image;
|
||||
if (font_cache)
|
||||
{
|
||||
cache = g_hash_table_lookup (font_cache->cache, &glyph_lookup);
|
||||
if (cache)
|
||||
{
|
||||
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
||||
|
||||
*out_bounds = cache->bounds;
|
||||
*out_origin = cache->origin;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
* hinting influence the rendering of hexboxes, and we get bad outcomes if
|
||||
* that happens.
|
||||
*/
|
||||
scaled_font = gsk_reload_font (font, scale, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_STYLE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT);
|
||||
priv->last_font_cache = font_cache;
|
||||
|
||||
if (*out_scaled_font)
|
||||
scaled_font = *out_scaled_font;
|
||||
else
|
||||
scaled_font = gsk_get_scaled_font (font, scale);
|
||||
|
||||
subpixel_x = (flags & 3) / 4.f;
|
||||
subpixel_y = ((flags >> 2) & 3) / 4.f;
|
||||
@@ -953,10 +1037,9 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
cache = gsk_gpu_cached_new (self, &GSK_GPU_CACHED_GLYPH_CLASS, NULL);
|
||||
}
|
||||
|
||||
cache->font = g_object_ref (font);
|
||||
cache->glyph = glyph;
|
||||
cache->flags = flags;
|
||||
cache->scale = scale;
|
||||
cache->font_cache = font_cache;
|
||||
cache->glyph_key.glyph = glyph;
|
||||
cache->glyph_key.flags = flags;
|
||||
cache->bounds = rect;
|
||||
cache->image = image;
|
||||
cache->origin = GRAPHENE_POINT_INIT (- origin.x + subpixel_x,
|
||||
@@ -976,13 +1059,12 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
&GRAPHENE_POINT_INIT (cache->origin.x + padding,
|
||||
cache->origin.y + padding));
|
||||
|
||||
g_hash_table_insert (priv->glyph_cache, cache, cache);
|
||||
g_hash_table_insert (font_cache->cache, cache, cache);
|
||||
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
|
||||
|
||||
*out_bounds = cache->bounds;
|
||||
*out_origin = cache->origin;
|
||||
|
||||
g_object_unref (scaled_font);
|
||||
*out_scaled_font = scaled_font;
|
||||
|
||||
return cache->image;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,8 @@ GskGpuImage * gsk_gpu_device_lookup_glyph_image (GskGpuD
|
||||
GskGpuGlyphLookupFlags flags,
|
||||
float scale,
|
||||
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)
|
||||
|
||||
@@ -126,7 +126,7 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
|
||||
bytes,
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
gsk_gpu_buffer_unmap (self->buffer, 0);
|
||||
gsk_gpu_buffer_unmap (self->buffer);
|
||||
}
|
||||
|
||||
static GskGpuOp *
|
||||
|
||||
@@ -426,7 +426,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
|
||||
if (priv->vertex_buffer_data)
|
||||
{
|
||||
memcpy (new_data, priv->vertex_buffer_data, old_size);
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer, old_size);
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer);
|
||||
}
|
||||
g_object_unref (priv->vertex_buffer);
|
||||
priv->vertex_buffer = new_buffer;
|
||||
@@ -434,7 +434,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
|
||||
}
|
||||
|
||||
priv->vertex_buffer_used = size_needed;
|
||||
|
||||
|
||||
return size_needed - size;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ gsk_gpu_frame_write_storage_buffer (GskGpuFrame *self,
|
||||
{
|
||||
g_assert (offset > 0);
|
||||
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer, 0);
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer);
|
||||
g_clear_object (&priv->storage_buffer);
|
||||
priv->storage_buffer_data = 0;
|
||||
priv->storage_buffer_used = 0;
|
||||
@@ -591,14 +591,14 @@ gsk_gpu_frame_submit (GskGpuFrame *self)
|
||||
|
||||
if (priv->vertex_buffer)
|
||||
{
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer, priv->vertex_buffer_used);
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer);
|
||||
priv->vertex_buffer_data = NULL;
|
||||
priv->vertex_buffer_used = 0;
|
||||
}
|
||||
|
||||
if (priv->storage_buffer_data)
|
||||
{
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer, priv->storage_buffer_used);
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer);
|
||||
priv->storage_buffer_data = NULL;
|
||||
priv->storage_buffer_used = 0;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskstrokeprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
#include "gdk/gdksubsurfaceprivate.h"
|
||||
@@ -152,7 +151,7 @@ static void
|
||||
gsk_gpu_node_processor_finish (GskGpuNodeProcessor *self)
|
||||
{
|
||||
g_clear_pointer (&self->modelview, gsk_transform_unref);
|
||||
g_clear_pointer (&self->desc, gsk_gpu_descriptors_unref);
|
||||
g_clear_object (&self->desc);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -170,7 +169,7 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
|
||||
|
||||
self->frame = frame;
|
||||
if (desc)
|
||||
self->desc = gsk_gpu_descriptors_ref (desc);
|
||||
self->desc = g_object_ref (desc);
|
||||
else
|
||||
self->desc = NULL;
|
||||
|
||||
@@ -184,13 +183,13 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
|
||||
{
|
||||
float scale_x = viewport->size.width / width;
|
||||
float scale_y = viewport->size.height / height;
|
||||
gsk_gpu_clip_init_empty (&self->clip,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
scale_x * clip->x,
|
||||
scale_y * clip->y,
|
||||
scale_x * clip->width,
|
||||
scale_y * clip->height
|
||||
));
|
||||
gsk_gpu_clip_init_rect (&self->clip,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
scale_x * clip->x,
|
||||
scale_y * clip->y,
|
||||
scale_x * clip->width,
|
||||
scale_y * clip->height
|
||||
));
|
||||
}
|
||||
|
||||
self->modelview = NULL;
|
||||
@@ -268,7 +267,7 @@ gsk_gpu_node_processor_add_image (GskGpuNodeProcessor *self,
|
||||
if (gsk_gpu_descriptors_add_image (self->desc, image, sampler, &descriptor))
|
||||
return descriptor;
|
||||
|
||||
gsk_gpu_descriptors_unref (self->desc);
|
||||
g_object_unref (self->desc);
|
||||
}
|
||||
|
||||
self->desc = gsk_gpu_frame_create_descriptors (self->frame);
|
||||
@@ -545,7 +544,7 @@ gsk_gpu_pattern_writer_finish (GskGpuPatternWriter *self)
|
||||
{
|
||||
pattern_buffer_clear (&self->buffer);
|
||||
g_assert (self->stack == 0);
|
||||
g_clear_pointer (&self->desc, gsk_gpu_descriptors_unref);
|
||||
g_clear_object (&self->desc);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1328,7 +1327,7 @@ gsk_gpu_node_processor_add_node_clipped (GskGpuNodeProcessor *self,
|
||||
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
|
||||
return;
|
||||
}
|
||||
else if ((self->clip.type == GSK_GPU_CLIP_RECT || self->clip.type == GSK_GPU_CLIP_CONTAINED) &&
|
||||
else if (self->clip.type == GSK_GPU_CLIP_RECT &&
|
||||
gsk_rect_contains_rect (&self->clip.rect.bounds, &clip))
|
||||
{
|
||||
self->clip.type = GSK_GPU_CLIP_NONE;
|
||||
@@ -1611,7 +1610,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
inverse = gsk_transform_invert (gsk_transform_ref (clip_transform));
|
||||
gsk_transform_transform_bounds (inverse, &old_clip.rect.bounds, &new_bounds);
|
||||
gsk_transform_unref (inverse);
|
||||
gsk_gpu_clip_init_empty (&self->clip, &new_bounds);
|
||||
gsk_gpu_clip_init_contained (&self->clip, &new_bounds);
|
||||
}
|
||||
else if (!gsk_gpu_clip_transform (&self->clip, &old_clip, clip_transform, &child->bounds))
|
||||
{
|
||||
@@ -1649,13 +1648,10 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
|
||||
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
|
||||
|
||||
old_pixels = MAX (graphene_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
|
||||
graphene_vec2_get_y (&old_scale) * old_clip.rect.bounds.size.height);
|
||||
new_pixels = MAX (scale_x * self->clip.rect.bounds.size.width,
|
||||
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)
|
||||
old_pixels = graphene_vec2_get_x (&old_scale) * graphene_vec2_get_y (&old_scale) *
|
||||
old_clip.rect.bounds.size.width * old_clip.rect.bounds.size.height;
|
||||
new_pixels = scale_x * scale_y * self->clip.rect.bounds.size.width * self->clip.rect.bounds.size.height;
|
||||
if (new_pixels > 2 * old_pixels)
|
||||
{
|
||||
float forced_downscale = 2 * old_pixels / new_pixels;
|
||||
scale_x *= forced_downscale;
|
||||
@@ -2059,7 +2055,7 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
guint32 descriptor;
|
||||
gboolean need_mipmap, need_offscreen;
|
||||
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
!graphene_vec2_equal (&self->scale, graphene_vec2_one ());
|
||||
if (need_offscreen)
|
||||
{
|
||||
@@ -2996,16 +2992,15 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
GskGpuDevice *device;
|
||||
const PangoGlyphInfo *glyphs;
|
||||
PangoFont *font;
|
||||
PangoFont *scaled_font = NULL;
|
||||
graphene_point_t offset;
|
||||
guint i, num_glyphs;
|
||||
float scale, inv_scale;
|
||||
GdkRGBA color;
|
||||
float align_scale_x, align_scale_y;
|
||||
float inv_align_scale_x, inv_align_scale_y;
|
||||
unsigned int flags_mask;
|
||||
gboolean glyph_align;
|
||||
GskGpuImage *last_image;
|
||||
guint32 descriptor;
|
||||
const float inv_pango_scale = 1.f / PANGO_SCALE;
|
||||
guint32 descriptor = 0;
|
||||
GskGpuClip old_clip;
|
||||
|
||||
if (self->opacity < 1.0 &&
|
||||
gsk_text_node_has_color_glyphs (node))
|
||||
@@ -3014,8 +3009,13 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
return;
|
||||
}
|
||||
|
||||
device = gsk_gpu_frame_get_device (self->frame);
|
||||
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);
|
||||
color = *gsk_text_node_get_color (node);
|
||||
color.alpha *= self->opacity;
|
||||
num_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||
@@ -3028,23 +3028,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
|
||||
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
|
||||
{
|
||||
align_scale_x = scale * 4;
|
||||
align_scale_y = scale;
|
||||
flags_mask = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
align_scale_x = align_scale_y = scale * 4;
|
||||
flags_mask = 15;
|
||||
}
|
||||
|
||||
inv_align_scale_x = 1 / align_scale_x;
|
||||
inv_align_scale_y = 1 / align_scale_y;
|
||||
|
||||
last_image = NULL;
|
||||
descriptor = 0;
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
@@ -3052,14 +3036,21 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
|
||||
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
|
||||
|
||||
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
|
||||
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
|
||||
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
|
||||
glyph_origin.x *= inv_align_scale_x;
|
||||
glyph_origin.y *= inv_align_scale_y;
|
||||
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 (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
|
||||
{
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
@@ -3068,16 +3059,11 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
flags,
|
||||
scale,
|
||||
&glyph_bounds,
|
||||
&glyph_offset);
|
||||
&glyph_offset,
|
||||
&scaled_font);
|
||||
|
||||
glyph_tex_rect = GRAPHENE_RECT_INIT (-glyph_bounds.origin.x * inv_scale,
|
||||
-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);
|
||||
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);
|
||||
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
|
||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||
|
||||
@@ -3105,8 +3091,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
&glyph_tex_rect,
|
||||
&color);
|
||||
|
||||
offset.x += glyphs[i].geometry.width * inv_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
|
||||
@@ -3116,16 +3106,13 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
GskGpuDevice *device;
|
||||
const PangoGlyphInfo *glyphs;
|
||||
PangoFont *font;
|
||||
PangoFont *scaled_font = NULL;
|
||||
guint num_glyphs;
|
||||
gsize i;
|
||||
float scale, inv_scale;
|
||||
guint32 tex_id;
|
||||
GskGpuImage *last_image;
|
||||
graphene_point_t offset;
|
||||
float align_scale_x, align_scale_y;
|
||||
float inv_align_scale_x, inv_align_scale_y;
|
||||
unsigned int flags_mask;
|
||||
const float inv_pango_scale = 1.f / PANGO_SCALE;
|
||||
|
||||
if (gsk_text_node_has_color_glyphs (node))
|
||||
return FALSE;
|
||||
@@ -3145,57 +3132,33 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
|
||||
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
|
||||
|
||||
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
|
||||
{
|
||||
align_scale_x = scale * 4;
|
||||
align_scale_y = scale;
|
||||
flags_mask = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
align_scale_x = align_scale_y = scale * 4;
|
||||
flags_mask = 15;
|
||||
}
|
||||
|
||||
inv_align_scale_x = 1 / align_scale_x;
|
||||
inv_align_scale_y = 1 / align_scale_y;
|
||||
|
||||
last_image = NULL;
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
graphene_rect_t glyph_bounds;
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
|
||||
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
|
||||
|
||||
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
|
||||
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
|
||||
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
|
||||
glyph_origin.x *= inv_align_scale_x;
|
||||
glyph_origin.y *= inv_align_scale_y;
|
||||
graphene_point_t glyph_offset;
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
font,
|
||||
glyphs[i].glyph,
|
||||
flags,
|
||||
0,
|
||||
scale,
|
||||
&glyph_bounds,
|
||||
&glyph_offset);
|
||||
&glyph_offset,
|
||||
&scaled_font);
|
||||
|
||||
if (image != last_image)
|
||||
{
|
||||
if (!gsk_gpu_pattern_writer_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT, &tex_id))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
last_image = image;
|
||||
}
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
|
||||
gsk_gpu_pattern_writer_append_uint (self, tex_id);
|
||||
gsk_gpu_pattern_writer_append_rect (self,
|
||||
@@ -3205,7 +3168,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
glyph_bounds.size.width * inv_scale,
|
||||
glyph_bounds.size.height * inv_scale
|
||||
),
|
||||
&glyph_origin);
|
||||
&glyph_offset);
|
||||
gsk_gpu_pattern_writer_append_rect (self,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
- glyph_bounds.origin.x * inv_scale,
|
||||
@@ -3213,12 +3176,14 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
gsk_gpu_image_get_width (image) * inv_scale,
|
||||
gsk_gpu_image_get_height (image) * inv_scale
|
||||
),
|
||||
&glyph_origin);
|
||||
&glyph_offset);
|
||||
|
||||
offset.x += glyphs[i].geometry.width * inv_pango_scale;
|
||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
g_clear_object (&scaled_font);
|
||||
|
||||
return i == num_glyphs;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -30,6 +30,7 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
|
||||
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
|
||||
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
|
||||
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
|
||||
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the subpixel grid" },
|
||||
|
||||
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ gsk_gpu_shader_op_finish (GskGpuOp *op)
|
||||
{
|
||||
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
|
||||
|
||||
g_clear_pointer (&self->desc, gsk_gpu_descriptors_unref);
|
||||
g_clear_object (&self->desc);
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
@@ -197,7 +197,7 @@ gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
|
||||
self->variation = variation;
|
||||
self->clip = clip;
|
||||
if (desc)
|
||||
self->desc = gsk_gpu_descriptors_ref (desc);
|
||||
self->desc = g_object_ref (desc);
|
||||
else
|
||||
self->desc = NULL;
|
||||
self->vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
|
||||
|
||||
@@ -118,7 +118,8 @@ typedef enum {
|
||||
GSK_GPU_OPTIMIZE_BLIT = 1 << 3,
|
||||
GSK_GPU_OPTIMIZE_GRADIENTS = 1 << 4,
|
||||
GSK_GPU_OPTIMIZE_MIPMAP = 1 << 5,
|
||||
GSK_GPU_OPTIMIZE_GLYPH_ALIGN = 1 << 6,
|
||||
/* These require hardware support */
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 6,
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 7,
|
||||
} GskGpuOptimizations;
|
||||
|
||||
|
||||
@@ -110,8 +110,8 @@ gsk_gpu_upload_op_vk_command_with_area (GskGpuOp *op,
|
||||
data = gsk_gpu_buffer_map (*buffer);
|
||||
|
||||
draw_func (op, data, stride);
|
||||
|
||||
gsk_gpu_buffer_unmap (*buffer, area->height * stride);
|
||||
|
||||
gsk_gpu_buffer_unmap (*buffer);
|
||||
|
||||
vkCmdPipelineBarrier (state->vk_command_buffer,
|
||||
VK_PIPELINE_STAGE_HOST_BIT,
|
||||
@@ -531,7 +531,6 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
||||
GskGpuUploadGlyphOp *self = (GskGpuUploadGlyphOp *) op;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
PangoRectangle ink_rect = { 0, };
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
@@ -553,19 +552,12 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
||||
/* Draw glyph */
|
||||
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,
|
||||
self->font,
|
||||
&(PangoGlyphString) {
|
||||
.num_glyphs = 1,
|
||||
.glyphs = (PangoGlyphInfo[1]) { {
|
||||
.glyph = self->glyph,
|
||||
.geometry = {
|
||||
.width = ink_rect.width,
|
||||
}
|
||||
.glyph = self->glyph
|
||||
} }
|
||||
});
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ gsk_vulkan_buffer_map (GskGpuBuffer *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_buffer_unmap (GskGpuBuffer *buffer,
|
||||
gsize size)
|
||||
gsk_vulkan_buffer_unmap (GskGpuBuffer *buffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,22 @@
|
||||
#include "gskvulkanframeprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanDescriptors, gsk_vulkan_descriptors, GSK_TYPE_GPU_DESCRIPTORS)
|
||||
|
||||
static void
|
||||
gsk_vulkan_descriptors_class_init (GskVulkanDescriptorsClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_descriptors_init (GskVulkanDescriptors *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskVulkanPipelineLayout *
|
||||
gsk_vulkan_descriptors_get_pipeline_layout (GskVulkanDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
GskVulkanDescriptorsClass *class = GSK_VULKAN_DESCRIPTORS_CLASS (desc->desc_class);
|
||||
|
||||
return class->get_pipeline_layout (self);
|
||||
return GSK_VULKAN_DESCRIPTORS_GET_CLASS (self)->get_pipeline_layout (self);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -39,19 +48,5 @@ gsk_vulkan_descriptors_bind (GskVulkanDescriptors *self,
|
||||
GskVulkanDescriptors *previous,
|
||||
VkCommandBuffer vk_command_buffer)
|
||||
{
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
GskVulkanDescriptorsClass *class = GSK_VULKAN_DESCRIPTORS_CLASS (desc->desc_class);
|
||||
|
||||
return class->bind (self, previous, vk_command_buffer);
|
||||
}
|
||||
|
||||
GskVulkanDescriptors *
|
||||
gsk_vulkan_descriptors_new (GskVulkanDescriptorsClass *desc_class,
|
||||
gsize child_size)
|
||||
{
|
||||
GskGpuDescriptors *desc;
|
||||
|
||||
desc = gsk_gpu_descriptors_new ((GskGpuDescriptorsClass *)desc_class, child_size);
|
||||
|
||||
return GSK_VULKAN_DESCRIPTORS (desc);
|
||||
return GSK_VULKAN_DESCRIPTORS_GET_CLASS (self)->bind (self, previous, vk_command_buffer);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskVulkanDescriptors GskVulkanDescriptors;
|
||||
typedef struct _GskVulkanDescriptorsClass GskVulkanDescriptorsClass;
|
||||
#define GSK_TYPE_VULKAN_DESCRIPTORS (gsk_vulkan_descriptors_get_type ())
|
||||
#define GSK_VULKAN_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSK_TYPE_VULKAN_DESCRIPTORS, GskVulkanDescriptors))
|
||||
#define GSK_VULKAN_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSK_TYPE_VULKAN_DESCRIPTORS, GskVulkanDescriptorsClass))
|
||||
#define GSK_IS_VULKAN_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSK_TYPE_VULKAN_DESCRIPTORS))
|
||||
#define GSK_IS_VULKAN_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSK_TYPE_VULKAN_DESCRIPTORS))
|
||||
#define GSK_VULKAN_DESCRIPTORS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSK_TYPE_VULKAN_DESCRIPTORS, GskVulkanDescriptorsClass))
|
||||
|
||||
#define GSK_VULKAN_DESCRIPTORS(d) ((GskVulkanDescriptors *) (d))
|
||||
#define GSK_VULKAN_DESCRIPTORS_CLASS(d) ((GskVulkanDescriptorsClass *) (d))
|
||||
typedef struct _GskVulkanDescriptorsClass GskVulkanDescriptorsClass;
|
||||
|
||||
struct _GskVulkanDescriptors
|
||||
{
|
||||
@@ -27,6 +30,8 @@ struct _GskVulkanDescriptorsClass
|
||||
VkCommandBuffer vk_command_buffer);
|
||||
};
|
||||
|
||||
GType gsk_vulkan_descriptors_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GskVulkanPipelineLayout * gsk_vulkan_descriptors_get_pipeline_layout (GskVulkanDescriptors *self);
|
||||
|
||||
void gsk_vulkan_descriptors_transition (GskVulkanDescriptors *self,
|
||||
@@ -36,9 +41,7 @@ void gsk_vulkan_descriptors_bind
|
||||
GskVulkanDescriptors *previous,
|
||||
VkCommandBuffer vk_command_buffer);
|
||||
|
||||
GskVulkanDescriptors * gsk_vulkan_descriptors_new (GskVulkanDescriptorsClass *desc_class,
|
||||
gsize child_size);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskVulkanDescriptors, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -13,16 +13,10 @@
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkdmabuftextureprivate.h"
|
||||
|
||||
static inline void
|
||||
gsk_vulkan_real_descriptors_unref (GskVulkanRealDescriptors *desc)
|
||||
{
|
||||
gsk_gpu_descriptors_unref (GSK_GPU_DESCRIPTORS (desc));
|
||||
}
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_descriptors
|
||||
#define GDK_ARRAY_TYPE_NAME GskDescriptors
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GskVulkanRealDescriptors *
|
||||
#define GDK_ARRAY_FREE_FUNC gsk_vulkan_real_descriptors_unref
|
||||
#define GDK_ARRAY_FREE_FUNC g_object_unref
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
@@ -268,7 +262,7 @@ gsk_vulkan_frame_create_descriptors (GskGpuFrame *frame)
|
||||
desc = gsk_vulkan_real_descriptors_new (self);
|
||||
gsk_descriptors_append (&self->descriptors, desc);
|
||||
|
||||
return gsk_gpu_descriptors_ref (GSK_GPU_DESCRIPTORS (desc));
|
||||
return GSK_GPU_DESCRIPTORS (g_object_ref (desc));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "gskvulkanrealdescriptorsprivate.h"
|
||||
|
||||
#include "gskvulkanbufferprivate.h"
|
||||
#include "gskvulkanframeprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_descriptor_image_infos
|
||||
#define GDK_ARRAY_TYPE_NAME GskDescriptorImageInfos
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorImageInfo
|
||||
@@ -41,6 +45,8 @@ struct _GskVulkanRealDescriptors
|
||||
VkDescriptorSet descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanRealDescriptors, gsk_vulkan_real_descriptors, GSK_TYPE_VULKAN_DESCRIPTORS)
|
||||
|
||||
static GskVulkanPipelineLayout *
|
||||
gsk_vulkan_real_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc)
|
||||
{
|
||||
@@ -148,9 +154,9 @@ gsk_vulkan_real_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_real_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
gsk_vulkan_real_descriptors_finalize (GObject *object)
|
||||
{
|
||||
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
||||
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (object);
|
||||
|
||||
gsk_samplers_clear (&self->immutable_samplers);
|
||||
gsk_descriptor_image_infos_clear (&self->descriptor_immutable_images);
|
||||
@@ -159,18 +165,25 @@ gsk_vulkan_real_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
|
||||
gsk_vulkan_device_release_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame))),
|
||||
self->pipeline_layout);
|
||||
|
||||
G_OBJECT_CLASS (gsk_vulkan_real_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GskVulkanDescriptorsClass GSK_VULKAN_REAL_DESCRIPTORS_CLASS =
|
||||
static void
|
||||
gsk_vulkan_real_descriptors_class_init (GskVulkanRealDescriptorsClass *klass)
|
||||
{
|
||||
.parent_class = (GskGpuDescriptorsClass) {
|
||||
.finalize = gsk_vulkan_real_descriptors_finalize,
|
||||
.add_image = gsk_vulkan_real_descriptors_add_image,
|
||||
.add_buffer = gsk_vulkan_real_descriptors_add_buffer,
|
||||
},
|
||||
.get_pipeline_layout = gsk_vulkan_real_descriptors_get_pipeline_layout,
|
||||
.bind = gsk_vulkan_real_descriptors_bind
|
||||
};
|
||||
GskVulkanDescriptorsClass *vulkan_descriptors_class = GSK_VULKAN_DESCRIPTORS_CLASS (klass);
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_vulkan_real_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_vulkan_real_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_vulkan_real_descriptors_add_buffer;
|
||||
|
||||
vulkan_descriptors_class->get_pipeline_layout = gsk_vulkan_real_descriptors_get_pipeline_layout;
|
||||
vulkan_descriptors_class->bind = gsk_vulkan_real_descriptors_bind;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_real_descriptors_init (GskVulkanRealDescriptors *self)
|
||||
@@ -185,14 +198,9 @@ GskVulkanRealDescriptors *
|
||||
gsk_vulkan_real_descriptors_new (GskVulkanFrame *frame)
|
||||
{
|
||||
GskVulkanRealDescriptors *self;
|
||||
GskVulkanDescriptors *desc;
|
||||
|
||||
desc = gsk_vulkan_descriptors_new (&GSK_VULKAN_REAL_DESCRIPTORS_CLASS,
|
||||
sizeof (GskVulkanRealDescriptors));
|
||||
self = g_object_new (GSK_TYPE_VULKAN_REAL_DESCRIPTORS, NULL);
|
||||
|
||||
self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
||||
|
||||
gsk_vulkan_real_descriptors_init (self);
|
||||
self->frame = frame;
|
||||
|
||||
return self;
|
||||
|
||||
@@ -3,17 +3,11 @@
|
||||
#include "gskvulkandescriptorsprivate.h"
|
||||
#include "gskvulkanframeprivate.h"
|
||||
|
||||
#include "gskvulkanbufferprivate.h"
|
||||
#include "gskvulkanframeprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskVulkanRealDescriptors GskVulkanRealDescriptors;
|
||||
|
||||
#define GSK_VULKAN_REAL_DESCRIPTORS(d) ((GskVulkanRealDescriptors *) (d))
|
||||
#define GSK_TYPE_VULKAN_REAL_DESCRIPTORS (gsk_vulkan_real_descriptors_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskVulkanRealDescriptors, gsk_vulkan_real_descriptors, GSK, VULKAN_REAL_DESCRIPTORS, GskVulkanDescriptors)
|
||||
|
||||
GskVulkanRealDescriptors * gsk_vulkan_real_descriptors_new (GskVulkanFrame *frame);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "gskvulkansubdescriptorsprivate.h"
|
||||
|
||||
|
||||
struct _GskVulkanSubDescriptors
|
||||
{
|
||||
GskVulkanDescriptors parent_instance;
|
||||
@@ -10,31 +9,7 @@ struct _GskVulkanSubDescriptors
|
||||
GskVulkanDescriptors *parent;
|
||||
};
|
||||
|
||||
|
||||
static void gsk_vulkan_sub_descriptors_finalize (GskGpuDescriptors *desc);
|
||||
static gboolean gsk_vulkan_sub_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
GskGpuBuffer *buffer,
|
||||
guint32 *out_descriptor);
|
||||
static gboolean gsk_vulkan_sub_descriptors_add_image (GskGpuDescriptors *desc,
|
||||
GskGpuImage *image,
|
||||
GskGpuSampler sampler,
|
||||
guint32 *out_descriptor);
|
||||
static GskVulkanPipelineLayout *
|
||||
gsk_vulkan_sub_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc);
|
||||
static void gsk_vulkan_sub_descriptors_bind (GskVulkanDescriptors *desc,
|
||||
GskVulkanDescriptors *previous,
|
||||
VkCommandBuffer vk_command_buffer);
|
||||
|
||||
static GskVulkanDescriptorsClass GSK_VULKAN_SUB_DESCRIPTORS_CLASS =
|
||||
{
|
||||
.parent_class = (GskGpuDescriptorsClass) {
|
||||
.finalize = gsk_vulkan_sub_descriptors_finalize,
|
||||
.add_image = gsk_vulkan_sub_descriptors_add_image,
|
||||
.add_buffer = gsk_vulkan_sub_descriptors_add_buffer,
|
||||
},
|
||||
.get_pipeline_layout = gsk_vulkan_sub_descriptors_get_pipeline_layout,
|
||||
.bind = gsk_vulkan_sub_descriptors_bind,
|
||||
};
|
||||
G_DEFINE_TYPE (GskVulkanSubDescriptors, gsk_vulkan_sub_descriptors, GSK_TYPE_VULKAN_DESCRIPTORS)
|
||||
|
||||
static GskVulkanPipelineLayout *
|
||||
gsk_vulkan_sub_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc)
|
||||
@@ -51,7 +26,7 @@ gsk_vulkan_sub_descriptors_bind (GskVulkanDescriptors *desc,
|
||||
{
|
||||
GskVulkanSubDescriptors *self = GSK_VULKAN_SUB_DESCRIPTORS (desc);
|
||||
|
||||
if (GSK_GPU_DESCRIPTORS (previous)->desc_class == (GskGpuDescriptorsClass *) &GSK_VULKAN_SUB_DESCRIPTORS_CLASS)
|
||||
if (GSK_IS_VULKAN_SUB_DESCRIPTORS (previous))
|
||||
previous = GSK_VULKAN_SUB_DESCRIPTORS (previous)->parent;
|
||||
|
||||
if (self->parent == previous)
|
||||
@@ -87,24 +62,45 @@ gsk_vulkan_sub_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_sub_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
gsk_vulkan_sub_descriptors_finalize (GObject *object)
|
||||
{
|
||||
GskVulkanSubDescriptors *self = GSK_VULKAN_SUB_DESCRIPTORS (desc);
|
||||
GskVulkanSubDescriptors *self = GSK_VULKAN_SUB_DESCRIPTORS (object);
|
||||
|
||||
gsk_gpu_descriptors_unref (GSK_GPU_DESCRIPTORS (self->parent));
|
||||
g_object_unref (self->parent);
|
||||
|
||||
G_OBJECT_CLASS (gsk_vulkan_sub_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_sub_descriptors_class_init (GskVulkanSubDescriptorsClass *klass)
|
||||
{
|
||||
GskVulkanDescriptorsClass *vulkan_descriptors_class = GSK_VULKAN_DESCRIPTORS_CLASS (klass);
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_vulkan_sub_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_vulkan_sub_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_vulkan_sub_descriptors_add_buffer;
|
||||
|
||||
vulkan_descriptors_class->get_pipeline_layout = gsk_vulkan_sub_descriptors_get_pipeline_layout;
|
||||
vulkan_descriptors_class->bind = gsk_vulkan_sub_descriptors_bind;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_sub_descriptors_init (GskVulkanSubDescriptors *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskVulkanSubDescriptors *
|
||||
gsk_vulkan_sub_descriptors_new (GskVulkanDescriptors *parent)
|
||||
{
|
||||
GskVulkanSubDescriptors *self;
|
||||
GskVulkanDescriptors *desc;
|
||||
|
||||
desc = gsk_vulkan_descriptors_new (&GSK_VULKAN_SUB_DESCRIPTORS_CLASS,
|
||||
sizeof (GskVulkanSubDescriptors));
|
||||
self = g_object_new (GSK_TYPE_VULKAN_SUB_DESCRIPTORS, NULL);
|
||||
|
||||
self = GSK_VULKAN_SUB_DESCRIPTORS (desc);
|
||||
self->parent = GSK_VULKAN_DESCRIPTORS (gsk_gpu_descriptors_ref (GSK_GPU_DESCRIPTORS (parent)));
|
||||
self->parent = g_object_ref (parent);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskVulkanSubDescriptors GskVulkanSubDescriptors;
|
||||
|
||||
#define GSK_VULKAN_SUB_DESCRIPTORS(d) ((GskVulkanSubDescriptors *) (d))
|
||||
#define GSK_TYPE_VULKAN_SUB_DESCRIPTORS (gsk_vulkan_sub_descriptors_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskVulkanSubDescriptors, gsk_vulkan_sub_descriptors, GSK, VULKAN_SUB_DESCRIPTORS, GskVulkanDescriptors)
|
||||
|
||||
GskVulkanSubDescriptors * gsk_vulkan_sub_descriptors_new (GskVulkanDescriptors *parent);
|
||||
|
||||
|
||||
20
gsk/gskpointprivate.h
Normal file
20
gsk/gskpointprivate.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
static inline void G_GNUC_PURE
|
||||
gsk_point_interpolate (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2,
|
||||
float t,
|
||||
graphene_point_t *p)
|
||||
{
|
||||
p->x = p1->x * (1 - t) + p2->x * t;
|
||||
p->Y = p1->y * (1 - t) + p2->y * t;
|
||||
}
|
||||
|
||||
static inline float G_GNUC_PURE
|
||||
gsk_point_distance (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2)
|
||||
{
|
||||
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
|
||||
}
|
||||
192
gsk/gskprivate.c
192
gsk/gskprivate.c
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <pango/pangoft2.h>
|
||||
#include <math.h>
|
||||
|
||||
static gpointer
|
||||
@@ -22,106 +21,51 @@ gsk_ensure_resources (void)
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_reload_font:
|
||||
* gsk_get_scaled_font:
|
||||
* @font: a `PangoFont`
|
||||
* @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
|
||||
* @scale: the scale
|
||||
*
|
||||
* Returns a font that is just like @font, but uses the
|
||||
* given scale and hinting options for its glyphs and metrics.
|
||||
* Returns a font that is just like @font, at a size that
|
||||
* is multiplied by @scale.
|
||||
*
|
||||
* Returns: (transfer full): the modified `PangoFont`
|
||||
* Returns: (transfer full): a scaled version of @font
|
||||
*/
|
||||
PangoFont *
|
||||
gsk_reload_font (PangoFont *font,
|
||||
float scale,
|
||||
cairo_hint_metrics_t hint_metrics,
|
||||
cairo_hint_style_t hint_style,
|
||||
cairo_antialias_t antialias)
|
||||
gsk_get_scaled_font (PangoFont *font,
|
||||
float scale)
|
||||
{
|
||||
cairo_font_options_t *options;
|
||||
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 (scale == 1.0)
|
||||
return g_object_ref (font);
|
||||
|
||||
#if PANGO_VERSION_CHECK (1, 52, 0)
|
||||
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, context, NULL);
|
||||
return pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, NULL, NULL);
|
||||
#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;
|
||||
|
||||
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
|
||||
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultMatch)
|
||||
pango_cairo_context_set_resolution (context, dpi);
|
||||
key = (int) roundf (scale * PANGO_SCALE);
|
||||
|
||||
fonts = (GHashTable *) g_object_get_data (G_OBJECT (font), "gsk-scaled-fonts");
|
||||
|
||||
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);
|
||||
size = pango_font_description_get_size (desc);
|
||||
@@ -129,64 +73,24 @@ gsk_reload_font (PangoFont *font,
|
||||
if (pango_font_description_get_size_is_absolute (desc))
|
||||
pango_font_description_set_absolute_size (desc, size * scale);
|
||||
else
|
||||
pango_font_description_set_size (desc, (int) floor (size * scale + .5));
|
||||
pango_font_description_set_size (desc, (int) roundf (size * scale));
|
||||
|
||||
last_result = pango_font_map_load_font (pango_font_get_font_map (font), context, desc);
|
||||
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;
|
||||
fontmap = pango_font_get_font_map (font);
|
||||
context = pango_font_map_create_context (fontmap);
|
||||
|
||||
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||
options = cairo_font_options_create ();
|
||||
cairo_scaled_font_get_font_options (sf, options);
|
||||
style = cairo_font_options_get_hint_style (options);
|
||||
pango_cairo_context_set_font_options (context, options);
|
||||
cairo_font_options_destroy (options);
|
||||
|
||||
return style;
|
||||
font2 = pango_font_map_load_font (fontmap, context, desc);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -2,23 +2,13 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <pango/pango.h>
|
||||
#include <cairo.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_ensure_resources (void);
|
||||
|
||||
PangoFont *gsk_reload_font (PangoFont *font,
|
||||
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);
|
||||
PangoFont *gsk_get_scaled_font (PangoFont *font,
|
||||
float scale);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -688,6 +688,9 @@ get_renderer_for_vulkan (GdkSurface *surface)
|
||||
static GType
|
||||
get_renderer_for_gles2 (GdkSurface *surface)
|
||||
{
|
||||
if (gl_software_rendering (surface))
|
||||
return G_TYPE_INVALID;
|
||||
|
||||
return GSK_TYPE_GL_RENDERER;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskstrokeprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
#include "gdk/gdkprivate.h"
|
||||
@@ -3474,7 +3473,7 @@ gsk_transform_node_draw (GskRenderNode *node,
|
||||
* (like when flipping an axis at the point where scale == 0)
|
||||
* and just means that nothing should be drawn.
|
||||
* 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;
|
||||
}
|
||||
@@ -5792,12 +5791,6 @@ gsk_text_node_class_init (gpointer g_class,
|
||||
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:
|
||||
* @font: the `PangoFont` containing the glyphs
|
||||
@@ -5824,7 +5817,8 @@ gsk_text_node_new (PangoFont *font,
|
||||
PangoGlyphInfo *glyph_infos;
|
||||
int n;
|
||||
|
||||
gsk_get_unhinted_glyph_string_extents (glyphs, font, &ink_rect);
|
||||
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
|
||||
/* Don't create nodes with empty bounds */
|
||||
if (ink_rect.width == 0 || ink_rect.height == 0)
|
||||
@@ -5861,10 +5855,10 @@ gsk_text_node_new (PangoFont *font,
|
||||
self->num_glyphs = n;
|
||||
|
||||
gsk_rect_init (&node->bounds,
|
||||
offset->x + pango_units_to_float (ink_rect.x),
|
||||
offset->y + pango_units_to_float (ink_rect.y),
|
||||
pango_units_to_float (ink_rect.width),
|
||||
pango_units_to_float (ink_rect.height));
|
||||
offset->x + ink_rect.x,
|
||||
offset->y + ink_rect.y,
|
||||
ink_rect.width,
|
||||
ink_rect.height);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "gskstroke.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskenumtypes.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
@@ -47,9 +46,7 @@
|
||||
#include <cairo-script-interpreter.h>
|
||||
#endif
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
#include <pango/pangofc-fontmap.h>
|
||||
#endif
|
||||
@@ -89,39 +86,6 @@ context_finish (Context *context)
|
||||
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
|
||||
parse_rect (GtkCssParser *parser,
|
||||
Context *context,
|
||||
@@ -1218,8 +1182,6 @@ clear_font (gpointer inout_font)
|
||||
g_clear_object ((PangoFont **) inout_font);
|
||||
}
|
||||
|
||||
#define GLYPH_NEEDS_WIDTH (1 << 15)
|
||||
|
||||
static gboolean
|
||||
parse_glyphs (GtkCssParser *parser,
|
||||
Context *context,
|
||||
@@ -1246,7 +1208,6 @@ parse_glyphs (GtkCssParser *parser,
|
||||
gtk_css_parser_error_value (parser, "Unsupported character %d in string", 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);
|
||||
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
|
||||
}
|
||||
@@ -1255,22 +1216,14 @@ parse_glyphs (GtkCssParser *parser,
|
||||
}
|
||||
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);
|
||||
return FALSE;
|
||||
}
|
||||
gi.glyph = i;
|
||||
|
||||
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;
|
||||
}
|
||||
gi.geometry.width = (int) (d * PANGO_SCALE);
|
||||
|
||||
if (gtk_css_parser_has_number (parser))
|
||||
{
|
||||
@@ -2240,36 +2193,23 @@ unpack_glyphs (PangoFont *font,
|
||||
|
||||
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||
{
|
||||
PangoGlyphInfo *gi = &glyphs->glyphs[i];
|
||||
PangoGlyph glyph = glyphs->glyphs[i].glyph;
|
||||
|
||||
if (((*(unsigned int *) &gi->attr) & GLYPH_NEEDS_WIDTH) == 0)
|
||||
if (glyph < PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH ||
|
||||
glyph >= PANGO_GLYPH_INVALID_INPUT)
|
||||
continue;
|
||||
|
||||
*(unsigned int *) &gi->attr &= ~GLYPH_NEEDS_WIDTH;
|
||||
glyph = glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
|
||||
|
||||
if (gi->glyph >= PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH &&
|
||||
gi->glyph < PANGO_GLYPH_INVALID_INPUT)
|
||||
if (ascii == NULL)
|
||||
{
|
||||
PangoGlyph idx = gi->glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
|
||||
|
||||
ascii = create_ascii_glyphs (font);
|
||||
if (ascii == NULL)
|
||||
{
|
||||
ascii = create_ascii_glyphs (font);
|
||||
if (ascii == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gi->glyph = ascii->glyphs[idx].glyph;
|
||||
gi->geometry.width = ascii->glyphs[idx].geometry.width;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PangoRectangle ink_rect;
|
||||
|
||||
pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL);
|
||||
|
||||
gi->geometry.width = ink_rect.width;
|
||||
}
|
||||
glyphs->glyphs[i].glyph = ascii->glyphs[glyph].glyph;
|
||||
glyphs->glyphs[i].geometry.width = ascii->glyphs[glyph].geometry.width;
|
||||
}
|
||||
|
||||
g_clear_pointer (&ascii, pango_glyph_string_free);
|
||||
@@ -2277,45 +2217,6 @@ unpack_glyphs (PangoFont *font,
|
||||
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 *
|
||||
parse_text_node (GtkCssParser *parser,
|
||||
Context *context)
|
||||
@@ -2324,16 +2225,11 @@ parse_text_node (GtkCssParser *parser,
|
||||
graphene_point_t offset = GRAPHENE_POINT_INIT (0, 0);
|
||||
GdkRGBA color = GDK_RGBA("000000");
|
||||
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[] = {
|
||||
{ "font", parse_font, clear_font, &font },
|
||||
{ "offset", parse_point, NULL, &offset },
|
||||
{ "color", parse_color, NULL, &color },
|
||||
{ "glyphs", parse_glyphs, clear_glyphs, &glyphs },
|
||||
{ "hint-style", parse_hint_style, NULL, &hint_style },
|
||||
{ "antialias", parse_antialias, NULL, &antialias },
|
||||
{ "glyphs", parse_glyphs, clear_glyphs, &glyphs }
|
||||
};
|
||||
GskRenderNode *result;
|
||||
|
||||
@@ -2341,14 +2237,10 @@ parse_text_node (GtkCssParser *parser,
|
||||
|
||||
if (font == NULL)
|
||||
{
|
||||
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 15px", TRUE);
|
||||
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 11", TRUE);
|
||||
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)
|
||||
{
|
||||
const char *text = "Hello";
|
||||
@@ -2360,7 +2252,6 @@ parse_text_node (GtkCssParser *parser,
|
||||
for (i = 0; i < strlen (text); i++)
|
||||
{
|
||||
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + text[i];
|
||||
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||
glyphs->glyphs[i] = gi;
|
||||
}
|
||||
}
|
||||
@@ -2538,6 +2429,39 @@ clear_dash (gpointer inout_array)
|
||||
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
|
||||
parse_fill_rule (GtkCssParser *parser,
|
||||
Context *context,
|
||||
@@ -3324,33 +3248,6 @@ append_string_param (Printer *p,
|
||||
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
|
||||
append_vec4_param (Printer *p,
|
||||
const char *param_name,
|
||||
@@ -3574,7 +3471,7 @@ gsk_text_node_serialize_font (GskRenderNode *node,
|
||||
PangoFontDescription *desc;
|
||||
char *s;
|
||||
|
||||
desc = pango_font_describe_with_absolute_size (font);
|
||||
desc = pango_font_describe (font);
|
||||
s = pango_font_description_to_string (desc);
|
||||
g_string_append_printf (p->str, "\"%s\"", s);
|
||||
g_free (s);
|
||||
@@ -3618,37 +3515,6 @@ gsk_text_node_serialize_font (GskRenderNode *node,
|
||||
#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
|
||||
gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
GString *p)
|
||||
@@ -3730,6 +3596,33 @@ gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
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
|
||||
append_path_param (Printer *p,
|
||||
const char *param_name,
|
||||
@@ -4194,8 +4087,6 @@ render_node_print (Printer *p,
|
||||
if (!graphene_point_equal (offset, graphene_point_zero ()))
|
||||
append_point_param (p, "offset", offset);
|
||||
|
||||
gsk_text_node_serialize_font_options (node, p);
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
@@ -4466,8 +4357,6 @@ render_node_print (Printer *p,
|
||||
start_node (p, "subsurface", node_name);
|
||||
|
||||
append_node_param (p, "child", gsk_subsurface_node_get_child (node));
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "gtkatspicontextprivate.h"
|
||||
|
||||
#include "gtkaccessibleprivate.h"
|
||||
#include "gtkaccessibletextprivate.h"
|
||||
#include "gtkaccessibletext-private.h"
|
||||
|
||||
#include "gtkatspiactionprivate.h"
|
||||
#include "gtkatspieditabletextprivate.h"
|
||||
@@ -771,7 +771,7 @@ emit_text_selection_changed (GtkAtSpiContext *self,
|
||||
"org.a11y.atspi.Event.Object",
|
||||
"TextCaretMoved",
|
||||
g_variant_new ("(siiva{sv})",
|
||||
"", cursor_position, 0, g_variant_new_int32 (0), NULL),
|
||||
"", cursor_position, 0, g_variant_new_string (""), NULL),
|
||||
NULL);
|
||||
else
|
||||
g_dbus_connection_emit_signal (self->connection,
|
||||
@@ -1590,7 +1590,7 @@ gtk_at_spi_context_update_caret_position (GtkATContext *context)
|
||||
"",
|
||||
(int) offset,
|
||||
0,
|
||||
g_variant_new_int32 (0),
|
||||
g_variant_new_string (""),
|
||||
NULL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -418,8 +418,8 @@ gtk_at_spi_socket_embed (GtkAtSpiSocket *self,
|
||||
* usually done through a side channel with the remote side, for
|
||||
* example using sockets, or reading the output of a subprocess.
|
||||
*
|
||||
* The remote accessible object at @object_path must support
|
||||
* the `org.a11y.atspi.Socket` interface with the `Embedded()`
|
||||
* The remote accessible object at @object_path must be a must
|
||||
* have an `org.a11y.atspi.Socket` interface with the `Embedded()`
|
||||
* method.
|
||||
*
|
||||
* 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:
|
||||
* @self: a #GtkAtSpiSocket
|
||||
*
|
||||
* Retrieves the object path of the remote accessible object that
|
||||
* Retrieves the object path of the remove accessible object that
|
||||
* the socket is connected to.
|
||||
*
|
||||
* Returns: (transfer none): the object path of the socket remote
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "a11y/atspi/atspi-text.h"
|
||||
|
||||
#include "gtkaccessibletextprivate.h"
|
||||
#include "gtkatcontextprivate.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkeditable.h"
|
||||
@@ -42,6 +41,7 @@
|
||||
#include "gtkspinbuttonprivate.h"
|
||||
#include "gtktextbufferprivate.h"
|
||||
#include "gtktextviewprivate.h"
|
||||
#include "gtkaccessibletext-private.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
@@ -222,72 +222,19 @@ accessible_text_handle_method (GDBusConnection *connection,
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
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);
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||
{
|
||||
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));
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
||||
{
|
||||
gsize n_ranges;
|
||||
GtkAccessibleTextRange *ranges = NULL;
|
||||
|
||||
if (!gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges))
|
||||
n_ranges = 0;
|
||||
gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", (int)n_ranges));
|
||||
|
||||
@@ -301,8 +248,7 @@ accessible_text_handle_method (GDBusConnection *connection,
|
||||
|
||||
g_variant_get (parameters, "(i)", &num);
|
||||
|
||||
if (!gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges))
|
||||
n_ranges = 0;
|
||||
gtk_accessible_text_get_selection (accessible_text, &n_ranges, &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);
|
||||
@@ -1110,20 +1056,15 @@ gtk_editable_get_text_widget (GtkWidget *widget)
|
||||
{
|
||||
if (GTK_IS_EDITABLE (widget))
|
||||
{
|
||||
GtkEditable *editable;
|
||||
guint redirects = 0;
|
||||
GtkEditable *delegate;
|
||||
|
||||
editable = GTK_EDITABLE (widget);
|
||||
delegate = gtk_editable_get_delegate (GTK_EDITABLE (widget));
|
||||
|
||||
do {
|
||||
if (GTK_IS_TEXT (editable))
|
||||
return GTK_TEXT (editable);
|
||||
if (GTK_IS_TEXT (delegate))
|
||||
return GTK_TEXT (delegate);
|
||||
|
||||
if (++redirects >= 6)
|
||||
g_assert_not_reached ();
|
||||
|
||||
editable = gtk_editable_get_delegate (editable);
|
||||
} while (editable != NULL);
|
||||
if (GTK_IS_TEXT (widget))
|
||||
return GTK_TEXT (widget);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1668,79 +1609,63 @@ text_view_handle_method (GDBusConnection *connection,
|
||||
}
|
||||
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}"));
|
||||
GHashTable *attrs;
|
||||
GHashTableIter iter;
|
||||
int offset;
|
||||
int start, end;
|
||||
gpointer key, value;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
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 : "");
|
||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &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)
|
||||
{
|
||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
const char *name;
|
||||
int start, end;
|
||||
GVariant *attrs;
|
||||
const char *val;
|
||||
GHashTable *attrs;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
|
||||
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, FALSE, &start, &end);
|
||||
val = g_hash_table_lookup (attrs, name);
|
||||
if (val == NULL)
|
||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
||||
|
||||
attrs = g_variant_builder_end (&builder);
|
||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
||||
val = "";
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
g_hash_table_unref (attrs);
|
||||
g_variant_unref (attrs);
|
||||
}
|
||||
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}"));
|
||||
int offset;
|
||||
gboolean include_defaults;
|
||||
int start, end;
|
||||
GHashTable *attrs;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, include_defaults, &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 : "");
|
||||
if (include_defaults)
|
||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), &builder);
|
||||
|
||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &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 ||
|
||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||
{
|
||||
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), 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 : "");
|
||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), &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)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,101 @@
|
||||
#include "gtktextviewprivate.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 *
|
||||
gtk_text_view_get_text_before (GtkTextView *view,
|
||||
int offset,
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_text_view_add_default_attributes (GtkTextView *view,
|
||||
GVariantBuilder *builder);
|
||||
|
||||
char *gtk_text_view_get_text_before (GtkTextView *view,
|
||||
int offset,
|
||||
AtspiTextBoundaryType boundary_type,
|
||||
|
||||
@@ -370,7 +370,6 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object,
|
||||
else
|
||||
texture = NULL;
|
||||
take_image_definition (cellpixbuf, gtk_image_definition_new_paintable (GDK_PAINTABLE (texture)));
|
||||
g_clear_object (&texture);
|
||||
break;
|
||||
case PROP_PIXBUF_EXPANDER_OPEN:
|
||||
g_clear_object (&priv->pixbuf_expander_open);
|
||||
|
||||
Binary file not shown.
@@ -24,14 +24,9 @@
|
||||
|
||||
/* The format of the generated data is: a(aussasasu).
|
||||
* Each member of the array has the following fields:
|
||||
* au - sequence of unicode codepoints, including the emoji presentation
|
||||
* selector (FE0F) where necessary. skin tone variations are represented
|
||||
* 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.
|
||||
* au - sequence of unicode codepoints. If the
|
||||
* sequence contains a 0, it marks the point
|
||||
* where skin tone modifiers should be inserted
|
||||
* s - name in english, e.g. "man worker"
|
||||
* s - name in locale
|
||||
* as - keywords in english, e.g. "man", "worker"
|
||||
@@ -53,8 +48,7 @@
|
||||
|
||||
gboolean
|
||||
parse_code (GVariantBuilder *b,
|
||||
const char *code,
|
||||
gboolean needs_presentation_selector)
|
||||
const char *code)
|
||||
{
|
||||
g_auto(GStrv) strv = NULL;
|
||||
int j;
|
||||
@@ -72,31 +66,11 @@ parse_code (GVariantBuilder *b,
|
||||
return FALSE;
|
||||
}
|
||||
if (0x1f3fb <= u && u <= 0x1f3ff)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
g_variant_builder_add (b, "u", 0);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -146,6 +120,7 @@ main (int argc, char *argv[])
|
||||
array_en = json_node_get_array (root_en);
|
||||
length_en = json_array_get_length (array_en);
|
||||
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)"));
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
@@ -158,21 +133,13 @@ main (int argc, char *argv[])
|
||||
const char *name;
|
||||
const char *name_en;
|
||||
char *code;
|
||||
const char *text;
|
||||
gboolean needs_presentation_selector;
|
||||
|
||||
if (!json_object_has_member (obj, "group"))
|
||||
continue;
|
||||
if (!json_object_has_member (obj_en, "group"))
|
||||
continue;
|
||||
|
||||
group = json_object_get_int_member (obj, "group");
|
||||
name = json_object_get_string_member (obj, "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"))
|
||||
{
|
||||
JsonArray *a2 = json_object_get_array_member (obj, "skins");
|
||||
@@ -184,12 +151,9 @@ main (int argc, char *argv[])
|
||||
{
|
||||
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
if (!parse_code (&b1, code))
|
||||
return 1;
|
||||
|
||||
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.
@@ -1,4 +1,4 @@
|
||||
/* gtkaccessibletextprivate.h: Private definitions for GtkAccessibleText
|
||||
/* gtkaccessibletext-private.h: Private definitions for GtkAccessibleText
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Emmanuele Bassi
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
@@ -37,19 +37,4 @@ gtk_accessible_text_get_attributes (GtkAccessibleText *self,
|
||||
GtkAccessibleTextRange **ranges,
|
||||
char ***attribute_names,
|
||||
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
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkaccessibletextprivate.h"
|
||||
#include "gtkaccessibletext-private.h"
|
||||
|
||||
#include "gtkatcontextprivate.h"
|
||||
|
||||
@@ -63,15 +63,6 @@ gtk_accessible_text_default_get_attributes (GtkAccessibleText *self,
|
||||
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
|
||||
gtk_accessible_text_default_init (GtkAccessibleTextInterface *iface)
|
||||
{
|
||||
@@ -80,7 +71,6 @@ gtk_accessible_text_default_init (GtkAccessibleTextInterface *iface)
|
||||
iface->get_caret_position = gtk_accessible_text_default_get_caret_position;
|
||||
iface->get_selection = gtk_accessible_text_default_get_selection;
|
||||
iface->get_attributes = gtk_accessible_text_default_get_attributes;
|
||||
iface->get_default_attributes = gtk_accessible_text_default_get_default_attributes;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
@@ -165,16 +155,12 @@ gtk_accessible_text_get_contents_at (GtkAccessibleText *self,
|
||||
unsigned int *start,
|
||||
unsigned int *end)
|
||||
{
|
||||
static const char empty[] = {0};
|
||||
GBytes *bytes;
|
||||
|
||||
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);
|
||||
|
||||
if (bytes == NULL)
|
||||
return g_bytes_new_static (empty, sizeof empty);
|
||||
|
||||
return nul_terminate_contents (bytes);
|
||||
}
|
||||
|
||||
@@ -274,158 +260,6 @@ gtk_accessible_text_get_attributes (GtkAccessibleText *self,
|
||||
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:
|
||||
* @self: the accessible object
|
||||
|
||||
@@ -228,33 +228,6 @@ struct _GtkAccessibleTextInterface
|
||||
GtkAccessibleTextRange **ranges,
|
||||
char ***attribute_names,
|
||||
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
|
||||
|
||||
@@ -1390,25 +1390,9 @@ gtk_at_context_get_text_accumulate (GtkATContext *self,
|
||||
{
|
||||
const char *text = gtk_widget_get_tooltip_text (GTK_WIDGET (self->accessible));
|
||||
if (text && not_just_space (text))
|
||||
{
|
||||
gboolean append = !check_duplicates;
|
||||
|
||||
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);
|
||||
}
|
||||
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)))
|
||||
append_with_space (res, text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,9 @@
|
||||
* Objects are described by `<object>` elements, which can contain
|
||||
* `<property>` elements to set properties, `<signal>` elements which
|
||||
* connect signals to handlers, and `<child>` elements, which describe
|
||||
* child objects.
|
||||
* child objects (most often widgets inside a container, but also e.g.
|
||||
* 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>`
|
||||
* element is specified by the “class” attribute. If the type has not
|
||||
@@ -171,53 +173,6 @@
|
||||
* 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.
|
||||
*
|
||||
* ### 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
|
||||
*
|
||||
* It is also possible to bind a property value to another object's
|
||||
@@ -253,11 +208,6 @@
|
||||
* For more information, see the documentation of the
|
||||
* [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
|
||||
*
|
||||
* Sometimes it is necessary to refer to widgets which have implicitly
|
||||
|
||||
@@ -242,7 +242,6 @@ gtk_emoji_chooser_finalize (GObject *object)
|
||||
g_source_remove (chooser->populate_idle);
|
||||
|
||||
g_clear_pointer (&chooser->data, g_variant_unref);
|
||||
g_clear_pointer (&chooser->iter, g_variant_iter_free);
|
||||
g_clear_object (&chooser->settings);
|
||||
|
||||
G_OBJECT_CLASS (gtk_emoji_chooser_parent_class)->finalize (object);
|
||||
@@ -449,7 +448,7 @@ static gboolean
|
||||
has_variations (GVariant *emoji_data)
|
||||
{
|
||||
GVariant *codes;
|
||||
gsize i;
|
||||
int i;
|
||||
gboolean has_variations;
|
||||
|
||||
has_variations = FALSE;
|
||||
@@ -458,7 +457,7 @@ has_variations (GVariant *emoji_data)
|
||||
{
|
||||
gunichar code;
|
||||
g_variant_get_child (codes, i, "u", &code);
|
||||
if (code == 0 || code == 0x1f3fb)
|
||||
if (code == 0)
|
||||
{
|
||||
has_variations = TRUE;
|
||||
break;
|
||||
@@ -571,14 +570,15 @@ add_emoji (GtkWidget *box,
|
||||
{
|
||||
g_variant_get_child (codes, i, "u", &code);
|
||||
if (code == 0)
|
||||
code = modifier != 0 ? modifier : 0xfe0f;
|
||||
if (code == 0x1f3fb)
|
||||
code = modifier;
|
||||
if (code != 0)
|
||||
p += g_unichar_to_utf8 (code, p);
|
||||
}
|
||||
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;
|
||||
|
||||
label = gtk_label_new (text);
|
||||
|
||||
@@ -409,7 +409,7 @@ has_variations (GVariant *emoji_data)
|
||||
{
|
||||
gunichar code;
|
||||
g_variant_get_child (codes, i, "u", &code);
|
||||
if (code == 0 || code == 0x1f3fb)
|
||||
if (code == 0)
|
||||
{
|
||||
has_variations = TRUE;
|
||||
break;
|
||||
@@ -438,13 +438,12 @@ get_text (GVariant *emoji_data,
|
||||
|
||||
g_variant_get_child (codes, i, "u", &code);
|
||||
if (code == 0)
|
||||
code = modifier != 0 ? modifier : 0xfe0f;
|
||||
if (code == 0x1f3fb)
|
||||
code = modifier;
|
||||
if (code != 0)
|
||||
p += g_unichar_to_utf8 (code, p);
|
||||
}
|
||||
g_variant_unref (codes);
|
||||
p += g_unichar_to_utf8 (0xFE0F, p); /* U+FE0F is the Emoji variation selector */
|
||||
p[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,10 +150,9 @@
|
||||
* <constant type='gchararray'>Hello, world</constant>
|
||||
* ```
|
||||
*
|
||||
* To create a closure expression, use the `<closure>` element. The `function`
|
||||
* attribute specifies what function to use for the closure, and the `type`
|
||||
* attribute specifies its return type. The content of the element contains the
|
||||
* expressions for the parameters. For instance:
|
||||
* To create a closure expression, use the `<closure>` element. The `type` and `function`
|
||||
* attributes specify what function to use for the closure, the content of the element
|
||||
* contains the expressions for the parameters. For instance:
|
||||
*
|
||||
* ```xml
|
||||
* <closure type='gchararray' function='combine_args_somehow'>
|
||||
@@ -161,22 +160,6 @@
|
||||
* <lookup type='GFile' name='size'>myfile</lookup>
|
||||
* </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;
|
||||
|
||||
@@ -708,7 +708,6 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry)
|
||||
old_file_part = chooser_entry->file_part;
|
||||
|
||||
text = gtk_file_chooser_entry_get_completion_text (chooser_entry);
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
last_slash = strrchr (text, G_DIR_SEPARATOR);
|
||||
if (last_slash)
|
||||
|
||||
@@ -2232,7 +2232,6 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
|
||||
attr->start_index = 0;
|
||||
attr->end_index = strlen (input);
|
||||
pango_attr_list_insert (attrs, attr);
|
||||
g_free (str);
|
||||
str = g_strconcat (item->name, " 1", NULL);
|
||||
attr = pango_attr_font_features_new (str);
|
||||
attr->start_index = strlen (input) + strlen (" → ");
|
||||
@@ -2242,7 +2241,6 @@ update_feature_example (GtkFontChooserWidget *fontchooser,
|
||||
attr->start_index = strlen (input) + strlen (" → ");
|
||||
attr->end_index = attr->start_index + strlen (input);
|
||||
pango_attr_list_insert (attrs, attr);
|
||||
g_free (str);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (item->example), text);
|
||||
gtk_label_set_attributes (GTK_LABEL (item->example), attrs);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include "gtkimcontext.h"
|
||||
#include "gtkimcontextprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkmarshalers.h"
|
||||
@@ -1006,30 +1007,11 @@ gtk_im_context_set_property (GObject *obj,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
void
|
||||
gtk_im_context_activate_osk (GtkIMContext *context)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
|
||||
g_return_val_if_fail (!event || GDK_IS_EVENT (event), FALSE);
|
||||
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
|
||||
|
||||
if (!GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk_with_event)
|
||||
return FALSE;
|
||||
|
||||
return GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk_with_event (context, event);
|
||||
if (GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk)
|
||||
GTK_IM_CONTEXT_GET_CLASS (context)->activate_osk (context);
|
||||
}
|
||||
|
||||
@@ -96,10 +96,9 @@ struct _GtkIMContextClass
|
||||
|
||||
/*< private >*/
|
||||
void (* activate_osk) (GtkIMContext *context);
|
||||
gboolean (* activate_osk_with_event) (GtkIMContext *context,
|
||||
GdkEvent *event);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
@@ -169,10 +168,6 @@ gboolean gtk_im_context_delete_surrounding (GtkIMContext *context,
|
||||
int offset,
|
||||
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_END_DECLS
|
||||
|
||||
23
gtk/gtkimcontextprivate.h
Normal file
23
gtk/gtkimcontextprivate.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* 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,6 +71,10 @@ struct _GtkIMContextWayland
|
||||
GtkIMContextSimple parent_instance;
|
||||
GtkWidget *widget;
|
||||
|
||||
GtkGesture *gesture;
|
||||
double press_x;
|
||||
double press_y;
|
||||
|
||||
struct {
|
||||
char *text;
|
||||
int cursor_idx;
|
||||
@@ -517,6 +521,7 @@ gtk_im_context_wayland_finalize (GObject *object)
|
||||
gtk_im_context_wayland_focus_out (GTK_IM_CONTEXT (context));
|
||||
|
||||
g_clear_object (&context->widget);
|
||||
g_clear_object (&context->gesture);
|
||||
g_free (context->surrounding.text);
|
||||
g_free (context->current_preedit.text);
|
||||
g_free (context->pending_preedit.text);
|
||||
@@ -525,6 +530,50 @@ gtk_im_context_wayland_finalize (GObject *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
|
||||
gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
|
||||
GtkWidget *widget)
|
||||
@@ -537,7 +586,34 @@ gtk_im_context_wayland_set_client_widget (GtkIMContext *context,
|
||||
if (context_wayland->widget)
|
||||
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);
|
||||
|
||||
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
|
||||
@@ -771,6 +847,9 @@ gtk_im_context_wayland_focus_in (GtkIMContext *context)
|
||||
if (!global->text_input)
|
||||
return;
|
||||
|
||||
if (self->gesture)
|
||||
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (self->gesture));
|
||||
|
||||
if (global->focused)
|
||||
enable (self, global);
|
||||
}
|
||||
@@ -805,6 +884,7 @@ gtk_im_context_wayland_set_cursor_location (GtkIMContext *context,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
GtkIMContextWayland *context_wayland;
|
||||
int side;
|
||||
|
||||
context_wayland = GTK_IM_CONTEXT_WAYLAND (context);
|
||||
|
||||
@@ -814,6 +894,20 @@ gtk_im_context_wayland_set_cursor_location (GtkIMContext *context,
|
||||
context_wayland->cursor_rect.height == rect->height)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -880,20 +974,18 @@ gtk_im_context_wayland_commit (GtkIMContext *context,
|
||||
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_im_context_wayland_activate_osk_with_event (GtkIMContext *context,
|
||||
GdkEvent *event)
|
||||
static void
|
||||
gtk_im_context_wayland_activate_osk (GtkIMContext *context)
|
||||
{
|
||||
GtkIMContextWaylandGlobal *global;
|
||||
|
||||
global = gtk_im_context_wayland_get_global (GTK_IM_CONTEXT_WAYLAND (context));
|
||||
if (global == NULL)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
zwp_text_input_v3_enable (global->text_input);
|
||||
notify_im_change (GTK_IM_CONTEXT_WAYLAND (context),
|
||||
ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_OTHER);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -915,7 +1007,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->get_surrounding_with_selection = gtk_im_context_wayland_get_surrounding;
|
||||
im_context_class->commit = gtk_im_context_wayland_commit;
|
||||
im_context_class->activate_osk_with_event = gtk_im_context_wayland_activate_osk_with_event;
|
||||
im_context_class->activate_osk = gtk_im_context_wayland_activate_osk;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "gtkimcontextprivate.h"
|
||||
#include "gtkimmulticontext.h"
|
||||
#include "gtkimmoduleprivate.h"
|
||||
#include "gtklabel.h"
|
||||
@@ -105,8 +106,7 @@ static gboolean gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *
|
||||
int offset,
|
||||
int n_chars,
|
||||
GtkIMMulticontext *multicontext);
|
||||
static gboolean gtk_im_multicontext_activate_osk_with_event (GtkIMContext *context,
|
||||
GdkEvent *event);
|
||||
static void gtk_im_multicontext_activate_osk (GtkIMContext *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_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->activate_osk_with_event = gtk_im_multicontext_activate_osk_with_event;
|
||||
im_context_class->activate_osk = gtk_im_multicontext_activate_osk;
|
||||
|
||||
gobject_class->finalize = gtk_im_multicontext_finalize;
|
||||
}
|
||||
@@ -516,17 +516,14 @@ gtk_im_multicontext_set_surrounding_with_selection (GtkIMContext *context,
|
||||
gtk_im_context_set_surrounding_with_selection (delegate, text, len, cursor_index, anchor_index);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_im_multicontext_activate_osk_with_event (GtkIMContext *context,
|
||||
GdkEvent *event)
|
||||
static void
|
||||
gtk_im_multicontext_activate_osk (GtkIMContext *context)
|
||||
{
|
||||
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
|
||||
GtkIMContext *delegate = gtk_im_multicontext_get_delegate (multicontext);
|
||||
|
||||
if (delegate)
|
||||
return gtk_im_context_activate_osk (delegate, event);
|
||||
else
|
||||
return FALSE;
|
||||
gtk_im_context_activate_osk (delegate);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "gtkinscriptionprivate.h"
|
||||
|
||||
#include "gtkaccessibletextprivate.h"
|
||||
#include "gtkaccessibletext-private.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkcssstylechangeprivate.h"
|
||||
#include "gtkpangoprivate.h"
|
||||
@@ -1363,19 +1363,6 @@ gtk_inscription_accessible_text_get_contents (GtkAccessibleText *self,
|
||||
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
|
||||
gtk_inscription_accessible_text_get_caret_position (GtkAccessibleText *self)
|
||||
{
|
||||
@@ -1421,29 +1408,13 @@ gtk_inscription_accessible_text_get_attributes (GtkAccessibleText *self,
|
||||
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
|
||||
gtk_inscription_accessible_text_init (GtkAccessibleTextInterface *iface)
|
||||
{
|
||||
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_selection = gtk_inscription_accessible_text_get_selection;
|
||||
iface->get_attributes = gtk_inscription_accessible_text_get_attributes;
|
||||
iface->get_default_attributes = gtk_inscription_accessible_text_get_default_attributes;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user