Compare commits

...

60 Commits

Author SHA1 Message Date
Alexander Larsson 42306022a0 gdk: Convert mouse position to doubles, add new getters
We've long had double precision mouse coordinates on wayland (e.g.
when rotating a window) but with the new scaling we even have it on
X (and, its also in Xinput2), so convert all the internal mouse/device
position getters to use doubles and add new accessors for the
public APIs that take doubles instead of ints.
2013-07-03 12:07:05 +02:00
Alexander Larsson 0c990645de win32: Remove unused functions
The _gdk_windowing_* stuff is not used anymore
2013-07-03 12:07:05 +02:00
Alexander Larsson daaf2a0d0f quartz: Remove unused functions
The _gdk_windowing_* stuff is not used anymore
2013-07-03 12:07:05 +02:00
Alexander Larsson 17e8846bf9 gtk: Use cairo surfaces rather than patterns for icons
cairo_pattern_t were used because they also support scaling
via the pattern matrix. However, patterns are not a great fit
for icons as they are potentially unbounded (i.e. for gradients).
So we switch to surfaces, using the device_scale for scaling.
2013-07-02 22:28:06 +02:00
Alexander Larsson e70de7a1c6 filechooser: Fix missing surface to pattern conversion from last commit 2013-07-02 21:08:31 +02:00
Alexander Larsson a35db35996 filesystem: Render to surfaces instead of patterns 2013-07-02 17:06:44 +02:00
Alexander Larsson 2d850b0d03 GtkIconTheme: load_pattern -> load_surface
We use cairo_surface_t instead of cairo_pattern_t, and
we use device-scale to handle scaling.
2013-07-02 16:54:05 +02:00
Alexander Larsson e08285fc78 gdk: Add scale to gdk_cairo_surface_create_from_pixbuf
This is needed so we can create scaled surfaces as we want to
switch away from using patterns.
2013-07-02 16:46:07 +02:00
Alexander Larsson 0b06e2029c gdk: gdk_cairo_pixbuf_to_surface -> gdk_cairo_surface_create_from_pixbuf 2013-07-02 16:35:05 +02:00
Alexander Larsson 29463e9ea9 Revert "gdk: Add gdk_cairo_surface_create_similar"
This reverts commit 6a98703c9a.

Conflicts:
	gdk/gdkcairo.h
2013-07-02 16:30:23 +02:00
Alexander Larsson 86a5f2c30e Revert "Gtk: Use gdk_cairo_surface_create_similar"
This reverts commit bb7e83399b.
2013-07-02 16:27:06 +02:00
Alexander Larsson 0ed5dbf9c4 widget: Add missing AVAILIBLE_IN 2013-07-02 16:17:18 +02:00
Alexander Larsson 3563bdcce7 x11: Don't follow dpi and scale from xsettings when GDK_SCALE set
If things are hardcoded in the environment, that wins.
2013-07-01 20:55:37 +02:00
Alexander Larsson 8e6eb0da22 quartz: Fix the build for the scale_factor changes 2013-07-01 09:55:45 +02:00
Alexander Larsson 1e31befc1a x11: Add Gdk/UnscaledDPI to override Xft/DPI
This lets use use a scaled Xft/DPI for old apps while not
blowing up the size of scaled windows. Only apps supporting
Gdk/WindowScaleFactor should supprt Gdk/UnscaledDPI.
2013-06-28 13:23:45 +02:00
Alexander Larsson d22dbf7648 x11: Remove leftover debug spew 2013-06-28 12:26:52 +02:00
Alexander Larsson 4e45126834 widget: Track when the window scale factor changes and notify
The scale-factor property on the widgets will be notified, and the
scale will change on the style property, causing us to pick up
new css assets.
2013-06-28 12:17:55 +02:00
Alexander Larsson 536a6676cb x11: Also change size & pos on child windows when scale changes
Any native windows need to also change size and position.
We don't change the size of any foreign windows since we
don't generally control these.
2013-06-28 12:17:55 +02:00
Alexander Larsson a0fb6c8360 x11: Properly resize child native windows 2013-06-28 12:17:55 +02:00
Alexander Larsson 8e89015f4d GtkWidget: Add scale-factor property 2013-06-28 12:17:55 +02:00
Alexander Larsson cdabe7db91 GtkCssImageScaled: Ensure we compute the child when computing the image 2013-06-28 12:17:55 +02:00
Alexander Larsson 681a6ad229 x11: Support the Gdk/WindowScalingFactor xsetting
This xsetting can be used to tell Gtk to use a specific window
scaling for the screen.
2013-06-28 12:17:55 +02:00
Alexander Larsson c3cf2df07f gtk-demo: Add demo of hidpi css assets via -gtk-scaled() 2013-06-28 12:17:54 +02:00
Alexander Larsson dbcfc1f66e CSS: Add -gtk-scaled(image1,image2,...) support for hidpi assets 2013-06-28 12:17:54 +02:00
Alexander Larsson 0f837618ed css: Add a scale argument to css-value compute vfunc
We need to be able to compute different GtkCssImage values
depending on the scale, and we need this at compute time so that
we don't need to read any images other than the scale in used (to
e.g. calculate the image size). GtkStyleProviderPrivate is shared
for all style contexts, so its not right.
2013-06-28 12:17:54 +02:00
Alexander Larsson 339d4ef757 GtkWidget: Propagate scale to GtkStyleContext 2013-06-28 12:17:54 +02:00
Alexander Larsson d36bc524da GtkStyleContext: Add gtk_style_context_get/set_scale 2013-06-28 12:17:54 +02:00
Alexander Larsson bdc3343a88 File chooser: Convert icons to using cairo_pattern_t
This means we draw faster, and automatically handle hidpi icons.
2013-06-28 12:17:54 +02:00
Alexander Larsson bcde0f387d GtkCellRendererPixbuf: Add pattern property 2013-06-28 12:17:54 +02:00
Alexander Larsson b5a5bd0717 GtkImage: Add new_from_pattern() and set_from_pattern() 2013-06-28 12:17:54 +02:00
Alexander Larsson 3d2041524c GtkIconHelper: Add support for cairo_pattern_t 2013-06-28 12:17:54 +02:00
Alexander Larsson d5f56fcb8f GtkIconTheme: Add helpers to load to cairo_pattern_t
Right now this just uses the pixbuf load code and converts
it to a pattern. In the future we could cache the pattern
to allow reusing the pattern.
2013-06-28 12:17:54 +02:00
Alexander Larsson a5411cbe98 icon helper: support specifying pixbuf scale 2013-06-28 12:17:54 +02:00
Alexander Larsson 721c384f4f icon helper: Support scaled icons 2013-06-28 12:17:45 +02:00
Alexander Larsson c00611ca32 icon factory: Support scaled icons
Dupport scales when falling back to loading icons from the
icon theme.

In order to actually render scaled icons we add gtk_icon_set_render_icon_pattern
which renders to a cairo_pattern_t which includes whatever scaling you
need for scaled icons.
2013-06-28 12:17:45 +02:00
Carlos Garnacho a5698f6c06 icontheme: Add support for high resolution icons
An optional OutputScale integer key has been added to index.theme
subdirs description, so icon themes may provide icons that are
more suitable to render at a (typically 2x) integer upscaled
resolution. This way it is possible to make eg. a 16x16@2x icon has a
real size of 32x32, but contains a similar level of detail to the
16x16 icon so things don't look any more cluttered on high-dpi
screens.

The pixbuf lookup has changed so it prefers a minimal scale change
that yields the minimal real size difference, so if looking up for
a 16x16 icon at 2x, it would first prefer 16x16@2x, then 32x32, and
then any other icon that's closest to match

There is now *_for_scale() variants for all GtkIconTheme ways
to directly or indirectly fetch a GdkPixbuf.

This is based on code by Carlos Garnacho with changes by Alexander
Larsson
2013-06-28 12:17:45 +02:00
Alexander Larsson afb8f614f4 GtkIconHelper: render to cairo pattern rather than pixbuf for drawing
We render the source into a cairo_patter_t into a pixbuf so that
we can render it directly, rather than having to convert it every
time we render. We also specify the target window when creating
the cairo surface so that rendering can be faster.
2013-06-28 12:17:45 +02:00
Alexander Larsson 98481e95aa CellRendererPixbuf: Set the window on the icon helper
This lets us get scaled icons if needed.
2013-06-28 12:17:45 +02:00
Alexander Larsson b85c053e28 spinbutton: set the window on the icon helper 2013-06-28 12:17:45 +02:00
Alexander Larsson 338f959bb5 entry: Set the window on the icon helper 2013-06-28 12:17:45 +02:00
Alexander Larsson c3807bb122 GtkImage: Set the window on the gtkiconhelper 2013-06-28 12:17:45 +02:00
Alexander Larsson a6e4f5f0c4 GtkIconHelper: Add set_window()
This is a hint on where the icon will be drawn. It
will allow us to pre-allocate cairo surfaces for the right
target.
2013-06-28 12:17:45 +02:00
Alexander Larsson c64b269019 Use gdk_cairo_pixbuf_to_surface when possible
Rather than creating a surface and drawing to it.
2013-06-28 12:17:45 +02:00
Alexander Larsson a543702beb stylecontext: add gtk_render_icon_pattern
This draws an icon from a cairo_pattern. We want to use this more rather
than render_icon as this means we can skip the pixbuf to surface
conversion (including allocation and alpha premultiplication) at
render time, plus we can use create_similar_image which may allow
faster rendering.
2013-06-28 12:17:45 +02:00
Alexander Larsson d9abadbcee gdk: Add gdk_cairo_pixbuf_to_surface 2013-06-28 12:17:45 +02:00
Alexander Larsson e1ed8b50de gdk: add gdk_window_create_similar_image_surface
This lets us create image surfaces that render faster on specific windows.
It also supports creating scaled image surfaces.
2013-06-28 12:17:44 +02:00
Alexander Larsson 04e4814f4f Add GDK_DPI_SCALE env var
This is very useful for hidpi where the dpi is scaled to make
non-dpi aware apps larger. In that case a dpi aware gtk+ using
GDK_SCALE will be getting huge fonts. You can the set GDK_DPI_SCALE
to compensate for this.
2013-06-28 12:17:44 +02:00
Alexander Larsson a15998db18 x11: Initial cut at supporting window scaling for X11
If you set GDK_SCALE=2 in the environment then all windows will be
scaled by 2. Its not an ideal solution as it doesn't handle
multi-monitors at different scales, and only affects gtk apps.
But it is a good starting points and will help a lot on HiDPI
laptops.
2013-06-28 12:17:38 +02:00
Alexander Larsson 42342d73b5 wayland: Support gdk_window_get_scale
We track the list of outputs each window is on, and set the
scale to the largest scale value of the outputs. Any time the scale
changes we also emit a configure event.
2013-06-28 12:11:58 +02:00
Alexander Larsson 25e9052610 wayland: Require wayland-client 1.1.90
This has the new methods required for buffer scaling.
2013-06-28 12:11:58 +02:00
Alexander Larsson 790f0cee51 wayland: Implement gdk_screen_get_monitor_scale()
We bind to the newer version of the wl_output which supports
the new done and scale events, and if we use this to get the
scale for each monitor (defaulting to 1 if not supported).
2013-06-28 12:11:58 +02:00
Alexander Larsson 26722dc1cb offscreenwindow: Handle window_scale
We create similar windows in the right way to get the
device scale right.
2013-06-28 12:11:58 +02:00
Alexander Larsson 78b774cc8e gdkwindow: Respect cairo surfaces with device scale
If a cairo_surface for a window has a device scale set we need
to respect this when creating a similar window. I.e. we want
to then automatically create a larger window which inherits
the scale from the original.

We also need to calculate a different device_offset if there
is a device_scale set.
2013-06-28 12:11:58 +02:00
Alexander Larsson a95578e9e1 configure: Add buildtime check for cairo_surface_set_device_scale
We will need this for the window scale support, but its not yet
in a stable cairo release (or even on a master yet), so we make
this optional.
2013-06-28 12:11:58 +02:00
Alexander Larsson d7abaae7bc pixel-cache: Refresh pixel cache on window scale factor changes. 2013-06-28 12:11:58 +02:00
Alexander Larsson bb7e83399b Gtk: Use gdk_cairo_surface_create_similar 2013-06-28 12:11:57 +02:00
Alexander Larsson 6a98703c9a gdk: Add gdk_cairo_surface_create_similar
We track the window that each cairo surface is created for, which
allows us to use gdk_window_create_similar_surface() when creating
similar surfaces, even when you don't have access to the GdkWindow.
This will be extra important when we need to create larger surfaces
on HiDPI displays.
2013-06-28 12:11:57 +02:00
Michael Natterer 5931818450 gtk: add gtk_widget_get_scale_factor() 2013-06-28 12:11:57 +02:00
Michael Natterer 7c34f6221f quartz: Implement get_scale_factor() on screen and window
which return 1 normally and 2 on retina displays.
2013-06-28 12:11:57 +02:00
Michael Natterer 52d320e1a2 add gdk_screen_ and gdk_window_get_scale_factor()
These report the internal scaling factor, mapping from UI pixels
to hardware pixels.
2013-06-28 12:11:53 +02:00
115 changed files with 3337 additions and 1006 deletions
+12 -1
View File
@@ -402,7 +402,7 @@ if test "x$enable_wayland_backend" = "xyes"; then
GDK_WINDOWING="$GDK_WINDOWING
#define GDK_WINDOWING_WAYLAND"
DISABLE_ON_WAYLAND='%'
WAYLAND_PACKAGES="wayland-client >= 1.0.0 xkbcommon >= 0.2.0 wayland-cursor"
WAYLAND_PACKAGES="wayland-client >= 1.1.90 xkbcommon >= 0.2.0 wayland-cursor"
AM_CONDITIONAL(USE_WAYLAND, true)
else
AM_CONDITIONAL(USE_WAYLAND, false)
@@ -1263,6 +1263,17 @@ else
LIBS="$gtk_save_LIBS"
fi
# Check for cairo_set_device_scale, as we don't want to depend hard on
# this until there is a stable release with it
CAIRO_CFLAGS=`$PKG_CONFIG --cflags cairo`
CAIRO_LIBS=`$PKG_CONFIG --libs cairo`
CFLAGS="$CFLAGS $CAIRO_CFLAGS"
gtk_save_LIBS="$LIBS"
LIBS="$CAIRO_LIBS $LIBS"
AC_CHECK_FUNCS(cairo_surface_set_device_scale)
LIBS="$gtk_save_LIBS"
CFLAGS="$saved_cflags"
LDFLAGS="$saved_ldflags"
+2
View File
@@ -119,6 +119,8 @@ RESOURCES= $(demos) \
listbox.ui \
alphatest.png \
apple-red.png \
brick.png \
brick2.png \
background.jpg \
floppybuddy.gif \
gnome-applets.png \
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+1 -1
View File
@@ -117,7 +117,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
gtk_widget_set_name (child, "bricks-button");
gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
gtk_widget_set_size_request (child, 200, 80);
gtk_widget_set_size_request (child, 250, 84);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
gtk_overlay_add_overlay (GTK_OVERLAY (container), paned);
+1 -1
View File
@@ -56,7 +56,7 @@
/*
#bricks-button {
background-color: #eef;
background-image: url('resource:///css_multiplebgs/brick.png');
background-image: -gtk-scaled(url('resource:///css_multiplebgs/brick.png'),url('resource:///css_multiplebgs/brick2.png'));
background-repeat: no-repeat;
background-position: center;
}
+1
View File
@@ -26,6 +26,7 @@
<gresource prefix="/css_multiplebgs">
<file>css_multiplebgs.css</file>
<file>brick.png</file>
<file>brick2.png</file>
<file>cssview.css</file>
<file>reset.css</file>
</gresource>
+20 -20
View File
@@ -38,16 +38,16 @@ static void gdk_broadway_device_set_window_cursor (GdkDevice *device,
GdkCursor *cursor);
static void gdk_broadway_device_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
gdouble x,
gdouble y);
static void gdk_broadway_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_broadway_device_grab (GdkDevice *device,
GdkWindow *window,
@@ -59,8 +59,8 @@ static GdkGrabStatus gdk_broadway_device_grab (GdkDevice *device,
static void gdk_broadway_device_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_broadway_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_broadway_device_select_window_events (GdkDevice *device,
@@ -114,14 +114,14 @@ gdk_broadway_device_get_state (GdkDevice *device,
gdouble *axes,
GdkModifierType *mask)
{
gint x_int, y_int;
gdouble x, y;
gdk_window_get_device_position (window, device, &x_int, &y_int, mask);
gdk_window_get_device_position_double (window, device, &x, &y, mask);
if (axes)
{
axes[0] = x_int;
axes[1] = y_int;
axes[0] = x;
axes[1] = y;
}
}
@@ -135,8 +135,8 @@ gdk_broadway_device_set_window_cursor (GdkDevice *device,
static void
gdk_broadway_device_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
}
@@ -145,10 +145,10 @@ gdk_broadway_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkWindow *toplevel;
@@ -335,8 +335,8 @@ gdk_broadway_device_ungrab (GdkDevice *device,
static GdkWindow *
gdk_broadway_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
+2 -2
View File
@@ -750,8 +750,8 @@ gdk_broadway_window_get_frame_extents (GdkWindow *window,
static gboolean
gdk_window_broadway_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkWindow *child;
+44 -23
View File
@@ -176,24 +176,20 @@ gdk_cairo_region (cairo_t *cr,
}
/**
* gdk_cairo_set_source_pixbuf:
* @cr: a cairo context
* gdk_cairo_surface_create_from_pixbuf:
* @pixbuf: a #GdkPixbuf
* @pixbuf_x: X coordinate of location to place upper left corner of @pixbuf
* @pixbuf_y: Y coordinate of location to place upper left corner of @pixbuf
* @scale: the scale of the new surface, or 0 to use same as @window
* @for_window: The window this will be drawn to, on %NULL.
*
* Sets the given pixbuf as the source pattern for @cr.
* Creates an image surface with the same contents as
* the pixbuf.
*
* The pattern has an extend mode of %CAIRO_EXTEND_NONE and is aligned
* so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y.
*
* Since: 2.8
* Since: 3.10
*/
void
gdk_cairo_set_source_pixbuf (cairo_t *cr,
const GdkPixbuf *pixbuf,
gdouble pixbuf_x,
gdouble pixbuf_y)
cairo_surface_t *
gdk_cairo_surface_create_from_pixbuf (const GdkPixbuf *pixbuf,
int scale,
GdkWindow *for_window)
{
gint width = gdk_pixbuf_get_width (pixbuf);
gint height = gdk_pixbuf_get_height (pixbuf);
@@ -204,7 +200,6 @@ gdk_cairo_set_source_pixbuf (cairo_t *cr,
guchar *cairo_pixels;
cairo_format_t format;
cairo_surface_t *surface;
static const cairo_user_data_key_t key;
int j;
if (n_channels == 3)
@@ -212,14 +207,13 @@ gdk_cairo_set_source_pixbuf (cairo_t *cr,
else
format = CAIRO_FORMAT_ARGB32;
cairo_stride = cairo_format_stride_for_width (format, width);
cairo_pixels = g_malloc (height * cairo_stride);
surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels,
format,
width, height, cairo_stride);
cairo_surface_set_user_data (surface, &key,
cairo_pixels, (cairo_destroy_func_t)g_free);
surface =
gdk_window_create_similar_image_surface (for_window,
format,
width, height,
scale);
cairo_stride = cairo_image_surface_get_stride (surface);
cairo_pixels = cairo_image_surface_get_data (surface);
for (j = height; j; j--)
{
@@ -277,6 +271,33 @@ gdk_cairo_set_source_pixbuf (cairo_t *cr,
cairo_pixels += cairo_stride;
}
cairo_surface_mark_dirty (surface);
return surface;
}
/**
* gdk_cairo_set_source_pixbuf:
* @cr: a cairo context
* @pixbuf: a #GdkPixbuf
* @pixbuf_x: X coordinate of location to place upper left corner of @pixbuf
* @pixbuf_y: Y coordinate of location to place upper left corner of @pixbuf
*
* Sets the given pixbuf as the source pattern for @cr.
*
* The pattern has an extend mode of %CAIRO_EXTEND_NONE and is aligned
* so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y.
*
* Since: 2.8
*/
void
gdk_cairo_set_source_pixbuf (cairo_t *cr,
const GdkPixbuf *pixbuf,
gdouble pixbuf_x,
gdouble pixbuf_y)
{
cairo_surface_t *surface;
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y);
cairo_surface_destroy (surface);
}
+10
View File
@@ -66,6 +66,16 @@ GDK_DEPRECATED_IN_3_4_FOR(gdk_cairo_set_source_rgba)
void gdk_cairo_set_source_color (cairo_t *cr,
const GdkColor *color);
GDK_AVAILABLE_IN_3_10
cairo_surface_t * gdk_cairo_surface_create_similar (cairo_surface_t *surface,
cairo_content_t content,
int width,
int height);
GDK_AVAILABLE_IN_3_10
cairo_surface_t * gdk_cairo_surface_create_from_pixbuf (const GdkPixbuf *pixbuf,
int scale,
GdkWindow *for_window);
G_END_DECLS
#endif /* __GDK_CAIRO_H__ */
+105 -38
View File
@@ -24,6 +24,9 @@
#include "gdkinternals.h"
#include "gdkintl.h"
/* for the use of round() */
#include "fallback-c89.c"
/**
* SECTION:gdkdevice
* @Short_description: Object representing an input device
@@ -406,28 +409,28 @@ gdk_device_get_state (GdkDevice *device,
}
/**
* gdk_device_get_position:
* gdk_device_get_position_double:
* @device: pointer device to query status about.
* @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
* the @device is on, or %NULL.
* @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
* @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
*
* Gets the current location of @device. As a slave device
* Gets the current location of @device in double precision. As a slave device
* coordinates are those of its master pointer, This function
* may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
* unless there is an ongoing grab on them, see gdk_device_grab().
*
* Since: 3.0
* Since: 3.10
**/
void
gdk_device_get_position (GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y)
gdk_device_get_position_double (GdkDevice *device,
GdkScreen **screen,
gdouble *x,
gdouble *y)
{
GdkDisplay *display;
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkScreen *default_screen;
GdkWindow *root;
@@ -455,6 +458,87 @@ gdk_device_get_position (GdkDevice *device,
*y = tmp_y;
}
/**
* gdk_device_get_position:
* @device: pointer device to query status about.
* @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
* the @device is on, or %NULL.
* @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
* @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
*
* Gets the current location of @device. As a slave device
* coordinates are those of its master pointer, This function
* may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
* unless there is an ongoing grab on them, see gdk_device_grab().
*
* Since: 3.0
**/
void
gdk_device_get_position (GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y)
{
gdouble tmp_x, tmp_y;
gdk_device_get_position_double (device, screen, &tmp_x, &tmp_y);
if (x)
*x = round (tmp_x);
if (y)
*y = round (tmp_y);
}
/**
* gdk_device_get_window_at_position_double:
* @device: pointer #GdkDevice to query info to.
* @win_x: (out) (allow-none): return location for the X coordinate of the device location,
* relative to the window origin, or %NULL.
* @win_y: (out) (allow-none): return location for the Y coordinate of the device location,
* relative to the window origin, or %NULL.
*
* Obtains the window underneath @device, returning the location of the device in @win_x and @win_y in
* double precision. Returns %NULL if the window tree under @device is not known to GDK (for example,
* belongs to another application).
*
* As a slave device coordinates are those of its master pointer, This
* function may not be called on devices of type %GDK_DEVICE_TYPE_SLAVE,
* unless there is an ongoing grab on them, see gdk_device_grab().
*
* Returns: (transfer none): the #GdkWindow under the device position, or %NULL.
*
* Since: 3.0
**/
GdkWindow *
gdk_device_get_window_at_position_double (GdkDevice *device,
gdouble *win_x,
gdouble *win_y)
{
gdouble tmp_x, tmp_y;
GdkWindow *window;
g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
g_return_val_if_fail (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE ||
gdk_display_device_is_grabbed (gdk_device_get_display (device), device), NULL);
window = _gdk_device_window_at_position (device, &tmp_x, &tmp_y, NULL, FALSE);
/* This might need corrections, as the native window returned
may contain client side children */
if (window)
window = _gdk_window_find_descendant_at (window,
tmp_x, tmp_y,
&tmp_x, &tmp_y);
if (win_x)
*win_x = tmp_x;
if (win_y)
*win_y = tmp_y;
return window;
}
/**
* gdk_device_get_window_at_position:
* @device: pointer #GdkDevice to query info to.
@@ -479,33 +563,16 @@ gdk_device_get_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y)
{
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkWindow *window;
g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
g_return_val_if_fail (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE ||
gdk_display_device_is_grabbed (gdk_device_get_display (device), device), NULL);
window = _gdk_device_window_at_position (device, &tmp_x, &tmp_y, NULL, FALSE);
/* This might need corrections, as the native window returned
may contain client side children */
if (window)
{
double xx, yy;
window = _gdk_window_find_descendant_at (window,
tmp_x, tmp_y,
&xx, &yy);
tmp_x = floor (xx + 0.5);
tmp_y = floor (yy + 0.5);
}
window =
gdk_device_get_window_at_position_double (device, &tmp_x, &tmp_y);
if (win_x)
*win_x = tmp_x;
*win_x = round (tmp_x);
if (win_y)
*win_y = tmp_y;
*win_y = round (tmp_y);
return window;
}
@@ -1535,8 +1602,8 @@ _gdk_device_translate_window_coord (GdkDevice *device,
gboolean
_gdk_device_translate_screen_coord (GdkDevice *device,
GdkWindow *window,
gint window_root_x,
gint window_root_y,
gdouble window_root_x,
gdouble window_root_y,
guint index_,
gdouble value,
gdouble *axis_value)
@@ -1616,10 +1683,10 @@ _gdk_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GDK_DEVICE_GET_CLASS (device)->query_state (device,
@@ -1635,8 +1702,8 @@ _gdk_device_query_state (GdkDevice *device,
GdkWindow *
_gdk_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
+11
View File
@@ -198,6 +198,17 @@ GdkWindow *
(GdkDevice *device,
gint *win_x,
gint *win_y);
GDK_AVAILABLE_IN_3_10
void gdk_device_get_position_double (GdkDevice *device,
GdkScreen **screen,
gdouble *x,
gdouble *y);
GDK_AVAILABLE_IN_3_10
GdkWindow *
gdk_device_get_window_at_position_double
(GdkDevice *device,
gdouble *win_x,
gdouble *win_y);
GDK_AVAILABLE_IN_ALL
gboolean gdk_device_get_history (GdkDevice *device,
GdkWindow *window,
+16 -16
View File
@@ -80,16 +80,16 @@ struct _GdkDeviceClass
void (* warp) (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
gdouble x,
gdouble y);
void (* query_state) (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
GdkGrabStatus (* grab) (GdkDevice *device,
GdkWindow *window,
@@ -102,8 +102,8 @@ struct _GdkDeviceClass
guint32 time_);
GdkWindow * (* window_at_position) (GdkDevice *device,
gint *win_x,
gint *win_y,
double *win_x,
double *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
void (* select_window_events) (GdkDevice *device,
@@ -140,8 +140,8 @@ gboolean _gdk_device_translate_window_coord (GdkDevice *device,
gboolean _gdk_device_translate_screen_coord (GdkDevice *device,
GdkWindow *window,
gint window_root_x,
gint window_root_y,
gdouble window_root_x,
gdouble window_root_y,
guint index,
gdouble value,
gdouble *axis_value);
@@ -162,14 +162,14 @@ void _gdk_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
GdkWindow * _gdk_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
+22 -19
View File
@@ -32,8 +32,11 @@
#include "gdkmarshalers.h"
#include "gdkscreen.h"
#include <math.h>
#include <glib.h>
/* for the use of round() */
#include "fallback-c89.c"
/**
* SECTION:gdkdisplay
@@ -546,7 +549,7 @@ gdk_display_get_pointer (GdkDisplay *display,
{
GdkScreen *default_screen;
GdkWindow *root;
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkModifierType tmp_mask;
g_return_if_fail (GDK_IS_DISPLAY (display));
@@ -569,9 +572,9 @@ gdk_display_get_pointer (GdkDisplay *display,
if (screen)
*screen = gdk_window_get_screen (root);
if (x)
*x = tmp_x;
*x = round (tmp_x);
if (y)
*y = tmp_y;
*y = round (tmp_y);
if (mask)
*mask = tmp_mask;
}
@@ -792,7 +795,7 @@ synthesize_crossing_events (GdkDisplay *display,
{
GdkWindow *src_toplevel, *dest_toplevel;
GdkModifierType state;
int x, y;
double x, y;
if (src_window)
src_toplevel = gdk_window_get_toplevel (src_window);
@@ -810,9 +813,9 @@ synthesize_crossing_events (GdkDisplay *display,
src_toplevel == dest_toplevel)
{
/* Same toplevels */
gdk_window_get_device_position (dest_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (dest_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
dest_window,
@@ -825,9 +828,9 @@ synthesize_crossing_events (GdkDisplay *display,
}
else if (dest_toplevel == NULL)
{
gdk_window_get_device_position (src_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (src_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
@@ -841,9 +844,9 @@ synthesize_crossing_events (GdkDisplay *display,
else
{
/* Different toplevels */
gdk_window_get_device_position (src_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (src_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
@@ -853,9 +856,9 @@ synthesize_crossing_events (GdkDisplay *display,
time,
NULL,
serial, FALSE);
gdk_window_get_device_position (dest_toplevel,
device,
&x, &y, &state);
gdk_window_get_device_position_double (dest_toplevel,
device,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
NULL,
dest_window,
@@ -876,7 +879,7 @@ get_current_toplevel (GdkDisplay *display,
GdkModifierType *state_out)
{
GdkWindow *pointer_window;
int x, y;
gdouble x, y;
GdkModifierType state;
pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
@@ -887,8 +890,8 @@ get_current_toplevel (GdkDisplay *display,
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
pointer_window = NULL;
*x_out = x;
*y_out = y;
*x_out = round (x);
*y_out = round (y);
*state_out = state;
return pointer_window;
+3 -3
View File
@@ -358,7 +358,7 @@ void _gdk_window_invalidate_for_expose (GdkWindow *window,
cairo_region_t *region);
GdkWindow * _gdk_window_find_child_at (GdkWindow *window,
int x, int y);
double x, double y);
GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
double x, double y,
double *found_x,
@@ -380,8 +380,8 @@ void _gdk_synthesize_crossing_events (GdkDisplay *display,
GdkDevice *device,
GdkDevice *source_device,
GdkCrossingMode mode,
gint toplevel_x,
gint toplevel_y,
gdouble toplevel_x,
gdouble toplevel_y,
GdkModifierType mask,
guint32 time_,
GdkEvent *event_in_queue,
+22 -18
View File
@@ -141,18 +141,11 @@ _gdk_offscreen_window_create_surface (GdkWindow *offscreen,
gint width,
gint height)
{
cairo_surface_t *similar;
cairo_surface_t *surface;
g_return_val_if_fail (GDK_IS_OFFSCREEN_WINDOW (offscreen->impl), NULL);
similar = _gdk_window_ref_cairo_surface (offscreen->parent);
surface = cairo_surface_create_similar (similar, CAIRO_CONTENT_COLOR_ALPHA, width, height);
cairo_surface_destroy (similar);
return surface;
return gdk_window_create_similar_surface (offscreen->parent,
CAIRO_CONTENT_COLOR_ALPHA,
width, height);
}
void
@@ -287,12 +280,12 @@ gdk_offscreen_window_get_root_coords (GdkWindow *window,
static gboolean
gdk_offscreen_window_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkOffscreenWindow *offscreen;
int tmpx, tmpy;
double tmpx, tmpy;
double dtmpx, dtmpy;
GdkModifierType tmpmask;
@@ -303,18 +296,18 @@ gdk_offscreen_window_get_device_state (GdkWindow *window,
offscreen = GDK_OFFSCREEN_WINDOW (window->impl);
if (offscreen->embedder != NULL)
{
gdk_window_get_device_position (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
gdk_window_get_device_position_double (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
from_embedder (window,
tmpx, tmpy,
&dtmpx, &dtmpy);
tmpx = floor (dtmpx + 0.5);
tmpy = floor (dtmpy + 0.5);
tmpx = dtmpx;
tmpy = dtmpy;
}
if (x)
*x = tmpx;
*x = round (tmpx);
if (y)
*y = tmpy;
*y = round (tmpy);
if (mask)
*mask = tmpmask;
return TRUE;
@@ -687,6 +680,16 @@ gdk_offscreen_window_get_frame_extents (GdkWindow *window,
rect->height = window->height;
}
static gint
gdk_offscreen_window_get_scale_factor (GdkWindow *window)
{
if (GDK_WINDOW_DESTROYED (window))
return 1;
return gdk_window_get_scale_factor (window->parent);
}
static void
gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
{
@@ -773,4 +776,5 @@ gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
impl_class->get_property = NULL;
impl_class->change_property = NULL;
impl_class->delete_property = NULL;
impl_class->get_scale_factor = gdk_offscreen_window_get_scale_factor;
}
+34
View File
@@ -1048,3 +1048,37 @@ gdk_screen_get_setting (GdkScreen *screen,
return GDK_SCREEN_GET_CLASS (screen)->get_setting (screen, name, value);
}
/**
* gdk_screen_get_monitor_scale_factor:
* @screen: screen to get scale factor for
* @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
*
* Returns the internal scale factor that maps from monitor coordiantes
* to the actual device pixels. On traditional systems this is 1, but
* on very high density outputs this can be a higher value (often 2).
*
* This can be used if you want to create pixel based data for a
* particula monitor, but most of the time you're drawing to a window
* where it is better to use gdk_window_get_scale_factor() instead.
*
* Since: 3.10
* Return value: the scale factor
*/
gint
gdk_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num)
{
GdkScreenClass *screen_class;
g_return_val_if_fail (GDK_IS_SCREEN (screen), 1);
g_return_val_if_fail (monitor_num >= 0, 1);
g_return_val_if_fail (monitor_num < gdk_screen_get_n_monitors (screen), 1);
screen_class = GDK_SCREEN_GET_CLASS (screen);
if (screen_class->get_monitor_scale_factor)
return screen_class->get_monitor_scale_factor (screen, monitor_num);
return 1.0;
}
+3
View File
@@ -99,6 +99,9 @@ gint gdk_screen_get_monitor_height_mm (GdkScreen *screen,
GDK_AVAILABLE_IN_ALL
gchar * gdk_screen_get_monitor_plug_name (GdkScreen *screen,
gint monitor_num);
GDK_AVAILABLE_IN_3_10
gint gdk_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num);
GDK_AVAILABLE_IN_ALL
GdkScreen *gdk_screen_get_default (void);
+2 -1
View File
@@ -91,7 +91,8 @@ struct _GdkScreenClass
void (* query_visual_types) (GdkScreen *screen,
GdkVisualType **visual_types,
gint *count);
gint (* get_monitor_scale_factor) (GdkScreen *screen,
gint monitor_num);
/* Signals: */
void (*size_changed) (GdkScreen *screen);
+175 -17
View File
@@ -2756,6 +2756,7 @@ gdk_window_begin_paint_region (GdkWindow *window,
GdkWindowImplClass *impl_class;
GdkWindowPaint *paint;
GSList *list;
double sx, sy;
gboolean needs_surface;
g_return_if_fail (GDK_IS_WINDOW (window));
@@ -2782,7 +2783,11 @@ gdk_window_begin_paint_region (GdkWindow *window,
gdk_window_get_content (window),
MAX (clip_box.width, 1),
MAX (clip_box.height, 1));
cairo_surface_set_device_offset (paint->surface, -clip_box.x, -clip_box.y);
sx = sy = 1;
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_get_device_scale (paint->surface, &sx, &sy);
#endif
cairo_surface_set_device_offset (paint->surface, -clip_box.x*sx, -clip_box.y*sy);
}
for (list = window->paint_stack; list != NULL; list = list->next)
@@ -4420,30 +4425,30 @@ gdk_window_get_pointer (GdkWindow *window,
}
/**
* gdk_window_get_device_position:
* gdk_window_get_device_position_double:
* @window: a #GdkWindow.
* @device: pointer #GdkDevice to query to.
* @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
* @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
* @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
*
* Obtains the current device position and modifier state.
* Obtains the current device position in doubles and modifier state.
* The position is given in coordinates relative to the upper left
* corner of @window.
*
* Return value: (transfer none): The window underneath @device (as with
* gdk_device_get_window_at_position()), or %NULL if the window is not known to GDK.
*
* Since: 3.0
* Since: 3.10
**/
GdkWindow *
gdk_window_get_device_position (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
GdkModifierType *mask)
gdk_window_get_device_position_double (GdkWindow *window,
GdkDevice *device,
double *x,
double *y,
GdkModifierType *mask)
{
gint tmp_x, tmp_y;
gdouble tmp_x, tmp_y;
GdkModifierType tmp_mask;
gboolean normal_child;
@@ -4473,6 +4478,44 @@ gdk_window_get_device_position (GdkWindow *window,
return NULL;
}
/**
* gdk_window_get_device_position:
* @window: a #GdkWindow.
* @device: pointer #GdkDevice to query to.
* @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
* @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
* @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
*
* Obtains the current device position and modifier state.
* The position is given in coordinates relative to the upper left
* corner of @window.
*
* Use gdk_window_get_device_position_double() if you need subpixel precision.
*
* Return value: (transfer none): The window underneath @device (as with
* gdk_device_get_window_at_position()), or %NULL if the window is not known to GDK.
*
* Since: 3.0
**/
GdkWindow *
gdk_window_get_device_position (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
GdkModifierType *mask)
{
gdouble tmp_x, tmp_y;
window = gdk_window_get_device_position_double (window, device,
&tmp_x, &tmp_y, mask);
if (x)
*x = round (tmp_x);
if (y)
*y = round (tmp_y);
return window;
}
/**
* gdk_get_default_root_window:
*
@@ -6948,8 +6991,8 @@ pick_embedded_child (GdkWindow *window,
GdkWindow *
_gdk_window_find_child_at (GdkWindow *window,
int x,
int y)
double x,
double y)
{
GdkWindow *sub;
double child_x, child_y;
@@ -7390,8 +7433,8 @@ send_crossing_event (GdkDisplay *display,
GdkWindow *subwindow,
GdkDevice *device,
GdkDevice *source_device,
gint toplevel_x,
gint toplevel_y,
gdouble toplevel_x,
gdouble toplevel_y,
GdkModifierType mask,
guint32 time_,
GdkEvent *event_in_queue,
@@ -7506,8 +7549,8 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
GdkDevice *device,
GdkDevice *source_device,
GdkCrossingMode mode,
gint toplevel_x,
gint toplevel_y,
double toplevel_x,
double toplevel_y,
GdkModifierType mask,
guint32 time_,
GdkEvent *event_in_queue,
@@ -9197,10 +9240,18 @@ gdk_window_create_similar_surface (GdkWindow * window,
int height)
{
cairo_surface_t *window_surface, *surface;
double sx, sy;
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
window_surface = gdk_window_ref_impl_surface (window);
sx = sy = 1;
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_get_device_scale (window_surface, &sx, &sy);
#endif
width = width * sx;
height = height * sy;
switch (_gdk_rendering_mode)
{
@@ -9223,11 +9274,80 @@ gdk_window_create_similar_surface (GdkWindow * window,
break;
}
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_set_device_scale (surface, sx, sy);
#endif
cairo_surface_destroy (window_surface);
return surface;
}
/**
* gdk_window_create_similar_image_surface:
* @window: window to make new surface similar to, or %NULL if none
* @format: (type int): the format for the new surface
* @width: width of the new surface
* @height: height of the new surface
* @scale: the scale of the new surface, or 0 to use same as @window
*
* Create a new image surface that is efficient to draw on the
* given @window.
*
* Initially the surface contents are all 0 (transparent if contents
* have transparency, black otherwise.)
*
* Returns: a pointer to the newly allocated surface. The caller
* owns the surface and should call cairo_surface_destroy() when done
* with it.
*
* This function always returns a valid pointer, but it will return a
* pointer to a "nil" surface if @other is already in an error state
* or any other error occurs.
*
* Since: 3.10
**/
cairo_surface_t *
gdk_window_create_similar_image_surface (GdkWindow * window,
cairo_format_t format,
int width,
int height,
int scale)
{
cairo_surface_t *window_surface, *surface;
GdkDisplay *display;
GdkScreen *screen;
g_return_val_if_fail (window ==NULL || GDK_IS_WINDOW (window), NULL);
if (window == NULL)
{
display = gdk_display_get_default ();
screen = gdk_display_get_default_screen (display);
window = gdk_screen_get_root_window (screen);
}
window_surface = gdk_window_ref_impl_surface (window);
if (scale == 0)
scale = gdk_window_get_scale_factor (window);
surface =
cairo_surface_create_similar_image (window_surface,
format,
width,
height);
cairo_surface_destroy (window_surface);
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_set_device_scale (surface, scale, scale);
#endif
return surface;
}
/**
* gdk_window_focus:
* @window: a #GdkWindow
@@ -10620,3 +10740,41 @@ gdk_window_get_frame_clock (GdkWindow *window)
return toplevel->frame_clock;
}
/**
* gdk_window_get_scale_factor:
* @window: window to get scale factor for
*
* Returns the internal scale factor that maps from window coordiantes
* to the actual device pixels. On traditional systems this is 1, but
* on very high density outputs this can be a higher value (often 2).
*
* A higher value means that drawing is automatically scaled up to
* a higher resolution, so any code doing drawing will automatically look
* nicer. However, if you are supplying pixel-based data the scale
* value can be used to determine whether to use a pixel resource
* with higher resolution data.
*
* The scale of a window may change during runtime, if this happens
* a configure event will be sent to the toplevel window.
*
* Since: 3.10
* Return value: the scale factor
*/
gint
gdk_window_get_scale_factor (GdkWindow *window)
{
GdkWindowImplClass *impl_class;
g_return_val_if_fail (GDK_IS_WINDOW (window), 1);
if (GDK_WINDOW_DESTROYED (window))
return 1;
impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
if (impl_class->get_scale_factor)
return impl_class->get_scale_factor (window);
return 1;
}
+16
View File
@@ -829,6 +829,9 @@ GDK_AVAILABLE_IN_ALL
void gdk_window_get_frame_extents (GdkWindow *window,
GdkRectangle *rect);
GDK_AVAILABLE_IN_3_10
gint gdk_window_get_scale_factor (GdkWindow *window);
#ifndef GDK_MULTIDEVICE_SAFE
GDK_DEPRECATED_IN_3_0_FOR(gdk_window_get_device_position)
GdkWindow * gdk_window_get_pointer (GdkWindow *window,
@@ -842,6 +845,12 @@ GdkWindow * gdk_window_get_device_position (GdkWindow *window,
gint *x,
gint *y,
GdkModifierType *mask);
GDK_AVAILABLE_IN_3_10
GdkWindow * gdk_window_get_device_position_double (GdkWindow *window,
GdkDevice *device,
gdouble *x,
gdouble *y,
GdkModifierType *mask);
GDK_AVAILABLE_IN_ALL
GdkWindow * gdk_window_get_parent (GdkWindow *window);
GDK_AVAILABLE_IN_ALL
@@ -908,6 +917,13 @@ cairo_surface_t *
cairo_content_t content,
int width,
int height);
GDK_AVAILABLE_IN_3_10
cairo_surface_t *
gdk_window_create_similar_image_surface (GdkWindow *window,
cairo_format_t format,
int width,
int height,
int scale);
GDK_AVAILABLE_IN_ALL
void gdk_window_beep (GdkWindow *window);
+4 -2
View File
@@ -98,8 +98,8 @@ struct _GdkWindowImplClass
gint *root_y);
gboolean (* get_device_state) (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask);
gboolean (* begin_paint_region) (GdkWindow *window,
const cairo_region_t *region);
@@ -285,6 +285,8 @@ struct _GdkWindowImplClass
gint n_elements);
void (*delete_property) (GdkWindow *window,
GdkAtom property);
gint (* get_scale_factor) (GdkWindow *window);
};
/* Interface Functions */
+16 -16
View File
@@ -58,10 +58,10 @@ static void gdk_quartz_device_core_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_quartz_device_core_grab (GdkDevice *device,
GdkWindow *window,
@@ -73,8 +73,8 @@ static GdkGrabStatus gdk_quartz_device_core_grab (GdkDevice *device,
static void gdk_quartz_device_core_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_quartz_device_core_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_quartz_device_core_select_window_events (GdkDevice *device,
@@ -181,8 +181,8 @@ gdk_quartz_device_core_set_window_cursor (GdkDevice *device,
static void
gdk_quartz_device_core_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
}
@@ -190,8 +190,8 @@ gdk_quartz_device_core_warp (GdkDevice *device,
static GdkWindow *
gdk_quartz_device_core_query_state_helper (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkWindow *toplevel;
@@ -260,10 +260,10 @@ gdk_quartz_device_core_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkWindow *found_window;
@@ -318,8 +318,8 @@ gdk_quartz_device_core_ungrab (GdkDevice *device,
static GdkWindow *
gdk_quartz_device_core_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
+30
View File
@@ -427,6 +427,35 @@ gdk_quartz_screen_get_monitor_workarea (GdkScreen *screen,
GDK_QUARTZ_RELEASE_POOL;
}
/* Protocol to build cleanly for OSX < 10.7 */
@protocol ScaleFactor
- (CGFloat) backingScaleFactor;
@end
gint
_gdk_quartz_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num)
{
GdkQuartzScreen *quartz_screen;
NSArray *array;
NSScreen *nsscreen;
gint scale_factor = 1;
quartz_screen = GDK_QUARTZ_SCREEN (screen);
GDK_QUARTZ_ALLOC_POOL;
array = [NSScreen screens];
nsscreen = [array objectAtIndex:monitor_num];
if (gdk_quartz_osx_version() >= GDK_OSX_LION)
scale_factor = [(id <ScaleFactor>) nsscreen backingScaleFactor];
GDK_QUARTZ_RELEASE_POOL;
return scale_factor;
}
static gchar *
gdk_quartz_screen_make_display_name (GdkScreen *screen)
{
@@ -491,4 +520,5 @@ gdk_quartz_screen_class_init (GdkQuartzScreenClass *klass)
screen_class->query_depths = _gdk_quartz_screen_query_depths;
screen_class->query_visual_types = _gdk_quartz_screen_query_visual_types;
screen_class->list_visuals = _gdk_quartz_screen_list_visuals;
screen_class->get_monitor_scale_factor = _gdk_quartz_screen_get_monitor_scale_factor;
}
+26 -105
View File
@@ -1818,8 +1818,8 @@ gdk_quartz_window_get_root_origin (GdkWindow *window,
static GdkWindow *
gdk_window_quartz_get_device_state_helper (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
NSPoint point;
@@ -1880,8 +1880,8 @@ gdk_window_quartz_get_device_state_helper (GdkWindow *window,
static gboolean
gdk_window_quartz_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
return gdk_window_quartz_get_device_state_helper (window,
@@ -1889,100 +1889,7 @@ gdk_window_quartz_get_device_state (GdkWindow *window,
x, y, mask) != NULL;
}
/* Returns coordinates relative to the root. */
void
_gdk_windowing_get_device_state (GdkDisplay *display,
GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask)
{
g_return_if_fail (display == _gdk_display);
*screen = _gdk_screen;
gdk_window_quartz_get_device_state_helper (_gdk_root, device, x, y, mask);
}
/* Returns coordinates relative to the found window. */
GdkWindow *
_gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
GdkWindow *found_window;
gint x, y;
GdkModifierType tmp_mask = 0;
found_window = gdk_window_quartz_get_device_state_helper (_gdk_root,
display->core_pointer,
&x, &y,
&tmp_mask);
if (found_window)
{
/* The coordinates returned above are relative the root, we want
* coordinates relative the window here.
*/
while (found_window != _gdk_root)
{
x -= found_window->x;
y -= found_window->y;
found_window = found_window->parent;
}
*win_x = x;
*win_y = y;
}
else
{
/* Mimic the X backend here, -1,-1 for unknown windows. */
*win_x = -1;
*win_y = -1;
}
if (mask)
*mask = tmp_mask;
if (get_toplevel)
{
/* Requested toplevel, find it. */
/* TODO: This can be implemented more efficient by never
recursing into children in the first place */
if (found_window)
{
/* Convert to toplevel */
while (found_window->parent != NULL &&
found_window->parent->window_type != GDK_WINDOW_ROOT)
{
*win_x += found_window->x;
*win_y += found_window->y;
found_window = found_window->parent;
}
}
}
return found_window;
}
GdkWindow*
_gdk_windowing_window_at_device_position (GdkDisplay *display,
GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
return GDK_DEVICE_GET_CLASS (device)->window_at_position (device,
win_x, win_y,
mask,
get_toplevel);
}
static GdkEventMask
static GdkEventMask
gdk_window_quartz_get_events (GdkWindow *window)
{
if (GDK_WINDOW_DESTROYED (window))
@@ -2683,13 +2590,6 @@ gdk_quartz_window_set_functions (GdkWindow *window,
/* FIXME: Implement */
}
gboolean
_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
cairo_region_t *area)
{
return FALSE;
}
static void
gdk_quartz_window_stick (GdkWindow *window)
{
@@ -3001,6 +2901,26 @@ gdk_quartz_window_get_input_shape (GdkWindow *window)
return NULL;
}
/* Protocol to build cleanly for OSX < 10.7 */
@protocol ScaleFactor
- (CGFloat) backingScaleFactor;
@end
static gint
gdk_quartz_window_get_scale_factor (GdkWindow *window)
{
GdkWindowImplQuartz *impl;
if (GDK_WINDOW_DESTROYED (window))
return 1;
impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
if (gdk_quartz_osx_version() >= GDK_OSX_LION)
return [(id <ScaleFactor>) impl->toplevel backingScaleFactor];
return 1;
}
static void
gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
@@ -3040,6 +2960,7 @@ gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
impl_class->get_input_shape = gdk_quartz_window_get_input_shape;
impl_class->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
impl_class->end_paint = gdk_window_impl_quartz_end_paint;
impl_class->get_scale_factor = gdk_quartz_window_get_scale_factor;
impl_class->focus = gdk_quartz_window_focus;
impl_class->set_type_hint = gdk_quartz_window_set_type_hint;
+12 -12
View File
@@ -135,14 +135,14 @@ gdk_wayland_device_get_state (GdkDevice *device,
gdouble *axes,
GdkModifierType *mask)
{
gint x_int, y_int;
gdouble x, y;
gdk_window_get_device_position (window, device, &x_int, &y_int, mask);
gdk_window_get_device_position_double (window, device, &x, &y, mask);
if (axes)
{
axes[0] = x_int;
axes[1] = y_int;
axes[0] = x;
axes[1] = y;
}
}
@@ -228,8 +228,8 @@ gdk_wayland_device_set_window_cursor (GdkDevice *device,
static void
gdk_wayland_device_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
}
@@ -238,10 +238,10 @@ gdk_wayland_device_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkWaylandDeviceData *wd;
@@ -345,8 +345,8 @@ gdk_wayland_device_ungrab (GdkDevice *device,
static GdkWindow *
gdk_wayland_device_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
+2 -2
View File
@@ -168,8 +168,8 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id
wl_registry_bind(display_wayland->wl_registry, id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_output") == 0) {
output =
wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 1);
_gdk_wayland_screen_add_output(display_wayland->screen, id, output);
wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 2);
_gdk_wayland_screen_add_output(display_wayland->screen, id, output, version);
/* We need another roundtrip to receive the modes and geometry
* events for the output, which gives us the physical properties
* and available modes on the output. */
+4 -1
View File
@@ -161,11 +161,14 @@ GdkWindow *_gdk_wayland_screen_create_root_window (GdkScreen *screen,
GdkScreen *_gdk_wayland_screen_new (GdkDisplay *display);
void _gdk_wayland_screen_add_output (GdkScreen *screen,
guint32 id,
struct wl_output *output);
struct wl_output *output,
guint32 version);
void _gdk_wayland_screen_remove_output (GdkScreen *screen,
guint32 id);
int _gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen,
struct wl_output *output);
guint32 _gdk_wayland_screen_get_output_scale (GdkScreen *screen,
struct wl_output *output);
void _gdk_wayland_window_set_device_grabbed (GdkWindow *window,
GdkDevice *device,
+71 -5
View File
@@ -77,10 +77,13 @@ struct _GdkWaylandScreenClass
void (* window_manager_changed) (GdkWaylandScreen *screen_wayland);
};
#define OUTPUT_VERSION_WITH_DONE 2
struct _GdkWaylandMonitor
{
GdkWaylandScreen *screen;
guint32 id;
guint32 version;
struct wl_output *output;
GdkRectangle geometry;
int width_mm;
@@ -88,6 +91,7 @@ struct _GdkWaylandMonitor
char * output_name;
char * manufacturer;
int refresh_rate;
gint scale;
};
G_DEFINE_TYPE (GdkWaylandScreen, _gdk_wayland_screen, GDK_TYPE_SCREEN)
@@ -249,6 +253,21 @@ gdk_wayland_screen_get_monitor_geometry (GdkScreen *screen,
*dest = monitor->geometry;
}
static gint
gdk_wayland_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num)
{
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
GdkWaylandMonitor *monitor;
if (monitor_num >= screen_wayland->monitors->len)
return 1;
monitor = g_ptr_array_index(screen_wayland->monitors, monitor_num);
return monitor->scale;
}
static GdkVisual *
gdk_wayland_screen_get_system_visual (GdkScreen * screen)
{
@@ -822,6 +841,7 @@ _gdk_wayland_screen_class_init (GdkWaylandScreenClass *klass)
screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_wayland_screen_get_monitor_geometry;
screen_class->get_monitor_scale_factor = gdk_wayland_screen_get_monitor_scale_factor;
screen_class->get_system_visual = gdk_wayland_screen_get_system_visual;
screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual;
screen_class->is_composited = gdk_wayland_screen_is_composited;
@@ -888,13 +908,33 @@ output_handle_geometry(void *data,
monitor->manufacturer = g_strdup (make);
monitor->output_name = g_strdup (model);
if (monitor->geometry.width != 0)
if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
{
g_signal_emit_by_name (monitor->screen, "monitors-changed");
update_screen_size (monitor->screen);
}
}
static void
output_handle_done(void *data,
struct wl_output *wl_output)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
g_signal_emit_by_name (monitor->screen, "monitors-changed");
update_screen_size (monitor->screen);
}
static void
output_handle_scale(void *data,
struct wl_output *wl_output,
int32_t factor)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
monitor->scale = factor;
}
static void
output_handle_mode(void *data,
struct wl_output *wl_output,
@@ -912,27 +952,35 @@ output_handle_mode(void *data,
monitor->geometry.height = height;
monitor->refresh_rate = refresh;
g_signal_emit_by_name (monitor->screen, "monitors-changed");
update_screen_size (monitor->screen);
if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
{
g_signal_emit_by_name (monitor->screen, "monitors-changed");
update_screen_size (monitor->screen);
}
}
static const struct wl_output_listener output_listener =
{
output_handle_geometry,
output_handle_mode
output_handle_mode,
output_handle_done,
output_handle_scale,
};
void
_gdk_wayland_screen_add_output (GdkScreen *screen,
guint32 id,
struct wl_output *output)
struct wl_output *output,
guint32 version)
{
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
GdkWaylandMonitor *monitor = g_new0(GdkWaylandMonitor, 1);
monitor->id = id;
monitor->output = output;
monitor->version = version;
monitor->screen = screen_wayland;
monitor->scale = 1;
g_ptr_array_add(screen_wayland->monitors, monitor);
wl_output_add_listener(output, &output_listener, monitor);
@@ -977,3 +1025,21 @@ _gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen,
return 0;
}
guint32
_gdk_wayland_screen_get_output_scale (GdkScreen *screen,
struct wl_output *output)
{
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
int i;
for (i = 0; i < screen_wayland->monitors->len; i++)
{
GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
if (monitor->output == output)
return monitor->scale;
}
return 0;
}
+88 -12
View File
@@ -145,6 +145,7 @@ struct _GdkWindowImplWayland
gboolean use_custom_surface;
guint32 scale;
gboolean pending_commit;
gint64 pending_frame_counter;
};
@@ -154,11 +155,15 @@ struct _GdkWindowImplWaylandClass
GdkWindowImplClass parent_class;
};
static void gdk_wayland_window_configure (GdkWindow *window,
int width, int height, int edges);
G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
static void
_gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
{
impl->scale = 1;
}
void
@@ -391,6 +396,7 @@ typedef struct _GdkWaylandCairoSurfaceData {
struct wl_buffer *buffer;
GdkWaylandDisplay *display;
int32_t width, height;
uint32_t scale;
gboolean busy;
} GdkWaylandCairoSurfaceData;
@@ -419,6 +425,44 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
data->busy = TRUE;
}
static void
window_update_scale (GdkWindow *window)
{
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
guint32 scale;
GSList *l;
scale = 1;
for (l = impl->outputs; l != NULL; l = l->next)
{
guint32 output_scale =
_gdk_wayland_screen_get_output_scale (wayland_display->screen,
l->data);
scale = MAX (scale, output_scale);
}
#ifndef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
/* Don't announce a scale if we can't support it */
scale = 1;
#endif
if (scale != impl->scale)
{
impl->scale = scale;
/* Notify app that scale changed */
gdk_wayland_window_configure (window, window->width, window->height, impl->resize_edges);
}
}
static void
on_monitors_changed (GdkScreen *screen,
GdkWindow *window)
{
window_update_scale (window);
}
void
_gdk_wayland_display_create_window_impl (GdkDisplay *display,
GdkWindow *window,
@@ -449,6 +493,9 @@ _gdk_wayland_display_create_window_impl (GdkDisplay *display,
g_object_ref (window);
/* More likely to be right than just assuming 1 */
impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
impl->title = NULL;
switch (GDK_WINDOW_TYPE (window))
@@ -477,6 +524,9 @@ _gdk_wayland_display_create_window_impl (GdkDisplay *display,
G_CALLBACK (on_frame_clock_before_paint), window);
g_signal_connect (frame_clock, "after-paint",
G_CALLBACK (on_frame_clock_after_paint), window);
g_signal_connect (screen, "monitors-changed",
G_CALLBACK (on_monitors_changed), window);
}
static void
@@ -528,6 +578,8 @@ gdk_wayland_window_attach_image (GdkWindow *window)
/* Attach this new buffer to the surface */
wl_surface_attach (impl->surface, data->buffer, dx, dy);
wl_surface_set_buffer_scale (impl->surface, data->scale);
impl->pending_commit = TRUE;
}
@@ -609,7 +661,7 @@ static const struct wl_buffer_listener buffer_listener = {
static cairo_surface_t *
gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
int width, int height)
int width, int height, guint scale)
{
GdkWaylandCairoSurfaceData *data;
cairo_surface_t *surface = NULL;
@@ -621,29 +673,34 @@ gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
data->buffer = NULL;
data->width = width;
data->height = height;
data->scale = scale;
data->busy = FALSE;
stride = width * 4;
data->pool = _create_shm_pool (display->shm,
width, height,
width*scale, height*scale,
&data->buf_length,
&data->buf);
data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
width, height,
stride, WL_SHM_FORMAT_ARGB8888);
width*scale, height*scale,
stride*scale, WL_SHM_FORMAT_ARGB8888);
wl_buffer_add_listener (data->buffer, &buffer_listener, data);
surface = cairo_image_surface_create_for_data (data->buf,
CAIRO_FORMAT_ARGB32,
width,
height,
stride);
width*scale,
height*scale,
stride*scale);
cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
data, gdk_wayland_cairo_surface_destroy);
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_set_device_scale (surface, scale, scale);
#endif
status = cairo_surface_status (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
@@ -665,8 +722,9 @@ gdk_wayland_window_ensure_cairo_surface (GdkWindow *window)
impl->cairo_surface =
gdk_wayland_create_cairo_surface (display_wayland,
impl->wrapper->width,
impl->wrapper->height);
impl->wrapper->width,
impl->wrapper->height,
impl->scale);
}
}
@@ -727,7 +785,7 @@ gdk_wayland_window_configure (GdkWindow *window,
display = gdk_window_get_display (window);
/* TODO: Only generate a configure event if width or height have actually
/* TODO: Only generate a configure event if width/height/scale have actually
* changed?
*/
event = gdk_event_new (GDK_CONFIGURE);
@@ -841,6 +899,8 @@ surface_enter (void *data,
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
impl->outputs = g_slist_prepend (impl->outputs, output);
window_update_scale (window);
}
static void
@@ -852,8 +912,11 @@ surface_leave (void *data,
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
impl->outputs = g_slist_remove (impl->outputs, output);
window_update_scale (window);
}
static void
shell_surface_handle_configure(void *data,
struct wl_shell_surface *shell_surface,
@@ -1174,8 +1237,8 @@ gdk_window_wayland_get_root_coords (GdkWindow *window,
static gboolean
gdk_window_wayland_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
gboolean return_val;
@@ -1905,6 +1968,18 @@ gdk_wayland_window_delete_property (GdkWindow *window,
{
}
static gint
gdk_wayland_window_get_scale_factor (GdkWindow *window)
{
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
if (GDK_WINDOW_DESTROYED (window))
return 1;
return impl->scale;
}
static void
_gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
{
@@ -1991,6 +2066,7 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
impl_class->get_property = gdk_wayland_window_get_property;
impl_class->change_property = gdk_wayland_window_change_property;
impl_class->delete_property = gdk_wayland_window_delete_property;
impl_class->get_scale_factor = gdk_wayland_window_get_scale_factor;
}
+12 -12
View File
@@ -47,10 +47,10 @@ static void gdk_device_virtual_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_device_virtual_grab (GdkDevice *device,
GdkWindow *window,
@@ -62,8 +62,8 @@ static GdkGrabStatus gdk_device_virtual_grab (GdkDevice *device,
static void gdk_device_virtual_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_device_virtual_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_device_virtual_select_window_events (GdkDevice *device,
@@ -245,10 +245,10 @@ gdk_device_virtual_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkDeviceVirtual *virtual = GDK_DEVICE_VIRTUAL (device);
@@ -342,8 +342,8 @@ screen_to_client (HWND hwnd, POINT screen_pt, POINT *client_pt)
static GdkWindow *
gdk_device_virtual_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
+14 -14
View File
@@ -47,10 +47,10 @@ static void gdk_device_win32_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_device_win32_grab (GdkDevice *device,
GdkWindow *window,
@@ -62,8 +62,8 @@ static GdkGrabStatus gdk_device_win32_grab (GdkDevice *device,
static void gdk_device_win32_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_device_win32_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_device_win32_select_window_events (GdkDevice *device,
@@ -138,8 +138,8 @@ gdk_device_win32_set_window_cursor (GdkDevice *device,
static void
gdk_device_win32_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
}
@@ -174,10 +174,10 @@ gdk_device_win32_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
POINT point;
@@ -259,8 +259,8 @@ screen_to_client (HWND hwnd, POINT screen_pt, POINT *client_pt)
static GdkWindow *
gdk_device_win32_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
+12 -12
View File
@@ -46,10 +46,10 @@ static void gdk_device_wintab_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_device_wintab_grab (GdkDevice *device,
GdkWindow *window,
@@ -61,8 +61,8 @@ static GdkGrabStatus gdk_device_wintab_grab (GdkDevice *device,
static void gdk_device_wintab_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_device_wintab_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_device_wintab_select_window_events (GdkDevice *device,
@@ -180,10 +180,10 @@ gdk_device_wintab_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkDeviceWintab *device_wintab;
@@ -268,8 +268,8 @@ gdk_device_wintab_ungrab (GdkDevice *device,
static GdkWindow *
gdk_device_wintab_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
-6
View File
@@ -33,12 +33,6 @@
#undef HAVE_MONITOR_INFO
#endif
void
_gdk_windowing_set_default_display (GdkDisplay *display)
{
g_assert (display == NULL || _gdk_display == display);
}
static gulong
gdk_win32_display_get_next_serial (GdkDisplay *display)
{
+2 -34
View File
@@ -2128,8 +2128,8 @@ gdk_win32_window_get_frame_extents (GdkWindow *window,
static gboolean
gdk_window_win32_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkWindow *child;
@@ -2143,27 +2143,6 @@ gdk_window_win32_get_device_state (GdkWindow *window,
return (child != NULL);
}
void
_gdk_windowing_get_device_state (GdkDisplay *display,
GdkDevice *device,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask)
{
g_return_if_fail (display == _gdk_display);
if (screen)
*screen = _gdk_screen;
GDK_DEVICE_GET_CLASS (device)->query_state (device,
gdk_screen_get_root_window (_gdk_screen),
NULL, NULL,
x, y,
NULL, NULL,
mask);
}
void
gdk_display_warp_device (GdkDisplay *display,
GdkDevice *device,
@@ -2179,17 +2158,6 @@ gdk_display_warp_device (GdkDisplay *display,
GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
}
GdkWindow*
_gdk_windowing_window_at_device_position (GdkDisplay *display,
GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
return GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
}
static GdkEventMask
gdk_win32_window_get_events (GdkWindow *window)
{
+49 -31
View File
@@ -17,6 +17,7 @@
#include "config.h"
#include "gdkx11device-core.h"
#include "gdkdeviceprivate.h"
@@ -25,6 +26,11 @@
#include "gdkprivate-x11.h"
#include "gdkasync.h"
#include <math.h>
/* for the use of round() */
#include "fallback-c89.c"
struct _GdkX11DeviceCore
{
GdkDevice parent_instance;
@@ -50,16 +56,16 @@ static void gdk_x11_device_core_set_window_cursor (GdkDevice *device,
GdkCursor *cursor);
static void gdk_x11_device_core_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
gdouble x,
gdouble y);
static void gdk_x11_device_core_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_x11_device_core_grab (GdkDevice *device,
GdkWindow *window,
@@ -71,8 +77,8 @@ static GdkGrabStatus gdk_x11_device_core_grab (GdkDevice *device,
static void gdk_x11_device_core_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_x11_device_core_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_x11_device_core_select_window_events (GdkDevice *device,
@@ -135,10 +141,12 @@ gdk_x11_device_core_get_history (GdkDevice *device,
XTimeCoord *xcoords;
GdkTimeCoord **coords;
GdkWindow *impl_window;
GdkWindowImplX11 *impl;
int tmp_n_events;
int i, j;
impl_window = _gdk_window_get_impl_window (window);
impl = GDK_WINDOW_IMPL_X11 (impl_window->impl);
xcoords = XGetMotionEvents (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (impl_window),
start, stop, &tmp_n_events);
@@ -149,11 +157,13 @@ gdk_x11_device_core_get_history (GdkDevice *device,
for (i = 0, j = 0; i < tmp_n_events; i++)
{
if (impl_coord_in_window (window, xcoords[i].x, xcoords[i].y))
if (impl_coord_in_window (window,
xcoords[i].x / impl->window_scale,
xcoords[i].y / impl->window_scale))
{
coords[j]->time = xcoords[i].time;
coords[j]->axes[0] = xcoords[i].x - window->abs_x;
coords[j]->axes[1] = xcoords[i].y - window->abs_y;
coords[j]->axes[0] = (double)xcoords[i].x / impl->window_scale - window->abs_x;
coords[j]->axes[1] = (double)xcoords[i].y / impl->window_scale - window->abs_y;
j++;
}
}
@@ -192,14 +202,14 @@ gdk_x11_device_core_get_state (GdkDevice *device,
gdouble *axes,
GdkModifierType *mask)
{
gint x_int, y_int;
gdouble x, y;
gdk_window_get_device_position (window, device, &x_int, &y_int, mask);
gdk_window_get_device_position_double (window, device, &x, &y, mask);
if (axes)
{
axes[0] = x_int;
axes[1] = y_int;
axes[0] = x;
axes[1] = y;
}
}
@@ -223,8 +233,8 @@ gdk_x11_device_core_set_window_cursor (GdkDevice *device,
static void
gdk_x11_device_core_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
Display *xdisplay;
Window dest;
@@ -232,7 +242,9 @@ gdk_x11_device_core_warp (GdkDevice *device,
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_device_get_display (device));
dest = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0,
round (x * GDK_X11_SCREEN (screen)->window_scale),
round (y * GDK_X11_SCREEN (screen)->window_scale));
}
static void
@@ -240,12 +252,13 @@ gdk_x11_device_core_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
GdkDisplay *display;
GdkScreen *default_screen;
Window xroot_window, xchild_window;
@@ -291,16 +304,16 @@ gdk_x11_device_core_query_state (GdkDevice *device,
*child_window = gdk_x11_window_lookup_for_display (display, xchild_window);
if (root_x)
*root_x = xroot_x;
*root_x = (double)xroot_x / impl->window_scale;
if (root_y)
*root_y = xroot_y;
*root_y = (double)xroot_y / impl->window_scale;
if (win_x)
*win_x = xwin_x;
*win_x = (double)xwin_x / impl->window_scale;
if (win_y)
*win_y = xwin_y;
*win_y = (double)xwin_y / impl->window_scale;
if (mask)
*mask = xmask;
@@ -408,11 +421,12 @@ gdk_x11_device_core_ungrab (GdkDevice *device,
static GdkWindow *
gdk_x11_device_core_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
GdkWindowImplX11 *impl;
GdkDisplay *display;
GdkScreen *screen;
Display *xdisplay;
@@ -464,6 +478,7 @@ gdk_x11_device_core_window_at_position (GdkDevice *device,
for (list = toplevels; list != NULL; list = g_list_next (list))
{
window = GDK_WINDOW (list->data);
impl = GDK_WINDOW_IMPL_X11 (window->impl);
xwindow = GDK_WINDOW_XID (window);
gdk_x11_display_error_trap_push (display);
XQueryPointer (xdisplay, xwindow,
@@ -479,7 +494,7 @@ gdk_x11_device_core_window_at_position (GdkDevice *device,
break;
}
gdk_window_get_geometry (window, NULL, NULL, &width, &height);
if (winx >= 0 && winy >= 0 && winx < width && winy < height)
if (winx >= 0 && winy >= 0 && winx < width * impl->window_scale && winy < height * impl->window_scale)
{
/* A childless toplevel, or below another window? */
XSetWindowAttributes attributes;
@@ -532,12 +547,15 @@ gdk_x11_device_core_window_at_position (GdkDevice *device,
gdk_x11_display_ungrab (display);
window = gdk_x11_window_lookup_for_display (display, last);
impl = NULL;
if (window)
impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (win_x)
*win_x = (window) ? xwin_x : -1;
*win_x = (window) ? (double)xwin_x / impl->window_scale : -1;
if (win_y)
*win_y = (window) ? xwin_y : -1;
*win_y = (window) ? (double)xwin_y / impl->window_scale : -1;
if (mask)
*mask = xmask;
+34 -23
View File
@@ -29,6 +29,10 @@
#include <X11/Xutil.h>
#include <X11/extensions/XInput2.h>
#include <math.h>
/* for the use of round() */
#include "fallback-c89.c"
typedef struct _ScrollValuator ScrollValuator;
@@ -76,16 +80,16 @@ static void gdk_x11_device_xi2_set_window_cursor (GdkDevice *device,
GdkCursor *cursor);
static void gdk_x11_device_xi2_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
gdouble x,
gdouble y);
static void gdk_x11_device_xi2_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_x11_device_xi2_grab (GdkDevice *device,
@@ -99,8 +103,8 @@ static void gdk_x11_device_xi2_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_x11_device_xi2_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_x11_device_xi2_select_window_events (GdkDevice *device,
@@ -292,8 +296,8 @@ gdk_x11_device_xi2_set_window_cursor (GdkDevice *device,
static void
gdk_x11_device_xi2_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
gdouble x,
gdouble y)
{
GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device);
Window dest;
@@ -303,7 +307,9 @@ gdk_x11_device_xi2_warp (GdkDevice *device,
XIWarpPointer (GDK_SCREEN_XDISPLAY (screen),
device_xi2->device_id,
None, dest,
0, 0, 0, 0, x, y);
0, 0, 0, 0,
round (x * GDK_X11_SCREEN(screen)->window_scale),
round (y * GDK_X11_SCREEN(screen)->window_scale));
}
static void
@@ -311,12 +317,13 @@ gdk_x11_device_xi2_query_state (GdkDevice *device,
GdkWindow *window,
GdkWindow **root_window,
GdkWindow **child_window,
gint *root_x,
gint *root_y,
gint *win_x,
gint *win_y,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device);
GdkDisplay *display;
GdkScreen *default_screen;
@@ -381,16 +388,16 @@ gdk_x11_device_xi2_query_state (GdkDevice *device,
*child_window = gdk_x11_window_lookup_for_display (display, xchild_window);
if (root_x)
*root_x = (gint) xroot_x;
*root_x = xroot_x / impl->window_scale;
if (root_y)
*root_y = (gint) xroot_y;
*root_y = xroot_y / impl->window_scale;
if (win_x)
*win_x = (gint) xwin_x;
*win_x = xwin_x / impl->window_scale;
if (win_y)
*win_y = (gint) xwin_y;
*win_y = xwin_y / impl->window_scale;
if (mask)
*mask = _gdk_x11_device_xi2_translate_state (&mod_state, &button_state, &group_state);
@@ -474,11 +481,12 @@ gdk_x11_device_xi2_ungrab (GdkDevice *device,
static GdkWindow *
gdk_x11_device_xi2_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
GdkWindowImplX11 *impl;
GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device);
GdkDisplay *display;
GdkScreen *screen;
@@ -624,12 +632,15 @@ gdk_x11_device_xi2_window_at_position (GdkDevice *device,
gdk_x11_display_ungrab (display);
window = gdk_x11_window_lookup_for_display (display, last);
impl = NULL;
if (window)
impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (win_x)
*win_x = (window) ? (gint) xwin_x : -1;
*win_x = (window) ? (xwin_x / impl->window_scale) : -1;
if (win_y)
*win_y = (window) ? (gint) xwin_y : -1;
*win_y = (window) ? (xwin_y / impl->window_scale) : -1;
if (mask)
*mask = _gdk_x11_device_xi2_translate_state (&mod_state, &button_state, &group_state);
+30 -24
View File
@@ -332,9 +332,11 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
GdkEvent *event,
XEvent *xevent)
{
GdkWindowImplX11 *impl;
GdkX11DeviceManagerCore *device_manager;
GdkWindow *window;
gboolean return_val;
int scale;
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
device_manager = GDK_X11_DEVICE_MANAGER_CORE (translator);
@@ -342,14 +344,18 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
window = get_event_window (translator, xevent);
scale = 1;
if (window)
{
if (GDK_WINDOW_DESTROYED (window) || !GDK_IS_WINDOW (window))
return FALSE;
g_object_ref (window);
impl = GDK_WINDOW_IMPL_X11 (window->impl);
scale = impl->window_scale;
}
event->any.window = window;
event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
@@ -458,10 +464,10 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
event->scroll.window = window;
event->scroll.time = xevent->xbutton.time;
event->scroll.x = (gdouble) xevent->xbutton.x;
event->scroll.y = (gdouble) xevent->xbutton.y;
event->scroll.x_root = (gdouble) xevent->xbutton.x_root;
event->scroll.y_root = (gdouble) xevent->xbutton.y_root;
event->scroll.x = (gdouble) xevent->xbutton.x / scale;
event->scroll.y = (gdouble) xevent->xbutton.y / scale;
event->scroll.x_root = (gdouble) xevent->xbutton.x_root / scale;
event->scroll.y_root = (gdouble) xevent->xbutton.y_root / scale;
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
event->scroll.device = device_manager->core_pointer;
@@ -480,10 +486,10 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
event->button.type = GDK_BUTTON_PRESS;
event->button.window = window;
event->button.time = xevent->xbutton.time;
event->button.x = (gdouble) xevent->xbutton.x;
event->button.y = (gdouble) xevent->xbutton.y;
event->button.x_root = (gdouble) xevent->xbutton.x_root;
event->button.y_root = (gdouble) xevent->xbutton.y_root;
event->button.x = (gdouble) xevent->xbutton.x / scale;
event->button.y = (gdouble) xevent->xbutton.y / scale;
event->button.x_root = (gdouble) xevent->xbutton.x_root / scale;
event->button.y_root = (gdouble) xevent->xbutton.y_root / scale;
event->button.axes = NULL;
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
@@ -523,10 +529,10 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
event->button.type = GDK_BUTTON_RELEASE;
event->button.window = window;
event->button.time = xevent->xbutton.time;
event->button.x = (gdouble) xevent->xbutton.x;
event->button.y = (gdouble) xevent->xbutton.y;
event->button.x_root = (gdouble) xevent->xbutton.x_root;
event->button.y_root = (gdouble) xevent->xbutton.y_root;
event->button.x = (gdouble) xevent->xbutton.x / scale;
event->button.y = (gdouble) xevent->xbutton.y / scale;
event->button.x_root = (gdouble) xevent->xbutton.x_root / scale;
event->button.y_root = (gdouble) xevent->xbutton.y_root / scale;
event->button.axes = NULL;
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
@@ -553,10 +559,10 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
event->motion.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = xevent->xmotion.time;
event->motion.x = (gdouble) xevent->xmotion.x;
event->motion.y = (gdouble) xevent->xmotion.y;
event->motion.x_root = (gdouble) xevent->xmotion.x_root;
event->motion.y_root = (gdouble) xevent->xmotion.y_root;
event->motion.x = (gdouble) xevent->xmotion.x / scale;
event->motion.y = (gdouble) xevent->xmotion.y / scale;
event->motion.x_root = (gdouble) xevent->xmotion.x_root / scale;
event->motion.y_root = (gdouble) xevent->xmotion.y_root / scale;
event->motion.axes = NULL;
event->motion.state = (GdkModifierType) xevent->xmotion.state;
event->motion.is_hint = xevent->xmotion.is_hint;
@@ -602,10 +608,10 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
event->crossing.x = (gdouble) xevent->xcrossing.x;
event->crossing.y = (gdouble) xevent->xcrossing.y;
event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
event->crossing.x = (gdouble) xevent->xcrossing.x / scale;
event->crossing.y = (gdouble) xevent->xcrossing.y / scale;
event->crossing.x_root = (gdouble) xevent->xcrossing.x_root / scale;
event->crossing.y_root = (gdouble) xevent->xcrossing.y_root / scale;
event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
@@ -646,10 +652,10 @@ gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
event->crossing.x = (gdouble) xevent->xcrossing.x;
event->crossing.y = (gdouble) xevent->xcrossing.y;
event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
event->crossing.x = (gdouble) xevent->xcrossing.x / scale;
event->crossing.y = (gdouble) xevent->xcrossing.y / scale;
event->crossing.x_root = (gdouble) xevent->xcrossing.x_root / scale;
event->crossing.y_root = (gdouble) xevent->xcrossing.y_root / scale;
event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
+37 -28
View File
@@ -1113,6 +1113,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
XGenericEventCookie *cookie;
gboolean return_val = TRUE;
GdkWindow *window;
GdkWindowImplX11 *impl;
int scale;
XIEvent *ev;
device_manager = (GdkX11DeviceManagerXI2 *) translator;
@@ -1134,6 +1136,13 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
if (window && GDK_WINDOW_DESTROYED (window))
return FALSE;
scale = 1;
if (window)
{
impl = GDK_WINDOW_IMPL_X11 (window->impl);
scale = impl->window_scale;
}
if (ev->evtype == XI_Motion ||
ev->evtype == XI_ButtonRelease)
{
@@ -1230,10 +1239,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->scroll.window = window;
event->scroll.time = xev->time;
event->scroll.x = (gdouble) xev->event_x;
event->scroll.y = (gdouble) xev->event_y;
event->scroll.x_root = (gdouble) xev->root_x;
event->scroll.y_root = (gdouble) xev->root_y;
event->scroll.x = (gdouble) xev->event_x / scale;
event->scroll.y = (gdouble) xev->event_y / scale;
event->scroll.x_root = (gdouble) xev->root_x / scale;
event->scroll.y_root = (gdouble) xev->root_y / scale;
event->scroll.delta_x = 0;
event->scroll.delta_y = 0;
@@ -1257,10 +1266,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->button.window = window;
event->button.time = xev->time;
event->button.x = (gdouble) xev->event_x;
event->button.y = (gdouble) xev->event_y;
event->button.x_root = (gdouble) xev->root_x;
event->button.y_root = (gdouble) xev->root_y;
event->button.x = (gdouble) xev->event_x / scale;
event->button.y = (gdouble) xev->event_y / scale;
event->button.x_root = (gdouble) xev->root_x / scale;
event->button.y_root = (gdouble) xev->root_y / scale;
event->button.device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (xev->deviceid));
@@ -1348,10 +1357,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->scroll.window = window;
event->scroll.time = xev->time;
event->scroll.x = (gdouble) xev->event_x;
event->scroll.y = (gdouble) xev->event_y;
event->scroll.x_root = (gdouble) xev->root_x;
event->scroll.y_root = (gdouble) xev->root_y;
event->scroll.x = (gdouble) xev->event_x / scale;
event->scroll.y = (gdouble) xev->event_y / scale;
event->scroll.x_root = (gdouble) xev->root_x / scale;
event->scroll.y_root = (gdouble) xev->root_y / scale;
event->scroll.delta_x = delta_x;
event->scroll.delta_y = delta_y;
@@ -1365,10 +1374,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->motion.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = xev->time;
event->motion.x = (gdouble) xev->event_x;
event->motion.y = (gdouble) xev->event_y;
event->motion.x_root = (gdouble) xev->root_x;
event->motion.y_root = (gdouble) xev->root_y;
event->motion.x = (gdouble) xev->event_x / scale;
event->motion.y = (gdouble) xev->event_y / scale;
event->motion.x_root = (gdouble) xev->root_x / scale;
event->motion.y_root = (gdouble) xev->root_y / scale;
event->motion.device = device;
gdk_event_set_source_device (event, source_device);
@@ -1421,10 +1430,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->touch.window = window;
event->touch.time = xev->time;
event->touch.x = (gdouble) xev->event_x;
event->touch.y = (gdouble) xev->event_y;
event->touch.x_root = (gdouble) xev->root_x;
event->touch.y_root = (gdouble) xev->root_y;
event->touch.x = (gdouble) xev->event_x / scale;
event->touch.y = (gdouble) xev->event_y / scale;
event->touch.x_root = (gdouble) xev->root_x / scale;
event->touch.y_root = (gdouble) xev->root_y / scale;
event->touch.device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (xev->deviceid));
@@ -1490,10 +1499,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->touch.sequence = GUINT_TO_POINTER (xev->detail);
event->touch.type = GDK_TOUCH_UPDATE;
event->touch.time = xev->time;
event->touch.x = (gdouble) xev->event_x;
event->touch.y = (gdouble) xev->event_y;
event->touch.x_root = (gdouble) xev->root_x;
event->touch.y_root = (gdouble) xev->root_y;
event->touch.x = (gdouble) xev->event_x / scale;
event->touch.y = (gdouble) xev->event_y / scale;
event->touch.x_root = (gdouble) xev->root_x / scale;
event->touch.y_root = (gdouble) xev->root_y / scale;
event->touch.device = g_hash_table_lookup (device_manager->id_table,
GINT_TO_POINTER (xev->deviceid));
@@ -1538,10 +1547,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
event->crossing.x = (gdouble) xev->event_x;
event->crossing.y = (gdouble) xev->event_y;
event->crossing.x_root = (gdouble) xev->root_x;
event->crossing.y_root = (gdouble) xev->root_y;
event->crossing.x = (gdouble) xev->event_x / scale;
event->crossing.y = (gdouble) xev->event_y / scale;
event->crossing.x_root = (gdouble) xev->root_x / scale;
event->crossing.y_root = (gdouble) xev->root_y / scale;
event->crossing.time = xev->time;
event->crossing.focus = xev->focus;
+36 -22
View File
@@ -558,11 +558,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
{
GdkRectangle expose_rect;
int x2, y2;
expose_rect.x = xevent->xexpose.x;
expose_rect.y = xevent->xexpose.y;
expose_rect.width = xevent->xexpose.width;
expose_rect.height = xevent->xexpose.height;
expose_rect.x = xevent->xexpose.x / window_impl->window_scale;
expose_rect.y = xevent->xexpose.y / window_impl->window_scale;
x2 = (xevent->xexpose.x + xevent->xexpose.width + window_impl->window_scale -1) / window_impl->window_scale;
expose_rect.width = x2 - expose_rect.x;
y2 = (xevent->xexpose.y + xevent->xexpose.height + window_impl->window_scale -1) / window_impl->window_scale;
expose_rect.height = y2 - expose_rect.y;
_gdk_x11_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
return_val = FALSE;
@@ -573,6 +578,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
case GraphicsExpose:
{
GdkRectangle expose_rect;
int x2, y2;
GDK_NOTE (EVENTS,
g_message ("graphics expose:\tdrawable: %ld",
@@ -584,10 +590,14 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
break;
}
expose_rect.x = xevent->xgraphicsexpose.x;
expose_rect.y = xevent->xgraphicsexpose.y;
expose_rect.width = xevent->xgraphicsexpose.width;
expose_rect.height = xevent->xgraphicsexpose.height;
expose_rect.x = xevent->xgraphicsexpose.x / window_impl->window_scale;
expose_rect.y = xevent->xgraphicsexpose.y / window_impl->window_scale;
x2 = (xevent->xgraphicsexpose.x + xevent->xgraphicsexpose.width + window_impl->window_scale -1) / window_impl->window_scale;
expose_rect.width = x2 - expose_rect.x;
y2 = (xevent->xgraphicsexpose.y + xevent->xgraphicsexpose.height + window_impl->window_scale -1) / window_impl->window_scale;
expose_rect.height = y2 - expose_rect.y;
_gdk_x11_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
return_val = FALSE;
@@ -773,8 +783,8 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
: ""));
if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
{
window->width = xevent->xconfigure.width;
window->height = xevent->xconfigure.height;
window->width = xevent->xconfigure.width / window_impl->window_scale;
window->height = xevent->xconfigure.height / window_impl->window_scale;
_gdk_window_update_size (window);
_gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
@@ -799,8 +809,8 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
{
event->configure.type = GDK_CONFIGURE;
event->configure.window = window;
event->configure.width = xevent->xconfigure.width;
event->configure.height = xevent->xconfigure.height;
event->configure.width = xevent->xconfigure.width / window_impl->window_scale;
event->configure.height = xevent->xconfigure.height / window_impl->window_scale;
if (!xevent->xconfigure.send_event &&
!xevent->xconfigure.override_redirect &&
@@ -818,22 +828,22 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
&tx, &ty,
&child_window))
{
event->configure.x = tx;
event->configure.y = ty;
event->configure.x = tx / window_impl->window_scale;
event->configure.y = ty / window_impl->window_scale;
}
gdk_x11_display_error_trap_pop_ignored (display);
}
else
{
event->configure.x = xevent->xconfigure.x;
event->configure.y = xevent->xconfigure.y;
event->configure.x = xevent->xconfigure.x / window_impl->window_scale;
event->configure.y = xevent->xconfigure.y / window_impl->window_scale;
}
if (!is_substructure)
{
window->x = event->configure.x;
window->y = event->configure.y;
window->width = xevent->xconfigure.width;
window->height = xevent->xconfigure.height;
window->width = xevent->xconfigure.width / window_impl->window_scale;
window->height = xevent->xconfigure.height / window_impl->window_scale;
_gdk_window_update_size (window);
_gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
@@ -1015,11 +1025,15 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) xevent;
XserverRegion repair;
GdkRectangle rect;
int x2, y2;
rect.x = window->x + damage_event->area.x;
rect.y = window->y + damage_event->area.y;
rect.width = damage_event->area.width;
rect.height = damage_event->area.height;
rect.x = window->x + damage_event->area.x / window_impl->window_scale;
rect.y = window->y + damage_event->area.y / window_impl->window_scale;
x2 = (rect.x * window_impl->window_scale + damage_event->area.width + window_impl->window_scale -1) / window_impl->window_scale;
y2 = (rect.y * window_impl->window_scale + damage_event->area.height + window_impl->window_scale -1) / window_impl->window_scale;
rect.width = x2 - rect.x;
rect.height = y2 - rect.y;
repair = XFixesCreateRegion (display_x11->xdisplay,
&damage_event->area, 1);
+25 -10
View File
@@ -510,15 +510,19 @@ gdk_window_cache_new (GdkScreen *screen)
{
GList *toplevel_windows, *list;
GdkWindow *window;
GdkWindowImplX11 *impl;
gint x, y, width, height;
toplevel_windows = gdk_screen_get_toplevel_windows (screen);
for (list = toplevel_windows; list; list = list->next)
{
window = GDK_WINDOW (list->data);
impl = GDK_WINDOW_IMPL_X11 (window->impl);
gdk_window_get_geometry (window, &x, &y, &width, &height);
gdk_window_cache_add (result, GDK_WINDOW_XID (window),
x, y, width, height,
x * impl->window_scale, y * impl->window_scale,
width * impl->window_scale,
height * impl->window_scale,
gdk_window_is_visible (window));
}
g_list_free (toplevel_windows);
@@ -556,7 +560,10 @@ gdk_window_cache_new (GdkScreen *screen)
if (gdk_screen_is_composited (screen))
{
cow = XCompositeGetOverlayWindow (xdisplay, GDK_WINDOW_XID (root_window));
gdk_window_cache_add (result, cow, 0, 0, gdk_screen_get_width (screen), gdk_screen_get_height (screen), TRUE);
gdk_window_cache_add (result, cow, 0, 0,
gdk_screen_get_width (screen) * GDK_X11_SCREEN(screen)->window_scale,
gdk_screen_get_height (screen) * GDK_X11_SCREEN(screen)->window_scale,
TRUE);
XCompositeReleaseOverlayWindow (xdisplay, GDK_WINDOW_XID (root_window));
}
#endif
@@ -651,12 +658,12 @@ is_pointer_within_shape (GdkDisplay *display,
child->shape = NULL;
if (gdk_display_supports_shapes (display))
child->shape = _gdk_x11_xwindow_get_shape (display_x11->xdisplay,
child->xid, ShapeBounding);
child->xid, 1, ShapeBounding);
#ifdef ShapeInput
input_shape = NULL;
if (gdk_display_supports_input_shapes (display))
input_shape = _gdk_x11_xwindow_get_shape (display_x11->xdisplay,
child->xid, ShapeInput);
child->xid, 1, ShapeInput);
if (child->shape && input_shape)
{
@@ -1744,6 +1751,7 @@ xdnd_position_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
GdkWindowImplX11 *impl;
XEvent *xevent = (XEvent *)xev;
guint32 source_window = xevent->xclient.data.l[0];
gint16 x_root = xevent->xclient.data.l[2] >> 16;
@@ -1774,6 +1782,8 @@ xdnd_position_filter (GdkXEvent *xev,
(context->protocol == GDK_DRAG_PROTO_XDND) &&
(GDK_WINDOW_XID (context->source_window) == source_window))
{
impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl);
context_x11 = GDK_X11_DRAG_CONTEXT (context);
event->dnd.type = GDK_DRAG_MOTION;
@@ -1788,11 +1798,11 @@ xdnd_position_filter (GdkXEvent *xev,
if (!context_x11->xdnd_have_actions)
context->actions = context->suggested_action;
event->dnd.x_root = x_root;
event->dnd.y_root = y_root;
event->dnd.x_root = x_root / impl->window_scale;
event->dnd.y_root = y_root / impl->window_scale;
context_x11->last_x = x_root;
context_x11->last_y = y_root;
context_x11->last_x = x_root / impl->window_scale;
context_x11->last_y = y_root / impl->window_scale;
return GDK_FILTER_TRANSLATE;
}
@@ -2015,6 +2025,7 @@ gdk_x11_drag_context_find_window (GdkDragContext *context,
gint y_root,
GdkDragProtocol *protocol)
{
GdkX11Screen *screen_x11 = GDK_X11_SCREEN(screen);
GdkX11DragContext *context_x11 = GDK_X11_DRAG_CONTEXT (context);
GdkWindowCache *window_cache;
GdkDisplay *display;
@@ -2028,7 +2039,8 @@ gdk_x11_drag_context_find_window (GdkDragContext *context,
dest = get_client_window_at_coords (window_cache,
drag_window && GDK_WINDOW_IS_X11 (drag_window) ?
GDK_WINDOW_XID (drag_window) : None,
x_root, y_root);
x_root * screen_x11->window_scale,
y_root * screen_x11->window_scale);
if (context_x11->dest_xid != dest)
{
@@ -2075,6 +2087,7 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
guint32 time)
{
GdkX11DragContext *context_x11 = GDK_X11_DRAG_CONTEXT (context);
GdkWindowImplX11 *impl;
context_x11->old_actions = context->actions;
context->actions = possible_actions;
@@ -2198,12 +2211,14 @@ gdk_x11_drag_context_drag_motion (GdkDragContext *context,
if (context->dest_window)
{
impl = GDK_WINDOW_IMPL_X11 (context->dest_window->impl);
if (context_x11->drag_status == GDK_DRAG_STATUS_DRAG)
{
switch (context->protocol)
{
case GDK_DRAG_PROTO_XDND:
xdnd_send_motion (context_x11, x_root, y_root, suggested_action, time);
xdnd_send_motion (context_x11, x_root * impl->window_scale, y_root * impl->window_scale, suggested_action, time);
break;
case GDK_DRAG_PROTO_ROOTWIN:
+14 -9
View File
@@ -42,18 +42,22 @@ _gdk_x11_window_move_resize_child (GdkWindow *window,
gint width,
gint height)
{
GdkWindowImplX11 *impl;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (width > 65535 ||
height > 65535)
impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (width * impl->window_scale > 65535 ||
height * impl->window_scale > 65535)
{
g_warning ("Native children wider or taller than 65535 pixels are not supported");
if (width > 65535)
width = 65535;
if (height > 65535)
height = 65535;
if (width * impl->window_scale > 65535)
width = 65535 / impl->window_scale;
if (height * impl->window_scale > 65535)
height = 65535 / impl->window_scale;
}
window->x = x;
@@ -69,9 +73,10 @@ _gdk_x11_window_move_resize_child (GdkWindow *window,
_gdk_x11_window_tmp_unset_bg (window, TRUE);
XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
window->x + window->parent->abs_x,
window->y + window->parent->abs_y,
width, height);
(window->x + window->parent->abs_x) * impl->window_scale,
(window->y + window->parent->abs_y) * impl->window_scale,
width * impl->window_scale,
height * impl->window_scale);
_gdk_x11_window_tmp_reset_parent_bg (window);
_gdk_x11_window_tmp_reset_bg (window, TRUE);
}
+5 -4
View File
@@ -368,6 +368,7 @@ void
_gdk_x11_region_get_xrectangles (const cairo_region_t *region,
gint x_offset,
gint y_offset,
gint scale,
XRectangle **rects,
gint *n_rects)
{
@@ -381,10 +382,10 @@ _gdk_x11_region_get_xrectangles (const cairo_region_t *region,
for (i = 0; i < n; i++)
{
cairo_region_get_rectangle (region, i, &box);
rectangles[i].x = CLAMP (box.x + x_offset, G_MINSHORT, G_MAXSHORT);
rectangles[i].y = CLAMP (box.y + y_offset, G_MINSHORT, G_MAXSHORT);
rectangles[i].width = CLAMP (box.width, G_MINSHORT, G_MAXSHORT);
rectangles[i].height = CLAMP (box.height, G_MINSHORT, G_MAXSHORT);
rectangles[i].x = CLAMP ((box.x + x_offset) * scale, G_MINSHORT, G_MAXSHORT);
rectangles[i].y = CLAMP ((box.y + y_offset) * scale, G_MINSHORT, G_MAXSHORT);
rectangles[i].width = CLAMP (box.width * scale, G_MINSHORT, G_MAXSHORT);
rectangles[i].height = CLAMP (box.height * scale, G_MINSHORT, G_MAXSHORT);
}
*n_rects = n;
+2
View File
@@ -140,11 +140,13 @@ gboolean _gdk_x11_selection_filter_clear_event (XSelectionClearEvent *event);
cairo_region_t* _gdk_x11_xwindow_get_shape (Display *xdisplay,
Window window,
gint scale,
gint shape_type);
void _gdk_x11_region_get_xrectangles (const cairo_region_t *region,
gint x_offset,
gint y_offset,
gint scale,
XRectangle **rects,
gint *n_rects);
+65 -6
View File
@@ -96,13 +96,13 @@ gdk_x11_screen_get_display (GdkScreen *screen)
static gint
gdk_x11_screen_get_width (GdkScreen *screen)
{
return WidthOfScreen (GDK_X11_SCREEN (screen)->xscreen);
return WidthOfScreen (GDK_X11_SCREEN (screen)->xscreen) / GDK_X11_SCREEN (screen)->window_scale;
}
static gint
gdk_x11_screen_get_height (GdkScreen *screen)
{
return HeightOfScreen (GDK_X11_SCREEN (screen)->xscreen);
return HeightOfScreen (GDK_X11_SCREEN (screen)->xscreen) / GDK_X11_SCREEN (screen)->window_scale;
}
static gint
@@ -253,7 +253,13 @@ gdk_x11_screen_get_monitor_geometry (GdkScreen *screen,
GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
if (dest)
*dest = x11_screen->monitors[monitor_num].geometry;
{
*dest = x11_screen->monitors[monitor_num].geometry;
dest->x /= x11_screen->window_scale;
dest->y /= x11_screen->window_scale;
dest->width /= x11_screen->window_scale;
dest->height /= x11_screen->window_scale;
}
}
static int
@@ -297,6 +303,7 @@ static void
get_work_area (GdkScreen *screen,
GdkRectangle *area)
{
GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
Atom workarea;
Atom type;
Window win;
@@ -318,8 +325,8 @@ get_work_area (GdkScreen *screen,
/* Defaults in case of error */
area->x = 0;
area->y = 0;
area->width = gdk_screen_get_width (screen);
area->height = gdk_screen_get_height (screen);
area->width = gdk_screen_get_width (screen) / x11_screen->window_scale;
area->height = gdk_screen_get_height (screen) / x11_screen->window_scale;
if (!gdk_x11_screen_supports_net_wm_hint (screen,
gdk_atom_intern_static_string ("_NET_WORKAREA")))
@@ -356,6 +363,11 @@ get_work_area (GdkScreen *screen,
area->width = workareas[desktop * 4 + 2];
area->height = workareas[desktop * 4 + 3];
area->x /= x11_screen->window_scale;
area->y /= x11_screen->window_scale;
area->width /= x11_screen->window_scale;
area->height /= x11_screen->window_scale;
XFree (ret_workarea);
}
@@ -382,6 +394,15 @@ gdk_x11_screen_get_monitor_workarea (GdkScreen *screen,
}
}
static gint
gdk_x11_screen_get_monitor_scale_factor (GdkScreen *screen,
gint monitor_num)
{
GdkX11Screen *screen_x11 = GDK_X11_SCREEN (screen);
return screen_x11->window_scale;
}
static GdkVisual *
gdk_x11_screen_get_rgba_visual (GdkScreen *screen)
{
@@ -1029,6 +1050,7 @@ _gdk_x11_screen_new (GdkDisplay *display,
GdkScreen *screen;
GdkX11Screen *x11_screen;
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
const char *scale_str;
screen = g_object_new (GDK_TYPE_X11_SCREEN, NULL);
@@ -1041,7 +1063,22 @@ _gdk_x11_screen_new (GdkDisplay *display,
x11_screen->wmspec_check_window = None;
/* we want this to be always non-null */
x11_screen->window_manager_name = g_strdup ("unknown");
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
scale_str = g_getenv ("GDK_SCALE");
#else
scale_str = NULL;
#endif
if (scale_str)
{
x11_screen->fixed_window_scale = TRUE;
x11_screen->window_scale = atol (scale_str);
if (x11_screen->window_scale == 0)
x11_screen->window_scale = 1;
}
else
x11_screen->window_scale = 1;
init_multihead (screen);
init_randr_support (screen);
@@ -1051,6 +1088,27 @@ _gdk_x11_screen_new (GdkDisplay *display,
return screen;
}
void
_gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen,
int scale)
{
GList *toplevels, *l;
if (x11_screen->window_scale == scale)
return;
x11_screen->window_scale = scale;
toplevels = gdk_screen_get_toplevel_windows (GDK_SCREEN (x11_screen));
for (l = toplevels; l != NULL; l = l->next)
{
GdkWindow *window = l->data;
_gdk_x11_window_set_window_scale (window, scale);
}
}
/*
* It is important that we first request the selection
* notification, and then setup the initial state of
@@ -1627,6 +1685,7 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass)
screen_class->get_monitor_plug_name = gdk_x11_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_x11_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_x11_screen_get_monitor_workarea;
screen_class->get_monitor_scale_factor = gdk_x11_screen_get_monitor_scale_factor;
screen_class->get_system_visual = _gdk_x11_screen_get_system_visual;
screen_class->get_rgba_visual = gdk_x11_screen_get_rgba_visual;
screen_class->is_composited = gdk_x11_screen_is_composited;
+5
View File
@@ -47,6 +47,9 @@ struct _GdkX11Screen
GdkX11Monitor *monitors;
gint primary_monitor;
gint window_scale;
gboolean fixed_window_scale;
/* Xft resources for the display, used for default values for
* the Xft/ XSETTINGS
*/
@@ -119,6 +122,8 @@ void _gdk_x11_screen_get_edge_monitors (GdkScreen *screen,
gint *bottom,
gint *left,
gint *right);
void _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen,
int scale);
G_END_DECLS
+6 -1
View File
@@ -62,7 +62,12 @@ static const struct {
{"Gtk/ShellShowsMenubar", "gtk-shell-shows-menubar"},
{"Gtk/EnablePrimaryPaste", "gtk-enable-primary-paste"},
{"Gtk/RecentFilesMaxAge", "gtk-recent-files-max-age"},
{"Gtk/RecentFilesEnabled", "gtk-recent-files-enabled"}
{"Gtk/RecentFilesEnabled", "gtk-recent-files-enabled"},
/* These are here in order to be recognized, but are not sent to
gtk as they are handled internally by gdk: */
{"Gdk/WindowScalingFactor", "gdk-window-scaling-factor"},
{"Gdk/UnscaledDPI", "gdk-unscaled-dpi"}
};
static const char *
+213 -74
View File
@@ -156,6 +156,7 @@ gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
{
impl->device_cursor = g_hash_table_new_full (NULL, NULL,
NULL, g_object_unref);
impl->window_scale = 1;
}
GdkToplevelX11 *
@@ -194,8 +195,8 @@ _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
if (impl->cairo_surface)
{
cairo_xlib_surface_set_size (impl->cairo_surface,
gdk_window_get_width (impl->wrapper),
gdk_window_get_height (impl->wrapper));
gdk_window_get_width (impl->wrapper) * impl->window_scale,
gdk_window_get_height (impl->wrapper) * impl->window_scale);
}
}
@@ -464,8 +465,11 @@ gdk_x11_ref_cairo_surface (GdkWindow *window)
if (!impl->cairo_surface)
{
impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
gdk_window_get_width (window),
gdk_window_get_height (window));
gdk_window_get_width (window) * impl->window_scale,
gdk_window_get_height (window) * impl->window_scale);
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_set_device_scale (impl->cairo_surface, impl->window_scale, impl->window_scale);
#endif
if (impl->cairo_surface)
cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
@@ -727,6 +731,7 @@ _gdk_x11_screen_init_root_window (GdkScreen *screen)
impl->xid = x11_screen->xroot_window;
impl->wrapper = window;
impl->window_scale = x11_screen->window_scale;
window->window_type = GDK_WINDOW_ROOT;
window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
@@ -735,8 +740,8 @@ _gdk_x11_screen_init_root_window (GdkScreen *screen)
window->y = 0;
window->abs_x = 0;
window->abs_y = 0;
window->width = WidthOfScreen (x11_screen->xscreen);
window->height = HeightOfScreen (x11_screen->xscreen);
window->width = WidthOfScreen (x11_screen->xscreen) / impl->window_scale;
window->height = HeightOfScreen (x11_screen->xscreen) / impl->window_scale;
window->viewable = TRUE;
/* see init_randr_support() in gdkscreen-x11.c */
@@ -872,6 +877,7 @@ setup_toplevel_window (GdkWindow *window,
GdkWindow *parent)
{
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
GdkDisplay *display = gdk_window_get_display (window);
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
XID xid = GDK_WINDOW_XID (window);
@@ -900,8 +906,8 @@ setup_toplevel_window (GdkWindow *window,
* correct value???
*/
size_hints.flags = PSize;
size_hints.width = window->width;
size_hints.height = window->height;
size_hints.width = window->width * impl->window_scale;
size_hints.height = window->height * impl->window_scale;
XSetWMNormalHints (xdisplay, xid, &size_hints);
@@ -1006,6 +1012,7 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display,
impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
window->impl = GDK_WINDOW_IMPL (impl);
impl->wrapper = GDK_WINDOW (window);
impl->window_scale = x11_screen->window_scale;
xdisplay = x11_screen->xdisplay;
@@ -1076,21 +1083,21 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display,
class = InputOnly;
}
if (window->width > 65535 ||
window->height > 65535)
if (window->width * impl->window_scale > 65535 ||
window->height * impl->window_scale > 65535)
{
g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
if (window->width > 65535)
window->width = 65535;
if (window->height > 65535)
window->height = 65535;
if (window->width * impl->window_scale > 65535)
window->width = 65535 / impl->window_scale;
if (window->height * impl->window_scale > 65535)
window->height = 65535 / impl->window_scale;
}
impl->xid = XCreateWindow (xdisplay, xparent,
window->x + window->parent->abs_x,
window->y + window->parent->abs_y,
window->width, window->height,
(window->x + window->parent->abs_x) * impl->window_scale,
(window->y + window->parent->abs_y) * impl->window_scale,
window->width * impl->window_scale, window->height * impl->window_scale,
0, window->depth, class, xvisual,
xattributes_mask, &xattributes);
@@ -1219,6 +1226,7 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
impl = GDK_WINDOW_IMPL_X11 (win->impl);
impl->wrapper = win;
impl->window_scale = GDK_X11_SCREEN (screen)->window_scale;
win->parent = gdk_x11_window_lookup_for_display (display, parent);
@@ -1231,10 +1239,10 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
impl->xid = window;
win->x = attrs.x;
win->y = attrs.y;
win->width = attrs.width;
win->height = attrs.height;
win->x = attrs.x / impl->window_scale;
win->y = attrs.y / impl->window_scale;
win->width = attrs.width / impl->window_scale;
win->height = attrs.height / impl->window_scale;
win->window_type = GDK_WINDOW_FOREIGN;
win->destroyed = FALSE;
@@ -1765,7 +1773,7 @@ window_x11_move (GdkWindow *window,
{
XMoveWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
x, y);
x * impl->window_scale, y * impl->window_scale);
if (impl->override_redirect)
{
@@ -1800,7 +1808,7 @@ window_x11_resize (GdkWindow *window,
XResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
width, height);
width * impl->window_scale, height * impl->window_scale);
if (impl->override_redirect)
{
@@ -1814,8 +1822,6 @@ window_x11_resize (GdkWindow *window,
window->resize_count += 1;
}
}
_gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
}
static inline void
@@ -1844,7 +1850,8 @@ window_x11_move_resize (GdkWindow *window,
XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
x, y, width, height);
x * impl->window_scale, y * impl->window_scale,
width * impl->window_scale, height * impl->window_scale);
if (impl->override_redirect)
{
@@ -1883,6 +1890,75 @@ gdk_window_x11_move_resize (GdkWindow *window,
}
}
static void
set_scale_recursive (GdkWindow *window, int scale)
{
GdkWindow *child;
GList *l;
for (l = window->children; l; l = l->next)
{
child = l->data;
if (child->impl != window->impl)
_gdk_x11_window_set_window_scale (child, scale);
else
set_scale_recursive (child, scale);
}
}
void
_gdk_x11_window_set_window_scale (GdkWindow *window,
int scale)
{
GdkWindowImplX11 *impl;
GdkToplevelX11 *toplevel;
GdkWindowHints geom_mask;
if (window->window_type == GDK_WINDOW_OFFSCREEN)
return;
g_print ("_gdk_x11_window_set_window_scale %p %d\n", window, scale);
impl = GDK_WINDOW_IMPL_X11 (window->impl);
impl->window_scale = scale;
toplevel = _gdk_x11_window_get_toplevel (window);
if (toplevel && window->window_type != GDK_WINDOW_FOREIGN)
{
/* These are affected by window scale: */
geom_mask = toplevel->last_geometry_hints_mask &
(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC);
if (geom_mask)
gdk_window_set_geometry_hints (window,
&toplevel->last_geometry_hints,
geom_mask);
}
if (window->window_type == GDK_WINDOW_FOREIGN)
XMoveWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
(window->x + window->parent->abs_x) * impl->window_scale,
(window->y + window->parent->abs_y) * impl->window_scale);
else if (WINDOW_IS_TOPLEVEL(window))
XResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
window->width * impl->window_scale,
window->height * impl->window_scale);
else
XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
(window->x + window->parent->abs_x) * impl->window_scale,
(window->y + window->parent->abs_y) * impl->window_scale,
window->width * impl->window_scale,
window->height * impl->window_scale);
gdk_window_invalidate_rect (window, NULL, TRUE);
set_scale_recursive (window, scale);
}
static gboolean
gdk_window_x11_reparent (GdkWindow *window,
GdkWindow *new_parent,
@@ -1898,7 +1974,8 @@ gdk_window_x11_reparent (GdkWindow *window,
XReparentWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XID (new_parent),
new_parent->abs_x + x, new_parent->abs_y + y);
(new_parent->abs_x + x) * impl->window_scale,
(new_parent->abs_y + y) * impl->window_scale);
_gdk_x11_window_tmp_reset_parent_bg (window);
_gdk_x11_window_tmp_reset_bg (window, TRUE);
@@ -2390,11 +2467,20 @@ gdk_x11_window_set_geometry_hints (GdkWindow *window,
const GdkGeometry *geometry,
GdkWindowHints geom_mask)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
XSizeHints size_hints;
GdkToplevelX11 *toplevel;
if (GDK_WINDOW_DESTROYED (window) ||
!WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
if (toplevel)
{
toplevel->last_geometry_hints = *geometry;
toplevel->last_geometry_hints_mask = geom_mask;
}
size_hints.flags = 0;
@@ -2422,31 +2508,37 @@ gdk_x11_window_set_geometry_hints (GdkWindow *window,
if (geom_mask & GDK_HINT_MIN_SIZE)
{
size_hints.flags |= PMinSize;
size_hints.min_width = geometry->min_width;
size_hints.min_height = geometry->min_height;
size_hints.min_width = geometry->min_width * impl->window_scale;
size_hints.min_height = geometry->min_height * impl->window_scale;
}
if (geom_mask & GDK_HINT_MAX_SIZE)
{
size_hints.flags |= PMaxSize;
size_hints.max_width = MAX (geometry->max_width, 1);
size_hints.max_height = MAX (geometry->max_height, 1);
size_hints.max_width = MAX (geometry->max_width, 1) * impl->window_scale;
size_hints.max_height = MAX (geometry->max_height, 1) * impl->window_scale;
}
if (geom_mask & GDK_HINT_BASE_SIZE)
{
size_hints.flags |= PBaseSize;
size_hints.base_width = geometry->base_width;
size_hints.base_height = geometry->base_height;
size_hints.base_width = geometry->base_width * impl->window_scale;
size_hints.base_height = geometry->base_height * impl->window_scale;
}
if (geom_mask & GDK_HINT_RESIZE_INC)
{
size_hints.flags |= PResizeInc;
size_hints.width_inc = geometry->width_inc;
size_hints.height_inc = geometry->height_inc;
size_hints.width_inc = geometry->width_inc * impl->window_scale;
size_hints.height_inc = geometry->height_inc * impl->window_scale;
}
else if (impl->window_scale > 1)
{
size_hints.flags |= PResizeInc;
size_hints.width_inc = impl->window_scale;
size_hints.height_inc = impl->window_scale;
}
if (geom_mask & GDK_HINT_ASPECT)
{
size_hints.flags |= PAspect;
@@ -2491,6 +2583,7 @@ gdk_window_get_geometry_hints (GdkWindow *window,
GdkGeometry *geometry,
GdkWindowHints *geom_mask)
{
GdkWindowImplX11 *impl;
XSizeHints *size_hints;
glong junk_supplied_mask = 0;
@@ -2504,6 +2597,8 @@ gdk_window_get_geometry_hints (GdkWindow *window,
!WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
return;
impl = GDK_WINDOW_IMPL_X11 (window->impl);
size_hints = XAllocSizeHints ();
if (!size_hints)
return;
@@ -2517,22 +2612,22 @@ gdk_window_get_geometry_hints (GdkWindow *window,
if (size_hints->flags & PMinSize)
{
*geom_mask |= GDK_HINT_MIN_SIZE;
geometry->min_width = size_hints->min_width;
geometry->min_height = size_hints->min_height;
geometry->min_width = size_hints->min_width / impl->window_scale;
geometry->min_height = size_hints->min_height / impl->window_scale;
}
if (size_hints->flags & PMaxSize)
{
*geom_mask |= GDK_HINT_MAX_SIZE;
geometry->max_width = MAX (size_hints->max_width, 1);
geometry->max_height = MAX (size_hints->max_height, 1);
geometry->max_width = MAX (size_hints->max_width, 1) / impl->window_scale;
geometry->max_height = MAX (size_hints->max_height, 1) / impl->window_scale;
}
if (size_hints->flags & PResizeInc)
{
*geom_mask |= GDK_HINT_RESIZE_INC;
geometry->width_inc = size_hints->width_inc;
geometry->height_inc = size_hints->height_inc;
geometry->width_inc = size_hints->width_inc / impl->window_scale;
geometry->height_inc = size_hints->height_inc / impl->window_scale;
}
if (size_hints->flags & PAspect)
@@ -2793,6 +2888,7 @@ static void
gdk_window_x11_set_background (GdkWindow *window,
cairo_pattern_t *pattern)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
double r, g, b, a;
cairo_surface_t *surface;
cairo_matrix_t matrix;
@@ -2831,12 +2927,17 @@ gdk_window_x11_set_background (GdkWindow *window,
cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
{
double x, y;
double x, y, sx, sy;
cairo_surface_get_device_offset (surface, &x, &y);
sx = sy = 1.;
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_get_device_scale (surface, &sx, &sy);
#endif
/* XXX: This still bombs for non-pixmaps, but there's no way to
* detect we're not a pixmap in Cairo... */
if (x == 0.0 && y == 0.0)
if (x == 0.0 && y == 0.0 &&
sx == impl->window_scale && sy == impl->window_scale)
{
XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
@@ -2900,6 +3001,7 @@ gdk_window_x11_get_geometry (GdkWindow *window,
gint *width,
gint *height)
{
GdkWindowImplX11 *impl;
Window root;
gint tx;
gint ty;
@@ -2910,18 +3012,20 @@ gdk_window_x11_get_geometry (GdkWindow *window,
if (!GDK_WINDOW_DESTROYED (window))
{
impl = GDK_WINDOW_IMPL_X11 (window->impl);
XGetGeometry (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
&root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
if (x)
*x = tx;
*x = tx / impl->window_scale;
if (y)
*y = ty;
*y = ty / impl->window_scale;
if (width)
*width = twidth;
*width = twidth / impl->window_scale;
if (height)
*height = theight;
*height = theight / impl->window_scale;
}
}
@@ -2932,6 +3036,7 @@ gdk_window_x11_get_root_coords (GdkWindow *window,
gint *root_x,
gint *root_y)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
gint return_val;
Window child;
gint tx;
@@ -2940,13 +3045,13 @@ gdk_window_x11_get_root_coords (GdkWindow *window,
return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XROOTWIN (window),
x, y, &tx, &ty,
x * impl->window_scale, y * impl->window_scale, &tx, &ty,
&child);
if (root_x)
*root_x = tx;
*root_x = tx / impl->window_scale;
if (root_y)
*root_y = ty;
*root_y = ty / impl->window_scale;
return return_val;
}
@@ -3001,13 +3106,14 @@ gdk_x11_window_get_frame_extents (GdkWindow *window,
while (window->parent && (window->parent)->parent)
window = window->parent;
/* Refine our fallback answer a bit using local information */
rect->x = window->x;
rect->y = window->y;
rect->width = window->width;
rect->height = window->height;
impl = GDK_WINDOW_IMPL_X11 (window->impl);
/* Refine our fallback answer a bit using local information */
rect->x = window->x * impl->window_scale;
rect->y = window->y * impl->window_scale;
rect->width = window->width * impl->window_scale;
rect->height = window->height * impl->window_scale;
if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
return;
@@ -3126,14 +3232,18 @@ gdk_x11_window_get_frame_extents (GdkWindow *window,
if (vroots)
XFree (vroots);
rect->x /= impl->window_scale;
rect->y /= impl->window_scale;
rect->width /= impl->window_scale;
rect->height /= impl->window_scale;
gdk_x11_display_error_trap_pop_ignored (display);
}
static gboolean
gdk_window_x11_get_device_state (GdkWindow *window,
GdkDevice *device,
gint *x,
gint *y,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkWindow *child;
@@ -3143,6 +3253,7 @@ gdk_window_x11_get_device_state (GdkWindow *window,
if (GDK_WINDOW_DESTROYED (window))
return FALSE;
/*HIDPI: handle coords here?*/
GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
NULL, &child,
NULL, NULL,
@@ -3199,6 +3310,8 @@ do_shape_combine_region (GdkWindow *window,
gint offset_y,
gint shape)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (GDK_WINDOW_DESTROYED (window))
return;
@@ -3237,7 +3350,7 @@ do_shape_combine_region (GdkWindow *window,
XRectangle *xrects = NULL;
_gdk_x11_region_get_xrectangles (shape_region,
0, 0,
0, 0, impl->window_scale,
&xrects, &n_rects);
if (shape == ShapeBounding)
@@ -3248,7 +3361,8 @@ do_shape_combine_region (GdkWindow *window,
XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
shape,
offset_x, offset_y,
offset_x * impl->window_scale,
offset_y * impl->window_scale,
xrects, n_rects,
ShapeSet,
YXBanded);
@@ -4307,6 +4421,7 @@ gdk_x11_window_set_functions (GdkWindow *window,
cairo_region_t *
_gdk_x11_xwindow_get_shape (Display *xdisplay,
Window window,
gint scale,
gint shape_type)
{
cairo_region_t *shape;
@@ -4340,13 +4455,15 @@ _gdk_x11_xwindow_get_shape (Display *xdisplay,
return NULL;
}
/* NOTE: The scale divisions here may lose some precision if someone
else set the shape to be non-scale precision */
rl = g_new (GdkRectangle, rn);
for (i = 0; i < rn; i++)
{
rl[i].x = xrl[i].x;
rl[i].y = xrl[i].y;
rl[i].width = xrl[i].width;
rl[i].height = xrl[i].height;
rl[i].x = xrl[i].x / scale;
rl[i].y = xrl[i].y / scale;
rl[i].width = xrl[i].width / scale;
rl[i].height = xrl[i].height / scale;
}
XFree (xrl);
@@ -4360,10 +4477,13 @@ _gdk_x11_xwindow_get_shape (Display *xdisplay,
static cairo_region_t *
gdk_x11_window_get_shape (GdkWindow *window)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (!GDK_WINDOW_DESTROYED (window) &&
gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
impl->window_scale,
ShapeBounding);
return NULL;
@@ -4373,10 +4493,13 @@ static cairo_region_t *
gdk_x11_window_get_input_shape (GdkWindow *window)
{
#if defined(ShapeInput)
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (!GDK_WINDOW_DESTROYED (window) &&
gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
impl->window_scale,
ShapeInput);
#endif
@@ -4467,6 +4590,7 @@ wmspec_send_message (GdkDisplay *display,
gint action,
gint button)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
XClientMessageEvent xclient;
memset (&xclient, 0, sizeof (xclient));
@@ -4475,8 +4599,8 @@ wmspec_send_message (GdkDisplay *display,
xclient.message_type =
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
xclient.format = 32;
xclient.data.l[0] = root_x;
xclient.data.l[1] = root_y;
xclient.data.l[0] = root_x * impl->window_scale;
xclient.data.l[1] = root_y * impl->window_scale;
xclient.data.l[2] = action;
xclient.data.l[3] = button;
xclient.data.l[4] = 1; /* source indication */
@@ -4798,6 +4922,7 @@ _gdk_x11_moveresize_handle_event (XEvent *event)
guint button_mask = 0;
GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
GdkWindowImplX11 *impl;
if (!mv_resize || !mv_resize->moveresize_window)
{
@@ -4805,6 +4930,8 @@ _gdk_x11_moveresize_handle_event (XEvent *event)
return FALSE;
}
impl = GDK_WINDOW_IMPL_X11 (mv_resize->moveresize_window->impl);
button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
switch (event->xany.type)
@@ -4824,8 +4951,8 @@ _gdk_x11_moveresize_handle_event (XEvent *event)
break;
update_pos (mv_resize,
event->xmotion.x_root,
event->xmotion.y_root);
event->xmotion.x_root / impl->window_scale,
event->xmotion.y_root / impl->window_scale);
/* This should never be triggered in normal cases, but in the
* case where the drag started without an implicit grab being
@@ -4839,8 +4966,8 @@ _gdk_x11_moveresize_handle_event (XEvent *event)
case ButtonRelease:
update_pos (mv_resize,
event->xbutton.x_root,
event->xbutton.y_root);
event->xbutton.x_root / impl->window_scale,
event->xbutton.y_root / impl->window_scale);
if (event->xbutton.button == mv_resize->moveresize_button)
finish_drag (mv_resize);
@@ -4856,14 +4983,14 @@ _gdk_x11_moveresize_handle_event (XEvent *event)
switch (ev->evtype)
{
case XI_Motion:
update_pos (mv_resize, xev->root_x, xev->root_y);
update_pos (mv_resize, xev->root_x / impl->window_scale, xev->root_y / impl->window_scale);
state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
if ((state & button_mask) == 0)
finish_drag (mv_resize);
break;
case XI_ButtonRelease:
update_pos (mv_resize, xev->root_x, xev->root_y);
update_pos (mv_resize, xev->root_x / impl->window_scale, xev->root_y / impl->window_scale);
if (xev->detail == mv_resize->moveresize_button)
finish_drag (mv_resize);
break;
@@ -5307,6 +5434,17 @@ gdk_x11_window_get_xid (GdkWindow *window)
return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
}
static gint
gdk_x11_window_get_scale_factor (GdkWindow *window)
{
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (GDK_WINDOW_DESTROYED (window))
return 1;
return impl->window_scale;
}
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
{
@@ -5394,4 +5532,5 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
impl_class->get_property = _gdk_x11_window_get_property;
impl_class->change_property = _gdk_x11_window_change_property;
impl_class->delete_property = _gdk_x11_window_delete_property;
impl_class->get_scale_factor = gdk_x11_window_get_scale_factor;
}
+8 -1
View File
@@ -64,6 +64,8 @@ struct _GdkWindowImplX11
Window xid;
gint window_scale;
GdkToplevelX11 *toplevel; /* Toplevel-specific information */
GdkCursor *cursor;
GHashTable *device_cursor;
@@ -150,7 +152,10 @@ struct _GdkToplevelX11
* that might not even be part of this app
*/
Window focus_window;
GdkWindowHints last_geometry_hints_mask;
GdkGeometry last_geometry_hints;
#ifdef HAVE_XSYNC
XID update_counter;
XID extended_update_counter;
@@ -183,6 +188,8 @@ void _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window);
GdkCursor *_gdk_x11_window_get_cursor (GdkWindow *window);
void _gdk_x11_window_update_size (GdkWindowImplX11 *impl);
void _gdk_x11_window_set_window_scale (GdkWindow *window,
int scale);
G_END_DECLS
+27
View File
@@ -68,6 +68,9 @@ gdk_xsettings_notify (GdkX11Screen *x11_screen,
{
GdkEvent new_event;
if (!g_str_has_prefix (name, "gtk-"))
return;
new_event.type = GDK_SETTING;
new_event.setting.window = gdk_screen_get_root_window (GDK_SCREEN (x11_screen));
new_event.setting.send_event = FALSE;
@@ -406,6 +409,8 @@ read_settings (GdkX11Screen *x11_screen,
int result;
GHashTable *old_list = x11_screen->xsettings;
GValue value = G_VALUE_INIT;
GValue *setting, *copy;
x11_screen->xsettings = NULL;
@@ -439,10 +444,32 @@ read_settings (GdkX11Screen *x11_screen,
}
}
/* Since we support scaling we look at the specific Gdk/UnscaledDPI
setting if it exists and use that instead of Xft/DPI if it is set */
if (x11_screen->xsettings && !x11_screen->fixed_window_scale)
{
setting = g_hash_table_lookup (x11_screen->xsettings, "gdk-unscaled-dpi");
if (setting)
{
copy = g_new0 (GValue, 1);
g_value_init (copy, G_VALUE_TYPE (setting));
g_value_copy (setting, copy);
g_hash_table_insert (x11_screen->xsettings,
"gtk-xft-dpi", copy);
}
}
if (do_notify)
notify_changes (x11_screen, old_list);
if (old_list)
g_hash_table_unref (old_list);
g_value_init (&value, G_TYPE_INT);
if (!x11_screen->fixed_window_scale &&
gdk_screen_get_setting (GDK_SCREEN (x11_screen),
"gdk-window-scaling-factor", &value))
_gdk_x11_screen_set_window_scale (x11_screen,
g_value_get_int (&value));
}
static Atom
+2
View File
@@ -449,6 +449,7 @@ gtk_private_h_sources = \
gtkcssimageprivate.h \
gtkcssimagesurfaceprivate.h \
gtkcssimageurlprivate.h \
gtkcssimagescaledprivate.h \
gtkcssimagevalueprivate.h \
gtkcssimagewin32private.h \
gtkcssinheritvalueprivate.h \
@@ -683,6 +684,7 @@ gtk_base_c_sources = \
gtkcssimagelinear.c \
gtkcssimagesurface.c \
gtkcssimageurl.c \
gtkcssimagescaled.c \
gtkcssimagevalue.c \
gtkcssimagewin32.c \
gtkcssinheritvalue.c \
+21
View File
@@ -17,6 +17,7 @@
#include "config.h"
#include <stdlib.h>
#include <cairo-gobject.h>
#include "gtkcellrendererpixbuf.h"
#include "gtkiconfactory.h"
#include "gtkiconhelperprivate.h"
@@ -74,6 +75,7 @@ enum {
PROP_PIXBUF,
PROP_PIXBUF_EXPANDER_OPEN,
PROP_PIXBUF_EXPANDER_CLOSED,
PROP_SURFACE,
PROP_STOCK_ID,
PROP_STOCK_SIZE,
PROP_STOCK_DETAIL,
@@ -168,6 +170,13 @@ gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
P_("Pixbuf for closed expander"),
GDK_TYPE_PIXBUF,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SURFACE,
g_param_spec_boxed ("surface",
P_("surface"),
P_("The surface to render"),
CAIRO_GOBJECT_TYPE_SURFACE,
GTK_PARAM_READWRITE));
/**
* GtkCellRendererPixbuf:stock-id:
@@ -279,6 +288,9 @@ gtk_cell_renderer_pixbuf_get_property (GObject *object,
case PROP_PIXBUF_EXPANDER_CLOSED:
g_value_set_object (value, priv->pixbuf_expander_closed);
break;
case PROP_SURFACE:
g_value_set_boxed (value, _gtk_icon_helper_peek_surface (priv->icon_helper));
break;
case PROP_STOCK_ID:
g_value_set_string (value, _gtk_icon_helper_get_stock_id (priv->icon_helper));
break;
@@ -311,6 +323,9 @@ gtk_cell_renderer_pixbuf_reset (GtkCellRendererPixbuf *cellpixbuf)
switch (storage_type)
{
case GTK_IMAGE_SURFACE:
g_object_notify (G_OBJECT (cellpixbuf), "surface");
break;
case GTK_IMAGE_PIXBUF:
g_object_notify (G_OBJECT (cellpixbuf), "pixbuf");
break;
@@ -356,6 +371,10 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object,
g_object_unref (priv->pixbuf_expander_closed);
priv->pixbuf_expander_closed = (GdkPixbuf*) g_value_dup_object (value);
break;
case PROP_SURFACE:
gtk_cell_renderer_pixbuf_reset (cellpixbuf);
_gtk_icon_helper_set_surface (priv->icon_helper, g_value_get_boxed (value));
break;
case PROP_STOCK_ID:
gtk_cell_renderer_pixbuf_reset (cellpixbuf);
_gtk_icon_helper_set_stock_id (priv->icon_helper, g_value_get_string (value), priv->icon_size);
@@ -552,6 +571,8 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell,
if (icon_helper == NULL)
icon_helper = g_object_ref (priv->icon_helper);
_gtk_icon_helper_set_window (icon_helper,
gtk_widget_get_window (widget));
_gtk_icon_helper_draw (icon_helper,
context, cr,
pix_rect.x, pix_rect.y);
+2 -1
View File
@@ -46,6 +46,7 @@ static GtkCssValue *
gtk_css_value_array_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -58,7 +59,7 @@ gtk_css_value_array_compute (GtkCssValue *value,
result = NULL;
for (i = 0; i < value->n_values; i++)
{
i_value = _gtk_css_value_compute (value->values[i], property_id, provider, values, parent_values, &child_deps);
i_value = _gtk_css_value_compute (value->values[i], property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
+3 -2
View File
@@ -44,6 +44,7 @@ static GtkCssValue *
gtk_css_value_bg_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -58,10 +59,10 @@ gtk_css_value_bg_size_compute (GtkCssValue *value,
x = y = NULL;
if (value->x)
x = _gtk_css_value_compute (value->x, property_id, provider, values, parent_values, &x_deps);
x = _gtk_css_value_compute (value->x, property_id, provider, scale, values, parent_values, &x_deps);
if (value->y)
y = _gtk_css_value_compute (value->y, property_id, provider, values, parent_values, &y_deps);
y = _gtk_css_value_compute (value->y, property_id, provider, scale, values, parent_values, &y_deps);
*dependencies = _gtk_css_dependencies_union (x_deps, y_deps);
+2 -1
View File
@@ -45,6 +45,7 @@ static GtkCssValue *
gtk_css_value_border_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -61,7 +62,7 @@ gtk_css_value_border_compute (GtkCssValue *value,
{
if (value->values[i])
{
computed->values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, values, parent_values, &child_deps);
computed->values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
changed |= (computed->values[i] != value->values[i]);
}
+4 -1
View File
@@ -101,6 +101,7 @@ gtk_css_value_color_free (GtkCssValue *color)
static GtkCssValue *
gtk_css_value_color_get_fallback (guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values)
{
@@ -124,6 +125,7 @@ gtk_css_value_color_get_fallback (guint property_id,
return _gtk_css_value_compute (_gtk_css_style_property_get_initial_value (_gtk_css_style_property_lookup_by_id (property_id)),
property_id,
provider,
scale,
values,
parent_values,
NULL);
@@ -297,6 +299,7 @@ static GtkCssValue *
gtk_css_value_color_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -335,7 +338,7 @@ gtk_css_value_color_compute (GtkCssValue *value,
NULL);
if (resolved == NULL)
return gtk_css_value_color_get_fallback (property_id, provider, values, parent_values);
return gtk_css_value_color_get_fallback (property_id, provider, scale, values, parent_values);
return resolved;
}
+6 -3
View File
@@ -113,6 +113,7 @@ maybe_unref_section (gpointer section)
void
_gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *parent_values,
guint id,
GtkCssValue *specified,
@@ -142,7 +143,7 @@ _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
else
_gtk_css_value_ref (specified);
value = _gtk_css_value_compute (specified, id, provider, values, parent_values, &dependencies);
value = _gtk_css_value_compute (specified, id, provider, scale, values, parent_values, &dependencies);
_gtk_css_computed_values_set_value (values, id, value, dependencies, section);
@@ -445,6 +446,7 @@ gtk_css_computed_values_create_css_animations (GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
gint64 timestamp,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *source)
{
GtkCssValue *durations, *delays, *timing_functions, *animations;
@@ -489,7 +491,7 @@ gtk_css_computed_values_create_css_animations (GtkCssComputedValues *values,
if (keyframes == NULL)
continue;
keyframes = _gtk_css_keyframes_compute (keyframes, provider, values, parent_values);
keyframes = _gtk_css_keyframes_compute (keyframes, provider, scale, values, parent_values);
animation = _gtk_css_animation_new (name,
keyframes,
@@ -514,11 +516,12 @@ _gtk_css_computed_values_create_animations (GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
gint64 timestamp,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *source)
{
if (source != NULL)
gtk_css_computed_values_create_css_transitions (values, timestamp, source);
gtk_css_computed_values_create_css_animations (values, parent_values, timestamp, provider, source);
gtk_css_computed_values_create_css_animations (values, parent_values, timestamp, provider, scale, source);
}
GtkBitmask *
+2
View File
@@ -66,6 +66,7 @@ GtkCssComputedValues * _gtk_css_computed_values_new (void);
void _gtk_css_computed_values_compute_value (GtkCssComputedValues *values,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *parent_values,
guint id,
GtkCssValue *specified,
@@ -94,6 +95,7 @@ void _gtk_css_computed_values_create_animations (GtkCssCom
GtkCssComputedValues *parent_values,
gint64 timestamp,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *source);
GtkBitmask * _gtk_css_computed_values_advance (GtkCssComputedValues *values,
gint64 timestamp);
+3 -2
View File
@@ -40,6 +40,7 @@ static GtkCssValue *
gtk_css_value_corner_compute (GtkCssValue *corner,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -47,8 +48,8 @@ gtk_css_value_corner_compute (GtkCssValue *corner,
GtkCssValue *x, *y;
GtkCssDependencies x_deps, y_deps;
x = _gtk_css_value_compute (corner->x, property_id, provider, values, parent_values, &x_deps);
y = _gtk_css_value_compute (corner->y, property_id, provider, values, parent_values, &y_deps);
x = _gtk_css_value_compute (corner->x, property_id, provider, scale, values, parent_values, &x_deps);
y = _gtk_css_value_compute (corner->y, property_id, provider, scale, values, parent_values, &y_deps);
*dependencies = _gtk_css_dependencies_union (x_deps, y_deps);
if (x == corner->x && y == corner->y)
{
+1
View File
@@ -53,6 +53,7 @@ static GtkCssValue *
gtk_css_value_ease_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+1
View File
@@ -38,6 +38,7 @@ static GtkCssValue *
gtk_css_value_engine_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+2
View File
@@ -41,6 +41,7 @@ static GtkCssValue *
gtk_css_value_enum_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -164,6 +165,7 @@ static GtkCssValue *
gtk_css_value_font_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+5 -1
View File
@@ -28,6 +28,7 @@
#include "gtk/gtkcssimagegradientprivate.h"
#include "gtk/gtkcssimagelinearprivate.h"
#include "gtk/gtkcssimageurlprivate.h"
#include "gtk/gtkcssimagescaledprivate.h"
#include "gtk/gtkcssimagewin32private.h"
G_DEFINE_ABSTRACT_TYPE (GtkCssImage, _gtk_css_image, G_TYPE_OBJECT)
@@ -62,6 +63,7 @@ static GtkCssImage *
gtk_css_image_real_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -146,6 +148,7 @@ GtkCssImage *
_gtk_css_image_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -163,7 +166,7 @@ _gtk_css_image_compute (GtkCssImage *image,
klass = GTK_CSS_IMAGE_GET_CLASS (image);
return klass->compute (image, property_id, provider, values, parent_values, dependencies);
return klass->compute (image, property_id, provider, scale, values, parent_values, dependencies);
}
GtkCssImage *
@@ -417,6 +420,7 @@ gtk_css_image_get_parser_type (GtkCssParser *parser)
} image_types[] = {
{ "url", _gtk_css_image_url_get_type },
{ "-gtk-gradient", _gtk_css_image_gradient_get_type },
{ "-gtk-scaled", _gtk_css_image_scaled_get_type },
{ "-gtk-win32-theme-part", _gtk_css_image_win32_get_type },
{ "linear-gradient", _gtk_css_image_linear_get_type },
{ "repeating-linear-gradient", _gtk_css_image_linear_get_type },
+1
View File
@@ -34,6 +34,7 @@ static GtkCssImage *
gtk_css_image_gradient_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+4 -3
View File
@@ -420,6 +420,7 @@ static GtkCssImage *
gtk_css_image_linear_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -431,7 +432,7 @@ gtk_css_image_linear_compute (GtkCssImage *image,
copy = g_object_new (GTK_TYPE_CSS_IMAGE_LINEAR, NULL);
copy->repeating = linear->repeating;
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, values, parent_values, dependencies);
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, scale, values, parent_values, dependencies);
g_array_set_size (copy->stops, linear->stops->len);
for (i = 0; i < linear->stops->len; i++)
@@ -442,12 +443,12 @@ gtk_css_image_linear_compute (GtkCssImage *image,
stop = &g_array_index (linear->stops, GtkCssImageLinearColorStop, i);
scopy = &g_array_index (copy->stops, GtkCssImageLinearColorStop, i);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, values, parent_values, &child_deps);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, values, parent_values, &child_deps);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
}
else
+2
View File
@@ -58,6 +58,7 @@ struct _GtkCssImageClass
GtkCssImage *(* compute) (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies);
@@ -95,6 +96,7 @@ double _gtk_css_image_get_aspect_ratio (GtkCssImage *
GtkCssImage * _gtk_css_image_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies);
+205
View File
@@ -0,0 +1,205 @@
/*
* Copyright © 2013 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@gnome.org>
*/
#include "config.h"
#include "gtkcssimagescaledprivate.h"
G_DEFINE_TYPE (GtkCssImageScaled, _gtk_css_image_scaled, GTK_TYPE_CSS_IMAGE)
static int
gtk_css_image_scaled_get_width (GtkCssImage *image)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
return _gtk_css_image_get_width (scaled->images[scaled->scale - 1]) / scaled->scale;
}
static int
gtk_css_image_scaled_get_height (GtkCssImage *image)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
return _gtk_css_image_get_height (scaled->images[scaled->scale - 1]) / scaled->scale;
}
static double
gtk_css_image_scaled_get_aspect_ratio (GtkCssImage *image)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
return _gtk_css_image_get_aspect_ratio (scaled->images[scaled->scale - 1]);
}
static void
gtk_css_image_scaled_draw (GtkCssImage *image,
cairo_t *cr,
double width,
double height)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
_gtk_css_image_draw (scaled->images[scaled->scale - 1], cr, width, height);
}
static void
gtk_css_image_scaled_print (GtkCssImage *image,
GString *string)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
int i;
g_string_append (string, "-gtk-scaled(");
for (i = 0; i < scaled->n_images; i++)
{
_gtk_css_image_print (scaled->images[i], string);
if (i != scaled->n_images - 1)
g_string_append (string, ",");
}
g_string_append (string, ")");
}
static void
gtk_css_image_scaled_dispose (GObject *object)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (object);
int i;
for (i = 0; i < scaled->n_images; i++)
g_object_unref (scaled->images[i]);
g_free (scaled->images);
scaled->images = NULL;
G_OBJECT_CLASS (_gtk_css_image_scaled_parent_class)->dispose (object);
}
static GtkCssImage *
gtk_css_image_scaled_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
GtkCssImageScaled *copy;
int i;
scale = MAX(MIN (scale, scaled->n_images), 1);
if (scaled->scale == scale)
return g_object_ref (scaled);
else
{
copy = g_object_new (_gtk_css_image_scaled_get_type (), NULL);
copy->scale = scale;
copy->n_images = scaled->n_images;
copy->images = g_new (GtkCssImage *, scaled->n_images);
for (i = 0; i < scaled->n_images; i++)
{
if (i == scale - 1)
copy->images[i] = _gtk_css_image_compute (scaled->images[i],
property_id,
provider,
scale,
values,
parent_values,
dependencies);
else
copy->images[i] = g_object_ref (scaled->images[i]);
}
return GTK_CSS_IMAGE (copy);
}
}
static gboolean
gtk_css_image_scaled_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
GPtrArray *images;
GtkCssImage *child;
if (!_gtk_css_parser_try (parser, "-gtk-scaled", TRUE))
{
_gtk_css_parser_error (parser, "'-gtk-scaled'");
return FALSE;
}
if (!_gtk_css_parser_try (parser, "(", TRUE))
{
_gtk_css_parser_error (parser,
"Expected '(' after '-gtk-scaled'");
return FALSE;
}
images = g_ptr_array_new_with_free_func (g_object_unref);
do
{
child = _gtk_css_image_new_parse (parser);
if (child == NULL)
{
g_ptr_array_free (images, TRUE);
return FALSE;
}
g_ptr_array_add (images, child);
}
while ( _gtk_css_parser_try (parser, ",", TRUE));
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
g_ptr_array_free (images, TRUE);
_gtk_css_parser_error (parser,
"Expected ')' at end of '-gtk-scaled'");
return FALSE;
}
scaled->n_images = images->len;
scaled->images = (GtkCssImage **) g_ptr_array_free (images, FALSE);
return TRUE;
}
static void
_gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass)
{
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
image_class->get_width = gtk_css_image_scaled_get_width;
image_class->get_height = gtk_css_image_scaled_get_height;
image_class->get_aspect_ratio = gtk_css_image_scaled_get_aspect_ratio;
image_class->draw = gtk_css_image_scaled_draw;
image_class->parse = gtk_css_image_scaled_parse;
image_class->compute = gtk_css_image_scaled_compute;
image_class->print = gtk_css_image_scaled_print;
object_class->dispose = gtk_css_image_scaled_dispose;
}
static void
_gtk_css_image_scaled_init (GtkCssImageScaled *image_scaled)
{
image_scaled->scale = 1;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright © 2013 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@gnome.org>
*/
#ifndef __GTK_CSS_IMAGE_SCALED_PRIVATE_H__
#define __GTK_CSS_IMAGE_SCALED_PRIVATE_H__
#include "gtk/gtkcssimageprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_CSS_IMAGE_SCALED (_gtk_css_image_scaled_get_type ())
#define GTK_CSS_IMAGE_SCALED(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_SCALED, GtkCssImageScaled))
#define GTK_CSS_IMAGE_SCALED_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_SCALED, GtkCssImageScaledClass))
#define GTK_IS_CSS_IMAGE_SCALED(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_SCALED))
#define GTK_IS_CSS_IMAGE_SCALED_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMAGE_SCALED))
#define GTK_CSS_IMAGE_SCALED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMAGE_SCALED, GtkCssImageScaledClass))
typedef struct _GtkCssImageScaled GtkCssImageScaled;
typedef struct _GtkCssImageScaledClass GtkCssImageScaledClass;
struct _GtkCssImageScaled
{
GtkCssImage parent;
int scale;
GtkCssImage **images;
int n_images;
};
struct _GtkCssImageScaledClass
{
GtkCssImageClass parent_class;
};
GType _gtk_css_image_scaled_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GTK_CSS_IMAGE_SCALED_PRIVATE_H__ */
+1 -9
View File
@@ -142,20 +142,12 @@ _gtk_css_image_surface_new_for_pixbuf (GdkPixbuf *pixbuf)
{
GtkCssImage *image;
cairo_surface_t *surface;
cairo_t *cr;
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
cr = cairo_create (surface);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
image = _gtk_css_image_surface_new (surface);
cairo_surface_destroy (surface);
return image;
+1
View File
@@ -120,6 +120,7 @@ static GtkCssImage *
gtk_css_image_url_compute (GtkCssImage *image,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+2 -1
View File
@@ -37,6 +37,7 @@ static GtkCssValue *
gtk_css_value_image_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -48,7 +49,7 @@ gtk_css_value_image_compute (GtkCssValue *value,
if (image == NULL)
return _gtk_css_value_ref (value);
computed = _gtk_css_image_compute (image, property_id, provider, values, parent_values, dependencies);
computed = _gtk_css_image_compute (image, property_id, provider, scale, values, parent_values, dependencies);
if (computed == image)
{
+2
View File
@@ -37,6 +37,7 @@ static GtkCssValue *
gtk_css_value_inherit_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -51,6 +52,7 @@ gtk_css_value_inherit_compute (GtkCssValue *value,
return _gtk_css_value_compute (_gtk_css_initial_value_get (),
property_id,
provider,
scale,
values,
parent_values,
dependencies);
+2
View File
@@ -40,6 +40,7 @@ static GtkCssValue *
gtk_css_value_initial_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -80,6 +81,7 @@ gtk_css_value_initial_compute (GtkCssValue *value,
return _gtk_css_value_compute (_gtk_css_style_property_get_initial_value (_gtk_css_style_property_lookup_by_id (property_id)),
property_id,
provider,
scale,
values,
parent_values,
dependencies);
+2
View File
@@ -427,6 +427,7 @@ _gtk_css_keyframes_print (GtkCssKeyframes *keyframes,
GtkCssKeyframes *
_gtk_css_keyframes_compute (GtkCssKeyframes *keyframes,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values)
{
@@ -455,6 +456,7 @@ _gtk_css_keyframes_compute (GtkCssKeyframes *keyframes,
KEYFRAMES_VALUE (resolved, k, p) = _gtk_css_value_compute (KEYFRAMES_VALUE (keyframes, k, p),
resolved->property_ids[p],
provider,
scale,
values,
parent_values,
NULL);
+1
View File
@@ -38,6 +38,7 @@ void _gtk_css_keyframes_print (GtkCssKeyframes
GtkCssKeyframes * _gtk_css_keyframes_compute (GtkCssKeyframes *keyframes,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values);
+2
View File
@@ -140,6 +140,7 @@ _gtk_css_lookup_set_computed (GtkCssLookup *lookup,
void
_gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values)
{
@@ -164,6 +165,7 @@ _gtk_css_lookup_resolve (GtkCssLookup *lookup,
_gtk_bitmask_get (lookup->missing, i))
_gtk_css_computed_values_compute_value (values,
provider,
scale,
parent_values,
i,
lookup->values[i].value,
+1
View File
@@ -55,6 +55,7 @@ void _gtk_css_lookup_set_computed (GtkCssLookup
GtkCssValue *value);
void _gtk_css_lookup_resolve (GtkCssLookup *lookup,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values);
+1
View File
@@ -59,6 +59,7 @@ static GtkCssValue *
gtk_css_value_number_compute (GtkCssValue *number,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+3 -2
View File
@@ -40,6 +40,7 @@ static GtkCssValue *
gtk_css_value_position_compute (GtkCssValue *position,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -47,8 +48,8 @@ gtk_css_value_position_compute (GtkCssValue *position,
GtkCssValue *x, *y;
GtkCssDependencies x_deps, y_deps;
x = _gtk_css_value_compute (position->x, property_id, provider, values, parent_values, &x_deps);
y = _gtk_css_value_compute (position->y, property_id, provider, values, parent_values, &y_deps);
x = _gtk_css_value_compute (position->x, property_id, provider, scale, values, parent_values, &x_deps);
y = _gtk_css_value_compute (position->y, property_id, provider, scale, values, parent_values, &y_deps);
*dependencies = _gtk_css_dependencies_union (x_deps, y_deps);
if (x == position->x && y == position->y)
{
+1
View File
@@ -37,6 +37,7 @@ static GtkCssValue *
gtk_css_value_repeat_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+1
View File
@@ -37,6 +37,7 @@ static GtkCssValue *
gtk_css_value_rgba_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+2 -1
View File
@@ -51,6 +51,7 @@ static GtkCssValue *
gtk_css_value_shadows_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -65,7 +66,7 @@ gtk_css_value_shadows_compute (GtkCssValue *value,
result = gtk_css_shadows_value_new (value->values, value->len);
for (i = 0; i < value->len; i++)
{
result->values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, values, parent_values, &child_deps);
result->values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
}
+6 -5
View File
@@ -70,6 +70,7 @@ static GtkCssValue *
gtk_css_value_shadow_compute (GtkCssValue *shadow,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -78,23 +79,23 @@ gtk_css_value_shadow_compute (GtkCssValue *shadow,
GtkCssDependencies child_deps;
child_deps = 0;
hoffset = _gtk_css_value_compute (shadow->hoffset, property_id, provider, values, parent_values, &child_deps);
hoffset = _gtk_css_value_compute (shadow->hoffset, property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
child_deps = 0;
voffset = _gtk_css_value_compute (shadow->voffset, property_id, provider, values, parent_values, &child_deps);
voffset = _gtk_css_value_compute (shadow->voffset, property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
child_deps = 0;
radius = _gtk_css_value_compute (shadow->radius, property_id, provider, values, parent_values, &child_deps);
radius = _gtk_css_value_compute (shadow->radius, property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
child_deps = 0;
spread = _gtk_css_value_compute (shadow->spread, property_id, provider, values, parent_values, &child_deps),
spread = _gtk_css_value_compute (shadow->spread, property_id, provider, scale, values, parent_values, &child_deps),
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
child_deps = 0;
color = _gtk_css_value_compute (shadow->color, property_id, provider, values, parent_values, &child_deps);
color = _gtk_css_value_compute (shadow->color, property_id, provider, scale, values, parent_values, &child_deps);
*dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
return gtk_css_shadow_value_new (hoffset, voffset, radius, spread, shadow->inset, color);
+1
View File
@@ -37,6 +37,7 @@ static GtkCssValue *
gtk_css_value_string_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+2 -9
View File
@@ -766,7 +766,6 @@ pattern_value_parse (GtkCssParser *parser,
GFile *file;
cairo_surface_t *surface;
cairo_pattern_t *pattern;
cairo_t *cr;
cairo_matrix_t matrix;
file = _gtk_css_parser_read_url (parser);
@@ -784,21 +783,15 @@ pattern_value_parse (GtkCssParser *parser,
return FALSE;
}
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
cr = cairo_create (surface);
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
cairo_paint (cr);
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
pattern = cairo_pattern_create_for_surface (surface);
cairo_surface_destroy (surface);
cairo_matrix_init_scale (&matrix,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
cairo_pattern_set_matrix (pattern, &matrix);
cairo_surface_destroy (surface);
cairo_destroy (cr);
g_object_unref (pixbuf);
g_value_take_boxed (value, pattern);
+1
View File
@@ -38,6 +38,7 @@ static GtkCssValue *
gtk_css_value_typed_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
+2 -1
View File
@@ -88,6 +88,7 @@ GtkCssValue *
_gtk_css_value_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies)
@@ -103,7 +104,7 @@ _gtk_css_value_compute (GtkCssValue *value,
dependencies = &fallback;
*dependencies = 0;
return value->class->compute (value, property_id, provider, values, parent_values, dependencies);
return value->class->compute (value, property_id, provider, scale, values, parent_values, dependencies);
}
gboolean
+2
View File
@@ -43,6 +43,7 @@ struct _GtkCssValueClass {
GtkCssValue * (* compute) (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies);
@@ -68,6 +69,7 @@ void _gtk_css_value_unref (GtkCssValue
GtkCssValue *_gtk_css_value_compute (GtkCssValue *value,
guint property_id,
GtkStyleProviderPrivate *provider,
int scale,
GtkCssComputedValues *values,
GtkCssComputedValues *parent_values,
GtkCssDependencies *dependencies);
+6
View File
@@ -3047,6 +3047,10 @@ realize_icon_info (GtkWidget *widget,
gtk_widget_register_window (widget, icon_info->window);
gtk_widget_queue_resize (widget);
_gtk_icon_helper_set_window (icon_info->icon_helper,
gtk_widget_get_window (widget));
}
static EntryIconInfo*
@@ -3233,6 +3237,8 @@ gtk_entry_unrealize (GtkWidget *widget)
{
if ((icon_info = priv->icons[i]) != NULL)
{
_gtk_icon_helper_set_window (icon_info->icon_helper, NULL);
if (icon_info->window != NULL)
{
gtk_widget_unregister_window (widget, icon_info->window);
+97 -77
View File
@@ -1321,7 +1321,7 @@ change_icon_theme_get_info_cb (GCancellable *cancellable,
gpointer user_data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
struct ChangeIconThemeData *data = user_data;
if (!g_slist_find (data->button->priv->change_icon_theme_cancellables, cancellable))
@@ -1333,15 +1333,15 @@ change_icon_theme_get_info_cb (GCancellable *cancellable,
if (cancelled || error)
goto out;
pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size);
surface = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size);
if (pixbuf)
if (surface)
{
gint width = 0;
GtkTreeIter iter;
GtkTreePath *path;
width = MAX (width, gdk_pixbuf_get_width (pixbuf));
width = MAX (width, data->button->priv->icon_size);
path = gtk_tree_row_reference_get_path (data->row_ref);
if (path)
@@ -1350,14 +1350,14 @@ change_icon_theme_get_info_cb (GCancellable *cancellable,
gtk_tree_path_free (path);
gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
-1);
g_object_set (data->button->priv->icon_cell,
"width", width,
NULL);
}
g_object_unref (pixbuf);
cairo_surface_destroy (surface);
}
out:
@@ -1398,7 +1398,7 @@ change_icon_theme (GtkFileChooserButton *button)
do
{
GdkPixbuf *pixbuf = NULL;
cairo_surface_t *surface = NULL;
gchar type;
gpointer data;
@@ -1435,39 +1435,47 @@ change_icon_theme (GtkFileChooserButton *button)
info);
button->priv->change_icon_theme_cancellables =
g_slist_append (button->priv->change_icon_theme_cancellables, cancellable);
pixbuf = NULL;
surface = NULL;
}
else
/* Don't call get_info for remote paths to avoid latency and
* auth dialogs.
* If we switch to a better bookmarks file format (XBEL), we
* should use mime info to get a better icon.
*/
pixbuf = gtk_icon_theme_load_icon (theme, "folder-remote",
priv->icon_size, 0, NULL);
{
/* Don't call get_info for remote paths to avoid latency and
* auth dialogs.
* If we switch to a better bookmarks file format (XBEL), we
* should use mime info to get a better icon.
*/
surface = gtk_icon_theme_load_surface (theme, "folder-remote",
priv->icon_size,
gtk_widget_get_scale_factor (GTK_WIDGET (button)),
gtk_widget_get_window (GTK_WIDGET (button)),
0, NULL);
}
}
break;
case ROW_TYPE_VOLUME:
if (data)
pixbuf = _gtk_file_system_volume_render_icon (data,
GTK_WIDGET (button),
priv->icon_size,
NULL);
{
surface = _gtk_file_system_volume_render_icon (data,
GTK_WIDGET (button),
priv->icon_size,
NULL);
}
break;
default:
continue;
break;
}
if (pixbuf)
width = MAX (width, gdk_pixbuf_get_width (pixbuf));
if (surface)
width = MAX (width, priv->icon_size);
gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
-1);
if (pixbuf)
g_object_unref (pixbuf);
if (surface)
cairo_surface_destroy (surface);
}
while (gtk_tree_model_iter_next (priv->model, &iter));
@@ -1526,7 +1534,7 @@ set_info_get_info_cb (GCancellable *cancellable,
gpointer callback_data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
GtkTreePath *path;
GtkTreeIter iter;
GCancellable *model_cancellable = NULL;
@@ -1560,7 +1568,7 @@ set_info_get_info_cb (GCancellable *cancellable,
/* There was an error, leave the fallback name in there */
goto out;
pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size);
surface = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size);
if (!data->label)
data->label = g_strdup (g_file_info_get_display_name (info));
@@ -1568,13 +1576,13 @@ set_info_get_info_cb (GCancellable *cancellable,
is_folder = _gtk_file_info_consider_as_directory (info);
gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
DISPLAY_NAME_COLUMN, data->label,
IS_FOLDER_COLUMN, is_folder,
-1);
if (pixbuf)
g_object_unref (pixbuf);
if (surface)
cairo_surface_destroy (surface);
out:
g_object_unref (data->button);
@@ -1716,7 +1724,7 @@ model_add_special_get_info_cb (GCancellable *cancellable,
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GtkTreeIter iter;
GtkTreePath *path;
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
GCancellable *model_cancellable = NULL;
struct ChangeIconThemeData *data = user_data;
gchar *name;
@@ -1746,14 +1754,13 @@ model_add_special_get_info_cb (GCancellable *cancellable,
if (cancelled || error)
goto out;
pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size);
if (pixbuf)
surface = _gtk_file_info_render_icon (info, GTK_WIDGET (data->button), data->button->priv->icon_size);
if (surface)
{
gtk_list_store_set (GTK_LIST_STORE (data->button->priv->model), &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
-1);
g_object_unref (pixbuf);
cairo_surface_destroy (surface);
}
gtk_tree_model_get (data->button->priv->model, &iter,
@@ -1881,7 +1888,7 @@ model_add_volumes (GtkFileChooserButton *button,
{
GtkFileSystemVolume *volume;
GtkTreeIter iter;
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
gchar *display_name;
volume = l->data;
@@ -1906,23 +1913,23 @@ model_add_volumes (GtkFileChooserButton *button,
}
}
pixbuf = _gtk_file_system_volume_render_icon (volume,
GTK_WIDGET (button),
button->priv->icon_size,
NULL);
surface = _gtk_file_system_volume_render_icon (volume,
GTK_WIDGET (button),
button->priv->icon_size,
NULL);
display_name = _gtk_file_system_volume_get_display_name (volume);
gtk_list_store_insert (store, &iter, pos);
gtk_list_store_set (store, &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
DISPLAY_NAME_COLUMN, display_name,
TYPE_COLUMN, ROW_TYPE_VOLUME,
DATA_COLUMN, _gtk_file_system_volume_ref (volume),
IS_FOLDER_COLUMN, TRUE,
-1);
if (pixbuf)
g_object_unref (pixbuf);
if (surface)
cairo_surface_destroy (surface);
g_free (display_name);
button->priv->n_volumes++;
@@ -1971,7 +1978,7 @@ model_add_bookmarks (GtkFileChooserButton *button,
{
gchar *label;
GtkIconTheme *icon_theme;
GdkPixbuf *pixbuf;
cairo_surface_t *surface = NULL;
if (local_only)
continue;
@@ -1986,12 +1993,15 @@ model_add_bookmarks (GtkFileChooserButton *button,
label = _gtk_file_chooser_label_for_file (file);
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button)));
pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote",
button->priv->icon_size, 0, NULL);
surface = gtk_icon_theme_load_surface (icon_theme, "folder-remote",
button->priv->icon_size,
gtk_widget_get_scale_factor (GTK_WIDGET (button)),
gtk_widget_get_window (GTK_WIDGET (button)),
0, NULL);
gtk_list_store_insert (store, &iter, pos);
gtk_list_store_set (store, &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
DISPLAY_NAME_COLUMN, label,
TYPE_COLUMN, ROW_TYPE_BOOKMARK,
DATA_COLUMN, g_object_ref (file),
@@ -1999,7 +2009,8 @@ model_add_bookmarks (GtkFileChooserButton *button,
-1);
g_free (label);
g_object_unref (pixbuf);
if (surface)
cairo_surface_destroy (surface);
}
button->priv->n_bookmarks++;
@@ -2077,7 +2088,7 @@ model_update_current_folder (GtkFileChooserButton *button,
{
gchar *label;
GtkIconTheme *icon_theme;
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
/* Don't call get_info for remote paths to avoid latency and
* auth dialogs.
@@ -2091,14 +2102,20 @@ model_update_current_folder (GtkFileChooserButton *button,
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button)));
if (g_file_is_native (file))
pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder",
button->priv->icon_size, 0, NULL);
surface = gtk_icon_theme_load_surface (icon_theme, "folder",
button->priv->icon_size,
gtk_widget_get_scale_factor (GTK_WIDGET (button)),
gtk_widget_get_window (GTK_WIDGET (button)),
0, NULL);
else
pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote",
button->priv->icon_size, 0, NULL);
surface = gtk_icon_theme_load_surface (icon_theme, "folder-remote",
button->priv->icon_size,
gtk_widget_get_scale_factor (GTK_WIDGET (button)),
gtk_widget_get_window (GTK_WIDGET (button)),
0, NULL);
gtk_list_store_set (store, &iter,
ICON_COLUMN, pixbuf,
ICON_COLUMN, surface,
DISPLAY_NAME_COLUMN, label,
TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER,
DATA_COLUMN, g_object_ref (file),
@@ -2106,7 +2123,8 @@ model_update_current_folder (GtkFileChooserButton *button,
-1);
g_free (label);
g_object_unref (pixbuf);
if (surface)
cairo_surface_destroy (surface);
}
}
@@ -2442,7 +2460,7 @@ update_label_get_info_cb (GCancellable *cancellable,
gpointer data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
GtkFileChooserButton *button = data;
GtkFileChooserButtonPrivate *priv = button->priv;
@@ -2456,11 +2474,10 @@ update_label_get_info_cb (GCancellable *cancellable,
gtk_label_set_text (GTK_LABEL (priv->label), g_file_info_get_display_name (info));
pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (priv->image), priv->icon_size);
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
surface = _gtk_file_info_render_icon (info, GTK_WIDGET (priv->image), priv->icon_size);
gtk_image_set_from_surface (GTK_IMAGE (priv->image), surface);
if (surface)
cairo_surface_destroy (surface);
out:
emit_selection_changed_if_changing_selection (button);
@@ -2500,16 +2517,16 @@ update_label_and_image (GtkFileChooserButton *button)
base_file = _gtk_file_system_volume_get_root (volume);
if (base_file && g_file_equal (base_file, file))
{
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
label_text = _gtk_file_system_volume_get_display_name (volume);
pixbuf = _gtk_file_system_volume_render_icon (volume,
GTK_WIDGET (button),
priv->icon_size,
NULL);
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
surface = _gtk_file_system_volume_render_icon (volume,
GTK_WIDGET (button),
priv->icon_size,
NULL);
gtk_image_set_from_surface (GTK_IMAGE (priv->image), surface);
if (surface)
cairo_surface_destroy (surface);
}
if (base_file)
@@ -2534,15 +2551,18 @@ update_label_and_image (GtkFileChooserButton *button)
}
else
{
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
label_text = _gtk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)),
"text-x-generic",
priv->icon_size, 0, NULL);
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
surface = gtk_icon_theme_load_surface (get_icon_theme (GTK_WIDGET (priv->image)),
"text-x-generic",
priv->icon_size,
gtk_widget_get_scale_factor (GTK_WIDGET (button)),
gtk_widget_get_window (GTK_WIDGET (button)),
0, NULL);
gtk_image_set_from_surface (GTK_IMAGE (priv->image), surface);
if (surface)
cairo_surface_destroy (surface);
done_changing_selection = TRUE;
}
@@ -2566,7 +2586,7 @@ out:
else
{
gtk_label_set_text (GTK_LABEL (priv->label), _(FALLBACK_DISPLAY_NAME));
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
gtk_image_set_from_surface (GTK_IMAGE (priv->image), NULL);
}
if (done_changing_selection)
+2 -2
View File
@@ -84,7 +84,7 @@
<child>
<object class="GtkCellRendererPixbuf" id="icon_cell"/>
<attributes>
<attribute name="pixbuf">0</attribute>
<attribute name="surface">0</attribute>
</attributes>
</child>
<child>
@@ -104,7 +104,7 @@
<object class="GtkListStore" id="model">
<columns>
<!-- column-name icon -->
<column type="GdkPixbuf"/>
<column type="CairoSurface"/>
<!-- column-name display-name -->
<column type="gchararray"/>
<!-- column-name type -->
+7 -6
View File
@@ -76,6 +76,7 @@
#include "gtkorientable.h"
#include "gtkintl.h"
#include <cairo-gobject.h>
#include <errno.h>
#include <string.h>
#include <time.h>
@@ -364,7 +365,7 @@ enum {
MODEL_COL_NAME_COLLATED,
MODEL_COL_IS_FOLDER,
MODEL_COL_IS_SENSITIVE,
MODEL_COL_PIXBUF,
MODEL_COL_SURFACE,
MODEL_COL_SIZE_TEXT,
MODEL_COL_MTIME_TEXT,
MODEL_COL_ELLIPSIZE,
@@ -381,7 +382,7 @@ enum {
G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */ \
G_TYPE_BOOLEAN, /* MODEL_COL_IS_SENSITIVE */ \
GDK_TYPE_PIXBUF, /* MODEL_COL_PIXBUF */ \
CAIRO_GOBJECT_TYPE_SURFACE, /* MODEL_COL_SURFACE */ \
G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */ \
G_TYPE_STRING, /* MODEL_COL_MTIME_TEXT */ \
PANGO_TYPE_ELLIPSIZE_MODE /* MODEL_COL_ELLIPSIZE */
@@ -3132,7 +3133,7 @@ change_icon_theme (GtkFileChooserDefault *impl)
set_icon_cell_renderer_fixed_size (impl);
if (priv->browse_files_model)
_gtk_file_system_model_clear_cache (priv->browse_files_model, MODEL_COL_PIXBUF);
_gtk_file_system_model_clear_cache (priv->browse_files_model, MODEL_COL_SURFACE);
gtk_widget_queue_resize (priv->browse_files_tree_view);
profile_end ("end", NULL);
@@ -4152,12 +4153,12 @@ file_system_model_set (GtkFileSystemModel *model,
else
g_value_set_boolean (value, TRUE);
break;
case MODEL_COL_PIXBUF:
case MODEL_COL_SURFACE:
if (info)
{
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
{
g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), priv->icon_size));
g_value_take_boxed (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), priv->icon_size));
}
else
{
@@ -7069,7 +7070,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
if (GTK_IS_CELL_RENDERER_PIXBUF (renderer))
{
gtk_tree_view_column_set_attributes (column, renderer,
"pixbuf", MODEL_COL_PIXBUF,
"surface", MODEL_COL_SURFACE,
NULL);
}
else
+40 -28
View File
@@ -709,42 +709,45 @@ _gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
return file;
}
static GdkPixbuf *
get_pixbuf_from_gicon (GIcon *icon,
GtkWidget *widget,
gint icon_size,
GError **error)
static cairo_surface_t *
get_surface_from_gicon (GIcon *icon,
GtkWidget *widget,
gint icon_size,
GError **error)
{
GdkScreen *screen;
GtkIconTheme *icon_theme;
GtkIconInfo *icon_info;
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
screen = gtk_widget_get_screen (GTK_WIDGET (widget));
icon_theme = gtk_icon_theme_get_for_screen (screen);
icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme,
icon,
icon_size,
GTK_ICON_LOOKUP_USE_BUILTIN);
icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme,
icon,
icon_size,
gtk_widget_get_scale_factor (widget),
GTK_ICON_LOOKUP_USE_BUILTIN);
if (!icon_info)
return NULL;
pixbuf = gtk_icon_info_load_icon (icon_info, error);
surface = gtk_icon_info_load_surface (icon_info,
gtk_widget_get_window (widget), error);
g_object_unref (icon_info);
return pixbuf;
return surface;
}
GdkPixbuf *
cairo_surface_t *
_gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
GtkWidget *widget,
gint icon_size,
GError **error)
{
GIcon *icon = NULL;
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
DEBUG ("volume_get_icon_name");
@@ -760,11 +763,11 @@ _gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
if (!icon)
return NULL;
pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, error);
surface = get_surface_from_gicon (icon, widget, icon_size, error);
g_object_unref (icon);
return pixbuf;
return surface;
}
GtkFileSystemVolume *
@@ -795,39 +798,48 @@ _gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
}
/* GFileInfo helper functions */
GdkPixbuf *
cairo_surface_t *
_gtk_file_info_render_icon (GFileInfo *info,
GtkWidget *widget,
gint icon_size)
GtkWidget *widget,
gint icon_size)
{
GIcon *icon;
GdkPixbuf *pixbuf = NULL;
GdkPixbuf *pixbuf;
const gchar *thumbnail_path;
cairo_surface_t *surface = NULL;
int scale;
thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
if (thumbnail_path)
pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
icon_size, icon_size,
NULL);
{
scale = gtk_widget_get_scale_factor (widget);
pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
icon_size*scale, icon_size*scale,
NULL);
if (!pixbuf)
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale,
gtk_widget_get_window (widget));
g_object_unref (pixbuf);
}
if (!surface)
{
icon = g_file_info_get_icon (info);
if (icon)
pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
surface = get_surface_from_gicon (icon, widget, icon_size, NULL);
if (!pixbuf)
if (!surface)
{
/* Use general fallback for all files without icon */
icon = g_themed_icon_new ("text-x-generic");
pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
surface = get_surface_from_gicon (icon, widget, icon_size, NULL);
g_object_unref (icon);
}
}
return pixbuf;
return surface;
}
gboolean
+4 -4
View File
@@ -93,7 +93,7 @@ GtkFileSystemVolume * _gtk_file_system_get_volume_for_file (GtkFileSystem
gchar * _gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume);
gboolean _gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume);
GFile * _gtk_file_system_volume_get_root (GtkFileSystemVolume *volume);
GdkPixbuf * _gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
cairo_surface_t * _gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
GtkWidget *widget,
gint icon_size,
GError **error);
@@ -102,9 +102,9 @@ GtkFileSystemVolume *_gtk_file_system_volume_ref (GtkFileSystemVol
void _gtk_file_system_volume_unref (GtkFileSystemVolume *volume);
/* GFileInfo helper functions */
GdkPixbuf * _gtk_file_info_render_icon (GFileInfo *info,
GtkWidget *widget,
gint icon_size);
cairo_surface_t * _gtk_file_info_render_icon (GFileInfo *info,
GtkWidget *widget,
gint icon_size);
gboolean _gtk_file_info_consider_as_directory (GFileInfo *info);
+112 -44
View File
@@ -995,12 +995,14 @@ static GdkPixbuf *find_in_cache (GtkIconSet *icon_set,
GtkStyleContext *style_context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size);
GtkIconSize size,
gint scale);
static void add_to_cache (GtkIconSet *icon_set,
GtkStyleContext *style_context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size,
gint scale,
GdkPixbuf *pixbuf);
/* Clear icon set contents, drop references to all contained
* GdkPixbuf objects and forget all GtkIconSources. Used to
@@ -1289,7 +1291,8 @@ ensure_filename_pixbuf (GtkIconSet *icon_set,
static GdkPixbuf *
render_icon_name_pixbuf (GtkIconSource *icon_source,
GtkStyleContext *context,
GtkIconSize size)
GtkIconSize size,
gint scale)
{
GdkPixbuf *pixbuf;
GdkPixbuf *tmp_pixbuf;
@@ -1359,9 +1362,10 @@ render_icon_name_pixbuf (GtkIconSource *icon_source,
names[1] = icon_source->source.icon_name;
names[2] = NULL;
info = gtk_icon_theme_choose_icon (icon_theme,
(const char **) names,
pixel_size, GTK_ICON_LOOKUP_USE_BUILTIN);
info = gtk_icon_theme_choose_icon_for_scale (icon_theme,
(const char **) names,
pixel_size, scale,
GTK_ICON_LOOKUP_USE_BUILTIN);
g_free (names[0]);
if (info)
{
@@ -1373,10 +1377,10 @@ render_icon_name_pixbuf (GtkIconSource *icon_source,
}
else
{
tmp_pixbuf = gtk_icon_theme_load_icon (icon_theme,
icon_source->source.icon_name,
pixel_size, 0,
&error);
tmp_pixbuf = gtk_icon_theme_load_icon_for_scale (icon_theme,
icon_source->source.icon_name,
pixel_size, scale, 0,
&error);
}
if (!tmp_pixbuf)
@@ -1407,7 +1411,8 @@ find_and_render_icon_source (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size)
GtkIconSize size,
gint scale)
{
GSList *failed = NULL;
GdkPixbuf *pixbuf = NULL;
@@ -1442,10 +1447,21 @@ find_and_render_icon_source (GtkIconSet *icon_set,
g_warning ("Failed to render icon");
failed = g_slist_prepend (failed, source);
}
if (scale != 1)
{
GdkPixbuf *tmp = pixbuf;
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
gdk_pixbuf_get_width (pixbuf) * scale,
gdk_pixbuf_get_height (pixbuf) * scale,
GDK_INTERP_BILINEAR);
g_object_unref (tmp);
}
break;
case GTK_ICON_SOURCE_ICON_NAME:
case GTK_ICON_SOURCE_STATIC_ICON_NAME:
pixbuf = render_icon_name_pixbuf (source, context, size);
pixbuf = render_icon_name_pixbuf (source, context,
size, scale);
if (!pixbuf)
failed = g_slist_prepend (failed, source);
break;
@@ -1489,6 +1505,51 @@ render_fallback_image (GtkStyleContext *context,
return gtk_render_icon_pixbuf (context, &fallback_source, size);
}
static GdkPixbuf*
gtk_icon_set_render_icon_pixbuf_for_scale (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size,
gint scale)
{
GdkPixbuf *icon = NULL;
GtkStateFlags flags = 0;
GtkStateType state;
GtkTextDirection direction;
g_return_val_if_fail (icon_set != NULL, NULL);
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
flags = gtk_style_context_get_state (context);
if (flags & GTK_STATE_FLAG_INSENSITIVE)
state = GTK_STATE_INSENSITIVE;
else if (flags & GTK_STATE_FLAG_PRELIGHT)
state = GTK_STATE_PRELIGHT;
else
state = GTK_STATE_NORMAL;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
direction = gtk_style_context_get_direction (context);
G_GNUC_END_IGNORE_DEPRECATIONS;
if (icon_set->sources)
{
icon = find_in_cache (icon_set, context, direction, state, size, scale);
if (icon)
return g_object_ref (icon);
}
if (icon_set->sources)
icon = find_and_render_icon_source (icon_set, context, direction, state,
size, scale);
if (icon == NULL)
icon = render_fallback_image (context, direction, state, size);
add_to_cache (icon_set, context, direction, state, size, scale, icon);
return icon;
}
/**
* gtk_icon_set_render_icon_pixbuf:
* @icon_set: a #GtkIconSet
@@ -1514,45 +1575,48 @@ gtk_icon_set_render_icon_pixbuf (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size)
{
GdkPixbuf *icon = NULL;
GtkStateFlags flags = 0;
GtkStateType state;
GtkTextDirection direction;
g_return_val_if_fail (icon_set != NULL, NULL);
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
flags = gtk_style_context_get_state (context);
if (flags & GTK_STATE_FLAG_INSENSITIVE)
state = GTK_STATE_INSENSITIVE;
else if (flags & GTK_STATE_FLAG_PRELIGHT)
state = GTK_STATE_PRELIGHT;
else
state = GTK_STATE_NORMAL;
return gtk_icon_set_render_icon_pixbuf_for_scale (icon_set, context, size, 1);
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
direction = gtk_style_context_get_direction (context);
G_GNUC_END_IGNORE_DEPRECATIONS;
/**
* gtk_icon_set_render_icon_surface:
* @icon_set: a #GtkIconSet
* @context: a #GtkStyleContext
* @size: (type int): icon size. A size of (GtkIconSize)-1
* means render at the size of the source and don't scale.
* @scale: the window scale to render for
* @for_window: (allow-none): #GdkWindow to optimize drawing for, or %NULL
*
* Renders an icon using gtk_render_icon_pixbuf() and converts it to a
* cairo surface.
*
* This function never returns %NULL; if the icon can't be rendered
* (perhaps because an image file fails to load), a default "missing
* image" icon will be returned instead.
*
* Return value: (transfer full): a #cairo_surface_t to be displayed
*
* Since: 3.10
*/
cairo_surface_t *
gtk_icon_set_render_icon_surface (GtkIconSet *icon_set,
GtkStyleContext *context,
GtkIconSize size,
gint scale,
GdkWindow *for_window)
{
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
if (icon_set->sources)
{
icon = find_in_cache (icon_set, context, direction, state, size);
if (icon)
{
g_object_ref (icon);
return icon;
}
}
pixbuf = gtk_icon_set_render_icon_pixbuf_for_scale (icon_set, context, size, scale);
if (icon_set->sources)
icon = find_and_render_icon_source (icon_set, context, direction, state, size);
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, for_window);
g_object_unref (pixbuf);
if (icon == NULL)
icon = render_fallback_image (context, direction, state, size);
add_to_cache (icon_set, context, direction, state, size, icon);
return icon;
return surface;
}
/**
@@ -2402,6 +2466,7 @@ struct _CachedIcon
GtkTextDirection direction;
GtkStateType state;
GtkIconSize size;
gint scale;
GdkPixbuf *pixbuf;
};
@@ -2430,7 +2495,8 @@ find_in_cache (GtkIconSet *icon_set,
GtkStyleContext *style_context,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size)
GtkIconSize size,
gint scale)
{
GSList *tmp_list;
GSList *prev;
@@ -2472,6 +2538,7 @@ add_to_cache (GtkIconSet *icon_set,
GtkTextDirection direction,
GtkStateType state,
GtkIconSize size,
gint scale,
GdkPixbuf *pixbuf)
{
CachedIcon *icon;
@@ -2488,6 +2555,7 @@ add_to_cache (GtkIconSet *icon_set,
icon->direction = direction;
icon->state = state;
icon->size = size;
icon->scale = scale;
icon->pixbuf = pixbuf;
attach_to_style (icon_set, icon->style);
+469 -24
View File
@@ -19,6 +19,7 @@
#include "config.h"
#include <math.h>
#include "gtkiconhelperprivate.h"
G_DEFINE_TYPE (GtkIconHelper, _gtk_icon_helper, G_TYPE_OBJECT)
@@ -26,12 +27,16 @@ G_DEFINE_TYPE (GtkIconHelper, _gtk_icon_helper, G_TYPE_OBJECT)
struct _GtkIconHelperPrivate {
GtkImageType storage_type;
GdkWindow *window;
GdkPixbuf *orig_pixbuf;
int orig_pixbuf_scale;
GdkPixbufAnimation *animation;
GIcon *gicon;
GtkIconSet *icon_set;
gchar *icon_name;
gchar *stock_id;
cairo_surface_t *orig_surface;
GtkIconSize icon_size;
gint pixel_size;
@@ -41,6 +46,12 @@ struct _GtkIconHelperPrivate {
GdkPixbuf *rendered_pixbuf;
GtkStateFlags last_rendered_state;
cairo_surface_t *rendered_surface;
gint rendered_surface_width;
gint rendered_surface_height;
GtkStateFlags last_surface_state;
gint last_surface_scale;
};
void
@@ -50,6 +61,19 @@ _gtk_icon_helper_clear (GtkIconHelper *self)
g_clear_object (&self->priv->orig_pixbuf);
g_clear_object (&self->priv->animation);
g_clear_object (&self->priv->rendered_pixbuf);
g_clear_object (&self->priv->window);
if (self->priv->orig_surface)
{
cairo_surface_destroy (self->priv->orig_surface);
self->priv->orig_surface = NULL;
}
if (self->priv->rendered_surface)
{
cairo_surface_destroy (self->priv->rendered_surface);
self->priv->rendered_surface = NULL;
}
if (self->priv->icon_set != NULL)
{
@@ -68,6 +92,8 @@ _gtk_icon_helper_clear (GtkIconHelper *self)
self->priv->storage_type = GTK_IMAGE_EMPTY;
self->priv->icon_size = GTK_ICON_SIZE_INVALID;
self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
self->priv->last_surface_state = GTK_STATE_FLAG_NORMAL;
self->priv->last_surface_scale = 0;
}
void
@@ -76,6 +102,17 @@ _gtk_icon_helper_invalidate (GtkIconHelper *self)
g_clear_object (&self->priv->rendered_pixbuf);
}
void
_gtk_icon_helper_set_window (GtkIconHelper *self,
GdkWindow *window)
{
if (window)
g_object_ref (window);
g_clear_object (&self->priv->window);
self->priv->window = window;
}
static void
gtk_icon_helper_finalize (GObject *object)
{
@@ -106,6 +143,7 @@ _gtk_icon_helper_init (GtkIconHelper *self)
self->priv->icon_size = GTK_ICON_SIZE_INVALID;
self->priv->pixel_size = -1;
self->priv->last_rendered_state = GTK_STATE_FLAG_NORMAL;
self->priv->orig_pixbuf_scale = 1;
}
static void
@@ -286,6 +324,64 @@ ensure_pixbuf_for_icon_set (GtkIconHelper *self,
G_GNUC_END_IGNORE_DEPRECATIONS;
}
static void
get_surface_size (GtkIconHelper *self,
GtkStyleContext *context,
cairo_surface_t *surface,
int *width,
int *height)
{
double x_scale, y_scale;
if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE)
{
x_scale = y_scale = 1;
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
#endif
/* Assume any set scaling is icon scale */
*width =
ceil (cairo_image_surface_get_width (surface) / x_scale);
*height =
ceil (cairo_image_surface_get_height (surface) / y_scale);
}
else
ensure_icon_size (self, context, width, height);
}
static void
ensure_pixbuf_from_surface (GtkIconHelper *self,
GtkStyleContext *context)
{
cairo_surface_t *surface;
gint width, height;
cairo_t *cr;
if (!check_invalidate_pixbuf (self, context))
return;
if (self->priv->rendered_pixbuf)
return;
get_surface_size (self, context, self->priv->orig_surface, &width, &height);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
width, height);
cr = cairo_create (surface);
cairo_set_source_surface (cr, self->priv->orig_surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
self->priv->rendered_pixbuf =
gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
cairo_surface_destroy (surface);
}
static void
ensure_pixbuf_at_size (GtkIconHelper *self,
GtkStyleContext *context)
@@ -298,17 +394,34 @@ ensure_pixbuf_at_size (GtkIconHelper *self,
if (self->priv->rendered_pixbuf)
return;
if (self->priv->pixel_size != -1 ||
self->priv->icon_size != GTK_ICON_SIZE_INVALID)
if (self->priv->force_scale_pixbuf &&
(self->priv->pixel_size != -1 ||
self->priv->icon_size != GTK_ICON_SIZE_INVALID))
{
ensure_icon_size (self, context, &width, &height);
if (width < gdk_pixbuf_get_width (self->priv->orig_pixbuf) ||
if (self->priv->orig_pixbuf_scale > 1 ||
/* These should divide the orig_pixbuf size by scale, but need not
due to the above scale > 1 check */
width < gdk_pixbuf_get_width (self->priv->orig_pixbuf) ||
height < gdk_pixbuf_get_height (self->priv->orig_pixbuf))
self->priv->rendered_pixbuf =
gdk_pixbuf_scale_simple (self->priv->orig_pixbuf,
width, height,
GDK_INTERP_BILINEAR);
{
width = MIN (width, gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale);
height = MIN (height, gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale);
self->priv->rendered_pixbuf =
gdk_pixbuf_scale_simple (self->priv->orig_pixbuf,
width, height,
GDK_INTERP_BILINEAR);
}
}
else if (self->priv->orig_pixbuf_scale > 1)
{
width = gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale;
height =gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale;
self->priv->rendered_pixbuf =
gdk_pixbuf_scale_simple (self->priv->orig_pixbuf,
width, height,
GDK_INTERP_BILINEAR);
}
if (!self->priv->rendered_pixbuf)
@@ -324,11 +437,12 @@ _gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
switch (self->priv->storage_type)
{
case GTK_IMAGE_SURFACE:
ensure_pixbuf_from_surface (self, context);
break;
case GTK_IMAGE_PIXBUF:
if (self->priv->force_scale_pixbuf)
ensure_pixbuf_at_size (self, context);
else
pixbuf = g_object_ref (self->priv->orig_pixbuf);
ensure_pixbuf_at_size (self, context);
break;
case GTK_IMAGE_STOCK:
@@ -365,24 +479,320 @@ _gtk_icon_helper_ensure_pixbuf (GtkIconHelper *self,
return pixbuf;
}
static gint
get_scale_factor (GtkIconHelper *self,
GtkStyleContext *context)
{
GdkScreen *screen;
if (self->priv->window)
return gdk_window_get_scale_factor (self->priv->window);
screen = gtk_style_context_get_screen (context);
/* else fall back to something that is more likely to be right than
* just returning 1:
*/
return gdk_screen_get_monitor_scale_factor (screen, 0);
}
static gboolean
check_invalidate_surface (GtkIconHelper *self,
GtkStyleContext *context)
{
GtkStateFlags state;
int scale;
state = gtk_style_context_get_state (context);
scale = get_scale_factor (self, context);
if ((self->priv->rendered_surface != NULL) &&
(self->priv->last_surface_state == state) &&
(self->priv->last_surface_scale == scale))
return FALSE;
self->priv->last_surface_state = state;
self->priv->last_surface_scale = scale;
if (self->priv->rendered_surface)
cairo_surface_destroy (self->priv->rendered_surface);
self->priv->rendered_surface = NULL;
return TRUE;
}
static void
ensure_surface_from_surface (GtkIconHelper *self,
GtkStyleContext *context)
{
if (!check_invalidate_surface (self, context))
return;
if (self->priv->rendered_surface)
return;
self->priv->rendered_surface =
cairo_surface_reference (self->priv->orig_surface);
get_surface_size (self, context, self->priv->orig_surface,
&self->priv->rendered_surface_width,
&self->priv->rendered_surface_height);
}
static void
ensure_surface_from_pixbuf (GtkIconHelper *self,
GtkStyleContext *context)
{
gint width, height;
GdkPixbuf *pixbuf;
int scale;
if (!check_invalidate_surface (self, context))
return;
if (self->priv->rendered_surface)
return;
scale = get_scale_factor (self, context);
if (self->priv->force_scale_pixbuf &&
(self->priv->pixel_size != -1 ||
self->priv->icon_size != GTK_ICON_SIZE_INVALID))
{
ensure_icon_size (self, context, &width, &height);
if (scale != self->priv->orig_pixbuf_scale ||
width < gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale ||
height < gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale)
{
width = MIN (width * scale, gdk_pixbuf_get_width (self->priv->orig_pixbuf) * scale / self->priv->orig_pixbuf_scale);
height = MIN (height * scale, gdk_pixbuf_get_height (self->priv->orig_pixbuf) * scale / self->priv->orig_pixbuf_scale);
pixbuf = gdk_pixbuf_scale_simple (self->priv->orig_pixbuf,
width, height,
GDK_INTERP_BILINEAR);
}
else
{
pixbuf = g_object_ref (self->priv->orig_pixbuf);
scale = self->priv->orig_pixbuf_scale;
}
}
else
{
pixbuf = g_object_ref (self->priv->orig_pixbuf);
scale = self->priv->orig_pixbuf_scale;
}
self->priv->rendered_surface_width = (gdk_pixbuf_get_width (pixbuf) + scale - 1) / scale;
self->priv->rendered_surface_height = (gdk_pixbuf_get_height (pixbuf) + scale - 1) / scale;
self->priv->rendered_surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, self->priv->window);
g_object_unref (pixbuf);
}
static void
ensure_surface_for_icon_set (GtkIconHelper *self,
GtkStyleContext *context,
GtkIconSet *icon_set)
{
gint scale;
if (!check_invalidate_surface (self, context))
return;
scale = get_scale_factor (self, context);
self->priv->rendered_surface =
gtk_icon_set_render_icon_surface (icon_set, context,
self->priv->icon_size,
scale, self->priv->window);
if (self->priv->rendered_surface)
get_surface_size (self, context, self->priv->rendered_surface,
&self->priv->rendered_surface_width,
&self->priv->rendered_surface_height);
}
static void
ensure_stated_surface_from_info (GtkIconHelper *self,
GtkStyleContext *context,
GtkIconInfo *info,
int scale)
{
GdkPixbuf *destination = NULL;
cairo_surface_t *surface;
gboolean symbolic;
symbolic = FALSE;
if (info)
destination =
gtk_icon_info_load_symbolic_for_context (info,
context,
&symbolic,
NULL);
if (destination == NULL)
{
GtkIconSet *icon_set;
icon_set = gtk_style_context_lookup_icon_set (context, GTK_STOCK_MISSING_IMAGE);
destination =
gtk_icon_set_render_icon_pixbuf (icon_set, context, self->priv->icon_size);
}
else if (!symbolic)
{
GtkIconSource *source;
GdkPixbuf *rendered;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
source = gtk_icon_source_new ();
gtk_icon_source_set_pixbuf (source, destination);
/* The size here is arbitrary; since size isn't
* wildcarded in the source, it isn't supposed to be
* scaled by the engine function
*/
gtk_icon_source_set_size (source,
GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_icon_source_set_size_wildcarded (source, FALSE);
rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
gtk_icon_source_free (source);
G_GNUC_END_IGNORE_DEPRECATIONS;
g_object_unref (destination);
destination = rendered;
}
surface = NULL;
if (destination)
{
surface = gdk_cairo_surface_create_from_pixbuf (destination, scale, self->priv->window);
self->priv->rendered_surface_width =
(gdk_pixbuf_get_width (destination) + scale - 1) / scale;
self->priv->rendered_surface_height =
(gdk_pixbuf_get_height (destination) + scale - 1) / scale;
}
self->priv->rendered_surface = surface;
}
static void
ensure_surface_for_icon_name_or_gicon (GtkIconHelper *self,
GtkStyleContext *context)
{
GtkIconTheme *icon_theme;
gint width, height, scale;
GtkIconInfo *info;
GtkIconLookupFlags flags;
if (!check_invalidate_surface (self, context))
return;
icon_theme = gtk_icon_theme_get_default ();
flags = get_icon_lookup_flags (self);
ensure_icon_size (self, context, &width, &height);
scale = get_scale_factor (self, context);
if (self->priv->storage_type == GTK_IMAGE_ICON_NAME &&
self->priv->icon_name != NULL)
{
info = gtk_icon_theme_lookup_icon_for_scale (icon_theme,
self->priv->icon_name,
MIN (width, height),
scale, flags);
}
else if (self->priv->storage_type == GTK_IMAGE_GICON &&
self->priv->gicon != NULL)
{
info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme,
self->priv->gicon,
MIN (width, height),
scale, flags);
}
else
{
g_assert_not_reached ();
return;
}
ensure_stated_surface_from_info (self, context, info, scale);
if (info)
g_object_unref (info);
}
cairo_surface_t *
_gtk_icon_helper_ensure_surface (GtkIconHelper *self,
GtkStyleContext *context)
{
cairo_surface_t *surface = NULL;
GtkIconSet *icon_set;
switch (self->priv->storage_type)
{
case GTK_IMAGE_SURFACE:
ensure_surface_from_surface (self, context);
break;
case GTK_IMAGE_PIXBUF:
ensure_surface_from_pixbuf (self, context);
break;
case GTK_IMAGE_STOCK:
icon_set = gtk_style_context_lookup_icon_set (context, self->priv->stock_id);
if (icon_set != NULL)
ensure_surface_for_icon_set (self, context, icon_set);
else
surface = NULL;
break;
case GTK_IMAGE_ICON_SET:
icon_set = self->priv->icon_set;
ensure_surface_for_icon_set (self, context, icon_set);
break;
case GTK_IMAGE_ICON_NAME:
case GTK_IMAGE_GICON:
ensure_surface_for_icon_name_or_gicon (self, context);
break;
case GTK_IMAGE_ANIMATION:
case GTK_IMAGE_EMPTY:
default:
surface = NULL;
break;
}
if (surface == NULL &&
self->priv->rendered_surface != NULL)
surface = cairo_surface_reference (self->priv->rendered_surface);
return surface;
}
void
_gtk_icon_helper_get_size (GtkIconHelper *self,
GtkStyleContext *context,
gint *width_out,
gint *height_out)
{
GdkPixbuf *pix;
cairo_surface_t *surface;
gint width, height;
width = height = 0;
pix = _gtk_icon_helper_ensure_pixbuf (self, context);
surface = _gtk_icon_helper_ensure_surface (self, context);
if (pix != NULL)
if (surface != NULL)
{
width = gdk_pixbuf_get_width (pix);
height = gdk_pixbuf_get_height (pix);
g_object_unref (pix);
width = self->priv->rendered_surface_width;
height = self->priv->rendered_surface_height;
cairo_surface_destroy (surface);
}
else if (self->priv->storage_type == GTK_IMAGE_ANIMATION)
{
@@ -474,6 +884,19 @@ _gtk_icon_helper_set_animation (GtkIconHelper *self,
}
}
void
_gtk_icon_helper_set_surface (GtkIconHelper *self,
cairo_surface_t *surface)
{
_gtk_icon_helper_clear (self);
if (surface != NULL)
{
self->priv->storage_type = GTK_IMAGE_SURFACE;
self->priv->orig_surface = cairo_surface_reference (surface);
}
}
void
_gtk_icon_helper_set_stock_id (GtkIconHelper *self,
const gchar *stock_id,
@@ -571,6 +994,12 @@ _gtk_icon_helper_peek_icon_set (GtkIconHelper *self)
return self->priv->icon_set;
}
cairo_surface_t *
_gtk_icon_helper_peek_surface (GtkIconHelper *self)
{
return self->priv->orig_surface;
}
const gchar *
_gtk_icon_helper_get_stock_id (GtkIconHelper *self)
{
@@ -596,14 +1025,13 @@ _gtk_icon_helper_draw (GtkIconHelper *self,
gdouble x,
gdouble y)
{
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
pixbuf = _gtk_icon_helper_ensure_pixbuf (self, context);
if (pixbuf != NULL)
surface = _gtk_icon_helper_ensure_surface (self, context);
if (surface != NULL)
{
gtk_render_icon (context, cr, pixbuf, x, y);
g_object_unref (pixbuf);
gtk_render_icon_surface (context, cr, surface, x, y);
cairo_surface_destroy (surface);
}
}
@@ -629,3 +1057,20 @@ _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,
_gtk_icon_helper_invalidate (self);
}
}
void
_gtk_icon_helper_set_pixbuf_scale (GtkIconHelper *self,
int scale)
{
if (self->priv->orig_pixbuf_scale != scale)
{
self->priv->orig_pixbuf_scale = scale;
_gtk_icon_helper_invalidate (self);
}
}
int
_gtk_icon_helper_get_pixbuf_scale (GtkIconHelper *self)
{
return self->priv->orig_pixbuf_scale;
}
+9 -1
View File
@@ -70,6 +70,8 @@ GtkIconHelper *_gtk_icon_helper_new (void);
void _gtk_icon_helper_clear (GtkIconHelper *self);
void _gtk_icon_helper_invalidate (GtkIconHelper *self);
void _gtk_icon_helper_set_window (GtkIconHelper *self,
GdkWindow *window);
gboolean _gtk_icon_helper_get_is_empty (GtkIconHelper *self);
@@ -77,7 +79,10 @@ void _gtk_icon_helper_set_gicon (GtkIconHelper *self,
GIcon *gicon,
GtkIconSize icon_size);
void _gtk_icon_helper_set_pixbuf (GtkIconHelper *self,
GdkPixbuf *pixbuf);
GdkPixbuf *pixbuf);
void _gtk_icon_helper_set_pixbuf_scale (GtkIconHelper *self,
int scale);
int _gtk_icon_helper_get_pixbuf_scale (GtkIconHelper *self);
void _gtk_icon_helper_set_animation (GtkIconHelper *self,
GdkPixbufAnimation *animation);
void _gtk_icon_helper_set_icon_set (GtkIconHelper *self,
@@ -90,6 +95,8 @@ void _gtk_icon_helper_set_icon_name (GtkIconHelper *self,
void _gtk_icon_helper_set_stock_id (GtkIconHelper *self,
const gchar *stock_id,
GtkIconSize icon_size);
void _gtk_icon_helper_set_surface (GtkIconHelper *self,
cairo_surface_t *surface);
void _gtk_icon_helper_set_icon_size (GtkIconHelper *self,
GtkIconSize icon_size);
@@ -107,6 +114,7 @@ GdkPixbuf *_gtk_icon_helper_peek_pixbuf (GtkIconHelper *self);
GIcon *_gtk_icon_helper_peek_gicon (GtkIconHelper *self);
GtkIconSet *_gtk_icon_helper_peek_icon_set (GtkIconHelper *self);
GdkPixbufAnimation *_gtk_icon_helper_peek_animation (GtkIconHelper *self);
cairo_surface_t *_gtk_icon_helper_peek_surface (GtkIconHelper *self);
const gchar *_gtk_icon_helper_get_stock_id (GtkIconHelper *self);
const gchar *_gtk_icon_helper_get_icon_name (GtkIconHelper *self);
+470 -114
View File
@@ -55,6 +55,10 @@
#include "deprecated/gtkstyle.h"
/* this is in case round() is not provided by the compiler,
* such as in the case of C89 compilers, like MSVC
*/
#include "fallback-c89.c"
/**
* SECTION:gtkicontheme
@@ -208,6 +212,7 @@ struct _GtkIconThemePrivate
typedef struct {
gchar **icon_names;
gint size;
gint scale;
GtkIconLookupFlags flags;
} IconInfoKey;
@@ -252,11 +257,13 @@ struct _GtkIconInfo
*/
IconThemeDirType dir_type;
gint dir_size;
gint dir_scale;
gint threshold;
/* Parameters influencing the scaled icon
*/
gint desired_size;
gint desired_scale;
guint raw_coordinates : 1;
guint forced_size : 1;
guint emblems_applied : 1;
@@ -294,6 +301,7 @@ typedef struct
int min_size;
int max_size;
int threshold;
int scale;
char *dir;
char *subdir;
@@ -332,6 +340,7 @@ static void theme_destroy (IconTheme *theme);
static GtkIconInfo *theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
gint scale,
gboolean allow_svg,
gboolean use_default_icons);
static void theme_list_icons (IconTheme *theme,
@@ -367,8 +376,8 @@ static IconSuffix suffix_from_name (const char *name);
static BuiltinIcon *find_builtin_icon (const gchar *icon_name,
gint size,
gint *min_difference_p,
gboolean *has_larger_p);
gint scale,
gint *min_difference_p);
static void remove_from_lru_cache (GtkIconTheme *icon_theme,
GtkIconInfo *icon_info);
@@ -390,7 +399,8 @@ icon_info_key_hash (gconstpointer _key)
h ^= g_str_hash (key->icon_names[i]);
h ^= key->size * 0x10001;
h ^= key->flags * 0x1000010;
h ^= key->scale * 0x1000010;
h ^= key->flags * 0x100000100;
return h;
}
@@ -406,6 +416,9 @@ icon_info_key_equal (gconstpointer _a,
if (a->size != b->size)
return FALSE;
if (a->scale != b->scale)
return FALSE;
if (a->flags != b->flags)
return FALSE;
@@ -1342,11 +1355,11 @@ _gtk_icon_theme_ensure_builtin_cache (void)
IconThemeDir *dir;
static IconThemeDir dirs[5] =
{
{ ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", -1, NULL, NULL, NULL }
{ ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, 1, NULL, "16", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, 1, NULL, "20", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, 1, NULL, "24", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, 1, NULL, "32", -1, NULL, NULL, NULL },
{ ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, 1, NULL, "48", -1, NULL, NULL, NULL }
};
gint i;
@@ -1574,6 +1587,7 @@ static GtkIconInfo *
choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
gint scale,
GtkIconLookupFlags flags)
{
GtkIconThemePrivate *priv;
@@ -1591,6 +1605,7 @@ choose_icon (GtkIconTheme *icon_theme,
key.icon_names = (char **)icon_names;
key.size = size;
key.scale = scale;
key.flags = flags;
icon_info = g_hash_table_lookup (priv->info_cache, &key);
@@ -1628,7 +1643,7 @@ choose_icon (GtkIconTheme *icon_theme,
for (l = priv->themes; l; l = l->next)
{
IconTheme *theme = l->data;
icon_info = theme_lookup_icon (theme, icon_names[0], size, allow_svg, use_builtin);
icon_info = theme_lookup_icon (theme, icon_names[0], size, scale, allow_svg, use_builtin);
if (icon_info)
goto out;
}
@@ -1640,7 +1655,7 @@ choose_icon (GtkIconTheme *icon_theme,
for (i = 0; icon_names[i]; i++)
{
icon_info = theme_lookup_icon (theme, icon_names[i], size, allow_svg, use_builtin);
icon_info = theme_lookup_icon (theme, icon_names[i], size, scale, allow_svg, use_builtin);
if (icon_info)
goto out;
}
@@ -1674,6 +1689,7 @@ choose_icon (GtkIconTheme *icon_theme,
DestroyIcon (hIcon);
icon_info->dir_type = ICON_THEME_DIR_UNTHEMED;
icon_info->dir_size = size;
icon_info->dir_scale = 1;
}
g_strfreev (resources);
}
@@ -1698,16 +1714,19 @@ choose_icon (GtkIconTheme *icon_theme,
icon_info->dir_type = ICON_THEME_DIR_UNTHEMED;
icon_info->dir_size = size;
icon_info->dir_scale = 1;
}
out:
if (icon_info)
{
icon_info->desired_size = size;
icon_info->desired_scale = scale;
icon_info->forced_size = (flags & GTK_ICON_LOOKUP_FORCE_SIZE) != 0;
icon_info->key.icon_names = g_strdupv ((char **)icon_names);
icon_info->key.size = size;
icon_info->key.scale = scale;
icon_info->key.flags = flags;
icon_info->in_cache = icon_theme;
DEBUG_CACHE (("adding %p (%s %d 0x%x) to cache (cache size %d)\n",
@@ -1776,6 +1795,44 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags)
{
g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
GTK_NOTE (ICONTHEME,
g_print ("gtk_icon_theme_lookup_icon %s\n", icon_name));
return gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name,
size, 1, flags);
}
/**
* gtk_icon_theme_lookup_icon_for_scale:
* @icon_theme: a #GtkIconTheme
* @icon_name: the name of the icon to lookup
* @size: desired icon size
* @scale: the desired scale
* @flags: flags modifying the behavior of the icon lookup
*
* Looks up a named icon for a particular window scale and returns a
* structure containing information such as the filename of the
* icon. The icon can then be rendered into a pixbuf using
* gtk_icon_info_load_icon(). (gtk_icon_theme_load_icon() combines
* these two steps if all you need is the pixbuf.)
*
* Return value: (transfer full): a #GtkIconInfo object containing
* information about the icon, or %NULL if the icon wasn't found.
*
* Since: 3.10
*/
GtkIconInfo *
gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
gint scale,
GtkIconLookupFlags flags)
{
GtkIconInfo *info;
@@ -1783,6 +1840,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
g_return_val_if_fail (scale >= 1, NULL);
GTK_NOTE (ICONTHEME,
g_print ("gtk_icon_theme_lookup_icon %s\n", icon_name));
@@ -1808,7 +1866,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
}
names[dashes + 1] = NULL;
info = choose_icon (icon_theme, (const gchar **) names, size, flags);
info = choose_icon (icon_theme, (const gchar **) names, size, scale, flags);
g_strfreev (names);
}
@@ -1819,7 +1877,7 @@ gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme,
names[0] = icon_name;
names[1] = NULL;
info = choose_icon (icon_theme, names, size, flags);
info = choose_icon (icon_theme, names, size, scale, flags);
}
return info;
@@ -1859,9 +1917,50 @@ gtk_icon_theme_choose_icon (GtkIconTheme *icon_theme,
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
return choose_icon (icon_theme, icon_names, size, flags);
return choose_icon (icon_theme, icon_names, size, 1, flags);
}
/**
* gtk_icon_theme_choose_icon_for_scale:
* @icon_theme: a #GtkIconTheme
* @icon_names: (array zero-terminated=1): %NULL-terminated array of
* icon names to lookup
* @size: desired icon size
* @scale: desired scale
* @flags: flags modifying the behavior of the icon lookup
*
* Looks up a named icon for a particular window scale and returns a
* structure containing information such as the filename of the
* icon. The icon can then be rendered into a pixbuf using
* gtk_icon_info_load_icon(). (gtk_icon_theme_load_icon() combines
* these two steps if all you need is the pixbuf.)
*
* If @icon_names contains more than one name, this function
* tries them all in the given order before falling back to
* inherited icon themes.
*
* Return value: (transfer full): a #GtkIconInfo object containing information
* about the icon, or %NULL if the icon wasn't found.
*
* Since: 3.10
*/
GtkIconInfo *
gtk_icon_theme_choose_icon_for_scale (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
gint scale,
GtkIconLookupFlags flags)
{
g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
g_return_val_if_fail (icon_names != NULL, NULL);
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
g_return_val_if_fail (scale >= 1, NULL);
return choose_icon (icon_theme, icon_names, size, scale, flags);
}
/* Error quark */
GQuark
gtk_icon_theme_error_quark (void)
@@ -1905,6 +2004,56 @@ gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
gint size,
GtkIconLookupFlags flags,
GError **error)
{
g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
return gtk_icon_theme_load_icon_for_scale (icon_theme, icon_name,
size, 1, flags, error);
}
/**
* gtk_icon_theme_load_icon_for_scale:
* @icon_theme: a #GtkIconTheme
* @icon_name: the name of the icon to lookup
* @size: the desired icon size. The resulting icon may not be
* exactly this size; see gtk_icon_info_load_icon().
* @scale: desired scale
* @flags: flags modifying the behavior of the icon lookup
* @error: (allow-none): Location to store error information on failure,
* or %NULL.
*
* Looks up an icon in an icon theme for a particular window scale,
* scales it to the given size and renders it into a pixbuf. This is a
* convenience function; if more details about the icon are needed,
* use gtk_icon_theme_lookup_icon() followed by
* gtk_icon_info_load_icon().
*
* Note that you probably want to listen for icon theme changes and
* update the icon. This is usually done by connecting to the
* GtkWidget::style-set signal. If for some reason you do not want to
* update the icon when the icon theme changes, you should consider
* using gdk_pixbuf_copy() to make a private copy of the pixbuf
* returned by this function. Otherwise GTK+ may need to keep the old
* icon theme loaded, which would be a waste of memory.
*
* Return value: (transfer full): the rendered icon; this may be a
* newly created icon or a new reference to an internal icon, so
* you must not modify the icon. Use g_object_unref() to release
* your reference to the icon. %NULL if the icon isn't found.
*
* Since: 3.10
**/
GdkPixbuf *
gtk_icon_theme_load_icon_for_scale (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
gint scale,
GtkIconLookupFlags flags,
GError **error)
{
GtkIconInfo *icon_info;
GdkPixbuf *pixbuf = NULL;
@@ -1914,9 +2063,10 @@ gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size,
flags | GTK_ICON_LOOKUP_USE_BUILTIN);
g_return_val_if_fail (scale >= 1, NULL);
icon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale,
flags | GTK_ICON_LOOKUP_USE_BUILTIN);
if (!icon_info)
{
g_set_error (error, GTK_ICON_THEME_ERROR, GTK_ICON_THEME_NOT_FOUND,
@@ -1930,6 +2080,69 @@ gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
return pixbuf;
}
/**
* gtk_icon_theme_load_surface:
* @icon_theme: a #GtkIconTheme
* @icon_name: the name of the icon to lookup
* @size: the desired icon size. The resulting icon may not be
* exactly this size; see gtk_icon_info_load_icon().
* @scale: desired scale
* @for_window: (allow-none): #GdkWindow to optimize drawing for, or %NULL
* @flags: flags modifying the behavior of the icon lookup
* @error: (allow-none): Location to store error information on failure,
* or %NULL.
*
* Looks up an icon in an icon theme for a particular window scale,
* scales it to the given size and renders it into a cairo surface. This is a
* convenience function; if more details about the icon are needed,
* use gtk_icon_theme_lookup_icon() followed by
* gtk_icon_info_load_surface().
*
* Note that you probably want to listen for icon theme changes and
* update the icon. This is usually done by connecting to the
* GtkWidget::style-set signal.
*
* Return value: (transfer full): the rendered icon; this may be a
* newly created icon or a new reference to an internal icon, so
* you must not modify the icon. Use cairo_surface_destroy() to release
* your reference to the icon. %NULL if the icon isn't found.
*
* Since: 3.10
**/
cairo_surface_t *
gtk_icon_theme_load_surface (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
gint scale,
GdkWindow *for_window,
GtkIconLookupFlags flags,
GError **error)
{
GtkIconInfo *icon_info;
cairo_surface_t *surface = NULL;
g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
g_return_val_if_fail (icon_name != NULL, NULL);
g_return_val_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
(flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
g_return_val_if_fail (scale >= 1, NULL);
icon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, icon_name, size, scale,
flags | GTK_ICON_LOOKUP_USE_BUILTIN);
if (!icon_info)
{
g_set_error (error, GTK_ICON_THEME_ERROR, GTK_ICON_THEME_NOT_FOUND,
_("Icon '%s' not present in theme"), icon_name);
return NULL;
}
surface = gtk_icon_info_load_surface (icon_info, for_window, error);
g_object_unref (icon_info);
return surface;
}
/**
* gtk_icon_theme_has_icon:
* @icon_theme: a #GtkIconTheme
@@ -2352,31 +2565,35 @@ theme_dir_destroy (IconThemeDir *dir)
}
static int
theme_dir_size_difference (IconThemeDir *dir, int size, gboolean *smaller)
theme_dir_size_difference (IconThemeDir *dir,
int size,
gint scale)
{
int scaled_size, scaled_dir_size;
int min, max;
scaled_size = size * scale;
scaled_dir_size = dir->size * dir->scale;
switch (dir->type)
{
case ICON_THEME_DIR_FIXED:
*smaller = size < dir->size;
return abs (size - dir->size);
return abs (scaled_size - scaled_dir_size);
break;
case ICON_THEME_DIR_SCALABLE:
*smaller = size < dir->min_size;
if (size < dir->min_size)
return dir->min_size - size;
if (size > dir->max_size)
return size - dir->max_size;
if (scaled_size < (dir->min_size * dir->scale))
return (dir->min_size * dir->scale) - scaled_size;
if (size > (dir->max_size * dir->scale))
return scaled_size - (dir->max_size * dir->scale);
return 0;
break;
case ICON_THEME_DIR_THRESHOLD:
min = dir->size - dir->threshold;
max = dir->size + dir->threshold;
*smaller = size < min;
if (size < min)
return min - size;
if (size > max)
return size - max;
min = (dir->size - dir->threshold) * dir->scale;
max = (dir->size + dir->threshold) * dir->scale;
if (scaled_size < min)
return min - scaled_size;
if (scaled_size > max)
return scaled_size - max;
return 0;
break;
case ICON_THEME_DIR_UNTHEMED:
@@ -2463,10 +2680,75 @@ theme_dir_get_icon_suffix (IconThemeDir *dir,
return suffix;
}
/* returns TRUE if dir_a is a better match */
static gboolean
compare_dir_matches (IconThemeDir *dir_a, int difference_a,
IconThemeDir *dir_b, int difference_b,
int requested_size, int requested_scale)
{
int diff_a;
int diff_b;
if (difference_a == 0)
{
if (difference_b != 0)
return TRUE;
/* a and b both exact matches */
}
else
{
/* If scaling, *always* prefer downscaling */
if (dir_a->size >= requested_size &&
dir_b->size < requested_size)
return TRUE;
if (dir_a->size < requested_size &&
dir_b->size >= requested_size)
return FALSE;
/* Otherwise prefer the closest match */
if (difference_a < difference_b)
return TRUE;
if (difference_a > difference_b)
return FALSE;
/* same pixel difference */
}
if (dir_a->scale == requested_scale &&
dir_b->scale != requested_scale)
return TRUE;
if (dir_a->scale != requested_scale &&
dir_b->scale == requested_scale)
return FALSE;
/* a and b both match the scale */
if (dir_a->type != ICON_THEME_DIR_SCALABLE &&
dir_b->type == ICON_THEME_DIR_SCALABLE)
return TRUE;
if (dir_a->type == ICON_THEME_DIR_SCALABLE &&
dir_b->type != ICON_THEME_DIR_SCALABLE)
return FALSE;
/* a and b both are scalable */
diff_a = abs (requested_size * requested_scale - dir_a->size * dir_a->scale);
diff_b = abs (requested_size * requested_scale - dir_b->size * dir_b->scale);
return diff_a <= diff_b;
}
static GtkIconInfo *
theme_lookup_icon (IconTheme *theme,
const char *icon_name,
int size,
gint scale,
gboolean allow_svg,
gboolean use_builtin)
{
@@ -2475,13 +2757,10 @@ theme_lookup_icon (IconTheme *theme,
char *file;
int min_difference, difference;
BuiltinIcon *closest_builtin = NULL;
gboolean smaller, has_larger, match;
IconSuffix suffix;
min_difference = G_MAXINT;
min_dir = NULL;
has_larger = FALSE;
match = FALSE;
/* Builtin icons are logically part of the default theme and
* are searched before other subdirectories of the default theme.
@@ -2489,9 +2768,8 @@ theme_lookup_icon (IconTheme *theme,
if (use_builtin && strcmp (theme->name, DEFAULT_THEME_NAME) == 0)
{
closest_builtin = find_builtin_icon (icon_name,
size,
&min_difference,
&has_larger);
size, scale,
&min_difference);
if (min_difference == 0)
return icon_info_new_builtin (closest_builtin);
@@ -2511,57 +2789,14 @@ theme_lookup_icon (IconTheme *theme,
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
if (best_suffix (suffix, allow_svg) != ICON_SUFFIX_NONE)
{
difference = theme_dir_size_difference (dir, size, &smaller);
if (difference == 0)
difference = theme_dir_size_difference (dir, size, scale);
if (min_dir == NULL ||
compare_dir_matches (dir, difference,
min_dir, min_difference,
size, scale))
{
if (dir->type == ICON_THEME_DIR_SCALABLE)
{
/* don't pick scalable if we already found
* a matching non-scalable dir
*/
if (!match)
{
min_dir = dir;
break;
}
}
else
{
/* for a matching non-scalable dir keep
* going and look for a closer match
*/
difference = abs (size - dir->size);
if (!match || difference < min_difference)
{
match = TRUE;
min_difference = difference;
min_dir = dir;
}
if (difference == 0)
break;
}
}
if (!match)
{
if (!has_larger)
{
if (difference < min_difference || smaller)
{
min_difference = difference;
min_dir = dir;
has_larger = smaller;
}
}
else
{
if (difference < min_difference && smaller)
{
min_difference = difference;
min_dir = dir;
}
}
min_dir = dir;
min_difference = difference;
}
}
@@ -2640,6 +2875,7 @@ theme_lookup_icon (IconTheme *theme,
icon_info->dir_type = min_dir->type;
icon_info->dir_size = min_dir->size;
icon_info->dir_scale = min_dir->scale;
icon_info->threshold = min_dir->threshold;
return icon_info;
@@ -2858,6 +3094,7 @@ theme_subdir_load (GtkIconTheme *icon_theme,
char *full_dir;
GError *error = NULL;
IconThemeDirMtime *dir_mtime;
int scale;
size = g_key_file_get_integer (theme_file, subdir, "Size", &error);
if (error)
@@ -2905,6 +3142,11 @@ theme_subdir_load (GtkIconTheme *icon_theme,
else
threshold = 2;
if (g_key_file_has_key (theme_file, subdir, "OutputScale", NULL))
scale = g_key_file_get_integer (theme_file, subdir, "OutputScale", NULL);
else
scale = 1;
for (d = icon_theme->priv->dir_mtimes; d; d = d->next)
{
dir_mtime = (IconThemeDirMtime *)d->data;
@@ -2933,6 +3175,8 @@ theme_subdir_load (GtkIconTheme *icon_theme,
dir->dir = full_dir;
dir->icon_data = NULL;
dir->subdir = g_strdup (subdir);
dir->scale = scale;
if (dir_mtime->cache != NULL)
{
dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
@@ -3048,8 +3292,10 @@ icon_info_dup (GtkIconInfo *icon_info)
dup->data = icon_data_dup (icon_info->data);
dup->dir_type = icon_info->dir_type;
dup->dir_size = icon_info->dir_size;
dup->dir_scale = icon_info->dir_scale;
dup->threshold = icon_info->threshold;
dup->desired_size = icon_info->desired_size;
dup->desired_scale = icon_info->desired_scale;
dup->raw_coordinates = icon_info->raw_coordinates;
dup->forced_size = icon_info->forced_size;
dup->emblems_applied = icon_info->emblems_applied;
@@ -3065,6 +3311,7 @@ icon_info_new_builtin (BuiltinIcon *icon)
icon_info->cache_pixbuf = g_object_ref (icon->pixbuf);
icon_info->dir_type = ICON_THEME_DIR_THRESHOLD;
icon_info->dir_size = icon->size;
icon_info->dir_scale = 1;
icon_info->threshold = 2;
return icon_info;
@@ -3158,7 +3405,10 @@ gtk_icon_info_class_init (GtkIconInfoClass *klass)
* to a larger icon. These icons will be given
* the same base size as the larger icons to which
* they are attached.
*
*
* Note that for scaled icons the base size does
* not include the base scale.
*
* Return value: the base size, or 0, if no base
* size is known for the icon.
*
@@ -3172,6 +3422,27 @@ gtk_icon_info_get_base_size (GtkIconInfo *icon_info)
return icon_info->dir_size;
}
/**
* gtk_icon_info_get_base_scale:
* @icon_info: a #GtkIconInfo
*
* Gets the base scale for the icon. The base scale is a scale for the
* icon that was specified by the icon theme creator. For instance an
* icon drawn for a high-dpi screen with window-scale 2 for a base
* size of 32 will be 64 pixels tall and have a base_scale of 2.
*
* Return value: the base scale.
*
* Since: 3.10
**/
gint
gtk_icon_info_get_base_scale (GtkIconInfo *icon_info)
{
g_return_val_if_fail (icon_info != NULL, 0);
return icon_info->dir_scale;
}
/**
* gtk_icon_info_get_filename:
* @icon_info: a #GtkIconInfo
@@ -3332,6 +3603,7 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
gboolean scale_only)
{
int image_width, image_height;
int scaled_desired_size;
GdkPixbuf *source_pixbuf;
gboolean is_svg;
@@ -3356,6 +3628,8 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
if (icon_info->icon_file && !icon_info->loadable)
icon_info->loadable = G_LOADABLE_ICON (g_file_icon_new (icon_info->icon_file));
scaled_desired_size = icon_info->desired_size * icon_info->desired_scale;
is_svg = FALSE;
if (G_IS_FILE_ICON (icon_info->loadable))
{
@@ -3383,20 +3657,21 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
{
GInputStream *stream;
icon_info->scale = icon_info->desired_size / 1000.;
icon_info->scale = scaled_desired_size / 1000.;
if (scale_only)
return TRUE;
/* TODO: We should have a load_at_scale */
stream = g_loadable_icon_load (icon_info->loadable,
icon_info->desired_size,
scaled_desired_size,
NULL, NULL,
&icon_info->load_error);
if (stream)
{
icon_info->pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
icon_info->desired_size,
icon_info->desired_size,
scaled_desired_size,
scaled_desired_size,
TRUE,
NULL,
&icon_info->load_error);
@@ -3419,19 +3694,19 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
if (icon_info->forced_size)
icon_info->scale = -1;
else if (icon_info->dir_type == ICON_THEME_DIR_FIXED)
icon_info->scale = 1.0;
icon_info->scale = round((gdouble) scaled_desired_size / (icon_info->dir_size * icon_info->dir_scale));
else if (icon_info->dir_type == ICON_THEME_DIR_THRESHOLD)
{
if (icon_info->desired_size >= icon_info->dir_size - icon_info->threshold &&
icon_info->desired_size <= icon_info->dir_size + icon_info->threshold)
icon_info->scale = 1.0;
if (scaled_desired_size >= (icon_info->dir_size - icon_info->threshold) * icon_info->dir_scale &&
scaled_desired_size <= (icon_info->dir_size + icon_info->threshold) * icon_info->dir_scale)
icon_info->scale = round((gdouble) scaled_desired_size / (icon_info->dir_size * icon_info->dir_scale));
else if (icon_info->dir_size > 0)
icon_info->scale =(gdouble) icon_info->desired_size / icon_info->dir_size;
icon_info->scale =(gdouble) scaled_desired_size / (icon_info->dir_size * icon_info->dir_scale);
}
else if (icon_info->dir_type == ICON_THEME_DIR_SCALABLE)
{
if (icon_info->dir_size > 0)
icon_info->scale = (gdouble) icon_info->desired_size / icon_info->dir_size;
icon_info->scale = (gdouble) scaled_desired_size / (icon_info->dir_size * icon_info->dir_scale);
}
if (icon_info->scale >= 0. && scale_only)
@@ -3447,8 +3722,9 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
{
GInputStream *stream;
/* TODO: We should have a load_at_scale */
stream = g_loadable_icon_load (icon_info->loadable,
icon_info->desired_size,
scaled_desired_size,
NULL, NULL,
&icon_info->load_error);
if (stream)
@@ -3472,7 +3748,7 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info,
{
gint image_size = MAX (image_width, image_height);
if (image_size > 0)
icon_info->scale = (gdouble)icon_info->desired_size / (gdouble)image_size;
icon_info->scale = (gdouble)scaled_desired_size / (gdouble)image_size;
else
icon_info->scale = 1.0;
@@ -3589,6 +3865,54 @@ gtk_icon_info_load_icon (GtkIconInfo *icon_info,
return icon_info->proxy_pixbuf;
}
/**
* gtk_icon_info_load_surface:
* @icon_info: a #GtkIconInfo structure from gtk_icon_theme_lookup_icon()
* @for_window: (allow-none): #GdkWindow to optimize drawing for, or %NULL
* @error: (allow-none): location to store error information on failure,
* or %NULL.
*
* Renders an icon previously looked up in an icon theme using
* gtk_icon_theme_lookup_icon(); the size will be based on the size
* passed to gtk_icon_theme_lookup_icon(). Note that the resulting
* surface may not be exactly this size; an icon theme may have icons
* that differ slightly from their nominal sizes, and in addition GTK+
* will avoid scaling icons that it considers sufficiently close to the
* requested size or for which the source image would have to be scaled
* up too far. (This maintains sharpness.). This behaviour can be changed
* by passing the %GTK_ICON_LOOKUP_FORCE_SIZE flag when obtaining
* the #GtkIconInfo. If this flag has been specified, the pixbuf
* returned by this function will be scaled to the exact size.
*
* Return value: (transfer full): the rendered icon; this may be a newly
* created icon or a new reference to an internal icon, so you must
* not modify the icon. Use cairo_surface_destroy() to release your reference
* to the icon.
*
* Since: 3.10
**/
cairo_surface_t *
gtk_icon_info_load_surface (GtkIconInfo *icon_info,
GdkWindow *for_window,
GError **error)
{
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
g_return_val_if_fail (icon_info != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
pixbuf = gtk_icon_info_load_icon (icon_info, error);
if (pixbuf == NULL)
return NULL;
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, icon_info->desired_scale, for_window);
g_object_unref (pixbuf);
return surface;
}
static void
load_icon_thread (GTask *task,
gpointer source_object,
@@ -3887,8 +4211,8 @@ _gtk_icon_info_load_symbolic_internal (GtkIconInfo *icon_info,
stream = g_memory_input_stream_new_from_data (data, -1, g_free);
pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
icon_info->desired_size,
icon_info->desired_size,
icon_info->desired_size * icon_info->desired_scale,
icon_info->desired_size * icon_info->desired_scale,
TRUE,
NULL,
error);
@@ -4740,8 +5064,8 @@ gtk_icon_theme_add_builtin_icon (const gchar *icon_name,
static BuiltinIcon *
find_builtin_icon (const gchar *icon_name,
gint size,
gint *min_difference_p,
gboolean *has_larger_p)
gint scale,
gint *min_difference_p)
{
GSList *icons = NULL;
gint min_difference = G_MAXINT;
@@ -4751,6 +5075,8 @@ find_builtin_icon (const gchar *icon_name,
if (!icon_theme_builtin_icons)
return NULL;
size *= scale;
icons = g_hash_table_lookup (icon_theme_builtin_icons, icon_name);
while (icons)
@@ -4798,8 +5124,6 @@ find_builtin_icon (const gchar *icon_name,
if (min_difference_p)
*min_difference_p = min_difference;
if (has_larger_p)
*has_larger_p = has_larger;
return min_icon;
}
@@ -4827,6 +5151,37 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
GIcon *icon,
gint size,
GtkIconLookupFlags flags)
{
return gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, icon,
size, 1, flags);
}
/**
* gtk_icon_theme_lookup_by_gicon_for_scale:
* @icon_theme: a #GtkIconTheme
* @icon: the #GIcon to look up
* @size: desired icon size
* @scale: the desired scale
* @flags: flags modifying the behavior of the icon lookup
*
* Looks up an icon and returns a structure containing
* information such as the filename of the icon.
* The icon can then be rendered into a pixbuf using
* gtk_icon_info_load_icon_for_scale ().
*
* Return value: (transfer full): a #GtkIconInfo structure containing
* information about the icon, or %NULL if the icon
* wasn't found. Unref with g_object_unref()
*
* Since: 2.14
*/
GtkIconInfo *
gtk_icon_theme_lookup_by_gicon_for_scale (GtkIconTheme *icon_theme,
GIcon *icon,
gint size,
gint scale,
GtkIconLookupFlags flags)
{
GtkIconInfo *info;
@@ -4851,6 +5206,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
info->dir_type = ICON_THEME_DIR_UNTHEMED;
info->dir_size = size;
info->desired_size = size;
info->desired_scale = scale;
info->threshold = 2;
info->forced_size = (flags & GTK_ICON_LOOKUP_FORCE_SIZE) != 0;
@@ -4861,7 +5217,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
const gchar **names;
names = (const gchar **)g_themed_icon_get_names (G_THEMED_ICON (icon));
info = gtk_icon_theme_choose_icon (icon_theme, names, size, flags);
info = gtk_icon_theme_choose_icon_for_scale (icon_theme, names, size, scale, flags);
return info;
}
@@ -4875,7 +5231,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
_gtk_numerable_icon_set_background_icon_size (GTK_NUMERABLE_ICON (icon), size / 2);
base = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon));
base_info = gtk_icon_theme_lookup_by_gicon (icon_theme, base, size, flags);
base_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, base, size, scale, flags);
if (base_info)
{
info = icon_info_dup (base_info);
@@ -4886,7 +5242,7 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
{
emblem = g_emblem_get_icon (G_EMBLEM (l->data));
/* always force size for emblems */
emblem_info = gtk_icon_theme_lookup_by_gicon (icon_theme, emblem, size / 2, flags | GTK_ICON_LOOKUP_FORCE_SIZE);
emblem_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, emblem, size / 2, scale, flags | GTK_ICON_LOOKUP_FORCE_SIZE);
if (emblem_info)
info->emblem_infos = g_slist_prepend (info->emblem_infos, emblem_info);
}
@@ -4905,17 +5261,17 @@ gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
if ((flags & GTK_ICON_LOOKUP_FORCE_SIZE) != 0)
{
gint width, height, max;
gdouble scale;
gdouble pixbuf_scale;
GdkPixbuf *scaled;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
max = MAX (width, height);
scale = (gdouble) size / (gdouble) max;
pixbuf_scale = (gdouble) size * scale / (gdouble) max;
scaled = gdk_pixbuf_scale_simple (pixbuf,
0.5 + width * scale,
0.5 + height * scale,
0.5 + width * pixbuf_scale,
0.5 + height * pixbuf_scale,
GDK_INTERP_BILINEAR);
info = gtk_icon_info_new_for_pixbuf (icon_theme, scaled);
+40
View File
@@ -179,23 +179,57 @@ GtkIconInfo * gtk_icon_theme_lookup_icon (GtkIconTheme
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_3_10
GtkIconInfo * gtk_icon_theme_lookup_icon_for_scale (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
gint scale,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_ALL
GtkIconInfo * gtk_icon_theme_choose_icon (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_3_10
GtkIconInfo * gtk_icon_theme_choose_icon_for_scale (GtkIconTheme *icon_theme,
const gchar *icon_names[],
gint size,
gint scale,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_ALL
GdkPixbuf * gtk_icon_theme_load_icon (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
GtkIconLookupFlags flags,
GError **error);
GDK_AVAILABLE_IN_3_10
GdkPixbuf * gtk_icon_theme_load_icon_for_scale (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
gint scale,
GtkIconLookupFlags flags,
GError **error);
GDK_AVAILABLE_IN_3_10
cairo_surface_t * gtk_icon_theme_load_surface (GtkIconTheme *icon_theme,
const gchar *icon_name,
gint size,
gint scale,
GdkWindow *for_window,
GtkIconLookupFlags flags,
GError **error);
GDK_AVAILABLE_IN_ALL
GtkIconInfo * gtk_icon_theme_lookup_by_gicon (GtkIconTheme *icon_theme,
GIcon *icon,
gint size,
GtkIconLookupFlags flags);
GtkIconInfo * gtk_icon_theme_lookup_by_gicon_for_scale (GtkIconTheme *icon_theme,
GIcon *icon,
gint size,
gint scale,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_ALL
GList * gtk_icon_theme_list_icons (GtkIconTheme *icon_theme,
@@ -226,6 +260,8 @@ GtkIconInfo * gtk_icon_info_new_for_pixbuf (GtkIconTheme *icon_them
GDK_AVAILABLE_IN_ALL
gint gtk_icon_info_get_base_size (GtkIconInfo *icon_info);
GDK_AVAILABLE_IN_3_10
gint gtk_icon_info_get_base_scale (GtkIconInfo *icon_info);
GDK_AVAILABLE_IN_ALL
const gchar * gtk_icon_info_get_filename (GtkIconInfo *icon_info);
GDK_AVAILABLE_IN_ALL
@@ -233,6 +269,10 @@ GdkPixbuf * gtk_icon_info_get_builtin_pixbuf (GtkIconInfo *icon_info
GDK_AVAILABLE_IN_ALL
GdkPixbuf * gtk_icon_info_load_icon (GtkIconInfo *icon_info,
GError **error);
GDK_AVAILABLE_IN_3_10
cairo_surface_t * gtk_icon_info_load_surface (GtkIconInfo *icon_info,
GdkWindow *for_window,
GError **error);
GDK_AVAILABLE_IN_3_8
void gtk_icon_info_load_icon_async (GtkIconInfo *icon_info,
GCancellable *cancellable,

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