aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornirav <nirav@teisuu.com>2018-09-05 00:35:24 +0530
committerDandelion <nirav@teisuu.com>2018-09-07 21:16:09 +0530
commit02f7a54e67260ee7995c6cd9bf40ae784b60203d (patch)
treed8bb663f273f4adf1d737ea39f19e5154c9ac07c
parent28e58ba0dbf30a4a28465f460c67e1c4337bd3a4 (diff)
downloadim-02f7a54e67260ee7995c6cd9bf40ae784b60203d.tar.gz
im-02f7a54e67260ee7995c6cd9bf40ae784b60203d.zip
Added image panning support, refactoring
-rw-r--r--file.c6
-rw-r--r--image.c12
-rw-r--r--image.h4
-rw-r--r--input.c146
-rw-r--r--input.h13
-rw-r--r--main.c161
-rw-r--r--makefile2
-rw-r--r--window.c98
-rw-r--r--window.h11
9 files changed, 291 insertions, 162 deletions
diff --git a/file.c b/file.c
index 33d326b..528de4b 100644
--- a/file.c
+++ b/file.c
@@ -1,5 +1,6 @@
#include "file.h"
#include <dirent.h>
+#include <gtk-3.0/gtk/gtk.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
@@ -27,7 +28,6 @@ int scan(const char *file_name)
{
struct dirent **name_list;
char *dir_name = dirname(strdup(file_name));
- size_t dir_name_len = strlen(dir_name);
file_list_count = scandir(dir_name, &name_list, image_filter, alphasort);
if (file_list_count < 0) {
return -1;
@@ -39,9 +39,7 @@ int scan(const char *file_name)
while (i < file_list_count) {
if (!strcmp(file_basename, name_list[i]->d_name))
curr_file_index = i;
- file_list[i] = malloc(
- (strlen(name_list[i]->d_name) + dir_name_len + 2) * sizeof(char *));
- sprintf(file_list[i], "%s/%s", dir_name, name_list[i]->d_name);
+ file_list[i] = g_build_filename(dir_name, name_list[i]->d_name, NULL);
free(name_list[i]);
i++;
}
diff --git a/image.c b/image.c
index 5489259..17a2093 100644
--- a/image.c
+++ b/image.c
@@ -1,4 +1,5 @@
#include "image.h"
+#include "window.h"
#include <gtk-3.0/gtk/gtk.h>
GtkWidget *new_image()
@@ -7,9 +8,8 @@ GtkWidget *new_image()
return image;
}
-int load_image(char *file_name, int win_width, int win_height)
+int load_image(char *file_name)
{
- printf("loading: %s\n", file_name);
GError *error = NULL;
if (pixbuf != NULL)
g_object_unref(pixbuf);
@@ -21,7 +21,7 @@ int load_image(char *file_name, int win_width, int win_height)
gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf));
aspect_ratio = (double)pixbuf_width / (double)pixbuf_height;
curr_zoom = 1.0;
- fit_image(win_width, win_height);
+ fit_image();
return 1;
}
@@ -37,8 +37,11 @@ void update_pixbuf()
gtk_image_set_from_pixbuf(GTK_IMAGE(image), GDK_PIXBUF(curr_pixbuf));
}
-void fit_image(int win_width, int win_height)
+void fit_image()
{
+ gint win_width, win_height;
+ get_curr_win_size(&win_width, &win_height);
+ curr_scale_mod = fit;
if (pixbuf == NULL || win_width < 1 || win_height < 1)
return;
if (win_width < pixbuf_width && win_height > pixbuf_height) {
@@ -69,6 +72,7 @@ void fit_image(int win_width, int win_height)
void zoom(int type)
{
+ curr_scale_mod = zoomed;
if (pixbuf == NULL)
return;
if (type == 0) {
diff --git a/image.h b/image.h
index 3771790..e58afd7 100644
--- a/image.h
+++ b/image.h
@@ -18,8 +18,8 @@ double aspect_ratio;
double curr_zoom;
GtkWidget *new_image();
-int load_image(char *file_name, int win_width, int win_height);
-void fit_image(int win_width, int win_height);
+int load_image(char *file_name);
+void fit_image();
void zoom(int type);
void print_supported_formats();
diff --git a/input.c b/input.c
new file mode 100644
index 0000000..1d460d9
--- /dev/null
+++ b/input.c
@@ -0,0 +1,146 @@
+#include "input.h"
+#include "file.h"
+#include "image.h"
+#include "window.h"
+#include <gtk-3.0/gtk/gtk.h>
+
+#define TIMEOUT 20
+
+int grabbed = 0;
+gdouble start_x, start_y;
+
+void next()
+{
+ char *name;
+ if ((name = get_next_file()) != NULL)
+ load_image(name);
+}
+
+void prev()
+{
+ char *name;
+ if ((name = get_prev_file()) != NULL)
+ load_image(name);
+}
+
+void first()
+{
+ char *name;
+ if ((name = get_first_file()) != NULL)
+ load_image(name);
+}
+
+void last()
+{
+ char *name;
+ if ((name = get_last_file()) != NULL)
+ load_image(name);
+}
+
+void handle_key_press(GdkEventKey key)
+{
+ switch (key.keyval) {
+ case GDK_KEY_q:
+ quit();
+ case GDK_KEY_w:
+ fit_image();
+ break;
+ case GDK_KEY_plus:
+ case GDK_KEY_KP_Add:
+ zoom(1);
+ break;
+ case GDK_KEY_minus:
+ case GDK_KEY_KP_Subtract:
+ zoom(-1);
+ break;
+ case GDK_KEY_equal:
+ zoom(0);
+ break;
+ case GDK_KEY_n:
+ case GDK_KEY_j:
+ case GDK_KEY_Right:
+ next();
+ break;
+ case GDK_KEY_p:
+ case GDK_KEY_k:
+ case GDK_KEY_Left:
+ prev();
+ break;
+ case GDK_KEY_g:
+ case GDK_KEY_Home:
+ first();
+ break;
+ case GDK_KEY_G:
+ case GDK_KEY_End:
+ last();
+ break;
+ default:
+ break;
+ }
+}
+
+void handle_button_press(GdkEvent *event)
+{
+ grabbed = 1;
+ start_x = event->motion.x;
+ start_y = event->motion.y;
+}
+
+void handle_button_release()
+{
+ grabbed = 0;
+}
+
+void handle_mouse_move(gdouble x, gdouble y)
+{
+ if (grabbed) {
+ gdouble diff_x = start_x - x;
+ gdouble diff_y = start_y - y;
+ start_x = x;
+ start_y = y;
+ scroll_window(diff_x, diff_y);
+ }
+}
+
+void handle_scroll(GdkEvent *event)
+{
+ GdkModifierType state;
+ gdk_event_get_state(event, &state);
+
+ switch (event->scroll.direction) {
+ case GDK_SCROLL_UP:
+ if (state & GDK_CONTROL_MASK) {
+ zoom(1);
+ } else {
+ prev();
+ }
+ break;
+ case GDK_SCROLL_DOWN:
+ if (state & GDK_CONTROL_MASK) {
+ zoom(-1);
+ } else {
+ next();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+gboolean resize_done(gpointer data)
+{
+ guint *id = data;
+ *id = 0;
+ fit_image();
+ return FALSE;
+}
+
+void handle_resize()
+{
+ if (curr_scale_mod != fit)
+ return;
+ static guint id = 0;
+ if (id)
+ g_source_remove(id);
+ id = g_timeout_add(TIMEOUT, resize_done, &id);
+}
diff --git a/input.h b/input.h
new file mode 100644
index 0000000..9d88383
--- /dev/null
+++ b/input.h
@@ -0,0 +1,13 @@
+#ifndef __INPUT_H
+#define __INPUT_H
+
+#include <gtk-3.0/gtk/gtk.h>
+
+void handle_key_press(GdkEventKey key);
+void handle_button_press(GdkEvent *event);
+void handle_button_release();
+void handle_mouse_move(gdouble x, gdouble y);
+void handle_scroll(GdkEvent *event);
+void handle_resize();
+
+#endif
diff --git a/main.c b/main.c
index d3b25f6..f458ca5 100644
--- a/main.c
+++ b/main.c
@@ -1,178 +1,37 @@
#include "file.h"
#include "image.h"
-#include <dirent.h>
+#include "input.h"
+#include "window.h"
#include <gtk-3.0/gtk/gtk.h>
-#include <libgen.h>
-#include <stdlib.h>
-#include <string.h>
-#define TIMEOUT 20
-
-GtkWidget *window;
-gint win_width, win_height;
-GError *error = NULL;
-
-void next()
-{
- char *name;
- if ((name = get_next_file()) != NULL)
- load_image(name, win_width, win_height);
-}
-
-void prev()
-{
- char *name;
- if ((name = get_prev_file()) != NULL)
- load_image(name, win_width, win_height);
-}
-
-void first()
-{
- char *name;
- if ((name = get_first_file()) != NULL)
- load_image(name, win_width, win_height);
-}
-
-void last()
-{
- char *name;
- if ((name = get_last_file()) != NULL)
- load_image(name, win_width, win_height);
-}
-
-static gboolean key_press(GtkWindow *window, GdkEvent *event, gpointer data)
-{
- switch (event->key.keyval) {
- case GDK_KEY_q:
- g_application_quit(
- G_APPLICATION(gtk_window_get_application(GTK_WINDOW(window))));
- return FALSE;
- case GDK_KEY_w:
- curr_scale_mod = fit;
- fit_image(win_width, win_height);
- return FALSE;
- case GDK_KEY_plus:
- case GDK_KEY_KP_Add:
- zoom(1);
- return FALSE;
- case GDK_KEY_minus:
- case GDK_KEY_KP_Subtract:
- zoom(-1);
- return FALSE;
- case GDK_KEY_equal:
- zoom(0);
- return FALSE;
- case GDK_KEY_n:
- case GDK_KEY_j:
- case GDK_KEY_Right:
- next();
- return FALSE;
- case GDK_KEY_p:
- case GDK_KEY_k:
- case GDK_KEY_Left:
- prev();
- return FALSE;
- case GDK_KEY_g:
- case GDK_KEY_Home:
- first();
- return FALSE;
- case GDK_KEY_G:
- case GDK_KEY_End:
- last();
- return FALSE;
- default:
- return TRUE;
- }
-}
-
-gboolean scroll_callback(GtkWindow *window, GdkEvent *event, gpointer data)
-{
- GdkModifierType state;
- gdk_event_get_state(event, &state);
-
- switch (event->scroll.direction) {
- case GDK_SCROLL_UP:
- if (state & GDK_CONTROL_MASK) {
- zoom(1);
- curr_scale_mod = zoomed;
- } else {
- next();
- }
- return FALSE;
- break;
- case GDK_SCROLL_DOWN:
- if (state & GDK_CONTROL_MASK) {
- zoom(-1);
- curr_scale_mod = zoomed;
- } else {
- prev();
- }
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-gboolean resize_done(gpointer data)
+void print_help()
{
- guint *id = data;
- *id = 0;
- gtk_window_get_size(GTK_WINDOW(window), &win_width, &win_height);
- fit_image(win_width, win_height);
- return FALSE;
-}
-
-gboolean configure_callback(GtkWindow *window, GdkEvent *event, gpointer data)
-{
- if (curr_scale_mod != fit) {
- return FALSE;
- }
- static guint id = 0;
- if (id)
- g_source_remove(id);
- id = g_timeout_add(TIMEOUT, resize_done, &id);
- return FALSE;
+ printf("usage: qwe [filename]\n");
}
static void activate(GtkApplication *app, gpointer user_data)
{
+ print_help();
}
static void open(GApplication *app, GFile **files, gint n_files,
const gchar *hint)
{
if (n_files != 1) {
+ print_help();
return;
}
- window = gtk_application_window_new(GTK_APPLICATION(app));
- gtk_window_set_title(GTK_WINDOW(window), "qwe");
- gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
- g_signal_connect(G_OBJECT(window), "configure-event",
- G_CALLBACK(configure_callback), NULL);
- g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press),
- NULL);
- gtk_widget_add_events(GTK_WIDGET(window), GDK_SCROLL_MASK);
- g_signal_connect(G_OBJECT(window), "scroll-event",
- G_CALLBACK(scroll_callback), NULL);
- char *curr_filename = g_file_get_path(files[0]);
+ create_main_window(app);
+ char *curr_filename = g_file_get_path(files[0]);
int i = scan(curr_filename);
if (i < 0) {
- printf("scan() error %d\n", i);
+ printf("failed to load file");
return;
}
- GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(new_image()));
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(scrolled_window));
- gtk_widget_show_all(GTK_WIDGET(window));
-
- load_image(curr_filename, win_width, win_height);
+ load_image(curr_filename);
}
int main(int argc, char *argv[])
diff --git a/makefile b/makefile
index f5cb9cb..f763130 100644
--- a/makefile
+++ b/makefile
@@ -6,7 +6,7 @@ LDFLAGS=$(shell pkg-config --libs gtk+-3.0)
PREFIX=/usr
BINDIR=$(PREFIX)/bin
-OBJECTS=main.o file.o image.o
+OBJECTS=main.o file.o image.o input.o window.o
all: qwe
diff --git a/window.c b/window.c
new file mode 100644
index 0000000..2d095c6
--- /dev/null
+++ b/window.c
@@ -0,0 +1,98 @@
+#include "window.h"
+#include "image.h"
+#include "input.h"
+#include <gtk-3.0/gtk/gtk.h>
+
+GtkWidget *window;
+GtkWidget *scrolled_window;
+
+static gboolean key_press(GtkWindow *window, GdkEvent *event, gpointer data)
+{
+ handle_key_press(event->key);
+ return FALSE;
+}
+
+static gboolean button_press(GtkWindow *window, GdkEvent *event, gpointer data)
+{
+ handle_button_press(event);
+ return TRUE;
+}
+
+static gboolean button_release(GtkWindow *window, GdkEvent *event,
+ gpointer data)
+{
+ handle_button_release();
+ return TRUE;
+}
+
+static gboolean motion_notify(GtkWindow *window, GdkEvent *event, gpointer data)
+{
+ handle_mouse_move(event->motion.x, event->motion.y);
+ return TRUE;
+}
+
+static gboolean scroll_callback(GtkWindow *window, GdkEvent *event,
+ gpointer data)
+{
+ handle_scroll(event);
+ return TRUE;
+}
+
+static gboolean configure_callback(GtkWindow *window, GdkEvent *event,
+ gpointer data)
+{
+ handle_resize();
+ return TRUE;
+}
+
+void create_main_window(GApplication *app)
+{
+ window = gtk_application_window_new(GTK_APPLICATION(app));
+ gtk_window_set_title(GTK_WINDOW(window), "qwe");
+ gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
+ g_signal_connect(G_OBJECT(window), "configure-event",
+ G_CALLBACK(configure_callback), NULL);
+ g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press),
+ NULL);
+ g_signal_connect(G_OBJECT(window), "button-press-event",
+ G_CALLBACK(button_press), NULL);
+ g_signal_connect(G_OBJECT(window), "button-release-event",
+ G_CALLBACK(button_release), NULL);
+ g_signal_connect(G_OBJECT(window), "motion-notify-event",
+ G_CALLBACK(motion_notify), NULL);
+ gtk_widget_add_events(GTK_WIDGET(window), GDK_SCROLL_MASK);
+ g_signal_connect(G_OBJECT(window), "scroll-event",
+ G_CALLBACK(scroll_callback), NULL);
+
+ scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(new_image()));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(scrolled_window));
+ gtk_widget_show_all(GTK_WIDGET(window));
+}
+
+void scroll_window(gdouble x, gdouble y)
+{
+ GtkAdjustment *h_adj = gtk_scrolled_window_get_hadjustment(
+ GTK_SCROLLED_WINDOW(scrolled_window));
+ GtkAdjustment *v_adj = gtk_scrolled_window_get_vadjustment(
+ GTK_SCROLLED_WINDOW(scrolled_window));
+ gtk_adjustment_set_value(h_adj, gtk_adjustment_get_value(h_adj) + x);
+ gtk_adjustment_set_value(v_adj, gtk_adjustment_get_value(v_adj) + y);
+ gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(scrolled_window),
+ h_adj);
+ gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window),
+ v_adj);
+}
+
+void get_curr_win_size(gint *width, gint *height)
+{
+ gtk_window_get_size(GTK_WINDOW(window), width, height);
+}
+
+void quit()
+{
+ g_application_quit(
+ G_APPLICATION(gtk_window_get_application(GTK_WINDOW(window))));
+}
diff --git a/window.h b/window.h
new file mode 100644
index 0000000..5d5f272
--- /dev/null
+++ b/window.h
@@ -0,0 +1,11 @@
+#ifndef __WINDOW_H
+#define __WINDOW_H
+
+#include <gtk-3.0/gtk/gtk.h>
+
+void create_main_window(GApplication *app);
+void get_curr_win_size(gint *width, gint *height);
+void scroll_window(gdouble x, gdouble y);
+void quit();
+
+#endif