From 714561987e264c5f3e9fb01d9ebbf545225b35b7 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 14 Sep 2024 01:57:00 +0200 Subject: Properly damage if moving cursor Only damage if cursor is inside the target area --- include/cursor.h | 2 +- include/damage.h | 8 ++++-- include/egl.h | 2 +- src/capture/kms.c | 2 +- src/capture/xcomposite.c | 2 +- src/cursor.c | 2 +- src/damage.c | 70 +++++++++++++++++++++++++++++++++++++++++++----- src/egl.c | 2 +- src/main.cpp | 5 ++-- 9 files changed, 79 insertions(+), 16 deletions(-) diff --git a/include/cursor.h b/include/cursor.h index 2f26dfd..323d098 100644 --- a/include/cursor.h +++ b/include/cursor.h @@ -24,7 +24,7 @@ int gsr_cursor_init(gsr_cursor *self, gsr_egl *egl, Display *display); void gsr_cursor_deinit(gsr_cursor *self); /* Returns true if the cursor image has updated or if the cursor has moved */ -bool gsr_cursor_update(gsr_cursor *self, XEvent *xev); +bool gsr_cursor_on_event(gsr_cursor *self, XEvent *xev); void gsr_cursor_tick(gsr_cursor *self, Window relative_to); #endif /* GSR_CURSOR_H */ diff --git a/include/damage.h b/include/damage.h index 68cd0d2..2bf43d7 100644 --- a/include/damage.h +++ b/include/damage.h @@ -21,13 +21,16 @@ typedef struct { int damage_event; int damage_error; - uint64_t window; uint64_t damage; bool damaged; int randr_event; int randr_error; + uint64_t window; + //vec2i window_pos; + vec2i window_size; + vec2i cursor_position; /* Relative to |window| */ gsr_monitor monitor; char monitor_name[32]; @@ -38,7 +41,8 @@ void gsr_damage_deinit(gsr_damage *self); bool gsr_damage_set_target_window(gsr_damage *self, uint64_t window); bool gsr_damage_set_target_monitor(gsr_damage *self, const char *monitor_name); -void gsr_damage_update(gsr_damage *self, XEvent *xev); +void gsr_damage_on_event(gsr_damage *self, XEvent *xev); +void gsr_damage_tick(gsr_damage *self); /* Also returns true if damage tracking is not available */ bool gsr_damage_is_damaged(gsr_damage *self); void gsr_damage_clear(gsr_damage *self); diff --git a/include/egl.h b/include/egl.h index 9e50ad0..61890b4 100644 --- a/include/egl.h +++ b/include/egl.h @@ -314,7 +314,7 @@ bool gsr_egl_load(gsr_egl *self, Display *dpy, bool wayland, bool is_monitor_cap void gsr_egl_unload(gsr_egl *self); /* Returns true if an event is available */ -bool gsr_egl_update(gsr_egl *self); +bool gsr_egl_process_event(gsr_egl *self); /* Does opengl swap with egl or glx, depending on which one is active */ void gsr_egl_swap_buffers(gsr_egl *self); diff --git a/src/capture/kms.c b/src/capture/kms.c index 9ba4bd2..9287a8b 100644 --- a/src/capture/kms.c +++ b/src/capture/kms.c @@ -203,7 +203,7 @@ static void gsr_capture_kms_on_event(gsr_capture *cap, gsr_egl *egl) { return; XEvent *xev = gsr_egl_get_event_data(egl); - gsr_cursor_update(&self->x11_cursor, xev); + gsr_cursor_on_event(&self->x11_cursor, xev); } static float monitor_rotation_to_radians(gsr_monitor_rotation rot) { diff --git a/src/capture/xcomposite.c b/src/capture/xcomposite.c index e99cabf..1b6021b 100644 --- a/src/capture/xcomposite.c +++ b/src/capture/xcomposite.c @@ -230,7 +230,7 @@ static void gsr_capture_xcomposite_on_event(gsr_capture *cap, gsr_egl *egl) { } } - gsr_cursor_update(&self->cursor, xev); + gsr_cursor_on_event(&self->cursor, xev); } static bool gsr_capture_xcomposite_should_stop(gsr_capture *cap, bool *err) { diff --git a/src/cursor.c b/src/cursor.c index ffa1562..b1cc397 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -155,7 +155,7 @@ void gsr_cursor_deinit(gsr_cursor *self) { self->egl = NULL; } -bool gsr_cursor_update(gsr_cursor *self, XEvent *xev) { +bool gsr_cursor_on_event(gsr_cursor *self, XEvent *xev) { bool updated = false; XGenericEventCookie *cookie = (XGenericEventCookie*)&xev->xcookie; const Bool got_event_data = XGetEventData(self->display, cookie); diff --git a/src/damage.c b/src/damage.c index 2eda5d7..168ed6b 100644 --- a/src/damage.c +++ b/src/damage.c @@ -84,7 +84,26 @@ bool gsr_damage_set_target_window(gsr_damage *self, uint64_t window) { self->damage = None; } + if(self->window) + XSelectInput(self->egl->x11.dpy, self->window, 0); + self->window = window; + XSelectInput(self->egl->x11.dpy, self->window, StructureNotifyMask | ExposureMask); + + XWindowAttributes win_attr; + win_attr.x = 0; + win_attr.y = 0; + win_attr.width = 0; + win_attr.height = 0; + if(!XGetWindowAttributes(self->egl->x11.dpy, self->window, &win_attr)) + fprintf(stderr, "gsr warning: gsr_damage_set_target_window failed: failed to get window attributes: %ld\n", (long)self->window); + + //self->window_pos.x = win_attr.x; + //self->window_pos.y = win_attr.y; + + self->window_size.x = win_attr.width; + self->window_size.y = win_attr.height; + self->damage = XDamageCreate(self->egl->x11.dpy, window, XDamageReportNonEmpty); if(self->damage) { XDamageSubtract(self->egl->x11.dpy, self->damage, None, None); @@ -114,6 +133,9 @@ bool gsr_damage_set_target_monitor(gsr_damage *self, const char *monitor_name) { if(!get_monitor_by_name(self->egl, GSR_CONNECTION_X11, monitor_name, &self->monitor)) fprintf(stderr, "gsr warning: gsr_damage_set_target_monitor: failed to find monitor: %s\n", monitor_name); + if(self->window) + XSelectInput(self->egl->x11.dpy, self->window, 0); + self->window = DefaultRootWindow(self->egl->x11.dpy); self->damage = XDamageCreate(self->egl->x11.dpy, self->window, XDamageReportNonEmpty); if(self->damage) { @@ -221,22 +243,53 @@ static void gsr_damage_on_damage_event(gsr_damage *self, XEvent *xev) { XFlush(self->egl->x11.dpy); } -static void gsr_damage_update_cursor(gsr_damage *self) { - Window dummy_window; +static void gsr_damage_on_event_cursor(gsr_damage *self) { + Window root_return = None; + Window child_return = None; int dummy_i; unsigned int dummy_u; vec2i cursor_position = {0, 0}; - XQueryPointer(self->egl->x11.dpy, self->window, &dummy_window, &dummy_window, &dummy_i, &dummy_i, &cursor_position.x, &cursor_position.y, &dummy_u); + XQueryPointer(self->egl->x11.dpy, self->window, &root_return, &child_return, &dummy_i, &dummy_i, &cursor_position.x, &cursor_position.y, &dummy_u); if(cursor_position.x != self->cursor_position.x || cursor_position.y != self->cursor_position.y) { self->cursor_position = cursor_position; - self->damaged = true; + const gsr_rectangle cursor_region = { self->cursor_position, {64, 64} }; // TODO: Track cursor size + switch(self->track_type) { + case GSR_DAMAGE_TRACK_NONE: { + self->damaged = true; + break; + } + case GSR_DAMAGE_TRACK_WINDOW: { + const gsr_rectangle window_region = { (vec2i){0, 0}, self->window_size }; + self->damaged = self->window_size.x == 0 || rectangles_intersect(window_region, cursor_region); + break; + } + case GSR_DAMAGE_TRACK_MONITOR: { + const gsr_rectangle monitor_region = { self->monitor.pos, self->monitor.size }; + self->damaged = self->monitor.monitor_identifier == 0 || rectangles_intersect(monitor_region, cursor_region); + break; + } + } } } -void gsr_damage_update(gsr_damage *self, XEvent *xev) { +static void gsr_damage_on_window_configure_notify(gsr_damage *self, XEvent *xev) { + if(xev->xconfigure.window != self->window) + return; + + //self->window_pos.x = xev->xconfigure.x; + //self->window_pos.y = xev->xconfigure.y; + + self->window_size.x = xev->xconfigure.width; + self->window_size.y = xev->xconfigure.height; +} + +void gsr_damage_on_event(gsr_damage *self, XEvent *xev) { if(self->damage_event == 0 || self->track_type == GSR_DAMAGE_TRACK_NONE) return; + if(self->track_type == GSR_DAMAGE_TRACK_WINDOW && xev->type == ConfigureNotify) + gsr_damage_on_window_configure_notify(self, xev); + if(self->randr_event) { if(xev->type == self->randr_event + RRScreenChangeNotify) XRRUpdateConfiguration(xev); @@ -247,9 +300,14 @@ void gsr_damage_update(gsr_damage *self, XEvent *xev) { if(self->damage_event && xev->type == self->damage_event + XDamageNotify) gsr_damage_on_damage_event(self, xev); +} + +void gsr_damage_tick(gsr_damage *self) { + if(self->damage_event == 0 || self->track_type == GSR_DAMAGE_TRACK_NONE) + return; if(self->track_cursor && !self->damaged) - gsr_damage_update_cursor(self); + gsr_damage_on_event_cursor(self); } bool gsr_damage_is_damaged(gsr_damage *self) { diff --git a/src/egl.c b/src/egl.c index ea69796..b4e3902 100644 --- a/src/egl.c +++ b/src/egl.c @@ -676,7 +676,7 @@ void gsr_egl_unload(gsr_egl *self) { memset(self, 0, sizeof(gsr_egl)); } -bool gsr_egl_update(gsr_egl *self) { +bool gsr_egl_process_event(gsr_egl *self) { switch(gsr_egl_get_display_server(self)) { case GSR_DISPLAY_SERVER_X11: { if(XPending(self->x11.dpy)) { diff --git a/src/main.cpp b/src/main.cpp index 2cefd0a..2c302ab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3318,10 +3318,11 @@ int main(int argc, char **argv) { while(running) { const double frame_start = clock_get_monotonic_seconds(); - while(gsr_egl_update(&egl)) { + while(gsr_egl_process_event(&egl)) { gsr_capture_on_event(capture, &egl); - gsr_damage_update(&damage, gsr_egl_get_event_data(&egl)); + gsr_damage_on_event(&damage, gsr_egl_get_event_data(&egl)); } + gsr_damage_tick(&damage); gsr_capture_tick(capture, video_codec_context); if(!is_monitor_capture) { -- cgit v1.2.3