decompose wl_stubs.c: move wl_icon_paint + wl_appicon_paint to wl_icon.c
This commit is contained in:
parent
75a4224370
commit
d376eec495
|
|
@ -198,6 +198,8 @@ wmaker_SOURCES += \
|
|||
backend/wayland/wl_xwayland.c \
|
||||
backend/wayland/wl_dock.c \
|
||||
backend/wayland/wl_layer_shell.c \
|
||||
backend/wayland/wl_handlers.c \
|
||||
backend/wayland/wl_icon.c \
|
||||
backend/wayland/wl_virtual_pointer.c \
|
||||
backend/wayland/wl_input_fwd.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1644,26 +1644,6 @@ handle_idle_new_inhibitor(struct wl_listener *listener, void *data)
|
|||
* to the seat so the focused Wayland client receives wl_pointer.axis events.
|
||||
* Without this, scrolling is silently dropped in every Wayland client.
|
||||
*/
|
||||
void
|
||||
handle_pointer_axis(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_pointer_axis_event *ev = data;
|
||||
if (!wl_state.seat)
|
||||
return;
|
||||
/* Drop axis events during a compositor grab so the grabbed window
|
||||
* does not receive unexpected scroll events mid-move/resize. */
|
||||
if (wl_state.grab_type)
|
||||
return;
|
||||
wlr_seat_pointer_notify_axis(wl_state.seat,
|
||||
ev->time_msec,
|
||||
ev->orientation,
|
||||
ev->delta,
|
||||
ev->delta_discrete,
|
||||
ev->source,
|
||||
ev->relative_direction);
|
||||
}
|
||||
|
||||
/*
|
||||
* Phase 30: new pointer constraint — a client requested pointer lock or
|
||||
* pointer confinement (e.g. a game locking the cursor to its window).
|
||||
|
|
@ -1892,158 +1872,6 @@ handle_layer_shell_new_surface(struct wl_listener *listener, void *data)
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
void
|
||||
handle_pointer_button(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_pointer_button_event *ev = data;
|
||||
if (!wl_state.seat)
|
||||
return;
|
||||
/* Phase 22: any button release ends an active compositor grab (move/resize).
|
||||
* Type 3 (WM policy grab) is NOT ended here — the policy code calls
|
||||
* pointer_ungrab itself after processing the button release event. */
|
||||
if (wl_state.grab_type && wl_state.grab_type != 3 &&
|
||||
ev->state == WLR_BUTTON_RELEASED) {
|
||||
wwarning("wl_backend: grab ended (button release) grab_type=%d", wl_state.grab_type);
|
||||
wl_grab_end();
|
||||
wl_update_pointer_focus(ev->time_msec);
|
||||
return;
|
||||
}
|
||||
/* Phase 24: click-to-focus — on button press, find the view under the
|
||||
* pointer and focus + raise it via the WM policy layer.
|
||||
* This mirrors what the X11 backend does via ButtonPress on frame windows. */
|
||||
if (ev->state == WLR_BUTTON_PRESSED) {
|
||||
double sx, sy;
|
||||
struct wl_toplevel_view *view = NULL;
|
||||
view_surface_at(wl_state.pointer_x, wl_state.pointer_y,
|
||||
&sx, &sy, &view);
|
||||
if (view) {
|
||||
WObjDescriptor *desc =
|
||||
wm_backend->context_find(view->id, WM_CTX_CLIENT_WIN);
|
||||
if (desc && desc->parent_type == WCLASS_WINDOW) {
|
||||
WWindow *wwin = (WWindow *)desc->parent;
|
||||
WScreen *scr = wScreenWithNumber(0);
|
||||
wSetFocusTo(scr, wwin);
|
||||
/* Raise entire window assembly via tree */
|
||||
if (view->frame_id) {
|
||||
struct wl_frame_buf *fb = frame_buf_find(view->frame_id);
|
||||
if (fb && fb->tree)
|
||||
wlr_scene_node_raise_to_top(&fb->tree->node);
|
||||
} else if (view->scene_node) {
|
||||
wlr_scene_node_raise_to_top(&view->scene_node->node);
|
||||
}
|
||||
/* Also raise it in our toplevel list so view_surface_at()
|
||||
* returns it first on subsequent hits. */
|
||||
wl_list_remove(&view->link);
|
||||
wl_list_insert(&wl_state.toplevel_list, &view->link);
|
||||
}
|
||||
} else {
|
||||
/* No toplevel surface — check if a WINGs dialog frame_buf was clicked */
|
||||
struct wl_frame_buf *hit = frame_buf_hit(wl_state.pointer_x,
|
||||
wl_state.pointer_y);
|
||||
if (hit) {
|
||||
/* Walk up to the parent frame to find the WWindow */
|
||||
WNativeWindow lookup = hit->parent_id ? hit->parent_id : hit->id;
|
||||
WObjDescriptor *desc =
|
||||
wm_backend->context_find(lookup, WM_CTX_CLIENT_WIN);
|
||||
if (desc && desc->parent_type == WCLASS_WINDOW) {
|
||||
WWindow *wwin = (WWindow *)desc->parent;
|
||||
WScreen *scr = wScreenWithNumber(0);
|
||||
wSetFocusTo(scr, wwin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Phase A: enqueue native WMEvent for WINGs */
|
||||
WMScreen *wmscr = wl_get_wmscreen();
|
||||
if (wmscr) {
|
||||
WMEvent wev;
|
||||
memset(&wev, 0, sizeof(wev));
|
||||
wev.type = (ev->state == WLR_BUTTON_PRESSED)
|
||||
? WME_BUTTON_PRESS : WME_BUTTON_RELEASE;
|
||||
|
||||
/* Hit-test: determine which WM window was clicked.
|
||||
* Use frame_buf_hit so button sub-windows (invisible to the scene
|
||||
* graph because their pixels are composited into the titlebar buffer)
|
||||
* are resolved to their own window IDs, letting handleButtonPress
|
||||
* route the event to buttonMouseDown instead of titlebarMouseDown. */
|
||||
struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x,
|
||||
wl_state.pointer_y);
|
||||
if (fb) {
|
||||
wev.window = fb->id;
|
||||
wev.u.button.window = fb->id;
|
||||
wev.u.button.x = wl_state.pointer_x - fb->x;
|
||||
wev.u.button.y = wl_state.pointer_y - fb->y;
|
||||
} else {
|
||||
WScreen *scr0 = wScreenWithNumber(0);
|
||||
WNativeWindow root = scr0 ? scr0->root_win : (WNativeWindow)0x0FFFFFFF;
|
||||
wev.window = root;
|
||||
wev.u.button.window = root;
|
||||
wev.u.button.x = wl_state.pointer_x;
|
||||
wev.u.button.y = wl_state.pointer_y;
|
||||
}
|
||||
wev.u.button.time = ev->time_msec;
|
||||
wev.u.button.x_root = wl_state.pointer_x;
|
||||
wev.u.button.y_root = wl_state.pointer_y;
|
||||
/* Linux evdev BTN_LEFT=0x110, BTN_RIGHT=0x111, BTN_MIDDLE=0x112
|
||||
* Button1=1(left), Button2=2(middle), Button3=3(right) */
|
||||
switch (ev->button) {
|
||||
case 0x110: wev.u.button.button = 1; break;
|
||||
case 0x111: wev.u.button.button = 3; break;
|
||||
case 0x112: wev.u.button.button = 2; break;
|
||||
default: wev.u.button.button = (ev->button - 0x110) + 1; break;
|
||||
}
|
||||
/* For WINGs views, resolve the child widget at click coordinates */
|
||||
struct W_View *target = NULL;
|
||||
if (fb && fb->id >= 0x20000000) {
|
||||
extern W_View *W_GetViewForWindow(unsigned long id);
|
||||
extern struct W_View *W_FindViewAtPoint(struct W_View *parent, int x, int y);
|
||||
W_View *toplevel = W_GetViewForWindow((unsigned long)fb->id);
|
||||
if (toplevel) {
|
||||
target = W_FindViewAtPoint(toplevel,
|
||||
wev.u.button.x, wev.u.button.y);
|
||||
if (!target)
|
||||
target = toplevel;
|
||||
/* Adjust event coordinates to target view's local space */
|
||||
if (target != toplevel) {
|
||||
W_View *p = target;
|
||||
int ox = 0, oy = 0;
|
||||
while (p && p != toplevel) {
|
||||
ox += p->pos.x;
|
||||
oy += p->pos.y;
|
||||
p = p->parent;
|
||||
}
|
||||
wev.u.button.x -= ox;
|
||||
wev.u.button.y -= oy;
|
||||
}
|
||||
}
|
||||
}
|
||||
W_WL_EnqueueEvent(wmscr, &wev, target);
|
||||
}
|
||||
|
||||
/* Refresh pointer focus before delivering button event.
|
||||
* The last wl_update_pointer_focus call was during the most recent
|
||||
* motion event. If no motion happened since then, the XWayland
|
||||
* surface might not have pointer focus, causing
|
||||
* wlr_seat_pointer_notify_button to be a no-op. */
|
||||
wl_update_pointer_focus(ev->time_msec);
|
||||
|
||||
wlr_seat_pointer_notify_button(wl_state.seat, ev->time_msec,
|
||||
ev->button, ev->state);
|
||||
wlr_seat_pointer_notify_frame(wl_state.seat);
|
||||
}
|
||||
|
||||
void
|
||||
handle_pointer_frame(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener; (void)data;
|
||||
if (wl_state.seat)
|
||||
wlr_seat_pointer_notify_frame(wl_state.seat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Keyboard grabs */
|
||||
|
||||
|
|
@ -2055,7 +1883,6 @@ handle_pointer_frame(struct wl_listener *listener, void *data)
|
|||
/* Screen internals */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
int wl_screen_replace_wm(WScreen *scr) { (void)scr; return 1; }
|
||||
int wl_screen_select_input(WScreen *scr, long mask) { (void)scr; (void)mask; return 1; }
|
||||
void wl_screen_set_root_cursor(WScreen *scr, int cursor_id) { (void)scr; (void)cursor_id; }
|
||||
void wl_screen_set_icon_sizes(WScreen *scr, int min_size, int max_size) { (void)scr; (void)min_size; (void)max_size; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.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 "../../framewin.h"
|
||||
#include "../../window.h"
|
||||
#include "../../icon.h"
|
||||
#include "../../texture.h"
|
||||
#include "../../misc.h"
|
||||
#include "../../defaults.h"
|
||||
#include "../../def_pixmaps.h"
|
||||
#include "wl_types.h"
|
||||
#include <WINGs/WINGsP.h>
|
||||
|
||||
/* Forward declarations */
|
||||
struct wl_frame_buf *frame_buf_find(WNativeWindow id);
|
||||
|
||||
void
|
||||
wl_icon_paint(WIcon *icon)
|
||||
{
|
||||
if (!icon || !icon->core) return;
|
||||
|
||||
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window);
|
||||
if (!fb || !fb->image) return;
|
||||
|
||||
WScreen *scr = icon->core->screen_ptr;
|
||||
if (!scr) return;
|
||||
int size = wPreferences.icon_size;
|
||||
|
||||
RImage *tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL;
|
||||
if (!tile) {
|
||||
tile = RCreateImage(size, size, 1);
|
||||
if (!tile) return;
|
||||
RColor grey = {0xAE, 0xAA, 0xAE, 0xFF};
|
||||
RClearImage(tile, &grey);
|
||||
}
|
||||
|
||||
RImage *img = icon->file_image;
|
||||
if (img) {
|
||||
int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0;
|
||||
unsigned w = ((unsigned)img->width > (unsigned)size) ? (unsigned)size : (unsigned)img->width;
|
||||
unsigned h = ((unsigned)img->height + (unsigned)theight > (unsigned)size)
|
||||
? (unsigned)(size - theight) : (unsigned)img->height;
|
||||
int x = (size - (int)w) / 2;
|
||||
int y = theight + (size - theight - (int)h) / 2;
|
||||
int sx = ((int)img->width - (int)w) / 2;
|
||||
int sy = ((int)img->height - (int)h) / 2;
|
||||
RCombineArea(tile, img, sx, sy, w, h, x, y);
|
||||
}
|
||||
|
||||
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
|
||||
int stride = pixman_image_get_stride(fb->image) / 4;
|
||||
unsigned char *tsrc = tile->data;
|
||||
int has_alpha = (tile->format == RRGBAFormat);
|
||||
for (int row = 0; row < size && row < fb->height; row++) {
|
||||
for (int col = 0; col < size && col < fb->width; col++) {
|
||||
int si = (row * tile->width + col) * (has_alpha ? 4 : 3);
|
||||
unsigned char r = tsrc[si], g = tsrc[si+1], b = tsrc[si+2];
|
||||
unsigned char a = has_alpha ? tsrc[si+3] : 0xFF;
|
||||
dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16)
|
||||
| ((uint32_t)g << 8) | (uint32_t)b;
|
||||
}
|
||||
}
|
||||
RReleaseImage(tile);
|
||||
|
||||
if (icon->show_title && icon->icon_name && scr->icon_title_font) {
|
||||
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
|
||||
int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name,
|
||||
strlen(icon->icon_name));
|
||||
int tx = (size - tw) / 2;
|
||||
if (tx < 2) tx = 2;
|
||||
WMColor *color = scr->icon_title_color;
|
||||
if (color)
|
||||
WMDrawString(scr->wmscreen, d, color, scr->icon_title_font,
|
||||
tx, 0, icon->icon_name, strlen(icon->icon_name));
|
||||
}
|
||||
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
if (fb->tree)
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, true);
|
||||
}
|
||||
|
||||
void
|
||||
wl_appicon_show(WApplication *wapp)
|
||||
{
|
||||
extern void paint_app_icon(WApplication *wapp);
|
||||
paint_app_icon(wapp);
|
||||
}
|
||||
|
||||
void
|
||||
wl_appicon_paint(WAppIcon *aicon)
|
||||
{
|
||||
WIcon *icon = aicon->icon;
|
||||
if (!icon || !icon->core)
|
||||
return;
|
||||
|
||||
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window);
|
||||
if (!fb || !fb->image)
|
||||
return;
|
||||
|
||||
WScreen *scr = icon->core->screen_ptr;
|
||||
int size = wPreferences.icon_size;
|
||||
|
||||
RImage *tile = NULL;
|
||||
switch (icon->tile_type) {
|
||||
case TILE_CLIP: tile = scr->clip_tile ? RCloneImage(scr->clip_tile) : NULL; break;
|
||||
case TILE_DRAWER: tile = scr->drawer_tile ? RCloneImage(scr->drawer_tile) : NULL; break;
|
||||
default: tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; break;
|
||||
}
|
||||
if (!tile) {
|
||||
tile = RCreateImage(size, size, 1);
|
||||
if (!tile) return;
|
||||
RColor grey = {0xAE, 0xAA, 0xAE, 0xFF};
|
||||
RClearImage(tile, &grey);
|
||||
}
|
||||
|
||||
if (icon->file_image) {
|
||||
RImage *img = icon->file_image;
|
||||
int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0;
|
||||
unsigned w = (img->width > size) ? size : img->width;
|
||||
unsigned h = (img->height + theight > size) ? size - theight : img->height;
|
||||
int x = (size - (int)w) / 2;
|
||||
int y = theight + (size - theight - (int)h) / 2;
|
||||
int sx = ((int)img->width - (int)w) / 2;
|
||||
int sy = ((int)img->height - (int)h) / 2;
|
||||
RCombineArea(tile, img, sx, sy, w, h, x, y);
|
||||
}
|
||||
|
||||
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
|
||||
int stride = pixman_image_get_stride(fb->image) / 4;
|
||||
unsigned char *src = tile->data;
|
||||
int has_alpha = (tile->format == RRGBAFormat);
|
||||
|
||||
for (int row = 0; row < size && row < fb->height; row++) {
|
||||
for (int col = 0; col < size && col < fb->width; col++) {
|
||||
int si = (row * tile->width + col) * (has_alpha ? 4 : 3);
|
||||
unsigned char r = src[si], g = src[si+1], b = src[si+2];
|
||||
unsigned char a = has_alpha ? src[si+3] : 0xFF;
|
||||
dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) |
|
||||
((uint32_t)g << 8) | (uint32_t)b;
|
||||
}
|
||||
}
|
||||
|
||||
if (icon->show_title && icon->icon_name && scr->icon_title_font) {
|
||||
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
|
||||
int fh = WMFontHeight(scr->icon_title_font);
|
||||
int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name,
|
||||
strlen(icon->icon_name));
|
||||
int tx = (size - tw) / 2;
|
||||
if (tx < 2) tx = 2;
|
||||
int ty = 0;
|
||||
WMColor *color = scr->icon_title_color;
|
||||
if (color)
|
||||
WMDrawString(scr->wmscreen, d, color, scr->icon_title_font,
|
||||
tx, ty, icon->icon_name, strlen(icon->icon_name));
|
||||
}
|
||||
|
||||
RReleaseImage(tile);
|
||||
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
}
|
||||
|
|
@ -41,6 +41,9 @@ struct wl_toplevel_view *wl_find_view_by_id(WNativeWindow id);
|
|||
void wl_set_cursor_image(const char *name);
|
||||
void wl_frame_paint_button(WCoreWindow *button, WTexture *texture, unsigned long color, WPixmap *image, int pushed);
|
||||
void wl_netwm_update_opacity(WWindow *wwin);
|
||||
void wl_icon_paint(WIcon *icon);
|
||||
void wl_appicon_show(WApplication *wapp);
|
||||
void wl_appicon_paint(WAppIcon *aicon);
|
||||
extern void *W_RegisterBacking(unsigned long id, void *img);
|
||||
extern void W_UnregisterBacking(unsigned long id);
|
||||
|
||||
|
|
@ -167,155 +170,6 @@ void wl_noop_icon_update_pixmap(WIcon *icon) { (void)icon; }
|
|||
* Called at the end of wIconPaint() in icon.c so the backend finalises the
|
||||
* surface after the policy layer has set up icon->file_image etc.
|
||||
*/
|
||||
void
|
||||
wl_icon_paint(WIcon *icon)
|
||||
{
|
||||
if (!icon || !icon->core) return;
|
||||
|
||||
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window);
|
||||
if (!fb || !fb->image) return;
|
||||
|
||||
WScreen *scr = icon->core->screen_ptr;
|
||||
if (!scr) return;
|
||||
int size = wPreferences.icon_size;
|
||||
|
||||
/* --- Tile background --- */
|
||||
RImage *tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL;
|
||||
if (!tile) {
|
||||
tile = RCreateImage(size, size, 1);
|
||||
if (!tile) return;
|
||||
RColor grey = {0xAE, 0xAA, 0xAE, 0xFF};
|
||||
RClearImage(tile, &grey);
|
||||
}
|
||||
|
||||
/* --- Composite icon image (file_image from database / NET_WM_ICON) --- */
|
||||
RImage *img = icon->file_image;
|
||||
if (img) {
|
||||
int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0;
|
||||
unsigned w = ((unsigned)img->width > (unsigned)size) ? (unsigned)size : (unsigned)img->width;
|
||||
unsigned h = ((unsigned)img->height + (unsigned)theight > (unsigned)size)
|
||||
? (unsigned)(size - theight) : (unsigned)img->height;
|
||||
int x = (size - (int)w) / 2;
|
||||
int y = theight + (size - theight - (int)h) / 2;
|
||||
int sx = ((int)img->width - (int)w) / 2;
|
||||
int sy = ((int)img->height - (int)h) / 2;
|
||||
RCombineArea(tile, img, sx, sy, w, h, x, y);
|
||||
}
|
||||
|
||||
/* --- Blit RImage (RGBA/RGB) -> pixman ARGB32 --- */
|
||||
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
|
||||
int stride = pixman_image_get_stride(fb->image) / 4;
|
||||
unsigned char *tsrc = tile->data;
|
||||
int has_alpha = (tile->format == RRGBAFormat);
|
||||
for (int row = 0; row < size && row < fb->height; row++) {
|
||||
for (int col = 0; col < size && col < fb->width; col++) {
|
||||
int si = (row * tile->width + col) * (has_alpha ? 4 : 3);
|
||||
unsigned char r = tsrc[si], g = tsrc[si+1], b = tsrc[si+2];
|
||||
unsigned char a = has_alpha ? tsrc[si+3] : 0xFF;
|
||||
dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16)
|
||||
| ((uint32_t)g << 8) | (uint32_t)b;
|
||||
}
|
||||
}
|
||||
RReleaseImage(tile);
|
||||
|
||||
/* --- Title text --- */
|
||||
if (icon->show_title && icon->icon_name && scr->icon_title_font) {
|
||||
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
|
||||
int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name,
|
||||
strlen(icon->icon_name));
|
||||
int tx = (size - tw) / 2;
|
||||
if (tx < 2) tx = 2;
|
||||
WMColor *color = scr->icon_title_color;
|
||||
if (color)
|
||||
WMDrawString(scr->wmscreen, d, color, scr->icon_title_font,
|
||||
tx, 0, icon->icon_name, strlen(icon->icon_name));
|
||||
}
|
||||
|
||||
/* --- Commit to scene graph --- */
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
if (fb->tree)
|
||||
wlr_scene_node_set_enabled(&fb->tree->node, true);
|
||||
}
|
||||
void wl_appicon_show(WApplication *wapp) { paint_app_icon(wapp); }
|
||||
void wl_appicon_paint(WAppIcon *aicon)
|
||||
{
|
||||
WIcon *icon = aicon->icon;
|
||||
if (!icon || !icon->core)
|
||||
return;
|
||||
|
||||
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window);
|
||||
if (!fb || !fb->image)
|
||||
return;
|
||||
|
||||
WScreen *scr = icon->core->screen_ptr;
|
||||
int size = wPreferences.icon_size;
|
||||
|
||||
/* Compose the tile image */
|
||||
RImage *tile = NULL;
|
||||
switch (icon->tile_type) {
|
||||
case TILE_CLIP: tile = scr->clip_tile ? RCloneImage(scr->clip_tile) : NULL; break;
|
||||
case TILE_DRAWER: tile = scr->drawer_tile ? RCloneImage(scr->drawer_tile) : NULL; break;
|
||||
default: tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; break;
|
||||
}
|
||||
if (!tile) {
|
||||
/* Fallback: solid grey */
|
||||
tile = RCreateImage(size, size, 1);
|
||||
if (!tile) return;
|
||||
RColor grey = {0xAE, 0xAA, 0xAE, 0xFF};
|
||||
RClearImage(tile, &grey);
|
||||
}
|
||||
|
||||
/* Composite the app image on top */
|
||||
if (icon->file_image) {
|
||||
RImage *img = icon->file_image;
|
||||
int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0;
|
||||
unsigned w = (img->width > size) ? size : img->width;
|
||||
unsigned h = (img->height + theight > size) ? size - theight : img->height;
|
||||
int x = (size - (int)w) / 2;
|
||||
int y = theight + (size - theight - (int)h) / 2;
|
||||
int sx = ((int)img->width - (int)w) / 2;
|
||||
int sy = ((int)img->height - (int)h) / 2;
|
||||
RCombineArea(tile, img, sx, sy, w, h, x, y);
|
||||
}
|
||||
|
||||
/* Blit RImage (RGBA) → pixman ARGB32 buffer */
|
||||
uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image);
|
||||
int stride = pixman_image_get_stride(fb->image) / 4;
|
||||
unsigned char *src = tile->data;
|
||||
int has_alpha = (tile->format == RRGBAFormat);
|
||||
|
||||
for (int row = 0; row < size && row < fb->height; row++) {
|
||||
for (int col = 0; col < size && col < fb->width; col++) {
|
||||
int si = (row * tile->width + col) * (has_alpha ? 4 : 3);
|
||||
unsigned char r = src[si], g = src[si+1], b = src[si+2];
|
||||
unsigned char a = has_alpha ? src[si+3] : 0xFF;
|
||||
dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) |
|
||||
((uint32_t)g << 8) | (uint32_t)b;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw title text */
|
||||
if (icon->show_title && icon->icon_name && scr->icon_title_font) {
|
||||
WMDrawable d = (WMDrawable)(uintptr_t)fb->image;
|
||||
int fh = WMFontHeight(scr->icon_title_font);
|
||||
int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name,
|
||||
strlen(icon->icon_name));
|
||||
int tx = (size - tw) / 2;
|
||||
if (tx < 2) tx = 2;
|
||||
int ty = 0; /* top of text area */
|
||||
WMColor *color = scr->icon_title_color;
|
||||
if (color)
|
||||
WMDrawString(scr->wmscreen, d, color, scr->icon_title_font,
|
||||
tx, ty, icon->icon_name, strlen(icon->icon_name));
|
||||
}
|
||||
|
||||
RReleaseImage(tile);
|
||||
|
||||
/* Commit to scene graph */
|
||||
wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, true);
|
||||
}
|
||||
void wl_noop_restore_desktop(WScreen *scr) { (void)scr; }
|
||||
void wl_noop_wipe_desktop(WScreen *scr) { (void)scr; }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue