Unfinished Wayland PR #1

Merged
IoI_xD merged 55 commits from IoI_xD/milsko:wayland into master 2025-12-10 11:11:02 +09:00
2 changed files with 100 additions and 45 deletions
Showing only changes of commit df43752fa7 - Show all commits

wayland: properly pump the events system, only drawing when necessary

IoIxD 2025-12-08 15:28:20 -07:00

View file

@ -76,18 +76,25 @@ struct _MwLLWayland {
struct wl_surface* surface; struct wl_surface* surface;
struct wl_shm* shm; struct wl_shm* shm;
struct wl_registry_listener registry_listener; struct wl_registry_listener registry_listener;
struct wl_event_queue* event_queue;
struct wl_pointer* pointer; struct wl_pointer* pointer;
MwLL* subwidgets; MwLL* subwidgets;
MwBool configured; MwBool configured;
MwBool force_redraw; MwBool force_redraw;
MwBool egl_setup; MwBool egl_setup;
MwBool egl_do_resetup; MwBool has_set_xy;
MwU32 x, y, ww, wh; MwU32 x, y, ww, wh;
MwPoint cur_mouse_pos; MwPoint cur_mouse_pos;
struct timeval timer;
MwU64 cooldown_timer;
MwU64 cooldown_timer_epoch;
MwLL parent; MwLL parent;
GLuint fbo; GLuint fbo;
@ -107,6 +114,7 @@ struct _MwLLWaylandColor {
struct _MwLLWaylandPixmap { struct _MwLLWaylandPixmap {
struct _MwLLCommonPixmap common; struct _MwLLCommonPixmap common;
GLuint texture; GLuint texture;
MwBool texture_deleted;
}; };
#endif #endif

View file

@ -26,6 +26,8 @@
void (*focus_out)(MwLL handle, void* data); void (*focus_out)(MwLL handle, void* data);
*/ */
static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer);
#define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name)
static void new_protocol(void* data, struct wl_registry* registry, static void new_protocol(void* data, struct wl_registry* registry,
@ -48,12 +50,12 @@ static void protocol_removed(void* data,
}; };
static void pointer_enter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial,
struct wl_surface* surface, wl_fixed_t surface_x, struct wl_surface* surface, wl_fixed_t surface_x,
wl_fixed_t surface_y) {}; wl_fixed_t surface_y) {};
static void pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial,
struct wl_surface* surface) {}; struct wl_surface* surface) {};
static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t time, static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time,
wl_fixed_t surface_x, wl_fixed_t surface_y) { wl_fixed_t surface_x, wl_fixed_t surface_y) {
MwLL self = data; MwLL self = data;
MwLLMouse p; MwLLMouse p;
@ -62,8 +64,10 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t t
self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y); self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y);
p.point = self->wayland.cur_mouse_pos; p.point = self->wayland.cur_mouse_pos;
MwLLDispatch(self, move, &p); MwLLDispatch(self, move, &p);
timed_redraw(self, time, 50, &self->wayland.cooldown_timer);
}; };
static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) {
MwLL self = data; MwLL self = data;
MwLLMouse p; MwLLMouse p;
p.point = self->wayland.cur_mouse_pos; p.point = self->wayland.cur_mouse_pos;
@ -88,9 +92,11 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t s
break; break;
} }
} }
timed_redraw(self, time, 50, &self->wayland.cooldown_timer);
}; };
static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time, static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time,
uint32_t axis, wl_fixed_t value) {}; MwU32 axis, wl_fixed_t value) {};
struct wl_pointer_listener pointer_listener = { struct wl_pointer_listener pointer_listener = {
.enter = pointer_enter, .enter = pointer_enter,
@ -112,7 +118,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) { if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) {
self->wayland.pointer = wl_seat_get_pointer(wl_seat); self->wayland.pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data);
return;
} }
}; };
@ -258,9 +263,14 @@ static MwBool egl_setup(MwLL self, int width, int height) {
return MwFALSE; return MwFALSE;
} }
if(!eglMakeCurrent(display, surface, surface, context)) { self->wayland.egl_display = display;
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); self->wayland.egl_surface = surface;
return MwFALSE; 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());
}
} }
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -270,26 +280,21 @@ static MwBool egl_setup(MwLL self, int width, int height) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable(GL_BLEND);
self->wayland.egl_display = display;
self->wayland.egl_surface = surface;
self->wayland.egl_context = context;
return MwTRUE; return MwTRUE;
} }
static void egl_resetup(MwLL handle) { static void egl_resetup(MwLL handle) {
int err; int err;
if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { // if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) {
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); // printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
return; // return;
} // }
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1); glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1);
glViewport(0, 0, handle->wayland.ww, handle->wayland.wh); glViewport(0, 0, handle->wayland.ww, handle->wayland.wh);
handle->wayland.egl_do_resetup = MwFALSE;
} }
static void recursive_draw(MwLL handle) { static void recursive_draw(MwLL handle) {
@ -302,16 +307,25 @@ static void recursive_draw(MwLL handle) {
} }
} }
static void recursive_resize(MwLL handle) { static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer) {
int i; if(handle->wayland.parent == NULL) {
if(handle->wayland.subwidgets != NULL) { if(time >= (*cooldown_timer + cooldown)) {
for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { egl_resetup(handle);
MwLLDispatch(handle->wayland.subwidgets[i], resize, NULL); MwLLDispatch(handle, draw, NULL);
recursive_resize(handle->wayland.subwidgets[i]); // recursive_draw(handle);
*cooldown_timer = time;
} }
} }
} }
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);
}
static void xdg_toplevel_configure(void* data, static void xdg_toplevel_configure(void* data,
struct xdg_toplevel* xdg_toplevel, struct xdg_toplevel* xdg_toplevel,
MwI32 width, MwI32 height, MwI32 width, MwI32 height,
@ -326,20 +340,17 @@ static void xdg_toplevel_configure(void* data,
return; return;
} }
} }
self->wayland.ww = width; self->wayland.ww = width;
self->wayland.wh = height; self->wayland.wh = height;
xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh);
MwLLSetWH(self, width, height);
MwLLDispatch(self, resize, NULL); MwLLDispatch(self, resize, NULL);
recursive_resize(self);
if(!self->wayland.egl_setup) { if(!self->wayland.egl_setup) {
self->wayland.egl_setup = egl_setup(self, width, height); self->wayland.egl_setup = egl_setup(self, width, height);
MwLLForceRender(self);
} else { } else {
wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0);
self->wayland.egl_do_resetup = MwTRUE;
egl_resetup(self); egl_resetup(self);
} }
@ -413,9 +424,13 @@ static int event_loop(MwLL handle) {
if(wl_display_dispatch_pending(wayland->display) > 0) { if(wl_display_dispatch_pending(wayland->display) > 0) {
} }
} else { } else {
/* Condition for no events being sent */
if(wl_display_dispatch_pending(wayland->display) == 0) { if(wl_display_dispatch_pending(wayland->display) == 0) {
MwLLDispatch(handle, draw, NULL); if(wayland->event_queue != NULL) {
recursive_draw(handle); if(wl_display_roundtrip_queue(wayland->display, wayland->event_queue) < 0) {
printf("error\n");
};
}
} }
} }
@ -444,8 +459,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) {
#undef WL_INTERFACE #undef WL_INTERFACE
static void setup_toplevel(MwLL r, int x, int y) { static void setup_toplevel(MwLL r, int x, int y) {
int i; int i;
struct wl_region* region;
r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.type = MWLL_WAYLAND_TOPLEVEL;
r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel));
@ -517,6 +531,10 @@ static void setup_toplevel(MwLL r, int x, int y) {
printf("zxdg null\n"); printf("zxdg null\n");
} }
r->wayland.event_queue = wl_display_create_queue(r->wayland.display);
MwLLForceRender(r);
// buffer_setup(&r->wayland); // buffer_setup(&r->wayland);
// glGenBuffers(1, &vertex_buffer); // glGenBuffers(1, &vertex_buffer);
@ -526,8 +544,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
struct wl_compositor* compositor = parent->wayland.compositor; struct wl_compositor* compositor = parent->wayland.compositor;
struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; struct wl_subcompositor* subcompositor = parent->wayland.subcompositor;
struct wl_surface* parent_surface = parent->wayland.surface; struct wl_surface* parent_surface = parent->wayland.surface;
MwLL topmost_parent = parent;
struct wl_region* region; struct wl_region* region;
MwLL topmost_parent = parent;
while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
topmost_parent = topmost_parent->wayland.parent; topmost_parent = topmost_parent->wayland.parent;
@ -572,7 +590,15 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
MwLLForceRender(r); MwLLForceRender(r);
}; };
r->wayland.event_queue = parent->wayland.event_queue;
arrpush(parent->wayland.subwidgets, r); arrpush(parent->wayland.subwidgets, r);
wl_surface_damage(parent->wayland.surface, 0, 0, parent->wayland.ww, parent->wayland.wh);
egl_resetup(topmost_parent);
MwLLDispatch(topmost_parent, draw, NULL);
recursive_draw(topmost_parent);
} }
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
@ -599,6 +625,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
r->wayland.parent = parent; r->wayland.parent = parent;
r->wayland.cooldown_timer = 0;
r->wayland.has_set_xy = MwFALSE;
r->wayland.force_redraw = MwFALSE; r->wayland.force_redraw = MwFALSE;
r->wayland.subwidgets = NULL; r->wayland.subwidgets = NULL;
r->wayland.pointer = NULL; r->wayland.pointer = NULL;
@ -626,10 +655,20 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign
static void MwLLSetXYImpl(MwLL handle, int x, int y) { static void MwLLSetXYImpl(MwLL handle, int x, int y) {
if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
MwLL topmost_parent = handle->wayland.parent;
while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
topmost_parent = topmost_parent->wayland.parent;
}
handle->wayland.x = x; handle->wayland.x = x;
handle->wayland.y = y; handle->wayland.y = y;
// wl_sublevel_set_position(handle->wayland.sublevel, x, y); if(handle->wayland.has_set_xy) {
MwLLForceRender(handle); timed_redraw_by_epoch(topmost_parent, 25);
recursive_draw(topmost_parent);
} else if(x != 0 && y != 0) {
handle->wayland.has_set_xy = MwTRUE;
}
} }
} }
@ -646,6 +685,13 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) {
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { 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); xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
} else { } else {
MwLL topmost_parent = handle->wayland.parent;
while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
topmost_parent = topmost_parent->wayland.parent;
}
timed_redraw_by_epoch(topmost_parent, 25);
recursive_draw(topmost_parent);
} }
} }
@ -692,6 +738,8 @@ static void MwLLBeginDrawImpl(MwLL handle) {
return; return;
} }
} }
// glClear(GL_COLOR_BUFFER_BIT);
// glClearColor(1.0, 0, 0, 1);
} }
static void MwLLEndDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) {
@ -711,8 +759,6 @@ static void MwLLEndDrawImpl(MwLL handle) {
// glClear(GL_COLOR_BUFFER_BIT); // glClear(GL_COLOR_BUFFER_BIT);
// glClearColor(1.0, 0, 0, 1); // glClearColor(1.0, 0, 0, 1);
wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
if(handle->wayland.parent == NULL) { if(handle->wayland.parent == NULL) {
if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) {
printf("error swapping buffers! %0X\n", eglGetError()); printf("error swapping buffers! %0X\n", eglGetError());
@ -745,7 +791,7 @@ static void MwLLFreeColorImpl(MwLLColor color) {
static int MwLLPendingImpl(MwLL handle) { static int MwLLPendingImpl(MwLL handle) {
if(wl_display_dispatch_pending(handle->wayland.display) == 0) { if(wl_display_dispatch_pending(handle->wayland.display) == 0) {
} }
return event_loop(handle) || handle->wayland.force_redraw; return event_loop(handle);
} }
static void MwLLNextEventImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) {
@ -815,16 +861,17 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
glTexCoord2f(0.0f, 1); glTexCoord2f(0.0f, 1);
glVertex2f(x, y + rect->height); glVertex2f(x, y + rect->height);
glEnd(); glEnd();
glFinish();
} }
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
} }
static void MwLLForceRenderImpl(MwLL handle) { static void MwLLForceRenderImpl(MwLL handle) {
wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
wl_surface_commit(handle->wayland.surface); if(handle->wayland.egl_setup) {
timed_redraw_by_epoch(handle, 25);
}
handle->wayland.force_redraw = MwTRUE; handle->wayland.force_redraw = MwTRUE;
} }