@@ -3,6 +3,9 @@
|
||||
#include "common.h"
|
||||
#include "vec.h"
|
||||
|
||||
#include <wlr/render/pass.h>
|
||||
#include <wlr/render/color.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
@@ -15,6 +18,10 @@
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
static void handle_new_output(struct wl_listener *listener, void *data);
|
||||
static void handle_output_frame(struct wl_listener *listener, void *data);
|
||||
static void handle_output_destroy(struct wl_listener *listener, void *data);
|
||||
|
||||
static inline SphericalCoord get_forward_spherical_with_nearest(
|
||||
Vector3 fwd, float r)
|
||||
{
|
||||
@@ -1481,12 +1488,151 @@ static void setup_xwayland(LunarWM *this)
|
||||
wl_signal_add(&this->wayland.xwayland->events.new_surface,
|
||||
&this->wayland.xwayland_new_surface);
|
||||
}
|
||||
static void destroy_output(LunarWM_Output *output) {
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (output->frame.link.prev || output->frame.link.next) {
|
||||
wl_list_remove(&output->frame.link);
|
||||
}
|
||||
if (output->destroy.link.prev || output->destroy.link.next) {
|
||||
wl_list_remove(&output->destroy.link);
|
||||
}
|
||||
|
||||
free(output);
|
||||
}
|
||||
|
||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||
(void)data;
|
||||
LunarWM_Output *output = wl_container_of(listener, output, destroy);
|
||||
LunarWM *wm = output->wm;
|
||||
|
||||
if (wm && wm->wayland.v_outputs) {
|
||||
for (size_t i = 0; i < vector_size(wm->wayland.v_outputs); ++i) {
|
||||
if (wm->wayland.v_outputs[i] == output) {
|
||||
vector_remove(wm->wayland.v_outputs, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroy_output(output);
|
||||
}
|
||||
|
||||
static void handle_output_frame(struct wl_listener *listener, void *data) {
|
||||
(void)data;
|
||||
LunarWM_Output *output = wl_container_of(listener, output, frame);
|
||||
LunarWM *wm = output->wm;
|
||||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
|
||||
if (wm->xr.available) {
|
||||
wlr_output_schedule_frame(wlr_output);
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_output_state state;
|
||||
wlr_output_state_init(&state);
|
||||
|
||||
struct wlr_render_pass *pass
|
||||
= wlr_output_begin_render_pass(wlr_output, &state, NULL);
|
||||
if (pass == NULL) {
|
||||
wlr_output_state_finish(&state);
|
||||
wlr_output_schedule_frame(wlr_output);
|
||||
wlr_log(WLR_ERROR, "Failed to begin render pass for output %s",
|
||||
wlr_output->name);
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = wlr_output->width,
|
||||
.height = wlr_output->height,
|
||||
};
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = box,
|
||||
.color = {
|
||||
.r = 1.0f,
|
||||
.g = 0.0f,
|
||||
.b = 0.0f,
|
||||
.a = 1.0f,
|
||||
},
|
||||
});
|
||||
|
||||
if (!wlr_render_pass_submit(pass)) {
|
||||
wlr_output_state_finish(&state);
|
||||
wlr_output_schedule_frame(wlr_output);
|
||||
wlr_log(WLR_ERROR, "Failed to submit render pass for output %s",
|
||||
wlr_output->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wlr_output_commit_state(wlr_output, &state)) {
|
||||
wlr_log(WLR_ERROR, "Failed to commit state for output %s",
|
||||
wlr_output->name);
|
||||
wlr_output_state_finish(&state);
|
||||
wlr_output_schedule_frame(wlr_output);
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_output_state_finish(&state);
|
||||
}
|
||||
|
||||
static void handle_new_output(struct wl_listener *listener, void *data) {
|
||||
struct wlr_output *wlr_output = data;
|
||||
LunarWM *wm = wl_container_of(listener, wm, wayland.new_output_listener);
|
||||
|
||||
if (!wlr_output_init_render(
|
||||
wlr_output, wm->wayland.allocator, wm->wayland.renderer)) {
|
||||
wlr_log(WLR_ERROR, "Failed to init render for output %s",
|
||||
wlr_output->name);
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_output_state state;
|
||||
wlr_output_state_init(&state);
|
||||
wlr_output_state_set_enabled(&state, true);
|
||||
|
||||
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
|
||||
if (mode != NULL) {
|
||||
wlr_output_state_set_mode(&state, mode);
|
||||
}
|
||||
|
||||
bool committed = wlr_output_commit_state(wlr_output, &state);
|
||||
wlr_output_state_finish(&state);
|
||||
if (!committed) {
|
||||
wlr_log(WLR_ERROR, "Failed to commit init state for output %s",
|
||||
wlr_output->name);
|
||||
return;
|
||||
}
|
||||
|
||||
LunarWM_Output *output = calloc(1, sizeof(*output));
|
||||
if (!output) {
|
||||
wlr_log(WLR_ERROR, "Out of memory creating output state");
|
||||
return;
|
||||
}
|
||||
|
||||
output->wm = wm;
|
||||
output->wlr_output = wlr_output;
|
||||
|
||||
output->frame.notify = handle_output_frame;
|
||||
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
||||
output->destroy.notify = handle_output_destroy;
|
||||
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
|
||||
|
||||
vector_add(&wm->wayland.v_outputs, output);
|
||||
|
||||
wlr_output_schedule_frame(wlr_output);
|
||||
}
|
||||
|
||||
|
||||
bool LunarWM_wayland_init(LunarWM *this)
|
||||
{
|
||||
wlr_log_init(WLR_DEBUG, nullptr);
|
||||
|
||||
this->wayland.v_toplevels = vector_create();
|
||||
this->wayland.v_outputs = vector_create();
|
||||
|
||||
this->wayland.display = wl_display_create();
|
||||
if (this->wayland.display == nullptr) {
|
||||
@@ -1587,6 +1733,10 @@ bool LunarWM_wayland_init(LunarWM *this)
|
||||
wl_list_init(&this->wayland.keyboards);
|
||||
wl_list_init(&this->wayland.pointers);
|
||||
|
||||
this->wayland.new_output_listener.notify = handle_new_output;
|
||||
wl_signal_add(&this->wayland.backend->events.new_output,
|
||||
&this->wayland.new_output_listener);
|
||||
|
||||
this->wayland.new_input_listener.notify = new_input_listener_notify;
|
||||
wl_signal_add(&this->wayland.backend->events.new_input,
|
||||
&this->wayland.new_input_listener);
|
||||
@@ -1616,6 +1766,20 @@ void LunarWM_wayland_cleanup(LunarWM *this)
|
||||
this->wayland.custom_out_hud = NULL;
|
||||
}
|
||||
|
||||
if (this->wayland.new_output_listener.link.prev
|
||||
|| this->wayland.new_output_listener.link.next) {
|
||||
wl_list_remove(&this->wayland.new_output_listener.link);
|
||||
this->wayland.new_output_listener.notify = NULL;
|
||||
}
|
||||
|
||||
if (this->wayland.v_outputs) {
|
||||
for (size_t i = 0; i < vector_size(this->wayland.v_outputs); ++i) {
|
||||
destroy_output(this->wayland.v_outputs[i]);
|
||||
}
|
||||
vector_free(this->wayland.v_outputs);
|
||||
this->wayland.v_outputs = NULL;
|
||||
}
|
||||
|
||||
if (this->wayland.xwayland) {
|
||||
if (this->wayland.xwayland_new_surface.link.prev
|
||||
|| this->wayland.xwayland_new_surface.link.next) {
|
||||
|
||||
Reference in New Issue
Block a user