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_shm* shm;
struct wl_registry_listener registry_listener;
struct wl_event_queue* event_queue;
struct wl_pointer* pointer;
MwLL* subwidgets;
MwBool configured;
MwBool force_redraw;
MwBool configured;
MwBool force_redraw;
MwBool egl_setup;
MwBool egl_do_resetup;
MwBool has_set_xy;
MwU32 x, y, ww, wh;
MwPoint cur_mouse_pos;
struct timeval timer;
MwU64 cooldown_timer;
MwU64 cooldown_timer_epoch;
MwLL parent;
GLuint fbo;
@ -107,6 +114,7 @@ struct _MwLLWaylandColor {
struct _MwLLWaylandPixmap {
struct _MwLLCommonPixmap common;
GLuint texture;
MwBool texture_deleted;
};
#endif

View file

@ -26,6 +26,8 @@
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)
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,
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) {};
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) {
MwLL self = data;
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);
p.point = self->wayland.cur_mouse_pos;
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;
MwLLMouse p;
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;
}
}
timed_redraw(self, time, 50, &self->wayland.cooldown_timer);
};
static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time,
uint32_t axis, wl_fixed_t value) {};
static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time,
MwU32 axis, wl_fixed_t value) {};
struct wl_pointer_listener pointer_listener = {
.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) {
self->wayland.pointer = wl_seat_get_pointer(wl_seat);
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;
}
if(!eglMakeCurrent(display, surface, surface, context)) {
printf("ERROR: eglMakeCurrent, %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());
}
}
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);
glEnable(GL_BLEND);
self->wayland.egl_display = display;
self->wayland.egl_surface = surface;
self->wayland.egl_context = context;
return MwTRUE;
}
static void egl_resetup(MwLL handle) {
int err;
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;
}
// 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;
// }
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1);
glViewport(0, 0, handle->wayland.ww, handle->wayland.wh);
handle->wayland.egl_do_resetup = MwFALSE;
}
static void recursive_draw(MwLL handle) {
@ -302,16 +307,25 @@ static void recursive_draw(MwLL handle) {
}
}
static void recursive_resize(MwLL handle) {
int i;
if(handle->wayland.subwidgets != NULL) {
for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) {
MwLLDispatch(handle->wayland.subwidgets[i], resize, NULL);
recursive_resize(handle->wayland.subwidgets[i]);
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);
// 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,
struct xdg_toplevel* xdg_toplevel,
MwI32 width, MwI32 height,
@ -326,20 +340,17 @@ static void xdg_toplevel_configure(void* data,
return;
}
}
self->wayland.ww = width;
self->wayland.wh = height;
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);
recursive_resize(self);
if(!self->wayland.egl_setup) {
self->wayland.egl_setup = egl_setup(self, width, height);
MwLLForceRender(self);
} else {
wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0);
self->wayland.egl_do_resetup = MwTRUE;
egl_resetup(self);
}
@ -413,9 +424,13 @@ static int event_loop(MwLL handle) {
if(wl_display_dispatch_pending(wayland->display) > 0) {
}
} else {
/* Condition for no events being sent */
if(wl_display_dispatch_pending(wayland->display) == 0) {
MwLLDispatch(handle, draw, NULL);
recursive_draw(handle);
if(wayland->event_queue != NULL) {
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
static void setup_toplevel(MwLL r, int x, int y) {
int i;
struct wl_region* region;
int i;
r->wayland.type = MWLL_WAYLAND_TOPLEVEL;
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");
}
r->wayland.event_queue = wl_display_create_queue(r->wayland.display);
MwLLForceRender(r);
// buffer_setup(&r->wayland);
// 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_subcompositor* subcompositor = parent->wayland.subcompositor;
struct wl_surface* parent_surface = parent->wayland.surface;
MwLL topmost_parent = parent;
struct wl_region* region;
MwLL topmost_parent = parent;
while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
topmost_parent = topmost_parent->wayland.parent;
@ -572,7 +590,15 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
MwLLForceRender(r);
};
r->wayland.event_queue = parent->wayland.event_queue;
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) {
@ -599,6 +625,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
r->wayland.parent = parent;
r->wayland.cooldown_timer = 0;
r->wayland.has_set_xy = MwFALSE;
r->wayland.force_redraw = MwFALSE;
r->wayland.subwidgets = 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) {
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.y = y;
// wl_sublevel_set_position(handle->wayland.sublevel, x, y);
MwLLForceRender(handle);
if(handle->wayland.has_set_xy) {
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) {
xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
} 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;
}
}
// glClear(GL_COLOR_BUFFER_BIT);
// glClearColor(1.0, 0, 0, 1);
}
static void MwLLEndDrawImpl(MwLL handle) {
@ -711,8 +759,6 @@ static void MwLLEndDrawImpl(MwLL handle) {
// glClear(GL_COLOR_BUFFER_BIT);
// 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(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) {
printf("error swapping buffers! %0X\n", eglGetError());
@ -745,7 +791,7 @@ static void MwLLFreeColorImpl(MwLLColor color) {
static int MwLLPendingImpl(MwLL handle) {
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) {
@ -815,16 +861,17 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
glTexCoord2f(0.0f, 1);
glVertex2f(x, y + rect->height);
glEnd();
glFinish();
}
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);
wl_surface_commit(handle->wayland.surface);
if(handle->wayland.egl_setup) {
timed_redraw_by_epoch(handle, 25);
}
handle->wayland.force_redraw = MwTRUE;
}