From 9c1e6ba4d99cb7f937b2b3998814a7486b88c4ce Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 5 Jan 2005 15:10:04 +0000 Subject: [PATCH] Beginnings of clipboard support. Incomplete but primary sort of work. 2005-01-05 Marco Pesenti Gritti * backend/ev-document.c: (ev_document_get_text): * backend/ev-document.h: * pdf/xpdf/pdf-document.cc: * shell/ev-view.c: (ev_view_realize), (expose_bin_window), (ev_view_primary_get_cb), (ev_view_primary_clear_cb), (ev_view_update_primary_selection), (ev_view_button_press_event), (ev_view_motion_notify_event), (ev_view_button_release_event): Beginnings of clipboard support. Incomplete but primary sort of work. --- ChangeLog | 13 +++++ backend/ev-document.c | 8 +++ backend/ev-document.h | 54 +++++++++++--------- pdf/xpdf/pdf-document.cc | 20 ++++++++ shell/ev-view.c | 107 +++++++++++++++++++++++++++++++++++---- 5 files changed, 168 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f4074c3..5ea38fb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2005-01-05 Marco Pesenti Gritti + + * backend/ev-document.c: (ev_document_get_text): + * backend/ev-document.h: + * pdf/xpdf/pdf-document.cc: + * shell/ev-view.c: (ev_view_realize), (expose_bin_window), + (ev_view_primary_get_cb), (ev_view_primary_clear_cb), + (ev_view_update_primary_selection), (ev_view_button_press_event), + (ev_view_motion_notify_event), (ev_view_button_release_event): + + Beginnings of clipboard support. Incomplete but primary sort + of work. + 2005-01-05 Marco Pesenti Gritti * shell/ev-view.c: (ev_gdk_color_to_rgb), (draw_rubberband), diff --git a/backend/ev-document.c b/backend/ev-document.c index 2306a21a..f0075466 100644 --- a/backend/ev-document.c +++ b/backend/ev-document.c @@ -161,6 +161,14 @@ ev_document_get_page_size (EvDocument *document, iface->get_page_size (document, width, height); } +char * +ev_document_get_text (EvDocument *document, + GdkRectangle *rect) +{ + EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + return iface->get_text (document, rect); +} + void ev_document_render (EvDocument *document, int clip_x, diff --git a/backend/ev-document.h b/backend/ev-document.h index c0a4b46c..ebf60af6 100644 --- a/backend/ev-document.h +++ b/backend/ev-document.h @@ -46,31 +46,33 @@ struct _EvDocumentIface void (* changed) (EvDocument *document); /* Methods */ - gboolean (* load) (EvDocument *document, - const char *uri, - GError **error); - gboolean (* save) (EvDocument *document, - const char *uri, - GError **error); - int (* get_n_pages) (EvDocument *document); - void (* set_page) (EvDocument *document, - int page); - int (* get_page) (EvDocument *document); - void (* set_target) (EvDocument *document, - GdkDrawable *target); - void (* set_scale) (EvDocument *document, - double scale); - void (* set_page_offset) (EvDocument *document, - int x, - int y); - void (* get_page_size) (EvDocument *document, - int *width, - int *height); - void (* render) (EvDocument *document, - int clip_x, - int clip_y, - int clip_width, - int clip_height); + gboolean (* load) (EvDocument *document, + const char *uri, + GError **error); + gboolean (* save) (EvDocument *document, + const char *uri, + GError **error); + int (* get_n_pages) (EvDocument *document); + void (* set_page) (EvDocument *document, + int page); + int (* get_page) (EvDocument *document); + void (* set_target) (EvDocument *document, + GdkDrawable *target); + void (* set_scale) (EvDocument *document, + double scale); + void (* set_page_offset) (EvDocument *document, + int x, + int y); + void (* get_page_size) (EvDocument *document, + int *width, + int *height); + char * (* get_text) (EvDocument *document, + GdkRectangle *rect); + void (* render) (EvDocument *document, + int clip_x, + int clip_y, + int clip_width, + int clip_height); }; GType ev_document_get_type (void); @@ -96,6 +98,8 @@ void ev_document_set_page_offset (EvDocument *document, void ev_document_get_page_size (EvDocument *document, int *width, int *height); +char *ev_document_get_text (EvDocument *document, + GdkRectangle *rect); void ev_document_render (EvDocument *document, int clip_x, int clip_y, diff --git a/pdf/xpdf/pdf-document.cc b/pdf/xpdf/pdf-document.cc index ed3b5054..2293841f 100644 --- a/pdf/xpdf/pdf-document.cc +++ b/pdf/xpdf/pdf-document.cc @@ -959,6 +959,25 @@ pdf_document_get_title (PdfDocument *pdf_document) return title; } +static char * +pdf_document_get_text (EvDocument *document, GdkRectangle *rect) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + GString *sel_text = new GString; + const char *text; + int x1, y1, x2, y2; + + x1 = rect->x; + y1 = rect->y; + x2 = x1 + rect->width; + y2 = y1 + rect->height; + + sel_text = pdf_document->out->getText (x1, y1, x2, y2); + text = sel_text->getCString (); + + return text ? g_strdup (text) : NULL; +} + static void pdf_document_get_property (GObject *object, guint prop_id, @@ -995,6 +1014,7 @@ pdf_document_document_iface_init (EvDocumentIface *iface) { iface->load = pdf_document_load; iface->save = pdf_document_save; + iface->get_text = pdf_document_get_text; iface->get_n_pages = pdf_document_get_n_pages; iface->set_page = pdf_document_set_page; iface->get_page = pdf_document_get_page; diff --git a/shell/ev-view.c b/shell/ev-view.c index 8616fea9..bd50b38b 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include "ev-marshal.h" @@ -31,6 +33,21 @@ #define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW)) #define EV_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_VIEW, EvViewClass)) +enum { + TARGET_STRING, + TARGET_TEXT, + TARGET_COMPOUND_TEXT, + TARGET_UTF8_STRING, + TARGET_TEXT_BUFFER_CONTENTS +}; + +static const GtkTargetEntry targets[] = { + { "STRING", 0, TARGET_STRING }, + { "TEXT", 0, TARGET_TEXT }, + { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }, + { "UTF8_STRING", 0, TARGET_UTF8_STRING }, +}; + struct _EvView { GtkWidget parent_instance; @@ -41,6 +58,9 @@ struct _EvView { int scroll_x; int scroll_y; + gboolean has_selection; + GdkRectangle selection; + GtkAdjustment *hadjustment; GtkAdjustment *vadjustment; @@ -247,8 +267,10 @@ ev_view_realize (GtkWidget *widget) attributes.height = MAX (widget->allocation.height, widget->requisition.height); attributes.event_mask = GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK | - GDK_KEY_PRESS_MASK; + GDK_KEY_PRESS_MASK | + GDK_BUTTON1_MOTION_MASK; view->bin_window = gdk_window_new (widget->window, &attributes, @@ -379,6 +401,10 @@ expose_bin_window (GtkWidget *widget, &results[i].highlight_area); ++i; } + + if (view->has_selection) { + draw_rubberband (widget, view->bin_window, &view->selection); + } } static gboolean @@ -395,14 +421,67 @@ ev_view_expose_event (GtkWidget *widget, return FALSE; } +static void +ev_view_primary_get_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gpointer data) +{ + EvView *ev_view = EV_VIEW (data); + char *text; + + text = ev_document_get_text (ev_view->document, &ev_view->selection); + gtk_selection_data_set_text (selection_data, text, -1); +} + +static void +ev_view_primary_clear_cb (GtkClipboard *clipboard, + gpointer data) +{ + EvView *ev_view = EV_VIEW (data); + + ev_view->has_selection = FALSE; +} + +static void +ev_view_update_primary_selection (EvView *ev_view) +{ + GtkClipboard *clipboard; + + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view), + GDK_SELECTION_PRIMARY); + + if (ev_view->has_selection) { + if (!gtk_clipboard_set_with_owner (clipboard, + targets, + G_N_ELEMENTS (targets), + ev_view_primary_get_cb, + ev_view_primary_clear_cb, + G_OBJECT (ev_view))) + ev_view_primary_clear_cb (clipboard, ev_view); + } else { + if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (ev_view)) + gtk_clipboard_clear (clipboard); + } +} + static gboolean ev_view_button_press_event (GtkWidget *widget, GdkEventButton *event) { - if (event->type == GDK_BUTTON_PRESS) { - if (!GTK_WIDGET_HAS_FOCUS (widget)) { - gtk_widget_grab_focus (widget); - } + EvView *view = EV_VIEW (widget); + + if (!GTK_WIDGET_HAS_FOCUS (widget)) { + gtk_widget_grab_focus (widget); + } + + switch (event->button) { + case 1: + view->selection.x = event->x; + view->selection.y = event->y; + view->selection.width = 0; + view->selection.height = 0; + break; } return TRUE; @@ -412,16 +491,26 @@ static gboolean ev_view_motion_notify_event (GtkWidget *widget, GdkEventMotion *event) { - /* EvView *view = EV_VIEW (widget); */ - - return FALSE; + EvView *view = EV_VIEW (widget); + + view->has_selection = TRUE; + view->selection.x = MIN (view->selection.x, event->x); + view->selection.y = MIN (view->selection.y, event->y); + view->selection.width = ABS (view->selection.x - event->x) + 1; + view->selection.height = ABS (view->selection.y - event->y) + 1; + + gtk_widget_queue_draw (widget); + + return TRUE; } static gboolean ev_view_button_release_event (GtkWidget *widget, GdkEventButton *event) { - /* EvView *view = EV_VIEW (widget); */ + EvView *view = EV_VIEW (widget); + + ev_view_update_primary_selection (view); return FALSE; } -- 2.43.5