diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ev-view-private.h | 2 | ||||
-rw-r--r-- | shell/ev-view.c | 34 | ||||
-rw-r--r-- | shell/ev-window.c | 92 |
3 files changed, 119 insertions, 9 deletions
diff --git a/shell/ev-view-private.h b/shell/ev-view-private.h index 9a0c773..ef48e0b 100644 --- a/shell/ev-view-private.h +++ b/shell/ev-view-private.h @@ -128,6 +128,8 @@ struct _EvViewClass { void (*zoom_invalid) (EvView *view); void (*external_link) (EvView *view, EvLink *link); + void (*popup_menu) (EvView *view, + EvLink *link); }; #endif /* __EV_VIEW_PRIVATE_H__ */ diff --git a/shell/ev-view.c b/shell/ev-view.c index be6f295..c39a265 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -64,6 +64,7 @@ enum { SIGNAL_BINDING_ACTIVATED, SIGNAL_ZOOM_INVALID, SIGNAL_EXTERNAL_LINK, + SIGNAL_POPUP_MENU, N_SIGNALS, }; @@ -149,9 +150,9 @@ static void find_page_at_location (EvView gint *y_offset); /*** Hyperrefs ***/ -static EvLink* get_link_at_location (EvView *view, - gdouble x, - gdouble y); +static EvLink * ev_view_get_link_at_location (EvView *view, + gdouble x, + gdouble y); static char* tip_from_link (EvView *view, EvLink *link); static void handle_link_over_xy (EvView *view, @@ -1031,13 +1032,16 @@ location_in_selected_text (EvView *view, /*** Hyperref ***/ static EvLink * -get_link_at_location (EvView *view, - gdouble x, - gdouble y) +ev_view_get_link_at_location (EvView *view, + gdouble x, + gdouble y) { gint page = -1; gint x_offset = 0, y_offset = 0; GList *link_mapping; + + x += view->scroll_x; + y += view->scroll_y; find_page_at_location (view, x, y, &page, &x_offset, &y_offset); @@ -1254,7 +1258,7 @@ handle_link_over_xy (EvView *view, gint x, gint y) { EvLink *link; - link = get_link_at_location (view, x + view->scroll_x, y + view->scroll_y); + link = ev_view_get_link_at_location (view, x, y); if (view->link_tooltip == NULL) { view->link_tooltip = ev_tooltip_new (GTK_WIDGET (view)); @@ -1617,6 +1621,7 @@ ev_view_button_press_event (GtkWidget *widget, GdkEventButton *event) { EvView *view = EV_VIEW (widget); + EvLink *link; if (!GTK_WIDGET_HAS_FOCUS (widget)) { gtk_widget_grab_focus (widget); @@ -1654,6 +1659,10 @@ ev_view_button_press_event (GtkWidget *widget, ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG); return TRUE; + case 3: + link = ev_view_get_link_at_location (view, event->x, event->y); + g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, link); + return TRUE; } return FALSE; @@ -1835,8 +1844,7 @@ ev_view_button_release_event (GtkWidget *widget, } if (view->document) { - link = get_link_at_location (view, event->x + view->scroll_x, - event->y + view->scroll_y); + link = ev_view_get_link_at_location (view, event->x, event->y); } else { link = NULL; } @@ -2399,6 +2407,14 @@ ev_view_class_init (EvViewClass *class) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); + signals[SIGNAL_POPUP_MENU] = g_signal_new ("popup", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvViewClass, popup_menu), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); g_object_class_install_property (object_class, PROP_STATUS, diff --git a/shell/ev-window.c b/shell/ev-window.c index 77bb4c9..fde1dae 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -114,12 +114,18 @@ struct _EvWindowPrivate { /* UI Builders */ GtkActionGroup *action_group; + GtkActionGroup *popups_action_group; GtkUIManager *ui_manager; /* Fullscreen mode */ GtkWidget *fullscreen_toolbar; GtkWidget *fullscreen_popup; GSource *fullscreen_timeout_source; + + /* Popup link */ + GtkWidget *popup; + GtkWidget *link_popup; + EvLink *link; /* Document */ char *uri; @@ -191,6 +197,10 @@ static void ev_window_stop_presentation (EvWindow *windo static void ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window); static void show_fullscreen_popup (EvWindow *window); +static void ev_popup_cmd_open_link (GtkAction *action, + EvWindow *window); +static void ev_popup_cmd_copy_link_address (GtkAction *action, + EvWindow *window); G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW) @@ -2607,6 +2617,30 @@ ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_sidebar, GParamSpec *pspe } } +static gboolean +view_menu_popup_cb (EvView *view, + EvLink *link, + EvWindow *ev_window) +{ + GtkWidget *popup; + + if (ev_window->priv->link) + g_object_unref (ev_window->priv->link); + ev_window->priv->link = link; + + if (ev_window->priv->link && + (ev_link_get_link_type (ev_window->priv->link) == EV_LINK_TYPE_EXTERNAL_URI)) { + popup = ev_window->priv->link_popup; + } else { + popup = ev_window->priv->popup; + } + + gtk_menu_popup (GTK_MENU (popup), NULL, NULL, + NULL, NULL, + 3, gtk_get_current_event_time ()); + return TRUE; +} + static void view_find_status_changed_cb (EvView *view, GParamSpec *pspec, @@ -2751,6 +2785,11 @@ ev_window_dispose (GObject *object) priv->action_group = NULL; } + if (priv->popups_action_group) { + g_object_unref (priv->popups_action_group); + priv->popups_action_group = NULL; + } + if (priv->page_cache) { g_signal_handlers_disconnect_by_func (priv->page_cache, page_changed_cb, window); priv->page_cache = NULL; @@ -2793,6 +2832,11 @@ ev_window_dispose (GObject *object) gtk_widget_destroy (priv->password_dialog); } + if (priv->link) { + g_object_unref (priv->link); + priv->link = NULL; + } + if (priv->find_bar) { g_signal_handlers_disconnect_by_func (window->priv->find_bar, @@ -2983,6 +3027,16 @@ static const GtkToggleActionEntry toggle_entries[] = { G_CALLBACK (ev_window_cmd_view_page_width) }, }; +/* Popups specific items */ +static const GtkActionEntry popups_entries [] = { + /* Links */ + { "OpenLink", GTK_STOCK_OPEN, N_("_Open Link"), NULL, + NULL, G_CALLBACK (ev_popup_cmd_open_link) }, + { "CopyLinkAddress", NULL, N_("_Copy Link Address"), NULL, + NULL, + G_CALLBACK (ev_popup_cmd_copy_link_address) }, +}; + static void drag_data_received_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, @@ -3301,6 +3355,25 @@ view_external_link_cb (EvView *view, EvLink *link, EvWindow *window) } static void +ev_popup_cmd_open_link (GtkAction *action, EvWindow *window) +{ + launch_external_uri (window, window->priv->link); +} + +static void +ev_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window) +{ + GtkClipboard *clipboard; + const gchar *uri; + + uri = ev_link_get_uri (window->priv->link); + + clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), + GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text (clipboard, uri, -1); +} + +static void ev_window_init (EvWindow *ev_window) { GtkActionGroup *action_group; @@ -3343,6 +3416,14 @@ ev_window_init (EvWindow *ev_window) ev_window_set_view_accels_sensitivity (ev_window, FALSE); + action_group = gtk_action_group_new ("PopupsActions"); + ev_window->priv->popups_action_group = action_group; + gtk_action_group_set_translation_domain (action_group, NULL); + gtk_action_group_add_actions (action_group, popups_entries, + G_N_ELEMENTS (popups_entries), ev_window); + gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager, + action_group, 0); + if (!gtk_ui_manager_add_ui_from_file (ev_window->priv->ui_manager, DATADIR"/evince-ui.xml", &error)) { @@ -3443,6 +3524,10 @@ ev_window_init (EvWindow *ev_window) g_signal_connect_object (ev_window->priv->view, "external-link", G_CALLBACK (view_external_link_cb), ev_window, 0); + g_signal_connect_object (ev_window->priv->view, + "popup", + G_CALLBACK (view_menu_popup_cb), + ev_window, 0); gtk_widget_show (ev_window->priv->view); gtk_widget_show (ev_window->priv->password_view); @@ -3524,6 +3609,13 @@ ev_window_init (EvWindow *ev_window) G_CALLBACK (find_bar_search_changed_cb), ev_window); + /* Popups */ + ev_window->priv->link_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager, + "/ExternalLinkPopup"); + ev_window->priv->popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager, + "/DocumentPopup"); + ev_window->priv->link = NULL; + /* Give focus to the document view */ gtk_widget_grab_focus (ev_window->priv->view); |