diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..405f995 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC = cc +CFLAGS = -g -std=c11 -DWLR_USE_UNSTABLE $(shell pkg-config --cflags wlroots-0.18 wayland-server) -Iinclude +LDFLAGS = $(shell pkg-config --libs wlroots-0.18 wayland-server) +SRC = src/main.c src/compositor.c src/renderer.c +OBJ = $(SRC:.c=.o) +BIN = panes + +all: $(BIN) + +$(BIN): $(OBJ) + $(CC) -o $@ $^ $(LDFLAGS) + +%.o: %.c + $(CC) -c $< -o $@ $(CFLAGS) + +clean: + rm -f $(OBJ) $(BIN) diff --git a/cursor.png b/assets/cursor.png similarity index 100% rename from cursor.png rename to assets/cursor.png diff --git a/include/panes/compositor.h b/include/panes/compositor.h new file mode 100644 index 0000000..c5a76a3 --- /dev/null +++ b/include/panes/compositor.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +struct compositor_state { + struct wl_display *display; + struct wlr_backend *backend; + struct wlr_renderer *renderer; + struct wlr_allocator *allocator; + struct wlr_scene *scene; + struct wlr_output_layout *layout; + struct wl_listener new_output; +}; + +void compositor_init(struct compositor_state *state); +void handle_new_output(struct wl_listener *listener, void *data); diff --git a/include/panes/input.h b/include/panes/input.h new file mode 100644 index 0000000..e69de29 diff --git a/include/panes/renderer.h b/include/panes/renderer.h new file mode 100644 index 0000000..903ba12 --- /dev/null +++ b/include/panes/renderer.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void renderer_set_background(struct wlr_scene *scene, uint32_t hex_color); diff --git a/main.c b/main.c deleted file mode 100644 index 4e9dc3a..0000000 --- a/main.c +++ /dev/null @@ -1,105 +0,0 @@ -#define WLR_USE_UNSTABLE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct server { - struct wl_display *display; - struct wlr_backend *backend; - struct wlr_renderer *renderer; - struct wlr_allocator *allocator; - struct wlr_scene *scene; - struct wlr_output_layout *layout; - struct wl_listener new_output; -}; - -static void handle_new_output(struct wl_listener *listener, void *data) { - struct server *server = wl_container_of(listener, server, new_output); - struct wlr_output *output = data; - - // Pick the first available mode - if (!wl_list_empty(&output->modes)) { - struct wlr_output_mode *mode = wl_container_of(output->modes.next, mode, link); - - struct wlr_output_state state; - memset(&state, 0, sizeof(state)); - state.committed = WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE; - state.enabled = true; - state.mode_type = WLR_OUTPUT_STATE_MODE_FIXED; - state.mode = mode; - - if (!wlr_output_commit_state(output, &state)) { - wlr_log(WLR_ERROR, "Failed to commit output state"); - return; - } - } - - wlr_output_layout_add_auto(server->layout, output); - wlr_scene_output_create(server->scene, output); - - float bg[4] = {0.1f, 0.1f, 0.1f, 1.0f}; - struct wlr_scene_rect *rect = - wlr_scene_rect_create(&server->scene->tree, 1, 1, bg); - wlr_scene_node_lower_to_bottom(&rect->node); -} - -int main(void) { - wlr_log_init(WLR_DEBUG, NULL); - struct server server = {0}; - - server.display = wl_display_create(); - struct wl_event_loop *loop = wl_display_get_event_loop(server.display); - - // Create the backend first - server.backend = wlr_backend_autocreate(loop, NULL); // Automatically choose the backend - if (!server.backend) { - wlr_log(WLR_ERROR, "Failed to create backend"); - return 1; - } - - // Create the renderer after the backend - server.renderer = wlr_renderer_autocreate(server.backend); - if (!server.renderer) { - wlr_log(WLR_ERROR, "Failed to create renderer"); - return 1; - } - - // Now create the allocator with the valid renderer - server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); - if (!server.allocator) { - wlr_log(WLR_ERROR, "Failed to create allocator"); - return 1; - } - - // Create the compositor with the renderer - wlr_compositor_create(server.display, 4, server.renderer); - wlr_data_device_manager_create(server.display); - - server.scene = wlr_scene_create(); - server.layout = wlr_output_layout_create(server.display); - - server.new_output.notify = handle_new_output; - wl_signal_add(&server.backend->events.new_output, &server.new_output); - - // Start the backend - if (!wlr_backend_start(server.backend)) { - wlr_log(WLR_ERROR, "Failed to start backend"); - return 1; - } - - wlr_log(WLR_INFO, "Panes compositor running (wlroots 0.18)..."); - wl_display_run(server.display); - wl_display_destroy(server.display); - return 0; -} diff --git a/panes b/panes index 380a9ae..5e1f12b 100755 Binary files a/panes and b/panes differ diff --git a/src/compositor.c b/src/compositor.c new file mode 100644 index 0000000..b0b6e53 --- /dev/null +++ b/src/compositor.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Add this to the top of the file + +static bool parse_hex_color(const char *hex_str, float *rgba_out) { + if (!hex_str) return false; + + if (hex_str[0] == '#') hex_str++; + else if (hex_str[0] == '0' && tolower(hex_str[1]) == 'x') hex_str += 2; + + if (strlen(hex_str) != 6) return false; + + char r_str[3] = { hex_str[0], hex_str[1], '\0' }; + char g_str[3] = { hex_str[2], hex_str[3], '\0' }; + char b_str[3] = { hex_str[4], hex_str[5], '\0' }; + + int r = strtol(r_str, NULL, 16); + int g = strtol(g_str, NULL, 16); + int b = strtol(b_str, NULL, 16); + + rgba_out[0] = r / 255.0f; + rgba_out[1] = g / 255.0f; + rgba_out[2] = b / 255.0f; + rgba_out[3] = 1.0f; + + return true; +} + +void compositor_init(struct compositor_state *state) { + state->display = wl_display_create(); + struct wl_event_loop *loop = wl_display_get_event_loop(state->display); + + state->backend = wlr_backend_autocreate(loop, NULL); + state->renderer = wlr_renderer_autocreate(state->backend); + state->allocator = wlr_allocator_autocreate(state->backend, state->renderer); + state->layout = wlr_output_layout_create(state->display); + state->scene = wlr_scene_create(); + + // Add headless output if applicable (nested testing) + if (wlr_backend_is_headless(state->backend)) { + struct wlr_output *headless_output = wlr_headless_add_output(state->backend, 800, 600); + if (!headless_output) { + wlr_log(WLR_ERROR, "Failed to create headless output"); + } else { + struct wlr_output_state pending; + memset(&pending, 0, sizeof(pending)); + pending.committed = WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE; + pending.enabled = true; + pending.mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM; + pending.custom_mode.width = 800; + pending.custom_mode.height = 600; + pending.custom_mode.refresh = 60000; + + if (!wlr_output_commit_state(headless_output, &pending)) { + wlr_log(WLR_ERROR, "Failed to commit headless output state"); + } + } + } + + wlr_compositor_create(state->display, 4, state->renderer); + wlr_data_device_manager_create(state->display); + + wl_signal_add(&state->backend->events.new_output, &state->new_output); + state->new_output.notify = handle_new_output; +} + +void handle_new_output(struct wl_listener *listener, void *data) { + struct compositor_state *state = wl_container_of(listener, state, new_output); + struct wlr_output *output = data; + + if (!wl_list_empty(&output->modes)) { + struct wlr_output_mode *mode = wl_container_of(output->modes.next, mode, link); + + struct wlr_output_state pending; + memset(&pending, 0, sizeof(pending)); + pending.committed = WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE; + pending.enabled = true; + pending.mode_type = WLR_OUTPUT_STATE_MODE_FIXED; + pending.mode = mode; + + if (!wlr_output_commit_state(output, &pending)) { + wlr_log(WLR_ERROR, "Failed to commit output"); + return; + } + } + + wlr_output_layout_add_auto(state->layout, output); + wlr_scene_output_create(state->scene, output); + renderer_set_background(state->scene, 0x018281); // Hex color +} diff --git a/src/compositor.o b/src/compositor.o new file mode 100644 index 0000000..03ab525 Binary files /dev/null and b/src/compositor.o differ diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..e69de29 diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..242c13f --- /dev/null +++ b/src/main.c @@ -0,0 +1,17 @@ +#include +#include + +int main() { + struct compositor_state state = {0}; + compositor_init(&state); + + if (!wlr_backend_start(state.backend)) { + wlr_log(WLR_ERROR, "Failed to start backend"); + return 1; + } + + wlr_log(WLR_INFO, "Panes compositor running..."); + wl_display_run(state.display); + wl_display_destroy(state.display); + return 0; +} diff --git a/src/main.o b/src/main.o new file mode 100644 index 0000000..ff8ce7a Binary files /dev/null and b/src/main.o differ diff --git a/src/renderer.c b/src/renderer.c new file mode 100644 index 0000000..e088314 --- /dev/null +++ b/src/renderer.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void renderer_set_background(struct wlr_scene *scene, uint32_t hex_color) { + float rgba[4]; + rgba[0] = ((hex_color >> 16) & 0xFF) / 255.0f; + rgba[1] = ((hex_color >> 8) & 0xFF) / 255.0f; + rgba[2] = ( hex_color & 0xFF) / 255.0f; + rgba[3] = 1.0f; + + struct wlr_scene_rect *rect = wlr_scene_rect_create(&scene->tree, 1, 1, rgba); + wlr_scene_node_lower_to_bottom(&rect->node); +} diff --git a/src/renderer.o b/src/renderer.o new file mode 100644 index 0000000..2c8e0b3 Binary files /dev/null and b/src/renderer.o differ