various fixes and code clean up stuff. improved frame management stability

This commit is contained in:
rozodru 2025-08-01 12:23:07 -04:00
parent 65ab6842b8
commit 8532261b96
7 changed files with 116 additions and 33 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ build
fuzz_corpus
fuzzing-directory
PROGRESS.md
TODO.md

29
nedm.c
View File

@ -20,6 +20,7 @@
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/backend/headless.h>
#include <wlr/backend/session.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>
@ -119,13 +120,21 @@ handle_signal(int signal, void *const data) {
case SIGINT:
/* Fallthrough */
case SIGTERM:
if(server && server->wl_display) {
// Only terminate if we're sure the server is in a valid state
display_terminate(server);
}
return 0;
case SIGALRM: {
// Only clear messages if server is running and valid
if(server && server->running && !wl_list_empty(&server->outputs)) {
struct nedm_output *output;
wl_list_for_each(output, &server->outputs, link) {
if(output) {
message_clear(output);
}
}
}
return 0;
}
case SIGPIPE:
@ -137,6 +146,7 @@ handle_signal(int signal, void *const data) {
}
}
static void
usage(FILE *file, const char *const cage) {
fprintf(file,
@ -418,6 +428,14 @@ main(int argc, char *argv[]) {
wl_event_loop_add_signal(event_loop, SIGPIPE, handle_signal, &server);
server.event_loop = event_loop;
// Let wlroots handle device selection automatically for better compatibility
const char *force_drm_device = getenv("WLR_DRM_DEVICES");
if (force_drm_device) {
wlr_log(WLR_INFO, "Using user-specified DRM devices: %s", force_drm_device);
} else {
wlr_log(WLR_DEBUG, "Using automatic DRM device selection");
}
backend = wlr_backend_autocreate(event_loop, &server.session);
server.headless_backend = wlr_headless_backend_create(event_loop);
if(!backend) {
@ -427,6 +445,15 @@ main(int argc, char *argv[]) {
}
server.backend = backend;
// Session is handled automatically by wlroots - no custom handlers needed
if (server.session) {
server.session_is_active = true; // Start active
wlr_log(WLR_INFO, "Session available - VT switching handled by wlroots");
} else {
wlr_log(WLR_DEBUG, "No session available - running without VT switching");
server.session_is_active = true; // Fallback for sessionless operation
}
if(!drop_permissions()) {
ret = 1;
goto end;
@ -812,6 +839,8 @@ end:
seat_destroy(server.seat);
}
// Session cleanup handled automatically by wlroots
if(sigint_source != NULL) {
wl_event_source_remove(sigint_source);
wl_event_source_remove(sigterm_source);

View File

@ -71,6 +71,10 @@ output_clear(struct nedm_output *output) {
struct nedm_view *view, *view_tmp;
if(server->running) {
for(unsigned int i = 0; i < server->nws; ++i) {
if(!output->workspaces || !output->workspaces[i] ||
!output->workspaces[i]->focused_tile) {
continue;
}
bool first = true;
for(struct nedm_tile *tile = output->workspaces[i]->focused_tile;
@ -79,20 +83,23 @@ output_clear(struct nedm_output *output) {
first = false;
workspace_tile_update_view(tile, NULL);
}
struct nedm_workspace *ws =
server->curr_output
->workspaces[server->curr_output->curr_workspace];
struct nedm_workspace *ws = NULL;
if(server->curr_output && server->curr_output->workspaces &&
server->curr_output->curr_workspace < server->nws &&
server->curr_output->workspaces[server->curr_output->curr_workspace]) {
ws = server->curr_output->workspaces[server->curr_output->curr_workspace];
}
wl_list_for_each_safe(view, view_tmp, &output->workspaces[i]->views,
link) {
wl_list_remove(&view->link);
if(wl_list_empty(&server->outputs)) {
view->impl->destroy(view);
} else {
} else if(ws) {
wl_list_insert(&ws->views, &view->link);
wlr_scene_node_reparent(&view->scene_tree->node, ws->scene);
view->workspace = ws;
view->tile = ws->focused_tile;
if(server->seat->focused_view == NULL) {
if(server->seat && server->seat->focused_view == NULL) {
seat_set_focus(server->seat, view);
}
}
@ -197,8 +204,13 @@ output_destroy(struct nedm_output *output) {
wlr_log(WLR_ERROR,
"Failed to allocate memory for output name in output_destroy");
}
// Note: Don't terminate when outputs become empty - this is normal during:
// - VT switches (outputs temporarily disabled)
// - Output hotplug events
// - Multi-GPU switching
// Modern compositors handle this gracefully and wait for outputs to return
if(wl_list_empty(&server->outputs) && server->running) {
wl_display_terminate(server->wl_display);
wlr_log(WLR_DEBUG, "No outputs available - waiting for outputs to return");
}
}
@ -612,9 +624,13 @@ output_make_workspace_fullscreen(struct nedm_output *output, uint32_t ws) {
if(ws >= server->nws) {
return;
}
struct nedm_view *current_view = output->workspaces[ws]->focused_tile->view;
struct nedm_view *current_view = NULL;
if(output->workspaces && ws < output->server->nws &&
output->workspaces[ws] && output->workspaces[ws]->focused_tile) {
current_view = output->workspaces[ws]->focused_tile->view;
}
if(current_view == NULL) {
if(current_view == NULL && output->workspaces[ws]) {
struct nedm_view *it = NULL;
wl_list_for_each(it, &output->workspaces[ws]->views, link) {
if(view_is_visible(it)) {

10
seat.c
View File

@ -803,7 +803,10 @@ process_cursor_motion(struct nedm_seat *seat, uint32_t time) {
break;
}
}
if(c_outp) {
if(c_outp && nedm_outp->workspaces &&
nedm_outp->curr_workspace < nedm_outp->server->nws &&
nedm_outp->workspaces[nedm_outp->curr_workspace] &&
nedm_outp->workspaces[nedm_outp->curr_workspace]->focused_tile) {
struct nedm_tile *c_tile;
bool first = true;
for(c_tile = nedm_outp->workspaces[nedm_outp->curr_workspace]->focused_tile;
@ -1184,10 +1187,15 @@ seat_set_focus(struct nedm_seat *seat, struct nedm_view *view) {
/* Focusing the background */
if(view == NULL) {
if(server->curr_output && server->curr_output->workspaces &&
server->curr_output->curr_workspace < server->nws &&
server->curr_output->workspaces[server->curr_output->curr_workspace] &&
server->curr_output->workspaces[server->curr_output->curr_workspace]->focused_tile) {
workspace_tile_update_view(
server->curr_output->workspaces[server->curr_output->curr_workspace]
->focused_tile,
NULL);
}
seat->focused_view = NULL;
if(prev_view != NULL) {
view_activate(prev_view, false);

View File

@ -66,3 +66,13 @@ server_show_info(struct nedm_server *server) {
free(input_str);
return ret;
}
bool
server_session_is_active(struct nedm_server *server) {
if (!server) {
return false;
}
// wlroots handles session state automatically
// Just return our tracked state for output termination logic
return server->session_is_active;
}

View File

@ -44,6 +44,8 @@ struct nedm_server {
struct wl_list output_priorities;
struct wlr_backend *headless_backend;
struct wlr_session *session;
struct wl_listener session_active;
bool session_is_active;
struct wlr_renderer *renderer;
struct wlr_allocator *allocator;
@ -90,5 +92,7 @@ int
get_mode_index_from_name(char *const *modes, const char *mode_name);
char *
server_show_info(struct nedm_server *server);
bool
server_session_is_active(struct nedm_server *server);
#endif

17
view.c
View File

@ -131,14 +131,17 @@ view_unmap(struct nedm_view *view) {
#endif
{
struct nedm_view *prev = view_get_prev_view(view);
if(view->server && view->server->seat) {
if(view == view->server->seat->focused_view) {
seat_set_focus(view->server->seat, prev);
} else if(view->server->seat->seat->keyboard_state.focused_surface ==
} else if(view->server->seat->seat &&
view->server->seat->seat->keyboard_state.focused_surface ==
view->wlr_surface) {
wlr_seat_keyboard_clear_focus(view->server->seat->seat);
seat_set_focus(view->server->seat,
view->server->seat->focused_view);
}
}
struct nedm_tile *view_tile = view_get_tile(view);
if(view_tile != NULL) {
workspace_tile_update_view(view_tile, prev);
@ -146,6 +149,7 @@ view_unmap(struct nedm_view *view) {
}
#if NEDM_HAS_XWAYLAND
else {
if(view->server && view->server->seat && view->server->seat->seat) {
if(view->server->seat->seat->keyboard_state.focused_surface == NULL ||
view->server->seat->seat->keyboard_state.focused_surface ==
view->wlr_surface) {
@ -153,6 +157,7 @@ view_unmap(struct nedm_view *view) {
view->server->seat->focused_view);
}
}
}
#endif
wl_list_remove(&view->link);
@ -193,7 +198,9 @@ view_map(struct nedm_view *view, struct wlr_surface *surface,
{
wl_list_insert(&ws->views, &view->link);
}
if(output && output->server && output->server->seat) {
seat_set_focus(output->server->seat, view);
}
int tile_id = 0;
if(view->tile == NULL) {
tile_id = -1;
@ -219,9 +226,17 @@ view_destroy(struct nedm_view *view) {
wlr_scene_node_destroy(&view->scene_tree->node);
view->impl->destroy(view);
// Safely activate the focused view if it exists
if(curr_output && curr_output->workspaces &&
curr_output->curr_workspace < curr_output->server->nws &&
curr_output->workspaces[curr_output->curr_workspace] &&
curr_output->workspaces[curr_output->curr_workspace]->focused_tile &&
curr_output->workspaces[curr_output->curr_workspace]->focused_tile->view) {
view_activate(curr_output->workspaces[curr_output->curr_workspace]
->focused_tile->view,
true);
}
}
void