+
+void hide_unimplemented(void)
+{
+ gtk_widget_hide(GET_COMPONENT("filePrintOptions"));
+ gtk_widget_hide(GET_COMPONENT("journalFlatten"));
+ gtk_widget_hide(GET_COMPONENT("toolsSelectRegion"));
+ gtk_widget_hide(GET_COMPONENT("buttonSelectRegion"));
+ gtk_widget_hide(GET_COMPONENT("button2SelectRegion"));
+ gtk_widget_hide(GET_COMPONENT("button3SelectRegion"));
+ gtk_widget_hide(GET_COMPONENT("helpIndex"));
+
+ /* config file only works with glib 2.6 and beyond */
+ if (glib_minor_version<6) {
+ gtk_widget_hide(GET_COMPONENT("optionsAutoSavePrefs"));
+ gtk_widget_hide(GET_COMPONENT("optionsSavePreferences"));
+ }
+ /* gtkprint only works with gtk+ 2.10 and beyond */
+ if (gtk_check_version(2, 10, 0)) {
+ gtk_widget_hide(GET_COMPONENT("filePrint"));
+ }
+
+ /* screenshot feature doesn't work yet in Win32 */
+#ifdef WIN32
+ gtk_widget_hide(GET_COMPONENT("journalScreenshot"));
+#endif
+}
+
+// toggle fullscreen mode
+void do_fullscreen(gboolean active)
+{
+ end_text();
+ ui.fullscreen = active;
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen);
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), ui.fullscreen);
+
+ if (ui.fullscreen) {
+#ifdef WIN32
+ gtk_window_get_size(GTK_WINDOW(winMain), &ui.pre_fullscreen_width, &ui.pre_fullscreen_height);
+ gtk_widget_set_size_request(GTK_WIDGET(winMain), gdk_screen_width(),
+ gdk_screen_height());
+#endif
+ gtk_window_fullscreen(GTK_WINDOW(winMain));
+ }
+ else {
+#ifdef WIN32
+ gtk_widget_set_size_request(GTK_WIDGET(winMain), -1, -1);
+ gtk_window_resize(GTK_WINDOW(winMain), ui.pre_fullscreen_width,
+ ui.pre_fullscreen_height);
+#endif
+ gtk_window_unfullscreen(GTK_WINDOW(winMain));
+ }
+
+ update_vbox_order(ui.vertical_order[ui.fullscreen?1:0]);
+}
+
+/* attempt to work around GTK+ 2.16/2.17 bugs where random interface
+ elements receive XInput events that they can't handle properly */
+
+// prevent interface items from getting bogus XInput events
+
+gboolean filter_extended_events (GtkWidget *widget, GdkEvent *event,
+ gpointer user_data)
+{
+ if (event->type == GDK_MOTION_NOTIFY &&
+ event->motion.device != gdk_device_get_core_pointer())
+ return TRUE;
+ if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS ||
+ event->type == GDK_3BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
+ event->button.device != gdk_device_get_core_pointer())
+ return TRUE;
+ return FALSE;
+}
+
+/* Code to turn an extended input event into a core event and send it to
+ a different GdkWindow -- e.g. could be used when a click in a text edit box
+ gets sent to the canvas instead due to incorrect event translation.
+ We now turn off xinput altogether while editing text under GTK+ 2.17, so
+ this isn't needed any more... but could become useful again someday!
+*/
+
+/*
+gboolean fix_extended_events (GtkWidget *widget, GdkEvent *event,
+ gpointer user_data)
+{
+ int ix, iy;
+ GdkWindow *window;
+
+ if (user_data) window = (GdkWindow *)user_data;
+ else window = widget->window;
+
+ if (event->type == GDK_MOTION_NOTIFY &&
+ event->motion.device != gdk_device_get_core_pointer()) {
+// printf("fixing motion\n");
+ gdk_window_get_pointer(window, &ix, &iy, NULL);
+ event->motion.x = ix; event->motion.y = iy;
+ event->motion.device = gdk_device_get_core_pointer();
+ g_object_unref(event->motion.window);
+ event->motion.window = g_object_ref(window);
+ gtk_widget_event(widget, event);
+ return TRUE;
+ }
+ if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
+ event->button.device != gdk_device_get_core_pointer()) {
+// printf("fixing button from pos = %f, %f\n", event->button.x, event->button.y);
+ gdk_window_get_pointer(window, &ix, &iy, NULL);
+ event->button.x = ix; event->button.y = iy;
+ event->button.device = gdk_device_get_core_pointer();
+ g_object_unref(event->button.window);
+ event->button.window = g_object_ref(window);
+// printf("fixing button to pos = %f, %f\n", event->button.x, event->button.y);
+ gtk_widget_event(widget, event);
+ return TRUE;
+ }
+ return FALSE;
+}
+*/
+
+
+/* When enter is pressed into page spinbox, send focus back to canvas. */
+
+gboolean handle_activate_signal(GtkWidget *widget, gpointer user_data)
+{
+ reset_focus();
+ return FALSE;
+}
+
+/* recursively unset widget flags */
+
+void unset_flags(GtkWidget *w, gpointer flag)
+{
+ GTK_WIDGET_UNSET_FLAGS(w, (GtkWidgetFlags)flag);
+ if(GTK_IS_CONTAINER(w))
+ gtk_container_forall(GTK_CONTAINER(w), unset_flags, flag);
+}
+
+/* reset focus when a key or button press event reaches someone, or when the
+ page-number spin button should relinquish control... */
+
+gboolean intercept_activate_events(GtkWidget *w, GdkEvent *ev, gpointer data)
+{
+ if (w == GET_COMPONENT("hbox1")) {
+ /* the event won't be processed since the hbox1 doesn't know what to do with it,
+ so we might as well kill it and avoid confusing ourselves when it gets
+ propagated further ... */
+ return TRUE;
+ }
+ if (w == GET_COMPONENT("spinPageNo")) {
+ /* we let the spin button take care of itself, and don't steal its focus,
+ unless the user presses Esc or Tab (in those cases we intervene) */
+ if (ev->type != GDK_KEY_PRESS) return FALSE;
+ if (ev->key.keyval == GDK_Escape)
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), ui.pageno+1); // abort
+ else if (ev->key.keyval != GDK_Tab && ev->key.keyval != GDK_ISO_Left_Tab)
+ return FALSE; // let the spin button process it
+ }
+
+ // otherwise, we want to make sure the canvas or text item gets focus back...
+ reset_focus();
+ return FALSE;
+}
+
+void install_focus_hooks(GtkWidget *w, gpointer data)
+{
+ if (w == NULL) return;
+ g_signal_connect(w, "key-press-event", G_CALLBACK(intercept_activate_events), data);
+ g_signal_connect(w, "button-press-event", G_CALLBACK(intercept_activate_events), data);
+ if (GTK_IS_MENU_ITEM(w)) {
+ g_signal_connect(w, "activate", G_CALLBACK(intercept_activate_events), data);
+ install_focus_hooks(gtk_menu_item_get_submenu(GTK_MENU_ITEM(w)), data);
+ }
+ if(GTK_IS_CONTAINER(w))
+ gtk_container_forall(GTK_CONTAINER(w), install_focus_hooks, data);
+}
+
+// wrapper for missing poppler functions (defunct poppler-gdk api)
+
+static void
+wrapper_copy_cairo_surface_to_pixbuf (cairo_surface_t *surface,
+ GdkPixbuf *pixbuf)
+{
+ int cairo_width, cairo_height, cairo_rowstride;
+ unsigned char *pixbuf_data, *dst, *cairo_data;
+ int pixbuf_rowstride, pixbuf_n_channels;
+ unsigned int *src;
+ int x, y;
+
+ cairo_width = cairo_image_surface_get_width (surface);
+ cairo_height = cairo_image_surface_get_height (surface);
+ cairo_rowstride = cairo_image_surface_get_stride (surface);
+ cairo_data = cairo_image_surface_get_data (surface);
+
+ pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
+ pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+ if (cairo_width > gdk_pixbuf_get_width (pixbuf))
+ cairo_width = gdk_pixbuf_get_width (pixbuf);
+ if (cairo_height > gdk_pixbuf_get_height (pixbuf))
+ cairo_height = gdk_pixbuf_get_height (pixbuf);
+ for (y = 0; y < cairo_height; y++)
+ {
+ src = (unsigned int *) (cairo_data + y * cairo_rowstride);
+ dst = pixbuf_data + y * pixbuf_rowstride;
+ for (x = 0; x < cairo_width; x++)
+ {
+ dst[0] = (*src >> 16) & 0xff;
+ dst[1] = (*src >> 8) & 0xff;
+ dst[2] = (*src >> 0) & 0xff;
+ if (pixbuf_n_channels == 4)
+ dst[3] = (*src >> 24) & 0xff;
+ dst += pixbuf_n_channels;
+ src++;
+ }
+ }
+}
+
+void
+wrapper_poppler_page_render_to_pixbuf (PopplerPage *page,
+ int src_x, int src_y,
+ int src_width, int src_height,
+ double scale,
+ int rotation,
+ GdkPixbuf *pixbuf)
+{
+ cairo_t *cr;
+ cairo_surface_t *surface;
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ src_width, src_height);
+ cr = cairo_create (surface);
+ cairo_save (cr);
+ switch (rotation) {
+ case 90:
+ cairo_translate (cr, src_x + src_width, -src_y);
+ break;
+ case 180:
+ cairo_translate (cr, src_x + src_width, src_y + src_height);
+ break;
+ case 270:
+ cairo_translate (cr, -src_x, src_y + src_height);
+ break;
+ default:
+ cairo_translate (cr, -src_x, -src_y);
+ }
+
+ if (scale != 1.0)
+ cairo_scale (cr, scale, scale);
+
+ if (rotation != 0)
+ cairo_rotate (cr, rotation * G_PI / 180.0);
+
+ poppler_page_render (page, cr);
+ cairo_restore (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_source_rgb (cr, 1., 1., 1.);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
+ wrapper_copy_cairo_surface_to_pixbuf (surface, pixbuf);
+ cairo_surface_destroy (surface);
+}