diff --git a/include/utils.h b/include/utils.h index ff8cb90..d2c3b7d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -16,6 +16,8 @@ typedef struct { int name_len; vec2i pos; /* This is 0, 0 on wayland. Use |drm_monitor_get_display_server_data| to get the position */ vec2i size; + vec2i logical_pos; + vec2i logical_size; uint32_t connector_id; /* Only on x11 and drm */ gsr_monitor_rotation rotation; /* Only on x11 and wayland */ uint32_t monitor_identifier; /* On x11 this is the crtc id */ diff --git a/src/args_parser.c b/src/args_parser.c index 95367a9..6debb77 100644 --- a/src/args_parser.c +++ b/src/args_parser.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include diff --git a/src/main.cpp b/src/main.cpp index 3d7b3b0..7030c99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,26 +110,23 @@ typedef struct { char *output_name; vec2i monitor_pos; vec2i monitor_size; + double monitor_scale_inverted; } MonitorByPositionCallback; static void get_monitor_by_position_callback(const gsr_monitor *monitor, void *userdata) { MonitorByPositionCallback *data = (MonitorByPositionCallback*)userdata; - vec2i monitor_position = monitor->pos; - vec2i monitor_size = monitor->size; - if(gsr_window_get_display_server(data->window) == GSR_DISPLAY_SERVER_WAYLAND) { - gsr_monitor_rotation monitor_rotation = GSR_MONITOR_ROT_0; - drm_monitor_get_display_server_data(data->window, monitor, &monitor_rotation, &monitor_position); - if(monitor_rotation == GSR_MONITOR_ROT_90 || monitor_rotation == GSR_MONITOR_ROT_270) - std::swap(monitor_size.x, monitor_size.y); - } + const vec2i monitor_position = monitor->logical_pos; + const vec2i monitor_size = monitor->size; + const vec2i monitor_logical_size = monitor->logical_size; - if(!data->output_name && data->position.x >= monitor_position.x && data->position.x <= monitor_position.x + monitor_size.x - && data->position.y >= monitor_position.y && data->position.y <= monitor_position.y + monitor_size.y) + if(!data->output_name && data->position.x >= monitor_position.x && data->position.x <= monitor_position.x + monitor_logical_size.x + && data->position.y >= monitor_position.y && data->position.y <= monitor_position.y + monitor_logical_size.y) { data->output_name = strdup(monitor->name); data->monitor_pos = monitor_position; data->monitor_size = monitor_size; + data->monitor_scale_inverted = (double)monitor_size.x / (double)monitor_logical_size.x; } } @@ -1204,9 +1201,9 @@ struct VideoSource { CaptureSource *capture_source; }; -static RecordingStartResult start_recording_create_streams(const char *filename, const args_parser &args_parser, AVCodecContext *video_codec_context, const std::vector &audio_tracks, bool hdr, std::vector &video_sources) { +static RecordingStartResult start_recording_create_streams(const char *filename, const args_parser &arg_parser, AVCodecContext *video_codec_context, const std::vector &audio_tracks, bool hdr, std::vector &video_sources) { AVFormatContext *av_format_context; - avformat_alloc_output_context2(&av_format_context, nullptr, args_parser.container_format, filename); + avformat_alloc_output_context2(&av_format_context, nullptr, arg_parser.container_format, filename); AVStream *video_stream = create_stream(av_format_context, video_codec_context); avcodec_parameters_from_context(video_stream->codecpar, video_codec_context); @@ -1231,8 +1228,8 @@ static RecordingStartResult start_recording_create_streams(const char *filename, AVDictionary *options = nullptr; av_dict_set(&options, "strict", "experimental", 0); - if(args_parser.ffmpeg_opts) - av_dict_parse_string(&options, args_parser.ffmpeg_opts, "=", ";", 0); + if(arg_parser.ffmpeg_opts) + av_dict_parse_string(&options, arg_parser.ffmpeg_opts, "=", ";", 0); const int header_write_ret = avformat_write_header(av_format_context, &options); av_dict_free(&options); @@ -2140,9 +2137,9 @@ static std::string validate_monitor_get_valid(const gsr_egl *egl, const char* wi return capture_source_result; } -static std::string get_monitor_by_region_center(const gsr_egl *egl, vec2i region_position, vec2i region_size, vec2i *monitor_pos, vec2i *monitor_size) { +static std::string get_monitor_by_region_center(const gsr_egl *egl, vec2i region_position, vec2i region_size, vec2i *monitor_pos, vec2i *monitor_size, double *monitor_scale_inverted) { const bool is_x11 = gsr_window_get_display_server(egl->window) == GSR_DISPLAY_SERVER_X11; - const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM; + const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_WAYLAND; MonitorByPositionCallback data; data.window = egl->window; @@ -2150,6 +2147,7 @@ static std::string get_monitor_by_region_center(const gsr_egl *egl, vec2i region data.output_name = NULL; data.monitor_pos = {0, 0}; data.monitor_size = {0, 0}; + data.monitor_scale_inverted = 1.0; for_each_active_monitor_output(egl->window, egl->card_path, connection_type, get_monitor_by_position_callback, &data); std::string result; @@ -2159,6 +2157,7 @@ static std::string get_monitor_by_region_center(const gsr_egl *egl, vec2i region } *monitor_pos = data.monitor_pos; *monitor_size = data.monitor_size; + *monitor_scale_inverted = data.monitor_scale_inverted; return result; } @@ -2229,7 +2228,8 @@ static gsr_capture* create_monitor_capture(const args_parser &arg_parser, gsr_eg static std::string region_get_data(gsr_egl *egl, vec2i *region_size, vec2i *region_position) { vec2i monitor_pos = {0, 0}; vec2i monitor_size = {0, 0}; - std::string window = get_monitor_by_region_center(egl, *region_position, *region_size, &monitor_pos, &monitor_size); + double monitor_scale_inverted = 1.0; + std::string window = get_monitor_by_region_center(egl, *region_position, *region_size, &monitor_pos, &monitor_size, &monitor_scale_inverted); if(window.empty()) { const bool is_x11 = gsr_window_get_display_server(egl->window) == GSR_DISPLAY_SERVER_X11; const gsr_connection_type connection_type = is_x11 ? GSR_CONNECTION_X11 : GSR_CONNECTION_DRM; @@ -2248,6 +2248,11 @@ static std::string region_get_data(gsr_egl *egl, vec2i *region_size, vec2i *regi } else { region_position->x -= monitor_pos.x; region_position->y -= monitor_pos.y; + region_position->x *= monitor_scale_inverted; + region_position->y *= monitor_scale_inverted; + + region_size->x *= monitor_scale_inverted; + region_size->y *= monitor_scale_inverted; } return window; } diff --git a/src/utils.c b/src/utils.c index 911fcf4..abe8354 100644 --- a/src/utils.c +++ b/src/utils.c @@ -121,6 +121,8 @@ void for_each_active_monitor_output_x11_not_cached(Display *display, active_moni .name_len = out_info->nameLen, .pos = { .x = crt_info->x, .y = crt_info->y }, .size = monitor_size, + .logical_pos = { .x = crt_info->x, .y = crt_info->y }, + .logical_size = monitor_size, .connector_id = x11_output_get_connector_id(display, screen_res->outputs[i], randr_connector_id_atom), .rotation = rotation, .monitor_identifier = out_info->crtc @@ -229,6 +231,8 @@ static void for_each_active_monitor_output_drm(const char *card_path, active_mon .name_len = display_name_len, .pos = { .x = crtc->x, .y = crtc->y }, .size = { .x = (int)crtc->width, .y = (int)crtc->height }, + .logical_pos = { .x = crtc->x, .y = crtc->y }, + .logical_size = { .x = (int)crtc->width, .y = (int)crtc->height }, .connector_id = connector->connector_id, .rotation = GSR_MONITOR_ROT_0, .monitor_identifier = connector_type_index_name != -1 ? monitor_identifier_from_type_and_count(connector_type_index_name, connector->connector_type_id) : 0 @@ -264,6 +268,8 @@ static void get_monitor_by_name_callback(const gsr_monitor *monitor, void *userd if(!data->found_monitor && strcmp(data->name, monitor->name) == 0) { data->monitor->pos = monitor->pos; data->monitor->size = monitor->size; + data->monitor->logical_pos = monitor->logical_pos; + data->monitor->logical_size = monitor->logical_size; data->monitor->connector_id = monitor->connector_id; data->monitor->rotation = monitor->rotation; data->monitor->monitor_identifier = monitor->monitor_identifier; diff --git a/src/window/wayland.c b/src/window/wayland.c index 037c85f..fc51c51 100644 --- a/src/window/wayland.c +++ b/src/window/wayland.c @@ -21,6 +21,8 @@ typedef struct { struct zxdg_output_v1 *xdg_output; vec2i pos; vec2i size; + vec2i logical_pos; + vec2i logical_size; int32_t transform; char *name; } gsr_wayland_output; @@ -123,6 +125,8 @@ static void registry_add_object(void *data, struct wl_registry *registry, uint32 .output = wl_registry_bind(registry, name, &wl_output_interface, 4), .pos = { .x = 0, .y = 0 }, .size = { .x = 0, .y = 0 }, + .logical_pos = { .x = 0, .y = 0 }, + .logical_size = { .x = 0, .y = 0 }, .transform = 0, .name = NULL, }; @@ -160,10 +164,10 @@ static void xdg_output_logical_position(void *data, struct zxdg_output_v1 *zxdg_ } static void xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) { - (void)data; (void)xdg_output; - (void)width; - (void)height; + gsr_wayland_output *gsr_xdg_output = data; + gsr_xdg_output->logical_size.x = width; + gsr_xdg_output->logical_size.y = height; } static void xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) { @@ -206,6 +210,42 @@ static void gsr_window_wayland_set_monitor_outputs_from_xdg_output(gsr_window_wa wl_display_roundtrip(self->display); } +// static int monitor_sort_x_pos(const void* a, const void* b) { +// const gsr_wayland_output *arg1 = *(const gsr_wayland_output**)a; +// const gsr_wayland_output *arg2 = *(const gsr_wayland_output**)b; +// return arg1->logical_pos.x - arg2->logical_pos.x; +// } + +// static int monitor_sort_y_pos(const void* a, const void* b) { +// const gsr_wayland_output *arg1 = *(const gsr_wayland_output**)a; +// const gsr_wayland_output *arg2 = *(const gsr_wayland_output**)b; +// return arg1->logical_pos.y - arg2->logical_pos.y; +// } + +static void gsr_window_wayland_set_monitor_real_positions(gsr_window_wayland *self) { + gsr_wayland_output *sorted_outputs[GSR_MAX_OUTPUTS]; + for(int i = 0; i < self->num_outputs; ++i) { + sorted_outputs[i] = &self->outputs[i]; + } + + // TODO: set correct physical positions + + // qsort(sorted_outputs, self->num_outputs, sizeof(gsr_wayland_output*), monitor_sort_x_pos); + // int x_pos = 0; + // for(int i = 0; i < self->num_outputs; ++i) { + // fprintf(stderr, "monitor: %s\n", sorted_outputs[i]->name); + // sorted_outputs[i]->pos.x = x_pos; + // x_pos += sorted_outputs[i]->logical_size.x; + // } + + // qsort(sorted_outputs, self->num_outputs, sizeof(gsr_wayland_output*), monitor_sort_y_pos); + // int y_pos = 0; + // for(int i = 0; i < self->num_outputs; ++i) { + // sorted_outputs[i]->pos.y = y_pos; + // y_pos += sorted_outputs[i]->logical_size.y; + // } +} + static void gsr_window_wayland_deinit(gsr_window_wayland *self) { if(self->window) { wl_egl_window_destroy(self->window); @@ -273,6 +313,7 @@ static bool gsr_window_wayland_init(gsr_window_wayland *self) { wl_display_roundtrip(self->display); gsr_window_wayland_set_monitor_outputs_from_xdg_output(self); + gsr_window_wayland_set_monitor_real_positions(self); if(!self->compositor) { fprintf(stderr, "gsr error: gsr_window_wayland_init failed: failed to find compositor\n"); @@ -337,6 +378,16 @@ static gsr_monitor_rotation wayland_transform_to_gsr_rotation(int32_t rot) { return GSR_MONITOR_ROT_0; } +static vec2i get_monitor_size_rotated(int width, int height, gsr_monitor_rotation rotation) { + vec2i size = { .x = width, .y = height }; + if(rotation == GSR_MONITOR_ROT_90 || rotation == GSR_MONITOR_ROT_270) { + int tmp_x = size.x; + size.x = size.y; + size.y = tmp_x; + } + return size; +} + static void gsr_window_wayland_for_each_active_monitor_output_cached(const gsr_window *window, active_monitor_callback callback, void *userdata) { const gsr_window_wayland *self = window->priv; for(int i = 0; i < self->num_outputs; ++i) { @@ -344,15 +395,21 @@ static void gsr_window_wayland_for_each_active_monitor_output_cached(const gsr_w if(!output->name) continue; + const gsr_monitor_rotation rotation = wayland_transform_to_gsr_rotation(output->transform); + vec2i size = { .x = output->size.x, .y = output->size.y }; + size = get_monitor_size_rotated(size.x, size.y, rotation); + const int connector_type_index = get_connector_type_by_name(output->name); const int connector_type_id = get_connector_type_id_by_name(output->name); const gsr_monitor monitor = { .name = output->name, .name_len = strlen(output->name), .pos = { .x = output->pos.x, .y = output->pos.y }, - .size = { .x = output->size.x, .y = output->size.y }, + .size = size, + .logical_pos = { .x = output->pos.x, .y = output->pos.y }, + .logical_size = { .x = output->logical_size.x, .y = output->logical_size.y }, .connector_id = 0, - .rotation = wayland_transform_to_gsr_rotation(output->transform), + .rotation = rotation, .monitor_identifier = (connector_type_index != -1 && connector_type_id != -1) ? monitor_identifier_from_type_and_count(connector_type_index, connector_type_id) : 0 }; callback(&monitor, userdata); diff --git a/src/window/x11.c b/src/window/x11.c index 964422d..3b3c955 100644 --- a/src/window/x11.c +++ b/src/window/x11.c @@ -121,6 +121,8 @@ static void gsr_window_x11_for_each_active_monitor_output_cached(const gsr_windo .name_len = strlen(output->name), .pos = output->pos, .size = output->size, + .logical_pos = output->pos, + .logical_size = output->size, .connector_id = output->connector_id, .rotation = output->rotation, .monitor_identifier = output->monitor_identifier