Compare commits

..

2 Commits

Author SHA1 Message Date
Matthias Clasen
675214574c css: Break the selector tree into many
Since we can only match one name, doing a hash
by matcher name lets us quickly discard most
initial selectors, and having much smaller trees.

We can apply the same idea for style classes,
as well, by looking up a tree for each class.

Comparing the number of gtk_css_selector_match() calls
while moving the pointer outside the window, I see:

Before:
65773 selector matches (12863 positive)

After:
32704 selector matches (12278 positive)

So this cuts the numer of selectors we need to check
roughly in half, at the cost of a handful of hash table
lookups.
2020-01-19 19:00:00 -05:00
Matthias Clasen
31b15bf5e0 css: Add getters for a matchers name and classes
These will be used in the selector tree in the future.

The classes getter annoyingly has to allow returning
allocated memory, due to widget paths. This can be
removed when widget paths go away.
2020-01-19 19:00:00 -05:00
140 changed files with 4224 additions and 5688 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -775,6 +775,7 @@ gtk_container_add
gtk_container_remove
gtk_container_foreach
gtk_container_get_children
gtk_container_get_path_for_child
gtk_container_get_focus_vadjustment
gtk_container_set_focus_vadjustment
gtk_container_get_focus_hadjustment
@@ -4411,6 +4412,7 @@ gtk_widget_get_layout_manager
gtk_widget_should_layout
<SUBSECTION>
gtk_widget_get_path
gtk_widget_get_style_context
gtk_widget_reset_style
gtk_widget_class_get_css_name
@@ -4895,6 +4897,7 @@ gtk_border_free
<SUBSECTION>
gtk_render_arrow
gtk_render_background
gtk_render_background_get_clip
gtk_render_check
gtk_render_expander
gtk_render_focus

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -196,7 +196,7 @@ dump_node (GskRenderNode *node,
cairo_surface_destroy (surface);
}
static inline gboolean G_GNUC_PURE
static inline gboolean
node_is_invisible (const GskRenderNode *node)
{
return node->bounds.size.width == 0.0f ||
@@ -237,7 +237,7 @@ sort_border_sides (const GdkRGBA *colors,
}
}
static inline gboolean G_GNUC_PURE
static inline gboolean
color_matrix_modifies_alpha (GskRenderNode *node)
{
const graphene_matrix_t *matrix = gsk_color_matrix_node_peek_color_matrix (node);
@@ -261,7 +261,7 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
MAX (self->corner[2].height, self->corner[3].height)) * 2);
}
static inline gboolean G_GNUC_PURE
static inline gboolean
node_supports_transform (GskRenderNode *node)
{
/* Some nodes can't handle non-trivial transforms without being
@@ -535,16 +535,17 @@ transform_rect (GskGLRenderer *self,
RenderOpBuilder *builder,
const GskRoundedRect *rect)
{
const float scale = ops_get_scale (builder);
GskRoundedRect r;
int i;
r.bounds.origin.x = builder->dx + rect->bounds.origin.x;
r.bounds.origin.y = builder->dy + rect->bounds.origin.y;
r.bounds.size = rect->bounds.size;
ops_transform_bounds_modelview (builder, &rect->bounds, &r.bounds);
r.corner[0] = rect->corner[0];
r.corner[1] = rect->corner[1];
r.corner[2] = rect->corner[2];
r.corner[3] = rect->corner[3];
for (i = 0; i < 4; i ++)
{
r.corner[i].width = rect->corner[i].width * scale;
r.corner[i].height = rect->corner[i].height * scale;
}
return r;
}
@@ -611,7 +612,7 @@ render_fallback_node (GskGLRenderer *self,
cairo_fill (cr);
cairo_restore (cr);
#ifdef G_ENABLE_DEBUG
#if G_ENABLE_DEBUG
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), FALLBACK))
{
cairo_move_to (cr, 0, 0);
@@ -744,18 +745,24 @@ render_border_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const float min_x = builder->dx + node->bounds.origin.x;
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const GdkRGBA *colors = gsk_border_node_peek_colors (node);
const GskRoundedRect *rounded_outline = gsk_border_node_peek_outline (node);
const float *widths = gsk_border_node_peek_widths (node);
const float *og_widths = gsk_border_node_peek_widths (node);
float widths[4];
int i;
struct {
float w;
float h;
} sizes[4];
if (widths[0] == widths[1] &&
widths[0] == widths[2] &&
widths[0] == widths[3] &&
if (og_widths[0] == og_widths[1] &&
og_widths[0] == og_widths[2] &&
og_widths[0] == og_widths[3] &&
gdk_rgba_equal (&colors[0], &colors[1]) &&
gdk_rgba_equal (&colors[0], &colors[2]) &&
gdk_rgba_equal (&colors[0], &colors[3]))
@@ -766,7 +773,7 @@ render_border_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = &colors[0];
op->outline = transform_rect (self, builder, rounded_outline);
op->spread = widths[0];
op->spread = og_widths[0] * scale;
op->offset[0] = 0;
op->offset[1] = 0;
@@ -774,6 +781,9 @@ render_border_node (GskGLRenderer *self,
return;
}
for (i = 0; i < 4; i ++)
widths[i] = og_widths[i];
/* Top left */
if (widths[3] > 0)
sizes[0].w = MAX (widths[3], rounded_outline->corner[0].width);
@@ -819,11 +829,10 @@ render_border_node (GskGLRenderer *self,
else
sizes[3].h = 0;
for (i = 0; i < 4; i ++)
widths[i] *= scale;
{
const float min_x = builder->dx + node->bounds.origin.x;
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const GskQuadVertex side_data[4][6] = {
/* Top */
{
@@ -1180,16 +1189,17 @@ render_rounded_clip_node (GskGLRenderer *self,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const GskRoundedRect *clip = gsk_rounded_clip_node_peek_clip (node);
GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
GskRoundedRect child_clip = *gsk_rounded_clip_node_peek_clip (node);
GskRoundedRect transformed_clip;
GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
gboolean need_offscreen;
int i;
if (node_is_invisible (child))
return;
ops_transform_bounds_modelview (builder, &clip->bounds, &transformed_clip.bounds);
transformed_clip = child_clip;
ops_transform_bounds_modelview (builder, &child_clip.bounds, &transformed_clip.bounds);
if (!ops_has_clip (builder))
need_offscreen = FALSE;
@@ -1205,8 +1215,8 @@ render_rounded_clip_node (GskGLRenderer *self,
* the new clip and add the render ops */
for (i = 0; i < 4; i ++)
{
transformed_clip.corner[i].width = clip->corner[i].width * scale;
transformed_clip.corner[i].height = clip->corner[i].height * scale;
transformed_clip.corner[i].width *= scale;
transformed_clip.corner[i].height *= scale;
}
ops_push_clip (builder, &transformed_clip);
@@ -1215,7 +1225,7 @@ render_rounded_clip_node (GskGLRenderer *self,
}
else
{
GskRoundedRect scaled_clip;
graphene_matrix_t scale_matrix;
gboolean is_offscreen;
TextureRegion region;
/* NOTE: We are *not* transforming the clip by the current modelview here.
@@ -1224,19 +1234,18 @@ render_rounded_clip_node (GskGLRenderer *self,
*
* We do, however, apply the scale factor to the child clip of course.
*/
scaled_clip.bounds.origin.x = clip->bounds.origin.x * scale;
scaled_clip.bounds.origin.y = clip->bounds.origin.y * scale;
scaled_clip.bounds.size.width = clip->bounds.size.width * scale;
scaled_clip.bounds.size.height = clip->bounds.size.height * scale;
graphene_matrix_init_scale (&scale_matrix, scale, scale, 1.0f);
graphene_matrix_transform_bounds (&scale_matrix, &child_clip.bounds, &child_clip.bounds);
/* Increase corner radius size by scale factor */
for (i = 0; i < 4; i ++)
{
scaled_clip.corner[i].width = clip->corner[i].width * scale;
scaled_clip.corner[i].height = clip->corner[i].height * scale;
child_clip.corner[i].width *= scale;
child_clip.corner[i].height *= scale;
}
ops_push_clip (builder, &scaled_clip);
ops_push_clip (builder, &child_clip);
if (!add_offscreen_ops (self, builder, &node->bounds,
child,
&region, &is_offscreen,
@@ -1446,9 +1455,6 @@ render_blur_node (GskGLRenderer *self,
GskRenderNode *child = gsk_blur_node_get_child (node);
TextureRegion blurred_region;
if (node_is_invisible (child))
return;
if (blur_radius <= 0)
{
gsk_gl_renderer_add_render_ops (self, child, builder);
@@ -1475,6 +1481,7 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const float blur_radius = gsk_inset_shadow_node_get_blur_radius (node);
const float dx = gsk_inset_shadow_node_get_dx (node);
const float dy = gsk_inset_shadow_node_get_dy (node);
@@ -1487,9 +1494,9 @@ render_unblurred_inset_shadow_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
op->color = gsk_inset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, gsk_inset_shadow_node_peek_outline (node));
op->spread = spread;
op->offset[0] = dx;
op->offset[1] = dy;
op->spread = spread * scale;
op->offset[0] = dx * scale;
op->offset[1] = dy * scale;
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
@@ -1640,6 +1647,7 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const GskRoundedRect *outline = gsk_outset_shadow_node_peek_outline (node);
const float spread = gsk_outset_shadow_node_get_spread (node);
const float dx = gsk_outset_shadow_node_get_dx (node);
@@ -1650,9 +1658,9 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
op->color = gsk_outset_shadow_node_peek_color (node);
op->outline = transform_rect (self, builder, outline);
op->spread = spread;
op->offset[0] = dx;
op->offset[1] = dy;
op->spread = spread * scale;
op->offset[0] = dx * scale;
op->offset[1] = dy * scale;
load_vertex_data (ops_draw (builder, NULL), node, builder);
}
@@ -2155,24 +2163,14 @@ render_cross_fade_node (GskGLRenderer *self,
start_node,
&start_region, &is_offscreen1,
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
{
gsk_gl_renderer_add_render_ops (self, end_node, builder);
return;
}
g_assert_not_reached ();
if (!add_offscreen_ops (self, builder,
&node->bounds,
end_node,
&end_region, &is_offscreen2,
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
{
load_vertex_data_with_region (ops_draw (builder, NULL),
node,
builder,
&start_region,
TRUE);
return;
}
g_assert_not_reached ();
ops_set_program (builder, &self->cross_fade_program);
@@ -2578,7 +2576,6 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
gboolean success = TRUE;
gsk_gl_shader_builder_init (&shader_builder,
"/org/gtk/libgsk/glsl/preamble.glsl",
"/org/gtk/libgsk/glsl/preamble.vs.glsl",
"/org/gtk/libgsk/glsl/preamble.fs.glsl");
@@ -2773,7 +2770,6 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
GError **error)
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
gint64 before = g_get_monotonic_time ();
/* If we didn't get a GdkGLContext before realization, try creating
* one now, for our exclusive use.
@@ -2803,9 +2799,6 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
self->icon_cache = get_icon_cache_for_display (gdk_surface_get_display (surface), self->atlases);
gsk_gl_shadow_cache_init (&self->shadow_cache);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "gl renderer realize", NULL);
return TRUE;
}
@@ -3492,7 +3485,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
gsk_profiler_push_samples (profiler);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (start_time, cpu_time, "GL render", "");
gdk_profiler_add_mark (start_time, cpu_time, "render", "");
#endif
}

View File

@@ -8,7 +8,7 @@ rect_equal (const graphene_rect_t *a,
return memcmp (a, b, sizeof (graphene_rect_t)) == 0;
}
static inline gboolean G_GNUC_PURE
static inline gboolean
rounded_rect_equal (const GskRoundedRect *r1,
const GskRoundedRect *r2)
{
@@ -31,7 +31,7 @@ rounded_rect_equal (const GskRoundedRect *r1,
return TRUE;
}
static inline gboolean G_GNUC_PURE
static inline gboolean
rounded_rect_corners_equal (const GskRoundedRect *r1,
const GskRoundedRect *r2)
{
@@ -180,15 +180,13 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst)
{
graphene_rect_t r = *src;
g_assert (builder->mv_stack != NULL);
g_assert (builder->mv_stack->len >= 1);
r.origin.x += builder->dx;
r.origin.y += builder->dy;
gsk_transform_transform_bounds (builder->current_modelview, src, dst);
gsk_transform_transform_bounds (builder->current_modelview, &r, dst);
dst->origin.x += builder->dx * builder->scale_x;
dst->origin.y += builder->dy * builder->scale_y;
}
void

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -297,25 +297,17 @@ gtk_application_startup (GApplication *g_application)
{
GtkApplication *application = GTK_APPLICATION (g_application);
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
gint64 before = g_get_monotonic_time ();
gint64 before2;
G_APPLICATION_CLASS (gtk_application_parent_class)->startup (g_application);
gtk_action_muxer_insert (priv->muxer, "app", G_ACTION_GROUP (application));
before2 = g_get_monotonic_time ();
gtk_init ();
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before2 * 1000, (g_get_monotonic_time () - before2) * 1000, "gtk init", NULL);
priv->impl = gtk_application_impl_new (application, gdk_display_get_default ());
gtk_application_impl_startup (priv->impl, priv->register_session);
gtk_application_load_resources (application);
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "gtk application startup", NULL);
}
static void

View File

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

View File

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

View File

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

View File

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

View File

@@ -299,7 +299,7 @@ gtk_css_value_array_transition (GtkCssValue *start,
}
static gboolean
gtk_css_value_array_is_dynamic (const GtkCssValue *value)
gtk_css_value_array_is_dynamic (GtkCssValue *value)
{
guint i;

View File

@@ -34,7 +34,7 @@ GtkCssValue * _gtk_css_array_value_parse (GtkCssParser *
GtkCssValue * _gtk_css_array_value_get_nth (GtkCssValue *value,
guint i);
guint _gtk_css_array_value_get_n_values (const GtkCssValue *value) G_GNUC_PURE;
guint _gtk_css_array_value_get_n_values (const GtkCssValue *value);
G_END_DECLS

View File

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

View File

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

View File

@@ -18,8 +18,8 @@
#include "config.h"
#include "gtkcsscornervalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssdimensionvalueprivate.h"
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
@@ -184,12 +184,3 @@ _gtk_css_corner_value_get_y (const GtkCssValue *corner,
return _gtk_css_number_value_get (corner->y, one_hundred_percent);
}
gboolean
gtk_css_corner_value_is_zero (const GtkCssValue *corner)
{
if (corner->class != &GTK_CSS_VALUE_CORNER)
return gtk_css_dimension_value_is_zero (corner);
return gtk_css_dimension_value_is_zero (corner->x) &&
gtk_css_dimension_value_is_zero (corner->y);
}

View File

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

View File

@@ -497,14 +497,3 @@ gtk_css_dimension_value_parse (GtkCssParser *parser,
return result;
}
gboolean
gtk_css_dimension_value_is_zero (const GtkCssValue *value)
{
if (!value)
return TRUE;
if (value->class != &GTK_CSS_VALUE_DIMENSION.value_class)
return FALSE;
return value->value == 0;
}

View File

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

View File

@@ -340,17 +340,6 @@ _gtk_css_image_print (GtkCssImage *image,
klass->print (image, string);
}
char *
gtk_css_image_to_string (GtkCssImage *image)
{
GString *str = g_string_new ("");
_gtk_css_image_print (image, str);
return g_string_free (str, FALSE);
}
/* Applies the algorithm outlined in
* http://dev.w3.org/csswg/css3-images/#default-sizing
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -82,7 +82,7 @@ gtk_css_value_image_transition (GtkCssValue *start,
}
static gboolean
gtk_css_value_image_is_dynamic (const GtkCssValue *value)
gtk_css_value_image_is_dynamic (GtkCssValue *value)
{
GtkCssImage *image = _gtk_css_image_value_get_image (value);

View File

@@ -41,7 +41,7 @@ GtkCssKeyframes * _gtk_css_keyframes_compute (GtkCssKeyframes
GtkCssStyle *style,
GtkCssStyle *parent_style);
guint _gtk_css_keyframes_get_n_properties (GtkCssKeyframes *keyframes) G_GNUC_PURE;
guint _gtk_css_keyframes_get_n_properties (GtkCssKeyframes *keyframes);
guint _gtk_css_keyframes_get_property_id (GtkCssKeyframes *keyframes,
guint id);
GtkCssValue * _gtk_css_keyframes_get_value (GtkCssKeyframes *keyframes,

View File

@@ -28,14 +28,11 @@ void
_gtk_css_lookup_init (GtkCssLookup *lookup)
{
memset (lookup, 0, sizeof (*lookup));
lookup->set_values = _gtk_bitmask_new ();
}
void
_gtk_css_lookup_destroy (GtkCssLookup *lookup)
{
_gtk_bitmask_free (lookup->set_values);
}
gboolean
@@ -44,7 +41,13 @@ _gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
{
gtk_internal_return_val_if_fail (lookup != NULL, FALSE);
return !_gtk_bitmask_get (lookup->set_values, id);
return lookup->values[id].value == NULL;
}
gboolean
_gtk_css_lookup_all_set (const GtkCssLookup *lookup)
{
return lookup->n_set_values == GTK_CSS_PROPERTY_N_PROPERTIES;
}
/**
@@ -72,5 +75,41 @@ _gtk_css_lookup_set (GtkCssLookup *lookup,
lookup->values[id].value = value;
lookup->values[id].section = section;
lookup->set_values = _gtk_bitmask_set (lookup->set_values, id, TRUE);
lookup->n_set_values ++;
}
/**
* _gtk_css_lookup_resolve:
* @lookup: the lookup
* @context: the context the values are resolved for
* @values: a new #GtkCssStyle to be filled with the new properties
*
* Resolves the current lookup into a styleproperties object. This is done
* by converting from the “winning declaration” to the “computed value”.
*
* XXX: This bypasses the notion of “specified value”. If this ever becomes
* an issue, go fix it.
**/
void
_gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProvider *provider,
GtkCssStaticStyle *style,
GtkCssStyle *parent_style)
{
guint i;
gtk_internal_return_if_fail (lookup != NULL);
gtk_internal_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
gtk_internal_return_if_fail (GTK_IS_CSS_STATIC_STYLE (style));
gtk_internal_return_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style));
for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
{
gtk_css_static_style_compute_value (style,
provider,
parent_style,
i,
lookup->values[i].value,
lookup->values[i].section);
}
}

View File

@@ -36,7 +36,7 @@ typedef struct {
} GtkCssLookupValue;
struct _GtkCssLookup {
GtkBitmask *set_values;
guint n_set_values;
GtkCssLookupValue values[GTK_CSS_PROPERTY_N_PROPERTIES];
};
@@ -44,16 +44,15 @@ void _gtk_css_lookup_init (GtkCssLookup
void _gtk_css_lookup_destroy (GtkCssLookup *lookup);
gboolean _gtk_css_lookup_is_missing (const GtkCssLookup *lookup,
guint id);
gboolean _gtk_css_lookup_all_set (const GtkCssLookup *lookup);
void _gtk_css_lookup_set (GtkCssLookup *lookup,
guint id,
GtkCssSection *section,
GtkCssValue *value);
static inline const GtkBitmask *
_gtk_css_lookup_get_set_values (const GtkCssLookup *lookup)
{
return lookup->set_values;
}
void _gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProvider *provider,
GtkCssStaticStyle *style,
GtkCssStyle *parent_style);
G_END_DECLS

View File

@@ -72,6 +72,80 @@ gtk_css_matcher_widget_path_get_previous (GtkCssMatcher *matcher,
return TRUE;
}
static const char *
gtk_css_matcher_widget_path_get_name (const GtkCssMatcher *matcher)
{
const GtkWidgetPath *siblings;
siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
{
const char *path_name = gtk_widget_path_iter_get_object_name (siblings, matcher->path.sibling_index);
if (path_name == NULL)
path_name = g_type_name (gtk_widget_path_iter_get_object_type (siblings, matcher->path.sibling_index));
return path_name;
}
else
{
const char *path_name = gtk_widget_path_iter_get_object_name (matcher->path.path, matcher->path.index);
if (path_name == NULL)
path_name = g_type_name (gtk_widget_path_iter_get_object_type (matcher->path.path, matcher->path.index));
return path_name;
}
return NULL;
}
static GQuark *
gtk_css_matcher_widget_path_get_classes (const GtkCssMatcher *matcher,
guint *n_classes,
gboolean *allocated)
{
int num;
const GtkWidgetPath *siblings;
GSList *list, *l;
GQuark *classes;
const GQuark *decl_classes = NULL;
guint n_decl_classes = 0;
int i;
if (matcher->path.decl)
decl_classes = gtk_css_node_declaration_get_classes (matcher->path.decl, &n_decl_classes);
siblings = gtk_widget_path_iter_get_siblings (matcher->path.path, matcher->path.index);
if (siblings && matcher->path.sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path.path, matcher->path.index))
list = gtk_widget_path_iter_list_classes (siblings, matcher->path.sibling_index);
else
list = gtk_widget_path_iter_list_classes (matcher->path.path, matcher->path.index);
num = n_decl_classes + g_slist_length (list);
classes = g_new (GQuark, num);
i = 0;
if (matcher->path.decl)
{
for (; i < n_decl_classes; i++)
classes[i] = decl_classes[i];
}
for (l = list; l; l = l->next)
{
const char *name = l->data;
classes[i++] = g_quark_from_string (name);
}
*n_classes = num;
*allocated = TRUE;
return classes;
}
static gboolean
gtk_css_matcher_widget_path_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
@@ -193,6 +267,8 @@ static const GtkCssMatcherClass GTK_CSS_MATCHER_WIDGET_PATH = {
GTK_CSS_MATCHER_TYPE_WIDGET_PATH,
gtk_css_matcher_widget_path_get_parent,
gtk_css_matcher_widget_path_get_previous,
gtk_css_matcher_widget_path_get_name,
gtk_css_matcher_widget_path_get_classes,
gtk_css_matcher_widget_path_has_state,
gtk_css_matcher_widget_path_has_name,
gtk_css_matcher_widget_path_has_class,
@@ -266,6 +342,22 @@ gtk_css_matcher_node_get_previous (GtkCssMatcher *matcher,
return gtk_css_node_init_matcher (node, matcher);
}
static const char *
gtk_css_matcher_node_get_name (const GtkCssMatcher *matcher)
{
return matcher->node.node_name;
}
static GQuark *
gtk_css_matcher_node_get_classes (const GtkCssMatcher *matcher,
guint *n_classes,
gboolean *allocated)
{
*n_classes = matcher->node.n_classes;
*allocated = FALSE;
return (GQuark *)matcher->node.classes;
}
static gboolean
gtk_css_matcher_node_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)
@@ -378,6 +470,8 @@ static const GtkCssMatcherClass GTK_CSS_MATCHER_NODE = {
GTK_CSS_MATCHER_TYPE_NODE,
gtk_css_matcher_node_get_parent,
gtk_css_matcher_node_get_previous,
gtk_css_matcher_node_get_name,
gtk_css_matcher_node_get_classes,
gtk_css_matcher_node_has_state,
gtk_css_matcher_node_has_name,
gtk_css_matcher_node_has_class,

View File

@@ -41,6 +41,11 @@ struct _GtkCssMatcherClass {
gboolean (* get_previous) (GtkCssMatcher *matcher,
const GtkCssMatcher *next);
const char * (* get_name) (const GtkCssMatcher *matcher);
GQuark * (* get_classes) (const GtkCssMatcher *matcher,
guint *n_classes,
gboolean *allocated);
gboolean (* has_state) (const GtkCssMatcher *matcher,
GtkStateFlags state);
gboolean (* has_name) (const GtkCssMatcher *matcher,
@@ -106,6 +111,20 @@ _gtk_css_matcher_get_previous (GtkCssMatcher *matcher,
return next->klass->get_previous (matcher, next);
}
static inline const char *
_gtk_css_matcher_get_name (const GtkCssMatcher *matcher)
{
return matcher->klass->get_name (matcher);
}
static inline GQuark *
_gtk_css_matcher_get_classes (const GtkCssMatcher *matcher,
guint *n_classes,
gboolean *allocated)
{
return matcher->klass->get_classes (matcher, n_classes, allocated);
}
static inline gboolean
_gtk_css_matcher_has_state (const GtkCssMatcher *matcher,
GtkStateFlags state)

View File

@@ -27,7 +27,6 @@
#include "gtksettingsprivate.h"
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
#include "gdkprofilerprivate.h"
/*
* CSS nodes are the backbone of the GtkStyleContext implementation and
@@ -123,11 +122,6 @@ gtk_css_node_get_style_provider_or_null (GtkCssNode *cssnode)
return GTK_CSS_NODE_GET_CLASS (cssnode)->get_style_provider (cssnode);
}
static int invalidated_nodes;
static int created_styles;
static guint invalidated_nodes_counter;
static guint created_styles_counter;
static void
gtk_css_node_set_invalid (GtkCssNode *node,
gboolean invalid)
@@ -137,9 +131,6 @@ gtk_css_node_set_invalid (GtkCssNode *node,
node->invalid = invalid;
if (invalid)
invalidated_nodes++;
if (node->visible)
{
if (node->parent)
@@ -378,8 +369,6 @@ gtk_css_node_create_style (GtkCssNode *cssnode,
if (style)
return g_object_ref (style);
created_styles++;
parent = cssnode->parent ? cssnode->parent->style : NULL;
if (change & GTK_CSS_CHANGE_NEEDS_RECOMPUTE)
@@ -506,6 +495,18 @@ gtk_css_node_real_init_matcher (GtkCssNode *cssnode,
return TRUE;
}
static GtkWidgetPath *
gtk_css_node_real_create_widget_path (GtkCssNode *cssnode)
{
return gtk_widget_path_new ();
}
static const GtkWidgetPath *
gtk_css_node_real_get_widget_path (GtkCssNode *cssnode)
{
return NULL;
}
static GtkStyleProvider *
gtk_css_node_real_get_style_provider (GtkCssNode *cssnode)
{
@@ -586,6 +587,8 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
klass->queue_validate = gtk_css_node_real_queue_validate;
klass->dequeue_validate = gtk_css_node_real_dequeue_validate;
klass->init_matcher = gtk_css_node_real_init_matcher;
klass->create_widget_path = gtk_css_node_real_create_widget_path;
klass->get_widget_path = gtk_css_node_real_get_widget_path;
klass->get_style_provider = gtk_css_node_real_get_style_provider;
klass->get_frame_clock = gtk_css_node_real_get_frame_clock;
@@ -662,12 +665,6 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
| G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, NUM_PROPERTIES, cssnode_properties);
if (invalidated_nodes_counter == 0)
{
invalidated_nodes_counter = gdk_profiler_define_int_counter ("invalidated-nodes", "CSS Node Invalidations");
created_styles_counter = gdk_profiler_define_int_counter ("created-styles", "CSS Style Creations");
}
}
static void
@@ -1382,24 +1379,10 @@ void
gtk_css_node_validate (GtkCssNode *cssnode)
{
gint64 timestamp;
gint64 before = g_get_monotonic_time ();
timestamp = gtk_css_node_get_timestamp (cssnode);
gtk_css_node_validate_internal (cssnode, timestamp);
if (cssnode->parent == NULL)
{
if (gdk_profiler_is_running ())
{
gint64 after = g_get_monotonic_time ();
gdk_profiler_add_mark (before * 1000, (after - before) * 1000, "css validation", "");
gdk_profiler_set_int_counter (invalidated_nodes_counter, after * 1000, invalidated_nodes);
gdk_profiler_set_int_counter (created_styles_counter, after * 1000, created_styles);
invalidated_nodes = 0;
created_styles = 0;
}
}
}
gboolean
@@ -1409,6 +1392,18 @@ gtk_css_node_init_matcher (GtkCssNode *cssnode,
return GTK_CSS_NODE_GET_CLASS (cssnode)->init_matcher (cssnode, matcher);
}
GtkWidgetPath *
gtk_css_node_create_widget_path (GtkCssNode *cssnode)
{
return GTK_CSS_NODE_GET_CLASS (cssnode)->create_widget_path (cssnode);
}
const GtkWidgetPath *
gtk_css_node_get_widget_path (GtkCssNode *cssnode)
{
return GTK_CSS_NODE_GET_CLASS (cssnode)->get_widget_path (cssnode);
}
GtkStyleProvider *
gtk_css_node_get_style_provider (GtkCssNode *cssnode)
{

View File

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

View File

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

View File

@@ -42,7 +42,6 @@
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "gdk/gdkprofilerprivate.h"
#include <cairo-gobject.h>
/**
@@ -74,8 +73,6 @@
* way back to 4.0.
*/
#define MAX_SELECTOR_LIST_LENGTH 64
struct _GtkCssProviderClass
{
GObjectClass parent_class;
@@ -121,7 +118,7 @@ struct _GtkCssProviderPrivate
GHashTable *keyframes;
GArray *rulesets;
GtkCssSelectorTree *tree;
GtkCssSelectorTrees *tree;
GResource *resource;
gchar *path;
};
@@ -489,6 +486,9 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
ruleset->styles[j].section,
ruleset->styles[j].value);
}
if (_gtk_css_lookup_all_set (lookup))
break;
}
g_ptr_array_free (tree_rules, TRUE);
@@ -549,28 +549,29 @@ gtk_css_provider_new (void)
}
static void
css_provider_commit (GtkCssProvider *css_provider,
GtkCssSelector **selectors,
guint n_selectors,
GtkCssRuleset *ruleset)
css_provider_commit (GtkCssProvider *css_provider,
GSList *selectors,
GtkCssRuleset *ruleset)
{
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (css_provider);
guint i;
GSList *l;
if (ruleset->styles == NULL)
{
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
return;
}
for (i = 0; i < n_selectors; i ++)
for (l = selectors; l; l = l->next)
{
GtkCssRuleset *new;
GtkCssRuleset new;
g_array_set_size (priv->rulesets, priv->rulesets->len + 1);
gtk_css_ruleset_init_copy (&new, ruleset, l->data);
new = &g_array_index (priv->rulesets, GtkCssRuleset, priv->rulesets->len - 1);
gtk_css_ruleset_init_copy (new, ruleset, selectors[i]);
g_array_append_val (priv->rulesets, new);
}
g_slist_free (selectors);
}
static void
@@ -755,32 +756,22 @@ parse_at_keyword (GtkCssScanner *scanner)
gtk_css_parser_end_block (scanner->parser);
}
static guint
parse_selector_list (GtkCssScanner *scanner,
GtkCssSelector *out_selectors[MAX_SELECTOR_LIST_LENGTH])
static GSList *
parse_selector_list (GtkCssScanner *scanner)
{
guint n_selectors = 0;
GSList *selectors = NULL;
do {
GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
if (select == NULL)
return 0;
return NULL;
out_selectors[n_selectors] = select;
n_selectors++;
if (G_UNLIKELY (n_selectors > MAX_SELECTOR_LIST_LENGTH))
{
gtk_css_parser_error_syntax (scanner->parser,
"Only %u selectors per ruleset allowed",
MAX_SELECTOR_LIST_LENGTH);
return 0;
}
selectors = g_slist_prepend (selectors, select);
}
while (gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COMMA));
return n_selectors;
return selectors;
}
static void
@@ -899,12 +890,11 @@ parse_declarations (GtkCssScanner *scanner,
static void
parse_ruleset (GtkCssScanner *scanner)
{
GtkCssSelector *selectors[MAX_SELECTOR_LIST_LENGTH];
guint n_selectors;
GSList *selectors;
GtkCssRuleset ruleset = { 0, };
n_selectors = parse_selector_list (scanner, selectors);
if (n_selectors == 0)
selectors = parse_selector_list (scanner);
if (selectors == NULL)
{
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
@@ -913,10 +903,8 @@ parse_ruleset (GtkCssScanner *scanner)
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY))
{
guint i;
gtk_css_parser_error_syntax (scanner->parser, "Expected '{' after selectors");
for (i = 0; i < n_selectors; i ++)
_gtk_css_selector_free (selectors[i]);
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
return;
@@ -928,7 +916,7 @@ parse_ruleset (GtkCssScanner *scanner)
gtk_css_parser_end_block (scanner->parser);
css_provider_commit (scanner->provider, selectors, n_selectors, &ruleset);
css_provider_commit (scanner->provider, selectors, &ruleset);
gtk_css_ruleset_clear (&ruleset);
}
@@ -978,7 +966,6 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (css_provider);
GtkCssSelectorTreeBuilder *builder;
guint i;
gint64 before = g_get_monotonic_time ();
g_array_sort (priv->rulesets, gtk_css_provider_compare_rule);
@@ -1009,9 +996,6 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
ruleset->selector = NULL;
}
#endif
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "create selector tree", NULL);
}
static void
@@ -1020,8 +1004,6 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
GFile *file,
GBytes *bytes)
{
gint64 before = g_get_monotonic_time ();
if (bytes == NULL)
{
GError *load_error = NULL;
@@ -1068,13 +1050,6 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
g_bytes_unref (bytes);
}
if (gdk_profiler_is_running ())
{
char *uri = g_file_get_uri (file);
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "theme load", uri);
g_free (uri);
}
}
/**

View File

@@ -30,23 +30,6 @@
# include <intrin.h>
#endif
/*
* @GTK_CSS_SELECTOR_CATEGORY_SIMPLE: A simple selector
* @GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL: A simple selector that matches
* what change tracking considers a "radical change"
* @GTK_CSS_SELECTOR_SIBLING: A selector matching siblings
* @GTK_CSS_SELECTOR_CATEGORY_PARENT: A selector matching a parent or other
* ancestor
*
* Categorize the selectors. This helps in various loops when matching.
*/
typedef enum {
GTK_CSS_SELECTOR_CATEGORY_SIMPLE,
GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL,
GTK_CSS_SELECTOR_CATEGORY_PARENT,
GTK_CSS_SELECTOR_CATEGORY_SIBLING,
} GtkCssSelectorCategory;
typedef struct _GtkCssSelectorClass GtkCssSelectorClass;
typedef gboolean (* GtkCssSelectorForeachFunc) (const GtkCssSelector *selector,
const GtkCssMatcher *matcher,
@@ -54,7 +37,6 @@ typedef gboolean (* GtkCssSelectorForeachFunc) (const GtkCssSelector *selector,
struct _GtkCssSelectorClass {
const char *name;
GtkCssSelectorCategory category;
void (* print) (const GtkCssSelector *selector,
GString *string);
@@ -79,6 +61,9 @@ struct _GtkCssSelectorClass {
guint (* hash_one) (const GtkCssSelector *selector);
int (* compare_one) (const GtkCssSelector *a,
const GtkCssSelector *b);
guint is_simple : 1;
guint ignore_for_change : 1;
};
typedef enum {
@@ -126,6 +111,12 @@ struct _GtkCssSelectorTree
gint32 matches_offset; /* pointers that we return as matches if selector matches */
};
struct _GtkCssSelectorTrees {
GHashTable *by_name;
GHashTable *by_class;
GtkCssSelectorTree *remaining;
};
static gboolean
gtk_css_selector_equal (const GtkCssSelector *a,
const GtkCssSelector *b)
@@ -323,7 +314,6 @@ gtk_css_selector_descendant_get_change (const GtkCssSelector *selector, GtkCssCh
static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
"descendant",
GTK_CSS_SELECTOR_CATEGORY_PARENT,
gtk_css_selector_descendant_print,
gtk_css_selector_descendant_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -331,6 +321,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
TRUE
};
/* CHILD */
@@ -364,7 +356,6 @@ gtk_css_selector_child_get_change (const GtkCssSelector *selector, GtkCssChange
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
"child",
GTK_CSS_SELECTOR_CATEGORY_PARENT,
gtk_css_selector_child_print,
gtk_css_selector_child_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -372,6 +363,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
TRUE
};
/* SIBLING */
@@ -410,7 +403,6 @@ gtk_css_selector_sibling_get_change (const GtkCssSelector *selector, GtkCssChang
static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
"sibling",
GTK_CSS_SELECTOR_CATEGORY_SIBLING,
gtk_css_selector_sibling_print,
gtk_css_selector_sibling_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -418,6 +410,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
TRUE
};
/* ADJACENT */
@@ -451,7 +445,6 @@ gtk_css_selector_adjacent_get_change (const GtkCssSelector *selector, GtkCssChan
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
"adjacent",
GTK_CSS_SELECTOR_CATEGORY_SIBLING,
gtk_css_selector_adjacent_print,
gtk_css_selector_adjacent_foreach_matcher,
gtk_css_selector_default_match_one,
@@ -459,6 +452,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
gtk_css_selector_default_add_specificity,
gtk_css_selector_default_hash_one,
gtk_css_selector_default_compare_one,
FALSE,
TRUE
};
/* SIMPLE SELECTOR DEFINE */
@@ -524,7 +519,6 @@ gtk_css_selector_ ## n ## _add_specificity (const GtkCssSelector *selector, \
\
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
G_STRINGIFY(n), \
ignore_for_change ? GTK_CSS_SELECTOR_CATEGORY_SIMPLE : GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL, \
gtk_css_selector_ ## n ## _print, \
gtk_css_selector_default_foreach_matcher, \
match_func, \
@@ -532,11 +526,12 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
TRUE, \
ignore_for_change \
};\
\
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
"not_" G_STRINGIFY(n), \
ignore_for_change ? GTK_CSS_SELECTOR_CATEGORY_SIMPLE : GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL, \
gtk_css_selector_not_ ## n ## _print, \
gtk_css_selector_default_foreach_matcher, \
gtk_css_selector_not_ ## n ## _match_one, \
@@ -544,6 +539,8 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
TRUE, \
ignore_for_change \
};
/* ANY */
@@ -1764,23 +1761,6 @@ _gtk_css_selector_get_change (const GtkCssSelector *selector)
/******************** SelectorTree handling *****************/
static gboolean
gtk_css_selector_is_simple (const GtkCssSelector *selector)
{
switch (selector->class->category)
{
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE:
case GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL:
return TRUE;
case GTK_CSS_SELECTOR_CATEGORY_PARENT:
case GTK_CSS_SELECTOR_CATEGORY_SIBLING:
return FALSE;
default:
g_assert_not_reached ();
return FALSE;
}
}
static GHashTable *
gtk_css_selectors_count_initial_init (void)
{
@@ -1790,7 +1770,7 @@ gtk_css_selectors_count_initial_init (void)
static void
gtk_css_selectors_count_initial (const GtkCssSelector *selector, GHashTable *hash_one)
{
if (!gtk_css_selector_is_simple (selector))
if (!selector->class->is_simple)
{
guint count = GPOINTER_TO_INT (g_hash_table_lookup (hash_one, selector));
g_hash_table_replace (hash_one, (gpointer)selector, GUINT_TO_POINTER (count + 1));
@@ -1798,7 +1778,7 @@ gtk_css_selectors_count_initial (const GtkCssSelector *selector, GHashTable *has
}
for (;
selector && gtk_css_selector_is_simple (selector);
selector && selector->class->is_simple;
selector = gtk_css_selector_previous (selector))
{
guint count = GPOINTER_TO_INT (g_hash_table_lookup (hash_one, selector));
@@ -1809,11 +1789,11 @@ gtk_css_selectors_count_initial (const GtkCssSelector *selector, GHashTable *has
static gboolean
gtk_css_selectors_has_initial_selector (const GtkCssSelector *selector, const GtkCssSelector *initial)
{
if (!gtk_css_selector_is_simple (selector))
if (!selector->class->is_simple)
return gtk_css_selector_equal (selector, initial);
for (;
selector && gtk_css_selector_is_simple (selector);
selector && selector->class->is_simple;
selector = gtk_css_selector_previous (selector))
{
if (gtk_css_selector_equal (selector, initial))
@@ -1833,13 +1813,13 @@ gtk_css_selectors_skip_initial_selector (GtkCssSelector *selector, const GtkCssS
without losing any other selectors */
if (!gtk_css_selector_equal (selector, initial))
{
for (found = selector; found && gtk_css_selector_is_simple (found); found = (GtkCssSelector *)gtk_css_selector_previous (found))
for (found = selector; found && found->class->is_simple; found = (GtkCssSelector *)gtk_css_selector_previous (found))
{
if (gtk_css_selector_equal (found, initial))
break;
}
g_assert (found != NULL && gtk_css_selector_is_simple (found));
g_assert (found != NULL && found->class->is_simple);
tmp = *found;
*found = *selector;
@@ -1870,15 +1850,43 @@ gtk_css_selector_tree_match_foreach (const GtkCssSelector *selector,
return FALSE;
}
static void
gtk_css_selector_tree_match_one (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher,
gpointer res)
{
for (; tree != NULL;
tree = gtk_css_selector_tree_get_sibling (tree))
gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_match_foreach, res);
}
GPtrArray *
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
_gtk_css_selector_tree_match_all (const GtkCssSelectorTrees *trees,
const GtkCssMatcher *matcher)
{
GPtrArray *array = NULL;
const char *name;
GQuark *classes;
guint n_classes;
gboolean allocated;
const GtkCssSelectorTree *tree;
int i;
for (; tree != NULL;
tree = gtk_css_selector_tree_get_sibling (tree))
gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_match_foreach, &array);
name = _gtk_css_matcher_get_name (matcher);
tree = (const GtkCssSelectorTree *)g_hash_table_lookup (trees->by_name, (gpointer)name);
gtk_css_selector_tree_match_one (tree, matcher, &array);
classes = _gtk_css_matcher_get_classes (matcher, &n_classes, &allocated);
for (i = 0; i < n_classes; i++)
{
tree = (const GtkCssSelectorTree *)g_hash_table_lookup (trees->by_class, GUINT_TO_POINTER (classes[i]));
gtk_css_selector_tree_match_one (tree, matcher, &array);
}
if (allocated)
g_free (classes);
gtk_css_selector_tree_match_one (trees->remaining, matcher, &array);
return array;
}
@@ -1892,7 +1900,7 @@ static gboolean
gtk_css_selector_match_for_change (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
if (selector->class->category != GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL)
if (selector->class->ignore_for_change)
return TRUE;
return selector->class->match_one (selector, matcher);
@@ -1935,7 +1943,7 @@ gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
if (!gtk_css_selector_match_for_change (&tree->selector, matcher))
return 0;
if (!gtk_css_selector_is_simple (&tree->selector))
if (!tree->selector.class->is_simple)
return gtk_css_selector_tree_collect_change (tree) | GTK_CSS_CHANGE_GOT_MATCH;
for (prev = gtk_css_selector_tree_get_previous (tree);
@@ -1950,14 +1958,19 @@ gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
}
gboolean
_gtk_css_selector_tree_is_empty (const GtkCssSelectorTree *tree)
_gtk_css_selector_tree_is_empty (const GtkCssSelectorTrees *tree)
{
return tree == NULL;
if (!tree)
return TRUE;
return g_hash_table_size (tree->by_name) == 0 &&
g_hash_table_size (tree->by_class) == 0 &&
tree->remaining == NULL;
}
GtkCssChange
_gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
static GtkCssChange
gtk_css_selector_tree_get_change_for_one (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GtkCssChange change;
@@ -1972,6 +1985,37 @@ _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
return change & ~GTK_CSS_CHANGE_RESERVED_BIT;
}
GtkCssChange
_gtk_css_selector_tree_get_change_all (const GtkCssSelectorTrees *trees,
const GtkCssMatcher *matcher)
{
GtkCssChange change = 0;
const char *name;
GQuark *classes;
guint n_classes;
gboolean allocated;
const GtkCssSelectorTree *tree;
int i;
name = _gtk_css_matcher_get_name (matcher);
tree = (const GtkCssSelectorTree *)g_hash_table_lookup (trees->by_name, (gpointer)name);
change |= gtk_css_selector_tree_get_change_for_one (tree, matcher);
classes = _gtk_css_matcher_get_classes (matcher, &n_classes, &allocated);
for (i = 0; i < n_classes; i++)
{
tree = (const GtkCssSelectorTree *)g_hash_table_lookup (trees->by_class, GUINT_TO_POINTER (classes[i]));
change |= gtk_css_selector_tree_get_change_for_one (tree, matcher);
}
if (allocated)
g_free (classes);
change |= gtk_css_selector_tree_get_change_for_one (trees->remaining, matcher);
return change;
}
#ifdef PRINT_TREE
static void
_gtk_css_selector_tree_print (const GtkCssSelectorTree *tree, GString *str, char *prefix)
@@ -2044,7 +2088,7 @@ _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
/* print name and * selector before others */
for (iter = tree;
iter && gtk_css_selector_is_simple (&iter->selector);
iter && iter->selector.class->is_simple;
iter = gtk_css_selector_tree_get_parent (iter))
{
if (iter->selector.class == &GTK_CSS_SELECTOR_NAME ||
@@ -2055,7 +2099,7 @@ _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
}
/* now print other simple selectors */
for (iter = tree;
iter && gtk_css_selector_is_simple (&iter->selector);
iter && iter->selector.class->is_simple;
iter = gtk_css_selector_tree_get_parent (iter))
{
if (iter->selector.class != &GTK_CSS_SELECTOR_NAME &&
@@ -2076,12 +2120,24 @@ _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
}
void
_gtk_css_selector_tree_free (GtkCssSelectorTree *tree)
_gtk_css_selector_tree_free (GtkCssSelectorTrees *trees)
{
if (tree == NULL)
GHashTableIter iter;
gpointer key;
gpointer tree;
if (trees == NULL)
return;
g_free (tree);
g_hash_table_iter_init (&iter, trees->by_name);
while (g_hash_table_iter_next (&iter, &key, (gpointer *)&tree))
g_free (tree);
g_hash_table_unref (trees->by_name);
g_free (trees->remaining);
g_free (trees);
}
@@ -2089,6 +2145,8 @@ typedef struct {
gpointer match;
GtkCssSelector *current_selector;
GtkCssSelectorTree **selector_match;
const char *name;
GQuark class;
} GtkCssSelectorRuleSetInfo;
static GtkCssSelectorTree *
@@ -2212,22 +2270,73 @@ subdivide_infos (GByteArray *array, GList *infos, gint32 parent_offset)
}
struct _GtkCssSelectorTreeBuilder {
GList *infos;
GHashTable *by_name;
GHashTable *by_class;
GList *remaining;
};
GtkCssSelectorTreeBuilder *
_gtk_css_selector_tree_builder_new (void)
{
return g_new0 (GtkCssSelectorTreeBuilder, 1);
GtkCssSelectorTreeBuilder *builder;
builder = g_new0 (GtkCssSelectorTreeBuilder, 1);
builder->by_name = g_hash_table_new (NULL, NULL);
builder->by_class = g_hash_table_new (NULL, NULL);
return builder;
}
void
_gtk_css_selector_tree_builder_free (GtkCssSelectorTreeBuilder *builder)
_gtk_css_selector_tree_builder_free (GtkCssSelectorTreeBuilder *builder)
{
g_list_free_full (builder->infos, g_free);
GHashTableIter iter;
gpointer key;
GList *infos;
g_hash_table_iter_init (&iter, builder->by_name);
while (g_hash_table_iter_next (&iter, &key, (gpointer *)&infos))
g_list_free_full (infos, g_free);
g_hash_table_unref (builder->by_name);
g_hash_table_iter_init (&iter, builder->by_class);
while (g_hash_table_iter_next (&iter, &key, (gpointer *)&infos))
g_list_free_full (infos, g_free);
g_hash_table_unref (builder->by_class);
g_list_free_full (builder->remaining, g_free);
g_free (builder);
}
static const char *
find_name (const GtkCssSelector *selector)
{
for (;
selector && selector->class->is_simple;
selector = gtk_css_selector_previous (selector))
{
if (selector->class == &GTK_CSS_SELECTOR_NAME)
return selector->name.name;
}
return NULL;
}
static GQuark
find_class (const GtkCssSelector *selector)
{
for (;
selector && selector->class->is_simple;
selector = gtk_css_selector_previous (selector))
{
if (selector->class == &GTK_CSS_SELECTOR_CLASS)
return selector->style_class.style_class;
}
return 0;
}
void
_gtk_css_selector_tree_builder_add (GtkCssSelectorTreeBuilder *builder,
GtkCssSelector *selectors,
@@ -2239,7 +2348,27 @@ _gtk_css_selector_tree_builder_add (GtkCssSelectorTreeBuilder *builder,
info->match = match;
info->current_selector = selectors;
info->selector_match = selector_match;
builder->infos = g_list_prepend (builder->infos, info);
info->name = find_name (selectors);
if (info->name)
{
GList *infos = g_hash_table_lookup (builder->by_name, (gpointer)info->name);
infos = g_list_prepend (infos, info);
g_hash_table_replace (builder->by_name, (gpointer)info->name, infos);
return;
}
info->class = find_class (selectors);
if (info->class)
{
GList *infos = g_hash_table_lookup (builder->by_class, GUINT_TO_POINTER (info->class));
infos = g_list_prepend (infos, info);
g_hash_table_replace (builder->by_class, GUINT_TO_POINTER (info->class), infos);
return;
}
builder->remaining = g_list_prepend (builder->remaining, info);
}
/* Convert all offsets to node-relative */
@@ -2266,8 +2395,8 @@ fixup_offsets (GtkCssSelectorTree *tree, guint8 *data)
}
}
GtkCssSelectorTree *
_gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
static GtkCssSelectorTree *
_gtk_css_selector_tree_builder_build_one (GList *infos)
{
GtkCssSelectorTree *tree;
GByteArray *array;
@@ -2277,7 +2406,7 @@ _gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
GtkCssSelectorRuleSetInfo *info;
array = g_byte_array_new ();
subdivide_infos (array, builder->infos, GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET);
subdivide_infos (array, infos, GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET);
len = array->len;
data = g_byte_array_free (array, FALSE);
@@ -2290,7 +2419,7 @@ _gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
fixup_offsets (tree, data);
/* Convert offsets to final pointers */
for (l = builder->infos; l != NULL; l = l->next)
for (l = infos; l != NULL; l = l->next)
{
info = l->data;
if (info->selector_match)
@@ -2308,3 +2437,36 @@ _gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
return tree;
}
GtkCssSelectorTrees *
_gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder)
{
GtkCssSelectorTrees *trees;
GHashTableIter iter;
const char *name;
GList *infos;
gpointer key;
trees = g_new0 (GtkCssSelectorTrees, 1);
trees->by_name = g_hash_table_new (NULL, NULL);
trees->by_class = g_hash_table_new (NULL, NULL);
g_hash_table_iter_init (&iter, builder->by_name);
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&infos))
{
GtkCssSelectorTree *tree = _gtk_css_selector_tree_builder_build_one (infos);
g_hash_table_insert (trees->by_name, (gpointer)name, tree);
}
g_hash_table_iter_init (&iter, builder->by_class);
while (g_hash_table_iter_next (&iter, &key, (gpointer *)&infos))
{
GtkCssSelectorTree *tree = _gtk_css_selector_tree_builder_build_one (infos);
g_hash_table_insert (trees->by_class, key, tree);
}
if (builder->remaining)
trees->remaining = _gtk_css_selector_tree_builder_build_one (builder->remaining);
return trees;
}

View File

@@ -25,6 +25,7 @@ G_BEGIN_DECLS
typedef union _GtkCssSelector GtkCssSelector;
typedef struct _GtkCssSelectorTree GtkCssSelectorTree;
typedef struct _GtkCssSelectorTrees GtkCssSelectorTrees;
typedef struct _GtkCssSelectorTreeBuilder GtkCssSelectorTreeBuilder;
GtkCssSelector * _gtk_css_selector_parse (GtkCssParser *parser);
@@ -40,14 +41,14 @@ GtkCssChange _gtk_css_selector_get_change (const GtkCssSelector *sel
int _gtk_css_selector_compare (const GtkCssSelector *a,
const GtkCssSelector *b);
void _gtk_css_selector_tree_free (GtkCssSelectorTree *tree);
GPtrArray * _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
void _gtk_css_selector_tree_free (GtkCssSelectorTrees *tree);
GPtrArray * _gtk_css_selector_tree_match_all (const GtkCssSelectorTrees *tree,
const GtkCssMatcher *matcher);
GtkCssChange _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
GtkCssChange _gtk_css_selector_tree_get_change_all (const GtkCssSelectorTrees *tree,
const GtkCssMatcher *matcher);
void _gtk_css_selector_tree_match_print (const GtkCssSelectorTree *tree,
GString *str);
gboolean _gtk_css_selector_tree_is_empty (const GtkCssSelectorTree *tree) G_GNUC_CONST;
gboolean _gtk_css_selector_tree_is_empty (const GtkCssSelectorTrees *tree) G_GNUC_CONST;
@@ -56,7 +57,7 @@ void _gtk_css_selector_tree_builder_add (GtkCssSelectorT
GtkCssSelector *selectors,
GtkCssSelectorTree **selector_match,
gpointer match);
GtkCssSelectorTree * _gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder);
GtkCssSelectorTrees * _gtk_css_selector_tree_builder_build (GtkCssSelectorTreeBuilder *builder);
void _gtk_css_selector_tree_builder_free (GtkCssSelectorTreeBuilder *builder);
const char *gtk_css_pseudoclass_name (GtkStateFlags flags);

View File

@@ -131,7 +131,6 @@ gtk_css_value_shadow_compute (GtkCssValue *value,
shadows[i].radius = _gtk_css_value_compute (shadow->radius, property_id, provider, style, parent_style);
shadows[i].spread = _gtk_css_value_compute (shadow->spread, property_id, provider, style, parent_style),
shadows[i].color = _gtk_css_value_compute (shadow->color, property_id, provider, style, parent_style);
shadows[i].inset = shadow->inset;
}
return gtk_css_shadow_value_new (shadows, value->n_shadows);

View File

@@ -46,8 +46,8 @@ void gtk_css_shadow_value_snapshot_inset (const GtkCssValue
GtkSnapshot *snapshot,
const GskRoundedRect *padding_box);
gboolean gtk_css_shadow_value_is_clear (const GtkCssValue *shadow) G_GNUC_PURE;
gboolean gtk_css_shadow_value_is_none (const GtkCssValue *shadow) G_GNUC_PURE;
gboolean gtk_css_shadow_value_is_clear (const GtkCssValue *shadow);
gboolean gtk_css_shadow_value_is_none (const GtkCssValue *shadow);
gboolean gtk_css_shadow_value_push_snapshot (const GtkCssValue *value,
GtkSnapshot *snapshot);

View File

@@ -67,7 +67,7 @@ GType _gtk_css_shorthand_property_get_type (void) G
GtkCssStyleProperty * _gtk_css_shorthand_property_get_subproperty (GtkCssShorthandProperty *shorthand,
guint property);
guint _gtk_css_shorthand_property_get_n_subproperties (GtkCssShorthandProperty *shorthand) G_GNUC_CONST;
guint _gtk_css_shorthand_property_get_n_subproperties (GtkCssShorthandProperty *shorthand);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@@ -34,164 +34,11 @@ G_BEGIN_DECLS
typedef struct _GtkCssStaticStyleClass GtkCssStaticStyleClass;
/* inherited */
typedef struct {
int ref_count;
GtkCssValue *color;
GtkCssValue *dpi;
GtkCssValue *font_size;
GtkCssValue *icon_theme;
GtkCssValue *icon_palette;
} GtkCssCoreValues;
typedef struct {
int ref_count;
GtkCssValue *background_color;
GtkCssValue *box_shadow;
GtkCssValue *background_clip;
GtkCssValue *background_origin;
GtkCssValue *background_size;
GtkCssValue *background_position;
GtkCssValue *background_repeat;
GtkCssValue *background_image;
GtkCssValue *background_blend_mode;
} GtkCssBackgroundValues;
typedef struct {
int ref_count;
GtkCssValue *border_top_style;
GtkCssValue *border_top_width;
GtkCssValue *border_left_style;
GtkCssValue *border_left_width;
GtkCssValue *border_bottom_style;
GtkCssValue *border_bottom_width;
GtkCssValue *border_right_style;
GtkCssValue *border_right_width;
GtkCssValue *border_top_left_radius;
GtkCssValue *border_top_right_radius;
GtkCssValue *border_bottom_right_radius;
GtkCssValue *border_bottom_left_radius;
GtkCssValue *border_top_color;
GtkCssValue *border_right_color;
GtkCssValue *border_bottom_color;
GtkCssValue *border_left_color;
GtkCssValue *border_image_source;
GtkCssValue *border_image_repeat;
GtkCssValue *border_image_slice;
GtkCssValue *border_image_width;
} GtkCssBorderValues;
/* inherited */
typedef struct {
int ref_count;
GtkCssValue *icon_size;
GtkCssValue *icon_shadow;
GtkCssValue *icon_style;
} GtkCssIconValues;
typedef struct {
int ref_count;
GtkCssValue *outline_style;
GtkCssValue *outline_width;
GtkCssValue *outline_offset;
GtkCssValue *outline_top_left_radius;
GtkCssValue *outline_top_right_radius;
GtkCssValue *outline_bottom_right_radius;
GtkCssValue *outline_bottom_left_radius;
GtkCssValue *outline_color;
} GtkCssOutlineValues;
/* inherited */
typedef struct {
int ref_count;
GtkCssValue *font_family;
GtkCssValue *font_style;
GtkCssValue *font_weight;
GtkCssValue *font_stretch;
GtkCssValue *letter_spacing;
GtkCssValue *text_shadow;
GtkCssValue *caret_color;
GtkCssValue *secondary_caret_color;
GtkCssValue *font_feature_settings;
GtkCssValue *font_variation_settings;
} GtkCssFontValues;
typedef struct {
int ref_count;
GtkCssValue *text_decoration_line;
GtkCssValue *text_decoration_color;
GtkCssValue *text_decoration_style;
GtkCssValue *font_kerning;
GtkCssValue *font_variant_ligatures;
GtkCssValue *font_variant_position;
GtkCssValue *font_variant_caps;
GtkCssValue *font_variant_numeric;
GtkCssValue *font_variant_alternates;
GtkCssValue *font_variant_east_asian;
} GtkCssFontVariantValues;
typedef struct {
int ref_count;
GtkCssValue *animation_name;
GtkCssValue *animation_duration;
GtkCssValue *animation_timing_function;
GtkCssValue *animation_iteration_count;
GtkCssValue *animation_direction;
GtkCssValue *animation_play_state;
GtkCssValue *animation_delay;
GtkCssValue *animation_fill_mode;
} GtkCssAnimationValues;
typedef struct {
int ref_count;
GtkCssValue *transition_property;
GtkCssValue *transition_duration;
GtkCssValue *transition_timing_function;
GtkCssValue *transition_delay;
} GtkCssTransitionValues;
typedef struct {
int ref_count;
GtkCssValue *margin_top;
GtkCssValue *margin_left;
GtkCssValue *margin_bottom;
GtkCssValue *margin_right;
GtkCssValue *padding_top;
GtkCssValue *padding_left;
GtkCssValue *padding_bottom;
GtkCssValue *padding_right;
GtkCssValue *border_spacing;
GtkCssValue *min_width;
GtkCssValue *min_height;
} GtkCssSizeValues;
typedef struct {
int ref_count;
GtkCssValue *icon_source;
GtkCssValue *icon_transform;
GtkCssValue *icon_filter;
GtkCssValue *transform;
GtkCssValue *opacity;
GtkCssValue *filter;
} GtkCssOtherValues;
struct _GtkCssStaticStyle
{
GtkCssStyle parent;
GtkCssCoreValues *core;
GtkCssBackgroundValues *background;
GtkCssBorderValues *border;
GtkCssIconValues *icon;
GtkCssOutlineValues *outline;
GtkCssFontValues *font;
GtkCssFontVariantValues *font_variant;
GtkCssAnimationValues *animation;
GtkCssTransitionValues *transition;
GtkCssSizeValues *size;
GtkCssOtherValues *other;
GtkCssValue *values[GTK_CSS_PROPERTY_N_PROPERTIES]; /* the values */
GPtrArray *sections; /* sections the values are defined in */
GtkCssChange change; /* change as returned by value lookup */
@@ -210,6 +57,13 @@ GtkCssStyle * gtk_css_static_style_new_compute (GtkStyleProvide
GtkCssStyle *parent,
GtkCssChange change);
void gtk_css_static_style_compute_value (GtkCssStaticStyle *style,
GtkStyleProvider *provider,
GtkCssStyle *parent_style,
guint id,
GtkCssValue *specified,
GtkCssSection *section);
GtkCssChange gtk_css_static_style_get_change (GtkCssStaticStyle *style);
G_END_DECLS

View File

@@ -921,9 +921,6 @@ icon_theme_value_parse (GtkCssStyleProperty *property,
/*** REGISTRATION ***/
G_STATIC_ASSERT (GTK_CSS_PROPERTY_COLOR == 0);
G_STATIC_ASSERT (GTK_CSS_PROPERTY_DPI < GTK_CSS_PROPERTY_FONT_SIZE);
void
_gtk_css_style_property_init_properties (void)
{
@@ -935,7 +932,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_COLOR,
GDK_TYPE_RGBA,
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_CONTENT | GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC,
GTK_CSS_AFFECTS_CONTENT | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
color_parse,
color_query,
gtk_css_color_value_new_white ());
@@ -959,7 +956,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_THEME,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT,
GTK_CSS_AFFECTS_ICON_TEXTURE,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | GTK_CSS_AFFECTS_ICON_SIZE,
icon_theme_value_parse,
NULL,
gtk_css_icon_theme_value_new (NULL));
@@ -967,7 +964,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_PALETTE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED | GTK_STYLE_PROPERTY_INHERIT,
GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC,
GTK_CSS_AFFECTS_SYMBOLIC_ICON,
icon_palette_parse,
NULL,
gtk_css_palette_value_new_default ());
@@ -1494,7 +1491,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_SOURCE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_ICON_TEXTURE,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
css_image_value_parse,
NULL,
_gtk_css_image_value_new (NULL));
@@ -1502,7 +1499,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_SIZE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_ICON_SIZE,
GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
icon_size_parse,
NULL,
_gtk_css_number_value_new (16, GTK_CSS_PX));
@@ -1510,7 +1507,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_SHADOW,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
GTK_CSS_AFFECTS_ICON_REDRAW,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON,
shadow_value_parse,
NULL,
gtk_css_shadow_value_new_none ());
@@ -1518,7 +1515,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_PROPERTY_ICON_STYLE,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_INHERIT,
GTK_CSS_AFFECTS_ICON_TEXTURE,
GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | GTK_CSS_AFFECTS_ICON_SIZE,
icon_style_parse,
NULL,
_gtk_css_icon_style_value_new (GTK_CSS_ICON_STYLE_REQUESTED));

View File

@@ -64,7 +64,7 @@ GType _gtk_css_style_property_get_type (void) G_GNUC_CO
void _gtk_css_style_property_init_properties (void);
guint _gtk_css_style_property_get_n_properties(void) G_GNUC_CONST;
guint _gtk_css_style_property_get_n_properties(void);
GtkCssStyleProperty * _gtk_css_style_property_lookup_by_id (guint id);
gboolean _gtk_css_style_property_is_inherit (GtkCssStyleProperty *property);

View File

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

View File

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

View File

@@ -329,7 +329,7 @@ _gtk_css_value_print (const GtkCssValue *value,
* Returns %TRUE if the value is dynamic
*/
gboolean
gtk_css_value_is_dynamic (const GtkCssValue *value)
gtk_css_value_is_dynamic (GtkCssValue *value)
{
gtk_internal_return_val_if_fail (value != NULL, FALSE);

View File

@@ -55,7 +55,7 @@ struct _GtkCssValueClass {
GtkCssValue *end,
guint property_id,
double progress);
gboolean (* is_dynamic) (const GtkCssValue *value);
gboolean (* is_dynamic) (GtkCssValue *value);
GtkCssValue * (* get_dynamic_value) (GtkCssValue *value,
gint64 monotonic_time);
void (* print) (const GtkCssValue *value,
@@ -77,16 +77,16 @@ GtkCssValue *_gtk_css_value_compute (GtkCssValue
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style) G_GNUC_PURE;
GtkCssStyle *parent_style);
gboolean _gtk_css_value_equal (const GtkCssValue *value1,
const GtkCssValue *value2) G_GNUC_PURE;
const GtkCssValue *value2);
gboolean _gtk_css_value_equal0 (const GtkCssValue *value1,
const GtkCssValue *value2) G_GNUC_PURE;
const GtkCssValue *value2);
GtkCssValue *_gtk_css_value_transition (GtkCssValue *start,
GtkCssValue *end,
guint property_id,
double progress);
gboolean gtk_css_value_is_dynamic (const GtkCssValue *value) G_GNUC_PURE;
gboolean gtk_css_value_is_dynamic (GtkCssValue *value);
GtkCssValue * gtk_css_value_get_dynamic_value (GtkCssValue *value,
gint64 monotonic_time);

View File

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

View File

@@ -22,12 +22,9 @@
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkwidgetprivate.h"
#include "gtkcssstyleprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcsstypesprivate.h"
#include "gtknativeprivate.h"
#include "gtkpicture.h"
#include "gtkcssnumbervalueprivate.h"
/**
@@ -110,15 +107,16 @@ gtk_drag_icon_native_get_surface_transform (GtkNative *native,
int *x,
int *y)
{
GtkCssStyle *style;
GtkStyleContext *context;
GtkBorder margin, border, padding;
style = gtk_css_node_get_style (gtk_widget_get_css_node (GTK_WIDGET (native)));
*x = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_MARGIN_LEFT), 100) +
_gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100) +
_gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_PADDING_LEFT), 100);
*y = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_MARGIN_TOP), 100) +
_gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100) +
_gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_PADDING_TOP), 100);
context = gtk_widget_get_style_context (GTK_WIDGET (native));
gtk_style_context_get_margin (context, &margin);
gtk_style_context_get_border (context, &border);
gtk_style_context_get_padding (context, &padding);
*x = margin.left + border.left + padding.left;
*y = margin.top + border.top + padding.top;
}
static void

View File

@@ -387,7 +387,8 @@ add_emoji (GtkWidget *box,
return;
}
child = g_object_new (GTK_TYPE_FLOW_BOX_CHILD, "css-name", "emoji", NULL);
child = gtk_flow_box_child_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (child), "emoji");
g_object_set_data_full (G_OBJECT (child), "emoji-data",
g_variant_ref (item),
(GDestroyNotify)g_variant_unref);

View File

@@ -179,11 +179,16 @@ move_active_row (GtkEmojiCompletion *completion,
int direction)
{
GtkWidget *child;
GtkWidget *base;
for (child = gtk_widget_get_first_child (completion->list);
child != NULL;
child = gtk_widget_get_next_sibling (child))
gtk_widget_unset_state_flags (child, GTK_STATE_FLAG_FOCUSED);
{
gtk_widget_unset_state_flags (child, GTK_STATE_FLAG_PRELIGHT);
base = GTK_WIDGET (g_object_get_data (G_OBJECT (child), "base"));
gtk_widget_unset_state_flags (base, GTK_STATE_FLAG_PRELIGHT);
}
if (completion->active != NULL)
{
@@ -202,11 +207,11 @@ move_active_row (GtkEmojiCompletion *completion,
}
if (completion->active != NULL)
gtk_widget_set_state_flags (completion->active, GTK_STATE_FLAG_FOCUSED, FALSE);
gtk_widget_set_state_flags (completion->active, GTK_STATE_FLAG_PRELIGHT, FALSE);
if (completion->active_variation)
{
gtk_widget_unset_state_flags (completion->active_variation, GTK_STATE_FLAG_FOCUSED);
gtk_widget_unset_state_flags (completion->active_variation, GTK_STATE_FLAG_PRELIGHT);
completion->active_variation = NULL;
}
}
@@ -227,7 +232,6 @@ show_variations (GtkEmojiCompletion *completion,
{
GtkWidget *stack;
GtkWidget *box;
GtkWidget *child;
gboolean is_visible;
if (!row)
@@ -242,10 +246,17 @@ show_variations (GtkEmojiCompletion *completion,
if (is_visible == visible)
return;
if (visible)
gtk_widget_unset_state_flags (row, GTK_STATE_FLAG_PRELIGHT);
else
gtk_widget_set_state_flags (row, GTK_STATE_FLAG_PRELIGHT, FALSE);
gtk_stack_set_visible_child_name (GTK_STACK (stack), visible ? "variations" : "text");
for (child = gtk_widget_get_first_child (box); child; child = gtk_widget_get_next_sibling (child))
gtk_widget_unset_state_flags (child, GTK_STATE_FLAG_FOCUSED);
completion->active_variation = NULL;
if (completion->active_variation)
{
gtk_widget_unset_state_flags (completion->active_variation, GTK_STATE_FLAG_PRELIGHT);
completion->active_variation = NULL;
}
}
static gboolean
@@ -283,9 +294,9 @@ move_active_variation (GtkEmojiCompletion *completion,
if (next)
{
if (completion->active_variation)
gtk_widget_unset_state_flags (completion->active_variation, GTK_STATE_FLAG_FOCUSED);
gtk_widget_unset_state_flags (completion->active_variation, GTK_STATE_FLAG_PRELIGHT);
completion->active_variation = next;
gtk_widget_set_state_flags (completion->active_variation, GTK_STATE_FLAG_FOCUSED, FALSE);
gtk_widget_set_state_flags (completion->active_variation, GTK_STATE_FLAG_PRELIGHT, FALSE);
}
return next != NULL;
@@ -466,7 +477,8 @@ add_emoji_variation (GtkWidget *box,
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
child = g_object_new (GTK_TYPE_FLOW_BOX_CHILD, "css-name", "emoji", NULL);
child = gtk_flow_box_child_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (child), "emoji");
g_object_set_data_full (G_OBJECT (child), "text", g_strdup (text), g_free);
g_object_set_data_full (G_OBJECT (child), "emoji-data",
g_variant_ref (emoji_data),
@@ -501,7 +513,7 @@ add_emoji (GtkWidget *list,
pango_attr_list_unref (attrs);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "emoji");
child = g_object_new (GTK_TYPE_LIST_BOX_ROW, "css-name", "emoji-completion-row", NULL);
child = gtk_list_box_row_new ();
gtk_widget_set_focus_on_click (child, FALSE);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add (GTK_CONTAINER (child), box);
@@ -538,6 +550,7 @@ add_emoji (GtkWidget *list,
g_object_set_data_full (G_OBJECT (child), "text", g_strdup (text), g_free);
g_object_set_data_full (G_OBJECT (child), "emoji-data",
g_variant_ref (emoji_data), (GDestroyNotify)g_variant_unref);
gtk_style_context_add_class (gtk_widget_get_style_context (child), "emoji-completion-row");
gtk_list_box_insert (GTK_LIST_BOX (list), child, -1);
}
@@ -553,12 +566,9 @@ populate_completion (GtkEmojiCompletion *completion,
GVariantIter iter;
GVariant *item;
if (completion->text != text)
{
g_free (completion->text);
completion->text = g_strdup (text);
completion->length = g_utf8_strlen (text, -1);
}
g_free (completion->text);
completion->text = g_strdup (text);
completion->length = g_utf8_strlen (text, -1);
completion->offset = offset;
children = gtk_container_get_children (GTK_CONTAINER (completion->list));
@@ -593,7 +603,7 @@ populate_completion (GtkEmojiCompletion *completion,
if (n_added > 0)
{
completion->active = gtk_widget_get_first_child (completion->list);
gtk_widget_set_state_flags (completion->active, GTK_STATE_FLAG_FOCUSED, FALSE);
gtk_widget_set_state_flags (completion->active, GTK_STATE_FLAG_PRELIGHT, FALSE);
}
return n_added;

View File

@@ -73,7 +73,7 @@
* ├── box.start
* │ ╰── box
* │ ├── [image.titlebutton.icon]
* │ ├── [menubutton.titlebutton.menu]
* │ ├── [menubutton.titlebutton.appmenu]
* │ ├── [button.titlebutton.minimize]
* │ ├── [button.titlebutton.maximize]
* │ ╰── [button.titlebutton.close]
@@ -406,7 +406,7 @@ _gtk_header_bar_update_window_buttons (GtkHeaderBar *bar)
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (button), menu);
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
gtk_style_context_add_class (gtk_widget_get_style_context (button), "menu");
gtk_style_context_add_class (gtk_widget_get_style_context (button), "appmenu");
image = gtk_image_new ();
gtk_menu_button_add_child (GTK_MENU_BUTTON (button), image);
gtk_widget_set_can_focus (button, FALSE);

View File

@@ -54,29 +54,6 @@ gtk_icon_snapshot (GtkWidget *widget,
gtk_css_style_snapshot_icon (style, snapshot, width, height);
}
static void
gtk_icon_style_updated (GtkWidget *widget)
{
GtkStyleContext *context;
GtkCssStyleChange *change = NULL;
context = gtk_widget_get_style_context (widget);
change = gtk_style_context_get_change (context);
GTK_WIDGET_CLASS (gtk_icon_parent_class)->style_updated (widget);
if (change == NULL ||
gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_SIZE))
{
gtk_widget_queue_resize (widget);
}
else if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_TEXTURE) ||
gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_REDRAW))
{
gtk_widget_queue_draw (widget);
}
}
static void
gtk_icon_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -99,7 +76,6 @@ gtk_icon_class_init (GtkIconClass *klass)
wclass->snapshot = gtk_icon_snapshot;
wclass->measure = gtk_icon_measure;
wclass->style_updated = gtk_icon_style_updated;
}
static void

View File

@@ -35,7 +35,6 @@
#include "gtkscalerprivate.h"
#include "gtksnapshot.h"
#include "gtkwidgetprivate.h"
#include "gdk/gdkprofilerprivate.h"
struct _GtkIconHelper
{
@@ -144,14 +143,11 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
GdkPaintable *paintable;
GIcon *gicon;
gboolean symbolic;
gint64 before = g_get_monotonic_time ();
char *item;
switch (gtk_image_definition_get_storage_type (self->def))
{
case GTK_IMAGE_PAINTABLE:
paintable = g_object_ref (gtk_image_definition_get_paintable (self->def));
item = g_strdup ("paintable");
symbolic = FALSE;
break;
@@ -160,7 +156,6 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
gicon = g_themed_icon_new_with_default_fallbacks (gtk_image_definition_get_icon_name (self->def));
else
gicon = g_themed_icon_new (gtk_image_definition_get_icon_name (self->def));
item = g_icon_to_string (gicon);
paintable = ensure_paintable_for_gicon (self,
gtk_css_node_get_style (self->node),
gtk_widget_get_direction (self->owner),
@@ -171,7 +166,6 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
break;
case GTK_IMAGE_GICON:
item = g_icon_to_string (gtk_image_definition_get_gicon (self->def));
paintable = ensure_paintable_for_gicon (self,
gtk_css_node_get_style (self->node),
gtk_widget_get_direction (self->owner),
@@ -184,16 +178,11 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
default:
paintable = NULL;
symbolic = FALSE;
item = NULL;
break;
}
*out_symbolic = symbolic;
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "icon helper load", item);
g_free (item);
return paintable;
}
@@ -385,24 +374,19 @@ gtk_icon_helper_invalidate_for_change (GtkIconHelper *self,
GtkCssStyleChange *change)
{
if (change == NULL ||
gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_TEXTURE))
((gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SYMBOLIC_ICON) &&
self->texture_is_symbolic) ||
(gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON) &&
!self->texture_is_symbolic)))
{
/* Avoid the queue_resize in gtk_icon_helper_invalidate */
g_clear_object (&self->paintable);
self->texture_is_symbolic = FALSE;
gtk_widget_queue_draw (self->owner);
}
if (change == NULL ||
gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_SIZE))
{
gtk_widget_queue_resize (self->owner);
}
else if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_REDRAW) ||
(self->texture_is_symbolic &&
gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_REDRAW_SYMBOLIC)))
{
gtk_widget_queue_draw (self->owner);
if (change == NULL ||
(gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_ICON_SIZE) &&
!GTK_IS_CSS_TRANSIENT_NODE (self->node)))
gtk_widget_queue_resize (self->owner);
}
}

View File

@@ -50,7 +50,6 @@
#include "gtkprivate.h"
#include "gdkpixbufutilsprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
/* this is in case round() is not provided by the compiler,
* such as in the case of C89 compilers, like MSVC
@@ -1363,7 +1362,6 @@ ensure_valid_themes (GtkIconTheme *self)
{
GTimeVal tv;
gboolean was_valid = self->themes_valid;
gint64 before = g_get_monotonic_time ();
if (self->loading_themes)
return;
@@ -1390,9 +1388,6 @@ ensure_valid_themes (GtkIconTheme *self)
queue_theme_changed (self);
}
if (gdk_profiler_is_running ())
gdk_profiler_add_mark (before * 1000, (g_get_monotonic_time () - before) * 1000, "icon theme load", NULL);
self->loading_themes = FALSE;
}
@@ -3248,8 +3243,6 @@ icon_info_ensure_scale_and_texture (GtkIconInfo *icon_info)
icon_info->scale = (gdouble) scaled_desired_size / (icon_info->dir_size * dir_scale);
}
gdk_profiler_add_mark (g_get_monotonic_time () * 1000, 0, "icon load", icon_info->filename);
/* At this point, we need to actually get the icon; either from the
* builtin image or by loading the file
*/

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