Add application icon, show gsr icon in notification

This commit is contained in:
dec05eba
2025-12-31 16:29:11 +01:00
parent 1ea9615584
commit df1610431d
9 changed files with 64 additions and 24 deletions

View File

@@ -0,0 +1,10 @@
[Desktop Entry]
Type=Application
Name=GPU Screen Recorder
GenericName=Screen recorder
Comment=A ShadowPlay-like screen recorder for Linux
Icon=gpu-screen-recorder
Exec=gsr-ui launch-hide-announce
Terminal=false
Keywords=gpu-screen-recorder;gsr-ui;screen recorder;streaming;twitch;replay;shadowplay;
Categories=AudioVideo;Recorder;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -40,7 +40,8 @@ namespace gsr {
RECORD, RECORD,
REPLAY, REPLAY,
STREAM, STREAM,
SCREENSHOT SCREENSHOT,
NOTICE
}; };
enum class NotificationLevel { enum class NotificationLevel {
@@ -98,6 +99,7 @@ namespace gsr {
bool global_hotkeys_ungrab_keyboard = false; bool global_hotkeys_ungrab_keyboard = false;
private: private:
const char* notification_type_to_string(NotificationType notification_type);
void update_upause_status(); void update_upause_status();
void hide(); void hide();
@@ -171,6 +173,8 @@ namespace gsr {
Config config; Config config;
Config current_recording_config; Config current_recording_config;
std::string gsr_icon_path;
bool visible = false; bool visible = false;
mgl::Texture window_texture_texture; mgl::Texture window_texture_texture;

View File

@@ -64,6 +64,7 @@ mglpp_dep = mglpp_proj.get_variable('mglpp_dep')
prefix = get_option('prefix') prefix = get_option('prefix')
datadir = get_option('datadir') datadir = get_option('datadir')
gsr_ui_resources_path = join_paths(prefix, datadir, 'gsr-ui') gsr_ui_resources_path = join_paths(prefix, datadir, 'gsr-ui')
icons_path = join_paths(prefix, datadir, 'icons')
add_project_arguments('-DGSR_UI_VERSION="' + meson.project_version() + '"', language: ['c', 'cpp']) add_project_arguments('-DGSR_UI_VERSION="' + meson.project_version() + '"', language: ['c', 'cpp'])
add_project_arguments('-DGSR_FLATPAK_VERSION="5.11.1"', language: ['c', 'cpp']) add_project_arguments('-DGSR_FLATPAK_VERSION="5.11.1"', language: ['c', 'cpp'])
@@ -112,6 +113,12 @@ executable(
install_subdir('images', install_dir : gsr_ui_resources_path) install_subdir('images', install_dir : gsr_ui_resources_path)
install_subdir('fonts', install_dir : gsr_ui_resources_path) install_subdir('fonts', install_dir : gsr_ui_resources_path)
install_data(files('gpu-screen-recorder.desktop'), install_dir : join_paths(prefix, datadir, 'applications'))
install_subdir('icons/hicolor', install_dir : icons_path)
gnome = import('gnome')
gnome.post_install(update_desktop_database : true)
if get_option('systemd') == true if get_option('systemd') == true
install_data(files('extra/gpu-screen-recorder-ui.service'), install_dir : 'lib/systemd/user') install_data(files('extra/gpu-screen-recorder-ui.service'), install_dir : 'lib/systemd/user')
endif endif

View File

@@ -473,6 +473,8 @@ namespace gsr {
top_bar_background({0.0f, 0.0f}), top_bar_background({0.0f, 0.0f}),
close_button_widget({0.0f, 0.0f}) close_button_widget({0.0f, 0.0f})
{ {
gsr_icon_path = this->resources_path + "images/gpu_screen_recorder_logo.png";
key_bindings[0].key_event.code = mgl::Keyboard::Escape; key_bindings[0].key_event.code = mgl::Keyboard::Escape;
key_bindings[0].key_event.alt = false; key_bindings[0].key_event.alt = false;
key_bindings[0].key_event.control = false; key_bindings[0].key_event.control = false;
@@ -519,7 +521,7 @@ namespace gsr {
if(!config.main_config.wayland_warning_shown) { if(!config.main_config.wayland_warning_shown) {
config.main_config.wayland_warning_shown = true; config.main_config.wayland_warning_shown = true;
save_config(config); save_config(config);
show_notification("Wayland doesn't support GPU Screen Recorder UI properly,\nthings may not work as expected. Use X11 if you experience issues.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("Wayland doesn't support GPU Screen Recorder UI properly,\nthings may not work as expected. Use X11 if you experience issues.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
} }
} }
@@ -735,7 +737,7 @@ namespace gsr {
show_notification( show_notification(
"Some keyboard remapping software conflicts with GPU Screen Recorder on your system.\n" "Some keyboard remapping software conflicts with GPU Screen Recorder on your system.\n"
"Keyboards have been ungrabbed, applications will now receive the hotkeys you press." "Keyboards have been ungrabbed, applications will now receive the hotkeys you press."
, 7.0, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); , 7.0, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
config.main_config.hotkeys_enable_option = "enable_hotkeys_no_grab"; config.main_config.hotkeys_enable_option = "enable_hotkeys_no_grab";
save_config(config); save_config(config);
@@ -774,7 +776,7 @@ namespace gsr {
if(selected_window && selected_window != DefaultRootWindow(display)) { if(selected_window && selected_window != DefaultRootWindow(display)) {
on_window_selected(); on_window_selected();
} else { } else {
show_notification("No window selected", notification_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("No window selected", notification_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
} }
on_window_selected = nullptr; on_window_selected = nullptr;
} }
@@ -825,7 +827,7 @@ namespace gsr {
start_region_capture = false; start_region_capture = false;
hide(); hide();
if(!region_selector.start(get_color_theme().tint_color)) { if(!region_selector.start(get_color_theme().tint_color)) {
show_notification("Failed to start region capture", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("Failed to start region capture", notification_error_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
on_region_selected = nullptr; on_region_selected = nullptr;
} }
} }
@@ -834,7 +836,7 @@ namespace gsr {
start_window_capture = false; start_window_capture = false;
hide(); hide();
if(!window_selector.start(get_color_theme().tint_color)) { if(!window_selector.start(get_color_theme().tint_color)) {
show_notification("Failed to start window capture", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("Failed to start window capture", notification_error_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
on_window_selected = nullptr; on_window_selected = nullptr;
} }
} }
@@ -1321,12 +1323,12 @@ namespace gsr {
if(exit_status == 127) { if(exit_status == 127) {
if(enable) if(enable)
show_notification("Failed to add GPU Screen Recorder to system startup.\nThis option only works on systems that use systemd.\nYou have to manually add \"gsr-ui\" to system startup on systems that uses another init system.", 7.0, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("Failed to add GPU Screen Recorder to system startup.\nThis option only works on systems that use systemd.\nYou have to manually add \"gsr-ui\" to system startup on systems that uses another init system.", 7.0, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
} else { } else {
if(enable) if(enable)
show_notification("Failed to add GPU Screen Recorder to system startup", notification_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("Failed to add GPU Screen Recorder to system startup", notification_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
else else
show_notification("Failed to remove GPU Screen Recorder from system startup", notification_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE, nullptr, NotificationLevel::ERROR); show_notification("Failed to remove GPU Screen Recorder from system startup", notification_timeout_seconds, mgl::Color(255, 255, 255), mgl::Color(255, 0, 0), NotificationType::NOTICE, nullptr, NotificationLevel::ERROR);
} }
}; };
@@ -1576,13 +1578,14 @@ namespace gsr {
on_press_take_screenshot(false, ScreenshotForceType::WINDOW); on_press_take_screenshot(false, ScreenshotForceType::WINDOW);
} }
static const char* notification_type_to_string(NotificationType notification_type) { const char* Overlay::notification_type_to_string(NotificationType notification_type) {
switch(notification_type) { switch(notification_type) {
case NotificationType::NONE: return nullptr; case NotificationType::NONE: return nullptr;
case NotificationType::RECORD: return "record"; case NotificationType::RECORD: return "record";
case NotificationType::REPLAY: return "replay"; case NotificationType::REPLAY: return "replay";
case NotificationType::STREAM: return "stream"; case NotificationType::STREAM: return "stream";
case NotificationType::SCREENSHOT: return "screenshot"; case NotificationType::SCREENSHOT: return "screenshot";
case NotificationType::NOTICE: return gsr_icon_path.c_str();
} }
return nullptr; return nullptr;
} }
@@ -1972,6 +1975,7 @@ namespace gsr {
} }
case NotificationType::NONE: case NotificationType::NONE:
case NotificationType::STREAM: case NotificationType::STREAM:
case NotificationType::NOTICE:
break; break;
} }
show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, notification_type, capture_target); show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, notification_type, capture_target);
@@ -2070,6 +2074,7 @@ namespace gsr {
const char *prefix = ""; const char *prefix = "";
switch(notification_type) { switch(notification_type) {
case NotificationType::NONE: case NotificationType::NONE:
case NotificationType::NOTICE:
break; break;
case NotificationType::SCREENSHOT: case NotificationType::SCREENSHOT:
prefix = "Failed to take a screenshot"; prefix = "Failed to take a screenshot";

View File

@@ -3,6 +3,7 @@
#include "../include/gui/Utils.hpp" #include "../include/gui/Utils.hpp"
#include "../include/Process.hpp" #include "../include/Process.hpp"
#include "../include/Rpc.hpp" #include "../include/Rpc.hpp"
#include "../include/Theme.hpp"
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
@@ -174,6 +175,7 @@ static void usage() {
enum class LaunchAction { enum class LaunchAction {
LAUNCH_SHOW, LAUNCH_SHOW,
LAUNCH_HIDE, LAUNCH_HIDE,
LAUNCH_HIDE_ANNOUNCE,
LAUNCH_DAEMON LAUNCH_DAEMON
}; };
@@ -197,6 +199,8 @@ int main(int argc, char **argv) {
launch_action = LaunchAction::LAUNCH_SHOW; launch_action = LaunchAction::LAUNCH_SHOW;
} else if(strcmp(launch_action_opt, "launch-hide") == 0) { } else if(strcmp(launch_action_opt, "launch-hide") == 0) {
launch_action = LaunchAction::LAUNCH_HIDE; launch_action = LaunchAction::LAUNCH_HIDE;
} else if(strcmp(launch_action_opt, "launch-hide-announce") == 0) {
launch_action = LaunchAction::LAUNCH_HIDE_ANNOUNCE;
} else if(strcmp(launch_action_opt, "launch-daemon") == 0) { } else if(strcmp(launch_action_opt, "launch-daemon") == 0) {
launch_action = LaunchAction::LAUNCH_DAEMON; launch_action = LaunchAction::LAUNCH_DAEMON;
} else { } else {
@@ -209,6 +213,19 @@ int main(int argc, char **argv) {
set_display_server_environment_variables(); set_display_server_environment_variables();
std::string resources_path;
if(access("sibs-build/linux_x86_64/debug/gsr-ui", F_OK) == 0) {
resources_path = "./";
} else {
#ifdef GSR_UI_RESOURCES_PATH
resources_path = GSR_UI_RESOURCES_PATH "/";
#else
resources_path = "/usr/share/gsr-ui/";
#endif
}
const std::string gsr_icon_path = resources_path + "images/gpu_screen_recorder_logo.png";
auto rpc = std::make_unique<gsr::Rpc>(); auto rpc = std::make_unique<gsr::Rpc>();
const gsr::RpcOpenResult rpc_open_result = rpc->open("gsr-ui"); const gsr::RpcOpenResult rpc_open_result = rpc->open("gsr-ui");
@@ -220,7 +237,10 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error: another instance of gsr-ui is already running, opening that one instead\n"); fprintf(stderr, "Error: another instance of gsr-ui is already running, opening that one instead\n");
} else { } else {
fprintf(stderr, "Error: failed to send command to running gsr-ui instance, user will have to open the UI manually with Alt+Z\n"); fprintf(stderr, "Error: failed to send command to running gsr-ui instance, user will have to open the UI manually with Alt+Z\n");
const char *args[] = { "gsr-notify", "--text", "Another instance of GPU Screen Recorder UI is already running.\nPress Alt+Z to open the UI.", "--timeout", "5.0", "--icon-color", "ff0000", "--bg-color", "ff0000", nullptr }; const char *args[] = {
"gsr-notify", "--text", "Another instance of GPU Screen Recorder UI is already running.\nPress Alt+Z to open the UI.", "--timeout", "5.0",
"--icon-color", "ffffff", "--icon", gsr_icon_path.c_str(), "--bg-color", "ff0000", nullptr
};
gsr::exec_program_daemonized(args); gsr::exec_program_daemonized(args);
} }
return 1; return 1;
@@ -230,7 +250,10 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error: Failed to create rpc\n"); fprintf(stderr, "Error: Failed to create rpc\n");
if(gsr::pidof("gpu-screen-recorder", -1) != -1) { if(gsr::pidof("gpu-screen-recorder", -1) != -1) {
const char *args[] = { "gsr-notify", "--text", "GPU Screen Recorder is already running in another process.\nPlease close it before using GPU Screen Recorder UI.", "--timeout", "5.0", "--icon-color", "ff0000", "--bg-color", "ff0000", nullptr }; const char *args[] = {
"gsr-notify", "--text", "GPU Screen Recorder is already running in another process.\nPlease close it before using GPU Screen Recorder UI.",
"--timeout", "5.0", "--icon-color", "ffffff", "--icon", gsr_icon_path.c_str(), "--bg-color", "ff0000", nullptr
};
gsr::exec_program_daemonized(args); gsr::exec_program_daemonized(args);
} }
@@ -284,17 +307,6 @@ int main(int argc, char **argv) {
gsr::SupportedCaptureOptions capture_options = gsr::get_supported_capture_options(gsr_info); gsr::SupportedCaptureOptions capture_options = gsr::get_supported_capture_options(gsr_info);
std::string resources_path;
if(access("sibs-build/linux_x86_64/debug/gsr-ui", F_OK) == 0) {
resources_path = "./";
} else {
#ifdef GSR_UI_RESOURCES_PATH
resources_path = GSR_UI_RESOURCES_PATH "/";
#else
resources_path = "/usr/share/gsr-ui/";
#endif
}
mgl_context *context = mgl_get_context(); mgl_context *context = mgl_get_context();
egl_functions egl_funcs; egl_functions egl_funcs;
@@ -313,6 +325,8 @@ int main(int argc, char **argv) {
auto overlay = std::make_unique<gsr::Overlay>(resources_path, std::move(gsr_info), std::move(capture_options), egl_funcs); auto overlay = std::make_unique<gsr::Overlay>(resources_path, std::move(gsr_info), std::move(capture_options), egl_funcs);
if(launch_action == LaunchAction::LAUNCH_SHOW) if(launch_action == LaunchAction::LAUNCH_SHOW)
overlay->show(); overlay->show();
else if(launch_action == LaunchAction::LAUNCH_HIDE_ANNOUNCE)
overlay->show_notification("Press Alt+Z to open the GPU Screen Recorder UI", 5.0, mgl::Color(255, 255, 255), gsr::get_color_theme().tint_color, gsr::NotificationType::NOTICE, nullptr, gsr::NotificationLevel::ERROR);
rpc_add_commands(rpc.get(), overlay.get()); rpc_add_commands(rpc.get(), overlay.get());