From 548dae6699b6409d27c19151f3e7ddd11022cb37 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 2 Aug 2024 06:05:01 +0200 Subject: Only take a screenshot if no compositor is running and fix transparent window alpha blending --- src/main.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index cbcefe9..45f8693 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,16 @@ // TODO: if alpha is not enabled (if no compositor is running) then take a screenshot of the selected monitor instead // and use that as the background. However if no compositor is running but a fullscreen application is running (on the focused monitor) // then use xcomposite to get that window as a texture and use that as a background because then the background can update. +// That case can also happen when using a compositor but when the compositor gets turned off when running a fullscreen application. // TODO: Update position when workspace changes (in dwm, sticky property handles it in real workspaces). +// TODO: Make keyboard controllable for steam deck (and other controllers). +// TODO: Keep track of gpu screen recorder run by other programs to not allow recording at the same time, or something. +// TODO: Remove gpu-screen-recorder-overlay-daemon and handle that alt+z global hotkey here instead, to show/hide the window +// without restaring the program. Or make the daemon handle gpu screen recorder program state and pass that to the overlay. +// TODO: Add systray by using org.kde.StatusNotifierWatcher/etc dbus directly. +// TODO: Dont allow replay and record/stream at the same time. If we want to allow that then do that in gpu screen recorder instead +// to make it more efficient by doing record/replay/stream with the same encoded packets. +// TODO: Make sure the overlay always stays on top. Test with starting the overlay and then opening youtube in fullscreen. #include @@ -107,7 +116,14 @@ static Bool make_window_sticky(Display* display, Window window) { return set_window_wm_state(display, window, net_wm_state_sticky_atom); } -mgl::Texture texture_from_ximage(XImage *img) { +static bool is_compositor_running(Display *dpy, int screen) { + char prop_name[20]; + snprintf(prop_name, sizeof(prop_name), "_NET_WM_CM_S%d", screen); + Atom prop_atom = XInternAtom(dpy, prop_name, False); + return XGetSelectionOwner(dpy, prop_atom) != None; +} + +static mgl::Texture texture_from_ximage(XImage *img) { uint8_t *texture_data = (uint8_t*)malloc(img->width * img->height * 3); // TODO: @@ -207,7 +223,7 @@ int main(int argc, char **argv) { window_create_params.hidden = true; //window_create_params.override_redirect = true; window_create_params.background_color = bg_color; - window_create_params.support_alpha = false; + window_create_params.support_alpha = is_compositor_running(display, 0); window_create_params.window_type = MGL_WINDOW_TYPE_DIALOG; mgl::Window window; @@ -260,11 +276,17 @@ int main(int argc, char **argv) { exit(1); } - mgl::Texture screenshot_texture = texture_from_ximage(img); - XDestroyImage(img); - img = NULL; + mgl::Texture screenshot_texture; + if(!window_create_params.support_alpha) { + screenshot_texture = texture_from_ximage(img); + XDestroyImage(img); + img = NULL; + } + + mgl::Sprite screenshot_sprite; + if(screenshot_texture.is_valid()) + screenshot_sprite.set_texture(&screenshot_texture); - mgl::Sprite screenshot_sprite(&screenshot_texture); mgl::Rectangle bg_screenshot_overlay(window.get_size().to_vec2f()); bg_screenshot_overlay.set_color(bg_color); @@ -434,6 +456,7 @@ int main(int argc, char **argv) { update_overlay_shape(); main_buttons[1].button->set_item_label(id, "Start"); + // TODO: Show this with a slight delay to make sure it doesn't show up in the video const char *notification_args[] = { "gpu-screen-recorder-notification", "--text", "Recording has been saved", "--timeout", "3.0", "--icon", "./images/record.png", @@ -460,6 +483,15 @@ int main(int argc, char **argv) { main_buttons[1].button->set_item_label(id, "Stop"); } + // TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video. + // Make clear to the user that the recording starts after the notification is gone. + // Maybe have the option in notification to show timer until its getting hidden, then the notification can say: + // Starting recording in 3... + // 2... + // 1... + // TODO: Do not run this is a daemon. Instead get the pid and when launching another notification close the current notification + // program and start another one. This can also be used to check when the notification has finished by checking with waitpid NOWAIT + // to see when the program has exit. const char *notification_args[] = { "gpu-screen-recorder-notification", "--text", "Recording has started", "--timeout", "3.0", "--icon", "./images/record.png", @@ -604,8 +636,10 @@ int main(int argc, char **argv) { const auto render = [&] { window.clear(bg_color); - window.draw(screenshot_sprite); - window.draw(bg_screenshot_overlay); + if(screenshot_texture.is_valid()) { + window.draw(screenshot_sprite); + window.draw(bg_screenshot_overlay); + } window.draw(top_bar_background); window.draw(top_bar_text); window.draw(logo_sprite); -- cgit v1.2.3