Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show snapshots side-by-side #18281

Merged
merged 3 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 6 additions & 48 deletions src/control/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,14 +391,6 @@ gboolean dt_control_configure(GtkWidget *da,
return TRUE;
}

static GdkRGBA _lookup_color(GtkStyleContext *context, const char *name)
{
GdkRGBA color, fallback = {1.0, 0.0, 0.0, 1.0};
if(!gtk_style_context_lookup_color (context, name, &color))
color = fallback;
return color;
}

void dt_control_draw_busy_msg(cairo_t *cr, int width, int height)
{
PangoRectangle ink;
Expand Down Expand Up @@ -431,60 +423,26 @@ void dt_control_draw_busy_msg(cairo_t *cr, int width, int height)
g_object_unref(layout);
}

void *dt_control_expose(void *voidptr)
void dt_control_expose(GtkWidget *widget, cairo_t *cr)
{
int pointerx, pointery;
if(!darktable.gui->surface) return NULL;

dt_control_t *dc = darktable.control;
const int width = dt_cairo_image_surface_get_width(darktable.gui->surface);
const int height = dt_cairo_image_surface_get_height(darktable.gui->surface);
GtkWidget *widget = dt_ui_center(darktable.gui->ui);
gdk_window_get_device_position(gtk_widget_get_window(widget),
gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(widget))),
&pointerx, &pointery, NULL);

// create a gtk-independent surface to draw on
cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cr = cairo_create(cst);

// TODO: control_expose: only redraw the part not overlapped by
// temporary control panel show!
//
dc->width = width;
dc->height = height;

GtkStyleContext *context = gtk_widget_get_style_context(widget);

// look up some colors once
const GdkRGBA bg_color = _lookup_color(context, "bg_color");
dt_control_t *dc = darktable.control;
dc->width = gtk_widget_get_allocated_width(widget);
dc->height = gtk_widget_get_allocated_height(widget);

gdk_cairo_set_source_rgba(cr, &bg_color);
cairo_save(cr);
cairo_rectangle(cr, 0, 0, width, height);
cairo_clip(cr);
cairo_new_path(cr);
// draw view
dt_view_manager_expose(darktable.view_manager, cr, width, height, pointerx, pointery);
cairo_restore(cr);
dt_view_manager_expose(darktable.view_manager, cr, dc->width, dc->height, pointerx, pointery);

// draw busy indicator
dt_pthread_mutex_lock(&dc->log_mutex);
if(dc->log_busy > 0)
{
dt_control_draw_busy_msg(cr, width, height);
dt_control_draw_busy_msg(cr, dc->width, dc->height);
}
dt_pthread_mutex_unlock(&dc->log_mutex);

cairo_destroy(cr);

cairo_t *cr_pixmap = cairo_create(darktable.gui->surface);
cairo_set_source_surface(cr_pixmap, cst, 0, 0);
cairo_paint(cr_pixmap);
cairo_destroy(cr_pixmap);

cairo_surface_destroy(cst);
return NULL;
}

gboolean dt_control_draw_endmarker(GtkWidget *widget,
Expand Down
2 changes: 1 addition & 1 deletion src/control/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct dt_lib_backgroundjob_element_t;
typedef GdkCursorType dt_cursor_t;

// called from gui
void *dt_control_expose(void *voidptr);
void dt_control_expose(GtkWidget *widget, cairo_t *cr);
gboolean dt_control_draw_endmarker(GtkWidget *widget, cairo_t *crf, gpointer user_data);
void dt_control_button_pressed(double x, double y, double pressure, int which, int type, uint32_t state);
void dt_control_button_released(double x, double y, int which, uint32_t state);
Expand Down
7 changes: 5 additions & 2 deletions src/develop/develop.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,8 +572,11 @@ float dt_dev_get_zoom_scale(dt_dev_viewport_t *port,
break;
}

if(preview) zoom_scale *= (float)darktable.develop->full.pipe->processed_width
/ darktable.develop->preview_pipe->processed_width;
if(!zoom_scale) zoom_scale = 1.0f;

if(preview && darktable.develop->preview_pipe->processed_width)
zoom_scale *= (float)darktable.develop->full.pipe->processed_width
/ darktable.develop->preview_pipe->processed_width;

return zoom_scale;
}
Expand Down
108 changes: 41 additions & 67 deletions src/gui/gtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ typedef struct dt_ui_t
/* center widget */
GtkWidget *center;
GtkWidget *center_base;
GtkWidget *snapshot;

/* main widget */
GtkWidget *main_window;
Expand Down Expand Up @@ -711,12 +712,11 @@ static gboolean _draw(GtkWidget *da,
cairo_t *cr,
gpointer user_data)
{
dt_control_expose(NULL);
if(darktable.gui->surface)
{
cairo_set_source_surface(cr, darktable.gui->surface, 0, 0);
cairo_paint(cr);
}
GtkWidget *ss = dt_ui_snapshot(darktable.gui->ui);
darktable.gui->drawing_snapshot = da == ss;
if(!darktable.gui->drawing_snapshot) gtk_widget_queue_draw(ss);

dt_control_expose(da, cr);

return TRUE;
}
Expand Down Expand Up @@ -951,35 +951,6 @@ static gboolean _configure(GtkWidget *da,
GdkEventConfigure *event,
gpointer user_data)
{
static int oldw = 0;
static int oldh = 0;
// make our selves a properly sized pixmap if our window has been resized
if(oldw != event->width || oldh != event->height)
{
// create our new pixmap with the correct size.
cairo_surface_t *tmpsurface
= dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, event->width, event->height);
// copy the contents of the old pixmap to the new pixmap. This keeps ugly uninitialized
// pixmaps from being painted upon resize
// int minw = oldw, minh = oldh;
// if(event->width < minw) minw = event->width;
// if(event->height < minh) minh = event->height;

cairo_t *cr = cairo_create(tmpsurface);
cairo_set_source_surface(cr, darktable.gui->surface, 0, 0);
cairo_paint(cr);
cairo_destroy(cr);

// we're done with our old pixmap, so we can get rid of it and
// replace it with our properly-sized one.
cairo_surface_destroy(darktable.gui->surface);
darktable.gui->surface = tmpsurface;
dt_colorspaces_set_display_profile(
DT_COLORSPACE_DISPLAY); // maybe we are on another screen now with > 50% of the area
}
oldw = event->width;
oldh = event->height;

#ifndef GDK_WINDOWING_QUARTZ
dt_configure_ppd_dpi((dt_gui_gtk_t *) user_data);
#endif
Expand Down Expand Up @@ -1352,7 +1323,6 @@ int dt_gui_gtk_init(dt_gui_gtk_t *gui)
GtkWidget *widget;
if(!gui->ui)
gui->ui = g_malloc0(sizeof(dt_ui_t));
gui->surface = NULL;
gui->hide_tooltips = dt_conf_get_bool("ui/hide_tooltips") ? 1 : 0;
gui->grouping = dt_conf_get_bool("ui_last/grouping");
gui->expanded_group_id = NO_IMGID;
Expand Down Expand Up @@ -1388,23 +1358,30 @@ int dt_gui_gtk_init(dt_gui_gtk_t *gui)
_init_widgets(gui);

widget = dt_ui_center(darktable.gui->ui);

g_signal_connect(G_OBJECT(widget), "configure-event",
G_CALLBACK(_configure), gui);
g_signal_connect(G_OBJECT(widget), "draw",
G_CALLBACK(_draw), NULL);
g_signal_connect(G_OBJECT(widget), "motion-notify-event",
G_CALLBACK(_mouse_moved), gui);
g_signal_connect(G_OBJECT(widget), "leave-notify-event",
G_CALLBACK(_center_leave), NULL);
g_signal_connect(G_OBJECT(widget), "enter-notify-event",
G_CALLBACK(_center_enter), NULL);
g_signal_connect(G_OBJECT(widget), "button-press-event",
G_CALLBACK(_button_pressed), NULL);
g_signal_connect(G_OBJECT(widget), "button-release-event",
G_CALLBACK(_button_released), NULL);
g_signal_connect(G_OBJECT(widget), "scroll-event",
G_CALLBACK(_scrolled), NULL);
G_CALLBACK(_configure), gui);
for(int i = 2; i; i--, widget = dt_ui_snapshot(darktable.gui->ui))
{
gtk_widget_add_events(widget,
GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK
| GDK_LEAVE_NOTIFY_MASK | darktable.gui->scroll_mask);

g_signal_connect(G_OBJECT(widget), "draw",
G_CALLBACK(_draw), NULL);
g_signal_connect(G_OBJECT(widget), "motion-notify-event",
G_CALLBACK(_mouse_moved), gui);
g_signal_connect(G_OBJECT(widget), "leave-notify-event",
G_CALLBACK(_center_leave), NULL);
g_signal_connect(G_OBJECT(widget), "enter-notify-event",
G_CALLBACK(_center_enter), NULL);
g_signal_connect(G_OBJECT(widget), "button-press-event",
G_CALLBACK(_button_pressed), NULL);
g_signal_connect(G_OBJECT(widget), "button-release-event",
G_CALLBACK(_button_released), NULL);
g_signal_connect(G_OBJECT(widget), "scroll-event",
G_CALLBACK(_scrolled), NULL);
}

// TODO: left, right, top, bottom:
// leave-notify-event
Expand Down Expand Up @@ -1563,9 +1540,7 @@ void dt_gui_gtk_run(dt_gui_gtk_t *gui)
GtkWidget *widget = dt_ui_center(darktable.gui->ui);
GtkAllocation allocation;
gtk_widget_get_allocation(widget, &allocation);
darktable.gui->surface
= dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
allocation.width, allocation.height);

// need to pre-configure views to avoid crash caused by draw coming
// before configure-event
darktable.control->tabborder = 8;
Expand All @@ -1585,12 +1560,6 @@ void dt_gui_gtk_run(dt_gui_gtk_t *gui)
gtk_main();
g_atomic_int_set(&darktable.gui_running, 0);
}

if(darktable.gui->surface)
{
cairo_surface_destroy(darktable.gui->surface);
darktable.gui->surface = NULL;
}
}

// refactored function to read current ppd, because gtk for osx has
Expand Down Expand Up @@ -1859,13 +1828,14 @@ static void _init_main_table(GtkWidget *container)
gtk_widget_set_hexpand(ocda, TRUE);
gtk_widget_set_vexpand(ocda, TRUE);
gtk_widget_set_app_paintable(cda, TRUE);
gtk_widget_set_events(cda,
GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK
| GDK_LEAVE_NOTIFY_MASK | darktable.gui->scroll_mask);
gtk_widget_set_can_focus(cda, TRUE);
gtk_widget_set_visible(cda, TRUE);
gtk_overlay_add_overlay(GTK_OVERLAY(ocda), cda);
darktable.gui->ui->snapshot = gtk_drawing_area_new();
gtk_widget_set_no_show_all(darktable.gui->ui->snapshot, TRUE);
GtkWidget *sidebyside = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(sidebyside), cda, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(sidebyside), darktable.gui->ui->snapshot, TRUE, TRUE, 0);
gtk_box_set_homogeneous(GTK_BOX(sidebyside), TRUE);
gtk_overlay_add_overlay(GTK_OVERLAY(ocda), sidebyside);

gtk_grid_attach(GTK_GRID(centergrid), ocda, 0, 0, 1, 1);
darktable.gui->ui->center = cda;
Expand Down Expand Up @@ -2332,6 +2302,10 @@ GtkWidget *dt_ui_center_base(dt_ui_t *ui)
{
return ui->center_base;
}
GtkWidget *dt_ui_snapshot(dt_ui_t *ui)
{
return ui->snapshot;
}
dt_thumbtable_t *dt_ui_thumbtable(struct dt_ui_t *ui)
{
return ui->thumbtable;
Expand Down
3 changes: 2 additions & 1 deletion src/gui/gtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ typedef struct dt_gui_gtk_t

dt_gui_scrollbars_t scrollbars;

cairo_surface_t *surface;
gboolean drawing_snapshot;

char *last_preset;

Expand Down Expand Up @@ -372,6 +372,7 @@ gboolean dt_ui_panel_ancestor(struct dt_ui_t *ui,
/** \brief get the center drawable widget */
GtkWidget *dt_ui_center(struct dt_ui_t *ui);
GtkWidget *dt_ui_center_base(struct dt_ui_t *ui);
GtkWidget *dt_ui_snapshot(struct dt_ui_t *ui);
/** \brief get the main window widget */
GtkWidget *dt_ui_main_window(struct dt_ui_t *ui);
/** \brief get the thumb table */
Expand Down
Loading
Loading