zathura/callbacks.c

592 lines
16 KiB
C
Raw Normal View History

2010-11-10 20:31:15 +01:00
/* See LICENSE file for license and copyright information */
2010-11-12 13:48:18 +01:00
#include <girara/statusbar.h>
#include <girara/session.h>
#include <girara/settings.h>
2012-01-21 22:03:08 +01:00
#include <girara/utils.h>
2010-11-13 12:40:48 +01:00
#include <stdlib.h>
2010-12-29 11:46:13 +01:00
#include <gtk/gtk.h>
2012-02-07 17:31:47 +01:00
#include <string.h>
#include <glib/gi18n.h>
2010-11-12 13:48:18 +01:00
2011-08-31 14:35:53 +02:00
#include "callbacks.h"
2012-05-28 12:43:22 +02:00
#include "links.h"
2010-11-12 13:48:18 +01:00
#include "zathura.h"
2011-01-07 09:07:02 +01:00
#include "render.h"
#include "document.h"
2011-04-19 20:23:58 +02:00
#include "utils.h"
2011-09-29 18:08:37 +02:00
#include "shortcuts.h"
2012-03-16 14:37:54 +01:00
#include "page-widget.h"
2012-03-26 14:44:56 +02:00
#include "page.h"
#include "adjustment.h"
2010-11-12 13:48:18 +01:00
gboolean
2012-03-07 01:11:18 +01:00
cb_destroy(GtkWidget* UNUSED(widget), zathura_t* zathura)
2010-11-12 13:48:18 +01:00
{
2012-03-07 01:11:18 +01:00
if (zathura != NULL && zathura->document != NULL) {
document_close(zathura, false);
2012-03-07 01:11:18 +01:00
}
2011-10-16 20:59:25 +02:00
gtk_main_quit();
2010-11-12 13:48:18 +01:00
return TRUE;
}
2010-11-13 12:40:48 +01:00
void
2012-02-08 15:19:51 +01:00
cb_buffer_changed(girara_session_t* session)
2010-11-13 12:40:48 +01:00
{
g_return_if_fail(session != NULL);
2011-04-18 17:37:03 +02:00
g_return_if_fail(session->global.data != NULL);
zathura_t* zathura = session->global.data;
2010-11-13 12:40:48 +01:00
char* buffer = girara_buffer_get(session);
2012-03-04 01:30:27 +01:00
if (buffer != NULL) {
2011-04-18 17:37:03 +02:00
girara_statusbar_item_set_text(session, zathura->ui.statusbar.buffer, buffer);
2010-11-13 12:40:48 +01:00
free(buffer);
2010-12-26 01:12:20 +01:00
} else {
2011-04-18 17:37:03 +02:00
girara_statusbar_item_set_text(session, zathura->ui.statusbar.buffer, "");
}
2010-11-13 12:40:48 +01:00
}
2010-12-29 11:46:13 +01:00
void
cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data)
2010-12-29 11:46:13 +01:00
{
2011-04-18 17:37:03 +02:00
zathura_t* zathura = data;
if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) {
2010-12-29 11:46:13 +01:00
return;
}
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
/* current adjustment values */
const GdkRectangle view_rect = {
.x = 0,
.y = 0,
.width = gtk_adjustment_get_page_size(view_hadjustment),
.height = gtk_adjustment_get_page_size(view_vadjustment)
};
int page_padding = 1;
girara_setting_get(zathura->ui.session, "page-padding", &page_padding);
2010-12-29 11:46:13 +01:00
const GdkRectangle center = {
.x = (view_rect.width + 1) / 2,
.y = (view_rect.height + 1) / 2,
.width = (2 * page_padding) + 1,
.height = (2 * page_padding) + 1
};
const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
const double scale = zathura_document_get_scale(zathura->document);
bool updated = false;
2010-12-29 11:46:13 +01:00
/* find page that fits */
for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
2011-01-06 08:59:10 +01:00
GdkRectangle page_rect = {
.width = zathura_page_get_width(page) * scale,
.height = zathura_page_get_height(page) * scale
};
GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget);
gtk_widget_translate_coordinates(page_widget, zathura->ui.session->gtk.view,
0, 0, &page_rect.x, &page_rect.y);
2011-04-19 20:41:16 +02:00
if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) {
if (zathura_page_get_visibility(page) == false) {
zathura_page_set_visibility(page, true);
zathura_page_widget_update_view_time(zathura_page_widget);
zathura_renderer_page_cache_add(zathura->sync.render_thread, zathura_page_get_index(page));
}
if (zathura->global.update_page_number == true && updated == false
&& gdk_rectangle_intersect(&center, &page_rect, NULL) == TRUE) {
zathura_document_set_current_page_number(zathura->document, page_id);
updated = true;
}
2011-04-19 20:46:33 +02:00
} else {
if (zathura_page_get_visibility(page) == true) {
zathura_page_set_visibility(page, false);
/* If a page becomes invisible, abort the render request. */
zathura_page_widget_abort_render_request(zathura_page_widget);
}
girara_list_t* results = NULL;
g_object_get(page_widget, "search-results", &results, NULL);
if (results != NULL) {
g_object_set(page_widget, "search-current", 0, NULL);
}
2010-12-29 11:46:13 +01:00
}
}
statusbar_page_number_update(zathura);
2010-12-29 11:46:13 +01:00
}
void
cb_view_hadjustment_changed(GtkAdjustment* adjustment, gpointer data)
{
zathura_t* zathura = data;
g_return_if_fail(zathura != NULL);
zathura_adjust_mode_t adjust_mode =
zathura_document_get_adjust_mode(zathura->document);
gdouble lower, upper, page_size, value, ratio;
bool zoom_center = false;
switch (adjust_mode) {
center:
case ZATHURA_ADJUST_BESTFIT:
case ZATHURA_ADJUST_WIDTH:
lower = gtk_adjustment_get_lower(adjustment);
upper = gtk_adjustment_get_upper(adjustment);
page_size = gtk_adjustment_get_page_size(adjustment);
value = ((upper - lower) - page_size) / 2.0;
zathura_adjustment_set_value(adjustment, value);
break;
default:
girara_setting_get(zathura->ui.session, "zoom-center", &zoom_center);
if (zoom_center) {
goto center;
}
ratio = zathura_adjustment_get_ratio(zathura->ui.hadjustment);
zathura_adjustment_set_value_from_ratio(adjustment, ratio);
break;
}
}
void
cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data)
{
zathura_t* zathura = data;
g_return_if_fail(zathura != NULL);
zathura_adjust_mode_t adjust_mode =
zathura_document_get_adjust_mode(zathura->document);
/* Don't scroll we're focusing the inputbar. */
if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) {
return;
}
double ratio = zathura_adjustment_get_ratio(zathura->ui.vadjustment);
zathura_adjustment_set_value_from_ratio(adjustment, ratio);
}
void
cb_adjustment_track_value(GtkAdjustment* adjustment, gpointer data)
{
GtkAdjustment* tracker = data;
gdouble lower = gtk_adjustment_get_lower(adjustment);
gdouble upper = gtk_adjustment_get_upper(adjustment);
if (lower != gtk_adjustment_get_lower(tracker) ||
upper != gtk_adjustment_get_upper(tracker)) {
return;
}
gdouble value = gtk_adjustment_get_value(adjustment);
gtk_adjustment_set_value(tracker, value);
}
void
cb_adjustment_track_bounds(GtkAdjustment* adjustment, gpointer data)
{
GtkAdjustment* tracker = data;
gdouble value = gtk_adjustment_get_value(adjustment);
gdouble lower = gtk_adjustment_get_lower(adjustment);
gdouble upper = gtk_adjustment_get_upper(adjustment);
gdouble page_size = gtk_adjustment_get_page_size(adjustment);
gtk_adjustment_set_value(tracker, value);
gtk_adjustment_set_lower(tracker, lower);
gtk_adjustment_set_upper(tracker, upper);
gtk_adjustment_set_page_size(tracker, page_size);
}
void
cb_pages_per_row_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{
2011-11-20 11:32:34 +01:00
g_return_if_fail(value != NULL);
g_return_if_fail(session != NULL);
g_return_if_fail(session->global.data != NULL);
zathura_t* zathura = session->global.data;
2011-11-20 11:32:34 +01:00
int pages_per_row = *(int*) value;
2011-07-21 14:48:48 +02:00
if (pages_per_row < 1) {
pages_per_row = 1;
2011-07-21 14:48:48 +02:00
}
unsigned int first_page_column = 1;
girara_setting_get(session, "first-page-column", &first_page_column);
page_widget_set_mode(zathura, pages_per_row, first_page_column);
if (zathura->document != NULL) {
unsigned int current_page = zathura_document_get_current_page_number(zathura->document);
page_set_delayed(zathura, current_page);
}
}
void
cb_first_page_column_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{
g_return_if_fail(value != NULL);
g_return_if_fail(session != NULL);
g_return_if_fail(session->global.data != NULL);
zathura_t* zathura = session->global.data;
int first_page_column = *(int*) value;
if (first_page_column < 1) {
first_page_column = 1;
}
unsigned int pages_per_row = 1;
girara_setting_get(session, "pages-per-row", &pages_per_row);
page_widget_set_mode(zathura, pages_per_row, first_page_column);
if (zathura->document != NULL) {
unsigned int current_page = zathura_document_get_current_page_number(zathura->document);
page_set_delayed(zathura, current_page);
}
}
2011-09-29 17:05:54 +02:00
void
2011-09-29 18:17:03 +02:00
cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path,
2012-10-09 01:12:18 +02:00
GtkTreeViewColumn* UNUSED(column), void* data)
2011-09-29 17:05:54 +02:00
{
2011-12-09 14:50:35 +01:00
zathura_t* zathura = data;
2011-09-29 17:05:54 +02:00
if (tree_view == NULL || zathura == NULL || zathura->ui.session == NULL) {
return;
}
GtkTreeModel *model;
GtkTreeIter iter;
g_object_get(tree_view, "model", &model, NULL);
2012-03-04 01:30:27 +01:00
if(gtk_tree_model_get_iter(model, &iter, path)) {
2011-09-29 17:05:54 +02:00
zathura_index_element_t* index_element;
2011-09-29 17:28:09 +02:00
gtk_tree_model_get(model, &iter, 2, &index_element, -1);
2011-09-29 17:05:54 +02:00
if (index_element == NULL) {
return;
}
2012-04-22 10:04:46 +02:00
sc_toggle_index(zathura->ui.session, NULL, NULL, 0);
zathura_link_evaluate(zathura, index_element->link);
2011-09-29 17:05:54 +02:00
}
g_object_unref(model);
}
2012-02-07 16:39:02 +01:00
typedef enum zathura_link_action_e
{
ZATHURA_LINK_ACTION_FOLLOW,
ZATHURA_LINK_ACTION_DISPLAY
} zathura_link_action_t;
static bool
handle_link(GtkEntry* entry, girara_session_t* session,
zathura_link_action_t action)
2012-02-07 17:31:47 +01:00
{
g_return_val_if_fail(session != NULL, FALSE);
g_return_val_if_fail(session->global.data != NULL, FALSE);
zathura_t* zathura = session->global.data;
2012-02-08 00:19:35 +01:00
bool eval = true;
2012-02-07 17:31:47 +01:00
char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
2012-02-08 00:19:35 +01:00
if (input == NULL || strlen(input) == 0) {
eval = false;
2012-02-07 17:31:47 +01:00
}
2012-02-08 00:19:35 +01:00
int index = 0;
if (eval == true) {
index = atoi(input);
if (index == 0 && g_strcmp0(input, "0") != 0) {
girara_notify(session, GIRARA_WARNING, _("Invalid input '%s' given."), input);
2012-02-08 00:19:35 +01:00
eval = false;
}
index = index - 1;
2012-02-07 17:31:47 +01:00
}
/* set pages to draw links */
bool invalid_index = true;
unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
2012-03-26 14:44:56 +02:00
if (page == NULL || zathura_page_get_visibility(page) == false) {
2012-02-07 17:31:47 +01:00
continue;
}
GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
2012-03-26 14:44:56 +02:00
g_object_set(page_widget, "draw-links", FALSE, NULL);
2012-02-07 18:00:47 +01:00
2012-02-08 00:19:35 +01:00
if (eval == true) {
2012-03-26 14:44:56 +02:00
zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page_widget), index);
2012-02-08 00:19:35 +01:00
if (link != NULL) {
invalid_index = false;
switch (action) {
case ZATHURA_LINK_ACTION_FOLLOW:
zathura_link_evaluate(zathura, link);
break;
case ZATHURA_LINK_ACTION_DISPLAY:
zathura_link_display(zathura, link);
break;
}
2012-02-07 17:31:47 +01:00
}
}
}
2012-02-08 00:19:35 +01:00
if (eval == true && invalid_index == true) {
girara_notify(session, GIRARA_WARNING, _("Invalid index '%s' given."), input);
2012-02-07 17:31:47 +01:00
}
g_free(input);
2012-02-08 00:19:35 +01:00
return (eval == TRUE) ? TRUE : FALSE;
2012-02-07 17:31:47 +01:00
}
2012-02-07 19:25:47 +01:00
bool
cb_sc_follow(GtkEntry* entry, girara_session_t* session)
{
return handle_link(entry, session, ZATHURA_LINK_ACTION_FOLLOW);
}
bool
cb_sc_display_link(GtkEntry* entry, girara_session_t* session)
{
return handle_link(entry, session, ZATHURA_LINK_ACTION_DISPLAY);
}
static gboolean
file_monitor_reload(void* data)
{
sc_reload((girara_session_t*) data, NULL, NULL, 0);
return FALSE;
}
2012-02-07 19:25:47 +01:00
void
cb_file_monitor(GFileMonitor* monitor, GFile* file, GFile* UNUSED(other_file), GFileMonitorEvent event, girara_session_t* session)
{
g_return_if_fail(monitor != NULL);
g_return_if_fail(file != NULL);
g_return_if_fail(session != NULL);
2012-02-20 20:07:24 +01:00
switch (event) {
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
case G_FILE_MONITOR_EVENT_CREATED:
g_main_context_invoke(NULL, file_monitor_reload, session);
2012-02-20 20:07:24 +01:00
break;
default:
return;
2012-02-07 19:25:47 +01:00
}
}
2012-02-08 23:21:27 +01:00
static gboolean
password_dialog(gpointer data)
{
zathura_password_dialog_info_t* dialog = data;
2012-03-04 01:30:27 +01:00
if (dialog != NULL) {
2012-03-04 01:30:27 +01:00
girara_dialog(
2012-10-09 01:12:18 +02:00
dialog->zathura->ui.session,
"Incorrect password. Enter password:",
true,
NULL,
(girara_callback_inputbar_activate_t) cb_password_dialog,
dialog
);
}
2012-03-04 01:30:27 +01:00
return FALSE;
}
2012-02-08 23:21:27 +01:00
bool
cb_password_dialog(GtkEntry* entry, zathura_password_dialog_info_t* dialog)
{
if (entry == NULL || dialog == NULL) {
goto error_ret;
}
if (dialog->path == NULL) {
free(dialog);
goto error_ret;
}
if (dialog->zathura == NULL) {
goto error_free;
}
char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
/* no or empty password: ask again */
if (input == NULL || strlen(input) == 0) {
if (input != NULL) {
g_free(input);
}
gdk_threads_add_idle(password_dialog, dialog);
2012-02-08 23:21:27 +01:00
return false;
}
/* try to open document again */
if (document_open(dialog->zathura, dialog->path, input,
ZATHURA_PAGE_NUMBER_UNSPECIFIED) == false) {
gdk_threads_add_idle(password_dialog, dialog);
} else {
g_free(dialog->path);
free(dialog);
}
2012-02-08 23:21:27 +01:00
g_free(input);
return true;
error_free:
2012-10-09 01:12:18 +02:00
g_free(dialog->path);
free(dialog);
2012-02-08 23:21:27 +01:00
error_ret:
return false;
}
2012-02-09 01:46:51 +01:00
bool
cb_view_resized(GtkWidget* UNUSED(widget), GtkAllocation* allocation, zathura_t* zathura)
2012-02-09 01:46:51 +01:00
{
if (zathura == NULL || zathura->document == NULL) {
return false;
}
static int height = -1;
static int width = -1;
2012-02-09 01:46:51 +01:00
/* adjust only if the allocation changed */
if (width != allocation->width || height != allocation->height) {
girara_argument_t argument = { zathura_document_get_adjust_mode(zathura->document), NULL };
sc_adjust_window(zathura->ui.session, &argument, NULL, 0);
2012-03-04 01:30:27 +01:00
width = allocation->width;
height = allocation->height;
}
return false;
2012-02-09 01:46:51 +01:00
}
2012-03-14 17:33:35 +01:00
void
cb_setting_recolor_change(girara_session_t* session, const char* name,
2012-10-09 01:12:18 +02:00
girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
2012-03-14 17:33:35 +01:00
{
g_return_if_fail(value != NULL);
g_return_if_fail(session != NULL);
g_return_if_fail(session->global.data != NULL);
g_return_if_fail(name != NULL);
zathura_t* zathura = session->global.data;
const bool bool_value = *((bool*) value);
2012-03-14 17:33:35 +01:00
if (zathura->sync.render_thread != NULL && zathura_renderer_recolor_enabled(zathura->sync.render_thread) != bool_value) {
zathura_renderer_enable_recolor(zathura->sync.render_thread, bool_value);
render_all(zathura);
2012-03-14 17:33:35 +01:00
}
}
2012-05-01 19:09:33 +02:00
void
cb_setting_recolor_keep_hue_change(girara_session_t* session, const char* name,
2012-10-09 01:12:18 +02:00
girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{
g_return_if_fail(value != NULL);
g_return_if_fail(session != NULL);
g_return_if_fail(session->global.data != NULL);
g_return_if_fail(name != NULL);
zathura_t* zathura = session->global.data;
const bool bool_value = *((bool*) value);
if (zathura->sync.render_thread != NULL && zathura_renderer_recolor_hue_enabled(zathura->sync.render_thread) != bool_value) {
zathura_renderer_enable_recolor_hue(zathura->sync.render_thread, bool_value);
render_all(zathura);
}
}
2012-05-01 19:09:33 +02:00
bool
cb_unknown_command(girara_session_t* session, const char* input)
{
g_return_val_if_fail(session != NULL, false);
g_return_val_if_fail(session->global.data != NULL, false);
g_return_val_if_fail(input != NULL, false);
zathura_t* zathura = session->global.data;
if (zathura->document == NULL) {
return false;
}
/* check for number */
const size_t size = strlen(input);
for (size_t i = 0; i < size; i++) {
2012-05-01 19:09:33 +02:00
if (g_ascii_isdigit(input[i]) == FALSE) {
return false;
}
}
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
zathura_jumplist_add(zathura);
2012-05-01 19:09:33 +02:00
page_set(zathura, atoi(input) - 1);
zathura_jumplist_add(zathura);
2012-05-01 19:09:33 +02:00
return true;
}
void
cb_page_widget_text_selected(ZathuraPage* page, const char* text, void* data)
{
g_return_if_fail(page != NULL);
g_return_if_fail(text != NULL);
g_return_if_fail(data != NULL);
zathura_t* zathura = data;
GdkAtom* selection = get_selection(zathura);
/* copy to clipboard */
if (selection != NULL) {
gtk_clipboard_set_text(gtk_clipboard_get(*selection), text, -1);
char* stripped_text = g_strdelimit(g_strdup(text), "\n\t\r\n", ' ');
char* escaped_text = g_markup_printf_escaped(
_("Copied selected text to clipboard: %s"), stripped_text);
g_free(stripped_text);
girara_notify(zathura->ui.session, GIRARA_INFO, "%s", escaped_text);
g_free(escaped_text);
}
g_free(selection);
}
void
cb_page_widget_image_selected(ZathuraPage* page, GdkPixbuf* pixbuf, void* data)
{
g_return_if_fail(page != NULL);
g_return_if_fail(pixbuf != NULL);
g_return_if_fail(data != NULL);
zathura_t* zathura = data;
GdkAtom* selection = get_selection(zathura);
if (selection != NULL) {
gtk_clipboard_set_image(gtk_clipboard_get(*selection), pixbuf);
}
g_free(selection);
}