From 320de34ce8d280cd01e1327ce3e3e2a6f6d8ea81 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 17 Dec 2025 19:14:54 -0700 Subject: [PATCH] remove opengl from wayland in favor of cairo --- Makefile.pl | 6 +- include/Mw/LowLevel/Wayland.h | 57 ++-- pl/ostype/Linux.pl | 7 +- pl/rules.pl | 12 +- src/backend/wayland.c | 540 ++++++++++++---------------------- src/widget/frame.c | 1 - src/widget/listbox.c | 1 - src/widget/opengl.c | 22 +- 8 files changed, 242 insertions(+), 404 deletions(-) diff --git a/Makefile.pl b/Makefile.pl index c00ca62..ea9f90c 100755 --- a/Makefile.pl +++ b/Makefile.pl @@ -56,14 +56,16 @@ my %features = ( "vulkan" => "build Vulkan widget", "vulkan-string-helper" => "use Vulkan string helper", "shared" => "build shared library", - "static" => "build static library" + "static" => "build static library", + "experimental-wayland" => "enable WIP wayland backend", ); my @features_keys = ( "1classic-theme", "1stb-image", "1stb-truetype", "1freetype2", "1opengl", "2xrender", "1vulkan", "2vulkan-string-helper", - "1shared", "1static" + "1shared", "1static", + "1experimental-wayland" ); foreach my $l (@ARGV) { diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index af80f47..32f6547 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -12,13 +12,10 @@ #include #include -#include -#include -#include -#include #include #include +#include MWDECL int MwLLWaylandCallInit(void); @@ -53,15 +50,27 @@ struct _MwLLWaylandTopLevel { MwBool xdg_surface_created; }; +struct _MwLLWaylandSublevel { + struct wl_subsurface* subsurface; + struct wl_subcompositor* subcompositor; + + MwLL parent; + MwLL topmost_parent; /* The parent at the top of all the other parents. Usually a toplevel. */ +}; + struct _MwLLWayland { struct _MwLLCommon common; - /* Pointer for data that's only loaded if the widget is a toplevel */ - struct _MwLLWaylandTopLevel* toplevel; + union { + /* Pointer for data that's only loaded if the widget is a toplevel */ + struct _MwLLWaylandTopLevel* toplevel; + /* Pointer for data that's only loaded if the widget is a sublevel */ + struct _MwLLWaylandSublevel* sublevel; + }; enum { MWLL_WAYLAND_TOPLEVEL = 0, - MWLL_WAYLAND_SUBLEVEL = 1, /* Sublevels are surfaces that have the toplevel as a parent. They could be implemented as subsurfaces if we ever switch away from OpenGL. Some parts of the code also call them subwidgets. */ + MWLL_WAYLAND_SUBLEVEL, /* Sublevels are surfaces that have the toplevel as a parent. Some parts of the code also call them subwidgets. */ } type; /* Map of Wayland interfaces to their relevant setup functions. */ @@ -79,33 +88,25 @@ struct _MwLLWayland { struct wl_display* display; struct wl_registry* registry; struct wl_compositor* compositor; - struct wl_subcompositor* subcompositor; struct wl_surface* surface; struct wl_registry_listener registry_listener; - struct wl_event_queue* event_queue; - - EGLNativeWindowType egl_window_native; - EGLDisplay egl_display; - EGLContext egl_context; - EGLSurface egl_surface; - EGLConfig egl_config; + /*struct wl_event_queue* event_queue;*/ MwLL* sublevels; /* stb_ds managed array of any sublevels */ MwBool configured; /* Whether or not xdg_toplevel_configure has run once */ - MwBool egl_setup; /* Whether or not EGL has been set up */ - MwBool has_set_xy /* Whether or not MwSetXY has been called */; - int resize_counter; /* Counter that's for a hack in event_loop */ - MwU32 x, y, ww, wh; /* Window position */ - MwU32 lw, lh; /* Last known window position */ - MwPoint cur_mouse_pos; /* Currently known mouse position */ + MwU32 x, y, ww, wh; /* Window position */ + MwPoint cur_mouse_pos; /* Currently known mouse position */ - struct timeval timer; - MwU64 cooldown_timer; - MwU64 cooldown_timer_epoch; + struct wl_shm* shm; + struct wl_shm_pool* shm_pool; + struct wl_buffer* shm_buffer; + void* mapped_shm_buf; + MwU64 mapped_shm_buf_size; + int shm_fd; - MwLL parent; - MwLL topmost_parent; /* The parent at the top of all the other parents. Usually a toplevel. */ + cairo_surface_t* cs; + cairo_t* cairo; }; struct _MwLLWaylandColor { @@ -114,8 +115,8 @@ struct _MwLLWaylandColor { struct _MwLLWaylandPixmap { struct _MwLLCommonPixmap common; - GLuint texture; - MwBool texture_deleted; + + cairo_surface_t* cs; }; #endif diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index f695e4f..155cd4a 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -1,3 +1,8 @@ -use_backend("x11"); +if (param_get("experimental-wayland")) { + use_backend("wayland", "x11"); +} +else { + use_backend("x11"); +} 1; diff --git a/pl/rules.pl b/pl/rules.pl index f8aec46..5cb4a90 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -29,21 +29,15 @@ if (grep(/^gdi$/, @backends)) { if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); new_object("src/backend/wayland.c"); - if ($cross) { - add_libs("-lGL -lEGL -lwayland-egl -lwayland-client -lxkbcommon"); - } - else { - add_libs("-lGL -lEGL"); - add_cflags(`pkg-config --cflags wayland-egl wayland-client xkbcommon`); - add_libs(`pkg-config --libs wayland-egl wayland-client xkbcommon`); - } + add_cflags(`pkg-config --cflags cairo wayland-client xkbcommon`); + add_libs(`pkg-config --libs cairo wayland-client xkbcommon`); scan_wayland_protocol("stable", "xdg-shell", ""); scan_wayland_protocol("stable", "tablet", "-v2"); scan_wayland_protocol("staging", "cursor-shape", "-v1"); scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1"); - $gl_libs = "-lGL -lGLU"; + $gl_libs = "-lEGL -lwayland-egl lGL -lGLU"; } if (param_get("stb-image")) { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 307e1ee..83e7439 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -6,7 +6,6 @@ #include "../../external/stb_ds.h" #include -#include #include /* TODO: find out what FreeBSD and such wants us to include */ @@ -18,19 +17,6 @@ #include #endif -/* - * TODO: - * make sure MwLLDestroy is finished (+ handle dropdown bug that results from it) - * GNOME doesn't want to support zxdg_decoration_protocol so we're gonna design some Windows 95 ass ui just for that window manager. - * finish the rest of the owl - */ - -/* - * Redraw `handle` if the given cooldown hasn't expired (`time` >= `cooldown_timer` + `cooldown)). - * Used for pointer callbacks, resize callbacks, etc. to ensure we only resize every x milliseconds - */ -static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer); - /* Get the registered interface from r, or NULL if it doesn't currently have it. */ #define WAYLAND_GET_INTERFACE(handle, inter) shget(handle.wl_protocol_map, inter##_interface.name) @@ -59,13 +45,11 @@ static void protocol_removed(void* data, /* `wl_pointer.enter` callback */ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface, wl_fixed_t surface_x, - wl_fixed_t surface_y) { -}; + wl_fixed_t surface_y) {}; /* `wl_pointer.leave` callback */ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, - struct wl_surface* surface) { -}; + struct wl_surface* surface) {}; /* `wl_pointer.motion` callback */ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, @@ -78,7 +62,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); - timed_redraw(self, time, 50, &self->wayland.cooldown_timer); + /*timed_redraw(self, time, 50, &self->wayland.cooldown_timer);*/ }; /* `wl_pointer.button` callback */ @@ -107,6 +91,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri break; } } + MwLLDispatch(self, draw, NULL); }; @@ -144,17 +129,6 @@ static void recursive_key_released(MwLL handle, void* ud) { } } -/* Recursively dispatch the draw event to `handle` and its children */ -static void recursive_draw(MwLL handle) { - int i; - if(handle->wayland.sublevels != NULL) { - for(i = 0; i < arrlen(handle->wayland.sublevels); i++) { - MwLLDispatch(handle->wayland.sublevels[i], draw, NULL); - recursive_draw(handle->wayland.sublevels[i]); - } - } -} - /* `wl_keyboard.keymap` callback */ static void keyboard_keymap(void* data, struct wl_keyboard* wl_keyboard, @@ -350,7 +324,7 @@ static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* /* wl_subcompositor setup function */ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); return NULL; } @@ -398,129 +372,6 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ return proto; } -/* EGL Setup function */ -static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { - int err; - EGLint numConfigs; - EGLint majorVersion; - EGLint minorVersion; - EGLContext context; - EGLSurface surface; - EGLint fbAttribs[] = - { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_NONE}; - EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 1, - EGL_CONTEXT_MAJOR_VERSION, 1, - EGL_CONTEXT_MINOR_VERSION, 1, - EGL_NONE}; - - EGLDisplay display; - display = eglGetDisplay(self->wayland.display); - if(display == EGL_NO_DISPLAY) { - printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); - return MwFALSE; - } - /* Initialize EGL */ - if(!eglInitialize(display, &majorVersion, &minorVersion)) { - printf("ERROR: eglInitialize, %0X\n", eglGetError()); - return MwFALSE; - } - - /* Get configs */ - if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { - printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); - return MwFALSE; - } - - /* Choose config */ - if((eglChooseConfig(display, fbAttribs, &self->wayland.egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { - printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); - return MwFALSE; - } - - self->wayland.egl_window_native = - wl_egl_window_create(self->wayland.surface, width, height); - if(self->wayland.egl_window_native == EGL_NO_SURFACE) { - printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); - return MwFALSE; - } - - /* Create a surface */ - surface = eglCreateWindowSurface(display, self->wayland.egl_config, self->wayland.egl_window_native, NULL); - if(surface == EGL_NO_SURFACE) { - printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); - return MwFALSE; - } - - eglBindAPI(EGL_OPENGL_API); - - /* Create a GL context */ - context = eglCreateContext(display, self->wayland.egl_config, EGL_NO_CONTEXT, contextAttribs); - if(context == EGL_NO_CONTEXT) { - printf("ERROR: eglCreateContext, %0X\n", eglGetError()); - return MwFALSE; - } - - self->wayland.egl_display = display; - self->wayland.egl_surface = surface; - self->wayland.egl_context = context; - - if(self->wayland.parent == NULL) { - if(!eglMakeCurrent(self->wayland.egl_display, self->wayland.egl_surface, self->wayland.egl_surface, self->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - } - } - - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_SCISSOR_TEST); - - return MwTRUE; -} - -/* EGL reconfiguration function for resizes */ -static void egl_resetup(MwLL handle) { - float w, h; - - if(handle->wayland.parent == NULL) { - w = handle->wayland.ww; - h = handle->wayland.wh; - } else { - w = handle->wayland.parent->wayland.ww; - h = handle->wayland.parent->wayland.wh; - } - - glViewport(handle->wayland.x, handle->wayland.y, w, h); - glScissor(handle->wayland.x, handle->wayland.y, w, h); -} - -static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer) { - if(handle->wayland.parent == NULL) { - if(time >= (*cooldown_timer + cooldown)) { - egl_resetup(handle); - MwLLDispatch(handle, draw, NULL); - *cooldown_timer = time; - } - } -} - -/* Same as timed_redraw but it uses the unix epoch as the cooldown timer. */ -static void timed_redraw_by_epoch(MwLL handle, int cooldown) { - gettimeofday(&handle->wayland.timer, NULL); - unsigned long long time = - (unsigned long long)(handle->wayland.timer.tv_sec) * 1000 + - (unsigned long long)(handle->wayland.timer.tv_usec) / 1000; - timed_redraw(handle, time, cooldown, &handle->wayland.cooldown_timer_epoch); -} - /* `xdg_toplevel.close` callback */ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, @@ -541,14 +392,20 @@ static void xdg_toplevel_configure(void* data, self->wayland.wh = height; xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); - MwLLDispatch(self, resize, NULL); + cairo_destroy(self->wayland.cairo); + cairo_surface_destroy(self->wayland.cs); + self->wayland.cs = cairo_image_surface_create_for_data(self->wayland.mapped_shm_buf, CAIRO_FORMAT_ARGB32, width, height, 4 * width); + self->wayland.cairo = cairo_create(self->wayland.cs); - if(!self->wayland.egl_setup) { + MwLLDispatch(self, resize, NULL); + MwLLDispatch(self, draw, NULL); + + /*if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, self->wayland.x, self->wayland.y, width, height); } else { wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); egl_resetup(self); - } + }*/ return; }; @@ -580,6 +437,58 @@ static void xdg_surface_configure( self->wayland.configured = MwTRUE; } +/* wl_shm setup function */ +static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { + int x, y; + int stride = wayland->ww * 4; + char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; + + wayland->mapped_shm_buf_size = wayland->ww * wayland->wh * 4; + + wayland->shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); + + wayland->shm_fd = mkstemp(temp_name); + + unlink(temp_name); + + if(posix_fallocate(wayland->shm_fd, 0, wayland->mapped_shm_buf_size) != 0) { + printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno)); + close(wayland->shm_fd); + return NULL; + } + if(ftruncate(wayland->shm_fd, wayland->mapped_shm_buf_size) != 0) { + printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); + close(wayland->shm_fd); + return NULL; + } + + wayland->mapped_shm_buf = mmap(NULL, wayland->mapped_shm_buf_size, PROT_WRITE, MAP_SHARED, wayland->shm_fd, 0); + + fsync(wayland->shm_fd); + + if(!(wayland->shm_pool = wl_shm_create_pool(wayland->shm, wayland->shm_fd, wayland->mapped_shm_buf_size))) { + printf("failure setting up wl_shm: could not create pool.\n"); + } + + wayland->shm_buffer = wl_shm_pool_create_buffer(wayland->shm_pool, 0, wayland->ww, wayland->wh, stride, WL_SHM_FORMAT_ARGB8888); + + if(wayland->configured) { + wl_surface_attach(wayland->surface, wayland->shm_buffer, 0, 0); + wl_surface_commit(wayland->surface); + } + + return NULL; +} + +static void update_buffer(MwLL handle) { + fsync(handle->wayland.shm_fd); + + if(handle->wayland.configured) { + wl_surface_attach(handle->wayland.surface, handle->wayland.shm_buffer, 0, 0); + wl_surface_commit(handle->wayland.surface); + } +} + /* Standard Wayland event loop. */ static int event_loop(MwLL handle) { enum { @@ -588,9 +497,8 @@ static int event_loop(MwLL handle) { CURSOR_FD }; struct pollfd fd; - int timeout = 100; - struct _MwLLWayland* wayland = &handle->wayland; - MwLL topmost_parent = handle->wayland.parent; + int timeout = 1; + struct _MwLLWayland* wayland = &handle->wayland; if(wayland->display == NULL) { return 0; @@ -598,6 +506,12 @@ static int event_loop(MwLL handle) { fd.fd = wl_display_get_fd(wayland->display); fd.events = POLLIN; + while(wl_display_prepare_read(handle->wayland.display) != 0) { + if(wl_display_dispatch_pending(handle->wayland.display) > 0) { + return 0; + } + } + /* If an error other than EAGAIN happens, we have likely been disconnected from the Wayland session */ while(wl_display_flush(wayland->display) == -1) { if(errno != EAGAIN) { @@ -614,38 +528,27 @@ static int event_loop(MwLL handle) { } } + /* Condition where no events are being sent. */ + if(!poll(&fd, 1, timeout)) { + wl_display_cancel_read(handle->wayland.display); + /* In this case, we need to commit the surface for any animations, etc. */ + wl_surface_commit(handle->wayland.surface); + return 0; + } + if(fd.revents & POLLIN) { wl_display_read_events(wayland->display); if(wl_display_dispatch_pending(wayland->display) > 0) { } } else { - /* Condition for no events being sent */ - if(wl_display_dispatch_pending(wayland->display) == 0) { - if(wayland->event_queue != NULL) { - if(wl_display_roundtrip_queue(wayland->display, wayland->event_queue) < 0) { - printf("error\n"); - }; - } - /* HACK: If the last known size is different, force a redraw */ - if(wayland->lw != wayland->ww || wayland->lh != wayland->wh) { - MwLLDispatch(handle, draw, 0); - wayland->resize_counter++; - if(wayland->resize_counter >= 5) { - wayland->lw = wayland->ww; - wayland->lh = wayland->wh; - wayland->lh = wayland->wh; - wayland->resize_counter = 0; - } - } - } + wl_display_cancel_read(handle->wayland.display); } - return 0; + return 1; } /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ static void setup_callbacks(struct _MwLLWayland* wayland) { - /* Convience macro for adding the interface functions to the setup map */ #define WL_INTERFACE(interface) \ shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); @@ -655,13 +558,15 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { wayland->wl_protocol_setup_map = NULL; wayland->wl_protocol_map = NULL; + WL_INTERFACE(wl_shm); WL_INTERFACE(wl_compositor); - WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_seat); if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(wp_cursor_shape_manager_v1); + } else { + WL_INTERFACE(wl_subcompositor); } #undef WL_INTERFACE } @@ -670,9 +575,8 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { static void setup_toplevel(MwLL r, int x, int y) { int i; - r->wayland.type = MWLL_WAYLAND_TOPLEVEL; - r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); - r->wayland.topmost_parent = NULL; + r->wayland.type = MWLL_WAYLAND_TOPLEVEL; + r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); setup_callbacks(&r->wayland); @@ -731,27 +635,17 @@ static void setup_toplevel(MwLL r, int x, int y) { printf("zxdg null\n"); } - r->wayland.event_queue = wl_display_create_queue(r->wayland.display); - - egl_resetup(r); + /*egl_resetup(r); MwLLDispatch(r, draw, NULL); - recursive_draw(r); + recursive_draw(r);*/ } /* Sublevel setup function */ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { - struct wl_compositor* compositor = parent->wayland.compositor; - struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; - struct wl_surface* parent_surface = parent->wayland.surface; - struct wl_region* region; - { - MwLL topmost_parent = parent; + struct wl_compositor* compositor = parent->wayland.compositor; + struct wl_surface* parent_surface = parent->wayland.surface; - while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { - topmost_parent = topmost_parent->wayland.parent; - } - r->wayland.topmost_parent = topmost_parent; - } + r->wayland.sublevel = malloc(sizeof(struct _MwLLWaylandSublevel)); r->wayland.type = MWLL_WAYLAND_SUBLEVEL; @@ -759,17 +653,12 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.surface = wl_compositor_create_surface(compositor); - region = wl_compositor_create_region(compositor); - wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh); - wl_surface_set_opaque_region(r->wayland.surface, region); - wl_surface_commit(r->wayland.surface); - event_loop(r); - wl_region_destroy(region); - setup_callbacks(&r->wayland); - r->wayland.registry = wl_display_get_registry(r->wayland.topmost_parent->wayland.display); - r->wayland.display = r->wayland.topmost_parent->wayland.display; + // printf("position %d %d\n", x, y); + + r->wayland.registry = wl_display_get_registry(parent->wayland.display); + r->wayland.display = parent->wayland.display; wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); if(wl_display_roundtrip(r->wayland.display) == -1) { @@ -778,23 +667,11 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { return; } + r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.surface, parent_surface); + + wl_subsurface_set_position(r->wayland.sublevel->subsurface, x, y); + r->wayland.configured = MwTRUE; - if(!r->wayland.egl_setup) { - r->wayland.egl_setup = egl_setup(r, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); - egl_resetup(r); - MwLLDispatch(r, draw, NULL); - recursive_draw(r); - }; - - r->wayland.event_queue = parent->wayland.event_queue; - - arrpush(parent->wayland.sublevels, r); - - wl_surface_damage(parent->wayland.surface, 0, 0, parent->wayland.ww, parent->wayland.wh); - - egl_resetup(r->wayland.topmost_parent); - MwLLDispatch(r->wayland.topmost_parent, draw, NULL); - recursive_draw(r->wayland.topmost_parent); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -804,8 +681,8 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.type = MwLLBackendWayland; - if(width == 0) width = 1; - if(height == 0) height = 1; + if(width < 2) width = 2; + if(height < 2) height = 2; if(x == MwDEFAULT) { x = 0; @@ -819,12 +696,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.x = x; r->wayland.y = y; - r->wayland.parent = parent; - - r->wayland.cooldown_timer = 0; - r->wayland.has_set_xy = MwFALSE; - r->wayland.resize_counter = 0; - r->wayland.sublevels = NULL; if(parent == NULL) { @@ -833,12 +704,29 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { setup_sublevel(parent, r, x, y); } + /* example of writing to the buffer */ + memset(r->wayland.mapped_shm_buf, 255, r->wayland.mapped_shm_buf_size); + update_buffer(r); + + r->wayland.cs = cairo_image_surface_create_for_data(r->wayland.mapped_shm_buf, CAIRO_FORMAT_ARGB32, width, height, 4 * width); + r->wayland.cairo = cairo_create(r->wayland.cs); + + MwLLForceRender(r); + return r; } static void MwLLDestroyImpl(MwLL handle) { MwLLDestroyCommon(handle); + cairo_destroy(handle->wayland.cairo); + cairo_surface_destroy(handle->wayland.cs); + + munmap(handle->wayland.mapped_shm_buf, handle->wayland.mapped_shm_buf_size); + wl_buffer_destroy(handle->wayland.mapped_shm_buf); + wl_shm_pool_destroy(handle->wayland.shm_pool); + close(handle->wayland.shm_fd); + free(handle); } @@ -853,111 +741,74 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { handle->wayland.x = x; handle->wayland.y = y; - if(handle->wayland.has_set_xy) { + /*if(handle->wayland.has_set_xy) { timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); - /* recursive_draw(handle->wayland.topmost_parent); */ } else if(x != 0 && y != 0) { handle->wayland.has_set_xy = MwTRUE; - } + }*/ + + wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); } + MwLLDispatch(handle, draw, NULL); } static void MwLLSetWHImpl(MwLL handle, int w, int h) { /* Prevent an integer underflow when the w/h is too low */ if((w < 10 || h < 10)) { - handle->wayland.ww = handle->wayland.lw = 10; - handle->wayland.wh = handle->wayland.lh = 10; + handle->wayland.ww = 10; + handle->wayland.wh = 10; return; } - handle->wayland.ww = handle->wayland.lw = w; - handle->wayland.wh = handle->wayland.lh = h; + handle->wayland.ww = w; + handle->wayland.wh = h; if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { - timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); - /* recursive_draw(handle->wayland.topmost_parent); */ + /* timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + recursive_draw(handle->wayland.topmost_parent); */ } + MwLLDispatch(handle, draw, NULL); } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - int i, n; - float maxX = 0, maxY = 0; - float centerX, centerY; - float w, h; - - if(handle->wayland.parent == NULL) { - w = handle->wayland.ww; - h = handle->wayland.wh; - } else { - w = handle->wayland.topmost_parent->wayland.ww; - h = handle->wayland.topmost_parent->wayland.wh; - } - - glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - - glBegin(GL_POLYGON); + int i; + cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + cairo_new_path(handle->wayland.cairo); for(i = 0; i < points_count; i++) { - float x = ((float)(handle->wayland.x + points[i].x) / (w / 2)) - 1.0; - float y = 1.0 - ((float)(handle->wayland.y + points[i].y) / (h / 2)); - - glVertex2f(x, y); + if(i == 0) { + cairo_move_to(handle->wayland.cairo, points[i].x, points[i].y); + } else { + cairo_line_to(handle->wayland.cairo, points[i].x, points[i].y); + } } - glEnd(); - glColor3f(0, 0, 0); + cairo_close_path(handle->wayland.cairo); + cairo_fill(handle->wayland.cairo); } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - int i; - float w, h; + int i; - if(handle->wayland.topmost_parent == NULL) { - w = handle->wayland.ww; - h = handle->wayland.wh; - } else { - w = handle->wayland.topmost_parent->wayland.ww; - h = handle->wayland.topmost_parent->wayland.wh; - } - - glLineWidth(1); - glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - - glBegin(GL_LINES); + cairo_set_line_cap(handle->wayland.cairo, CAIRO_LINE_CAP_SQUARE); + cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + cairo_new_path(handle->wayland.cairo); for(i = 0; i < 2; i++) { - float x = ((float)(handle->wayland.x + points[i].x) / (w / 2)) - 1.0; - float y = 1.0 - ((float)(handle->wayland.y + points[i].y) / (h / 2)); - - glVertex2f(x, y); + if(i == 0) { + cairo_move_to(handle->wayland.cairo, points[i].x, points[i].y); + } else { + cairo_line_to(handle->wayland.cairo, points[i].x, points[i].y); + } } - glEnd(); - glColor3f(0, 0, 0); + cairo_close_path(handle->wayland.cairo); + cairo_stroke(handle->wayland.cairo); } static void MwLLBeginDrawImpl(MwLL handle) { - if(handle->wayland.parent == NULL) { - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } - } } static void MwLLEndDrawImpl(MwLL handle) { - int w, h; - - recursive_draw(handle); - - /* glClear(GL_COLOR_BUFFER_BIT); */ - /* glClearColor(1.0, 0, 0, 1); */ - - if(handle->wayland.parent == NULL) { - if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { - printf("error swapping buffers! %0X\n", eglGetError()); - } else { - wl_surface_commit(handle->wayland.surface); - } - } + update_buffer(handle); } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -981,8 +832,6 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - if(wl_display_dispatch_pending(handle->wayland.display) == 0) { - } return event_loop(handle); } @@ -998,19 +847,12 @@ 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)); - r->common.width = width; - r->common.height = height; - r->common.raw = data; - r->wayland.texture = 0; + r->common.width = width; + r->common.height = height; + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); - glGenTextures(1, &r->wayland.texture); - - glBindTexture(GL_TEXTURE_2D, r->wayland.texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_2D, 0); + r->wayland.cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); MwLLPixmapUpdate(r); @@ -1018,46 +860,48 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int wid } static void MwLLPixmapUpdateImpl(MwLLPixmap r) { - glBindTexture(GL_TEXTURE_2D, r->wayland.texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r->common.width, r->common.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, r->common.raw); - glBindTexture(GL_TEXTURE_2D, 0); + 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); } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - glDeleteTextures(1, &pixmap->wayland.texture); + cairo_surface_destroy(pixmap->wayland.cs); + free(pixmap->common.raw); free(pixmap); } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - float x, y, w, h; + cairo_t* c; + cairo_surface_t* cs; - if(handle->wayland.topmost_parent == NULL) { - w = handle->wayland.ww; - h = handle->wayland.wh; - } else { - w = handle->wayland.topmost_parent->wayland.ww; - h = handle->wayland.topmost_parent->wayland.wh; - } + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); + c = cairo_create(cs); - x = ((float)(handle->wayland.x + rect->x) / (w / 2)) - 1.0; - y = 1.0 - ((float)(handle->wayland.y + rect->y) / (h / 2)); + 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_paint(c); - glColor3f(1.0, 1.0, 1.0); + cairo_set_source_rgb(handle->wayland.cairo, 1, 1, 1); + cairo_set_source_surface(handle->wayland.cairo, cs, rect->x, rect->y); + cairo_paint(handle->wayland.cairo); - glBindTexture(GL_TEXTURE_2D, pixmap->wayland.texture); - glActiveTexture(pixmap->wayland.texture); - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0); - glVertex2f(x, y); - glTexCoord2f(1, 0); - glVertex2f(x + (rect->width / (w / 2)), y); - glTexCoord2f(1, 1); - glVertex2f(x + (rect->width / (w / 2)), y - (rect->height / (h / 2))); - glTexCoord2f(0.0f, 1); - glVertex2f(x, y - (rect->height / (h / 2))); - glEnd(); - glFinish(); + cairo_destroy(c); + cairo_surface_destroy(cs); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } @@ -1065,9 +909,11 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + /* if(handle->wayland.egl_setup) { timed_redraw_by_epoch(handle, 25); } + */ } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { diff --git a/src/widget/frame.c b/src/widget/frame.c index 36085a6..d48c287 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -29,7 +29,6 @@ static void draw(MwWidget handle) { rr.width = MwGetInteger(handle, MwNwidth) - (MwDefaultBorderWidth(handle) * 2); rr.height = MwGetInteger(handle, MwNheight) - (MwDefaultBorderWidth(handle) * 2); } else { - rr.x = 0; rr.y = 0; rr.width = MwGetInteger(handle, MwNwidth); diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 4141f48..785468d 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -258,7 +258,6 @@ static void frame_draw(MwWidget handle) { if(j == (arrlen(lb->list[i].name) - 1)) p.x -= MwDefaultBorderWidth(handle); if(arrlen(lb->alignment) <= j || lb->alignment[j] == MwALIGNMENT_BEGINNING) { - p.x += 4; MwDrawText(handle, &p, str, 0, MwALIGNMENT_BEGINNING, selected ? base2 : text2); p.x -= 4; diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 9481c49..19a7c4d 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -1,12 +1,6 @@ #include #include -#ifdef USE_WAYLAND -#include -#include -#include -#endif - #ifdef USE_GDI typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); @@ -110,8 +104,8 @@ static int create(MwWidget handle) { } #endif #ifdef USE_WAYLAND - /* Wayland uses OpenGL as its backend so its already initialized */ if(handle->lowlevel->common.type == MwLLBackendWayland) { + /* todo */ } #endif @@ -146,7 +140,9 @@ static void destroy(MwWidget handle) { } #endif #ifdef USE_WAYLAND -/* Wayland uses OpenGL as its backend so its destroyed accordingly */ + if(handle->lowlevel->common.type == MwLLBackendWayland) { + /* todo */ + } #endif free(handle->internal); @@ -169,6 +165,7 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { + /* todo */ } #endif } @@ -189,14 +186,9 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) { } #endif #ifdef USE_WAYLAND -#define tp handle->lowlevel->wayland.topmost_parent->wayland if(handle->lowlevel->common.type == MwLLBackendWayland) { - if(!eglSwapBuffers( - tp.egl_display, tp.egl_surface)) { - printf("Userland error: eglSwapBuffers, %0X\n", eglGetError()); - } + /* todo */ } -#undef topmost_parent #endif } @@ -217,7 +209,7 @@ static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - return eglGetProcAddress(name); + /* todo */ } #endif return NULL;