Compare commits
	
		
			2 Commits
		
	
	
		
			b97ac26cfb
			...
			c39ac1a9da
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c39ac1a9da | |||
| 085f2d7eef | 
| @ -64,7 +64,7 @@ static const double g_permitted_width_multiplier = 2; | |||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||||||
| 
 | 
 | ||||||
| struct entry { | struct entry { | ||||||
| 	char *filename;                     ///< Absolute path
 | 	char *uri;                          ///< GIO URI
 | ||||||
| 	cairo_surface_t *thumbnail;         ///< Prescaled thumbnail
 | 	cairo_surface_t *thumbnail;         ///< Prescaled thumbnail
 | ||||||
| 	GIcon *icon;                        ///< If no thumbnail, use this icon
 | 	GIcon *icon;                        ///< If no thumbnail, use this icon
 | ||||||
| }; | }; | ||||||
| @ -72,7 +72,7 @@ struct entry { | |||||||
| static void | static void | ||||||
| entry_free(Entry *self) | entry_free(Entry *self) | ||||||
| { | { | ||||||
| 	g_free(self->filename); | 	g_free(self->uri); | ||||||
| 	g_clear_pointer(&self->thumbnail, cairo_surface_destroy); | 	g_clear_pointer(&self->thumbnail, cairo_surface_destroy); | ||||||
| 	g_clear_object(&self->icon); | 	g_clear_object(&self->icon); | ||||||
| } | } | ||||||
| @ -351,15 +351,15 @@ entry_add_thumbnail(gpointer data, gpointer user_data) | |||||||
| 	g_clear_pointer(&self->thumbnail, cairo_surface_destroy); | 	g_clear_pointer(&self->thumbnail, cairo_surface_destroy); | ||||||
| 
 | 
 | ||||||
| 	FastivBrowser *browser = FASTIV_BROWSER(user_data); | 	FastivBrowser *browser = FASTIV_BROWSER(user_data); | ||||||
|  | 	GFile *file = g_file_new_for_uri(self->uri); | ||||||
| 	self->thumbnail = rescale_thumbnail( | 	self->thumbnail = rescale_thumbnail( | ||||||
| 		fastiv_io_lookup_thumbnail(self->filename, browser->item_size), | 		fastiv_io_lookup_thumbnail(file, browser->item_size), | ||||||
| 		browser->item_height); | 		browser->item_height); | ||||||
| 	if (self->thumbnail) | 	if (self->thumbnail) | ||||||
| 		return; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	// Fall back to symbolic icons, though there's only so much we can do
 | 	// Fall back to symbolic icons, though there's only so much we can do
 | ||||||
| 	// in parallel--GTK+ isn't thread-safe.
 | 	// in parallel--GTK+ isn't thread-safe.
 | ||||||
| 	GFile *file = g_file_new_for_path(self->filename); |  | ||||||
| 	GFileInfo *info = g_file_query_info(file, | 	GFileInfo *info = g_file_query_info(file, | ||||||
| 		G_FILE_ATTRIBUTE_STANDARD_NAME | 		G_FILE_ATTRIBUTE_STANDARD_NAME | ||||||
| 		"," G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, | 		"," G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, | ||||||
| @ -371,6 +371,8 @@ entry_add_thumbnail(gpointer data, gpointer user_data) | |||||||
| 			self->icon = g_object_ref(icon); | 			self->icon = g_object_ref(icon); | ||||||
| 		g_object_unref(info); | 		g_object_unref(info); | ||||||
| 	} | 	} | ||||||
|  | out: | ||||||
|  | 	g_object_unref(file); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| @ -521,9 +523,9 @@ destroy_widget_idle_source_func(GtkWidget *widget) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| show_context_menu(GtkWidget *widget, const char *filename) | show_context_menu(GtkWidget *widget, const char *uri) | ||||||
| { | { | ||||||
| 	GFile *file = g_file_new_for_path(filename); | 	GFile *file = g_file_new_for_uri(uri); | ||||||
| 	GFileInfo *info = g_file_query_info(file, | 	GFileInfo *info = g_file_query_info(file, | ||||||
| 		G_FILE_ATTRIBUTE_STANDARD_NAME | 		G_FILE_ATTRIBUTE_STANDARD_NAME | ||||||
| 		"," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, | 		"," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, | ||||||
| @ -778,8 +780,10 @@ fastiv_browser_draw(GtkWidget *widget, cairo_t *cr) | |||||||
| static gboolean | static gboolean | ||||||
| open_entry(GtkWidget *self, const Entry *entry, gboolean new_window) | open_entry(GtkWidget *self, const Entry *entry, gboolean new_window) | ||||||
| { | { | ||||||
| 	g_signal_emit(self, browser_signals[ITEM_ACTIVATED], 0, entry->filename, | 	GFile *location = g_file_new_for_uri(entry->uri); | ||||||
|  | 	g_signal_emit(self, browser_signals[ITEM_ACTIVATED], 0, location, | ||||||
| 		new_window ? GTK_PLACES_OPEN_NEW_WINDOW : GTK_PLACES_OPEN_NORMAL); | 		new_window ? GTK_PLACES_OPEN_NEW_WINDOW : GTK_PLACES_OPEN_NORMAL); | ||||||
|  | 	g_object_unref(location); | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -817,7 +821,7 @@ fastiv_browser_button_press_event(GtkWidget *widget, GdkEventButton *event) | |||||||
| 		// On X11, after closing the menu, the pointer otherwise remains,
 | 		// On X11, after closing the menu, the pointer otherwise remains,
 | ||||||
| 		// no matter what its new location is.
 | 		// no matter what its new location is.
 | ||||||
| 		gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); | 		gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); | ||||||
| 		show_context_menu(widget, entry->filename); | 		show_context_menu(widget, entry->uri); | ||||||
| 		return TRUE; | 		return TRUE; | ||||||
| 	default: | 	default: | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| @ -871,7 +875,7 @@ fastiv_browser_query_tooltip(GtkWidget *widget, gint x, gint y, | |||||||
| 	if (!entry) | 	if (!entry) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 
 | 
 | ||||||
| 	GFile *file = g_file_new_for_path(entry->filename); | 	GFile *file = g_file_new_for_uri(entry->uri); | ||||||
| 	GFileInfo *info = g_file_query_info(file, | 	GFileInfo *info = g_file_query_info(file, | ||||||
| 		G_FILE_ATTRIBUTE_STANDARD_NAME | 		G_FILE_ATTRIBUTE_STANDARD_NAME | ||||||
| 		"," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, | 		"," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, | ||||||
| @ -967,7 +971,7 @@ fastiv_browser_class_init(FastivBrowserClass *klass) | |||||||
| 
 | 
 | ||||||
| 	browser_signals[ITEM_ACTIVATED] = g_signal_new("item-activated", | 	browser_signals[ITEM_ACTIVATED] = g_signal_new("item-activated", | ||||||
| 		G_TYPE_FROM_CLASS(klass), 0, 0, NULL, NULL, NULL, | 		G_TYPE_FROM_CLASS(klass), 0, 0, NULL, NULL, NULL, | ||||||
| 		G_TYPE_NONE, 2, G_TYPE_STRING, GTK_TYPE_PLACES_OPEN_FLAGS); | 		G_TYPE_NONE, 2, G_TYPE_FILE, GTK_TYPE_PLACES_OPEN_FLAGS); | ||||||
| 
 | 
 | ||||||
| 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); | 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); | ||||||
| 	widget_class->get_request_mode = fastiv_browser_get_request_mode; | 	widget_class->get_request_mode = fastiv_browser_get_request_mode; | ||||||
| @ -1020,8 +1024,8 @@ entry_compare(gconstpointer a, gconstpointer b) | |||||||
| { | { | ||||||
| 	const Entry *entry1 = a; | 	const Entry *entry1 = a; | ||||||
| 	const Entry *entry2 = b; | 	const Entry *entry2 = b; | ||||||
| 	GFile *location1 = g_file_new_for_path(entry1->filename); | 	GFile *location1 = g_file_new_for_uri(entry1->uri); | ||||||
| 	GFile *location2 = g_file_new_for_path(entry2->filename); | 	GFile *location2 = g_file_new_for_uri(entry2->uri); | ||||||
| 	gint result = fastiv_io_filecmp(location1, location2); | 	gint result = fastiv_io_filecmp(location1, location2); | ||||||
| 	g_object_unref(location1); | 	g_object_unref(location1); | ||||||
| 	g_object_unref(location2); | 	g_object_unref(location2); | ||||||
| @ -1055,7 +1059,7 @@ fastiv_browser_load( | |||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		g_array_append_val(self->entries, | 		g_array_append_val(self->entries, | ||||||
| 			((Entry) {.thumbnail = NULL, .filename = g_file_get_path(child)})); | 			((Entry) {.thumbnail = NULL, .uri = g_file_get_uri(child)})); | ||||||
| 	} | 	} | ||||||
| 	g_object_unref(enumerator); | 	g_object_unref(enumerator); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										84
									
								
								fastiv-io.c
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								fastiv-io.c
									
									
									
									
									
								
							| @ -955,39 +955,58 @@ open_xcursor(const gchar *data, gsize len, GError **error) | |||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Let's just arrange the pixel data in a recording surface.
 | 	// Interpret cursors as animated pages.
 | ||||||
| 	static cairo_user_data_key_t key = {}; | 	cairo_surface_t *pages = NULL, *frames_head = NULL, *frames_tail = NULL; | ||||||
| 	cairo_surface_t *recording = |  | ||||||
| 		cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA, NULL); |  | ||||||
| 	cairo_surface_set_user_data( |  | ||||||
| 		recording, &key, images, (cairo_destroy_func_t) XcursorImagesDestroy); |  | ||||||
| 	cairo_t *cr = cairo_create(recording); |  | ||||||
| 
 | 
 | ||||||
| 	// Unpack horizontally by animation, vertically by size.
 | 	// XXX: Assuming that all "nominal sizes" have the same dimensions.
 | ||||||
| 	XcursorDim last_nominal = -1; | 	XcursorDim last_nominal = -1; | ||||||
| 	int x = 0, y = 0, row_height = 0; |  | ||||||
| 	for (int i = 0; i < images->nimage; i++) { | 	for (int i = 0; i < images->nimage; i++) { | ||||||
| 		XcursorImage *image = images->images[i]; | 		XcursorImage *image = images->images[i]; | ||||||
| 		if (image->size != last_nominal) { |  | ||||||
| 			x = 0; |  | ||||||
| 			y += row_height; |  | ||||||
| 			row_height = 0; |  | ||||||
| 			last_nominal = image->size; |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		// The library automatically byte swaps in _XcursorReadImage().
 | 		// The library automatically byte swaps in _XcursorReadImage().
 | ||||||
| 		cairo_surface_t *source = cairo_image_surface_create_for_data( | 		cairo_surface_t *surface = cairo_image_surface_create_for_data( | ||||||
| 			(unsigned char *) image->pixels, CAIRO_FORMAT_ARGB32, | 			(unsigned char *) image->pixels, CAIRO_FORMAT_ARGB32, | ||||||
| 			image->width, image->height, image->width * sizeof *image->pixels); | 			image->width, image->height, image->width * sizeof *image->pixels); | ||||||
| 		cairo_set_source_surface(cr, source, x, y); | 		cairo_surface_set_user_data(surface, &fastiv_io_key_frame_duration, | ||||||
| 		cairo_surface_destroy(source); | 			(void *) (intptr_t) image->delay, NULL); | ||||||
| 		cairo_paint(cr); |  | ||||||
| 
 | 
 | ||||||
| 		x += image->width; | 		if (pages && image->size == last_nominal) { | ||||||
| 		row_height = MAX(row_height, (int) image->height); | 			cairo_surface_set_user_data(surface, | ||||||
|  | 				&fastiv_io_key_frame_previous, frames_tail, NULL); | ||||||
|  | 			cairo_surface_set_user_data(frames_tail, | ||||||
|  | 				&fastiv_io_key_frame_next, surface, | ||||||
|  | 				(cairo_destroy_func_t) cairo_surface_destroy); | ||||||
|  | 		} else if (frames_head) { | ||||||
|  | 			cairo_surface_set_user_data(frames_head, | ||||||
|  | 				&fastiv_io_key_frame_previous, frames_tail, NULL); | ||||||
|  | 
 | ||||||
|  | 			cairo_surface_set_user_data(frames_head, | ||||||
|  | 				&fastiv_io_key_page_next, surface, | ||||||
|  | 				(cairo_destroy_func_t) cairo_surface_destroy); | ||||||
|  | 			cairo_surface_set_user_data(surface, | ||||||
|  | 				&fastiv_io_key_page_previous, frames_head, NULL); | ||||||
|  | 			frames_head = surface; | ||||||
|  | 		} else { | ||||||
|  | 			pages = frames_head = surface; | ||||||
| 		} | 		} | ||||||
| 	cairo_destroy(cr); | 
 | ||||||
| 	return recording; | 		frames_tail = surface; | ||||||
|  | 		last_nominal = image->size; | ||||||
|  | 	} | ||||||
|  | 	if (!pages) { | ||||||
|  | 		XcursorImagesDestroy(images); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Wrap around animations in the last page.
 | ||||||
|  | 	cairo_surface_set_user_data( | ||||||
|  | 		frames_head, &fastiv_io_key_frame_previous, frames_tail, NULL); | ||||||
|  | 
 | ||||||
|  | 	// There is no need to copy data, assign it to the surface.
 | ||||||
|  | 	static cairo_user_data_key_t key = {}; | ||||||
|  | 	cairo_surface_set_user_data( | ||||||
|  | 		pages, &key, images, (cairo_destroy_func_t) XcursorImagesDestroy); | ||||||
|  | 	return pages; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif  // HAVE_XCURSOR --------------------------------------------------------
 | #endif  // HAVE_XCURSOR --------------------------------------------------------
 | ||||||
| @ -1041,6 +1060,9 @@ cairo_user_data_key_t fastiv_io_key_frame_previous; | |||||||
| cairo_user_data_key_t fastiv_io_key_frame_duration; | cairo_user_data_key_t fastiv_io_key_frame_duration; | ||||||
| cairo_user_data_key_t fastiv_io_key_loops; | cairo_user_data_key_t fastiv_io_key_loops; | ||||||
| 
 | 
 | ||||||
|  | cairo_user_data_key_t fastiv_io_key_page_next; | ||||||
|  | cairo_user_data_key_t fastiv_io_key_page_previous; | ||||||
|  | 
 | ||||||
| cairo_surface_t * | cairo_surface_t * | ||||||
| fastiv_io_open(const gchar *path, GError **error) | fastiv_io_open(const gchar *path, GError **error) | ||||||
| { | { | ||||||
| @ -1365,21 +1387,23 @@ fail_init: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| cairo_surface_t * | cairo_surface_t * | ||||||
| fastiv_io_lookup_thumbnail(const gchar *target, FastivIoThumbnailSize size) | fastiv_io_lookup_thumbnail(GFile *target, FastivIoThumbnailSize size) | ||||||
| { | { | ||||||
| 	g_return_val_if_fail(size >= FASTIV_IO_THUMBNAIL_SIZE_MIN && | 	g_return_val_if_fail(size >= FASTIV_IO_THUMBNAIL_SIZE_MIN && | ||||||
| 		size <= FASTIV_IO_THUMBNAIL_SIZE_MAX, NULL); | 		size <= FASTIV_IO_THUMBNAIL_SIZE_MAX, NULL); | ||||||
| 
 | 
 | ||||||
| 	GStatBuf st; | 	// Local files only, at least for now.
 | ||||||
| 	if (g_stat(target, &st)) | 	gchar *path = g_file_get_path(target); | ||||||
|  | 	if (!path) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	// TODO(p): Consider making the `target` an absolute path, if it isn't.
 | 	GStatBuf st = {}; | ||||||
| 	// Or maybe let it fail, and document the requirement.
 | 	int err = g_stat(path, &st); | ||||||
| 	gchar *uri = g_filename_to_uri(target, NULL, NULL); | 	g_free(path); | ||||||
| 	if (!uri) | 	if (err) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
|  | 	gchar *uri = g_file_get_uri(target); | ||||||
| 	gchar *sum = g_compute_checksum_for_string(G_CHECKSUM_MD5, uri, -1); | 	gchar *sum = g_compute_checksum_for_string(G_CHECKSUM_MD5, uri, -1); | ||||||
| 	gchar *cache_dir = get_xdg_home_dir("XDG_CACHE_HOME", ".cache"); | 	gchar *cache_dir = get_xdg_home_dir("XDG_CACHE_HOME", ".cache"); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -46,6 +46,13 @@ extern cairo_user_data_key_t fastiv_io_key_frame_duration; | |||||||
| /// How many times to repeat the animation, or zero for +inf, as a uintptr_t.
 | /// How many times to repeat the animation, or zero for +inf, as a uintptr_t.
 | ||||||
| extern cairo_user_data_key_t fastiv_io_key_loops; | extern cairo_user_data_key_t fastiv_io_key_loops; | ||||||
| 
 | 
 | ||||||
|  | /// The first frame of the next page, as a surface, in a chain.
 | ||||||
|  | /// There is no wrap-around.
 | ||||||
|  | extern cairo_user_data_key_t fastiv_io_key_page_next; | ||||||
|  | /// The first frame of the previous page, as a surface, in a chain.
 | ||||||
|  | /// There is no wrap-around. This is a weak pointer.
 | ||||||
|  | extern cairo_user_data_key_t fastiv_io_key_page_previous; | ||||||
|  | 
 | ||||||
| cairo_surface_t *fastiv_io_open(const gchar *path, GError **error); | cairo_surface_t *fastiv_io_open(const gchar *path, GError **error); | ||||||
| cairo_surface_t *fastiv_io_open_from_data( | cairo_surface_t *fastiv_io_open_from_data( | ||||||
| 	const char *data, size_t len, const gchar *path, GError **error); | 	const char *data, size_t len, const gchar *path, GError **error); | ||||||
| @ -99,4 +106,4 @@ extern FastivIoThumbnailSizeInfo | |||||||
| 	fastiv_io_thumbnail_sizes[FASTIV_IO_THUMBNAIL_SIZE_COUNT]; | 	fastiv_io_thumbnail_sizes[FASTIV_IO_THUMBNAIL_SIZE_COUNT]; | ||||||
| 
 | 
 | ||||||
| cairo_surface_t *fastiv_io_lookup_thumbnail( | cairo_surface_t *fastiv_io_lookup_thumbnail( | ||||||
| 	const gchar *target, FastivIoThumbnailSize size); | 	GFile *target, FastivIoThumbnailSize size); | ||||||
|  | |||||||
| @ -31,8 +31,9 @@ | |||||||
| 
 | 
 | ||||||
| struct _FastivView { | struct _FastivView { | ||||||
| 	GtkWidget parent_instance; | 	GtkWidget parent_instance; | ||||||
| 	cairo_surface_t *surface;           ///< The loaded image (sequence)
 | 	cairo_surface_t *image;             ///< The loaded image (sequence)
 | ||||||
| 	cairo_surface_t *frame;             ///< Current frame within, unreferenced
 | 	cairo_surface_t *page;              ///< Current page within image, weak
 | ||||||
|  | 	cairo_surface_t *frame;             ///< Current frame within page, weak
 | ||||||
| 	FastivIoOrientation orientation;    ///< Current orientation
 | 	FastivIoOrientation orientation;    ///< Current orientation
 | ||||||
| 	bool filter; | 	bool filter; | ||||||
| 	bool scale_to_fit; | 	bool scale_to_fit; | ||||||
| @ -89,7 +90,7 @@ static void | |||||||
| fastiv_view_finalize(GObject *gobject) | fastiv_view_finalize(GObject *gobject) | ||||||
| { | { | ||||||
| 	FastivView *self = FASTIV_VIEW(gobject); | 	FastivView *self = FASTIV_VIEW(gobject); | ||||||
| 	cairo_surface_destroy(self->surface); | 	cairo_surface_destroy(self->image); | ||||||
| 
 | 
 | ||||||
| 	G_OBJECT_CLASS(fastiv_view_parent_class)->finalize(gobject); | 	G_OBJECT_CLASS(fastiv_view_parent_class)->finalize(gobject); | ||||||
| } | } | ||||||
| @ -115,28 +116,28 @@ static void | |||||||
| get_surface_dimensions(FastivView *self, double *width, double *height) | get_surface_dimensions(FastivView *self, double *width, double *height) | ||||||
| { | { | ||||||
| 	*width = *height = 0; | 	*width = *height = 0; | ||||||
| 	if (!self->surface) | 	if (!self->image) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	cairo_rectangle_t extents = {}; | 	cairo_rectangle_t extents = {}; | ||||||
| 	switch (cairo_surface_get_type(self->surface)) { | 	switch (cairo_surface_get_type(self->page)) { | ||||||
| 	case CAIRO_SURFACE_TYPE_IMAGE: | 	case CAIRO_SURFACE_TYPE_IMAGE: | ||||||
| 		switch (self->orientation) { | 		switch (self->orientation) { | ||||||
| 		case FastivIoOrientation90: | 		case FastivIoOrientation90: | ||||||
| 		case FastivIoOrientationMirror90: | 		case FastivIoOrientationMirror90: | ||||||
| 		case FastivIoOrientation270: | 		case FastivIoOrientation270: | ||||||
| 		case FastivIoOrientationMirror270: | 		case FastivIoOrientationMirror270: | ||||||
| 			*width = cairo_image_surface_get_height(self->surface); | 			*width = cairo_image_surface_get_height(self->page); | ||||||
| 			*height = cairo_image_surface_get_width(self->surface); | 			*height = cairo_image_surface_get_width(self->page); | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			*width = cairo_image_surface_get_width(self->surface); | 			*width = cairo_image_surface_get_width(self->page); | ||||||
| 			*height = cairo_image_surface_get_height(self->surface); | 			*height = cairo_image_surface_get_height(self->page); | ||||||
| 		} | 		} | ||||||
| 		return; | 		return; | ||||||
| 	case CAIRO_SURFACE_TYPE_RECORDING: | 	case CAIRO_SURFACE_TYPE_RECORDING: | ||||||
| 		if (!cairo_recording_surface_get_extents(self->surface, &extents)) { | 		if (!cairo_recording_surface_get_extents(self->page, &extents)) { | ||||||
| 			cairo_recording_surface_ink_extents(self->surface, | 			cairo_recording_surface_ink_extents(self->page, | ||||||
| 				&extents.x, &extents.y, &extents.width, &extents.height); | 				&extents.x, &extents.y, &extents.width, &extents.height); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -198,7 +199,7 @@ fastiv_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation) | |||||||
| 		->size_allocate(widget, allocation); | 		->size_allocate(widget, allocation); | ||||||
| 
 | 
 | ||||||
| 	FastivView *self = FASTIV_VIEW(widget); | 	FastivView *self = FASTIV_VIEW(widget); | ||||||
| 	if (!self->surface || !self->scale_to_fit) | 	if (!self->image || !self->scale_to_fit) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	double w, h; | 	double w, h; | ||||||
| @ -271,7 +272,7 @@ fastiv_view_draw(GtkWidget *widget, cairo_t *cr) | |||||||
| 		allocation.width, allocation.height); | 		allocation.width, allocation.height); | ||||||
| 
 | 
 | ||||||
| 	FastivView *self = FASTIV_VIEW(widget); | 	FastivView *self = FASTIV_VIEW(widget); | ||||||
| 	if (!self->surface || | 	if (!self->image || | ||||||
| 		!gtk_cairo_should_draw_window(cr, gtk_widget_get_window(widget))) | 		!gtk_cairo_should_draw_window(cr, gtk_widget_get_window(widget))) | ||||||
| 		return TRUE; | 		return TRUE; | ||||||
| 
 | 
 | ||||||
| @ -408,7 +409,7 @@ static gboolean | |||||||
| fastiv_view_scroll_event(GtkWidget *widget, GdkEventScroll *event) | fastiv_view_scroll_event(GtkWidget *widget, GdkEventScroll *event) | ||||||
| { | { | ||||||
| 	FastivView *self = FASTIV_VIEW(widget); | 	FastivView *self = FASTIV_VIEW(widget); | ||||||
| 	if (!self->surface) | 	if (!self->image) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	if (event->state & gtk_accelerator_get_default_mod_mask()) | 	if (event->state & gtk_accelerator_get_default_mod_mask()) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| @ -431,7 +432,7 @@ fastiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event) | |||||||
| 	FastivView *self = FASTIV_VIEW(widget); | 	FastivView *self = FASTIV_VIEW(widget); | ||||||
| 	if (event->state & ~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask()) | 	if (event->state & ~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask()) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	if (!self->surface) | 	if (!self->image) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 
 | 
 | ||||||
| 	switch (event->keyval) { | 	switch (event->keyval) { | ||||||
| @ -462,16 +463,33 @@ fastiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event) | |||||||
| 		gtk_widget_queue_resize(widget); | 		gtk_widget_queue_resize(widget); | ||||||
| 		return TRUE; | 		return TRUE; | ||||||
| 
 | 
 | ||||||
| 	case GDK_KEY_bracketleft: | 	case GDK_KEY_bracketleft: { | ||||||
|  | 		cairo_surface_t *page = cairo_surface_get_user_data( | ||||||
|  | 			self->page, &fastiv_io_key_page_previous); | ||||||
|  | 		if (page) | ||||||
|  | 			self->frame = self->page = page; | ||||||
|  | 		gtk_widget_queue_resize(widget); | ||||||
|  | 		return TRUE; | ||||||
|  | 	} | ||||||
|  | 	case GDK_KEY_bracketright: { | ||||||
|  | 		cairo_surface_t *page = cairo_surface_get_user_data( | ||||||
|  | 			self->page, &fastiv_io_key_page_next); | ||||||
|  | 		if (page) | ||||||
|  | 			self->frame = self->page = page; | ||||||
|  | 		gtk_widget_queue_resize(widget); | ||||||
|  | 		return TRUE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	case GDK_KEY_braceleft: | ||||||
| 		if (!(self->frame = cairo_surface_get_user_data( | 		if (!(self->frame = cairo_surface_get_user_data( | ||||||
| 				self->frame, &fastiv_io_key_frame_previous))) | 				self->frame, &fastiv_io_key_frame_previous))) | ||||||
| 			self->frame = self->surface; | 			self->frame = self->page; | ||||||
| 		gtk_widget_queue_draw(widget); | 		gtk_widget_queue_draw(widget); | ||||||
| 		return TRUE; | 		return TRUE; | ||||||
| 	case GDK_KEY_bracketright: | 	case GDK_KEY_braceright: | ||||||
| 		if (!(self->frame = cairo_surface_get_user_data( | 		if (!(self->frame = cairo_surface_get_user_data( | ||||||
| 				self->frame, &fastiv_io_key_frame_next))) | 				self->frame, &fastiv_io_key_frame_next))) | ||||||
| 			self->frame = self->surface; | 			self->frame = self->page; | ||||||
| 		gtk_widget_queue_draw(widget); | 		gtk_widget_queue_draw(widget); | ||||||
| 		return TRUE; | 		return TRUE; | ||||||
| 	} | 	} | ||||||
| @ -527,14 +545,15 @@ fastiv_view_open(FastivView *self, const gchar *path, GError **error) | |||||||
| 	cairo_surface_t *surface = fastiv_io_open(path, error); | 	cairo_surface_t *surface = fastiv_io_open(path, error); | ||||||
| 	if (!surface) | 	if (!surface) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	if (self->surface) | 	if (self->image) | ||||||
| 		cairo_surface_destroy(self->surface); | 		cairo_surface_destroy(self->image); | ||||||
| 
 | 
 | ||||||
| 	self->frame = self->surface = surface; | 	self->frame = self->page = self->image = surface; | ||||||
| 	set_scale_to_fit(self, true); | 	set_scale_to_fit(self, true); | ||||||
| 
 | 
 | ||||||
|  | 	// TODO(p): This is actually per-page.
 | ||||||
| 	if ((self->orientation = (uintptr_t) cairo_surface_get_user_data( | 	if ((self->orientation = (uintptr_t) cairo_surface_get_user_data( | ||||||
| 			 self->surface, &fastiv_io_key_orientation)) == | 			 self->image, &fastiv_io_key_orientation)) == | ||||||
| 		FastivIoOrientationUnknown) | 		FastivIoOrientationUnknown) | ||||||
| 		self->orientation = FastivIoOrientation0; | 		self->orientation = FastivIoOrientation0; | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								fastiv.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								fastiv.c
									
									
									
									
									
								
							| @ -311,13 +311,17 @@ spawn_path(const char *path) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| on_item_activated(G_GNUC_UNUSED FastivBrowser *browser, const char *path, | on_item_activated(G_GNUC_UNUSED FastivBrowser *browser, GFile *location, | ||||||
| 	GtkPlacesOpenFlags flags, G_GNUC_UNUSED gpointer data) | 	GtkPlacesOpenFlags flags, G_GNUC_UNUSED gpointer data) | ||||||
| { | { | ||||||
|  | 	gchar *path = g_file_get_path(location); | ||||||
|  | 	if (path) { | ||||||
| 		if (flags == GTK_PLACES_OPEN_NEW_WINDOW) | 		if (flags == GTK_PLACES_OPEN_NEW_WINDOW) | ||||||
| 			spawn_path(path); | 			spawn_path(path); | ||||||
| 		else | 		else | ||||||
| 			open(path); | 			open(path); | ||||||
|  | 		g_free(path); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static gboolean | static gboolean | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user