Blame SOURCES/0367-tdf-96316-Decouple-view-only-editable-modes.patch

f325b2
From 74730e13d8ebee67a1c235ef203a9b56a8097593 Mon Sep 17 00:00:00 2001
f325b2
From: Pranav Kant <pranavk@libreoffice.org>
f325b2
Date: Wed, 9 Dec 2015 01:03:02 +0530
f325b2
Subject: [PATCH 367/398] tdf#96316: Decouple view-only/editable modes
f325b2
f325b2
- Move text selection and graphic selection tasks into functions
f325b2
- Merge GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE conditional code
f325b2
- Do not change to 'move' cursor in view-only mode
f325b2
- Ignore LOK_POST_COMMAND, LOK_SET_GRAPHIC_SELECTION in view-only
f325b2
f325b2
As a consequence this commit also allows dragging handles during text
f325b2
selection in view-only mode which was earlier not possible.
f325b2
f325b2
Change-Id: Iffb668d5447dd646a1e40237dee8d8d3fa3314b6
f325b2
Reviewed-on: https://gerrit.libreoffice.org/20487
f325b2
Reviewed-by: David Tardon <dtardon@redhat.com>
f325b2
Tested-by: David Tardon <dtardon@redhat.com>
f325b2
(cherry picked from commit b3bfc26d0863b074bb990725718f2ab23d05425d)
f325b2
(cherry picked from commit 0a28049853ce84aa8ef4f871065970c1220ae855)
f325b2
---
f325b2
 libreofficekit/source/gtk/lokdocview.cxx | 312 ++++++++++++++++++-------------
f325b2
 1 file changed, 180 insertions(+), 132 deletions(-)
f325b2
f325b2
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
f325b2
index 464348d95f1c..5e985d4a8c2f 100644
f325b2
--- a/libreofficekit/source/gtk/lokdocview.cxx
f325b2
+++ b/libreofficekit/source/gtk/lokdocview.cxx
f325b2
@@ -312,6 +312,153 @@ isEmptyRectangle(const GdkRectangle& rRectangle)
f325b2
     return rRectangle.x == 0 && rRectangle.y == 0 && rRectangle.width == 0 && rRectangle.height == 0;
f325b2
 }
f325b2
 
f325b2
+/// if handled, returns TRUE else FALSE
f325b2
+static bool
f325b2
+handleTextSelectionOnButtonPress(GdkRectangle& aClick, LOKDocView* pDocView) {
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
+
f325b2
+    if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleStartRect, nullptr))
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: start of drag start handle");
f325b2
+        priv->m_bInDragStartHandle = true;
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+    else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleMiddleRect, nullptr))
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: start of drag middle handle");
f325b2
+        priv->m_bInDragMiddleHandle = true;
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+    else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleEndRect, nullptr))
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: start of drag end handle");
f325b2
+        priv->m_bInDragEndHandle = true;
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+
f325b2
+    return FALSE;
f325b2
+}
f325b2
+
f325b2
+/// if handled, returns TRUE else FALSE
f325b2
+static bool
f325b2
+handleGraphicSelectionOnButtonPress(GdkRectangle& aClick, LOKDocView* pDocView) {
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
+    GError* error = nullptr;
f325b2
+
f325b2
+    for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
f325b2
+    {
f325b2
+        if (gdk_rectangle_intersect(&aClick, &priv->m_aGraphicHandleRects[i], nullptr))
f325b2
+        {
f325b2
+            g_info("LOKDocView_Impl::signalButton: start of drag graphic handle #%d", i);
f325b2
+            priv->m_bInDragGraphicHandles[i] = true;
f325b2
+
f325b2
+            GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
+            LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION);
f325b2
+            pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_START;
f325b2
+            pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(priv->m_aGraphicHandleRects[i].x + priv->m_aGraphicHandleRects[i].width / 2, priv->m_fZoom);
f325b2
+            pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(priv->m_aGraphicHandleRects[i].y + priv->m_aGraphicHandleRects[i].height / 2, priv->m_fZoom);
f325b2
+            g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
+
f325b2
+            g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
+            if (error != nullptr)
f325b2
+            {
f325b2
+                g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
f325b2
+                g_clear_error(&error);
f325b2
+            }
f325b2
+            g_object_unref(task);
f325b2
+
f325b2
+            return TRUE;
f325b2
+        }
f325b2
+    }
f325b2
+
f325b2
+    return FALSE;
f325b2
+}
f325b2
+
f325b2
+/// if handled, returns TRUE else FALSE
f325b2
+static bool
f325b2
+handleTextSelectionOnButtonRelease(LOKDocView* pDocView) {
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
+
f325b2
+    if (priv->m_bInDragStartHandle)
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: end of drag start handle");
f325b2
+        priv->m_bInDragStartHandle = false;
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+    else if (priv->m_bInDragMiddleHandle)
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: end of drag middle handle");
f325b2
+        priv->m_bInDragMiddleHandle = false;
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+    else if (priv->m_bInDragEndHandle)
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: end of drag end handle");
f325b2
+        priv->m_bInDragEndHandle = false;
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+
f325b2
+    return FALSE;
f325b2
+}
f325b2
+
f325b2
+/// if handled, returns TRUE else FALSE
f325b2
+static bool
f325b2
+handleGraphicSelectionOnButtonRelease(LOKDocView* pDocView, GdkEventButton* pEvent) {
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
+    GError* error = nullptr;
f325b2
+
f325b2
+    for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
f325b2
+    {
f325b2
+        if (priv->m_bInDragGraphicHandles[i])
f325b2
+        {
f325b2
+            g_info("LOKDocView_Impl::signalButton: end of drag graphic handle #%d", i);
f325b2
+            priv->m_bInDragGraphicHandles[i] = false;
f325b2
+
f325b2
+            GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
+            LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION);
f325b2
+            pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_END;
f325b2
+            pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom);
f325b2
+            pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom);
f325b2
+            g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
+
f325b2
+            g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
+            if (error != nullptr)
f325b2
+            {
f325b2
+                g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
f325b2
+                g_clear_error(&error);
f325b2
+            }
f325b2
+            g_object_unref(task);
f325b2
+
f325b2
+            return TRUE;
f325b2
+        }
f325b2
+    }
f325b2
+
f325b2
+    if (priv->m_bInDragGraphicSelection)
f325b2
+    {
f325b2
+        g_info("LOKDocView_Impl::signalButton: end of drag graphic selection");
f325b2
+        priv->m_bInDragGraphicSelection = false;
f325b2
+
f325b2
+        GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
+        LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION);
f325b2
+        pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_END;
f325b2
+        pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom);
f325b2
+        pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom);
f325b2
+        g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
+
f325b2
+        g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
+        if (error != nullptr)
f325b2
+        {
f325b2
+            g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
f325b2
+            g_clear_error(&error);
f325b2
+        }
f325b2
+        g_object_unref(task);
f325b2
+
f325b2
+        return TRUE;
f325b2
+    }
f325b2
+
f325b2
+    return FALSE;
f325b2
+}
f325b2
+
f325b2
 static void
f325b2
 postKeyEventInThread(gpointer data)
f325b2
 {
f325b2
@@ -747,11 +894,17 @@ callback (gpointer pData)
f325b2
     break;
f325b2
     case LOK_CALLBACK_MOUSE_POINTER:
f325b2
     {
f325b2
-        // The gtk docs claim that most css cursors should be supported, however
f325b2
-        // on my system at least this is not true and many cursors are unsupported.
f325b2
-        // In this case pCursor = null, which results in the default cursor being set.
f325b2
-        GdkCursor* pCursor = gdk_cursor_new_from_name(gtk_widget_get_display(GTK_WIDGET(pDocView)), pCallback->m_aPayload.c_str());
f325b2
-        gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(pDocView)), pCursor);
f325b2
+        // We do not want the cursor to get changed in view-only mode
f325b2
+        if (priv->m_bEdit)
f325b2
+        {
f325b2
+            // The gtk docs claim that most css cursors should be supported, however
f325b2
+            // on my system at least this is not true and many cursors are unsupported.
f325b2
+            // In this case pCursor = null, which results in the default cursor
f325b2
+            // being set.
f325b2
+            GdkCursor* pCursor = gdk_cursor_new_from_name(gtk_widget_get_display(GTK_WIDGET(pDocView)),
f325b2
+                                                          pCallback->m_aPayload.c_str());
f325b2
+            gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(pDocView)), pCursor);
f325b2
+        }
f325b2
     }
f325b2
     break;
f325b2
     case LOK_CALLBACK_GRAPHIC_SELECTION:
f325b2
@@ -1176,140 +1329,21 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent)
f325b2
            (int)pixelToTwip(pEvent->y, priv->m_fZoom));
f325b2
     gtk_widget_grab_focus(GTK_WIDGET(pDocView));
f325b2
 
f325b2
-    if (pEvent->type == GDK_BUTTON_RELEASE)
f325b2
+    switch (pEvent->type)
f325b2
     {
f325b2
-        if (priv->m_bInDragStartHandle)
f325b2
-        {
f325b2
-            g_info("LOKDocView_Impl::signalButton: end of drag start handle");
f325b2
-            priv->m_bInDragStartHandle = false;
f325b2
-            return FALSE;
f325b2
-        }
f325b2
-        else if (priv->m_bInDragMiddleHandle)
f325b2
-        {
f325b2
-            g_info("LOKDocView_Impl::signalButton: end of drag middle handle");
f325b2
-            priv->m_bInDragMiddleHandle = false;
f325b2
-            return FALSE;
f325b2
-        }
f325b2
-        else if (priv->m_bInDragEndHandle)
f325b2
-        {
f325b2
-            g_info("LOKDocView_Impl::signalButton: end of drag end handle");
f325b2
-            priv->m_bInDragEndHandle = false;
f325b2
-            return FALSE;
f325b2
-        }
f325b2
-
f325b2
-        for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
f325b2
-        {
f325b2
-            if (priv->m_bInDragGraphicHandles[i])
f325b2
-            {
f325b2
-                g_info("LOKDocView_Impl::signalButton: end of drag graphic handle #%d", i);
f325b2
-                priv->m_bInDragGraphicHandles[i] = false;
f325b2
-
f325b2
-                GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
-                LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION);
f325b2
-                pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_END;
f325b2
-                pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom);
f325b2
-                pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom);
f325b2
-                g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
-
f325b2
-                g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
-                if (error != nullptr)
f325b2
-                {
f325b2
-                    g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
f325b2
-                    g_clear_error(&error);
f325b2
-                }
f325b2
-                g_object_unref(task);
f325b2
-
f325b2
-                return FALSE;
f325b2
-            }
f325b2
-        }
f325b2
-
f325b2
-        if (priv->m_bInDragGraphicSelection)
f325b2
-        {
f325b2
-            g_info("LOKDocView_Impl::signalButton: end of drag graphic selection");
f325b2
-            priv->m_bInDragGraphicSelection = false;
f325b2
-
f325b2
-            GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
-            LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION);
f325b2
-            pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_END;
f325b2
-            pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom);
f325b2
-            pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom);
f325b2
-            g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
-
f325b2
-            g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
-            if (error != nullptr)
f325b2
-            {
f325b2
-                g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
f325b2
-                g_clear_error(&error);
f325b2
-            }
f325b2
-            g_object_unref(task);
f325b2
-
f325b2
-            return FALSE;
f325b2
-        }
f325b2
-    }
f325b2
-
f325b2
-    if (priv->m_bEdit)
f325b2
+    case GDK_BUTTON_PRESS:
f325b2
     {
f325b2
         GdkRectangle aClick;
f325b2
         aClick.x = pEvent->x;
f325b2
         aClick.y = pEvent->y;
f325b2
         aClick.width = 1;
f325b2
         aClick.height = 1;
f325b2
-        if (pEvent->type == GDK_BUTTON_PRESS)
f325b2
-        {
f325b2
-            if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleStartRect, nullptr))
f325b2
-            {
f325b2
-                g_info("LOKDocView_Impl::signalButton: start of drag start handle");
f325b2
-                priv->m_bInDragStartHandle = true;
f325b2
-                return FALSE;
f325b2
-            }
f325b2
-            else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleMiddleRect, nullptr))
f325b2
-            {
f325b2
-                g_info("LOKDocView_Impl::signalButton: start of drag middle handle");
f325b2
-                priv->m_bInDragMiddleHandle = true;
f325b2
-                return FALSE;
f325b2
-            }
f325b2
-            else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleEndRect, nullptr))
f325b2
-            {
f325b2
-                g_info("LOKDocView_Impl::signalButton: start of drag end handle");
f325b2
-                priv->m_bInDragEndHandle = true;
f325b2
-                return FALSE;
f325b2
-            }
f325b2
 
f325b2
-            for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
f325b2
-            {
f325b2
-                if (gdk_rectangle_intersect(&aClick, &priv->m_aGraphicHandleRects[i], nullptr))
f325b2
-                {
f325b2
-                    g_info("LOKDocView_Impl::signalButton: start of drag graphic handle #%d", i);
f325b2
-                    priv->m_bInDragGraphicHandles[i] = true;
f325b2
-
f325b2
-                    GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
-                    LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION);
f325b2
-                    pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_START;
f325b2
-                    pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(priv->m_aGraphicHandleRects[i].x + priv->m_aGraphicHandleRects[i].width / 2, priv->m_fZoom);
f325b2
-                    pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(priv->m_aGraphicHandleRects[i].y + priv->m_aGraphicHandleRects[i].height / 2, priv->m_fZoom);
f325b2
-                    g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
-
f325b2
-                    g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
-                    if (error != nullptr)
f325b2
-                    {
f325b2
-                        g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
f325b2
-                        g_clear_error(&error);
f325b2
-                    }
f325b2
-                    g_object_unref(task);
f325b2
-
f325b2
-                    return FALSE;
f325b2
-                }
f325b2
-            }
f325b2
-        }
f325b2
-    }
f325b2
-
f325b2
-    if (!priv->m_bEdit)
f325b2
-        lok_doc_view_set_edit(pDocView, TRUE);
f325b2
+        if (handleTextSelectionOnButtonPress(aClick, pDocView))
f325b2
+            return FALSE;
f325b2
+        if (handleGraphicSelectionOnButtonPress(aClick, pDocView))
f325b2
+            return FALSE;
f325b2
 
f325b2
-    switch (pEvent->type)
f325b2
-    {
f325b2
-    case GDK_BUTTON_PRESS:
f325b2
-    {
f325b2
         int nCount = 1;
f325b2
         if ((pEvent->time - priv->m_nLastButtonPressTime) < 250)
f325b2
             nCount++;
f325b2
@@ -1347,6 +1381,11 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent)
f325b2
     }
f325b2
     case GDK_BUTTON_RELEASE:
f325b2
     {
f325b2
+        if (handleTextSelectionOnButtonRelease(pDocView))
f325b2
+            return FALSE;
f325b2
+        if (handleGraphicSelectionOnButtonRelease(pDocView, pEvent))
f325b2
+            return FALSE;
f325b2
+
f325b2
         int nCount = 1;
f325b2
         if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250)
f325b2
             nCount++;
f325b2
@@ -1720,6 +1759,8 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
f325b2
 {
f325b2
     GTask* task = G_TASK(data);
f325b2
     LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task));
f325b2
+    LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
 
f325b2
     switch (pLOEvent->m_nType)
f325b2
     {
f325b2
@@ -1727,7 +1768,10 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
f325b2
         openDocumentInThread(task);
f325b2
         break;
f325b2
     case LOK_POST_COMMAND:
f325b2
-        postCommandInThread(task);
f325b2
+        if (priv->m_bEdit)
f325b2
+            postCommandInThread(task);
f325b2
+        else
f325b2
+            g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode");
f325b2
         break;
f325b2
     case LOK_SET_EDIT:
f325b2
         setEditInThread(task);
f325b2
@@ -1739,6 +1783,7 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
f325b2
         setPartmodeInThread(task);
f325b2
         break;
f325b2
     case LOK_POST_KEY:
f325b2
+        // view-only/editable mode already checked during signal key signal emission
f325b2
         postKeyEventInThread(task);
f325b2
         break;
f325b2
     case LOK_PAINT_TILE:
f325b2
@@ -1748,7 +1793,10 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
f325b2
         postMouseEventInThread(task);
f325b2
         break;
f325b2
     case LOK_SET_GRAPHIC_SELECTION:
f325b2
-        setGraphicSelectionInThread(task);
f325b2
+        if (priv->m_bEdit)
f325b2
+            setGraphicSelectionInThread(task);
f325b2
+        else
f325b2
+            g_info ("LOK_SET_GRAPHIC_SELECTION: skipping graphical operation in view-only mode");
f325b2
         break;
f325b2
     case LOK_SET_CLIENT_ZOOM:
f325b2
         setClientZoomInThread(task);
f325b2
-- 
f325b2
2.12.0
f325b2