aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/text/e-completion-test.c17
-rw-r--r--widgets/text/e-completion-view.c6
-rw-r--r--widgets/text/e-entry.c80
-rw-r--r--widgets/text/e-text.c24
4 files changed, 98 insertions, 29 deletions
diff --git a/widgets/text/e-completion-test.c b/widgets/text/e-completion-test.c
index 626842cb51..8550e9a10f 100644
--- a/widgets/text/e-completion-test.c
+++ b/widgets/text/e-completion-test.c
@@ -6,7 +6,7 @@
#include "e-completion.h"
#include "e-entry.h"
-#define TIMEOUT 50
+#define TIMEOUT 10
/* Dictionary Lookup test */
@@ -59,7 +59,7 @@ find_word (const gchar *str)
a = m;
else
return m;
- };
+ }
return b;
}
@@ -71,6 +71,7 @@ struct {
gint current;
gint len;
gint limit;
+ gint count;
} dict_info;
static guint dict_tag = 0;
@@ -88,15 +89,19 @@ dict_check (gpointer ptr)
}
i = dict_info.current;
- while (limit > 0 && i < word_count && g_strncasecmp (dict_info.txt, word_array[i], dict_info.len) == 0) {
+ while (limit > 0
+ && i < word_count
+ && dict_info.count < 50
+ && g_strncasecmp (dict_info.txt, word_array[i], dict_info.len) == 0) {
e_completion_found_match_full (dict_info.complete, word_array[i],
dict_info.len / (double)strlen (word_array[i]),
NULL, NULL);
++i;
--limit;
+ ++dict_info.count;
}
dict_info.current = i;
- dict_info.limit = MIN (dict_info.limit*2, 200);
+ dict_info.limit = MIN (dict_info.limit*2, 400);
if (limit != 0) {
dict_tag = 0;
@@ -125,10 +130,10 @@ begin_dict_search (ECompletion *complete, const gchar *txt, gint pos, gint limit
dict_info.start = -1;
dict_info.current = -1;
dict_info.len = len;
- dict_info.limit = 20;
+ dict_info.limit = 100;
+ dict_info.count = 0;
dict_tag = gtk_timeout_add (TIMEOUT, dict_check, NULL);
} else {
- g_message ("halting");
e_completion_end_search (complete);
}
}
diff --git a/widgets/text/e-completion-view.c b/widgets/text/e-completion-view.c
index 825e7c5e11..2ffb19f3e3 100644
--- a/widgets/text/e-completion-view.c
+++ b/widgets/text/e-completion-view.c
@@ -150,6 +150,7 @@ e_completion_view_class_init (ECompletionViewClass *klass)
gtk_object_class_add_signals (object_class, e_completion_view_signals, E_COMPLETION_VIEW_LAST_SIGNAL);
object_class->destroy = e_completion_view_destroy;
+
widget_class->key_press_event = e_completion_view_local_key_press_handler;
}
@@ -306,7 +307,7 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin
ECompletionView *cv = E_COMPLETION_VIEW (user_data);
gint dir = 0;
gboolean key_handled = TRUE;
-
+
/* Start up a completion.*/
if (cv->complete_key && key_event->keyval == cv->complete_key && !cv->editable) {
gtk_signal_emit (GTK_OBJECT (cv), e_completion_view_signals[E_COMPLETION_VIEW_BROWSE], NULL);
@@ -380,6 +381,7 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin
gtk_signal_emit (GTK_OBJECT (cv), e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE]);
stop_emission:
+
if (key_handled)
gtk_signal_emit_stop_by_name (GTK_OBJECT (w), "key_press_event");
@@ -518,6 +520,8 @@ e_completion_view_construct (ECompletionView *cv, ECompletion *completion)
/* Make sure we don't call construct twice. */
g_return_if_fail (cv->completion == NULL);
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (cv), GTK_CAN_FOCUS);
+
cv->completion = completion;
gtk_object_ref (GTK_OBJECT (completion));
diff --git a/widgets/text/e-entry.c b/widgets/text/e-entry.c
index 4ab21be725..b84e622de6 100644
--- a/widgets/text/e-entry.c
+++ b/widgets/text/e-entry.c
@@ -49,6 +49,12 @@
#include "e-text.h"
#include "e-entry.h"
+#define EVIL_POINTER_WARPING_HACK
+
+#ifdef EVIL_POINTER_WARPING_HACK
+#include <gdk/gdkx.h>
+#endif
+
#define MIN_ENTRY_WIDTH 150
#define INNER_BORDER 2
@@ -457,13 +463,13 @@ e_entry_show_popup (EEntry *entry, gboolean visible)
if (visible) {
GtkAllocation *dim = &(GTK_WIDGET (entry)->allocation);
- gint x, y, fudge;
+ gint x, y, xo, yo, fudge;
const GdkEventMask grab_mask = (GdkEventMask)GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK;
/* Figure out where to put our popup. */
- gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y);
- x += dim->x;
- y += dim->height + dim->y;
+ gdk_window_get_origin (GTK_WIDGET (entry)->window, &xo, &yo);
+ x = xo + dim->x;
+ y = yo + dim->height + dim->y;
/* Put our popup slightly to the right and up, to try to give a visual cue that this popup
is tied to this entry. Otherwise one-row popups can sort of "blend" with an entry
@@ -475,16 +481,41 @@ e_entry_show_popup (EEntry *entry, gboolean visible)
gtk_widget_set_uposition (pop, x, y);
e_completion_view_set_width (E_COMPLETION_VIEW (entry->priv->completion_view), dim->width);
+#ifdef EVIL_POINTER_WARPING_HACK
+ /*
+ I should have learned by now to listen to Havoc...
+ http://developer.gnome.org/doc/GGAD/faqs.html
+ */
+
+ if (! entry->priv->popup_is_visible) {
+ GdkWindow *gwin = GTK_WIDGET (entry)->window;
+ gint xx, yy;
+ gdk_window_get_pointer (gwin, &xx, &yy, NULL);
+ xx += xo;
+ yy += yo;
+
+ /* If we are inside the "zone of death" where the popup will appear, warp the pointer to safety.
+ This is a horrible thing to do. */
+ if (y <= yy && yy < yy + dim->height && x <= xx && xx < xx + dim->width) {
+ XWarpPointer (GDK_WINDOW_XDISPLAY (gwin), None, GDK_WINDOW_XWINDOW (gwin),
+ 0, 0, 0, 0,
+ xx - xo, (y-1) - yo);
+ }
+ }
+#endif
+
gtk_widget_show (pop);
if (! entry->priv->ptr_grab) {
- entry->priv->ptr_grab = gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE,
- grab_mask, NULL, NULL, GDK_CURRENT_TIME);
- if (entry->priv->ptr_grab)
- gtk_grab_add (GTK_WIDGET (entry->priv->completion_view));
+ entry->priv->ptr_grab = (0 == gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE,
+ grab_mask, NULL, NULL, GDK_CURRENT_TIME));
+ if (entry->priv->ptr_grab) {
+ gtk_grab_add (GTK_WIDGET (entry->priv->completion_view));
+ }
}
-
+
+
} else {
gtk_widget_hide (pop);
@@ -497,8 +528,6 @@ e_entry_show_popup (EEntry *entry, gboolean visible)
entry->priv->ptr_grab = FALSE;
entry->priv->last_completion_pos = -1;
-
-
}
e_completion_view_set_editable (E_COMPLETION_VIEW (entry->priv->completion_view), visible);
@@ -668,6 +697,24 @@ button_press_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data)
unbrowse_cb (E_COMPLETION_VIEW (w), entry);
}
+static gint
+key_press_cb (GtkWidget *w, GdkEventKey *ev, gpointer user_data)
+{
+ gint rv = 0;
+ /* Forward signal */
+ gtk_signal_emit_by_name (GTK_OBJECT (user_data), "key_press_event", ev, &rv);
+ return rv;
+}
+
+static gint
+key_release_cb (GtkWidget *w, GdkEventKey *ev, gpointer user_data)
+{
+ gint rv = 0;
+ /* Forward signal */
+ gtk_signal_emit_by_name (GTK_OBJECT (user_data), "key_release_event", ev, &rv);
+ return rv;
+}
+
void
e_entry_enable_completion_full (EEntry *entry, ECompletion *completion, gint delay, EEntryCompletionHandler handler)
{
@@ -725,7 +772,16 @@ e_entry_enable_completion_full (EEntry *entry, ECompletion *completion, gint del
entry);
entry->priv->completion_view_popup = gtk_window_new (GTK_WINDOW_POPUP);
-
+
+ gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view_popup),
+ "key_press_event",
+ GTK_SIGNAL_FUNC (key_press_cb),
+ entry->canvas);
+ gtk_signal_connect (GTK_OBJECT (entry->priv->completion_view_popup),
+ "key_release_event",
+ GTK_SIGNAL_FUNC (key_release_cb),
+ entry->canvas);
+
gtk_object_ref (GTK_OBJECT (entry->priv->completion_view_popup));
gtk_object_sink (GTK_OBJECT (entry->priv->completion_view_popup));
gtk_window_set_policy (GTK_WINDOW (entry->priv->completion_view_popup), FALSE, TRUE, FALSE);
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c
index ceb09ab25d..e9b6e3272f 100644
--- a/widgets/text/e-text.c
+++ b/widgets/text/e-text.c
@@ -2471,12 +2471,10 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double
*y2 = *y1 + height;
}
-static void
+static gboolean
_get_xy_from_position (EText *text, gint position, gint *xp, gint *yp)
{
- if ( !text->lines )
- return;
- if (xp || yp) {
+ if (text->lines && (xp || yp)) {
struct line *lines = NULL;
int x, y;
double xd, yd;
@@ -2506,7 +2504,11 @@ _get_xy_from_position (EText *text, gint position, gint *xp, gint *yp)
*xp = x;
if (yp)
*yp = y;
+
+ return TRUE;
}
+
+ return FALSE;
}
static gint
@@ -3312,15 +3314,17 @@ _get_position(EText *text, ETextEventProcessorCommand *command)
break;
case E_TEP_FORWARD_LINE:
- _get_xy_from_position(text, text->selection_end, &x, &y);
- y += e_font_height (text->font);
- new_pos = _get_position_from_xy(text, x, y);
+ if (_get_xy_from_position(text, text->selection_end, &x, &y)) {
+ y += e_font_height (text->font);
+ new_pos = _get_position_from_xy(text, x, y);
+ }
break;
case E_TEP_BACKWARD_LINE:
- _get_xy_from_position(text, text->selection_end, &x, &y);
- y -= e_font_height (text->font);
- new_pos = _get_position_from_xy(text, x, y);
+ if (_get_xy_from_position(text, text->selection_end, &x, &y)) {
+ y -= e_font_height (text->font);
+ new_pos = _get_position_from_xy(text, x, y);
+ }
break;
case E_TEP_SELECT_WORD: