seperate wayland's cairo functionality into a backend that can be used seperately

This commit is contained in:
IoIxD 2026-07-09 21:45:30 -07:00
commit c2bb601311
9 changed files with 563 additions and 285 deletions

View file

@ -245,6 +245,7 @@ if(MW_USE_WAYLAND)
target_sources(
Mw
PRIVATE
src/backend/cairo.c
src/backend/wayland/wayland.c
src/backend/wayland/buffer.c
src/backend/wayland/interfaces.c

View file

@ -132,6 +132,7 @@ union _MwLL {
#endif
#ifdef USE_WAYLAND
struct _MwLLWayland wayland;
struct _MwLLCairo cairo;
#endif
#ifdef USE_COCOA
struct _MwLLCocoa cocoa;
@ -153,7 +154,7 @@ union _MwLLColor {
struct _MwLLGDIColor gdi;
#endif
#ifdef USE_WAYLAND
struct _MwLLWaylandColor wayland;
struct _MwLLCairoColor wayland;
#endif
#ifdef USE_COCOA
struct _MwLLCocoaColor cocoa;
@ -173,6 +174,7 @@ union _MwLLPixmap {
#endif
#ifdef USE_WAYLAND
struct _MwLLWaylandPixmap wayland;
struct _MwLLCairoPixmap cairo; /* same structure but we do this for code clarity */
#endif
#ifdef USE_COCOA
struct _MwLLCocoaPixmap cocoa;

229
include/Mw/LowLevel/Cairo.h Normal file
View file

@ -0,0 +1,229 @@
/*!
* @file Mw/LowLevel/Cairo.h
* @brief Cairo Backend
* @warning This is used MEGA internally.
*/
#ifndef __MW_LOWLEVEL_CAIRO_H__
#define __MW_LOWLEVEL_CAIRO_H__
#include <Mw/MachDep.h>
#include <Mw/TypeDefs.h>
#include <Mw/LowLevel.h>
#include <Mw/Abstract/Dynamic.h>
#include <cairo/cairo.h>
#ifdef __cplusplus
extern "C" {
#endif
MWDECL int MwLLCairoCallInit(void);
#ifdef __cplusplus
}
#endif
#define CSD_BORDER_FRAME_LEFT 5
#define CSD_BORDER_FRAME_RIGHT 5
#define CSD_BORDER_FRAME_TOP 23
#define CSD_BORDER_FRAME_BOTTOM 4
typedef struct cairo_call_table {
void* cairo_lib;
void (*cairo_set_line_width)(cairo_t* cr,
double width);
void (*cairo_scale)(cairo_t* cr,
double sx,
double sy);
cairo_t* (*cairo_create)(cairo_surface_t* target);
void (*cairo_move_to)(cairo_t* cr,
double x,
double y);
void (*cairo_rectangle)(cairo_t* cr,
double x,
double y,
double width,
double height);
void (*cairo_new_path)(cairo_t* cr);
void (*cairo_set_line_cap)(cairo_t* cr,
cairo_line_cap_t line_cap);
void (*cairo_set_source_rgba)(cairo_t* cr,
double red,
double green,
double blue,
double alpha);
void (*cairo_set_source_rgb)(cairo_t* cr,
double red,
double green,
double blue);
void (*cairo_reset_clip)(cairo_t* cr);
unsigned char* (*cairo_image_surface_get_data)(cairo_surface_t* surface);
void (*cairo_line_to)(cairo_t* cr,
double x,
double y);
cairo_status_t (*cairo_surface_write_to_png)(cairo_surface_t* surface, const char* filename);
void (*cairo_surface_destroy)(cairo_surface_t* surface);
cairo_surface_t* (*cairo_image_surface_create_for_data)(unsigned char* data,
cairo_format_t format,
int width,
int height,
int stride);
cairo_surface_t* (*cairo_image_surface_create)(cairo_format_t format,
int width,
int height);
void (*cairo_destroy)(cairo_t* cr);
cairo_pattern_t* (*cairo_get_source)(cairo_t* cr);
void (*cairo_close_path)(cairo_t* cr);
void (*cairo_paint)(cairo_t* cr);
void (*cairo_surface_flush)(cairo_surface_t* surface);
void (*cairo_clip)(cairo_t* cr);
void (*cairo_save)(cairo_t* cr);
void (*cairo_restore)(cairo_t* cr);
void (*cairo_surface_mark_dirty)(cairo_surface_t* surface);
void (*cairo_stroke)(cairo_t* cr);
void (*cairo_set_source_surface)(cairo_t* cr,
cairo_surface_t* surface,
double x,
double y);
void (*cairo_fill)(cairo_t* cr);
void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern,
cairo_filter_t filter);
void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t);
void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op);
} cairo_call_table_t;
extern cairo_call_table_t cairo_call_tbl;
/* defined inline right here so that it doesn't conflict with the other macros */
MwInline int cairo_load_funcs() {
#ifdef __APPLE__
cairo_call_tbl.cairo_lib = MwDynamicOpen("libcairo.dylib");
#else
cairo_call_tbl.cairo_lib = MwDynamicOpen("libcairo.so");
#endif
if(!cairo_call_tbl.cairo_lib) {
printf("(libcairo not found, cannot use Wayland or Cairo backend.)\n");
return 1;
}
#define CAIRO_FUNC(x) \
cairo_call_tbl.x = MwDynamicSymbol(cairo_call_tbl.cairo_lib, #x); \
if(!cairo_call_tbl.x) { \
printf("WARNING: Could use Wayland/Cairo backend if " #x " was not found. Do you have libcairo?\n"); \
return 1; \
};
CAIRO_FUNC(cairo_set_line_width);
CAIRO_FUNC(cairo_scale);
CAIRO_FUNC(cairo_create);
CAIRO_FUNC(cairo_move_to);
CAIRO_FUNC(cairo_rectangle);
CAIRO_FUNC(cairo_new_path);
CAIRO_FUNC(cairo_set_line_cap);
CAIRO_FUNC(cairo_set_antialias);
CAIRO_FUNC(cairo_set_source_rgba);
CAIRO_FUNC(cairo_set_source_rgb);
CAIRO_FUNC(cairo_reset_clip);
CAIRO_FUNC(cairo_image_surface_get_data);
CAIRO_FUNC(cairo_line_to);
CAIRO_FUNC(cairo_surface_write_to_png);
CAIRO_FUNC(cairo_surface_destroy);
CAIRO_FUNC(cairo_image_surface_create_for_data);
CAIRO_FUNC(cairo_image_surface_create);
CAIRO_FUNC(cairo_destroy);
CAIRO_FUNC(cairo_get_source);
CAIRO_FUNC(cairo_close_path);
CAIRO_FUNC(cairo_paint);
CAIRO_FUNC(cairo_surface_flush);
CAIRO_FUNC(cairo_clip);
CAIRO_FUNC(cairo_save);
CAIRO_FUNC(cairo_restore);
CAIRO_FUNC(cairo_surface_mark_dirty);
CAIRO_FUNC(cairo_stroke);
CAIRO_FUNC(cairo_set_source_surface);
CAIRO_FUNC(cairo_fill);
CAIRO_FUNC(cairo_set_operator);
CAIRO_FUNC(cairo_pattern_set_filter);
#undef CAIRO_FUNC
return 0;
}
#define cairo_set_line_width cairo_call_tbl.cairo_set_line_width
#define cairo_scale cairo_call_tbl.cairo_scale
#define cairo_create cairo_call_tbl.cairo_create
#define cairo_move_to cairo_call_tbl.cairo_move_to
#define cairo_rectangle cairo_call_tbl.cairo_rectangle
#define cairo_new_path cairo_call_tbl.cairo_new_path
#define cairo_set_line_cap cairo_call_tbl.cairo_set_line_cap
#define cairo_set_antialias cairo_call_tbl.cairo_set_antialias
#define cairo_set_source_rgba cairo_call_tbl.cairo_set_source_rgba
#define cairo_set_source_rgb cairo_call_tbl.cairo_set_source_rgb
#define cairo_reset_clip cairo_call_tbl.cairo_reset_clip
#define cairo_image_surface_get_data cairo_call_tbl.cairo_image_surface_get_data
#define cairo_line_to cairo_call_tbl.cairo_line_to
#define cairo_surface_write_to_png cairo_call_tbl.cairo_surface_write_to_png
#define cairo_surface_destroy cairo_call_tbl.cairo_surface_destroy
#define cairo_image_surface_create_for_data cairo_call_tbl.cairo_image_surface_create_for_data
#define cairo_image_surface_create cairo_call_tbl.cairo_image_surface_create
#define cairo_destroy cairo_call_tbl.cairo_destroy
#define cairo_get_source cairo_call_tbl.cairo_get_source
#define cairo_close_path cairo_call_tbl.cairo_close_path
#define cairo_paint cairo_call_tbl.cairo_paint
#define cairo_surface_flush cairo_call_tbl.cairo_surface_flush
#define cairo_clip cairo_call_tbl.cairo_clip
#define cairo_save cairo_call_tbl.cairo_save
#define cairo_restore cairo_call_tbl.cairo_restore
#define cairo_surface_mark_dirty cairo_call_tbl.cairo_surface_mark_dirty
#define cairo_stroke cairo_call_tbl.cairo_stroke
#define cairo_set_source_surface cairo_call_tbl.cairo_set_source_surface
#define cairo_fill cairo_call_tbl.cairo_fill
#define cairo_set_operator cairo_call_tbl.cairo_set_operator
#define cairo_pattern_set_filter cairo_call_tbl.cairo_pattern_set_filter
struct _MwLLCairo {
struct _MwLLCommon common;
cairo_surface_t* front_cs;
cairo_surface_t* back_cs;
cairo_t* front_cairo;
cairo_t* back_cairo;
/* The cairo to actually use for draw operations. Typically is front_cairo, but wayland's MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */
cairo_t* selected_cairo;
int x;
int y;
int width;
int height;
MwBool toplevel;
MwLL parent;
};
struct _MwLLCairoColor {
struct _MwLLCommonColor common;
};
struct _MwLLCairoPixmap {
struct _MwLLCommonPixmap common;
cairo_surface_t* cs;
};
void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height);
void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height);
void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo);
void MwLLCairoBackDestroy(struct _MwLLCairo* cairo);
void MwLLCairoPolygon(struct _MwLLCairo handle, MwPoint* points, int points_count, MwLLColor color);
void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color);
MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, int width, int height);
void MwLLCairoPixmapUpdate(MwLLPixmap handle);
void MwLLCairoDestroyPixmap(MwLLPixmap pixmap);
void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixmap);
void MwLLCairoDestroy(struct _MwLLCairo handle);
#endif

View file

@ -11,8 +11,9 @@
#include <Mw/LowLevel.h>
#include <Mw/Abstract/Dynamic.h>
#include <Mw/LowLevel/Cairo.h>
#include <xkbcommon/xkbcommon.h>
#include <cairo/cairo.h>
#include <pthread.h>
#ifdef __cplusplus
@ -42,7 +43,6 @@ struct _MwLLWayland;
typedef struct wayland_call_table {
void* lib;
void* xkb_lib;
void* cairo_lib;
#ifdef USE_DBUS
MwLLDBusFuncTable dbus;
MwBool has_dbus;
@ -79,67 +79,6 @@ typedef struct wayland_call_table {
xkb_layout_index_t (*xkb_state_key_get_layout)(struct xkb_state* state, xkb_keycode_t key);
void (*xkb_keymap_unref)(struct xkb_keymap* keymap);
void (*cairo_set_line_width)(cairo_t* cr,
double width);
void (*cairo_scale)(cairo_t* cr,
double sx,
double sy);
cairo_t* (*cairo_create)(cairo_surface_t* target);
void (*cairo_move_to)(cairo_t* cr,
double x,
double y);
void (*cairo_rectangle)(cairo_t* cr,
double x,
double y,
double width,
double height);
void (*cairo_new_path)(cairo_t* cr);
void (*cairo_set_line_cap)(cairo_t* cr,
cairo_line_cap_t line_cap);
void (*cairo_set_source_rgba)(cairo_t* cr,
double red,
double green,
double blue,
double alpha);
void (*cairo_set_source_rgb)(cairo_t* cr,
double red,
double green,
double blue);
void (*cairo_reset_clip)(cairo_t* cr);
unsigned char* (*cairo_image_surface_get_data)(cairo_surface_t* surface);
void (*cairo_line_to)(cairo_t* cr,
double x,
double y);
void (*cairo_surface_destroy)(cairo_surface_t* surface);
cairo_surface_t* (*cairo_image_surface_create_for_data)(unsigned char* data,
cairo_format_t format,
int width,
int height,
int stride);
cairo_surface_t* (*cairo_image_surface_create)(cairo_format_t format,
int width,
int height);
void (*cairo_destroy)(cairo_t* cr);
cairo_pattern_t* (*cairo_get_source)(cairo_t* cr);
void (*cairo_close_path)(cairo_t* cr);
void (*cairo_paint)(cairo_t* cr);
void (*cairo_surface_flush)(cairo_surface_t* surface);
void (*cairo_clip)(cairo_t* cr);
void (*cairo_save)(cairo_t* cr);
void (*cairo_restore)(cairo_t* cr);
void (*cairo_surface_mark_dirty)(cairo_surface_t* surface);
void (*cairo_stroke)(cairo_t* cr);
void (*cairo_set_source_surface)(cairo_t* cr,
cairo_surface_t* surface,
double x,
double y);
void (*cairo_fill)(cairo_t* cr);
void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern,
cairo_filter_t filter);
void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t);
void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op);
} wayland_call_table_t;
extern wayland_call_table_t wl_call_tbl;
@ -149,6 +88,8 @@ extern MwBool MwWaylandVulkan;
#define MwWaylandVulkan 0
#endif
MWDECL MwBool MwWaylandCairoOnly;
/* defined inline right here so that it doesn't conflict with the other macros */
MwInline int wayland_load_funcs() {
#ifdef __APPLE__
@ -169,15 +110,7 @@ MwInline int wayland_load_funcs() {
printf("(libxkbcommon not found, cannot use Wayland backend.)\n");
return 1;
}
#ifdef __APPLE__
wl_call_tbl.cairo_lib = MwDynamicOpen("libcairo.dylib");
#else
wl_call_tbl.cairo_lib = MwDynamicOpen("libcairo.so");
#endif
if(!wl_call_tbl.cairo_lib) {
printf("(libcairo not found, cannot use Wayland backend.)\n");
return 1;
}
#define WAYLAND_FUNC(x) \
wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.lib, #x); \
if(!wl_call_tbl.x) { \
@ -223,44 +156,9 @@ MwInline int wayland_load_funcs() {
XKB_FUNC(xkb_state_key_get_layout)
#undef XKB_FUNC
#define CAIRO_FUNC(x) \
wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.cairo_lib, #x); \
if(!wl_call_tbl.x) { \
printf("WARNING: Could use Wayland backend if " #x " was found. Do you have libcairo?\n"); \
return 1; \
};
CAIRO_FUNC(cairo_set_line_width);
CAIRO_FUNC(cairo_scale);
CAIRO_FUNC(cairo_create);
CAIRO_FUNC(cairo_move_to);
CAIRO_FUNC(cairo_rectangle);
CAIRO_FUNC(cairo_new_path);
CAIRO_FUNC(cairo_set_line_cap);
CAIRO_FUNC(cairo_set_antialias);
CAIRO_FUNC(cairo_set_source_rgba);
CAIRO_FUNC(cairo_set_source_rgb);
CAIRO_FUNC(cairo_reset_clip);
CAIRO_FUNC(cairo_image_surface_get_data);
CAIRO_FUNC(cairo_line_to);
CAIRO_FUNC(cairo_surface_destroy);
CAIRO_FUNC(cairo_image_surface_create_for_data);
CAIRO_FUNC(cairo_image_surface_create);
CAIRO_FUNC(cairo_destroy);
CAIRO_FUNC(cairo_get_source);
CAIRO_FUNC(cairo_close_path);
CAIRO_FUNC(cairo_paint);
CAIRO_FUNC(cairo_surface_flush);
CAIRO_FUNC(cairo_clip);
CAIRO_FUNC(cairo_save);
CAIRO_FUNC(cairo_restore);
CAIRO_FUNC(cairo_surface_mark_dirty);
CAIRO_FUNC(cairo_stroke);
CAIRO_FUNC(cairo_set_source_surface);
CAIRO_FUNC(cairo_fill);
CAIRO_FUNC(cairo_set_operator);
CAIRO_FUNC(cairo_pattern_set_filter);
#undef CAIRO_FUNC
if(cairo_load_funcs() != 0) {
return 1;
}
#ifdef USE_DBUS
wl_call_tbl.has_dbus = MwLLDBusFuncSetup(&wl_call_tbl.dbus);
@ -297,37 +195,6 @@ MwInline int wayland_load_funcs() {
#define xkb_keymap_key_get_syms_by_level wl_call_tbl.xkb_keymap_key_get_syms_by_level
#define xkb_state_key_get_layout wl_call_tbl.xkb_state_key_get_layout
#define cairo_set_line_width wl_call_tbl.cairo_set_line_width
#define cairo_scale wl_call_tbl.cairo_scale
#define cairo_create wl_call_tbl.cairo_create
#define cairo_move_to wl_call_tbl.cairo_move_to
#define cairo_rectangle wl_call_tbl.cairo_rectangle
#define cairo_new_path wl_call_tbl.cairo_new_path
#define cairo_set_line_cap wl_call_tbl.cairo_set_line_cap
#define cairo_set_antialias wl_call_tbl.cairo_set_antialias
#define cairo_set_source_rgba wl_call_tbl.cairo_set_source_rgba
#define cairo_set_source_rgb wl_call_tbl.cairo_set_source_rgb
#define cairo_reset_clip wl_call_tbl.cairo_reset_clip
#define cairo_image_surface_get_data wl_call_tbl.cairo_image_surface_get_data
#define cairo_line_to wl_call_tbl.cairo_line_to
#define cairo_surface_destroy wl_call_tbl.cairo_surface_destroy
#define cairo_image_surface_create_for_data wl_call_tbl.cairo_image_surface_create_for_data
#define cairo_image_surface_create wl_call_tbl.cairo_image_surface_create
#define cairo_destroy wl_call_tbl.cairo_destroy
#define cairo_get_source wl_call_tbl.cairo_get_source
#define cairo_close_path wl_call_tbl.cairo_close_path
#define cairo_paint wl_call_tbl.cairo_paint
#define cairo_surface_flush wl_call_tbl.cairo_surface_flush
#define cairo_clip wl_call_tbl.cairo_clip
#define cairo_save wl_call_tbl.cairo_save
#define cairo_restore wl_call_tbl.cairo_restore
#define cairo_surface_mark_dirty wl_call_tbl.cairo_surface_mark_dirty
#define cairo_stroke wl_call_tbl.cairo_stroke
#define cairo_set_source_surface wl_call_tbl.cairo_set_source_surface
#define cairo_fill wl_call_tbl.cairo_fill
#define cairo_set_operator wl_call_tbl.cairo_set_operator
#define cairo_pattern_set_filter wl_call_tbl.cairo_pattern_set_filter
#ifndef WL_PROTOCOLS_DEFINED
#define WL_PROTOCOLS_DEFINED
#include "Wayland/wayland-core-protocol.h"
@ -434,6 +301,7 @@ typedef struct wl_clipboard_device_context {
struct _MwLLWayland {
struct _MwLLCommon common;
struct _MwLLCairo cairo;
union {
/* Pointer for data that's only loaded if the widget is a toplevel */
@ -583,24 +451,13 @@ struct _MwLLWayland {
MwU64 next_elapsed;
long start_time;
long end_time;
cairo_surface_t* front_cs;
cairo_surface_t* back_cs;
cairo_t* front_cairo;
cairo_t* back_cairo;
/* The cairo to actually use for draw operations. Typically is front_cairo, but MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */
cairo_t* selected_cairo;
};
struct _MwLLWaylandColor {
struct _MwLLCommonColor common;
};
struct _MwLLWaylandPixmap {
struct _MwLLCommonPixmap common;
cairo_surface_t* cs;
};
#define _MwLLWaylandPixmap _MwLLCairoPixmap
/* Setup the framebuffer with the saved width/height */
void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland);

View file

@ -46,6 +46,7 @@ if (grep(/^classicmacos$/, @backends)) {
if (grep(/^wayland$/, @backends)) {
add_cflags("-DUSE_WAYLAND");
new_object("src/backend/cairo.c");
new_object("src/backend/wayland/wayland.c");
new_object("src/backend/wayland/buffer.c");
new_object("src/backend/wayland/interfaces.c");

266
src/backend/cairo.c Normal file
View file

@ -0,0 +1,266 @@
#include <Mw/Milsko.h>
#include "../../external/stb_ds.h"
#include "stb_ds.h"
cairo_call_table_t cairo_call_tbl;
void MwLLCairoPolygon(struct _MwLLCairo handle, MwPoint* points, int points_count, MwLLColor color) {
int i;
cairo_set_source_rgba(handle.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle.front_cairo);
for(i = 0; i < points_count; i++) {
if(i == 0) {
cairo_move_to(handle.front_cairo, points[i].x, points[i].y);
} else {
cairo_line_to(handle.front_cairo, points[i].x, points[i].y);
}
}
cairo_close_path(handle.front_cairo);
cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_SOURCE);
cairo_fill(handle.front_cairo);
cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_OVER);
};
void MwLLCairoLine(struct _MwLLCairo handle, MwPoint* points, MwLLColor color) {
int i;
cairo_set_antialias(handle.front_cairo, CAIRO_ANTIALIAS_NONE);
cairo_set_line_cap(handle.front_cairo, CAIRO_LINE_CAP_SQUARE);
cairo_set_source_rgba(handle.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle.front_cairo);
for(i = 0; i < 2; i++) {
if(i == 0) {
cairo_move_to(handle.front_cairo, points[i].x, points[i].y);
} else {
cairo_line_to(handle.front_cairo, points[i].x, points[i].y);
}
}
cairo_close_path(handle.front_cairo);
cairo_stroke(handle.front_cairo);
};
MwLLPixmap MwLLCairoCreatePixmap(struct _MwLLCairo handle, unsigned char* data, int width, int height) {
MwLLPixmap r = malloc(sizeof(*r));
(void)handle;
if(width >= INT16_MAX) width = INT16_MAX;
if(height >= INT16_MAX) height = INT16_MAX;
r->common.width = width;
r->common.height = height;
r->common.raw = malloc(4 * width * height);
memcpy(r->common.raw, data, 4 * width * height);
r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
MwLLPixmapUpdate(r);
return r;
}
void MwLLCairoPixmapUpdate(MwLLPixmap r) {
int i;
unsigned char* d;
cairo_surface_flush(r->wayland.cs);
d = cairo_image_surface_get_data(r->wayland.cs);
for(i = 0; i < r->common.width * r->common.height * 4; i += 4) {
MwU32* p = (MwU32*)&d[i];
*p <<= 8;
*p |= r->common.raw[i + 3];
*p <<= 8;
*p |= r->common.raw[i + 0];
*p <<= 8;
*p |= r->common.raw[i + 1];
*p <<= 8;
*p |= r->common.raw[i + 2];
}
cairo_surface_mark_dirty(r->wayland.cs);
}
void MwLLCairoDestroyPixmap(MwLLPixmap pixmap) {
cairo_surface_destroy(pixmap->wayland.cs);
free(pixmap->common.raw);
free(pixmap);
}
void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixmap) {
cairo_t* c;
cairo_surface_t* cs;
cairo_t* selected_cairo = handle.selected_cairo ? handle.selected_cairo : handle.front_cairo;
cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height);
c = cairo_create(cs);
if(rect->width <= 0 || rect->height <= 0 || pixmap->common.width <= 0 || pixmap->common.height <= 0) return;
if(rect->width >= INT16_MAX) rect->width = INT16_MAX;
if(rect->height >= INT16_MAX) rect->height = INT16_MAX;
cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height);
cairo_set_source_surface(c, pixmap->cairo.cs, 0, 0);
cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST);
cairo_set_operator(handle.front_cairo, CAIRO_OPERATOR_OVER);
cairo_paint(c);
cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y);
cairo_paint(selected_cairo);
cairo_destroy(c);
cairo_surface_destroy(cs);
};
void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) {
if(data) {
cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
} else {
cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
}
cairo->front_cairo = cairo_create(cairo->front_cs);
}
void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) {
if(data) {
cairo->back_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
} else {
cairo->back_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
}
cairo->back_cairo = cairo_create(cairo->back_cs);
}
void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) {
cairo_destroy(cairo->front_cairo);
cairo_surface_destroy(cairo->front_cs);
};
void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) {
cairo_destroy(cairo->back_cairo);
cairo_surface_destroy(cairo->back_cs);
};
void MwLLCairoDestroy(struct _MwLLCairo handle) {
// MwLLCairoFrontDestroy(&handle);
// MwLLCairoBackDestroy(&handle);
}
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
MwLL r;
r = malloc(sizeof(*r));
memset(r, 0, sizeof(*r));
MwLLCreateCommon(r);
r->cairo.width = width;
r->cairo.height = height;
r->cairo.x = x;
r->cairo.y = x;
r->cairo.toplevel = !parent;
r->cairo.parent = parent;
MwLLCairoFrontSetup(&r->cairo, NULL, r->cairo.width, r->cairo.height);
MwLLCairoBackSetup(&r->cairo, NULL, r->cairo.width, r->cairo.height);
return r;
}
static void MwLLDestroyImpl(MwLL handle) {
MwLLCairoDestroy(handle->cairo);
free(handle);
}
static void MwLLBeginDrawImpl(MwLL handle) {
handle->cairo.selected_cairo = handle->cairo.front_cairo;
}
static void MwLLEndDrawImpl(MwLL handle) {
}
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
MwLLCairoPolygon(handle->cairo, points, points_count, color);
}
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
MwLLCairoLine(handle->cairo, points, color);
}
static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) {
MwLLColor c = malloc(sizeof(*c));
MwLLColorUpdate(handle, c, r, g, b);
return c;
}
static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) {
(void)handle;
c->common.red = r;
c->common.green = g;
c->common.blue = b;
}
static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
(void)handle;
*x = handle->cairo.x;
*y = handle->cairo.y;
*w = handle->cairo.width;
*h = handle->cairo.height;
}
static void MwLLSetXYImpl(MwLL handle, int x, int y) {
handle->cairo.x = x;
handle->cairo.y = y;
}
static void MwLLSetWHImpl(MwLL handle, int w, int h) {
handle->cairo.width = w;
handle->cairo.height = h;
}
static void MwLLFreeColorImpl(MwLLColor color) {}
static MwBool lmao = MwFALSE;
static int MwLLPendingImpl(MwLL handle) {
lmao = !lmao;
return lmao;
}
static void MwLLNextEventImpl(MwLL handle) {
MwLLDispatch(handle, draw, NULL);
}
static void MwLLSetTitleImpl(MwLL handle, const char* title) {}
static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) {
return MwLLCairoCreatePixmap(handle->cairo, data, width, height);
}
static void MwLLPixmapUpdateImpl(MwLLPixmap r) {
MwLLCairoPixmapUpdate(r);
}
static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) {
MwLLCairoPixmapUpdate(pixmap);
}
static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
MwLLCairoDrawPixmap(handle->cairo, rect, pixmap);
}
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {}
static void MwLLForceRenderImpl(MwLL handle) {}
static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {}
static void MwLLDetachImpl(MwLL handle, MwPoint* point) {}
static void MwLLShowImpl(MwLL handle, int show) {}
static void MwLLMakePopupImpl(MwLL handle, MwLL parent) {}
static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) {}
static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) {}
static void MwLLFocusImpl(MwLL handle) {}
static void MwLLGrabPointerImpl(MwLL handle, int toggle) {}
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {}
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {}
static void MwLLMakeToolWindowImpl(MwLL handle) {}
static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {}
static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {}
static void MwLLBeginStateChangeImpl(MwLL handle) {}
static void MwLLEndStateChangeImpl(MwLL handle) {}
static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) {}
static MwBool MwLLDoModernImpl(MwLL handle) {
return MwFALSE;
}
static void MwLLRaiseImpl(MwLL handle) {}
static void MwLLClipImpl(MwLL handle, MwRect* rect) {}
static int MwLLCairoCallInitImpl(void) {
if(cairo_load_funcs() != 0) {
return 1;
}
return 0;
}
#include "call.c"
CALL(Cairo);

View file

@ -4,8 +4,7 @@
void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) {
MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh);
wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf_back, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww);
wayland->front_cairo = cairo_create(wayland->front_cs);
MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh);
memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size);
if(wayland->configured)
@ -17,8 +16,7 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) {
};
void MwLLWaylandFramebufferDestroy(struct _MwLLWayland* wayland) {
MwLLWaylandBufferDestroy(&wayland->framebuffer);
cairo_destroy(wayland->front_cairo);
cairo_surface_destroy(wayland->front_cs);
MwLLCairoFrontDestroy(&wayland->cairo);
};
void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) {
@ -33,8 +31,7 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) {
}
MwLLWaylandBufferSetup(&wayland->backbuffer, w, h);
wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf_back, CAIRO_FORMAT_ARGB32, w, h, 4 * w);
wayland->back_cairo = cairo_create(wayland->back_cs);
MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, wayland->ww, wayland->wh);
memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size);
if(wayland->configured)
@ -45,8 +42,7 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) {
};
void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* wayland) {
MwLLWaylandBufferDestroy(&wayland->backbuffer);
cairo_destroy(wayland->back_cairo);
cairo_surface_destroy(wayland->back_cs);
MwLLCairoBackDestroy(&wayland->cairo);
};
void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {

View file

@ -10,6 +10,8 @@ wayland_call_table_t wl_call_tbl;
MwBool MwWaylandVulkan = MwFALSE;
#endif
MwBool MwWaylandCairoOnly = MwFALSE;
static pthread_mutex_t destroyedWidgetsTableMutex;
/*
* So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table.
@ -705,6 +707,7 @@ static void clip(MwLL handle) {
toplevel = toplevel->wayland.parent;
}
if(toplevel) {
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
/* i seriously have no fucking idea how this works, do not ask me how this really works (nishi) */
@ -752,15 +755,15 @@ static void clip(MwLL handle) {
handle->wayland.clipping_rect.height = my - cy;
MwLLWaylandRegionSetup(handle);
cairo_reset_clip(handle->wayland.front_cairo);
cairo_reset_clip(handle->wayland.cairo.front_cairo);
if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL && !handle->wayland.is_toplevel) {
cairo_rectangle(handle->wayland.front_cairo, cx - x, cy - y, mx - cx, my - cy);
cairo_clip(handle->wayland.front_cairo);
cairo_rectangle(handle->wayland.cairo.front_cairo, cx - x, cy - y, mx - cx, my - cy);
cairo_clip(handle->wayland.cairo.front_cairo);
}
if(handle->wayland.is_clipping) {
cairo_rectangle(handle->wayland.front_cairo, handle->wayland.clip.x, handle->wayland.clip.y, handle->wayland.clip.width, handle->wayland.clip.height);
cairo_clip(handle->wayland.front_cairo);
cairo_rectangle(handle->wayland.cairo.front_cairo, handle->wayland.clip.x, handle->wayland.clip.y, handle->wayland.clip.width, handle->wayland.clip.height);
cairo_clip(handle->wayland.cairo.front_cairo);
}
}
}
@ -1088,15 +1091,15 @@ const float_color two = {.05490196, .17254902, .30588235};
static void MwLLBeginDrawImpl(MwLL handle) {
WIDGET_CHECK(handle);
cairo_save(handle->wayland.front_cairo);
cairo_set_source_rgba(handle->wayland.front_cairo, 0, 0, 0, 0);
cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_SOURCE);
cairo_rectangle(handle->wayland.front_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh);
cairo_fill(handle->wayland.front_cairo);
cairo_restore(handle->wayland.front_cairo);
cairo_save(handle->wayland.cairo.front_cairo);
cairo_set_source_rgba(handle->wayland.cairo.front_cairo, 0, 0, 0, 0);
cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_SOURCE);
cairo_rectangle(handle->wayland.cairo.front_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh);
cairo_fill(handle->wayland.cairo.front_cairo);
cairo_restore(handle->wayland.cairo.front_cairo);
if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) {
handle->wayland.selected_cairo = handle->wayland.front_cairo;
handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo;
return;
}
@ -1105,25 +1108,25 @@ static void MwLLBeginDrawImpl(MwLL handle) {
MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT;
MwU32 h = handle->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM;
MwRect r;
handle->wayland.selected_cairo = handle->wayland.back_cairo;
handle->wayland.cairo.selected_cairo = handle->wayland.cairo.back_cairo;
#define DO_BOX(x, y, col, w, h) \
cairo_rectangle(handle->wayland.back_cairo, x, y, w, h); \
cairo_set_source_rgb(handle->wayland.back_cairo, col, col, col); \
cairo_fill(handle->wayland.back_cairo);
cairo_rectangle(handle->wayland.cairo.back_cairo, x, y, w, h); \
cairo_set_source_rgb(handle->wayland.cairo.back_cairo, col, col, col); \
cairo_fill(handle->wayland.cairo.back_cairo);
#define DO_LINE(off, col) \
cairo_move_to(handle->wayland.back_cairo, off, off); \
cairo_line_to(handle->wayland.back_cairo, off, h - (off)); \
cairo_set_source_rgb(handle->wayland.back_cairo, col, col, col); \
cairo_stroke(handle->wayland.back_cairo); \
cairo_move_to(handle->wayland.back_cairo, off, off); \
cairo_line_to(handle->wayland.back_cairo, w - (off), off); \
cairo_set_source_rgb(handle->wayland.back_cairo, col, col, col); \
cairo_stroke(handle->wayland.back_cairo);
cairo_move_to(handle->wayland.cairo.back_cairo, off, off); \
cairo_line_to(handle->wayland.cairo.back_cairo, off, h - (off)); \
cairo_set_source_rgb(handle->wayland.cairo.back_cairo, col, col, col); \
cairo_stroke(handle->wayland.cairo.back_cairo); \
cairo_move_to(handle->wayland.cairo.back_cairo, off, off); \
cairo_line_to(handle->wayland.cairo.back_cairo, w - (off), off); \
cairo_set_source_rgb(handle->wayland.cairo.back_cairo, col, col, col); \
cairo_stroke(handle->wayland.cairo.back_cairo);
/* border */
cairo_set_antialias(handle->wayland.back_cairo, CAIRO_ANTIALIAS_NONE);
cairo_set_antialias(handle->wayland.cairo.back_cairo, CAIRO_ANTIALIAS_NONE);
DO_BOX(0, 0, 0.14901961, w, h);
DO_BOX(1, 1, 0.55686275, w - 2, h - 2);
@ -1131,7 +1134,7 @@ static void MwLLBeginDrawImpl(MwLL handle) {
DO_BOX(3, 3, 0.93333333, w - 6, h - 6);
DO_BOX(4, 4, 1, w - 8, h - 8);
DO_BOX(4, 4, 0.14901961, w - CSD_BORDER_FRAME_LEFT - 4, h - CSD_BORDER_FRAME_BOTTOM - 4);
cairo_set_line_width(handle->wayland.back_cairo, 1.0);
cairo_set_line_width(handle->wayland.cairo.back_cairo, 1.0);
DO_LINE(1, 1)
DO_LINE(2, 0.93333333)
@ -1139,15 +1142,15 @@ static void MwLLBeginDrawImpl(MwLL handle) {
DO_LINE(4, 0.55686275)
DO_LINE(5, 0.14901961)
cairo_set_line_width(handle->wayland.back_cairo, 2.0);
cairo_set_line_width(handle->wayland.cairo.back_cairo, 2.0);
for(y = 1; y < CSD_BORDER_FRAME_TOP - CSD_BORDER_FRAME_LEFT; y++) {
float_color c = lerp_color(one, two, (double)y / (double)(CSD_BORDER_FRAME_TOP - CSD_BORDER_FRAME_LEFT));
cairo_set_source_rgb(handle->wayland.back_cairo, c.r, c.g, c.b);
cairo_set_source_rgb(handle->wayland.cairo.back_cairo, c.r, c.g, c.b);
cairo_move_to(handle->wayland.back_cairo, CSD_BORDER_FRAME_LEFT, y + CSD_BORDER_FRAME_LEFT);
cairo_line_to(handle->wayland.back_cairo, w - CSD_BORDER_FRAME_RIGHT, y + CSD_BORDER_FRAME_LEFT);
cairo_stroke(handle->wayland.back_cairo);
cairo_move_to(handle->wayland.cairo.back_cairo, CSD_BORDER_FRAME_LEFT, y + CSD_BORDER_FRAME_LEFT);
cairo_line_to(handle->wayland.cairo.back_cairo, w - CSD_BORDER_FRAME_RIGHT, y + CSD_BORDER_FRAME_LEFT);
cairo_stroke(handle->wayland.cairo.back_cairo);
}
/* icon */
@ -1158,7 +1161,7 @@ static void MwLLBeginDrawImpl(MwLL handle) {
DO_BOX(5, 5, 1, 18, 18);
DO_BOX(6, 6, 0.35294118, 17, 17);
DO_BOX(6, 6, 0.82352941, 16, 16);
handle->wayland.selected_cairo = handle->wayland.back_cairo;
handle->wayland.cairo.selected_cairo = handle->wayland.cairo.back_cairo;
if(handle->wayland.icon_pixmap) {
MwLLDrawPixmap(handle, &r, handle->wayland.icon_pixmap);
}
@ -1226,7 +1229,7 @@ static void MwLLBeginDrawImpl(MwLL handle) {
}
MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer);
}
handle->wayland.selected_cairo = handle->wayland.front_cairo;
handle->wayland.cairo.selected_cairo = handle->wayland.cairo.front_cairo;
}
static void MwLLEndDrawImpl(MwLL handle) {
@ -1239,25 +1242,11 @@ static void MwLLEndDrawImpl(MwLL handle) {
}
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
int i;
WIDGET_CHECK(handle);
clip(handle);
cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle->wayland.front_cairo);
for(i = 0; i < points_count; i++) {
if(i == 0) {
cairo_move_to(handle->wayland.front_cairo, points[i].x, points[i].y);
} else {
cairo_line_to(handle->wayland.front_cairo, points[i].x, points[i].y);
}
}
cairo_close_path(handle->wayland.front_cairo);
cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_SOURCE);
cairo_fill(handle->wayland.front_cairo);
cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_OVER);
MwLLCairoPolygon(handle->wayland.cairo, points, points_count, color);
handle->wayland.events_pending = 1;
}
@ -1268,19 +1257,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
clip(handle);
cairo_set_antialias(handle->wayland.front_cairo, CAIRO_ANTIALIAS_NONE);
cairo_set_line_cap(handle->wayland.front_cairo, CAIRO_LINE_CAP_SQUARE);
cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle->wayland.front_cairo);
for(i = 0; i < 2; i++) {
if(i == 0) {
cairo_move_to(handle->wayland.front_cairo, points[i].x, points[i].y);
} else {
cairo_line_to(handle->wayland.front_cairo, points[i].x, points[i].y);
}
}
cairo_close_path(handle->wayland.front_cairo);
cairo_stroke(handle->wayland.front_cairo);
MwLLCairoLine(handle->wayland.cairo, points, color);
handle->wayland.events_pending = 1;
}
@ -1421,80 +1398,23 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) {
}
static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) {
MwLLPixmap r = malloc(sizeof(*r));
(void)handle;
if(width >= INT16_MAX) width = INT16_MAX;
if(height >= INT16_MAX) height = INT16_MAX;
r->common.width = width;
r->common.height = height;
r->common.raw = malloc(4 * width * height);
memcpy(r->common.raw, data, 4 * width * height);
r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
MwLLPixmapUpdate(r);
return r;
return MwLLCairoCreatePixmap(handle->wayland.cairo, data, width, height);
}
static void MwLLPixmapUpdateImpl(MwLLPixmap r) {
int i;
unsigned char* d;
cairo_surface_flush(r->wayland.cs);
d = cairo_image_surface_get_data(r->wayland.cs);
for(i = 0; i < r->common.width * r->common.height * 4; i += 4) {
MwU32* p = (MwU32*)&d[i];
*p <<= 8;
*p |= r->common.raw[i + 3];
*p <<= 8;
*p |= r->common.raw[i + 0];
*p <<= 8;
*p |= r->common.raw[i + 1];
*p <<= 8;
*p |= r->common.raw[i + 2];
}
cairo_surface_mark_dirty(r->wayland.cs);
MwLLCairoPixmapUpdate(r);
}
static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) {
cairo_surface_destroy(pixmap->wayland.cs);
free(pixmap->common.raw);
free(pixmap);
MwLLCairoDestroyPixmap(pixmap);
}
static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
cairo_t* c;
cairo_surface_t* cs;
cairo_t* selected_cairo = handle->wayland.selected_cairo ? handle->wayland.selected_cairo : handle->wayland.front_cairo;
if(rect->width <= 0 || rect->height <= 0 || pixmap->common.width <= 0 || pixmap->common.height <= 0) return;
if(rect->width >= INT16_MAX) rect->width = INT16_MAX;
if(rect->height >= INT16_MAX) rect->height = INT16_MAX;
WIDGET_CHECK(handle);
cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height);
c = cairo_create(cs);
clip(handle);
cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height);
cairo_set_source_surface(c, pixmap->wayland.cs, 0, 0);
cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST);
cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_OVER);
cairo_paint(c);
cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y);
cairo_paint(selected_cairo);
cairo_destroy(c);
cairo_surface_destroy(cs);
MwLLCairoDrawPixmap(handle->wayland.cairo, rect, pixmap);
MwLLForceRender(handle);
wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);

View file

@ -1040,7 +1040,7 @@ typedef int (*call_t)(void);
int MwLibraryInit(void) {
call_t calls[] = {
#ifdef USE_WAYLAND
MwLLWaylandCallInit,
NULL, /* set in a bit */
#endif
#ifdef USE_X11
MwLLX11CallInit,
@ -1060,6 +1060,12 @@ int MwLibraryInit(void) {
NULL};
int i;
if(MwWaylandCairoOnly) {
calls[0] = MwLLCairoCallInit;
} else {
calls[0] = MwLLWaylandCallInit;
}
MwColorTableInit();
MwFLSetup();