Fix #262: double click and fullscreen
[geeqie.git] / src / image.c
index 826e920..e04037f 100644 (file)
@@ -1,16 +1,24 @@
 /*
- * Geeqie
- * (C) 2006 John Ellis
- * Copyright (C) 2008 - 2012 The Geeqie Team
+ * Copyright (C) 2006 John Ellis
+ * Copyright (C) 2008 - 2016 The Geeqie Team
  *
  * Author: John Ellis
  *
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-
 #include "main.h"
 #include "image.h"
 
@@ -48,6 +56,10 @@ static void image_cache_set(ImageWindow *imd, FileData *fd);
 static void image_click_cb(PixbufRenderer *pr, GdkEventButton *event, gpointer data)
 {
        ImageWindow *imd = data;
+       if (!options->image_lm_click_nav && event->button == MOUSE_BUTTON_MIDDLE)
+               {
+               imd->mouse_wheel_mode = !imd->mouse_wheel_mode;
+               }
 
        if (imd->func_button)
                {
@@ -55,7 +67,7 @@ static void image_click_cb(PixbufRenderer *pr, GdkEventButton *event, gpointer d
                }
 }
 
-static void image_drag_cb(PixbufRenderer *pr, GdkEventButton *event, gpointer data)
+static void image_drag_cb(PixbufRenderer *pr, GdkEventMotion *event, gpointer data)
 {
        ImageWindow *imd = data;
        gint width, height;
@@ -220,7 +232,7 @@ static gboolean image_post_process_color(ImageWindow *imd, gint start_row, gbool
            imd->color_profile_input <  COLOR_PROFILE_FILE + COLOR_PROFILE_INPUTS)
                {
                const gchar *file = options->color_profile.input_file[imd->color_profile_input - COLOR_PROFILE_FILE];
-       
+
                if (!is_readable_file(file)) return FALSE;
 
                input_type = COLOR_PROFILE_FILE;
@@ -259,7 +271,7 @@ static gboolean image_post_process_color(ImageWindow *imd, gint start_row, gbool
        imd->color_profile_from_image = COLOR_PROFILE_NONE;
 
        exif = exif_read_fd(imd->image_fd);
-               
+
        if (exif)
                {
                profile = exif_get_color_profile(exif, &profile_len);
@@ -320,7 +332,7 @@ static gboolean image_post_process_color(ImageWindow *imd, gint start_row, gbool
 
                exif_free_fd(imd->image_fd, exif);
                }
-       
+
 
        if (profile)
                {
@@ -348,13 +360,13 @@ static gboolean image_post_process_color(ImageWindow *imd, gint start_row, gbool
                }
 
        image_update_util(imd);
-       
+
        if (screen_profile)
                {
                g_free(screen_profile);
                screen_profile = NULL;
                }
-       
+
        return !!cm;
 }
 
@@ -367,7 +379,7 @@ static void image_post_process_tile_color_cb(PixbufRenderer *pr, GdkPixbuf **pix
 
 }
 
-void image_alter_orientation(ImageWindow *imd, AlterType type)
+void image_alter_orientation(ImageWindow *imd, FileData *fd_n, AlterType type)
 {
        static const gint rotate_90[]    = {1,   6, 7, 8, 5, 2, 3, 4, 1};
        static const gint rotate_90_cc[] = {1,   8, 5, 6, 7, 4, 1, 2, 3};
@@ -375,37 +387,49 @@ void image_alter_orientation(ImageWindow *imd, AlterType type)
        static const gint mirror[]       = {1,   2, 1, 4, 3, 6, 5, 8, 7};
        static const gint flip[]         = {1,   4, 3, 2, 1, 8, 7, 6, 5};
 
+       gint orientation;
 
-       if (!imd || !imd->pr || !imd->image_fd) return;
+       if (!imd || !imd->pr || !imd->image_fd || !fd_n) return;
 
-       if (imd->orientation < 1 || imd->orientation > 8) imd->orientation = 1;
+       orientation = EXIF_ORIENTATION_TOP_LEFT;
+       {
+       if (fd_n->user_orientation)
+               {
+               orientation = fd_n->user_orientation;
+               }
+       else
+               if (options->metadata.write_orientation)
+                       {
+                       orientation = metadata_read_int(fd_n, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT);
+                       }
+       }
 
        switch (type)
                {
                case ALTER_ROTATE_90:
-                       imd->orientation = rotate_90[imd->orientation];
+                       orientation = rotate_90[orientation];
                        break;
                case ALTER_ROTATE_90_CC:
-                       imd->orientation = rotate_90_cc[imd->orientation];
+                       orientation = rotate_90_cc[orientation];
                        break;
                case ALTER_ROTATE_180:
-                       imd->orientation = rotate_180[imd->orientation];
+                       orientation = rotate_180[orientation];
                        break;
                case ALTER_MIRROR:
-                       imd->orientation = mirror[imd->orientation];
+                       orientation = mirror[orientation];
                        break;
                case ALTER_FLIP:
-                       imd->orientation = flip[imd->orientation];
+                       orientation = flip[orientation];
                        break;
                case ALTER_NONE:
-                       imd->orientation = imd->image_fd->exif_orientation ? imd->image_fd->exif_orientation : 1;
+                       orientation = fd_n->exif_orientation ? fd_n->exif_orientation : 1;
                        break;
                default:
                        return;
                        break;
                }
 
-       if (imd->orientation != imd->image_fd->exif_orientation ? imd->image_fd->exif_orientation : 1)
+       if (orientation != (fd_n->exif_orientation ? fd_n->exif_orientation : 1))
                {
                if (!options->metadata.write_orientation)
                        {
@@ -414,29 +438,33 @@ void image_alter_orientation(ImageWindow *imd, AlterType type)
                           we must however handle switching metadata.write_orientation on and off, therefore
                           we just disable referencing new fd's, not unreferencing the old ones
                        */
-                       if (imd->image_fd->user_orientation == 0) file_data_ref(imd->image_fd);
-                       imd->image_fd->user_orientation = imd->orientation;
+                       if (fd_n->user_orientation == 0) file_data_ref(fd_n);
+                       fd_n->user_orientation = orientation;
                        }
                }
        else
                {
-               if (imd->image_fd->user_orientation != 0) file_data_unref(imd->image_fd);
-               imd->image_fd->user_orientation = 0;
+               if (fd_n->user_orientation != 0) file_data_unref(fd_n);
+               fd_n->user_orientation = 0;
                }
 
        if (options->metadata.write_orientation)
                {
                if (type == ALTER_NONE)
                        {
-                       metadata_write_revert(imd->image_fd, ORIENTATION_KEY);
+                       metadata_write_revert(fd_n, ORIENTATION_KEY);
                        }
                else
                        {
-                       metadata_write_int(imd->image_fd, ORIENTATION_KEY, imd->orientation);
+                       metadata_write_int(fd_n, ORIENTATION_KEY, orientation);
                        }
                }
 
-       pixbuf_renderer_set_orientation((PixbufRenderer *)imd->pr, imd->orientation);
+       if (imd->image_fd == fd_n && !(options->metadata.write_orientation && !options->image.exif_rotate_enable))
+               {
+               imd->orientation = orientation;
+               pixbuf_renderer_set_orientation((PixbufRenderer *)imd->pr, orientation);
+               }
 }
 
 void image_set_desaturate(ImageWindow *imd, gboolean desaturate)
@@ -475,6 +503,8 @@ static void image_read_ahead_done_cb(ImageLoader *il, gpointer data)
 {
        ImageWindow *imd = data;
 
+       if (!imd->read_ahead_fd || !imd->read_ahead_il) return;
+
        DEBUG_1("%s read ahead done for :%s", get_exec_time(), imd->read_ahead_fd->path);
 
        if (!imd->read_ahead_fd->pixbuf)
@@ -509,7 +539,7 @@ static void image_read_ahead_start(ImageWindow *imd)
        DEBUG_1("%s read ahead started for :%s", get_exec_time(), imd->read_ahead_fd->path);
 
        imd->read_ahead_il = image_loader_new(imd->read_ahead_fd);
-       
+
        image_loader_delay_area_ready(imd->read_ahead_il, TRUE); /* we will need the area_ready signals later */
 
        g_signal_connect(G_OBJECT(imd->read_ahead_il), "error", (GCallback)image_read_ahead_error_cb, imd);
@@ -573,7 +603,7 @@ static gint image_cache_get(ImageWindow *imd)
                g_assert(imd->image_fd->pixbuf);
                image_change_pixbuf(imd, imd->image_fd->pixbuf, image_zoom_get(imd), FALSE);
                }
-       
+
 //     file_cache_dump(image_get_cache());
        return success;
 }
@@ -832,7 +862,7 @@ static void image_change_complete(ImageWindow *imd, gdouble zoom)
                if (is_readable_file(imd->image_fd->path))
                        {
                        PixbufRenderer *pr;
-       
+
                        pr = PIXBUF_RENDERER(imd->pr);
                        pr->zoom = zoom;        /* store the zoom, needed by the loader */
 
@@ -845,7 +875,7 @@ static void image_change_complete(ImageWindow *imd, gdouble zoom)
                if (imd->unknown == TRUE)
                        {
                        GdkPixbuf *pixbuf;
-       
+
                        pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
                        image_change_pixbuf(imd, pixbuf, zoom, FALSE);
                        g_object_unref(pixbuf);
@@ -967,7 +997,7 @@ void image_set_button_func(ImageWindow *imd,
 }
 
 void image_set_drag_func(ImageWindow *imd,
-                          void (*func)(ImageWindow *, GdkEventButton *event, gdouble dx, gdouble dy, gpointer),
+                          void (*func)(ImageWindow *, GdkEventMotion *event, gdouble dx, gdouble dy, gpointer),
                           gpointer data)
 {
        imd->func_drag = func;
@@ -1059,7 +1089,8 @@ void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gboo
           a notification that removes the pixbuf from cache and unrefs it. Therefore we must ref it
           here before it is taken over by the renderer. */
        if (pixbuf) g_object_ref(pixbuf);
-       
+
+       imd->orientation = EXIF_ORIENTATION_TOP_LEFT;
        if (imd->image_fd)
                {
                if (imd->image_fd->user_orientation)
@@ -1194,6 +1225,17 @@ void image_move_from_image(ImageWindow *imd, ImageWindow *source)
        imd->color_profile_use_image = source->color_profile_use_image;
        color_man_free((ColorMan *)imd->cm);
        imd->cm = NULL;
+       if (source->cm)
+               {
+               ColorMan *cm;
+
+               imd->cm = source->cm;
+               source->cm = NULL;
+
+               cm = (ColorMan *)imd->cm;
+               cm->imd = imd;
+               cm->func_done_data = imd;
+               }
 
        file_data_unref(imd->read_ahead_fd);
        source->read_ahead_fd = NULL;
@@ -1402,8 +1444,8 @@ gchar *image_zoom_get_as_text(ImageWindow *imd)
                approx = "~";
                }
 
-       if (rint(l) != l) pl = 1;
-       if (rint(r) != r) pr = 1;
+       if (rint(l) != l) pl = 2;
+       if (rint(r) != r) pr = 2;
 
        return g_strdup_printf("%.*f :%s%.*f", pl, l, approx, pr, r);
 }
@@ -1580,7 +1622,7 @@ gboolean image_color_profile_get_status(ImageWindow *imd, gchar **image_profile,
 {
        ColorMan *cm;
        if (!imd) return FALSE;
-       
+
        cm = imd->cm;
        if (!cm) return FALSE;
        return color_man_get_status(cm, image_profile, screen_profile);
@@ -1652,7 +1694,7 @@ void image_to_root_window(ImageWindow *imd, gboolean scaled)
 void image_select(ImageWindow *imd, gboolean select)
 {
        if (!imd->has_frame) return;
-       
+
        if (select)
                {
                gtk_widget_set_state(imd->widget, GTK_STATE_SELECTED);
@@ -1665,7 +1707,7 @@ void image_select(ImageWindow *imd, gboolean select)
 void image_set_selectable(ImageWindow *imd, gboolean selectable)
 {
        if (!imd->has_frame) return;
-       
+
        gtk_frame_set_shadow_type(GTK_FRAME(imd->frame), GTK_SHADOW_NONE);
        gtk_container_set_border_width(GTK_CONTAINER(imd->frame), selectable ? 4 : 0);
 }
@@ -1701,11 +1743,12 @@ static void image_options_set(ImageWindow *imd)
                                        "window_limit_value", options->image.max_window_size,
                                        "autofit_limit", options->image.limit_autofit_size,
                                        "autofit_limit_value", options->image.max_autofit_size,
+                                       "enlargement_limit_value", options->image.max_enlargement_size,
 
                                        NULL);
 
        pixbuf_renderer_set_parent((PixbufRenderer *)imd->pr, (GtkWindow *)imd->top_window);
-       
+
        image_stereo_set(imd, options->stereo.mode);
        pixbuf_renderer_stereo_fixed_set((PixbufRenderer *)imd->pr,
                                        options->stereo.fixed_w, options->stereo.fixed_h,
@@ -1842,7 +1885,7 @@ void image_set_frame(ImageWindow *imd, gboolean frame)
                g_object_unref(imd->pr);
                gtk_widget_set_can_focus(imd->frame, TRUE);
                gtk_widget_set_app_paintable(imd->frame, TRUE);
-               
+
 #if GTK_CHECK_VERSION(3,0,0)
                g_signal_connect(G_OBJECT(imd->frame), "draw",
                                 G_CALLBACK(selectable_frame_draw_cb), NULL);
@@ -1898,7 +1941,7 @@ ImageWindow *image_new(gboolean frame)
 
        image_set_selectable(imd, 0);
 
-       g_signal_connect(G_OBJECT(imd->pr), "clicked",
+       g_signal_connect(G_OBJECT(imd->pr), "button_press_event",
                         G_CALLBACK(image_click_cb), imd);
        g_signal_connect(G_OBJECT(imd->pr), "scroll_notify",
                         G_CALLBACK(image_scroll_notify_cb), imd);