callbacks.c 15.9 KB
Newer Older
Moritz Lipp's avatar
Moritz Lipp committed
1
/* See LICENSE file for license and copyright information */
Moritz Lipp's avatar
Moritz Lipp committed
2

3 4 5
#include <girara/statusbar.h>
#include <girara/session.h>
#include <girara/settings.h>
Sebastian Ramacher's avatar
Sebastian Ramacher committed
6
#include <girara/utils.h>
Moritz Lipp's avatar
Moritz Lipp committed
7
#include <stdlib.h>
8
#include <gtk/gtk.h>
Moritz Lipp's avatar
Moritz Lipp committed
9
#include <string.h>
10
#include <glib/gi18n.h>
11
#include <math.h>
Moritz Lipp's avatar
Moritz Lipp committed
12

Sebastian Ramacher's avatar
Sebastian Ramacher committed
13
#include "callbacks.h"
Moritz Lipp's avatar
Moritz Lipp committed
14
#include "links.h"
Moritz Lipp's avatar
Moritz Lipp committed
15
#include "zathura.h"
Moritz Lipp's avatar
Moritz Lipp committed
16
#include "render.h"
17
#include "document.h"
Moritz Lipp's avatar
Moritz Lipp committed
18
#include "utils.h"
Sebastian Ramacher's avatar
Sebastian Ramacher committed
19
#include "shortcuts.h"
20
#include "page-widget.h"
Moritz Lipp's avatar
Moritz Lipp committed
21
#include "page.h"
22
#include "adjustment.h"
Moritz Lipp's avatar
Moritz Lipp committed
23 24

gboolean
25
cb_destroy(GtkWidget* UNUSED(widget), zathura_t* zathura)
Moritz Lipp's avatar
Moritz Lipp committed
26
{
27
  if (zathura != NULL && zathura->document != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
28
    document_close(zathura, false);
29 30
  }

31
  gtk_main_quit();
Moritz Lipp's avatar
Moritz Lipp committed
32 33
  return TRUE;
}
Moritz Lipp's avatar
Moritz Lipp committed
34 35

void
36
cb_buffer_changed(girara_session_t* session)
Moritz Lipp's avatar
Moritz Lipp committed
37 38
{
  g_return_if_fail(session != NULL);
Moritz Lipp's avatar
Moritz Lipp committed
39 40 41
  g_return_if_fail(session->global.data != NULL);

  zathura_t* zathura = session->global.data;
Moritz Lipp's avatar
Moritz Lipp committed
42 43

  char* buffer = girara_buffer_get(session);
Moritz Lipp's avatar
Moritz Lipp committed
44
  if (buffer != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
45
    girara_statusbar_item_set_text(session, zathura->ui.statusbar.buffer, buffer);
Moritz Lipp's avatar
Moritz Lipp committed
46
    free(buffer);
Moritz Lipp's avatar
Moritz Lipp committed
47
  } else {
Moritz Lipp's avatar
Moritz Lipp committed
48
    girara_statusbar_item_set_text(session, zathura->ui.statusbar.buffer, "");
49
  }
Moritz Lipp's avatar
Moritz Lipp committed
50
}
51

52 53
static void
update_visible_pages(zathura_t* zathura) {
54
  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
55 56 57

  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);
58
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
59
    ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget);
60

61 62
    if (page_is_visible(zathura->document, page_id) == true) {
      /* make page visible */
63
      if (zathura_page_get_visibility(page) == false) {
64
        zathura_page_set_visibility(page, true);
65
        zathura_page_widget_update_view_time(zathura_page_widget);
66
        zathura_renderer_page_cache_add(zathura->sync.render_thread, zathura_page_get_index(page));
67
      }
68

69
    } else {
70
      /* make page invisible */
71 72 73 74
      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);
75
      }
76

77
      /* reset current search result */
78 79 80
      girara_list_t* results = NULL;
      g_object_get(page_widget, "search-results", &results, NULL);
      if (results != NULL) {
81
        g_object_set(page_widget, "search-current", 0, NULL);
82
      }
83 84
    }
  }
85 86 87 88 89 90 91 92 93 94
}

void
cb_view_hadjustment_value_changed(GtkAdjustment* adjustment, gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL) {
    return;
  }

95 96 97 98 99
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  update_visible_pages(zathura);

  double position_x = zathura_adjustment_get_ratio(adjustment);
  double position_y = zathura_document_get_position_y(zathura->document);
  unsigned int page_id = position_to_page_number(zathura->document, position_x, position_y);

  zathura_document_set_position_x(zathura->document, position_x);
  zathura_document_set_position_y(zathura->document, position_y);
  zathura_document_set_current_page_number(zathura->document, page_id);

  statusbar_page_number_update(zathura);
}

void
cb_view_vadjustment_value_changed(GtkAdjustment* adjustment, gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL) {
    return;
  }

121 122 123 124 125
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

126 127 128 129 130 131 132 133 134
  update_visible_pages(zathura);

  double position_x = zathura_document_get_position_x(zathura->document);
  double position_y = zathura_adjustment_get_ratio(adjustment);
  unsigned int page_id = position_to_page_number(zathura->document, position_x, position_y);

  zathura_document_set_position_x(zathura->document, position_x);
  zathura_document_set_position_y(zathura->document, position_y);
  zathura_document_set_current_page_number(zathura->document, page_id);
135 136

  statusbar_page_number_update(zathura);
137
}
138

139 140 141 142 143 144 145 146 147
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);

148 149 150 151 152
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

153 154 155
  /* Don't scroll we're focusing the inputbar. */
  if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) {
    return;
156
  }
157 158 159 160 161 162 163 164

  /* save the viewport size */
  unsigned int view_width = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment));
  zathura_document_set_viewport_width(zathura->document, view_width);

  /* reset the adjustment, in case bounds have changed */
  double ratio = zathura_document_get_position_x(zathura->document);
  zathura_adjustment_set_value_from_ratio(adjustment, ratio);
165 166 167 168 169 170 171 172
}

void
cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data)
{
  zathura_t* zathura = data;
  g_return_if_fail(zathura != NULL);

173 174 175
  zathura_adjust_mode_t adjust_mode =
    zathura_document_get_adjust_mode(zathura->document);

176 177 178 179 180
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

181
  /* Don't scroll we're focusing the inputbar. */
Sebastian Ramacher's avatar
CS  
Sebastian Ramacher committed
182
  if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) {
183
    return;
Sebastian Ramacher's avatar
CS  
Sebastian Ramacher committed
184
  }
185

186 187 188 189 190 191
  /* save the viewport size */
  unsigned int view_height = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment));
  zathura_document_set_viewport_height(zathura->document, view_height);

  /* reset the adjustment, in case bounds have changed */
  double ratio = zathura_document_get_position_y(zathura->document);
192 193 194
  zathura_adjustment_set_value_from_ratio(adjustment, ratio);
}

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
void
cb_refresh_view(GtkWidget* GIRARA_UNUSED(view), gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL) {
    return;
  }

  unsigned int page_id = zathura_document_get_current_page_number(zathura->document);
  zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
  if (page == NULL) {
    return;
  }

  GtkAdjustment* vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  GtkAdjustment* hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));

  double position_x = zathura_document_get_position_x(zathura->document);
  double position_y = zathura_document_get_position_y(zathura->document);

  zathura_adjustment_set_value_from_ratio(vadj, position_y);
  zathura_adjustment_set_value_from_ratio(hadj, position_x);

  statusbar_page_number_update(zathura);
}

221
void
222
cb_page_layout_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
223
{
224
  g_return_if_fail(value != NULL);
225 226 227
  g_return_if_fail(session != NULL);
  g_return_if_fail(session->global.data != NULL);
  zathura_t* zathura = session->global.data;
228

229 230 231 232
  if (zathura->document == NULL) {
    /* no document has been openend yet */
    return;
  }
233

234 235
  unsigned int pages_per_row = 1;
  girara_setting_get(session, "pages-per-row", &pages_per_row);
236

237 238 239
  unsigned int first_page_column = 1;
  girara_setting_get(session, "first-page-column", &first_page_column);

240
  unsigned int page_padding = 1;
241
  girara_setting_get(zathura->ui.session, "page-padding", &page_padding);
242 243 244

  page_widget_set_mode(zathura, page_padding, pages_per_row, first_page_column);
  zathura_document_set_page_layout(zathura->document, page_padding, pages_per_row, first_page_column);
245
}
246 247

void
Moritz Lipp's avatar
Moritz Lipp committed
248
cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path,
Moritz Lipp's avatar
Moritz Lipp committed
249
                       GtkTreeViewColumn* UNUSED(column), void* data)
250
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
251
  zathura_t* zathura = data;
252 253 254 255 256 257 258 259 260
  if (tree_view == NULL || zathura == NULL || zathura->ui.session == NULL) {
    return;
  }

  GtkTreeModel  *model;
  GtkTreeIter   iter;

  g_object_get(tree_view, "model", &model, NULL);

Moritz Lipp's avatar
Moritz Lipp committed
261
  if(gtk_tree_model_get_iter(model, &iter, path)) {
262
    zathura_index_element_t* index_element;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
263
    gtk_tree_model_get(model, &iter, 2, &index_element, -1);
264 265 266 267 268

    if (index_element == NULL) {
      return;
    }

Moritz Lipp's avatar
Moritz Lipp committed
269
    sc_toggle_index(zathura->ui.session, NULL, NULL, 0);
270
    zathura_link_evaluate(zathura, index_element->link);
271 272 273 274
  }

  g_object_unref(model);
}
Moritz Lipp's avatar
Moritz Lipp committed
275

276 277 278 279 280 281 282 283 284
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)
Moritz Lipp's avatar
Moritz Lipp committed
285 286 287 288 289
{
  g_return_val_if_fail(session != NULL, FALSE);
  g_return_val_if_fail(session->global.data != NULL, FALSE);

  zathura_t* zathura = session->global.data;
Moritz Lipp's avatar
Moritz Lipp committed
290
  bool eval = true;
Moritz Lipp's avatar
Moritz Lipp committed
291 292

  char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
Moritz Lipp's avatar
Moritz Lipp committed
293 294
  if (input == NULL || strlen(input) == 0) {
    eval = false;
Moritz Lipp's avatar
Moritz Lipp committed
295 296
  }

Moritz Lipp's avatar
Moritz Lipp committed
297 298 299 300
  int index = 0;
  if (eval == true) {
    index = atoi(input);
    if (index == 0 && g_strcmp0(input, "0") != 0) {
301
      girara_notify(session, GIRARA_WARNING, _("Invalid input '%s' given."), input);
Moritz Lipp's avatar
Moritz Lipp committed
302 303 304
      eval = false;
    }
    index = index - 1;
Moritz Lipp's avatar
Moritz Lipp committed
305 306 307 308
  }

  /* set pages to draw links */
  bool invalid_index = true;
309 310 311
  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);
Moritz Lipp's avatar
Moritz Lipp committed
312
    if (page == NULL || zathura_page_get_visibility(page) == false) {
Moritz Lipp's avatar
Moritz Lipp committed
313 314 315
      continue;
    }

316
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
Moritz Lipp's avatar
Moritz Lipp committed
317
    g_object_set(page_widget, "draw-links", FALSE, NULL);
318

Moritz Lipp's avatar
Moritz Lipp committed
319
    if (eval == true) {
Moritz Lipp's avatar
Moritz Lipp committed
320
      zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page_widget), index);
321

Moritz Lipp's avatar
Moritz Lipp committed
322 323
      if (link != NULL) {
        invalid_index = false;
324 325 326 327 328 329 330 331
        switch (action) {
          case ZATHURA_LINK_ACTION_FOLLOW:
            zathura_link_evaluate(zathura, link);
            break;
          case ZATHURA_LINK_ACTION_DISPLAY:
            zathura_link_display(zathura, link);
            break;
        }
Moritz Lipp's avatar
Moritz Lipp committed
332 333 334 335
      }
    }
  }

Moritz Lipp's avatar
Moritz Lipp committed
336
  if (eval == true && invalid_index == true) {
337
    girara_notify(session, GIRARA_WARNING, _("Invalid index '%s' given."), input);
Moritz Lipp's avatar
Moritz Lipp committed
338 339 340 341
  }

  g_free(input);

Moritz Lipp's avatar
Moritz Lipp committed
342
  return (eval == TRUE) ? TRUE : FALSE;
Moritz Lipp's avatar
Moritz Lipp committed
343
}
Moritz Lipp's avatar
Moritz Lipp committed
344

345 346 347 348 349 350 351 352 353 354 355 356
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);
}

357 358 359 360 361 362 363
static gboolean
file_monitor_reload(void* data)
{
  sc_reload((girara_session_t*) data, NULL, NULL, 0);
  return FALSE;
}

Moritz Lipp's avatar
Moritz Lipp committed
364 365 366 367 368 369 370
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);

Moritz Lipp's avatar
Moritz Lipp committed
371 372 373
  switch (event) {
    case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
    case G_FILE_MONITOR_EVENT_CREATED:
374
      g_main_context_invoke(NULL, file_monitor_reload, session);
Moritz Lipp's avatar
Moritz Lipp committed
375 376 377
      break;
    default:
      return;
Moritz Lipp's avatar
Moritz Lipp committed
378 379
  }
}
380

381 382 383 384
static gboolean
password_dialog(gpointer data)
{
  zathura_password_dialog_info_t* dialog = data;
Moritz Lipp's avatar
Moritz Lipp committed
385

386
  if (dialog != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
387
    girara_dialog(
Moritz Lipp's avatar
Moritz Lipp committed
388 389 390 391 392 393 394
      dialog->zathura->ui.session,
      "Incorrect password. Enter password:",
      true,
      NULL,
      (girara_callback_inputbar_activate_t) cb_password_dialog,
      dialog
    );
395
  }
Moritz Lipp's avatar
Moritz Lipp committed
396

397 398 399
  return FALSE;
}

400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
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);
    }

424
    gdk_threads_add_idle(password_dialog, dialog);
425 426 427 428
    return false;
  }

  /* try to open document again */
429 430
  if (document_open(dialog->zathura, dialog->path, input,
                    ZATHURA_PAGE_NUMBER_UNSPECIFIED) == false) {
431
    gdk_threads_add_idle(password_dialog, dialog);
432 433 434 435
  } else {
    g_free(dialog->path);
    free(dialog);
  }
436 437 438 439 440 441 442

  g_free(input);

  return true;

error_free:

Moritz Lipp's avatar
Moritz Lipp committed
443 444
  g_free(dialog->path);
  free(dialog);
445 446 447 448 449

error_ret:

  return false;
}
450 451

bool
452
cb_view_resized(GtkWidget* UNUSED(widget), GtkAllocation* UNUSED(allocation), zathura_t* zathura)
453 454 455 456 457
{
  if (zathura == NULL || zathura->document == NULL) {
    return false;
  }

458 459
  /* adjust the scale according to settings. If nothing needs to be resized,
     it does not trigger the resize event.
460

461 462 463 464
     The right viewport size is already in the document object, due to a
     previous call to adjustment_changed. We don't want to use the allocation in
     here, because we would have to subtract scrollbars, etc. */
  adjust_view(zathura);
465 466

  return false;
467
}
Moritz Lipp's avatar
Moritz Lipp committed
468 469 470

void
cb_setting_recolor_change(girara_session_t* session, const char* name,
Moritz Lipp's avatar
Moritz Lipp committed
471
                          girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
Moritz Lipp's avatar
Moritz Lipp committed
472 473 474 475 476 477 478
{
  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;

479
  const bool bool_value = *((bool*) value);
Moritz Lipp's avatar
Moritz Lipp committed
480

481 482 483
  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);
Moritz Lipp's avatar
Moritz Lipp committed
484 485
  }
}
Moritz Lipp's avatar
Moritz Lipp committed
486

487 488
void
cb_setting_recolor_keep_hue_change(girara_session_t* session, const char* name,
Moritz Lipp's avatar
Moritz Lipp committed
489
                                   girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
490 491 492 493 494 495 496
{
  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;

497
  const bool bool_value = *((bool*) value);
498

499 500 501
  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);
502 503 504 505
  }
}


Moritz Lipp's avatar
Moritz Lipp committed
506 507 508 509 510 511 512 513 514 515 516 517 518 519
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 */
520 521
  const size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
Moritz Lipp's avatar
Moritz Lipp committed
522 523 524 525 526
    if (g_ascii_isdigit(input[i]) == FALSE) {
      return false;
    }
  }

527
  zathura_jumplist_add(zathura);
Moritz Lipp's avatar
Moritz Lipp committed
528
  page_set(zathura, atoi(input) - 1);
529
  zathura_jumplist_add(zathura);
Moritz Lipp's avatar
Moritz Lipp committed
530 531 532

  return true;
}
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548

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", ' ');
549 550
    char* escaped_text = g_markup_printf_escaped(
        _("Copied selected text to clipboard: %s"), stripped_text);
551
    g_free(stripped_text);
552

553
    girara_notify(zathura->ui.session, GIRARA_INFO, "%s", escaped_text);
554
    g_free(escaped_text);
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
  }

  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);
}