[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:
John Ralls
2012-01-30 01:54:01 +00:00
parent 4376c08601
commit 53c7d0c8d1
3 changed files with 64 additions and 261 deletions
+49 -187
View File
@@ -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);
+13 -57
View File
@@ -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;
}