Implement GtkScrollable in FivView
This fixes rendering and positioning behaviour when dragging on X11, where we aim to use a native GdkWindow.
This commit is contained in:
parent
ca57c2632a
commit
23429d9631
|
@ -198,12 +198,12 @@ relayout(FivBrowser *self, int width)
|
||||||
if (self->vadjustment) {
|
if (self->vadjustment) {
|
||||||
gtk_adjustment_set_lower(self->vadjustment, 0);
|
gtk_adjustment_set_lower(self->vadjustment, 0);
|
||||||
gtk_adjustment_set_upper(self->vadjustment, total_height);
|
gtk_adjustment_set_upper(self->vadjustment, total_height);
|
||||||
gtk_adjustment_set_page_size(
|
|
||||||
self->vadjustment, gtk_widget_get_allocated_height(widget));
|
|
||||||
gtk_adjustment_set_page_increment(
|
|
||||||
self->vadjustment, gtk_widget_get_allocated_height(widget));
|
|
||||||
gtk_adjustment_set_step_increment(self->vadjustment,
|
gtk_adjustment_set_step_increment(self->vadjustment,
|
||||||
self->item_height + self->item_spacing + 2 * self->item_border_y);
|
self->item_height + self->item_spacing + 2 * self->item_border_y);
|
||||||
|
gtk_adjustment_set_page_increment(
|
||||||
|
self->vadjustment, gtk_widget_get_allocated_height(widget) * 0.9);
|
||||||
|
gtk_adjustment_set_page_size(
|
||||||
|
self->vadjustment, gtk_widget_get_allocated_height(widget));
|
||||||
}
|
}
|
||||||
return total_height;
|
return total_height;
|
||||||
}
|
}
|
||||||
|
@ -765,8 +765,7 @@ static void
|
||||||
on_adjustment_value_changed(
|
on_adjustment_value_changed(
|
||||||
G_GNUC_UNUSED GtkAdjustment *adjustment, gpointer user_data)
|
G_GNUC_UNUSED GtkAdjustment *adjustment, gpointer user_data)
|
||||||
{
|
{
|
||||||
FivBrowser *self = FIV_BROWSER(user_data);
|
gtk_widget_queue_draw(GTK_WIDGET(user_data));
|
||||||
gtk_widget_queue_draw(GTK_WIDGET(self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
169
fiv-view.c
169
fiv-view.c
|
@ -50,6 +50,10 @@ fiv_view_command_get_type(void)
|
||||||
|
|
||||||
struct _FivView {
|
struct _FivView {
|
||||||
GtkWidget parent_instance;
|
GtkWidget parent_instance;
|
||||||
|
GtkAdjustment *hadjustment; ///< GtkScrollable boilerplate
|
||||||
|
GtkAdjustment *vadjustment; ///< GtkScrollable boilerplate
|
||||||
|
GtkScrollablePolicy hscroll_policy; ///< GtkScrollable boilerplate
|
||||||
|
GtkScrollablePolicy vscroll_policy; ///< GtkScrollable boilerplate
|
||||||
|
|
||||||
gchar *messages; ///< Image load information
|
gchar *messages; ///< Image load information
|
||||||
gchar *uri; ///< Path to the current image (if any)
|
gchar *uri; ///< Path to the current image (if any)
|
||||||
|
@ -73,7 +77,8 @@ struct _FivView {
|
||||||
gulong frame_update_connection; ///< GdkFrameClock::update
|
gulong frame_update_connection; ///< GdkFrameClock::update
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(FivView, fiv_view, GTK_TYPE_WIDGET)
|
G_DEFINE_TYPE_EXTENDED(FivView, fiv_view, GTK_TYPE_WIDGET, 0,
|
||||||
|
G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL))
|
||||||
|
|
||||||
typedef struct _Dimensions {
|
typedef struct _Dimensions {
|
||||||
double width, height;
|
double width, height;
|
||||||
|
@ -128,7 +133,13 @@ enum {
|
||||||
PROP_CAN_ANIMATE,
|
PROP_CAN_ANIMATE,
|
||||||
PROP_HAS_PREVIOUS_PAGE,
|
PROP_HAS_PREVIOUS_PAGE,
|
||||||
PROP_HAS_NEXT_PAGE,
|
PROP_HAS_NEXT_PAGE,
|
||||||
N_PROPERTIES
|
N_PROPERTIES,
|
||||||
|
|
||||||
|
// These are overriden, we do not register them.
|
||||||
|
PROP_HADJUSTMENT,
|
||||||
|
PROP_VADJUSTMENT,
|
||||||
|
PROP_HSCROLL_POLICY,
|
||||||
|
PROP_VSCROLL_POLICY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *view_properties[N_PROPERTIES];
|
static GParamSpec *view_properties[N_PROPERTIES];
|
||||||
|
@ -141,6 +152,75 @@ enum {
|
||||||
// Globals are, sadly, the canonical way of storing signal numbers.
|
// Globals are, sadly, the canonical way of storing signal numbers.
|
||||||
static guint view_signals[LAST_SIGNAL];
|
static guint view_signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_adjustment_value_changed(
|
||||||
|
G_GNUC_UNUSED GtkAdjustment *adjustment, gpointer user_data)
|
||||||
|
{
|
||||||
|
gtk_widget_queue_draw(GTK_WIDGET(user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dimensions
|
||||||
|
get_surface_dimensions(FivView *self)
|
||||||
|
{
|
||||||
|
if (!self->image)
|
||||||
|
return (Dimensions) {};
|
||||||
|
|
||||||
|
Dimensions dimensions = {};
|
||||||
|
fiv_io_orientation_dimensions(
|
||||||
|
self->page, self->orientation, &dimensions.width, &dimensions.height);
|
||||||
|
return dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_display_dimensions(FivView *self, int *width, int *height)
|
||||||
|
{
|
||||||
|
Dimensions surface_dimensions = get_surface_dimensions(self);
|
||||||
|
*width = ceil(surface_dimensions.width * self->scale);
|
||||||
|
*height = ceil(surface_dimensions.height * self->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_adjustments(FivView *self)
|
||||||
|
{
|
||||||
|
int w = 0, h = 0;
|
||||||
|
get_display_dimensions(self, &w, &h);
|
||||||
|
|
||||||
|
GtkAllocation alloc;
|
||||||
|
gtk_widget_get_allocation(GTK_WIDGET(self), &alloc);
|
||||||
|
|
||||||
|
if (self->hadjustment) {
|
||||||
|
gtk_adjustment_configure(self->hadjustment,
|
||||||
|
gtk_adjustment_get_value(self->hadjustment), 0, w,
|
||||||
|
alloc.width * 0.1, alloc.width * 0.9, alloc.width);
|
||||||
|
}
|
||||||
|
if (self->vadjustment) {
|
||||||
|
gtk_adjustment_configure(self->vadjustment,
|
||||||
|
gtk_adjustment_get_value(self->vadjustment), 0, h,
|
||||||
|
alloc.height * 0.1, alloc.height * 0.9, alloc.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
replace_adjustment(
|
||||||
|
FivView *self, GtkAdjustment **adjustment, GtkAdjustment *replacement)
|
||||||
|
{
|
||||||
|
if (*adjustment == replacement)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (*adjustment) {
|
||||||
|
g_signal_handlers_disconnect_by_func(
|
||||||
|
*adjustment, on_adjustment_value_changed, self);
|
||||||
|
g_clear_object(adjustment);
|
||||||
|
}
|
||||||
|
if (replacement) {
|
||||||
|
*adjustment = g_object_ref(replacement);
|
||||||
|
g_signal_connect(*adjustment, "value-changed",
|
||||||
|
G_CALLBACK(on_adjustment_value_changed), self);
|
||||||
|
update_adjustments(self);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fiv_view_finalize(GObject *gobject)
|
fiv_view_finalize(GObject *gobject)
|
||||||
{
|
{
|
||||||
|
@ -152,6 +232,9 @@ fiv_view_finalize(GObject *gobject)
|
||||||
g_free(self->uri);
|
g_free(self->uri);
|
||||||
g_free(self->messages);
|
g_free(self->messages);
|
||||||
|
|
||||||
|
replace_adjustment(self, &self->hadjustment, NULL);
|
||||||
|
replace_adjustment(self, &self->vadjustment, NULL);
|
||||||
|
|
||||||
G_OBJECT_CLASS(fiv_view_parent_class)->finalize(gobject);
|
G_OBJECT_CLASS(fiv_view_parent_class)->finalize(gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +282,19 @@ fiv_view_get_property(
|
||||||
g_value_set_boolean(value, self->page &&
|
g_value_set_boolean(value, self->page &&
|
||||||
cairo_surface_get_user_data(self->page, &fiv_io_key_page_next));
|
cairo_surface_get_user_data(self->page, &fiv_io_key_page_next));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_HADJUSTMENT:
|
||||||
|
g_value_set_object(value, self->hadjustment);
|
||||||
|
break;
|
||||||
|
case PROP_VADJUSTMENT:
|
||||||
|
g_value_set_object(value, self->vadjustment);
|
||||||
|
break;
|
||||||
|
case PROP_HSCROLL_POLICY:
|
||||||
|
g_value_set_enum(value, self->hscroll_policy);
|
||||||
|
break;
|
||||||
|
case PROP_VSCROLL_POLICY:
|
||||||
|
g_value_set_enum(value, self->vscroll_policy);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
}
|
}
|
||||||
|
@ -230,31 +326,36 @@ fiv_view_set_property(
|
||||||
if (self->enhance != g_value_get_boolean(value))
|
if (self->enhance != g_value_get_boolean(value))
|
||||||
fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_ENHANCE);
|
fiv_view_command(self, FIV_VIEW_COMMAND_TOGGLE_ENHANCE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_HADJUSTMENT:
|
||||||
|
if (replace_adjustment(
|
||||||
|
self, &self->hadjustment, g_value_get_object(value)))
|
||||||
|
g_object_notify_by_pspec(object, pspec);
|
||||||
|
break;
|
||||||
|
case PROP_VADJUSTMENT:
|
||||||
|
if (replace_adjustment(
|
||||||
|
self, &self->vadjustment, g_value_get_object(value)))
|
||||||
|
g_object_notify_by_pspec(object, pspec);
|
||||||
|
break;
|
||||||
|
case PROP_HSCROLL_POLICY:
|
||||||
|
if ((gint) self->hscroll_policy != g_value_get_enum(value)) {
|
||||||
|
self->hscroll_policy = g_value_get_enum(value);
|
||||||
|
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||||
|
g_object_notify_by_pspec(object, pspec);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROP_VSCROLL_POLICY:
|
||||||
|
if ((gint) self->vscroll_policy != g_value_get_enum(value)) {
|
||||||
|
self->vscroll_policy = g_value_get_enum(value);
|
||||||
|
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||||
|
g_object_notify_by_pspec(object, pspec);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dimensions
|
|
||||||
get_surface_dimensions(FivView *self)
|
|
||||||
{
|
|
||||||
if (!self->image)
|
|
||||||
return (Dimensions) {};
|
|
||||||
|
|
||||||
Dimensions dimensions = {};
|
|
||||||
fiv_io_orientation_dimensions(
|
|
||||||
self->page, self->orientation, &dimensions.width, &dimensions.height);
|
|
||||||
return dimensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_display_dimensions(FivView *self, int *width, int *height)
|
|
||||||
{
|
|
||||||
Dimensions surface_dimensions = get_surface_dimensions(self);
|
|
||||||
*width = ceil(surface_dimensions.width * self->scale);
|
|
||||||
*height = ceil(surface_dimensions.height * self->scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fiv_view_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural)
|
fiv_view_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural)
|
||||||
{
|
{
|
||||||
|
@ -308,7 +409,7 @@ fiv_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
|
||||||
|
|
||||||
FivView *self = FIV_VIEW(widget);
|
FivView *self = FIV_VIEW(widget);
|
||||||
if (!self->image || !self->scale_to_fit)
|
if (!self->image || !self->scale_to_fit)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
Dimensions surface_dimensions = get_surface_dimensions(self);
|
Dimensions surface_dimensions = get_surface_dimensions(self);
|
||||||
double scale = 1;
|
double scale = 1;
|
||||||
|
@ -322,6 +423,9 @@ fiv_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
|
||||||
g_object_notify_by_pspec(G_OBJECT(widget), view_properties[PROP_SCALE]);
|
g_object_notify_by_pspec(G_OBJECT(widget), view_properties[PROP_SCALE]);
|
||||||
prescale_page(self);
|
prescale_page(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
update_adjustments(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.freedesktop.org/wiki/OpenIcc/ICC_Profiles_in_X_Specification_0.4
|
// https://www.freedesktop.org/wiki/OpenIcc/ICC_Profiles_in_X_Specification_0.4
|
||||||
|
@ -438,6 +542,10 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr)
|
||||||
|
|
||||||
double x = 0;
|
double x = 0;
|
||||||
double y = 0;
|
double y = 0;
|
||||||
|
if (self->hadjustment)
|
||||||
|
x = -gtk_adjustment_get_value(self->hadjustment);
|
||||||
|
if (self->vadjustment)
|
||||||
|
y = -gtk_adjustment_get_value(self->vadjustment);
|
||||||
if (w < allocation.width)
|
if (w < allocation.width)
|
||||||
x = round((allocation.width - w) / 2.);
|
x = round((allocation.width - w) / 2.);
|
||||||
if (h < allocation.height)
|
if (h < allocation.height)
|
||||||
|
@ -554,8 +662,7 @@ static void
|
||||||
set_scale_to_fit_width(FivView *self)
|
set_scale_to_fit_width(FivView *self)
|
||||||
{
|
{
|
||||||
double w = get_surface_dimensions(self).width;
|
double w = get_surface_dimensions(self).width;
|
||||||
int allocated = gtk_widget_get_allocated_width(
|
int allocated = gtk_widget_get_allocated_width(GTK_WIDGET(self));
|
||||||
gtk_widget_get_parent(GTK_WIDGET(self)));
|
|
||||||
if (ceil(w * self->scale) > allocated)
|
if (ceil(w * self->scale) > allocated)
|
||||||
set_scale(self, allocated / w);
|
set_scale(self, allocated / w);
|
||||||
}
|
}
|
||||||
|
@ -564,8 +671,7 @@ static void
|
||||||
set_scale_to_fit_height(FivView *self)
|
set_scale_to_fit_height(FivView *self)
|
||||||
{
|
{
|
||||||
double h = get_surface_dimensions(self).height;
|
double h = get_surface_dimensions(self).height;
|
||||||
int allocated = gtk_widget_get_allocated_height(
|
int allocated = gtk_widget_get_allocated_height(GTK_WIDGET(self));
|
||||||
gtk_widget_get_parent(GTK_WIDGET(self)));
|
|
||||||
if (ceil(h * self->scale) > allocated)
|
if (ceil(h * self->scale) > allocated)
|
||||||
set_scale(self, allocated / h);
|
set_scale(self, allocated / h);
|
||||||
}
|
}
|
||||||
|
@ -1095,6 +1201,15 @@ fiv_view_class_init(FivViewClass *klass)
|
||||||
g_object_class_install_properties(
|
g_object_class_install_properties(
|
||||||
object_class, N_PROPERTIES, view_properties);
|
object_class, N_PROPERTIES, view_properties);
|
||||||
|
|
||||||
|
g_object_class_override_property(
|
||||||
|
object_class, PROP_HADJUSTMENT, "hadjustment");
|
||||||
|
g_object_class_override_property(
|
||||||
|
object_class, PROP_VADJUSTMENT, "vadjustment");
|
||||||
|
g_object_class_override_property(
|
||||||
|
object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
|
||||||
|
g_object_class_override_property(
|
||||||
|
object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
|
||||||
|
|
||||||
view_signals[COMMAND] =
|
view_signals[COMMAND] =
|
||||||
g_signal_new_class_handler("command", G_TYPE_FROM_CLASS(klass),
|
g_signal_new_class_handler("command", G_TYPE_FROM_CLASS(klass),
|
||||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_CALLBACK(fiv_view_command),
|
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_CALLBACK(fiv_view_command),
|
||||||
|
|
Loading…
Reference in New Issue