callbacks.c 21.9 KB
Newer Older
1
/* SPDX-License-Identifier: Zlib */
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"
23 24
#include "synctex.h"
#include "dbus-interface.h"
Moritz Lipp's avatar
Moritz Lipp committed
25 26

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

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

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

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

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

54
void
55 56
update_visible_pages(zathura_t* zathura)
{
57
  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
58 59 60

  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);
61
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
62
    ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget);
63

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

72
    } else {
73
      /* make page invisible */
74 75 76 77
      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);
78
      }
79

80
      /* reset current search result */
81
      girara_list_t* results = NULL;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
82 83
      GObject* obj_page_widget = G_OBJECT(page_widget);
      g_object_get(obj_page_widget, "search-results", &results, NULL);
84
      if (results != NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
85
        g_object_set(obj_page_widget, "search-current", 0, NULL);
86
      }
87 88
    }
  }
89 90 91 92 93 94 95 96 97 98
}

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

99 100 101 102 103
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
  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;
  }

125 126 127 128 129
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

130 131 132 133 134 135 136 137 138
  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);
139 140

  statusbar_page_number_update(zathura);
141
}
142

Sebastian Ramacher's avatar
Sebastian Ramacher committed
143 144 145
static void
cb_view_adjustment_changed(GtkAdjustment* adjustment, zathura_t* zathura,
    bool width)
146
{
147 148 149 150 151
  /* Do nothing in index mode */
  if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
    return;
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
152 153 154 155
  const zathura_adjust_mode_t adjust_mode =
    zathura_document_get_adjust_mode(zathura->document);

  /* Don't scroll, we're focusing the inputbar. */
156 157
  if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) {
    return;
158
  }
159

Sebastian Ramacher's avatar
Sebastian Ramacher committed
160 161 162 163 164 165 166
  /* Save the viewport size */
  unsigned int size = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment));
  if (width == true) {
    zathura_document_set_viewport_width(zathura->document, size);
  } else {
    zathura_document_set_viewport_height(zathura->document, size);
  }
167 168

  /* reset the adjustment, in case bounds have changed */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
169 170
  const double ratio = width == true ?
    zathura_document_get_position_x(zathura->document) :
Sebastian Ramacher's avatar
Sebastian Ramacher committed
171
    zathura_document_get_position_y(zathura->document);
172
  zathura_adjustment_set_value_from_ratio(adjustment, ratio);
173 174 175
}

void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
176
cb_view_hadjustment_changed(GtkAdjustment* adjustment, gpointer data)
177 178 179 180
{
  zathura_t* zathura = data;
  g_return_if_fail(zathura != NULL);

Sebastian Ramacher's avatar
Sebastian Ramacher committed
181 182
  cb_view_adjustment_changed(adjustment, zathura, true);
}
183

Sebastian Ramacher's avatar
Sebastian Ramacher committed
184 185 186 187 188
void
cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data)
{
  zathura_t* zathura = data;
  g_return_if_fail(zathura != NULL);
189

Sebastian Ramacher's avatar
Sebastian Ramacher committed
190
  cb_view_adjustment_changed(adjustment, zathura, false);
191 192
}

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
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);
}

219 220 221 222 223 224 225 226 227 228
void
cb_monitors_changed(GdkScreen* screen, gpointer data)
{
  girara_debug("signal received");

  zathura_t* zathura = data;
  if (screen == NULL || zathura == NULL) {
    return;
  }

229
  zathura_update_view_ppi(zathura);
230 231 232
}

void
233
cb_widget_screen_changed(GtkWidget* widget, GdkScreen* previous_screen, gpointer data)
234
{
235
  girara_debug("called");
236 237 238 239 240 241

  zathura_t* zathura = data;
  if (widget == NULL || zathura == NULL) {
    return;
  }

242 243 244 245 246 247
  /* disconnect previous screen handler if present */
  if (previous_screen != NULL && zathura->signals.monitors_changed_handler > 0) {
    g_signal_handler_disconnect(previous_screen, zathura->signals.monitors_changed_handler);
    zathura->signals.monitors_changed_handler = 0;
  }

248 249 250 251
  if (gtk_widget_has_screen(widget)) {
    GdkScreen* screen = gtk_widget_get_screen(widget);

    /* connect to new screen */
252
    zathura->signals.monitors_changed_handler = g_signal_connect(G_OBJECT(screen),
253 254 255
        "monitors-changed", G_CALLBACK(cb_monitors_changed), zathura);
  }

256
  zathura_update_view_ppi(zathura);
257 258
}

259
gboolean
260 261 262 263
cb_widget_configured(GtkWidget* UNUSED(widget), GdkEvent* UNUSED(event), gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL) {
264
    return false;
265 266 267
  }

  zathura_update_view_ppi(zathura);
268 269

  return false;
270 271
}

272
void
273
cb_scale_factor(GObject* object, GParamSpec* UNUSED(pspec), gpointer data)
274
{
275 276
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL) {
277
    return;
278 279
  }

280
  int new_factor = gtk_widget_get_scale_factor(GTK_WIDGET(object));
281 282 283 284
  if (new_factor == 0) {
    girara_debug("Ignoring new device scale factor = 0");
    return;
  }
285

286 287 288 289 290
  zathura_device_factors_t current = zathura_document_get_device_factors(zathura->document);
  if (fabs(new_factor - current.x) >= DBL_EPSILON ||
      fabs(new_factor - current.y) >= DBL_EPSILON) {
    zathura_document_set_device_factors(zathura->document, new_factor, new_factor);
    girara_debug("New device scale factor: %d", new_factor);
291
    zathura_update_view_ppi(zathura);
292 293 294 295
    render_all(zathura);
  }
}

296
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
297
cb_page_layout_value_changed(girara_session_t* session, const char* name, girara_setting_type_t UNUSED(type), const void* value, void* UNUSED(data))
298
{
299
  g_return_if_fail(value != NULL);
300 301 302
  g_return_if_fail(session != NULL);
  g_return_if_fail(session->global.data != NULL);
  zathura_t* zathura = session->global.data;
303

Moritz Lipp's avatar
Moritz Lipp committed
304 305
  /* pages-per-row must not be 0 */
  if (g_strcmp0(name, "pages-per-row") == 0) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
306
    unsigned int pages_per_row = *((const unsigned int*) value);
Moritz Lipp's avatar
Moritz Lipp committed
307 308 309
    if (pages_per_row == 0) {
      pages_per_row = 1;
      girara_setting_set(session, name, &pages_per_row);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
310
      girara_notify(session, GIRARA_WARNING, _("'%s' must not be 0. Set to 1."), name);
Moritz Lipp's avatar
Moritz Lipp committed
311 312 313 314
      return;
    }
  }

315 316 317 318
  if (zathura->document == NULL) {
    /* no document has been openend yet */
    return;
  }
319

320 321
  unsigned int pages_per_row = 1;
  girara_setting_get(session, "pages-per-row", &pages_per_row);
322

323 324 325 326 327 328 329
  /* get list of first_page_column settings */
  char* first_page_column_list = NULL;
  girara_setting_get(session, "first-page-column", &first_page_column_list);

  /* find value for first_page_column */
  unsigned int first_page_column = find_first_page_column(first_page_column_list, pages_per_row);
  g_free(first_page_column_list);
330

331
  unsigned int page_padding = 1;
332
  girara_setting_get(zathura->ui.session, "page-padding", &page_padding);
333

334 335 336 337
  bool page_right_to_left = false;
  girara_setting_get(zathura->ui.session, "page-right-to-left", &page_right_to_left);

  page_widget_set_mode(zathura, page_padding, pages_per_row, first_page_column, page_right_to_left);
338
  zathura_document_set_page_layout(zathura->document, page_padding, pages_per_row, first_page_column);
339
}
340 341

void
Moritz Lipp's avatar
Moritz Lipp committed
342
cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path,
Moritz Lipp's avatar
Moritz Lipp committed
343
                       GtkTreeViewColumn* UNUSED(column), void* data)
344
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
345
  zathura_t* zathura = data;
346 347 348 349 350 351 352
  if (tree_view == NULL || zathura == NULL || zathura->ui.session == NULL) {
    return;
  }

  GtkTreeModel  *model;
  GtkTreeIter   iter;

Sebastian Ramacher's avatar
Sebastian Ramacher committed
353
  g_object_get(G_OBJECT(tree_view), "model", &model, NULL);
354

Moritz Lipp's avatar
Moritz Lipp committed
355
  if(gtk_tree_model_get_iter(model, &iter, path)) {
356
    zathura_index_element_t* index_element;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
357
    gtk_tree_model_get(model, &iter, 2, &index_element, -1);
358 359 360 361 362

    if (index_element == NULL) {
      return;
    }

Moritz Lipp's avatar
Moritz Lipp committed
363
    sc_toggle_index(zathura->ui.session, NULL, NULL, 0);
364
    zathura_link_evaluate(zathura, index_element->link);
365 366 367 368
  }

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

370 371 372 373 374 375 376 377 378
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
379 380 381 382 383
{
  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
384
  bool eval = true;
Moritz Lipp's avatar
Moritz Lipp committed
385 386

  char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
Moritz Lipp's avatar
Moritz Lipp committed
387 388
  if (input == NULL || strlen(input) == 0) {
    eval = false;
Moritz Lipp's avatar
Moritz Lipp committed
389 390
  }

Moritz Lipp's avatar
Moritz Lipp committed
391 392 393 394
  int index = 0;
  if (eval == true) {
    index = atoi(input);
    if (index == 0 && g_strcmp0(input, "0") != 0) {
395
      girara_notify(session, GIRARA_WARNING, _("Invalid input '%s' given."), input);
Moritz Lipp's avatar
Moritz Lipp committed
396 397 398
      eval = false;
    }
    index = index - 1;
Moritz Lipp's avatar
Moritz Lipp committed
399 400 401 402
  }

  /* set pages to draw links */
  bool invalid_index = true;
403 404 405
  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
406
    if (page == NULL || zathura_page_get_visibility(page) == false) {
Moritz Lipp's avatar
Moritz Lipp committed
407 408 409
      continue;
    }

410
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
411
    g_object_set(G_OBJECT(page_widget), "draw-links", FALSE, NULL);
412

Moritz Lipp's avatar
Moritz Lipp committed
413
    if (eval == true) {
Moritz Lipp's avatar
Moritz Lipp committed
414
      zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page_widget), index);
415

Moritz Lipp's avatar
Moritz Lipp committed
416 417
      if (link != NULL) {
        invalid_index = false;
418 419 420 421 422 423 424 425
        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
426 427 428 429
      }
    }
  }

Moritz Lipp's avatar
Moritz Lipp committed
430
  if (eval == true && invalid_index == true) {
431
    girara_notify(session, GIRARA_WARNING, _("Invalid index '%s' given."), input);
Moritz Lipp's avatar
Moritz Lipp committed
432 433 434 435
  }

  g_free(input);

Moritz Lipp's avatar
Moritz Lipp committed
436
  return (eval == TRUE) ? TRUE : FALSE;
Moritz Lipp's avatar
Moritz Lipp committed
437
}
Moritz Lipp's avatar
Moritz Lipp committed
438

439
gboolean
440
cb_sc_follow(GtkEntry* entry, void* data)
441
{
442
  girara_session_t* session = data;
443 444 445
  return handle_link(entry, session, ZATHURA_LINK_ACTION_FOLLOW);
}

446
gboolean
447
cb_sc_display_link(GtkEntry* entry, void* data)
448
{
449
  girara_session_t* session = data;
450 451 452
  return handle_link(entry, session, ZATHURA_LINK_ACTION_DISPLAY);
}

453 454 455 456 457 458 459
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
460
void
461
cb_file_monitor(ZathuraFileMonitor* monitor, girara_session_t* session)
Moritz Lipp's avatar
Moritz Lipp committed
462 463 464 465
{
  g_return_if_fail(monitor  != NULL);
  g_return_if_fail(session  != NULL);

466
  g_main_context_invoke(NULL, file_monitor_reload, session);
Moritz Lipp's avatar
Moritz Lipp committed
467
}
468

469 470 471 472
static gboolean
password_dialog(gpointer data)
{
  zathura_password_dialog_info_t* dialog = data;
Moritz Lipp's avatar
Moritz Lipp committed
473

474
  if (dialog != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
475
    girara_dialog(
Moritz Lipp's avatar
Moritz Lipp committed
476 477 478 479
      dialog->zathura->ui.session,
      "Incorrect password. Enter password:",
      true,
      NULL,
480
      cb_password_dialog,
Moritz Lipp's avatar
Moritz Lipp committed
481 482
      dialog
    );
483
  }
Moritz Lipp's avatar
Moritz Lipp committed
484

485 486 487
  return FALSE;
}

488
gboolean
489
cb_password_dialog(GtkEntry* entry, void* data)
490
{
491
  if (entry == NULL || data == NULL) {
492 493 494
    goto error_ret;
  }

495 496
  zathura_password_dialog_info_t* dialog = data;

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
  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);
    }

514
    gdk_threads_add_idle(password_dialog, dialog);
515 516 517 518
    return false;
  }

  /* try to open document again */
Lukas K.'s avatar
Lukas K. committed
519
  if (document_open(dialog->zathura, dialog->path, dialog->uri, input,
520
                    ZATHURA_PAGE_NUMBER_UNSPECIFIED) == false) {
521
    gdk_threads_add_idle(password_dialog, dialog);
522 523
  } else {
    g_free(dialog->path);
Lukas K.'s avatar
Lukas K. committed
524
    g_free(dialog->uri);
525 526
    free(dialog);
  }
527 528 529 530 531 532 533

  g_free(input);

  return true;

error_free:

Moritz Lipp's avatar
Moritz Lipp committed
534 535
  g_free(dialog->path);
  free(dialog);
536 537 538 539 540

error_ret:

  return false;
}
541

542
gboolean
543
cb_view_resized(GtkWidget* UNUSED(widget), GtkAllocation* UNUSED(allocation), zathura_t* zathura)
544 545 546 547 548
{
  if (zathura == NULL || zathura->document == NULL) {
    return false;
  }

549 550
  /* adjust the scale according to settings. If nothing needs to be resized,
     it does not trigger the resize event.
551

552 553 554 555
     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);
556 557

  return false;
558
}
Moritz Lipp's avatar
Moritz Lipp committed
559 560 561

void
cb_setting_recolor_change(girara_session_t* session, const char* name,
Sebastian Ramacher's avatar
Sebastian Ramacher committed
562
                          girara_setting_type_t UNUSED(type), const void* value, void* UNUSED(data))
Moritz Lipp's avatar
Moritz Lipp committed
563 564 565 566 567 568 569
{
  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;

Sebastian Ramacher's avatar
Sebastian Ramacher committed
570
  const bool bool_value = *((const bool*) value);
Moritz Lipp's avatar
Moritz Lipp committed
571

572 573 574
  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
575 576
  }
}
Moritz Lipp's avatar
Moritz Lipp committed
577

578 579
void
cb_setting_recolor_keep_hue_change(girara_session_t* session, const char* name,
Sebastian Ramacher's avatar
Sebastian Ramacher committed
580
                                   girara_setting_type_t UNUSED(type), const void* value, void* UNUSED(data))
581 582 583 584 585 586 587
{
  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;

Sebastian Ramacher's avatar
Sebastian Ramacher committed
588
  const bool bool_value = *((const bool*) value);
589

590 591 592
  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);
593 594 595
  }
}

596 597
void
cb_setting_recolor_keep_reverse_video_change(girara_session_t* session, const char* name,
Sebastian Ramacher's avatar
Sebastian Ramacher committed
598
                                   girara_setting_type_t UNUSED(type), const void* value, void* UNUSED(data))
599 600 601 602 603 604 605
{
  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;

Sebastian Ramacher's avatar
Sebastian Ramacher committed
606
  const bool bool_value = *((const bool*) value);
607 608 609 610 611 612

  if (zathura->sync.render_thread != NULL && zathura_renderer_recolor_reverse_video_enabled(zathura->sync.render_thread) != bool_value) {
     zathura_renderer_enable_recolor_reverse_video(zathura->sync.render_thread, bool_value);
     render_all(zathura);
  }
}
613

Moritz Lipp's avatar
Moritz Lipp committed
614 615 616 617 618 619 620 621 622 623 624 625 626 627
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 */
628 629
  const size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
Moritz Lipp's avatar
Moritz Lipp committed
630 631 632 633 634
    if (g_ascii_isdigit(input[i]) == FALSE) {
      return false;
    }
  }

635
  zathura_jumplist_add(zathura);
Moritz Lipp's avatar
Moritz Lipp committed
636
  page_set(zathura, atoi(input) - 1);
637
  zathura_jumplist_add(zathura);
Moritz Lipp's avatar
Moritz Lipp committed
638 639 640

  return true;
}
641 642 643 644 645 646 647 648 649

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;
650 651 652 653 654
  girara_mode_t mode = girara_mode_get(zathura->ui.session);
  if (mode != zathura->modes.normal && mode != zathura->modes.fullscreen) {
    return;
  }

655 656 657 658 659 660
  GdkAtom* selection = get_selection(zathura);

  /* copy to clipboard */
  if (selection != NULL) {
    gtk_clipboard_set_text(gtk_clipboard_get(*selection), text, -1);

661 662
    bool notification = true;
    girara_setting_get(zathura->ui.session, "selection-notification", &notification);
663

664
    if (notification == true) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
665 666 667
      char* target = NULL;
      girara_setting_get(zathura->ui.session, "selection-clipboard", &target);

668 669
      char* stripped_text = g_strdelimit(g_strdup(text), "\n\t\r\n", ' ');
      char* escaped_text = g_markup_printf_escaped(
Sebastian Ramacher's avatar
Sebastian Ramacher committed
670 671
          _("Copied selected text to selection %s: %s"), target, stripped_text);
      g_free(target);
672 673 674 675 676
      g_free(stripped_text);

      girara_notify(zathura->ui.session, GIRARA_INFO, "%s", escaped_text);
      g_free(escaped_text);
    }
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
  }

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

695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
    bool notification = true;
    girara_setting_get(zathura->ui.session, "selection-notification", &notification);

    if (notification == true) {
      char* target = NULL;
      girara_setting_get(zathura->ui.session, "selection-clipboard", &target);

      char* escaped_text = g_markup_printf_escaped(
          _("Copied selected image to selection %s"), target);
      g_free(target);

      girara_notify(zathura->ui.session, GIRARA_INFO, "%s", escaped_text);
    }

    g_free(selection);
  }
711
}
712 713 714 715 716 717 718 719 720

void
cb_page_widget_link(ZathuraPage* page, void* data)
{
  g_return_if_fail(page != NULL);

  bool enter = (bool) data;

  GdkWindow* window = gtk_widget_get_parent_window(GTK_WIDGET(page));
721 722
  GdkDisplay* display = gtk_widget_get_display(GTK_WIDGET(page));
  GdkCursor* cursor = gdk_cursor_new_for_display(display, enter == true ? GDK_HAND1 : GDK_LEFT_PTR);
723 724 725
  gdk_window_set_cursor(window, cursor);
  g_object_unref(cursor);
}
726 727 728 729 730

void
cb_page_widget_scaled_button_release(ZathuraPage* page_widget, GdkEventButton* event,
    void* data)
{
731 732 733 734 735
  zathura_t* zathura = data;

  zathura_page_t* page = zathura_page_widget_get_page(page_widget);

  /* set page number (but don't scroll there. it was clicked on, so it's visible) */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
736
  if (event->button == GDK_BUTTON_PRIMARY) {
737 738 739 740
    zathura_document_set_current_page_number(zathura->document, zathura_page_get_index(page));
    refresh_view(zathura);
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
741
  if (event->button != GDK_BUTTON_PRIMARY || !(event->state & GDK_CONTROL_MASK)) {
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
    return;
  }

  bool synctex = false;
  girara_setting_get(zathura->ui.session, "synctex", &synctex);
  if (synctex == false) {
    return;
  }

  if (zathura->dbus != NULL) {
    zathura_dbus_edit(zathura->dbus, zathura_page_get_index(page), event->x, event->y);
  }

  char* editor = NULL;
  girara_setting_get(zathura->ui.session, "synctex-editor-command", &editor);
  if (editor == NULL || *editor == '\0') {
758
    girara_debug("No SyncTeX editor specified.");
759 760 761 762 763 764 765
    g_free(editor);
    return;
  }

  synctex_edit(editor, page, event->x, event->y);
  g_free(editor);
}
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780

void
cb_window_update_icon(ZathuraRenderRequest* GIRARA_UNUSED(request), cairo_surface_t* surface, void* data)
{
  zathura_t* zathura = data;

  girara_debug("updating window icon");
  GdkPixbuf* pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface));
  if (pixbuf == NULL) {
    girara_error("Unable to convert cairo surface to Gdk Pixbuf.");
  }

  gtk_window_set_icon(GTK_WINDOW(zathura->ui.session->gtk.window), pixbuf);
  g_object_unref(pixbuf);
}