mirror of
https://github.com/Gnucash/gnucash.git
synced 2026-09-03 20:53:02 -05:00
[r21886][Bug #667900] No clipboard copy and paste
Forward-port of r21886, done in the 2.4 branch to quickly resolve bug #667900 and to give windows users a nightly build to test with. Extends that change by also converting the GDK_SELECTION_PRIMARY operations to use GtkClipboard instead of GtkSelection. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@21918 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -582,9 +582,7 @@ gnc_item_edit_init (GncItemEdit *item_edit)
|
||||
item_edit->sheet = NULL;
|
||||
item_edit->parent = NULL;
|
||||
item_edit->editor = NULL;
|
||||
item_edit->clipboard = NULL;
|
||||
|
||||
item_edit->has_selection = FALSE;
|
||||
item_edit->is_popup = FALSE;
|
||||
item_edit->show_popup = FALSE;
|
||||
|
||||
@@ -654,12 +652,6 @@ gnc_item_edit_finalize (GObject *object)
|
||||
{
|
||||
GncItemEdit *item_edit = GNC_ITEM_EDIT (object);
|
||||
|
||||
if (item_edit->clipboard != NULL)
|
||||
{
|
||||
g_free (item_edit->clipboard);
|
||||
item_edit->clipboard = NULL;
|
||||
}
|
||||
|
||||
if (item_edit->gc)
|
||||
{
|
||||
g_object_unref (item_edit->gc);
|
||||
@@ -831,6 +823,7 @@ static void
|
||||
gnc_item_edit_cut_copy_clipboard (GncItemEdit *item_edit, guint32 time, gboolean cut)
|
||||
{
|
||||
GtkEditable *editable;
|
||||
GtkClipboard *clipboard;
|
||||
gint start_sel, end_sel;
|
||||
gchar *clip;
|
||||
|
||||
@@ -842,15 +835,13 @@ gnc_item_edit_cut_copy_clipboard (GncItemEdit *item_edit, guint32 time, gboolean
|
||||
if (!gtk_editable_get_selection_bounds (editable, &start_sel, &end_sel))
|
||||
return;
|
||||
|
||||
g_free(item_edit->clipboard);
|
||||
|
||||
if (gtk_selection_owner_set (GTK_WIDGET(item_edit->sheet),
|
||||
clipboard_atom, time))
|
||||
clip = gtk_editable_get_chars (editable, start_sel, end_sel);
|
||||
else
|
||||
clip = NULL;
|
||||
|
||||
item_edit->clipboard = clip;
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (editable),
|
||||
clipboard_atom);
|
||||
g_return_if_fail (clipboard != NULL);
|
||||
g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
|
||||
clip = gtk_editable_get_chars (editable, start_sel, end_sel);
|
||||
gtk_clipboard_set_text (clipboard, clip, -1);
|
||||
g_free (clip);
|
||||
|
||||
if (!cut)
|
||||
return;
|
||||
@@ -874,32 +865,53 @@ gnc_item_edit_copy_clipboard (GncItemEdit *item_edit, guint32 time)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gnc_item_edit_paste_clipboard (GncItemEdit *item_edit, guint32 time)
|
||||
|
||||
static void
|
||||
paste_received (GtkClipboard *clipboard, const gchar *text, gpointer data)
|
||||
{
|
||||
GtkEditable *editable = GTK_EDITABLE (data);
|
||||
gboolean reselect = FALSE;
|
||||
gint old_pos, tmp_pos;
|
||||
gint start_sel, end_sel;
|
||||
|
||||
if (text == NULL)
|
||||
return;
|
||||
if (gtk_editable_get_selection_bounds (editable, &start_sel, &end_sel))
|
||||
{
|
||||
reselect = TRUE;
|
||||
gtk_editable_delete_text (editable, start_sel, end_sel);
|
||||
}
|
||||
|
||||
tmp_pos = old_pos = gtk_editable_get_position (editable);
|
||||
|
||||
gtk_editable_insert_text (editable, text, -1, &tmp_pos);
|
||||
gtk_editable_set_position (editable, tmp_pos);
|
||||
|
||||
if (!reselect)
|
||||
return;
|
||||
|
||||
gtk_editable_select_region (editable, old_pos,
|
||||
gtk_editable_get_position (editable));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gnc_item_edit_paste_selection (GncItemEdit *item_edit, GdkAtom selection,
|
||||
guint32 time)
|
||||
{
|
||||
GtkClipboard *clipboard;
|
||||
g_return_if_fail(item_edit != NULL);
|
||||
g_return_if_fail(GNC_IS_ITEM_EDIT(item_edit));
|
||||
|
||||
gtk_selection_convert(GTK_WIDGET(item_edit->sheet),
|
||||
clipboard_atom,
|
||||
gdk_atom_intern("UTF8_STRING", FALSE),
|
||||
time);
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (item_edit->sheet),
|
||||
selection);
|
||||
|
||||
g_return_if_fail (clipboard != NULL);
|
||||
g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
|
||||
|
||||
gtk_clipboard_request_text (clipboard, paste_received, item_edit->editor);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gnc_item_edit_paste_primary (GncItemEdit *item_edit, guint32 time)
|
||||
{
|
||||
g_return_if_fail(item_edit != NULL);
|
||||
g_return_if_fail(GNC_IS_ITEM_EDIT(item_edit));
|
||||
|
||||
gtk_selection_convert(GTK_WIDGET(item_edit->sheet),
|
||||
GDK_SELECTION_PRIMARY,
|
||||
gdk_atom_intern("UTF8_STRING", FALSE),
|
||||
time);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gnc_item_edit_show_popup_toggle (GncItemEdit *item_edit,
|
||||
gint x, gint y,
|
||||
@@ -1464,153 +1476,3 @@ gnc_item_edit_get_has_selection (GncItemEdit *item_edit)
|
||||
return gtk_editable_get_selection_bounds(editable, NULL, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gnc_item_edit_selection_clear (GncItemEdit *item_edit,
|
||||
GdkEventSelection *event)
|
||||
{
|
||||
g_return_val_if_fail(item_edit != NULL, FALSE);
|
||||
g_return_val_if_fail(GNC_IS_ITEM_EDIT(item_edit), FALSE);
|
||||
g_return_val_if_fail(event != NULL, FALSE);
|
||||
|
||||
/* Let the selection handling code know that the selection
|
||||
* has been changed, since we've overriden the default handler */
|
||||
if (!gtk_selection_clear (GTK_WIDGET(item_edit->sheet), event))
|
||||
return FALSE;
|
||||
|
||||
if (event->selection == GDK_SELECTION_PRIMARY)
|
||||
{
|
||||
if (item_edit->has_selection)
|
||||
{
|
||||
item_edit->has_selection = FALSE;
|
||||
/* TODO: redraw differently? */
|
||||
}
|
||||
}
|
||||
else if (event->selection == clipboard_atom)
|
||||
{
|
||||
g_free (item_edit->clipboard);
|
||||
item_edit->clipboard = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gnc_item_edit_selection_get (GncItemEdit *item_edit,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time)
|
||||
{
|
||||
GtkEditable *editable;
|
||||
|
||||
gint start_pos;
|
||||
gint end_pos;
|
||||
|
||||
gchar *str;
|
||||
gint length;
|
||||
|
||||
g_return_if_fail(item_edit != NULL);
|
||||
g_return_if_fail(GNC_IS_ITEM_EDIT(item_edit));
|
||||
|
||||
editable = GTK_EDITABLE (item_edit->editor);
|
||||
|
||||
if (selection_data->selection == GDK_SELECTION_PRIMARY)
|
||||
{
|
||||
gtk_editable_get_selection_bounds (editable, &start_pos, &end_pos);
|
||||
|
||||
str = gtk_editable_get_chars(editable, start_pos, end_pos);
|
||||
}
|
||||
else /* CLIPBOARD */
|
||||
{
|
||||
str = item_edit->clipboard;
|
||||
}
|
||||
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
length = strlen(str);
|
||||
gtk_selection_data_set_text(selection_data, str, length);
|
||||
|
||||
if (str != item_edit->clipboard)
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gnc_item_edit_selection_received (GncItemEdit *item_edit,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
{
|
||||
GtkEditable *editable;
|
||||
gboolean reselect;
|
||||
gint old_pos;
|
||||
gint tmp_pos;
|
||||
gint start_sel, end_sel;
|
||||
enum {INVALID, CTEXT} type;
|
||||
|
||||
g_return_if_fail(item_edit != NULL);
|
||||
g_return_if_fail(GNC_IS_ITEM_EDIT(item_edit));
|
||||
|
||||
editable = GTK_EDITABLE(item_edit->editor);
|
||||
|
||||
/* @fixme: this should implement the fallback logic from
|
||||
* gtkclipboard.c:request_text_received_func. It'd be nice to have a
|
||||
* good way to test the various request types. :( --jsled **/
|
||||
|
||||
if (selection_data->type == GDK_TARGET_STRING
|
||||
|| selection_data->type == gdk_atom_intern("UTF8_STRING", FALSE)
|
||||
|| selection_data->type == gdk_atom_intern("COMPOUND_TEXT", FALSE)
|
||||
|| selection_data->type == gdk_atom_intern("TEXT", FALSE))
|
||||
{
|
||||
type = CTEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = INVALID;
|
||||
}
|
||||
|
||||
if (type == INVALID || selection_data->length < 0)
|
||||
{
|
||||
/* avoid infinite loop */
|
||||
if (selection_data->target != GDK_TARGET_STRING)
|
||||
{
|
||||
gtk_selection_convert(GTK_WIDGET(item_edit->sheet),
|
||||
selection_data->selection,
|
||||
GDK_TARGET_STRING, time);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
reselect = FALSE;
|
||||
|
||||
if (gtk_editable_get_selection_bounds(editable, &start_sel, &end_sel)
|
||||
&& (!item_edit->has_selection
|
||||
|| selection_data->selection == clipboard_atom))
|
||||
{
|
||||
reselect = TRUE;
|
||||
gtk_editable_delete_text(editable, start_sel, end_sel);
|
||||
}
|
||||
|
||||
tmp_pos = old_pos = gtk_editable_get_position (editable);
|
||||
|
||||
{
|
||||
guchar *sel = gtk_selection_data_get_text(selection_data);
|
||||
|
||||
if (sel)
|
||||
{
|
||||
gtk_editable_insert_text(editable,
|
||||
(gchar *)sel,
|
||||
strlen((char *)sel),
|
||||
&tmp_pos);
|
||||
gtk_editable_set_position(editable, tmp_pos);
|
||||
g_free(sel);
|
||||
}
|
||||
}
|
||||
|
||||
if (!reselect)
|
||||
return;
|
||||
|
||||
gtk_editable_select_region(editable, old_pos, gtk_editable_get_position (editable));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +75,6 @@ typedef struct
|
||||
/* The editor whose status we reflect on the sheet */
|
||||
GtkWidget *editor;
|
||||
|
||||
gchar *clipboard;
|
||||
|
||||
gboolean has_selection;
|
||||
|
||||
gboolean is_popup;
|
||||
@@ -147,24 +145,11 @@ void gnc_item_edit_redraw (GncItemEdit *item_edit);
|
||||
|
||||
void gnc_item_edit_cut_clipboard (GncItemEdit *item_edit, guint32 time);
|
||||
void gnc_item_edit_copy_clipboard (GncItemEdit *item_edit, guint32 time);
|
||||
void gnc_item_edit_paste_clipboard (GncItemEdit *item_edit, guint32 time);
|
||||
void gnc_item_edit_paste_primary (GncItemEdit *item_edit, guint32 time);
|
||||
void gnc_item_edit_paste_selection (GncItemEdit *item_edit, GdkAtom selection,
|
||||
guint32 time);
|
||||
|
||||
void gnc_item_edit_set_has_selection (GncItemEdit *item_edit, gboolean has_selection);
|
||||
gboolean gnc_item_edit_get_has_selection (GncItemEdit *item_edit);
|
||||
|
||||
gboolean gnc_item_edit_selection_clear (GncItemEdit *item_edit,
|
||||
GdkEventSelection *event);
|
||||
|
||||
void gnc_item_edit_selection_get (GncItemEdit *item_edit,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time);
|
||||
|
||||
void gnc_item_edit_selection_received (GncItemEdit *item_edit,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time);
|
||||
|
||||
void gnc_item_edit_focus_in (GncItemEdit *item_edit);
|
||||
void gnc_item_edit_focus_out (GncItemEdit *item_edit);
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include "gnucash-sheet.h"
|
||||
|
||||
@@ -1406,8 +1408,9 @@ gnucash_button_press_event (GtkWidget *widget, GdkEventButton *event)
|
||||
case 2:
|
||||
if (event->type != GDK_BUTTON_PRESS)
|
||||
return FALSE;
|
||||
gnc_item_edit_paste_primary(GNC_ITEM_EDIT(sheet->item_editor),
|
||||
event->time);
|
||||
gnc_item_edit_paste_selection (GNC_ITEM_EDIT(sheet->item_editor),
|
||||
GDK_SELECTION_PRIMARY,
|
||||
event->time);
|
||||
return TRUE;
|
||||
case 3:
|
||||
do_popup = (sheet->popup != NULL);
|
||||
@@ -1445,8 +1448,8 @@ gnucash_button_press_event (GtkWidget *widget, GdkEventButton *event)
|
||||
{
|
||||
gtk_grab_add(widget);
|
||||
sheet->grabbed = TRUE;
|
||||
gnc_item_edit_set_has_selection
|
||||
(GNC_ITEM_EDIT(sheet->item_editor), TRUE);
|
||||
gnc_item_edit_set_has_selection (GNC_ITEM_EDIT(sheet->item_editor),
|
||||
TRUE);
|
||||
}
|
||||
|
||||
if (virt_loc_equal (new_virt_loc, cur_virt_loc) && sheet->editing)
|
||||
@@ -1549,7 +1552,8 @@ gnucash_register_paste_clipboard (GnucashRegister *reg)
|
||||
sheet = GNUCASH_SHEET(reg->sheet);
|
||||
item_edit = GNC_ITEM_EDIT(sheet->item_editor);
|
||||
|
||||
gnc_item_edit_paste_clipboard(item_edit, GDK_CURRENT_TIME);
|
||||
gnc_item_edit_paste_selection (item_edit, GDK_SELECTION_CLIPBOARD,
|
||||
GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1610,14 +1614,16 @@ gnucash_sheet_clipboard_event (GnucashSheet *sheet, GdkEventKey *event)
|
||||
case GDK_v:
|
||||
if (event->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
gnc_item_edit_paste_clipboard(item_edit, time);
|
||||
gnc_item_edit_paste_selection (item_edit, GDK_SELECTION_CLIPBOARD,
|
||||
time);
|
||||
handled = TRUE;
|
||||
}
|
||||
break;
|
||||
case GDK_Insert:
|
||||
if (event->state & GDK_SHIFT_MASK)
|
||||
{
|
||||
gnc_item_edit_paste_clipboard(item_edit, time);
|
||||
gnc_item_edit_paste_selection (item_edit, GDK_SELECTION_CLIPBOARD,
|
||||
time);
|
||||
handled = TRUE;
|
||||
}
|
||||
else if (event->state & GDK_CONTROL_MASK)
|
||||
@@ -2544,53 +2550,6 @@ gnucash_sheet_table_load (GnucashSheet *sheet, gboolean do_scroll)
|
||||
gnucash_sheet_activate_cursor_cell (sheet, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnucash_sheet_selection_clear (GtkWidget *widget,
|
||||
GdkEventSelection *event)
|
||||
{
|
||||
GnucashSheet *sheet;
|
||||
|
||||
g_return_val_if_fail(widget != NULL, FALSE);
|
||||
g_return_val_if_fail(GNUCASH_IS_SHEET(widget), FALSE);
|
||||
|
||||
sheet = GNUCASH_SHEET(widget);
|
||||
|
||||
return gnc_item_edit_selection_clear(GNC_ITEM_EDIT(sheet->item_editor), event);
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_selection_get (GtkWidget *widget,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time)
|
||||
{
|
||||
GnucashSheet *sheet;
|
||||
|
||||
g_return_if_fail(widget != NULL);
|
||||
g_return_if_fail(GNUCASH_IS_SHEET(widget));
|
||||
|
||||
sheet = GNUCASH_SHEET(widget);
|
||||
|
||||
gnc_item_edit_selection_get(GNC_ITEM_EDIT(sheet->item_editor),
|
||||
selection_data, info, time);
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_selection_received (GtkWidget *widget,
|
||||
GtkSelectionData *selection_data,
|
||||
guint time)
|
||||
{
|
||||
GnucashSheet *sheet;
|
||||
|
||||
g_return_if_fail(widget != NULL);
|
||||
g_return_if_fail(GNUCASH_IS_SHEET(widget));
|
||||
|
||||
sheet = GNUCASH_SHEET(widget);
|
||||
|
||||
gnc_item_edit_selection_received(GNC_ITEM_EDIT(sheet->item_editor),
|
||||
selection_data, time);
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_realize_entry (GnucashSheet *sheet, GtkWidget *entry)
|
||||
{
|
||||
@@ -2738,9 +2697,6 @@ gnucash_sheet_class_init (GnucashSheetClass *class)
|
||||
widget_class->motion_notify_event = gnucash_motion_event;
|
||||
widget_class->scroll_event = gnucash_scroll_event;
|
||||
|
||||
widget_class->selection_clear_event = gnucash_sheet_selection_clear;
|
||||
widget_class->selection_received = gnucash_sheet_selection_received;
|
||||
widget_class->selection_get = gnucash_sheet_selection_get;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user