wayland: Implement DND icon hotspot API
In Wayland, the hotspot of a DND icon is set using the buffer offset in wl_buffer.attach. To implement this, add a private API to cause the next wl_surface.attach to offset the new buffer with a given offset. Setting a DND icon hotspot sets this offset while also queuing a redraw of the window to trigger the wl_surface.attach. https://bugzilla.gnome.org/show_bug.cgi?id=759168
This commit is contained in:
committed by
Matthias Clasen
parent
0164256aec
commit
3ab9d96623
@ -24,6 +24,7 @@
|
|||||||
#include "gdkproperty.h"
|
#include "gdkproperty.h"
|
||||||
#include "gdkprivate-wayland.h"
|
#include "gdkprivate-wayland.h"
|
||||||
#include "gdkdisplay-wayland.h"
|
#include "gdkdisplay-wayland.h"
|
||||||
|
#include "gdkwaylandwindow.h"
|
||||||
|
|
||||||
#include "gdkdeviceprivate.h"
|
#include "gdkdeviceprivate.h"
|
||||||
|
|
||||||
@ -48,6 +49,8 @@ struct _GdkWaylandDragContext
|
|||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
gdouble x;
|
gdouble x;
|
||||||
gdouble y;
|
gdouble y;
|
||||||
|
gint prev_hot_x;
|
||||||
|
gint prev_hot_y;
|
||||||
gint hot_x;
|
gint hot_x;
|
||||||
gint hot_y;
|
gint hot_y;
|
||||||
};
|
};
|
||||||
@ -306,8 +309,27 @@ gdk_wayland_drag_context_set_hotspot (GdkDragContext *context,
|
|||||||
gint hot_x,
|
gint hot_x,
|
||||||
gint hot_y)
|
gint hot_y)
|
||||||
{
|
{
|
||||||
GDK_WAYLAND_DRAG_CONTEXT (context)->hot_x = hot_x;
|
GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
|
||||||
GDK_WAYLAND_DRAG_CONTEXT (context)->hot_y = hot_y;
|
|
||||||
|
context_wayland->prev_hot_x = context_wayland->hot_x;
|
||||||
|
context_wayland->prev_hot_y = context_wayland->hot_x;
|
||||||
|
context_wayland->hot_x = hot_x;
|
||||||
|
context_wayland->hot_y = hot_y;
|
||||||
|
|
||||||
|
if (context_wayland->prev_hot_x == hot_x &&
|
||||||
|
context_wayland->prev_hot_x == hot_x)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_gdk_wayland_window_offset_next_wl_buffer (context_wayland->dnd_window,
|
||||||
|
-hot_x, -hot_y);
|
||||||
|
gdk_window_invalidate_rect (context_wayland->dnd_window,
|
||||||
|
&(GdkRectangle) {
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = 1,
|
||||||
|
.height = 1,
|
||||||
|
},
|
||||||
|
FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@ -104,6 +104,10 @@ void _gdk_wayland_window_register_dnd (GdkWindow *window);
|
|||||||
GdkDragContext *_gdk_wayland_window_drag_begin (GdkWindow *window,
|
GdkDragContext *_gdk_wayland_window_drag_begin (GdkWindow *window,
|
||||||
GdkDevice *device,
|
GdkDevice *device,
|
||||||
GList *targets);
|
GList *targets);
|
||||||
|
void _gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
|
||||||
GdkDragContext * _gdk_wayland_drop_context_new (struct wl_data_device *data_device);
|
GdkDragContext * _gdk_wayland_drop_context_new (struct wl_data_device *data_device);
|
||||||
void _gdk_wayland_drag_context_set_source_window (GdkDragContext *context,
|
void _gdk_wayland_drag_context_set_source_window (GdkDragContext *context,
|
||||||
GdkWindow *window);
|
GdkWindow *window);
|
||||||
|
|||||||
@ -121,6 +121,8 @@ struct _GdkWindowImplWayland
|
|||||||
GdkWindow *transient_for;
|
GdkWindow *transient_for;
|
||||||
|
|
||||||
cairo_surface_t *cairo_surface;
|
cairo_surface_t *cairo_surface;
|
||||||
|
int pending_buffer_offset_x;
|
||||||
|
int pending_buffer_offset_y;
|
||||||
|
|
||||||
gchar *title;
|
gchar *title;
|
||||||
|
|
||||||
@ -564,7 +566,10 @@ gdk_wayland_window_attach_image (GdkWindow *window)
|
|||||||
/* Attach this new buffer to the surface */
|
/* Attach this new buffer to the surface */
|
||||||
wl_surface_attach (impl->surface,
|
wl_surface_attach (impl->surface,
|
||||||
_gdk_wayland_shm_surface_get_wl_buffer (impl->cairo_surface),
|
_gdk_wayland_shm_surface_get_wl_buffer (impl->cairo_surface),
|
||||||
0, 0);
|
impl->pending_buffer_offset_x,
|
||||||
|
impl->pending_buffer_offset_y);
|
||||||
|
impl->pending_buffer_offset_x = 0;
|
||||||
|
impl->pending_buffer_offset_y = 0;
|
||||||
|
|
||||||
/* Only set the buffer scale if supported by the compositor */
|
/* Only set the buffer scale if supported by the compositor */
|
||||||
display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
|
display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
|
||||||
@ -2564,6 +2569,32 @@ gdk_wayland_window_get_wl_surface (GdkWindow *window)
|
|||||||
return GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface;
|
return GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_wayland_window_offset_next_wl_buffer:
|
||||||
|
* @window (type GdkWaylandWindow): a #GdkWindow
|
||||||
|
* @x: x offset which the next buffer should be attached at
|
||||||
|
* @y: y offset which the next buffer should be attached at
|
||||||
|
*
|
||||||
|
* Make GDK attach the next buffer at the given offset. This is useful for
|
||||||
|
* DND icons which may have a hotspot other than (0, 0).
|
||||||
|
*
|
||||||
|
* Since: 3.20
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
|
||||||
|
int x,
|
||||||
|
int y)
|
||||||
|
{
|
||||||
|
GdkWindowImplWayland *impl;
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
|
||||||
|
|
||||||
|
impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||||
|
|
||||||
|
impl->pending_buffer_offset_x = x;
|
||||||
|
impl->pending_buffer_offset_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
static struct wl_egl_window *
|
static struct wl_egl_window *
|
||||||
gdk_wayland_window_get_wl_egl_window (GdkWindow *window)
|
gdk_wayland_window_get_wl_egl_window (GdkWindow *window)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user