diff options
author | Gonzalo Odiard <godiard@gmail.com> | 2012-11-21 19:14:03 (GMT) |
---|---|---|
committer | Gonzalo Odiard <godiard@gmail.com> | 2012-11-21 19:14:03 (GMT) |
commit | 1b7dd90604e7b0e92449d258f2ffc26cf3c32309 (patch) | |
tree | ef04dd07c3c8c00ffb8da12a0dfc03aab22bd488 | |
parent | 1bcf6e6103c875bc173593b0bb2b0a2aa2c9edb2 (diff) |
Changes in olpc5 rpm
Apply patch from http://bugzilla.abisource.com/show_bug.cgi?id=13410#c5
-rw-r--r-- | abi-selection-handles.diff (renamed from abiword-text-handles.diff) | 3120 | ||||
-rw-r--r-- | abiword.spec | 6 | ||||
-rw-r--r-- | handles2.diff | 98 |
3 files changed, 1581 insertions, 1643 deletions
diff --git a/abiword-text-handles.diff b/abi-selection-handles.diff index 8230415..e8b6d9f 100644 --- a/abiword-text-handles.diff +++ b/abi-selection-handles.diff @@ -1,1541 +1,1579 @@ -diff --git a/src/af/ev/gtk/ev_UnixKeyboard.cpp b/src/af/ev/gtk/ev_UnixKeyboard.cpp
-index 5c5c109..af51672 100644
---- a/src/af/ev/gtk/ev_UnixKeyboard.cpp
-+++ b/src/af/ev/gtk/ev_UnixKeyboard.cpp
-@@ -79,6 +79,8 @@ bool ev_UnixKeyboard::keyPressEvent(AV_View* pView, GdkEventKey* e)
-
- UT_uint32 charData = e->keyval;
-
-+ pView->setVisualSelectionEnabled(false);
-+
- if (e->state & GDK_SHIFT_MASK)
- state |= EV_EMS_SHIFT;
- if (e->state & GDK_CONTROL_MASK)
-diff --git a/src/af/ev/gtk/ev_UnixMouse.cpp b/src/af/ev/gtk/ev_UnixMouse.cpp
-index 17ac999..af3cb2a 100644
---- a/src/af/ev/gtk/ev_UnixMouse.cpp
-+++ b/src/af/ev/gtk/ev_UnixMouse.cpp
-@@ -111,6 +111,9 @@ void EV_UnixMouse::mouseClick(AV_View* pView, GdkEventButton* e)
- EV_EditMouseButton emb = 0;
- EV_EditMouseOp mop = 0;
- EV_EditMouseContext emc = 0;
-+ GdkDevice *device;
-+
-+ device = gdk_event_get_source_device((GdkEvent *) e);
-
- if (e->button == 1)
- emb = EV_EMB_BUTTON1;
-@@ -160,6 +163,12 @@ void EV_UnixMouse::mouseClick(AV_View* pView, GdkEventButton* e)
- UT_ASSERT(pEM);
- invokeMouseMethod(pView,pEM,static_cast<UT_sint32>(pView->getGraphics()->tluD(e->x)),static_cast<UT_sint32>(pView->getGraphics()->tluD(e->y)));
- signal(emc|mop|emb|state, static_cast<UT_sint32>(pView->getGraphics()->tluD(e->x)),static_cast<UT_sint32>(pView->getGraphics()->tluD(e->y)));
-+
-+ if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN) {
-+ pView->setVisualSelectionEnabled(true);
-+ } else {
-+ pView->setVisualSelectionEnabled(false);
-+ }
- return;
- case EV_EEMR_INCOMPLETE:
- // I'm not sure this makes any sense, but we allow it.
-@@ -182,7 +191,10 @@ void EV_UnixMouse::mouseMotion(AV_View* pView, GdkEventMotion *e)
- EV_EditMouseButton emb = 0;
- EV_EditMouseOp mop;
- EV_EditMouseContext emc = 0;
--
-+ GdkDevice *device;
-+
-+ device = gdk_event_get_source_device((GdkEvent *) e);
-+
- if (e->state & GDK_SHIFT_MASK)
- ems |= EV_EMS_SHIFT;
- if (e->state & GDK_CONTROL_MASK)
-diff --git a/src/af/xap/gtk/xap_UnixFrameImpl.h b/src/af/xap/gtk/xap_UnixFrameImpl.h
-index 887104e..da4c1ac 100644
---- a/src/af/xap/gtk/xap_UnixFrameImpl.h
-+++ b/src/af/xap/gtk/xap_UnixFrameImpl.h
-@@ -67,6 +67,8 @@ class XAP_UnixFrameImpl : public XAP_FrameImpl
- }
- void resetIMContext ();
-
-+ virtual GtkWidget * getViewWidget (void) {return NULL;}
-+
- private:
- void _setGeometry ();
-
-diff --git a/src/af/xap/xp/xav_View.cpp b/src/af/xap/xp/xav_View.cpp
-index 21bf216..709eaad 100644
---- a/src/af/xap/xp/xav_View.cpp
-+++ b/src/af/xap/xp/xav_View.cpp
-@@ -39,7 +39,8 @@ AV_View::AV_View(XAP_App * pApp, void* pParentData)
- m_iWindowWidth(0),
- m_dOneTDU(0),
- m_bCouldBeActive(true),
-- m_bConfigureChanged(false)
-+ m_bConfigureChanged(false),
-+ m_VisualSelectionActive(false)
- {
- }
-
-diff --git a/src/af/xap/xp/xav_View.h b/src/af/xap/xp/xav_View.h
-index b411864..f7c7f22 100644
---- a/src/af/xap/xp/xav_View.h
-+++ b/src/af/xap/xp/xav_View.h
-@@ -150,6 +150,9 @@ public:
- virtual void cmdPaste(bool bHonorFormatting = true) = 0;
- virtual void cmdPasteSelectionAt(UT_sint32 xPos, UT_sint32 yPos) = 0;
-
-+ virtual void setVisualSelectionEnabled(bool bActive) { m_VisualSelectionActive=bActive; }
-+ bool getVisualSelectionEnabled(void) { return m_VisualSelectionActive; }
-+
- //
- // Let subclasses override but this is here to avoid a crash on frame closing.
- // With a selection in place. (Rather than pure virtual.)
-@@ -177,6 +180,7 @@ protected:
- AV_Focus m_focus;
- UT_uint32 m_iTick; // Count changes
- bool m_bInsertMode;
-+ bool m_VisualSelectionActive;
-
- UT_GenericVector<AV_ScrollObj*> m_scrollListeners;
- UT_GenericVector<AV_Listener*> m_vecListeners;
-diff --git a/src/text/fmt/gtk/Makefile.am b/src/text/fmt/gtk/Makefile.am
-index 4d96dfd..46ca135 100644
---- a/src/text/fmt/gtk/Makefile.am
-+++ b/src/text/fmt/gtk/Makefile.am
-@@ -6,11 +6,18 @@ noinst_LTLIBRARIES = libgtk.la
- AM_CPPFLAGS = \
- $(IMPEXP_CPPFLAGS)
-
-+cut_and_paste_code = \
-+ gtktexthandle.c
-+ gtktexthandleprivate.h
-+
- libgtk_la_SOURCES = \
-+ $(cut_and_paste_code) \
- fv_UnixFrameEdit.cpp \
- fv_UnixFrameEdit.h \
- fv_UnixInlineImage.cpp \
- fv_UnixInlineImage.h \
-+ fv_UnixSelectionHandles.cpp \
-+ fv_UnixSelectionHandles.h \
- fv_UnixVisualDrag.cpp \
- fv_UnixVisualDrag.h
-
-diff --git a/src/text/fmt/gtk/fv_UnixSelectionHandles.cpp b/src/text/fmt/gtk/fv_UnixSelectionHandles.cpp
-new file mode 100644
-index 0000000..935e8fa
---- /dev/null
-+++ b/src/text/fmt/gtk/fv_UnixSelectionHandles.cpp
-@@ -0,0 +1,123 @@
-+/* AbiWord - unix impl for selection handles
-+ * Copyright (c) 2012 One laptop per child
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+ * 02111-1307, USA.
-+ *
-+ * Author: Carlos Garnacho <carlos@lanedo.com>
-+ */
-+
-+#include "xap_Frame.h"
-+#include "xap_UnixFrameImpl.h"
-+#include "fv_UnixSelectionHandles.h"
-+#include "fv_View.h"
-+#include "gtktexthandleprivate.h"
-+
-+static void handle_dragged_cb (FvTextHandle *handle,
-+ FvTextHandlePosition pos,
-+ gint x,
-+ gint y,
-+ gpointer user_data)
-+{
-+ FvTextHandleMode mode;
-+ FV_UnixSelectionHandles *handles = static_cast<FV_UnixSelectionHandles *>(user_data);
-+
-+ mode = _fv_text_handle_get_mode (handle);
-+
-+ if (pos == FV_TEXT_HANDLE_POSITION_SELECTION_START)
-+ handles->updateSelectionStart ((UT_sint32)x, (UT_sint32)y);
-+ else {
-+ if (mode == FV_TEXT_HANDLE_MODE_SELECTION)
-+ handles->updateSelectionEnd ((UT_sint32)x, (UT_sint32)y);
-+ else
-+ handles->updateCursor((UT_sint32)x, (UT_sint32)y);
-+ }
-+}
-+
-+FV_UnixSelectionHandles::FV_UnixSelectionHandles(FV_View *view, FV_Selection selection)
-+ : FV_SelectionHandles (view, selection)
-+{
-+ XAP_Frame * pFrame = static_cast<XAP_Frame*>(m_pView->getParentData());
-+ XAP_UnixFrameImpl * pFrameImpl =static_cast<XAP_UnixFrameImpl *>( pFrame->getFrameImpl());
-+ GtkWidget * pWidget = pFrameImpl->getViewWidget();
-+
-+ m_text_handle = _fv_text_handle_new (pWidget);
-+ _fv_text_handle_set_relative_to (m_text_handle,
-+ gtk_widget_get_window (pWidget));
-+ g_signal_connect (m_text_handle, "handle-dragged",
-+ G_CALLBACK(handle_dragged_cb), this);
-+}
-+
-+FV_UnixSelectionHandles::~FV_UnixSelectionHandles()
-+{
-+ g_object_unref (m_text_handle);
-+}
-+
-+void FV_UnixSelectionHandles::hide()
-+{
-+ _fv_text_handle_set_mode (m_text_handle, FV_TEXT_HANDLE_MODE_NONE);
-+}
-+
-+void FV_UnixSelectionHandles::setCursorCoords(UT_sint32 x, UT_sint32 y, UT_uint32 height, bool visible)
-+{
-+ GdkRectangle rect;
-+
-+ _fv_text_handle_set_mode(m_text_handle, FV_TEXT_HANDLE_MODE_CURSOR);
-+ _fv_text_handle_set_visible (m_text_handle, FV_TEXT_HANDLE_POSITION_CURSOR, visible);
-+
-+ if (visible)
-+ {
-+ rect.x = (int)x;
-+ rect.y = (int)y;
-+ rect.width = 1;
-+ rect.height = (int)height;
-+ _fv_text_handle_set_position(m_text_handle,
-+ FV_TEXT_HANDLE_POSITION_CURSOR,
-+ &rect);
-+ }
-+}
-+
-+void FV_UnixSelectionHandles::setSelectionCoords(UT_sint32 start_x, UT_sint32 start_y, UT_uint32 start_height, bool start_visible,
-+ UT_sint32 end_x, UT_sint32 end_y, UT_uint32 end_height, bool end_visible)
-+{
-+ GdkRectangle rect;
-+
-+ _fv_text_handle_set_mode(m_text_handle, FV_TEXT_HANDLE_MODE_SELECTION);
-+
-+ _fv_text_handle_set_visible (m_text_handle, FV_TEXT_HANDLE_POSITION_SELECTION_START, start_visible);
-+ _fv_text_handle_set_visible (m_text_handle, FV_TEXT_HANDLE_POSITION_SELECTION_END, end_visible);
-+
-+ if (start_visible)
-+ {
-+ rect.x = (int)start_x;
-+ rect.y = (int)start_y;
-+ rect.width = 1;
-+ rect.height = (int)start_height;
-+ _fv_text_handle_set_position(m_text_handle,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_START,
-+ &rect);
-+ }
-+
-+ if (end_visible)
-+ {
-+ rect.x = (int)end_x;
-+ rect.y = (int)end_y;
-+ rect.width = 1;
-+ rect.height = (int)end_height;
-+ _fv_text_handle_set_position(m_text_handle,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_END,
-+ &rect);
-+ }
-+}
-diff --git a/src/text/fmt/gtk/fv_UnixSelectionHandles.h b/src/text/fmt/gtk/fv_UnixSelectionHandles.h
-new file mode 100644
-index 0000000..809ae2e
---- /dev/null
-+++ b/src/text/fmt/gtk/fv_UnixSelectionHandles.h
-@@ -0,0 +1,45 @@
-+/* AbiWord - unix impl for selection handles
-+ * Copyright (c) 2012 One laptop per child
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+ * 02111-1307, USA.
-+ *
-+ * Author: Carlos Garnacho <carlos@lanedo.com>
-+ */
-+
-+#ifndef FV_UNIXSELECTIONHANDLES_H
-+#define FV_UNIXSELECTIONHANDLES_H
-+
-+#include "fv_SelectionHandles.h"
-+#include "gtktexthandleprivate.h"
-+
-+class ABI_EXPORT FV_UnixSelectionHandles : public FV_SelectionHandles
-+{
-+ friend class fv_View;
-+
-+public:
-+ FV_UnixSelectionHandles (FV_View * pView, FV_Selection selection);
-+ virtual ~FV_UnixSelectionHandles();
-+
-+ virtual void hide(void);
-+ virtual void setCursorCoords (UT_sint32 x, UT_sint32 y, UT_uint32 height, bool visible);
-+ virtual void setSelectionCoords (UT_sint32 start_x, UT_sint32 start_y, UT_uint32 start_height, bool start_visible,
-+ UT_sint32 end_x, UT_sint32 end_y, UT_uint32 end_height, bool end_visible);
-+
-+private:
-+ FvTextHandle *m_text_handle;
-+};
-+
-+#endif /* FV_UNIXSELECTIONHANDLES_H */
-diff --git a/src/text/fmt/gtk/gtktexthandle.c b/src/text/fmt/gtk/gtktexthandle.c
-new file mode 100644
-index 0000000..64a37ed
---- /dev/null
-+++ b/src/text/fmt/gtk/gtktexthandle.c
-@@ -0,0 +1,675 @@
-+/* GTK - The GIMP Toolkit
-+ * Copyright © 2012 Carlos Garnacho <carlosg@gnome.org>
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include "gtktexthandleprivate.h"
-+#include <gtk/gtk.h>
-+
-+typedef struct _FvTextHandlePrivate FvTextHandlePrivate;
-+typedef struct _HandleWindow HandleWindow;
-+
-+enum {
-+ HANDLE_DRAGGED,
-+ DRAG_FINISHED,
-+ LAST_SIGNAL
-+};
-+
-+enum {
-+ PROP_0,
-+ PROP_PARENT,
-+ PROP_RELATIVE_TO
-+};
-+
-+struct _HandleWindow
-+{
-+ GdkWindow *window;
-+ GdkRectangle pointing_to;
-+ gint dx;
-+ gint dy;
-+ guint dragged : 1;
-+};
-+
-+struct _FvTextHandlePrivate
-+{
-+ HandleWindow windows[2];
-+ GtkWidget *parent;
-+ GdkWindow *relative_to;
-+ GtkStyleContext *style_context;
-+
-+ gulong draw_signal_id;
-+ gulong event_signal_id;
-+ gulong style_updated_id;
-+ gulong composited_changed_id;
-+ guint realized : 1;
-+ guint mode : 2;
-+};
-+
-+G_DEFINE_TYPE (FvTextHandle, _fv_text_handle, G_TYPE_OBJECT)
-+
-+static guint signals[LAST_SIGNAL] = { 0 };
-+
-+static void
-+_fv_text_handle_get_size (FvTextHandle *handle,
-+ gint *width,
-+ gint *height)
-+{
-+ FvTextHandlePrivate *priv;
-+ gint w, h;
-+
-+ priv = handle->priv;
-+
-+ gtk_widget_style_get (priv->parent,
-+ "text-handle-width", &w,
-+ "text-handle-height", &h,
-+ NULL);
-+ if (width)
-+ *width = w;
-+
-+ if (height)
-+ *height = h;
-+}
-+
-+static void
-+_fv_text_handle_draw (FvTextHandle *handle,
-+ cairo_t *cr,
-+ FvTextHandlePosition pos)
-+{
-+ FvTextHandlePrivate *priv;
-+ gint width, height;
-+
-+ priv = handle->priv;
-+ cairo_save (cr);
-+
-+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-+ cairo_set_source_rgba (cr, 0, 0, 0, 0);
-+ cairo_paint (cr);
-+
-+ gtk_style_context_save (priv->style_context);
-+ gtk_style_context_add_class (priv->style_context, "cursor-handle");
-+
-+ if (pos == FV_TEXT_HANDLE_POSITION_SELECTION_END)
-+ {
-+ gtk_style_context_add_class (priv->style_context,
-+ GTK_STYLE_CLASS_BOTTOM);
-+
-+ if (priv->mode == FV_TEXT_HANDLE_MODE_CURSOR)
-+ gtk_style_context_add_class (priv->style_context, "insert-cursor");
-+ }
-+ else
-+ gtk_style_context_add_class (priv->style_context, "top");
-+
-+ _fv_text_handle_get_size (handle, &width, &height);
-+ gtk_render_background (priv->style_context, cr, 0, 0, width, height);
-+
-+ gtk_style_context_restore (priv->style_context);
-+ cairo_restore (cr);
-+}
-+
-+static void
-+_fv_text_handle_update_shape (FvTextHandle *handle,
-+ GdkWindow *window,
-+ FvTextHandlePosition pos)
-+{
-+ FvTextHandlePrivate *priv;
-+ cairo_surface_t *surface;
-+ cairo_region_t *region;
-+ cairo_t *cr;
-+
-+ priv = handle->priv;
-+
-+ surface =
-+ gdk_window_create_similar_surface (window,
-+ CAIRO_CONTENT_COLOR_ALPHA,
-+ gdk_window_get_width (window),
-+ gdk_window_get_height (window));
-+
-+ cr = cairo_create (surface);
-+ _fv_text_handle_draw (handle, cr, pos);
-+ cairo_destroy (cr);
-+
-+ region = gdk_cairo_region_create_from_surface (surface);
-+
-+ if (gtk_widget_is_composited (priv->parent))
-+ gdk_window_shape_combine_region (window, NULL, 0, 0);
-+ else
-+ gdk_window_shape_combine_region (window, region, 0, 0);
-+
-+ gdk_window_input_shape_combine_region (window, region, 0, 0);
-+
-+ cairo_surface_destroy (surface);
-+ cairo_region_destroy (region);
-+}
-+
-+static GdkWindow *
-+_fv_text_handle_create_window (FvTextHandle *handle,
-+ FvTextHandlePosition pos)
-+{
-+ FvTextHandlePrivate *priv;
-+ GdkRGBA bg = { 0, 0, 0, 0 };
-+ GdkWindowAttr attributes;
-+ GdkWindow *window;
-+ GdkVisual *visual;
-+ gint mask;
-+
-+ priv = handle->priv;
-+
-+ attributes.x = 0;
-+ attributes.y = 0;
-+ _fv_text_handle_get_size (handle, &attributes.width, &attributes.height);
-+ attributes.window_type = GDK_WINDOW_TEMP;
-+ attributes.wclass = GDK_INPUT_OUTPUT;
-+ attributes.event_mask = (GDK_EXPOSURE_MASK |
-+ GDK_BUTTON_PRESS_MASK |
-+ GDK_BUTTON_RELEASE_MASK |
-+ GDK_BUTTON1_MOTION_MASK);
-+
-+ mask = GDK_WA_X | GDK_WA_Y;
-+
-+ visual = gdk_screen_get_rgba_visual (gtk_widget_get_screen (priv->parent));
-+
-+ if (visual)
-+ {
-+ attributes.visual = visual;
-+ mask |= GDK_WA_VISUAL;
-+ }
-+
-+ window = gdk_window_new (NULL, &attributes, mask);
-+ gdk_window_set_user_data (window, priv->parent);
-+ gdk_window_set_background_rgba (window, &bg);
-+
-+ _fv_text_handle_update_shape (handle, window, pos);
-+
-+ return window;
-+}
-+
-+static gboolean
-+fv_text_handle_widget_draw (GtkWidget *widget,
-+ cairo_t *cr,
-+ FvTextHandle *handle)
-+{
-+ FvTextHandlePrivate *priv;
-+ FvTextHandlePosition pos;
-+
-+ priv = handle->priv;
-+
-+ if (!priv->realized)
-+ return FALSE;
-+
-+ if (gtk_cairo_should_draw_window (cr, priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window))
-+ pos = FV_TEXT_HANDLE_POSITION_SELECTION_START;
-+ else if (gtk_cairo_should_draw_window (cr, priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window))
-+ pos = FV_TEXT_HANDLE_POSITION_SELECTION_END;
-+ else
-+ return FALSE;
-+
-+ _fv_text_handle_draw (handle, cr, pos);
-+ return TRUE;
-+}
-+
-+static gboolean
-+fv_text_handle_widget_event (GtkWidget *widget,
-+ GdkEvent *event,
-+ FvTextHandle *handle)
-+{
-+ FvTextHandlePrivate *priv;
-+ FvTextHandlePosition pos;
-+
-+ priv = handle->priv;
-+
-+ if (event->any.window == priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window)
-+ pos = FV_TEXT_HANDLE_POSITION_SELECTION_START;
-+ else if (event->any.window == priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window)
-+ pos = FV_TEXT_HANDLE_POSITION_SELECTION_END;
-+ else
-+ return FALSE;
-+
-+ if (event->type == GDK_BUTTON_PRESS)
-+ {
-+ priv->windows[pos].dx = event->button.x;
-+ priv->windows[pos].dy = event->button.y;
-+ priv->windows[pos].dragged = TRUE;
-+ }
-+ else if (event->type == GDK_BUTTON_RELEASE)
-+ {
-+ g_signal_emit (handle, signals[DRAG_FINISHED], 0, pos);
-+ priv->windows[pos].dx = priv->windows[pos].dy = 0;
-+ priv->windows[pos].dragged = FALSE;
-+ }
-+ else if (event->type == GDK_MOTION_NOTIFY && priv->windows[pos].dragged)
-+ {
-+ gint x, y, width, height;
-+
-+ _fv_text_handle_get_size (handle, &width, &height);
-+ gdk_window_get_origin (priv->relative_to, &x, &y);
-+
-+ x = event->motion.x_root - priv->windows[pos].dx + (width / 2) - x;
-+ y = event->motion.y_root - priv->windows[pos].dy - y;
-+
-+ if (pos == FV_TEXT_HANDLE_POSITION_SELECTION_START)
-+ y += height;
-+
-+ g_signal_emit (handle, signals[HANDLE_DRAGGED], 0, pos, x, y);
-+ }
-+
-+ return TRUE;
-+}
-+
-+static void
-+_fv_text_handle_update_window (FvTextHandle *handle,
-+ FvTextHandlePosition pos)
-+{
-+ FvTextHandlePrivate *priv;
-+ HandleWindow *handle_window;
-+ gboolean visible;
-+ gint x, y;
-+
-+ priv = handle->priv;
-+ handle_window = &priv->windows[pos];
-+
-+ if (!handle_window->window)
-+ return;
-+
-+ /* Get current state and destroy */
-+ visible = gdk_window_is_visible (handle_window->window);
-+
-+ if (visible)
-+ {
-+ gint width;
-+
-+ _fv_text_handle_get_size (handle, &width, NULL);
-+ gdk_window_get_root_coords (handle_window->window,
-+ width / 2, 0, &x, &y);
-+ }
-+
-+ gdk_window_destroy (handle_window->window);
-+
-+ /* Create new window and apply old state */
-+ handle_window->window = _fv_text_handle_create_window (handle, pos);
-+
-+ if (visible)
-+ {
-+ gdk_window_show (handle_window->window);
-+ _fv_text_handle_set_position (handle, pos,
-+ &handle_window->pointing_to);
-+ }
-+}
-+
-+static void
-+_fv_text_handle_update_windows (FvTextHandle *handle)
-+{
-+ FvTextHandlePrivate *priv = handle->priv;
-+
-+ gtk_style_context_invalidate (priv->style_context);
-+ _fv_text_handle_update_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+ _fv_text_handle_update_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_END);
-+}
-+
-+static void
-+fv_text_handle_constructed (GObject *object)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ priv = FV_TEXT_HANDLE (object)->priv;
-+ g_assert (priv->parent != NULL);
-+
-+ priv->draw_signal_id =
-+ g_signal_connect (priv->parent, "draw",
-+ G_CALLBACK (fv_text_handle_widget_draw),
-+ object);
-+ priv->event_signal_id =
-+ g_signal_connect (priv->parent, "event",
-+ G_CALLBACK (fv_text_handle_widget_event),
-+ object);
-+ priv->composited_changed_id =
-+ g_signal_connect_swapped (priv->parent, "composited-changed",
-+ G_CALLBACK (_fv_text_handle_update_windows),
-+ object);
-+ priv->style_updated_id =
-+ g_signal_connect_swapped (priv->parent, "style-updated",
-+ G_CALLBACK (_fv_text_handle_update_windows),
-+ object);
-+}
-+
-+static void
-+fv_text_handle_finalize (GObject *object)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ priv = FV_TEXT_HANDLE (object)->priv;
-+
-+ if (priv->relative_to)
-+ g_object_unref (priv->relative_to);
-+
-+ if (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window)
-+ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window);
-+
-+ if (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window)
-+ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window);
-+
-+#if 0
-+ if (g_signal_handler_is_connected (priv->parent, priv->draw_signal_id))
-+ g_signal_handler_disconnect (priv->parent, priv->draw_signal_id);
-+
-+ if (g_signal_handler_is_connected (priv->parent, priv->event_signal_id))
-+ g_signal_handler_disconnect (priv->parent, priv->event_signal_id);
-+
-+ if (g_signal_handler_is_connected (priv->parent, priv->composited_changed_id))
-+ g_signal_handler_disconnect (priv->parent, priv->composited_changed_id);
-+
-+ if (g_signal_handler_is_connected (priv->parent, priv->style_updated_id))
-+ g_signal_handler_disconnect (priv->parent, priv->style_updated_id);
-+#endif
-+
-+ g_object_unref (priv->style_context);
-+
-+ G_OBJECT_CLASS (_fv_text_handle_parent_class)->finalize (object);
-+}
-+
-+static void
-+fv_text_handle_set_property (GObject *object,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec)
-+{
-+ FvTextHandlePrivate *priv;
-+ FvTextHandle *handle;
-+
-+ handle = FV_TEXT_HANDLE (object);
-+ priv = handle->priv;
-+
-+ switch (prop_id)
-+ {
-+ case PROP_PARENT:
-+ priv->parent = g_value_get_object (value);
-+ break;
-+ case PROP_RELATIVE_TO:
-+ _fv_text_handle_set_relative_to (handle,
-+ g_value_get_object (value));
-+ break;
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+ }
-+}
-+
-+static void
-+fv_text_handle_get_property (GObject *object,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ priv = FV_TEXT_HANDLE (object)->priv;
-+
-+ switch (prop_id)
-+ {
-+ case PROP_PARENT:
-+ g_value_set_object (value, priv->parent);
-+ break;
-+ case PROP_RELATIVE_TO:
-+ g_value_set_object (value, priv->relative_to);
-+ break;
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+ }
-+}
-+
-+static void
-+_fv_text_handle_class_init (FvTextHandleClass *klass)
-+{
-+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
-+
-+ object_class->constructed = fv_text_handle_constructed;
-+ object_class->finalize = fv_text_handle_finalize;
-+ object_class->set_property = fv_text_handle_set_property;
-+ object_class->get_property = fv_text_handle_get_property;
-+
-+ signals[HANDLE_DRAGGED] =
-+ g_signal_new ("handle-dragged",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (FvTextHandleClass, handle_dragged),
-+ NULL, NULL,
-+ g_cclosure_marshal_generic,
-+ G_TYPE_NONE, 3,
-+ G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
-+ signals[DRAG_FINISHED] =
-+ g_signal_new ("drag-finished",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_LAST, 0,
-+ NULL, NULL,
-+ g_cclosure_marshal_VOID__INT,
-+ G_TYPE_NONE, 1, G_TYPE_INT);
-+
-+ g_object_class_install_property (object_class,
-+ PROP_PARENT,
-+ g_param_spec_object ("parent",
-+ "Parent widget",
-+ "Parent widget",
-+ GTK_TYPE_WIDGET,
-+ G_PARAM_READWRITE |
-+ G_PARAM_CONSTRUCT_ONLY));
-+ g_object_class_install_property (object_class,
-+ PROP_RELATIVE_TO,
-+ g_param_spec_object ("relative-to",
-+ "Window",
-+ "Window the coordinates are based upon",
-+ GDK_TYPE_WINDOW,
-+ G_PARAM_READWRITE));
-+
-+ g_type_class_add_private (object_class, sizeof (FvTextHandlePrivate));
-+}
-+
-+static void
-+_fv_text_handle_init (FvTextHandle *handle)
-+{
-+ FvTextHandlePrivate *priv;
-+ GtkWidgetPath *path;
-+
-+ handle->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (handle,
-+ FV_TYPE_TEXT_HANDLE,
-+ FvTextHandlePrivate);
-+
-+ path = gtk_widget_path_new ();
-+ gtk_widget_path_append_type (path, FV_TYPE_TEXT_HANDLE);
-+
-+ priv->style_context = gtk_style_context_new ();
-+ gtk_style_context_set_path (priv->style_context, path);
-+ gtk_widget_path_free (path);
-+}
-+
-+FvTextHandle *
-+_fv_text_handle_new (GtkWidget *parent)
-+{
-+ return g_object_new (FV_TYPE_TEXT_HANDLE,
-+ "parent", parent,
-+ NULL);
-+}
-+
-+void
-+_fv_text_handle_set_relative_to (FvTextHandle *handle,
-+ GdkWindow *window)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ g_return_if_fail (FV_IS_TEXT_HANDLE (handle));
-+ g_return_if_fail (!window || GDK_IS_WINDOW (window));
-+
-+ priv = handle->priv;
-+
-+ if (priv->relative_to)
-+ {
-+ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window);
-+ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window);
-+ g_object_unref (priv->relative_to);
-+ }
-+
-+ if (window)
-+ {
-+ priv->relative_to = g_object_ref (window);
-+ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window =
-+ _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window =
-+ _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+ priv->realized = TRUE;
-+ }
-+ else
-+ {
-+ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window = NULL;
-+ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window = NULL;
-+ priv->relative_to = NULL;
-+ priv->realized = FALSE;
-+ }
-+
-+ g_object_notify (G_OBJECT (handle), "relative-to");
-+}
-+
-+void
-+_fv_text_handle_set_mode (FvTextHandle *handle,
-+ FvTextHandleMode mode)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ g_return_if_fail (FV_IS_TEXT_HANDLE (handle));
-+
-+ priv = handle->priv;
-+
-+ if (priv->mode == mode)
-+ return;
-+
-+ switch (mode)
-+ {
-+ case FV_TEXT_HANDLE_MODE_CURSOR:
-+ /* Only display one handle */
-+ gdk_window_show (priv->windows[FV_TEXT_HANDLE_POSITION_CURSOR].window);
-+ gdk_window_hide (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window);
-+ break;
-+ case FV_TEXT_HANDLE_MODE_SELECTION:
-+ /* Display both handles */
-+ gdk_window_show (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window);
-+ gdk_window_show (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window);
-+ break;
-+ case FV_TEXT_HANDLE_MODE_NONE:
-+ default:
-+ gdk_window_hide (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window);
-+ gdk_window_hide (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window);
-+ break;
-+ }
-+
-+ priv->mode = mode;
-+}
-+
-+FvTextHandleMode
-+_fv_text_handle_get_mode (FvTextHandle *handle)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ g_return_val_if_fail (FV_IS_TEXT_HANDLE (handle), FV_TEXT_HANDLE_MODE_NONE);
-+
-+ priv = handle->priv;
-+ return priv->mode;
-+}
-+
-+void
-+_fv_text_handle_set_position (FvTextHandle *handle,
-+ FvTextHandlePosition pos,
-+ GdkRectangle *rect)
-+{
-+ FvTextHandlePrivate *priv;
-+ gint x, y, width, height;
-+ HandleWindow *handle_window;
-+
-+ g_return_if_fail (FV_IS_TEXT_HANDLE (handle));
-+
-+ priv = handle->priv;
-+ pos = CLAMP (pos, FV_TEXT_HANDLE_POSITION_CURSOR,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+
-+ if (!priv->realized)
-+ return;
-+
-+ if (priv->mode == FV_TEXT_HANDLE_MODE_NONE ||
-+ (priv->mode == FV_TEXT_HANDLE_MODE_CURSOR &&
-+ pos != FV_TEXT_HANDLE_POSITION_CURSOR))
-+ return;
-+
-+ gdk_window_get_root_coords (priv->relative_to,
-+ rect->x, rect->y,
-+ &x, &y);
-+ _fv_text_handle_get_size (handle, &width, &height);
-+ handle_window = &priv->windows[pos];
-+
-+ if (pos == FV_TEXT_HANDLE_POSITION_CURSOR)
-+ y += rect->height;
-+ else
-+ y -= height;
-+
-+ x -= width / 2;
-+
-+ gdk_window_move (handle_window->window, x, y);
-+ handle_window->pointing_to = *rect;
-+}
-+
-+void
-+_fv_text_handle_set_visible (FvTextHandle *handle,
-+ FvTextHandlePosition pos,
-+ gboolean visible)
-+{
-+ FvTextHandlePrivate *priv;
-+ GdkWindow *window;
-+
-+ g_return_if_fail (FV_IS_TEXT_HANDLE (handle));
-+
-+ priv = handle->priv;
-+ pos = CLAMP (pos, FV_TEXT_HANDLE_POSITION_CURSOR,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+
-+ if (!priv->realized)
-+ return;
-+
-+ window = priv->windows[pos].window;
-+
-+ if (!window)
-+ return;
-+
-+ if (!visible)
-+ gdk_window_hide (window);
-+ else
-+ {
-+ if (priv->mode == FV_TEXT_HANDLE_MODE_NONE ||
-+ (priv->mode == FV_TEXT_HANDLE_MODE_CURSOR &&
-+ pos != FV_TEXT_HANDLE_POSITION_CURSOR))
-+ return;
-+
-+ if (!gdk_window_is_visible (window))
-+ gdk_window_show (window);
-+ }
-+}
-+
-+gboolean
-+_fv_text_handle_get_is_dragged (FvTextHandle *handle,
-+ FvTextHandlePosition pos)
-+{
-+ FvTextHandlePrivate *priv;
-+
-+ g_return_val_if_fail (FV_IS_TEXT_HANDLE (handle), FALSE);
-+
-+ priv = handle->priv;
-+ pos = CLAMP (pos, FV_TEXT_HANDLE_POSITION_CURSOR,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+
-+ return priv->windows[pos].dragged;
-+}
-diff --git a/src/text/fmt/gtk/gtktexthandleprivate.h b/src/text/fmt/gtk/gtktexthandleprivate.h
-new file mode 100644
-index 0000000..d25dc72
---- /dev/null
-+++ b/src/text/fmt/gtk/gtktexthandleprivate.h
-@@ -0,0 +1,90 @@
-+/* GTK - The GIMP Toolkit
-+ * Copyright © 2012 Carlos Garnacho <carlosg@gnome.org>
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2 of the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#ifndef __FV_TEXT_HANDLE_PRIVATE_H__
-+#define __FV_TEXT_HANDLE_PRIVATE_H__
-+
-+#include <gtk/gtk.h>
-+
-+G_BEGIN_DECLS
-+
-+#define FV_TYPE_TEXT_HANDLE (_fv_text_handle_get_type ())
-+#define FV_TEXT_HANDLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FV_TYPE_TEXT_HANDLE, FvTextHandle))
-+#define FV_TEXT_HANDLE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), FV_TYPE_TEXT_HANDLE, FvTextHandleClass))
-+#define FV_IS_TEXT_HANDLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FV_TYPE_TEXT_HANDLE))
-+#define FV_IS_TEXT_HANDLE_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), FV_TYPE_TEXT_HANDLE))
-+#define FV_TEXT_HANDLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FV_TYPE_TEXT_HANDLE, FvTextHandleClass))
-+
-+typedef struct _FvTextHandle FvTextHandle;
-+typedef struct _FvTextHandleClass FvTextHandleClass;
-+
-+typedef enum
-+{
-+ FV_TEXT_HANDLE_POSITION_CURSOR,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_START,
-+ FV_TEXT_HANDLE_POSITION_SELECTION_END = FV_TEXT_HANDLE_POSITION_CURSOR
-+} FvTextHandlePosition;
-+
-+typedef enum
-+{
-+ FV_TEXT_HANDLE_MODE_NONE,
-+ FV_TEXT_HANDLE_MODE_CURSOR,
-+ FV_TEXT_HANDLE_MODE_SELECTION
-+} FvTextHandleMode;
-+
-+struct _FvTextHandle
-+{
-+ GObject parent_instance;
-+ gpointer priv;
-+};
-+
-+struct _FvTextHandleClass
-+{
-+ GObjectClass parent_class;
-+
-+ void (* handle_dragged) (FvTextHandle *handle,
-+ FvTextHandlePosition pos,
-+ gint x,
-+ gint y);
-+ void (* drag_finished) (FvTextHandle *handle,
-+ FvTextHandlePosition pos);
-+};
-+
-+GType _fv_text_handle_get_type (void) G_GNUC_CONST;
-+
-+FvTextHandle * _fv_text_handle_new (GtkWidget *parent);
-+
-+void _fv_text_handle_set_mode (FvTextHandle *handle,
-+ FvTextHandleMode mode);
-+FvTextHandleMode
-+ _fv_text_handle_get_mode (FvTextHandle *handle);
-+void _fv_text_handle_set_position (FvTextHandle *handle,
-+ FvTextHandlePosition pos,
-+ GdkRectangle *rect);
-+void _fv_text_handle_set_visible (FvTextHandle *handle,
-+ FvTextHandlePosition pos,
-+ gboolean visible);
-+
-+void _fv_text_handle_set_relative_to (FvTextHandle *handle,
-+ GdkWindow *window);
-+
-+gboolean _fv_text_handle_get_is_dragged (FvTextHandle *handle,
-+ FvTextHandlePosition pos);
-+
-+G_END_DECLS
-+
-+#endif /* __FV_TEXT_HANDLE_PRIVATE_H__ */
-diff --git a/src/text/fmt/xp/Makefile.am b/src/text/fmt/xp/Makefile.am
-index c8d1b29..ddaf273 100644
---- a/src/text/fmt/xp/Makefile.am
-+++ b/src/text/fmt/xp/Makefile.am
-@@ -104,6 +104,8 @@ libxp_la_SOURCES = \
- fv_InlineImage.h \
- fv_Selection.cpp \
- fv_Selection.h \
-+ fv_SelectionHandles.cpp \
-+ fv_SelectionHandles.h \
- fv_View_cmd.cpp \
- fv_View.cpp \
- fv_View.h \
-diff --git a/src/text/fmt/xp/fv_SelectionHandles.cpp b/src/text/fmt/xp/fv_SelectionHandles.cpp
-new file mode 100644
-index 0000000..c8d538b
---- /dev/null
-+++ b/src/text/fmt/xp/fv_SelectionHandles.cpp
-@@ -0,0 +1,120 @@
-+/* AbiWord - base class for selection handles
-+ * Copyright (c) 2012 One laptop per child
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+ * 02111-1307, USA.
-+ *
-+ * Author: Carlos Garnacho <carlos@lanedo.com>
-+ */
-+
-+#include "fv_View.h"
-+#include "fv_SelectionHandles.h"
-+#include "fp_Page.h"
-+
-+FV_SelectionHandles::FV_SelectionHandles (FV_View * pView, FV_Selection pSelection)
-+ : m_pView (pView),
-+ m_pSelection (pSelection)
-+{
-+}
-+
-+bool FV_SelectionHandles::_getPositionCoords(PT_DocPosition pos, UT_sint32& x, UT_sint32& y, UT_uint32& height)
-+{
-+ UT_sint32 x1, y1, x2, y2;
-+ UT_uint32 h;
-+ bool bPos, visible = true;
-+
-+ m_pView->_findPositionCoords (pos,false, x1, y1,
-+ x2, y2, h,
-+ bPos, NULL, NULL);
-+
-+ if (x1 < 0 || y1 < 0 ||
-+ x1 > m_pView->getWindowWidth() ||
-+ y1 > m_pView->getWindowHeight() - (UT_sint32) h)
-+ visible = false;
-+
-+ x = m_pView->getGraphics()->tdu(x1);
-+ y = m_pView->getGraphics()->tdu(y1);
-+ height = m_pView->getGraphics()->tdu(h);
-+
-+ return visible;
-+}
-+
-+void FV_SelectionHandles::setCursor (PT_DocPosition cursor)
-+{
-+ UT_sint32 x, y;
-+ UT_uint32 height;
-+ bool visible;
-+
-+ visible = _getPositionCoords (cursor, x, y, height);
-+ setCursorCoords(x, y, height, visible);
-+}
-+
-+void FV_SelectionHandles::setSelection (PT_DocPosition start, PT_DocPosition end)
-+{
-+ UT_sint32 start_x, start_y, end_x, end_y;
-+ UT_uint32 start_height, end_height;
-+ bool start_visible, end_visible;
-+
-+ start_visible = _getPositionCoords (start, start_x, start_y, start_height);
-+ end_visible = _getPositionCoords (end, end_x, end_y, end_height);
-+ setSelectionCoords(start_x, start_y, start_height, start_visible,
-+ end_x, end_y, end_height, end_visible);
-+}
-+
-+void FV_SelectionHandles::updateSelectionStart(UT_sint32 x, UT_sint32 y)
-+{
-+ PT_DocPosition pos, right;
-+ fp_Page *page;
-+ bool bBOL, bEOL, isTOC;
-+ UT_sint32 xClick, yClick;
-+
-+ x = m_pView->getGraphics()->tlu(x);
-+ y = m_pView->getGraphics()->tlu(y);
-+ page = m_pView->_getPageForXY(x, y, xClick, yClick);
-+ page->mapXYToPosition(xClick, yClick, pos, bBOL, bEOL,isTOC, true, NULL);
-+ right = m_pView->getSelectionRightAnchor();
-+
-+ pos = UT_MIN (pos, right - 1);
-+
-+ m_pView->selectRange(pos, right);
-+}
-+
-+void FV_SelectionHandles::updateSelectionEnd(UT_sint32 x, UT_sint32 y)
-+{
-+ PT_DocPosition pos, left;
-+ fp_Page *page;
-+ bool bBOL, bEOL, isTOC;
-+ UT_sint32 xClick, yClick;
-+
-+ x = m_pView->getGraphics()->tlu(x);
-+ y = m_pView->getGraphics()->tlu(y);
-+ page = m_pView->_getPageForXY(x, y, xClick, yClick);
-+ page->mapXYToPosition(xClick, yClick, pos, bBOL, bEOL,isTOC, true, NULL);
-+ left = m_pView->getSelectionLeftAnchor();
-+
-+ pos = UT_MAX (pos, left + 1);
-+
-+ m_pView->selectRange(left, pos);
-+}
-+
-+void FV_SelectionHandles::updateCursor(UT_sint32 x, UT_sint32 y)
-+{
-+ x = m_pView->getGraphics()->tlu(x);
-+ y = m_pView->getGraphics()->tlu(y);
-+ m_pView->warpInsPtToXY(x, y, false);
-+}
-+
-+FV_SelectionHandles::~FV_SelectionHandles() {
-+}
-diff --git a/src/text/fmt/xp/fv_SelectionHandles.h b/src/text/fmt/xp/fv_SelectionHandles.h
-new file mode 100644
-index 0000000..d998f5e
---- /dev/null
-+++ b/src/text/fmt/xp/fv_SelectionHandles.h
-@@ -0,0 +1,56 @@
-+/* AbiWord - base class for selection handles
-+ * Copyright (c) 2012 One laptop per child
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+ * 02111-1307, USA.
-+ *
-+ * Author: Carlos Garnacho <carlos@lanedo.com>
-+ */
-+
-+#ifndef FV_SELECTIONHANDLES_H
-+#define FV_SELECTIONHANDLES_H
-+
-+#include "pt_Types.h"
-+#include "fv_Selection.h"
-+
-+class FV_View;
-+
-+class ABI_EXPORT FV_SelectionHandles
-+{
-+public:
-+ FV_SelectionHandles (FV_View * pView, FV_Selection selection);
-+ virtual ~FV_SelectionHandles();
-+
-+ virtual void hide(void) {}
-+ virtual void setCursorCoords(UT_sint32 /*x*/, UT_sint32 /*y*/, UT_uint32 /*height*/, bool /*visible*/) {}
-+ virtual void setSelectionCoords(UT_sint32 /*start_x*/, UT_sint32 /*start_y*/, UT_uint32 /*start_height*/, bool /*start_visible*/,
-+ UT_sint32 /*end_x*/, UT_sint32 /*end_y*/, UT_uint32 /*end_height*/, bool /*end_visible*/) {}
-+
-+ void setCursor(PT_DocPosition cursor);
-+ void setSelection(PT_DocPosition start, PT_DocPosition end);
-+
-+ void updateSelectionStart(UT_sint32 x, UT_sint32 y);
-+ void updateSelectionEnd(UT_sint32 x, UT_sint32 y);
-+ void updateCursor(UT_sint32 x, UT_sint32 y);
-+
-+protected:
-+ FV_View * m_pView;
-+ FV_Selection m_pSelection;
-+
-+private:
-+ bool _getPositionCoords(PT_DocPosition pos, UT_sint32& x, UT_sint32& y, UT_uint32& height);
-+};
-+
-+#endif /* FV_SELECTIONHANDLES_H */
-diff --git a/src/text/fmt/xp/fv_View.cpp b/src/text/fmt/xp/fv_View.cpp
-index cb5d904..9e78a85 100644
---- a/src/text/fmt/xp/fv_View.cpp
-+++ b/src/text/fmt/xp/fv_View.cpp
-@@ -300,6 +300,7 @@ FV_View::FV_View(XAP_App * pApp, void* pParentData, FL_DocLayout* pLayout)
- m_bAllowSmartQuoteReplacement(true),
- m_bubbleBlockerCount(0),
- m_iOldPageCount(-1),
-+ m_SelectionHandles(this, m_Selection),
- m_pViewDoubleBufferingObject(NULL)
- {
- if(m_pDoc)
-@@ -945,7 +946,6 @@ void FV_View::replaceGraphics(GR_Graphics * pG)
- m_pLayout->rebuildFromHere(static_cast<fl_DocSectionLayout *>(m_pLayout->getFirstSection()));
- }
-
--
- //-------------------------
- // Visual Drag stuff
- //
-@@ -2481,6 +2481,7 @@ void FV_View::focusChange(AV_Focus focus)
- _setPoint(getPoint());
- }
- m_pApp->rememberFocussedFrame(m_pParentData);
-+ _updateSelectionHandles();
- break;
- case AV_FOCUS_NEARBY:
- if (isSelectionEmpty() && (getPoint() > 0))
-@@ -2497,6 +2498,7 @@ void FV_View::focusChange(AV_Focus focus)
- }
- break;
- case AV_FOCUS_NONE:
-+ m_SelectionHandles.hide();
- if (isSelectionEmpty() && (getPoint() > 0))
- {
- m_pG->allCarets()->disable(true);
-@@ -6996,6 +6998,13 @@ PT_DocPosition FV_View::getDocPositionFromXY(UT_sint32 xpos, UT_sint32 ypos, boo
- return iNewPoint;
- }
-
-+void FV_View::setVisualSelectionEnabled(bool bActive)
-+{
-+ if (!bActive)
-+ m_SelectionHandles.hide();
-+ m_VisualSelectionActive=bActive;
-+}
-+
- void FV_View::extSelToXY(UT_sint32 xPos, UT_sint32 yPos, bool bDrag)
- {
- // Figure out which page we clicked on.
-@@ -7056,6 +7065,7 @@ void FV_View::extSelToXY(UT_sint32 xPos, UT_sint32 yPos, bool bDrag)
- {
- _extSelToPos(iNewPoint);
- notifyListeners(AV_CHG_MOTION);
-+ _updateSelectionHandles();
- }
- }
-
-@@ -8098,6 +8108,7 @@ void FV_View::warpInsPtToXY(UT_sint32 xPos, UT_sint32 yPos, bool bClick = false)
- _setPoint(pos, bEOL);
- _ensureInsertionPointOnScreen();
- setCursorToContext();
-+ _updateSelectionHandles();
- notifyListeners(AV_CHG_MOTION | AV_CHG_HDRFTR ); // Sevior Put this in
- // notifyListeners(AV_CHG_HDRFTR );
-
-@@ -8309,6 +8320,7 @@ void FV_View::setXScrollOffset(UT_sint32 v) ///////////////////////TODO: Fix thi
- _draw(x1-m_pG->tlu(1), 0, dx2+m_pG->tlu(2), getWindowHeight(), false, true);
-
- _fixInsertionPointCoords();
-+ _updateSelectionHandles();
- }
-
- void FV_View::setYScrollOffset(UT_sint32 v)
-@@ -8323,6 +8335,7 @@ void FV_View::setYScrollOffset(UT_sint32 v)
- m_yScrollOffset = v;
-
- _fixInsertionPointCoords();
-+ _updateSelectionHandles();
- }
-
- void FV_View::draw(int page, dg_DrawArgs* da)
-@@ -14413,11 +14426,14 @@ bool FV_View::rtlPages() const
- void
- FV_View::selectRange( PT_DocPosition start, PT_DocPosition end )
- {
-- _clearSelection();
-+ _clearSelection(false);
- _setPoint(start);
-+ m_Selection.setSelectionLeftAnchor(start);
- _setSelectionAnchor();
- setPoint(end);
-+ m_Selection.setSelectionRightAnchor(end);
- _drawSelection();
-+ _updateSelectionHandles();
- }
-
- void
-diff --git a/src/text/fmt/xp/fv_View.h b/src/text/fmt/xp/fv_View.h
-index a361692..46d16ab 100644
---- a/src/text/fmt/xp/fv_View.h
-+++ b/src/text/fmt/xp/fv_View.h
-@@ -47,8 +47,10 @@
- #include "fv_UnixVisualDrag.h"
- #include "fv_UnixFrameEdit.h"
- #include "fv_UnixInlineImage.h"
-+#include "fv_UnixSelectionHandles.h"
- #else
- #include "fv_VisualDragText.h"
-+#include "fv_SelectionHandles.h"
- #endif
-
- #define AUTO_SCROLL_MSECS 100
-@@ -237,6 +239,7 @@ class ABI_EXPORT FV_View : public AV_View
- friend class CellLine;
- friend class FV_View_BubbleBlocker;
- friend class FV_ViewDoubleBuffering;
-+ friend class FV_SelectionHandles;
- public:
- FV_View(XAP_App*, void*, FL_DocLayout*);
- virtual ~FV_View();
-@@ -266,12 +269,15 @@ public:
-
- virtual void draw(const UT_Rect* pRect=static_cast<UT_Rect*>(NULL));
- virtual void drawSelectionBox(UT_Rect & box, bool drawHandles);
-+
-+ void setVisualSelectionEnabled(bool bActive);
- private:
- inline void _drawResizeHandle(UT_Rect & box);
- void getCmdInsertRangeVariables( PT_DocPosition& posStart,
- PT_DocPosition& posEnd,
- fl_BlockLayout*& pBL1,
- fl_BlockLayout*& pBL2 );
-+ void _updateSelectionHandles (void);
-
-
- public:
-@@ -945,7 +951,7 @@ protected:
- const gchar ** extra_props = NULL);
- void _moveToSelectionEnd(bool bForward);
- void _eraseSelection(void);
-- void _clearSelection(void);
-+ void _clearSelection(bool bRedraw = true);
- void _resetSelection(void);
- void _setSelectionAnchor(void);
- void _deleteSelection(PP_AttrProp *p_AttrProp_Before = NULL,
-@@ -1163,6 +1169,12 @@ private:
- int m_bubbleBlockerCount;
- UT_sint32 m_iOldPageCount;
-
-+#ifdef TOOLKIT_GTK_ALL
-+ FV_UnixSelectionHandles m_SelectionHandles;
-+#else
-+ FV_SelectionHandles m_SelectionHandles;
-+#endif
-+
- public:
- bool registerDoubleBufferingObject(FV_ViewDoubleBuffering *obj);
- bool unregisterDoubleBufferingObject(FV_ViewDoubleBuffering *obj);
-diff --git a/src/text/fmt/xp/fv_View_cmd.cpp b/src/text/fmt/xp/fv_View_cmd.cpp
-index b153dee..0851091 100644
---- a/src/text/fmt/xp/fv_View_cmd.cpp
-+++ b/src/text/fmt/xp/fv_View_cmd.cpp
-@@ -4674,6 +4674,7 @@ void FV_View::cmdCut(void)
- _ensureInsertionPointOnScreen();
- notifyListeners(AV_CHG_ALL);
-
-+ m_SelectionHandles.hide();
- }
-
- // bToClipboard is true if you want to copy to the CLIPBOARD
-diff --git a/src/text/fmt/xp/fv_View_protected.cpp b/src/text/fmt/xp/fv_View_protected.cpp
-index b5c1a85..df3234c 100644
---- a/src/text/fmt/xp/fv_View_protected.cpp
-+++ b/src/text/fmt/xp/fv_View_protected.cpp
-@@ -174,7 +174,7 @@ void FV_View::_eraseSelection(void)
- _clearBetweenPositions(iPos1, iPos2, true);
- }
-
--void FV_View::_clearSelection(void)
-+void FV_View::_clearSelection(bool bRedraw)
- {
- if( isSelectionEmpty() )
- {
-@@ -211,7 +211,8 @@ void FV_View::_clearSelection(void)
- m_iLowDrawPoint = 0;
- m_iHighDrawPoint = 0;
-
-- _drawBetweenPositions(iPos1, iPos2);
-+ if (bRedraw)
-+ _drawBetweenPositions(iPos1, iPos2);
- }
- else
- {
-@@ -235,7 +236,9 @@ void FV_View::_clearSelection(void)
- {
- iPos2++;
- }
-- /*bool bres =*/ _clearBetweenPositions(iPos1, iPos2, true);
-+
-+ if (bRedraw)
-+ /*bool bres =*/ _clearBetweenPositions(iPos1, iPos2, true);
- }
- }
- _resetSelection();
-@@ -250,7 +253,8 @@ void FV_View::_clearSelection(void)
- {
- iPos2++;
- }
-- _drawBetweenPositions(iPos1, iPos2);
-+ if (bRedraw)
-+ _drawBetweenPositions(iPos1, iPos2);
- }
- }
- UT_VECTOR_PURGEALL(PD_DocumentRange *,vecRanges);
-@@ -6440,3 +6444,15 @@ void FV_View::_adjustDeletePosition(UT_uint32 &iDocPos, UT_uint32 &iCount)
- // adjust point
- iDocPos = pos1;
- }
-+
-+void FV_View::_updateSelectionHandles(void)
-+{
-+ if (!getVisualSelectionEnabled()){
-+ m_SelectionHandles.hide();
-+ } else if (isSelectionEmpty()) {
-+ m_SelectionHandles.setCursor(getInsPoint());
-+ } else {
-+ m_SelectionHandles.setSelection(getSelectionLeftAnchor(),
-+ getSelectionRightAnchor());
-+ }
-+}
-diff --git a/src/wp/ap/gtk/ap_UnixFrameImpl.cpp b/src/wp/ap/gtk/ap_UnixFrameImpl.cpp
-index 385b104..b5266ac 100644
---- a/src/wp/ap/gtk/ap_UnixFrameImpl.cpp
-+++ b/src/wp/ap/gtk/ap_UnixFrameImpl.cpp
-@@ -363,6 +363,11 @@ GtkWidget * AP_UnixFrameImpl::_createDocumentWindow()
- return m_wSunkenBox;
- }
-
-+GtkWidget * AP_UnixFrameImpl::getViewWidget(void)
-+{
-+ return m_dArea;
-+}
-+
- void AP_UnixFrameImpl::_hideMenuScroll(bool bHideMenuScroll)
- {
- if(bHideMenuScroll)
-diff --git a/src/wp/ap/gtk/ap_UnixFrameImpl.h b/src/wp/ap/gtk/ap_UnixFrameImpl.h
-index 388d761..01b45f8 100644
---- a/src/wp/ap/gtk/ap_UnixFrameImpl.h
-+++ b/src/wp/ap/gtk/ap_UnixFrameImpl.h
-@@ -48,6 +48,7 @@ class AP_UnixFrameImpl : public XAP_UnixFrameImpl
- GtkWidget * getDrawingArea() const {return m_dArea;}
- static gboolean ap_focus_in_event (GtkWidget * drawing_area, GdkEventCrossing *event, AP_UnixFrameImpl * me);
- static gboolean ap_focus_out_event (GtkWidget * drawing_area, GdkEventCrossing *event, AP_UnixFrameImpl * me);
-+ virtual GtkWidget * getViewWidget(void);
-
- protected:
- friend class AP_UnixFrame;
+diff --git a/src/af/ev/gtk/ev_UnixKeyboard.cpp b/src/af/ev/gtk/ev_UnixKeyboard.cpp +index 5c5c109..af51672 100644 +--- a/src/af/ev/gtk/ev_UnixKeyboard.cpp ++++ b/src/af/ev/gtk/ev_UnixKeyboard.cpp +@@ -79,6 +79,8 @@ bool ev_UnixKeyboard::keyPressEvent(AV_View* pView, GdkEventKey* e) + + UT_uint32 charData = e->keyval; + ++ pView->setVisualSelectionEnabled(false); ++ + if (e->state & GDK_SHIFT_MASK) + state |= EV_EMS_SHIFT; + if (e->state & GDK_CONTROL_MASK) +diff --git a/src/af/ev/gtk/ev_UnixMouse.cpp b/src/af/ev/gtk/ev_UnixMouse.cpp +index 17ac999..2ca54ec 100644 +--- a/src/af/ev/gtk/ev_UnixMouse.cpp ++++ b/src/af/ev/gtk/ev_UnixMouse.cpp +@@ -111,6 +111,9 @@ void EV_UnixMouse::mouseClick(AV_View* pView, GdkEventButton* e) + EV_EditMouseButton emb = 0; + EV_EditMouseOp mop = 0; + EV_EditMouseContext emc = 0; ++ GdkDevice *device; ++ ++ device = gdk_event_get_source_device((GdkEvent *) e); + + if (e->button == 1) + emb = EV_EMB_BUTTON1; +@@ -160,6 +163,12 @@ void EV_UnixMouse::mouseClick(AV_View* pView, GdkEventButton* e) + UT_ASSERT(pEM); + invokeMouseMethod(pView,pEM,static_cast<UT_sint32>(pView->getGraphics()->tluD(e->x)),static_cast<UT_sint32>(pView->getGraphics()->tluD(e->y))); + signal(emc|mop|emb|state, static_cast<UT_sint32>(pView->getGraphics()->tluD(e->x)),static_cast<UT_sint32>(pView->getGraphics()->tluD(e->y))); ++ ++ if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN || getenv ("ABI_TEST_TOUCH")) { ++ pView->setVisualSelectionEnabled(true); ++ } else { ++ pView->setVisualSelectionEnabled(false); ++ } + return; + case EV_EEMR_INCOMPLETE: + // I'm not sure this makes any sense, but we allow it. +@@ -182,7 +191,10 @@ void EV_UnixMouse::mouseMotion(AV_View* pView, GdkEventMotion *e) + EV_EditMouseButton emb = 0; + EV_EditMouseOp mop; + EV_EditMouseContext emc = 0; +- ++ GdkDevice *device; ++ ++ device = gdk_event_get_source_device((GdkEvent *) e); ++ + if (e->state & GDK_SHIFT_MASK) + ems |= EV_EMS_SHIFT; + if (e->state & GDK_CONTROL_MASK) +diff --git a/src/af/xap/gtk/xap_UnixFrameImpl.h b/src/af/xap/gtk/xap_UnixFrameImpl.h +index 887104e..da4c1ac 100644 +--- a/src/af/xap/gtk/xap_UnixFrameImpl.h ++++ b/src/af/xap/gtk/xap_UnixFrameImpl.h +@@ -67,6 +67,8 @@ class XAP_UnixFrameImpl : public XAP_FrameImpl + } + void resetIMContext (); + ++ virtual GtkWidget * getViewWidget (void) {return NULL;} ++ + private: + void _setGeometry (); + +diff --git a/src/af/xap/xp/xav_View.cpp b/src/af/xap/xp/xav_View.cpp +index 21bf216..709eaad 100644 +--- a/src/af/xap/xp/xav_View.cpp ++++ b/src/af/xap/xp/xav_View.cpp +@@ -39,7 +39,8 @@ AV_View::AV_View(XAP_App * pApp, void* pParentData) + m_iWindowWidth(0), + m_dOneTDU(0), + m_bCouldBeActive(true), +- m_bConfigureChanged(false) ++ m_bConfigureChanged(false), ++ m_VisualSelectionActive(false) + { + } + +diff --git a/src/af/xap/xp/xav_View.h b/src/af/xap/xp/xav_View.h +index b411864..f7c7f22 100644 +--- a/src/af/xap/xp/xav_View.h ++++ b/src/af/xap/xp/xav_View.h +@@ -150,6 +150,9 @@ public: + virtual void cmdPaste(bool bHonorFormatting = true) = 0; + virtual void cmdPasteSelectionAt(UT_sint32 xPos, UT_sint32 yPos) = 0; + ++ virtual void setVisualSelectionEnabled(bool bActive) { m_VisualSelectionActive=bActive; } ++ bool getVisualSelectionEnabled(void) { return m_VisualSelectionActive; } ++ + // + // Let subclasses override but this is here to avoid a crash on frame closing. + // With a selection in place. (Rather than pure virtual.) +@@ -177,6 +180,7 @@ protected: + AV_Focus m_focus; + UT_uint32 m_iTick; // Count changes + bool m_bInsertMode; ++ bool m_VisualSelectionActive; + + UT_GenericVector<AV_ScrollObj*> m_scrollListeners; + UT_GenericVector<AV_Listener*> m_vecListeners; +diff --git a/src/text/fmt/gtk/Makefile.am b/src/text/fmt/gtk/Makefile.am +index 4d96dfd..46ca135 100644 +--- a/src/text/fmt/gtk/Makefile.am ++++ b/src/text/fmt/gtk/Makefile.am +@@ -6,11 +6,18 @@ noinst_LTLIBRARIES = libgtk.la + AM_CPPFLAGS = \ + $(IMPEXP_CPPFLAGS) + ++cut_and_paste_code = \ ++ gtktexthandle.c ++ gtktexthandleprivate.h ++ + libgtk_la_SOURCES = \ ++ $(cut_and_paste_code) \ + fv_UnixFrameEdit.cpp \ + fv_UnixFrameEdit.h \ + fv_UnixInlineImage.cpp \ + fv_UnixInlineImage.h \ ++ fv_UnixSelectionHandles.cpp \ ++ fv_UnixSelectionHandles.h \ + fv_UnixVisualDrag.cpp \ + fv_UnixVisualDrag.h + +diff --git a/src/text/fmt/gtk/fv_UnixSelectionHandles.cpp b/src/text/fmt/gtk/fv_UnixSelectionHandles.cpp +new file mode 100644 +index 0000000..935e8fa +--- /dev/null ++++ b/src/text/fmt/gtk/fv_UnixSelectionHandles.cpp +@@ -0,0 +1,123 @@ ++/* AbiWord - unix impl for selection handles ++ * Copyright (c) 2012 One laptop per child ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ * ++ * Author: Carlos Garnacho <carlos@lanedo.com> ++ */ ++ ++#include "xap_Frame.h" ++#include "xap_UnixFrameImpl.h" ++#include "fv_UnixSelectionHandles.h" ++#include "fv_View.h" ++#include "gtktexthandleprivate.h" ++ ++static void handle_dragged_cb (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ gint x, ++ gint y, ++ gpointer user_data) ++{ ++ FvTextHandleMode mode; ++ FV_UnixSelectionHandles *handles = static_cast<FV_UnixSelectionHandles *>(user_data); ++ ++ mode = _fv_text_handle_get_mode (handle); ++ ++ if (pos == FV_TEXT_HANDLE_POSITION_SELECTION_START) ++ handles->updateSelectionStart ((UT_sint32)x, (UT_sint32)y); ++ else { ++ if (mode == FV_TEXT_HANDLE_MODE_SELECTION) ++ handles->updateSelectionEnd ((UT_sint32)x, (UT_sint32)y); ++ else ++ handles->updateCursor((UT_sint32)x, (UT_sint32)y); ++ } ++} ++ ++FV_UnixSelectionHandles::FV_UnixSelectionHandles(FV_View *view, FV_Selection selection) ++ : FV_SelectionHandles (view, selection) ++{ ++ XAP_Frame * pFrame = static_cast<XAP_Frame*>(m_pView->getParentData()); ++ XAP_UnixFrameImpl * pFrameImpl =static_cast<XAP_UnixFrameImpl *>( pFrame->getFrameImpl()); ++ GtkWidget * pWidget = pFrameImpl->getViewWidget(); ++ ++ m_text_handle = _fv_text_handle_new (pWidget); ++ _fv_text_handle_set_relative_to (m_text_handle, ++ gtk_widget_get_window (pWidget)); ++ g_signal_connect (m_text_handle, "handle-dragged", ++ G_CALLBACK(handle_dragged_cb), this); ++} ++ ++FV_UnixSelectionHandles::~FV_UnixSelectionHandles() ++{ ++ g_object_unref (m_text_handle); ++} ++ ++void FV_UnixSelectionHandles::hide() ++{ ++ _fv_text_handle_set_mode (m_text_handle, FV_TEXT_HANDLE_MODE_NONE); ++} ++ ++void FV_UnixSelectionHandles::setCursorCoords(UT_sint32 x, UT_sint32 y, UT_uint32 height, bool visible) ++{ ++ GdkRectangle rect; ++ ++ _fv_text_handle_set_mode(m_text_handle, FV_TEXT_HANDLE_MODE_CURSOR); ++ _fv_text_handle_set_visible (m_text_handle, FV_TEXT_HANDLE_POSITION_CURSOR, visible); ++ ++ if (visible) ++ { ++ rect.x = (int)x; ++ rect.y = (int)y; ++ rect.width = 1; ++ rect.height = (int)height; ++ _fv_text_handle_set_position(m_text_handle, ++ FV_TEXT_HANDLE_POSITION_CURSOR, ++ &rect); ++ } ++} ++ ++void FV_UnixSelectionHandles::setSelectionCoords(UT_sint32 start_x, UT_sint32 start_y, UT_uint32 start_height, bool start_visible, ++ UT_sint32 end_x, UT_sint32 end_y, UT_uint32 end_height, bool end_visible) ++{ ++ GdkRectangle rect; ++ ++ _fv_text_handle_set_mode(m_text_handle, FV_TEXT_HANDLE_MODE_SELECTION); ++ ++ _fv_text_handle_set_visible (m_text_handle, FV_TEXT_HANDLE_POSITION_SELECTION_START, start_visible); ++ _fv_text_handle_set_visible (m_text_handle, FV_TEXT_HANDLE_POSITION_SELECTION_END, end_visible); ++ ++ if (start_visible) ++ { ++ rect.x = (int)start_x; ++ rect.y = (int)start_y; ++ rect.width = 1; ++ rect.height = (int)start_height; ++ _fv_text_handle_set_position(m_text_handle, ++ FV_TEXT_HANDLE_POSITION_SELECTION_START, ++ &rect); ++ } ++ ++ if (end_visible) ++ { ++ rect.x = (int)end_x; ++ rect.y = (int)end_y; ++ rect.width = 1; ++ rect.height = (int)end_height; ++ _fv_text_handle_set_position(m_text_handle, ++ FV_TEXT_HANDLE_POSITION_SELECTION_END, ++ &rect); ++ } ++} +diff --git a/src/text/fmt/gtk/fv_UnixSelectionHandles.h b/src/text/fmt/gtk/fv_UnixSelectionHandles.h +new file mode 100644 +index 0000000..809ae2e +--- /dev/null ++++ b/src/text/fmt/gtk/fv_UnixSelectionHandles.h +@@ -0,0 +1,45 @@ ++/* AbiWord - unix impl for selection handles ++ * Copyright (c) 2012 One laptop per child ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ * ++ * Author: Carlos Garnacho <carlos@lanedo.com> ++ */ ++ ++#ifndef FV_UNIXSELECTIONHANDLES_H ++#define FV_UNIXSELECTIONHANDLES_H ++ ++#include "fv_SelectionHandles.h" ++#include "gtktexthandleprivate.h" ++ ++class ABI_EXPORT FV_UnixSelectionHandles : public FV_SelectionHandles ++{ ++ friend class fv_View; ++ ++public: ++ FV_UnixSelectionHandles (FV_View * pView, FV_Selection selection); ++ virtual ~FV_UnixSelectionHandles(); ++ ++ virtual void hide(void); ++ virtual void setCursorCoords (UT_sint32 x, UT_sint32 y, UT_uint32 height, bool visible); ++ virtual void setSelectionCoords (UT_sint32 start_x, UT_sint32 start_y, UT_uint32 start_height, bool start_visible, ++ UT_sint32 end_x, UT_sint32 end_y, UT_uint32 end_height, bool end_visible); ++ ++private: ++ FvTextHandle *m_text_handle; ++}; ++ ++#endif /* FV_UNIXSELECTIONHANDLES_H */ +diff --git a/src/text/fmt/gtk/gtktexthandle.c b/src/text/fmt/gtk/gtktexthandle.c +new file mode 100644 +index 0000000..6ff0ffa +--- /dev/null ++++ b/src/text/fmt/gtk/gtktexthandle.c +@@ -0,0 +1,701 @@ ++/* GTK - The GIMP Toolkit ++ * Copyright © 2012 Carlos Garnacho <carlosg@gnome.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "gtktexthandleprivate.h" ++#include <gtk/gtk.h> ++ ++typedef struct _FvTextHandlePrivate FvTextHandlePrivate; ++typedef struct _HandleWindow HandleWindow; ++ ++enum { ++ HANDLE_DRAGGED, ++ DRAG_FINISHED, ++ LAST_SIGNAL ++}; ++ ++enum { ++ PROP_0, ++ PROP_PARENT, ++ PROP_RELATIVE_TO ++}; ++ ++struct _HandleWindow ++{ ++ GdkWindow *window; ++ GdkRectangle pointing_to; ++ gint dx; ++ gint dy; ++ guint dragged : 1; ++ guint mode_visible : 1; ++ guint user_visible : 1; ++ guint has_point : 1; ++}; ++ ++struct _FvTextHandlePrivate ++{ ++ HandleWindow windows[2]; ++ GtkWidget *parent; ++ GdkWindow *relative_to; ++ GtkStyleContext *style_context; ++ ++ gulong draw_signal_id; ++ gulong event_signal_id; ++ gulong style_updated_id; ++ gulong composited_changed_id; ++ guint realized : 1; ++ guint mode : 2; ++}; ++ ++G_DEFINE_TYPE (FvTextHandle, _fv_text_handle, G_TYPE_OBJECT) ++ ++static guint signals[LAST_SIGNAL] = { 0 }; ++ ++static void ++_fv_text_handle_get_size (FvTextHandle *handle, ++ gint *width, ++ gint *height) ++{ ++ FvTextHandlePrivate *priv; ++ gint w, h; ++ ++ priv = handle->priv; ++ ++ gtk_widget_style_get (priv->parent, ++ "text-handle-width", &w, ++ "text-handle-height", &h, ++ NULL); ++ if (width) ++ *width = w; ++ ++ if (height) ++ *height = h; ++} ++ ++static void ++_fv_text_handle_draw (FvTextHandle *handle, ++ cairo_t *cr, ++ FvTextHandlePosition pos) ++{ ++ FvTextHandlePrivate *priv; ++ gint width, height; ++ ++ priv = handle->priv; ++ cairo_save (cr); ++ ++ cairo_save (cr); ++ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); ++ cairo_set_source_rgba (cr, 0, 0, 0, 0); ++ cairo_paint (cr); ++ cairo_restore (cr); ++ ++ gtk_style_context_save (priv->style_context); ++ gtk_style_context_add_class (priv->style_context, "cursor-handle"); ++ ++ if (pos == FV_TEXT_HANDLE_POSITION_SELECTION_END) ++ { ++ gtk_style_context_add_class (priv->style_context, ++ GTK_STYLE_CLASS_BOTTOM); ++ ++ if (priv->mode == FV_TEXT_HANDLE_MODE_CURSOR) ++ gtk_style_context_add_class (priv->style_context, "insertion-cursor"); ++ } ++ else ++ gtk_style_context_add_class (priv->style_context, "top"); ++ ++ _fv_text_handle_get_size (handle, &width, &height); ++ gtk_render_background (priv->style_context, cr, 0, 0, width, height); ++ ++ gtk_style_context_restore (priv->style_context); ++ cairo_restore (cr); ++} ++ ++static void ++_fv_text_handle_update_shape (FvTextHandle *handle, ++ GdkWindow *window, ++ FvTextHandlePosition pos) ++{ ++ FvTextHandlePrivate *priv; ++ cairo_surface_t *surface; ++ cairo_region_t *region; ++ cairo_t *cr; ++ ++ priv = handle->priv; ++ ++ surface = ++ gdk_window_create_similar_surface (window, ++ CAIRO_CONTENT_COLOR_ALPHA, ++ gdk_window_get_width (window), ++ gdk_window_get_height (window)); ++ ++ cr = cairo_create (surface); ++ _fv_text_handle_draw (handle, cr, pos); ++ cairo_destroy (cr); ++ ++ region = gdk_cairo_region_create_from_surface (surface); ++ ++ if (gtk_widget_is_composited (priv->parent)) ++ gdk_window_shape_combine_region (window, NULL, 0, 0); ++ else ++ gdk_window_shape_combine_region (window, region, 0, 0); ++ ++ gdk_window_input_shape_combine_region (window, region, 0, 0); ++ ++ cairo_surface_destroy (surface); ++ cairo_region_destroy (region); ++} ++ ++static GdkWindow * ++_fv_text_handle_create_window (FvTextHandle *handle, ++ FvTextHandlePosition pos) ++{ ++ FvTextHandlePrivate *priv; ++ GdkRGBA bg = { 0, 0, 0, 0 }; ++ GdkWindowAttr attributes; ++ GdkWindow *window; ++ GdkVisual *visual; ++ gint mask; ++ ++ priv = handle->priv; ++ ++ attributes.x = 0; ++ attributes.y = 0; ++ _fv_text_handle_get_size (handle, &attributes.width, &attributes.height); ++ attributes.window_type = GDK_WINDOW_TEMP; ++ attributes.wclass = GDK_INPUT_OUTPUT; ++ attributes.event_mask = (GDK_EXPOSURE_MASK | ++ GDK_BUTTON_PRESS_MASK | ++ GDK_BUTTON_RELEASE_MASK | ++ GDK_BUTTON1_MOTION_MASK); ++ ++ mask = GDK_WA_X | GDK_WA_Y; ++ ++ visual = gdk_screen_get_rgba_visual (gtk_widget_get_screen (priv->parent)); ++ ++ if (visual) ++ { ++ attributes.visual = visual; ++ mask |= GDK_WA_VISUAL; ++ } ++ ++ window = gdk_window_new (NULL, &attributes, mask); ++ gdk_window_set_user_data (window, priv->parent); ++ gdk_window_set_background_rgba (window, &bg); ++ ++ _fv_text_handle_update_shape (handle, window, pos); ++ ++ return window; ++} ++ ++static gboolean ++fv_text_handle_widget_draw (GtkWidget *widget, ++ cairo_t *cr, ++ FvTextHandle *handle) ++{ ++ FvTextHandlePrivate *priv; ++ FvTextHandlePosition pos; ++ ++ priv = handle->priv; ++ ++ if (!priv->realized) ++ return FALSE; ++ ++ if (gtk_cairo_should_draw_window (cr, priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window)) ++ pos = FV_TEXT_HANDLE_POSITION_SELECTION_START; ++ else if (gtk_cairo_should_draw_window (cr, priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window)) ++ pos = FV_TEXT_HANDLE_POSITION_SELECTION_END; ++ else ++ return FALSE; ++ ++ _fv_text_handle_draw (handle, cr, pos); ++ return TRUE; ++} ++ ++static gboolean ++fv_text_handle_widget_event (GtkWidget *widget, ++ GdkEvent *event, ++ FvTextHandle *handle) ++{ ++ FvTextHandlePrivate *priv; ++ FvTextHandlePosition pos; ++ ++ priv = handle->priv; ++ ++ if (event->any.window == priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window) ++ pos = FV_TEXT_HANDLE_POSITION_SELECTION_START; ++ else if (event->any.window == priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window) ++ pos = FV_TEXT_HANDLE_POSITION_SELECTION_END; ++ else ++ return FALSE; ++ ++ if (event->type == GDK_BUTTON_PRESS) ++ { ++ priv->windows[pos].dx = event->button.x; ++ priv->windows[pos].dy = event->button.y; ++ priv->windows[pos].dragged = TRUE; ++ } ++ else if (event->type == GDK_BUTTON_RELEASE) ++ { ++ g_signal_emit (handle, signals[DRAG_FINISHED], 0, pos); ++ priv->windows[pos].dx = priv->windows[pos].dy = 0; ++ priv->windows[pos].dragged = FALSE; ++ } ++ else if (event->type == GDK_MOTION_NOTIFY && priv->windows[pos].dragged) ++ { ++ gint x, y, width, height; ++ ++ _fv_text_handle_get_size (handle, &width, &height); ++ gdk_window_get_origin (priv->relative_to, &x, &y); ++ ++ x = event->motion.x_root - priv->windows[pos].dx + (width / 2) - x; ++ y = event->motion.y_root - priv->windows[pos].dy - y; ++ ++ if (pos == FV_TEXT_HANDLE_POSITION_SELECTION_START) ++ y += height; ++ ++ g_signal_emit (handle, signals[HANDLE_DRAGGED], 0, pos, x, y); ++ } ++ ++ return TRUE; ++} ++ ++static void ++_fv_text_handle_update_window_state (FvTextHandle *handle, ++ FvTextHandlePosition pos) ++{ ++ FvTextHandlePrivate *priv; ++ HandleWindow *handle_window; ++ ++ priv = handle->priv; ++ handle_window = &priv->windows[pos]; ++ ++ if (!handle_window->window) ++ return; ++ ++ if (handle_window->has_point && ++ handle_window->mode_visible && handle_window->user_visible) ++ { ++ gint x, y, width, height; ++ ++ x = handle_window->pointing_to.x; ++ y = handle_window->pointing_to.y; ++ _fv_text_handle_get_size (handle, &width, &height); ++ ++ if (pos == FV_TEXT_HANDLE_POSITION_CURSOR) ++ y += handle_window->pointing_to.height; ++ else ++ y -= height; ++ ++ x -= width / 2; ++ ++ gdk_window_move_resize (handle_window->window, x, y, width, height); ++ gdk_window_show (handle_window->window); ++ } ++ else ++ gdk_window_hide (handle_window->window); ++} ++ ++static void ++_fv_text_handle_update_window (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ gboolean recreate) ++{ ++ FvTextHandlePrivate *priv; ++ HandleWindow *handle_window; ++ gboolean visible; ++ gint x, y; ++ ++ priv = handle->priv; ++ handle_window = &priv->windows[pos]; ++ ++ if (!handle_window->window) ++ return; ++ ++ if (recreate) ++ { ++ gdk_window_destroy (handle_window->window); ++ handle_window->window = _fv_text_handle_create_window (handle, pos); ++ } ++ ++ _fv_text_handle_update_window_state (handle, pos); ++} ++ ++static void ++_fv_text_handle_update_windows (FvTextHandle *handle) ++{ ++ FvTextHandlePrivate *priv = handle->priv; ++ ++ gtk_style_context_invalidate (priv->style_context); ++ _fv_text_handle_update_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START, FALSE); ++ _fv_text_handle_update_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_END, FALSE); ++} ++ ++static void ++_fv_text_handle_composited_changed (FvTextHandle *handle) ++{ ++ _fv_text_handle_update_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START, TRUE); ++ _fv_text_handle_update_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_END, TRUE); ++} ++ ++static void ++fv_text_handle_constructed (GObject *object) ++{ ++ FvTextHandlePrivate *priv; ++ ++ priv = FV_TEXT_HANDLE (object)->priv; ++ g_assert (priv->parent != NULL); ++ ++ priv->draw_signal_id = ++ g_signal_connect (priv->parent, "draw", ++ G_CALLBACK (fv_text_handle_widget_draw), ++ object); ++ priv->event_signal_id = ++ g_signal_connect (priv->parent, "event", ++ G_CALLBACK (fv_text_handle_widget_event), ++ object); ++ priv->composited_changed_id = ++ g_signal_connect_swapped (priv->parent, "composited-changed", ++ G_CALLBACK (_fv_text_handle_composited_changed), ++ object); ++ priv->style_updated_id = ++ g_signal_connect_swapped (priv->parent, "style-updated", ++ G_CALLBACK (_fv_text_handle_update_windows), ++ object); ++} ++ ++static void ++fv_text_handle_finalize (GObject *object) ++{ ++ FvTextHandlePrivate *priv; ++ ++ priv = FV_TEXT_HANDLE (object)->priv; ++ ++ if (priv->relative_to) ++ g_object_unref (priv->relative_to); ++ ++ if (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window) ++ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window); ++ ++ if (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window) ++ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window); ++ ++#if 0 ++ if (g_signal_handler_is_connected (priv->parent, priv->draw_signal_id)) ++ g_signal_handler_disconnect (priv->parent, priv->draw_signal_id); ++ ++ if (g_signal_handler_is_connected (priv->parent, priv->event_signal_id)) ++ g_signal_handler_disconnect (priv->parent, priv->event_signal_id); ++ ++ if (g_signal_handler_is_connected (priv->parent, priv->composited_changed_id)) ++ g_signal_handler_disconnect (priv->parent, priv->composited_changed_id); ++ ++ if (g_signal_handler_is_connected (priv->parent, priv->style_updated_id)) ++ g_signal_handler_disconnect (priv->parent, priv->style_updated_id); ++#endif ++ ++ g_object_unref (priv->style_context); ++ ++ G_OBJECT_CLASS (_fv_text_handle_parent_class)->finalize (object); ++} ++ ++static void ++fv_text_handle_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ FvTextHandlePrivate *priv; ++ FvTextHandle *handle; ++ ++ handle = FV_TEXT_HANDLE (object); ++ priv = handle->priv; ++ ++ switch (prop_id) ++ { ++ case PROP_PARENT: ++ priv->parent = g_value_get_object (value); ++ break; ++ case PROP_RELATIVE_TO: ++ _fv_text_handle_set_relative_to (handle, ++ g_value_get_object (value)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++fv_text_handle_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ FvTextHandlePrivate *priv; ++ ++ priv = FV_TEXT_HANDLE (object)->priv; ++ ++ switch (prop_id) ++ { ++ case PROP_PARENT: ++ g_value_set_object (value, priv->parent); ++ break; ++ case PROP_RELATIVE_TO: ++ g_value_set_object (value, priv->relative_to); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++_fv_text_handle_class_init (FvTextHandleClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->constructed = fv_text_handle_constructed; ++ object_class->finalize = fv_text_handle_finalize; ++ object_class->set_property = fv_text_handle_set_property; ++ object_class->get_property = fv_text_handle_get_property; ++ ++ signals[HANDLE_DRAGGED] = ++ g_signal_new ("handle-dragged", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (FvTextHandleClass, handle_dragged), ++ NULL, NULL, ++ g_cclosure_marshal_generic, ++ G_TYPE_NONE, 3, ++ G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); ++ signals[DRAG_FINISHED] = ++ g_signal_new ("drag-finished", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, 0, ++ NULL, NULL, ++ g_cclosure_marshal_VOID__INT, ++ G_TYPE_NONE, 1, G_TYPE_INT); ++ ++ g_object_class_install_property (object_class, ++ PROP_PARENT, ++ g_param_spec_object ("parent", ++ "Parent widget", ++ "Parent widget", ++ GTK_TYPE_WIDGET, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY)); ++ g_object_class_install_property (object_class, ++ PROP_RELATIVE_TO, ++ g_param_spec_object ("relative-to", ++ "Window", ++ "Window the coordinates are based upon", ++ GDK_TYPE_WINDOW, ++ G_PARAM_READWRITE)); ++ ++ g_type_class_add_private (object_class, sizeof (FvTextHandlePrivate)); ++} ++ ++static void ++_fv_text_handle_init (FvTextHandle *handle) ++{ ++ FvTextHandlePrivate *priv; ++ GtkWidgetPath *path; ++ ++ handle->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (handle, ++ FV_TYPE_TEXT_HANDLE, ++ FvTextHandlePrivate); ++ ++ path = gtk_widget_path_new (); ++ gtk_widget_path_append_type (path, FV_TYPE_TEXT_HANDLE); ++ ++ priv->style_context = gtk_style_context_new (); ++ gtk_style_context_set_path (priv->style_context, path); ++ gtk_widget_path_free (path); ++} ++ ++FvTextHandle * ++_fv_text_handle_new (GtkWidget *parent) ++{ ++ return g_object_new (FV_TYPE_TEXT_HANDLE, ++ "parent", parent, ++ NULL); ++} ++ ++void ++_fv_text_handle_set_relative_to (FvTextHandle *handle, ++ GdkWindow *window) ++{ ++ FvTextHandlePrivate *priv; ++ ++ g_return_if_fail (FV_IS_TEXT_HANDLE (handle)); ++ g_return_if_fail (!window || GDK_IS_WINDOW (window)); ++ ++ priv = handle->priv; ++ ++ if (priv->relative_to) ++ { ++ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window); ++ gdk_window_destroy (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window); ++ g_object_unref (priv->relative_to); ++ } ++ ++ if (window) ++ { ++ priv->relative_to = g_object_ref (window); ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window = ++ _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START); ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window = ++ _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_END); ++ priv->realized = TRUE; ++ } ++ else ++ { ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window = NULL; ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window = NULL; ++ priv->relative_to = NULL; ++ priv->realized = FALSE; ++ } ++ ++ g_object_notify (G_OBJECT (handle), "relative-to"); ++} ++ ++void ++_fv_text_handle_set_mode (FvTextHandle *handle, ++ FvTextHandleMode mode) ++{ ++ FvTextHandlePrivate *priv; ++ ++ g_return_if_fail (FV_IS_TEXT_HANDLE (handle)); ++ ++ priv = handle->priv; ++ ++ if (priv->mode == mode) ++ return; ++ ++ priv->mode = mode; ++ ++ switch (mode) ++ { ++ case FV_TEXT_HANDLE_MODE_CURSOR: ++ priv->windows[FV_TEXT_HANDLE_POSITION_CURSOR].mode_visible = TRUE; ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = FALSE; ++ break; ++ case FV_TEXT_HANDLE_MODE_SELECTION: ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = TRUE; ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].mode_visible = TRUE; ++ break; ++ case FV_TEXT_HANDLE_MODE_NONE: ++ default: ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = FALSE; ++ priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].mode_visible = FALSE; ++ break; ++ } ++ ++ if (mode != FV_TEXT_HANDLE_MODE_NONE) ++ _fv_text_handle_update_shape (handle, ++ priv->windows[FV_TEXT_HANDLE_POSITION_CURSOR].window, ++ FV_TEXT_HANDLE_POSITION_CURSOR); ++ ++ _fv_text_handle_update_window_state (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START); ++ _fv_text_handle_update_window_state (handle, FV_TEXT_HANDLE_POSITION_SELECTION_END); ++} ++ ++FvTextHandleMode ++_fv_text_handle_get_mode (FvTextHandle *handle) ++{ ++ FvTextHandlePrivate *priv; ++ ++ g_return_val_if_fail (FV_IS_TEXT_HANDLE (handle), FV_TEXT_HANDLE_MODE_NONE); ++ ++ priv = handle->priv; ++ return priv->mode; ++} ++ ++void ++_fv_text_handle_set_position (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ GdkRectangle *rect) ++{ ++ FvTextHandlePrivate *priv; ++ gint x, y, width, height; ++ HandleWindow *handle_window; ++ ++ g_return_if_fail (FV_IS_TEXT_HANDLE (handle)); ++ ++ priv = handle->priv; ++ pos = CLAMP (pos, FV_TEXT_HANDLE_POSITION_CURSOR, ++ FV_TEXT_HANDLE_POSITION_SELECTION_START); ++ handle_window = &priv->windows[pos]; ++ ++ if (!priv->realized) ++ return; ++ ++ if (priv->mode == FV_TEXT_HANDLE_MODE_NONE || ++ (priv->mode == FV_TEXT_HANDLE_MODE_CURSOR && ++ pos != FV_TEXT_HANDLE_POSITION_CURSOR)) ++ return; ++ ++ handle_window->pointing_to = *rect; ++ handle_window->has_point = TRUE; ++ gdk_window_get_root_coords (priv->relative_to, ++ rect->x, rect->y, ++ &handle_window->pointing_to.x, ++ &handle_window->pointing_to.y); ++ ++ _fv_text_handle_update_window_state (handle, pos); ++} ++ ++void ++_fv_text_handle_set_visible (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ gboolean visible) ++{ ++ FvTextHandlePrivate *priv; ++ GdkWindow *window; ++ ++ g_return_if_fail (FV_IS_TEXT_HANDLE (handle)); ++ ++ priv = handle->priv; ++ pos = CLAMP (pos, FV_TEXT_HANDLE_POSITION_CURSOR, ++ FV_TEXT_HANDLE_POSITION_SELECTION_START); ++ ++ if (!priv->realized) ++ return; ++ ++ window = priv->windows[pos].window; ++ ++ if (!window) ++ return; ++ ++ if (priv->windows[pos].dragged) ++ return; ++ ++ priv->windows[pos].user_visible = visible; ++ _fv_text_handle_update_window_state (handle, pos); ++} ++ ++gboolean ++_fv_text_handle_get_is_dragged (FvTextHandle *handle, ++ FvTextHandlePosition pos) ++{ ++ FvTextHandlePrivate *priv; ++ ++ g_return_val_if_fail (FV_IS_TEXT_HANDLE (handle), FALSE); ++ ++ priv = handle->priv; ++ pos = CLAMP (pos, FV_TEXT_HANDLE_POSITION_CURSOR, ++ FV_TEXT_HANDLE_POSITION_SELECTION_START); ++ ++ return priv->windows[pos].dragged; ++} +diff --git a/src/text/fmt/gtk/gtktexthandleprivate.h b/src/text/fmt/gtk/gtktexthandleprivate.h +new file mode 100644 +index 0000000..d25dc72 +--- /dev/null ++++ b/src/text/fmt/gtk/gtktexthandleprivate.h +@@ -0,0 +1,90 @@ ++/* GTK - The GIMP Toolkit ++ * Copyright © 2012 Carlos Garnacho <carlosg@gnome.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef __FV_TEXT_HANDLE_PRIVATE_H__ ++#define __FV_TEXT_HANDLE_PRIVATE_H__ ++ ++#include <gtk/gtk.h> ++ ++G_BEGIN_DECLS ++ ++#define FV_TYPE_TEXT_HANDLE (_fv_text_handle_get_type ()) ++#define FV_TEXT_HANDLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FV_TYPE_TEXT_HANDLE, FvTextHandle)) ++#define FV_TEXT_HANDLE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), FV_TYPE_TEXT_HANDLE, FvTextHandleClass)) ++#define FV_IS_TEXT_HANDLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FV_TYPE_TEXT_HANDLE)) ++#define FV_IS_TEXT_HANDLE_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), FV_TYPE_TEXT_HANDLE)) ++#define FV_TEXT_HANDLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FV_TYPE_TEXT_HANDLE, FvTextHandleClass)) ++ ++typedef struct _FvTextHandle FvTextHandle; ++typedef struct _FvTextHandleClass FvTextHandleClass; ++ ++typedef enum ++{ ++ FV_TEXT_HANDLE_POSITION_CURSOR, ++ FV_TEXT_HANDLE_POSITION_SELECTION_START, ++ FV_TEXT_HANDLE_POSITION_SELECTION_END = FV_TEXT_HANDLE_POSITION_CURSOR ++} FvTextHandlePosition; ++ ++typedef enum ++{ ++ FV_TEXT_HANDLE_MODE_NONE, ++ FV_TEXT_HANDLE_MODE_CURSOR, ++ FV_TEXT_HANDLE_MODE_SELECTION ++} FvTextHandleMode; ++ ++struct _FvTextHandle ++{ ++ GObject parent_instance; ++ gpointer priv; ++}; ++ ++struct _FvTextHandleClass ++{ ++ GObjectClass parent_class; ++ ++ void (* handle_dragged) (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ gint x, ++ gint y); ++ void (* drag_finished) (FvTextHandle *handle, ++ FvTextHandlePosition pos); ++}; ++ ++GType _fv_text_handle_get_type (void) G_GNUC_CONST; ++ ++FvTextHandle * _fv_text_handle_new (GtkWidget *parent); ++ ++void _fv_text_handle_set_mode (FvTextHandle *handle, ++ FvTextHandleMode mode); ++FvTextHandleMode ++ _fv_text_handle_get_mode (FvTextHandle *handle); ++void _fv_text_handle_set_position (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ GdkRectangle *rect); ++void _fv_text_handle_set_visible (FvTextHandle *handle, ++ FvTextHandlePosition pos, ++ gboolean visible); ++ ++void _fv_text_handle_set_relative_to (FvTextHandle *handle, ++ GdkWindow *window); ++ ++gboolean _fv_text_handle_get_is_dragged (FvTextHandle *handle, ++ FvTextHandlePosition pos); ++ ++G_END_DECLS ++ ++#endif /* __FV_TEXT_HANDLE_PRIVATE_H__ */ +diff --git a/src/text/fmt/xp/Makefile.am b/src/text/fmt/xp/Makefile.am +index c8d1b29..ddaf273 100644 +--- a/src/text/fmt/xp/Makefile.am ++++ b/src/text/fmt/xp/Makefile.am +@@ -104,6 +104,8 @@ libxp_la_SOURCES = \ + fv_InlineImage.h \ + fv_Selection.cpp \ + fv_Selection.h \ ++ fv_SelectionHandles.cpp \ ++ fv_SelectionHandles.h \ + fv_View_cmd.cpp \ + fv_View.cpp \ + fv_View.h \ +diff --git a/src/text/fmt/xp/fv_SelectionHandles.cpp b/src/text/fmt/xp/fv_SelectionHandles.cpp +new file mode 100644 +index 0000000..8c6cc4b +--- /dev/null ++++ b/src/text/fmt/xp/fv_SelectionHandles.cpp +@@ -0,0 +1,122 @@ ++/* AbiWord - base class for selection handles ++ * Copyright (c) 2012 One laptop per child ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ * ++ * Author: Carlos Garnacho <carlos@lanedo.com> ++ */ ++ ++#include "fv_View.h" ++#include "fv_SelectionHandles.h" ++#include "fp_Page.h" ++ ++FV_SelectionHandles::FV_SelectionHandles (FV_View * pView, FV_Selection pSelection) ++ : m_pView (pView), ++ m_pSelection (pSelection) ++{ ++} ++ ++bool FV_SelectionHandles::_getPositionCoords(PT_DocPosition pos, UT_sint32& x, UT_sint32& y, UT_uint32& height) ++{ ++ UT_sint32 x1, y1, x2, y2; ++ UT_uint32 h; ++ bool bPos, visible = true; ++ ++ m_pView->_findPositionCoords (pos,false, x1, y1, ++ x2, y2, h, ++ bPos, NULL, NULL); ++ ++ if (x1 < 0 || y1 < 0 || ++ x1 > m_pView->getWindowWidth() || ++ y1 > m_pView->getWindowHeight() - (UT_sint32) h) ++ visible = false; ++ ++ x = m_pView->getGraphics()->tdu(x1); ++ y = m_pView->getGraphics()->tdu(y1); ++ height = m_pView->getGraphics()->tdu(h); ++ ++ return visible; ++} ++ ++void FV_SelectionHandles::setCursor (PT_DocPosition cursor) ++{ ++ UT_sint32 x, y; ++ UT_uint32 height; ++ bool visible; ++ ++ visible = _getPositionCoords (cursor, x, y, height); ++ setCursorCoords(x, y, height, visible); ++} ++ ++void FV_SelectionHandles::setSelection (PT_DocPosition start, PT_DocPosition end) ++{ ++ UT_sint32 start_x, start_y, end_x, end_y; ++ UT_uint32 start_height, end_height; ++ bool start_visible, end_visible; ++ ++ start_visible = _getPositionCoords (start, start_x, start_y, start_height); ++ end_visible = _getPositionCoords (end, end_x, end_y, end_height); ++ setSelectionCoords(start_x, start_y, start_height, start_visible, ++ end_x, end_y, end_height, end_visible); ++} ++ ++void FV_SelectionHandles::updateSelectionStart(UT_sint32 x, UT_sint32 y) ++{ ++ PT_DocPosition pos, right; ++ fp_Page *page; ++ bool bBOL, bEOL, isTOC; ++ UT_sint32 xClick, yClick; ++ ++ x = m_pView->getGraphics()->tlu(x); ++ y = m_pView->getGraphics()->tlu(y); ++ page = m_pView->_getPageForXY(x, y, xClick, yClick); ++ page->mapXYToPosition(xClick, yClick, pos, bBOL, bEOL,isTOC, true, NULL); ++ right = m_pView->getSelectionRightAnchor(); ++ ++ pos = UT_MIN (pos, right - 1); ++ ++ m_pView->selectRange(pos, right); ++} ++ ++void FV_SelectionHandles::updateSelectionEnd(UT_sint32 x, UT_sint32 y) ++{ ++ PT_DocPosition pos, left; ++ fp_Page *page; ++ bool bBOL, bEOL, isTOC; ++ UT_sint32 xClick, yClick; ++ ++ x = m_pView->getGraphics()->tlu(x); ++ y = m_pView->getGraphics()->tlu(y); ++ page = m_pView->_getPageForXY(x, y, xClick, yClick); ++ page->mapXYToPosition(xClick, yClick, pos, bBOL, bEOL,isTOC, true, NULL); ++ left = m_pView->getSelectionLeftAnchor(); ++ ++ pos = UT_MAX (pos, left + 1); ++ ++ m_pView->selectRange(left, pos); ++ m_pView->_fixInsertionPointCoords(); ++ m_pView->ensureInsertionPointOnScreen(); ++} ++ ++void FV_SelectionHandles::updateCursor(UT_sint32 x, UT_sint32 y) ++{ ++ x = m_pView->getGraphics()->tlu(x); ++ y = m_pView->getGraphics()->tlu(y); ++ m_pView->warpInsPtToXY(x, y, false); ++} ++ ++FV_SelectionHandles::~FV_SelectionHandles() { ++} +diff --git a/src/text/fmt/xp/fv_SelectionHandles.h b/src/text/fmt/xp/fv_SelectionHandles.h +new file mode 100644 +index 0000000..d998f5e +--- /dev/null ++++ b/src/text/fmt/xp/fv_SelectionHandles.h +@@ -0,0 +1,56 @@ ++/* AbiWord - base class for selection handles ++ * Copyright (c) 2012 One laptop per child ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ * ++ * Author: Carlos Garnacho <carlos@lanedo.com> ++ */ ++ ++#ifndef FV_SELECTIONHANDLES_H ++#define FV_SELECTIONHANDLES_H ++ ++#include "pt_Types.h" ++#include "fv_Selection.h" ++ ++class FV_View; ++ ++class ABI_EXPORT FV_SelectionHandles ++{ ++public: ++ FV_SelectionHandles (FV_View * pView, FV_Selection selection); ++ virtual ~FV_SelectionHandles(); ++ ++ virtual void hide(void) {} ++ virtual void setCursorCoords(UT_sint32 /*x*/, UT_sint32 /*y*/, UT_uint32 /*height*/, bool /*visible*/) {} ++ virtual void setSelectionCoords(UT_sint32 /*start_x*/, UT_sint32 /*start_y*/, UT_uint32 /*start_height*/, bool /*start_visible*/, ++ UT_sint32 /*end_x*/, UT_sint32 /*end_y*/, UT_uint32 /*end_height*/, bool /*end_visible*/) {} ++ ++ void setCursor(PT_DocPosition cursor); ++ void setSelection(PT_DocPosition start, PT_DocPosition end); ++ ++ void updateSelectionStart(UT_sint32 x, UT_sint32 y); ++ void updateSelectionEnd(UT_sint32 x, UT_sint32 y); ++ void updateCursor(UT_sint32 x, UT_sint32 y); ++ ++protected: ++ FV_View * m_pView; ++ FV_Selection m_pSelection; ++ ++private: ++ bool _getPositionCoords(PT_DocPosition pos, UT_sint32& x, UT_sint32& y, UT_uint32& height); ++}; ++ ++#endif /* FV_SELECTIONHANDLES_H */ +diff --git a/src/text/fmt/xp/fv_View.cpp b/src/text/fmt/xp/fv_View.cpp +index cb5d904..5948ebe 100644 +--- a/src/text/fmt/xp/fv_View.cpp ++++ b/src/text/fmt/xp/fv_View.cpp +@@ -300,6 +300,7 @@ FV_View::FV_View(XAP_App * pApp, void* pParentData, FL_DocLayout* pLayout) + m_bAllowSmartQuoteReplacement(true), + m_bubbleBlockerCount(0), + m_iOldPageCount(-1), ++ m_SelectionHandles(this, m_Selection), + m_pViewDoubleBufferingObject(NULL) + { + if(m_pDoc) +@@ -945,7 +946,6 @@ void FV_View::replaceGraphics(GR_Graphics * pG) + m_pLayout->rebuildFromHere(static_cast<fl_DocSectionLayout *>(m_pLayout->getFirstSection())); + } + +- + //------------------------- + // Visual Drag stuff + // +@@ -2481,6 +2481,7 @@ void FV_View::focusChange(AV_Focus focus) + _setPoint(getPoint()); + } + m_pApp->rememberFocussedFrame(m_pParentData); ++ _updateSelectionHandles(); + break; + case AV_FOCUS_NEARBY: + if (isSelectionEmpty() && (getPoint() > 0)) +@@ -2497,6 +2498,7 @@ void FV_View::focusChange(AV_Focus focus) + } + break; + case AV_FOCUS_NONE: ++ m_SelectionHandles.hide(); + if (isSelectionEmpty() && (getPoint() > 0)) + { + m_pG->allCarets()->disable(true); +@@ -6996,6 +6998,13 @@ PT_DocPosition FV_View::getDocPositionFromXY(UT_sint32 xpos, UT_sint32 ypos, boo + return iNewPoint; + } + ++void FV_View::setVisualSelectionEnabled(bool bActive) ++{ ++ if (!bActive) ++ m_SelectionHandles.hide(); ++ m_VisualSelectionActive=bActive; ++} ++ + void FV_View::extSelToXY(UT_sint32 xPos, UT_sint32 yPos, bool bDrag) + { + // Figure out which page we clicked on. +@@ -7056,6 +7065,7 @@ void FV_View::extSelToXY(UT_sint32 xPos, UT_sint32 yPos, bool bDrag) + { + _extSelToPos(iNewPoint); + notifyListeners(AV_CHG_MOTION); ++ _updateSelectionHandles(); + } + } + +@@ -8098,6 +8108,7 @@ void FV_View::warpInsPtToXY(UT_sint32 xPos, UT_sint32 yPos, bool bClick = false) + _setPoint(pos, bEOL); + _ensureInsertionPointOnScreen(); + setCursorToContext(); ++ _updateSelectionHandles(); + notifyListeners(AV_CHG_MOTION | AV_CHG_HDRFTR ); // Sevior Put this in + // notifyListeners(AV_CHG_HDRFTR ); + +@@ -8309,6 +8320,7 @@ void FV_View::setXScrollOffset(UT_sint32 v) ///////////////////////TODO: Fix thi + _draw(x1-m_pG->tlu(1), 0, dx2+m_pG->tlu(2), getWindowHeight(), false, true); + + _fixInsertionPointCoords(); ++ _updateSelectionHandles(); + } + + void FV_View::setYScrollOffset(UT_sint32 v) +@@ -8323,6 +8335,7 @@ void FV_View::setYScrollOffset(UT_sint32 v) + m_yScrollOffset = v; + + _fixInsertionPointCoords(); ++ _updateSelectionHandles(); + } + + void FV_View::draw(int page, dg_DrawArgs* da) +@@ -14413,11 +14426,23 @@ bool FV_View::rtlPages() const + void + FV_View::selectRange( PT_DocPosition start, PT_DocPosition end ) + { +- _clearSelection(); ++ PT_DocPosition prev_start, prev_end; ++ ++ prev_start = m_Selection.getSelectionLeftAnchor(); ++ prev_end = m_Selection.getSelectionRightAnchor(); ++ ++ if (prev_start == start && prev_end == end) ++ return; ++ ++ _clearSelection(false); + _setPoint(start); ++ m_Selection.setSelectionLeftAnchor(start); + _setSelectionAnchor(); + setPoint(end); +- _drawSelection(); ++ m_Selection.setSelectionRightAnchor(end); ++ ++ _drawBetweenPositions(MIN (prev_start, start), MAX (prev_end, end)); ++ _updateSelectionHandles(); + } + + void +diff --git a/src/text/fmt/xp/fv_View.h b/src/text/fmt/xp/fv_View.h +index a361692..46d16ab 100644 +--- a/src/text/fmt/xp/fv_View.h ++++ b/src/text/fmt/xp/fv_View.h +@@ -47,8 +47,10 @@ + #include "fv_UnixVisualDrag.h" + #include "fv_UnixFrameEdit.h" + #include "fv_UnixInlineImage.h" ++#include "fv_UnixSelectionHandles.h" + #else + #include "fv_VisualDragText.h" ++#include "fv_SelectionHandles.h" + #endif + + #define AUTO_SCROLL_MSECS 100 +@@ -237,6 +239,7 @@ class ABI_EXPORT FV_View : public AV_View + friend class CellLine; + friend class FV_View_BubbleBlocker; + friend class FV_ViewDoubleBuffering; ++ friend class FV_SelectionHandles; + public: + FV_View(XAP_App*, void*, FL_DocLayout*); + virtual ~FV_View(); +@@ -266,12 +269,15 @@ public: + + virtual void draw(const UT_Rect* pRect=static_cast<UT_Rect*>(NULL)); + virtual void drawSelectionBox(UT_Rect & box, bool drawHandles); ++ ++ void setVisualSelectionEnabled(bool bActive); + private: + inline void _drawResizeHandle(UT_Rect & box); + void getCmdInsertRangeVariables( PT_DocPosition& posStart, + PT_DocPosition& posEnd, + fl_BlockLayout*& pBL1, + fl_BlockLayout*& pBL2 ); ++ void _updateSelectionHandles (void); + + + public: +@@ -945,7 +951,7 @@ protected: + const gchar ** extra_props = NULL); + void _moveToSelectionEnd(bool bForward); + void _eraseSelection(void); +- void _clearSelection(void); ++ void _clearSelection(bool bRedraw = true); + void _resetSelection(void); + void _setSelectionAnchor(void); + void _deleteSelection(PP_AttrProp *p_AttrProp_Before = NULL, +@@ -1163,6 +1169,12 @@ private: + int m_bubbleBlockerCount; + UT_sint32 m_iOldPageCount; + ++#ifdef TOOLKIT_GTK_ALL ++ FV_UnixSelectionHandles m_SelectionHandles; ++#else ++ FV_SelectionHandles m_SelectionHandles; ++#endif ++ + public: + bool registerDoubleBufferingObject(FV_ViewDoubleBuffering *obj); + bool unregisterDoubleBufferingObject(FV_ViewDoubleBuffering *obj); +diff --git a/src/text/fmt/xp/fv_View_cmd.cpp b/src/text/fmt/xp/fv_View_cmd.cpp +index b153dee..0851091 100644 +--- a/src/text/fmt/xp/fv_View_cmd.cpp ++++ b/src/text/fmt/xp/fv_View_cmd.cpp +@@ -4674,6 +4674,7 @@ void FV_View::cmdCut(void) + _ensureInsertionPointOnScreen(); + notifyListeners(AV_CHG_ALL); + ++ m_SelectionHandles.hide(); + } + + // bToClipboard is true if you want to copy to the CLIPBOARD +diff --git a/src/text/fmt/xp/fv_View_protected.cpp b/src/text/fmt/xp/fv_View_protected.cpp +index b5c1a85..df3234c 100644 +--- a/src/text/fmt/xp/fv_View_protected.cpp ++++ b/src/text/fmt/xp/fv_View_protected.cpp +@@ -174,7 +174,7 @@ void FV_View::_eraseSelection(void) + _clearBetweenPositions(iPos1, iPos2, true); + } + +-void FV_View::_clearSelection(void) ++void FV_View::_clearSelection(bool bRedraw) + { + if( isSelectionEmpty() ) + { +@@ -211,7 +211,8 @@ void FV_View::_clearSelection(void) + m_iLowDrawPoint = 0; + m_iHighDrawPoint = 0; + +- _drawBetweenPositions(iPos1, iPos2); ++ if (bRedraw) ++ _drawBetweenPositions(iPos1, iPos2); + } + else + { +@@ -235,7 +236,9 @@ void FV_View::_clearSelection(void) + { + iPos2++; + } +- /*bool bres =*/ _clearBetweenPositions(iPos1, iPos2, true); ++ ++ if (bRedraw) ++ /*bool bres =*/ _clearBetweenPositions(iPos1, iPos2, true); + } + } + _resetSelection(); +@@ -250,7 +253,8 @@ void FV_View::_clearSelection(void) + { + iPos2++; + } +- _drawBetweenPositions(iPos1, iPos2); ++ if (bRedraw) ++ _drawBetweenPositions(iPos1, iPos2); + } + } + UT_VECTOR_PURGEALL(PD_DocumentRange *,vecRanges); +@@ -6440,3 +6444,15 @@ void FV_View::_adjustDeletePosition(UT_uint32 &iDocPos, UT_uint32 &iCount) + // adjust point + iDocPos = pos1; + } ++ ++void FV_View::_updateSelectionHandles(void) ++{ ++ if (!getVisualSelectionEnabled()){ ++ m_SelectionHandles.hide(); ++ } else if (isSelectionEmpty()) { ++ m_SelectionHandles.setCursor(getInsPoint()); ++ } else { ++ m_SelectionHandles.setSelection(getSelectionLeftAnchor(), ++ getSelectionRightAnchor()); ++ } ++} +diff --git a/src/wp/ap/gtk/ap_UnixFrameImpl.cpp b/src/wp/ap/gtk/ap_UnixFrameImpl.cpp +index 385b104..b5266ac 100644 +--- a/src/wp/ap/gtk/ap_UnixFrameImpl.cpp ++++ b/src/wp/ap/gtk/ap_UnixFrameImpl.cpp +@@ -363,6 +363,11 @@ GtkWidget * AP_UnixFrameImpl::_createDocumentWindow() + return m_wSunkenBox; + } + ++GtkWidget * AP_UnixFrameImpl::getViewWidget(void) ++{ ++ return m_dArea; ++} ++ + void AP_UnixFrameImpl::_hideMenuScroll(bool bHideMenuScroll) + { + if(bHideMenuScroll) +diff --git a/src/wp/ap/gtk/ap_UnixFrameImpl.h b/src/wp/ap/gtk/ap_UnixFrameImpl.h +index 388d761..01b45f8 100644 +--- a/src/wp/ap/gtk/ap_UnixFrameImpl.h ++++ b/src/wp/ap/gtk/ap_UnixFrameImpl.h +@@ -48,6 +48,7 @@ class AP_UnixFrameImpl : public XAP_UnixFrameImpl + GtkWidget * getDrawingArea() const {return m_dArea;} + static gboolean ap_focus_in_event (GtkWidget * drawing_area, GdkEventCrossing *event, AP_UnixFrameImpl * me); + static gboolean ap_focus_out_event (GtkWidget * drawing_area, GdkEventCrossing *event, AP_UnixFrameImpl * me); ++ virtual GtkWidget * getViewWidget(void); + + protected: + friend class AP_UnixFrame; diff --git a/abiword.spec b/abiword.spec index fc5d04d..13867dc 100644 --- a/abiword.spec +++ b/abiword.spec @@ -5,7 +5,7 @@ Summary: The AbiWord word processor Name: abiword Version: %{majorversion}.%{minorversion}.%{microversion} -Release: 1.git20121011%{?dist}.olpc4 +Release: 1.git20121011%{?dist}.olpc5 Epoch: 1 Group: Applications/Editors License: GPLv2+ @@ -39,8 +39,7 @@ Patch5: memory-allocator-confusion.patch Patch6: abi-introspection.diff # OLPC patch to add touch text handles -Patch99: abiword-text-handles.diff -Patch100: handles2.diff +Patch99: abi-selection-handles.diff BuildRequires: autoconf, libtool BuildRequires: desktop-file-utils @@ -91,7 +90,6 @@ Includes and definitions for developing with libabiword. %patch6 -p1 %patch99 -p1 -%patch100 -p1 # setup abiword documentation %setup -q -T -b 1 -n abiword-docs-%{version} diff --git a/handles2.diff b/handles2.diff deleted file mode 100644 index 17839db..0000000 --- a/handles2.diff +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/src/af/ev/gtk/ev_UnixMouse.cpp b/src/af/ev/gtk/ev_UnixMouse.cpp
-index af3cb2a..2ca54ec 100644
---- a/src/af/ev/gtk/ev_UnixMouse.cpp
-+++ b/src/af/ev/gtk/ev_UnixMouse.cpp
-@@ -164,7 +164,7 @@ void EV_UnixMouse::mouseClick(AV_View* pView, GdkEventButton* e)
- invokeMouseMethod(pView,pEM,static_cast<UT_sint32>(pView->getGraphics()->tluD(e->x)),static_cast<UT_sint32>(pView->getGraphics()->tluD(e->y)));
- signal(emc|mop|emb|state, static_cast<UT_sint32>(pView->getGraphics()->tluD(e->x)),static_cast<UT_sint32>(pView->getGraphics()->tluD(e->y)));
-
-- if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN) {
-+ if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN || getenv ("ABI_TEST_TOUCH")) {
- pView->setVisualSelectionEnabled(true);
- } else {
- pView->setVisualSelectionEnabled(false);
-diff --git a/src/text/fmt/gtk/gtktexthandle.c b/src/text/fmt/gtk/gtktexthandle.c
-index 64a37ed..766eb8b 100644
---- a/src/text/fmt/gtk/gtktexthandle.c
-+++ b/src/text/fmt/gtk/gtktexthandle.c
-@@ -523,7 +523,7 @@ _fv_text_handle_set_relative_to (FvTextHandle *handle,
- priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_START].window =
- _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START);
- priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window =
-- _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_START);
-+ _fv_text_handle_create_window (handle, FV_TEXT_HANDLE_POSITION_SELECTION_END);
- priv->realized = TRUE;
- }
- else
-@@ -550,6 +550,12 @@ _fv_text_handle_set_mode (FvTextHandle *handle,
- if (priv->mode == mode)
- return;
-
-+ priv->mode = mode;
-+
-+ if (mode != FV_TEXT_HANDLE_MODE_NONE)
-+ _fv_text_handle_update_shape (handle,
-+ priv->windows[FV_TEXT_HANDLE_POSITION_CURSOR].window,
-+ FV_TEXT_HANDLE_POSITION_CURSOR);
- switch (mode)
- {
- case FV_TEXT_HANDLE_MODE_CURSOR:
-@@ -568,8 +574,6 @@ _fv_text_handle_set_mode (FvTextHandle *handle,
- gdk_window_hide (priv->windows[FV_TEXT_HANDLE_POSITION_SELECTION_END].window);
- break;
- }
--
-- priv->mode = mode;
- }
-
- FvTextHandleMode
-@@ -645,6 +649,9 @@ _fv_text_handle_set_visible (FvTextHandle *handle,
- if (!window)
- return;
-
-+ if (priv->windows[pos].dragged)
-+ return;
-+
- if (!visible)
- gdk_window_hide (window);
- else
-diff --git a/src/text/fmt/xp/fv_SelectionHandles.cpp b/src/text/fmt/xp/fv_SelectionHandles.cpp
-index c8d538b..8c6cc4b 100644
---- a/src/text/fmt/xp/fv_SelectionHandles.cpp
-+++ b/src/text/fmt/xp/fv_SelectionHandles.cpp
-@@ -107,6 +107,8 @@ void FV_SelectionHandles::updateSelectionEnd(UT_sint32 x, UT_sint32 y)
- pos = UT_MAX (pos, left + 1);
-
- m_pView->selectRange(left, pos);
-+ m_pView->_fixInsertionPointCoords();
-+ m_pView->ensureInsertionPointOnScreen();
- }
-
- void FV_SelectionHandles::updateCursor(UT_sint32 x, UT_sint32 y)
-diff --git a/src/text/fmt/xp/fv_View.cpp b/src/text/fmt/xp/fv_View.cpp
-index 9e78a85..5948ebe 100644
---- a/src/text/fmt/xp/fv_View.cpp
-+++ b/src/text/fmt/xp/fv_View.cpp
-@@ -14426,13 +14426,22 @@ bool FV_View::rtlPages() const
- void
- FV_View::selectRange( PT_DocPosition start, PT_DocPosition end )
- {
-+ PT_DocPosition prev_start, prev_end;
-+
-+ prev_start = m_Selection.getSelectionLeftAnchor();
-+ prev_end = m_Selection.getSelectionRightAnchor();
-+
-+ if (prev_start == start && prev_end == end)
-+ return;
-+
- _clearSelection(false);
- _setPoint(start);
- m_Selection.setSelectionLeftAnchor(start);
- _setSelectionAnchor();
- setPoint(end);
- m_Selection.setSelectionRightAnchor(end);
-- _drawSelection();
-+
-+ _drawBetweenPositions(MIN (prev_start, start), MAX (prev_end, end));
- _updateSelectionHandles();
- }
|