decompose wl_backend.c: extract wl_dragicon.c

This commit is contained in:
Window Maker 2026-06-02 14:30:57 +02:00
parent 7b02d32a02
commit 28fb61668f
3 changed files with 127 additions and 111 deletions

View File

@ -183,7 +183,8 @@ wmaker_SOURCES += \
backend/wayland/wl_clipboard.c \
backend/wayland/wl_dnd.c \
backend/wayland/wl_grabs.c \
backend/wayland/wl_grabstate.c
backend/wayland/wl_grabstate.c \
backend/wayland/wl_dragicon.c
endif
if USE_NESTED_FUNC

View File

@ -313,10 +313,10 @@ void wl_clipboard_store_to_seat(const char *text, int len);
char *wl_clipboard_fetch_from_seat(int *len_out);
/* Drag icon overlay for WINGs compositor-internal DND. */
static void wl_drag_icon_show(struct W_View *view, int x, int y);
static void wl_drag_icon_move(int x, int y);
static void wl_drag_icon_hide(void);
static void wl_drag_cursor_feedback(Bool accepted);
void wl_drag_icon_show(struct W_View *view, int x, int y);
void wl_drag_icon_move(int x, int y);
void wl_drag_icon_hide(void);
void wl_drag_cursor_feedback(Bool accepted);
/* Phase 28: idle inhibitor created/destroyed handler. */
static void handle_idle_new_inhibitor(struct wl_listener *listener, void *data);
/* Phase 29: scroll-wheel axis event handler. */
@ -3807,113 +3807,7 @@ handle_seat_request_cursor(struct wl_listener *listener, void *data)
/* Drag icon overlay for WINGs compositor-internal DND */
/* ------------------------------------------------------------------ */
/* State for the currently active drag icon (only one drag at a time) */
static struct {
struct wlr_scene_buffer *scene_buf;
struct wlr_scene_tree *tree;
pixman_image_t *image;
struct wlr_buffer base;
int width, height;
int offset_x, offset_y; /* cursor hotspot relative to top-left */
} wl_drag_icon_state = {0};
static void
wl_drag_icon_destroy(void)
{
if (wl_drag_icon_state.tree) {
wlr_scene_node_destroy(&wl_drag_icon_state.tree->node);
wl_drag_icon_state.tree = NULL;
wl_drag_icon_state.scene_buf = NULL;
}
if (wl_drag_icon_state.image) {
pixman_image_unref(wl_drag_icon_state.image);
wl_drag_icon_state.image = NULL;
}
memset(&wl_drag_icon_state, 0, sizeof(wl_drag_icon_state));
}
static void
wl_drag_icon_show(struct W_View *view, int x, int y)
{
/* Clean up any previous drag icon */
wl_drag_icon_destroy();
if (!view || !view->dragImage || !wl_state.scene)
return;
struct W_Pixmap *p = view->dragImage;
pixman_image_t *src = (pixman_image_t *)(uintptr_t)p->pixmap;
if (!src)
return;
int w = p->width;
int h = p->height;
/* Copy the pixman image so we own it independently */
pixman_image_t *copy = pixman_image_create_bits(
PIXMAN_a8r8g8b8, w, h, NULL, w * 4);
if (!copy)
return;
pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, copy,
0, 0, 0, 0, 0, 0, w, h);
wl_drag_icon_state.image = copy;
wl_drag_icon_state.width = w;
wl_drag_icon_state.height = h;
/* Center the icon on the cursor */
wl_drag_icon_state.offset_x = -w / 2;
wl_drag_icon_state.offset_y = -h / 2;
/* Wrap in wlr_buffer using the existing frame_buf_impl */
wlr_buffer_init(&wl_drag_icon_state.base, &frame_buf_impl, w, h);
/* Create scene tree under overlay layer */
struct wlr_scene_tree *parent = wl_state.level_trees[WL_LAYER_OVERLAY]
? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree;
wl_drag_icon_state.tree = wlr_scene_tree_create(parent);
if (!wl_drag_icon_state.tree) {
wl_drag_icon_destroy();
return;
}
wl_drag_icon_state.scene_buf = wlr_scene_buffer_create(
wl_drag_icon_state.tree, &wl_drag_icon_state.base);
if (!wl_drag_icon_state.scene_buf) {
wl_drag_icon_destroy();
return;
}
/* Position at cursor (centered) */
wlr_scene_node_set_position(&wl_drag_icon_state.tree->node,
x + wl_drag_icon_state.offset_x,
y + wl_drag_icon_state.offset_y);
}
static void
wl_drag_icon_move(int x, int y)
{
if (!wl_drag_icon_state.tree)
return;
wlr_scene_node_set_position(&wl_drag_icon_state.tree->node,
x + wl_drag_icon_state.offset_x,
y + wl_drag_icon_state.offset_y);
}
static void
wl_drag_icon_hide(void)
{
wl_drag_icon_destroy();
}
static void
wl_drag_cursor_feedback(Bool accepted)
{
if (accepted)
wl_set_cursor_image("plus");
else
wl_set_cursor_image("left_ptr");
}
/*
* Phase 25: seat request_set_selection — client calls wl_data_device.set_selection

View File

@ -0,0 +1,121 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/interfaces/wlr_buffer.h>
#include <pixman.h>
#include "../../screen.h"
#include "wl_types.h"
#include <WINGs/WINGsP.h>
/* Forward declarations */
void wl_set_cursor_image(const char *name);
static struct {
struct wlr_scene_buffer *scene_buf;
struct wlr_scene_tree *tree;
pixman_image_t *image;
struct wlr_buffer base;
int width, height;
int offset_x, offset_y; /* cursor hotspot relative to top-left */
} wl_drag_icon_state = {0};
void
wl_drag_icon_destroy(void)
{
if (wl_drag_icon_state.tree) {
wlr_scene_node_destroy(&wl_drag_icon_state.tree->node);
wl_drag_icon_state.tree = NULL;
wl_drag_icon_state.scene_buf = NULL;
}
if (wl_drag_icon_state.image) {
pixman_image_unref(wl_drag_icon_state.image);
wl_drag_icon_state.image = NULL;
}
memset(&wl_drag_icon_state, 0, sizeof(wl_drag_icon_state));
}
void
wl_drag_icon_show(struct W_View *view, int x, int y)
{
/* Clean up any previous drag icon */
wl_drag_icon_destroy();
if (!view || !view->dragImage || !wl_state.scene)
return;
struct W_Pixmap *p = view->dragImage;
pixman_image_t *src = (pixman_image_t *)(uintptr_t)p->pixmap;
if (!src)
return;
int w = p->width;
int h = p->height;
/* Copy the pixman image so we own it independently */
pixman_image_t *copy = pixman_image_create_bits(
PIXMAN_a8r8g8b8, w, h, NULL, w * 4);
if (!copy)
return;
pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, copy,
0, 0, 0, 0, 0, 0, w, h);
wl_drag_icon_state.image = copy;
wl_drag_icon_state.width = w;
wl_drag_icon_state.height = h;
/* Center the icon on the cursor */
wl_drag_icon_state.offset_x = -w / 2;
wl_drag_icon_state.offset_y = -h / 2;
/* Wrap in wlr_buffer using the existing frame_buf_impl */
wlr_buffer_init(&wl_drag_icon_state.base, &frame_buf_impl, w, h);
/* Create scene tree under overlay layer */
struct wlr_scene_tree *parent = wl_state.level_trees[WL_LAYER_OVERLAY]
? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree;
wl_drag_icon_state.tree = wlr_scene_tree_create(parent);
if (!wl_drag_icon_state.tree) {
wl_drag_icon_destroy();
return;
}
wl_drag_icon_state.scene_buf = wlr_scene_buffer_create(
wl_drag_icon_state.tree, &wl_drag_icon_state.base);
if (!wl_drag_icon_state.scene_buf) {
wl_drag_icon_destroy();
return;
}
/* Position at cursor (centered) */
wlr_scene_node_set_position(&wl_drag_icon_state.tree->node,
x + wl_drag_icon_state.offset_x,
y + wl_drag_icon_state.offset_y);
}
void
wl_drag_icon_move(int x, int y)
{
if (!wl_drag_icon_state.tree)
return;
wlr_scene_node_set_position(&wl_drag_icon_state.tree->node,
x + wl_drag_icon_state.offset_x,
y + wl_drag_icon_state.offset_y);
}
void
wl_drag_icon_hide(void)
{
wl_drag_icon_destroy();
}
void
wl_drag_cursor_feedback(Bool accepted)
{
if (accepted)
wl_set_cursor_image("plus");
else
wl_set_cursor_image("left_ptr");
}