fix(ui/render): adjust rendering based on window size

Compute the size of the GTK window based on sane compute that works well
for single monitor. Still not sure how this behaves on multi monitors.

This also fixes the issue where swappy would crop the image on scaled
output displays.

Closes #6
This commit is contained in:
Jeremy Attali 2020-05-17 23:37:09 -04:00
parent a78422b22d
commit 445980bbf4
4 changed files with 47 additions and 4 deletions

View File

@ -193,6 +193,7 @@ struct swappy_state {
char *file_str;
char *output_file;
struct swappy_box *window;
struct swappy_box *geometry;
GList *paints;

View File

@ -217,6 +217,7 @@ void application_finish(struct swappy_state *state) {
g_free(state->file_str);
g_free(state->geometry_str);
g_free(state->geometry);
g_free(state->window);
g_free(state->ui);
g_object_unref(state->app);
@ -492,6 +493,36 @@ void text_size_increase_handler(GtkWidget *widget, struct swappy_state *state) {
action_text_size_increase(state);
}
static void compute_window_size(struct swappy_state *state) {
GdkRectangle workarea = {0};
GdkDisplay *display = gdk_display_get_default();
GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(state->ui->window));
GdkMonitor *monitor = gdk_display_get_monitor_at_window(display, window);
gdk_monitor_get_workarea(monitor, &workarea);
g_info("size of monitor at window: %ux%u", workarea.width, workarea.height);
g_assert(workarea.width > 0);
g_assert(workarea.height > 0);
state->window = g_new(struct swappy_box, 1);
state->window->x = workarea.x;
state->window->y = workarea.y;
double threshold = 0.75;
double scaling = 1.0;
if (state->geometry->width > workarea.width * threshold) {
scaling = workarea.width * threshold / state->geometry->width;
} else if (state->geometry->height > workarea.height * threshold) {
scaling = workarea.height * threshold / state->geometry->height;
}
state->window->width = state->geometry->width * scaling;
state->window->height = state->geometry->height * scaling;
g_info("size of window to render: %ux%u", state->window->width,
state->window->height);
}
static void apply_css(GtkWidget *widget, GtkStyleProvider *provider) {
gtk_style_context_add_provider(gtk_widget_get_style_context(widget), provider,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
@ -511,7 +542,6 @@ static bool load_css(struct swappy_state *state) {
}
static bool load_layout(struct swappy_state *state) {
struct swappy_box *geometry = state->geometry;
GError *error = NULL;
/* Construct a GtkBuilder instance and load our UI description */
@ -565,8 +595,6 @@ static bool load_layout(struct swappy_state *state) {
state->ui->text_size =
GTK_BUTTON(gtk_builder_get_object(builder, "text-size-button"));
gtk_widget_set_size_request(area, geometry->width, geometry->height);
state->ui->brush = brush;
state->ui->text = text;
state->ui->rectangle = rectangle;
@ -575,6 +603,11 @@ static bool load_layout(struct swappy_state *state) {
state->ui->area = area;
state->ui->window = window;
compute_window_size(state);
gtk_widget_set_size_request(area, state->window->width,
state->window->height);
g_object_unref(G_OBJECT(builder));
return true;

View File

@ -268,6 +268,8 @@ bool buffer_init_from_file(struct swappy_state *state) {
geometry->width = (int32_t)width;
geometry->height = (int32_t)height;
g_info("size of image: %dx%d", width, height);
state->geometry = geometry;
cairo_pattern_t *output_pattern = cairo_pattern_create_for_surface(surface);

View File

@ -193,13 +193,20 @@ static void render_buffers(cairo_t *cr, struct swappy_state *state) {
return;
}
cairo_paint(cr);
cairo_save(cr);
double sx = (double)state->window->width / state->geometry->width;
double sy = (double)state->window->height / state->geometry->height;
cairo_scale(cr, sx, sy);
for (GList *elem = state->patterns; elem; elem = elem->prev) {
cairo_pattern_t *pattern = elem->data;
cairo_set_source(cr, pattern);
cairo_paint(cr);
}
cairo_restore(cr);
}
static void render_background(cairo_t *cr) {