[Libreoffice-commits] core.git: Branch 'feature/tiled-editing' - 2 commits - include/LibreOfficeKit libreofficekit/source

Miklos Vajna vmiklos at collabora.co.uk
Tue Feb 10 05:17:17 PST 2015


 include/LibreOfficeKit/LibreOfficeKitGtk.h |   12 ++++
 libreofficekit/source/gtk/lokdocview.c     |   86 +++++++++++++++++++++++++----
 2 files changed, 87 insertions(+), 11 deletions(-)

New commits:
commit e6d466dcdf2174cb162c151af8f501d964c5ea21
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Feb 10 14:15:42 2015 +0100

    lokdocview: allow dragging the middle handle
    
    Change-Id: I83ef2797c17c8de8f8e9b5f3dcbe9adb34eb4313

diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h
index d3e663d..95288cd 100644
--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h
+++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h
@@ -60,6 +60,10 @@ struct _LOKDocView
     cairo_surface_t* m_pHandleStart;
     /// Bitmap of the text selection middle handle.
     cairo_surface_t* m_pHandleMiddle;
+    /// Rectangle of the text selection middle handle, to know if the user clicked on it or not
+    GdkRectangle m_aHandleMiddleRect;
+    /// If we are in the middle of a drag of the text selection middle handle.
+    gboolean m_bInDragMiddleHandle;
     /// Bitmap of the text selection end handle.
     cairo_surface_t* m_pHandleEnd;
 };
diff --git a/libreofficekit/source/gtk/lokdocview.c b/libreofficekit/source/gtk/lokdocview.c
index 44f0d87..0fa3e11 100644
--- a/libreofficekit/source/gtk/lokdocview.c
+++ b/libreofficekit/source/gtk/lokdocview.c
@@ -42,12 +42,59 @@ void lcl_onDestroy( LOKDocView* pDocView, gpointer pData )
     pDocView->pDocument = NULL;
 }
 
+gboolean lcl_signalMotion(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocView* pDocView)
+{
+    (void)pEventBox;
+    if (pDocView->m_bInDragMiddleHandle)
+    {
+        // The user drags the handle, which is below the cursor, but wants to move the cursor accordingly.
+        GdkPoint aCursor, aHandle, aPoint;
+
+        g_info("lcl_signalMotion: dragging the middle handle");
+        // Center of the cursor rectangle: we know that it's above the handle.
+        aCursor.x = pDocView->m_aHandleMiddleRect.x + pDocView->m_aHandleMiddleRect.width / 2;
+        aCursor.y = pDocView->m_aHandleMiddleRect.y - pDocView->m_aHandleMiddleRect.height / 2;
+        // Center of the handle rectangle.
+        aHandle.x = pDocView->m_aHandleMiddleRect.x + pDocView->m_aHandleMiddleRect.width / 2;
+        aHandle.y = pDocView->m_aHandleMiddleRect.y + pDocView->m_aHandleMiddleRect.height / 2;
+        // Our target is the original cursor position + the dragged offset.
+        aPoint.x = aCursor.x + (pEvent->x - aHandle.x);
+        aPoint.y = aCursor.y + (pEvent->y - aHandle.y);
+
+        pDocView->pDocument->pClass->postMouseEvent(pDocView->pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, pixelToTwip(aPoint.x), pixelToTwip(aPoint.y), 1);
+        pDocView->pDocument->pClass->postMouseEvent(pDocView->pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, pixelToTwip(aPoint.x), pixelToTwip(aPoint.y), 1);
+    }
+    return FALSE;
+}
+
 /// Receives a button press event.
-void lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocView* pDocView)
+gboolean lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocView* pDocView)
 {
     g_info("lcl_signalButton: %d, %d (in twips: %d, %d)", (int)pEvent->x, (int)pEvent->y, (int)pixelToTwip(pEvent->x), (int)pixelToTwip(pEvent->y));
     (void) pEventBox;
 
+    if (pDocView->m_bInDragMiddleHandle && pEvent->type == GDK_BUTTON_RELEASE)
+    {
+        g_info("lcl_signalButton: end of drag middle handle");
+        pDocView->m_bInDragMiddleHandle = FALSE;
+        return FALSE;
+    }
+
+    if (pDocView->m_bEdit)
+    {
+        GdkRectangle aClick;
+        aClick.x = pEvent->x;
+        aClick.y = pEvent->y;
+        aClick.width = 1;
+        aClick.height = 1;
+        if (gdk_rectangle_intersect(&aClick, &pDocView->m_aHandleMiddleRect, NULL) && pEvent->type == GDK_BUTTON_PRESS)
+        {
+            g_info("lcl_signalButton: start of drag middle handle");
+            pDocView->m_bInDragMiddleHandle = TRUE;
+            return FALSE;
+        }
+    }
+
     lok_docview_set_edit(pDocView, TRUE);
 
     switch (pEvent->type)
@@ -73,6 +120,7 @@ void lcl_signalButton(GtkWidget* pEventBox, GdkEventButton* pEvent, LOKDocView*
     default:
         break;
     }
+    return FALSE;
 }
 
 SAL_DLLPUBLIC_EXPORT guint lok_docview_get_type()
@@ -115,8 +163,10 @@ static void lok_docview_init( LOKDocView* pDocView )
     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(pDocView),
                                            pDocView->pEventBox );
 
+    gtk_widget_set_events(pDocView->pEventBox, GDK_BUTTON_PRESS_MASK); // So that drag doesn't try to move the whole window.
     gtk_signal_connect(GTK_OBJECT(pDocView->pEventBox), "button-press-event", GTK_SIGNAL_FUNC(lcl_signalButton), pDocView);
     gtk_signal_connect(GTK_OBJECT(pDocView->pEventBox), "button-release-event", GTK_SIGNAL_FUNC(lcl_signalButton), pDocView);
+    gtk_signal_connect(GTK_OBJECT(pDocView->pEventBox), "motion-notify-event", GTK_SIGNAL_FUNC(lcl_signalMotion), pDocView);
 
     gtk_widget_show( pDocView->pEventBox );
 
@@ -139,6 +189,8 @@ static void lok_docview_init( LOKDocView* pDocView )
     pDocView->m_pHandleStart = NULL;
     pDocView->m_pHandleMiddle = NULL;
     pDocView->m_pHandleEnd = NULL;
+    memset(&pDocView->m_aHandleMiddleRect, 0, sizeof(pDocView->m_aHandleMiddleRect));
+    pDocView->m_bInDragMiddleHandle = FALSE;
 
     gtk_signal_connect( GTK_OBJECT(pDocView), "destroy",
                         GTK_SIGNAL_FUNC(lcl_onDestroy), NULL );
@@ -191,7 +243,7 @@ static gboolean lcl_handleTimeout(gpointer pData)
 }
 
 /// Renders pHandle below a pCursor rectangle on pCairo.
-static void lcl_renderHandle(cairo_t* pCairo, GdkRectangle* pCursor, cairo_surface_t* pHandle)
+static void lcl_renderHandle(cairo_t* pCairo, GdkRectangle* pCursor, cairo_surface_t* pHandle, GdkRectangle* pRectangle)
 {
     GdkPoint aCursorBottom;
     int nHandleWidth, nHandleHeight;
@@ -210,6 +262,15 @@ static void lcl_renderHandle(cairo_t* pCairo, GdkRectangle* pCursor, cairo_surfa
     cairo_set_source_surface(pCairo, pHandle, 0, 0);
     cairo_paint(pCairo);
     cairo_restore(pCairo);
+
+    if (pRectangle)
+    {
+        // Return the rectangle that contains the rendered handle.
+        pRectangle->x = aCursorBottom.x;
+        pRectangle->y = aCursorBottom.y;
+        pRectangle->width = nHandleWidth * fHandleScale;
+        pRectangle->height = nHandleHeight * fHandleScale;
+    }
 }
 
 static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpointer pData)
@@ -242,7 +303,7 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpoint
         // Have a cursor, but no selection: we need the middle handle.
         if (!pDocView->m_pHandleMiddle)
             pDocView->m_pHandleMiddle = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_middle.png");
-        lcl_renderHandle(pCairo, &pDocView->m_aVisibleCursor, pDocView->m_pHandleMiddle);
+        lcl_renderHandle(pCairo, &pDocView->m_aVisibleCursor, pDocView->m_pHandleMiddle, &pDocView->m_aHandleMiddleRect);
     }
 
     if (pDocView->m_pTextSelectionRectangles)
@@ -264,14 +325,14 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpoint
             // Have a start position: we need a start handle.
             if (!pDocView->m_pHandleStart)
                 pDocView->m_pHandleStart = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_start.png");
-            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionStart, pDocView->m_pHandleStart);
+            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionStart, pDocView->m_pHandleStart, NULL);
         }
         if (!lcl_isEmptyRectangle(&pDocView->m_aTextSelectionEnd))
         {
             // Have a start position: we need an end handle.
             if (!pDocView->m_pHandleEnd)
                 pDocView->m_pHandleEnd = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_end.png");
-            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionEnd, pDocView->m_pHandleEnd);
+            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionEnd, pDocView->m_pHandleEnd, NULL);
         }
     }
 
commit ec2ecd82ef128c2ab24530cb4242eab2f1f99019
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Feb 10 11:41:59 2015 +0100

    lokdocview: avoid loading the handle bitmaps again and again
    
    Change-Id: I767a1c0ddce4e06d421b6bb951aa6d0451943f89

diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h
index 04d61ad..d3e663d 100644
--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h
+++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h
@@ -52,8 +52,16 @@ struct _LOKDocView
     guint32 m_nLastButtonReleaseTime;
     /// Rectangles of the current text selection.
     GList* m_pTextSelectionRectangles;
+    /// Position and size of the selection start (as if there would be a cursor caret there).
     GdkRectangle m_aTextSelectionStart;
+    /// Position and size of the selection end.
     GdkRectangle m_aTextSelectionEnd;
+    /// Bitmap of the text selection start handle.
+    cairo_surface_t* m_pHandleStart;
+    /// Bitmap of the text selection middle handle.
+    cairo_surface_t* m_pHandleMiddle;
+    /// Bitmap of the text selection end handle.
+    cairo_surface_t* m_pHandleEnd;
 };
 
 struct _LOKDocViewClass
diff --git a/libreofficekit/source/gtk/lokdocview.c b/libreofficekit/source/gtk/lokdocview.c
index 89feeca..44f0d87 100644
--- a/libreofficekit/source/gtk/lokdocview.c
+++ b/libreofficekit/source/gtk/lokdocview.c
@@ -136,6 +136,9 @@ static void lok_docview_init( LOKDocView* pDocView )
     pDocView->m_pTextSelectionRectangles = NULL;
     memset(&pDocView->m_aTextSelectionStart, 0, sizeof(pDocView->m_aTextSelectionStart));
     memset(&pDocView->m_aTextSelectionEnd, 0, sizeof(pDocView->m_aTextSelectionEnd));
+    pDocView->m_pHandleStart = NULL;
+    pDocView->m_pHandleMiddle = NULL;
+    pDocView->m_pHandleEnd = NULL;
 
     gtk_signal_connect( GTK_OBJECT(pDocView), "destroy",
                         GTK_SIGNAL_FUNC(lcl_onDestroy), NULL );
@@ -237,9 +240,9 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpoint
     if (!lcl_isEmptyRectangle(&pDocView->m_aVisibleCursor) && !pDocView->m_pTextSelectionRectangles)
     {
         // Have a cursor, but no selection: we need the middle handle.
-        cairo_surface_t* pHandle = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_middle.png");
-        lcl_renderHandle(pCairo, &pDocView->m_aVisibleCursor, pHandle);
-        cairo_surface_destroy(pHandle);
+        if (!pDocView->m_pHandleMiddle)
+            pDocView->m_pHandleMiddle = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_middle.png");
+        lcl_renderHandle(pCairo, &pDocView->m_aVisibleCursor, pDocView->m_pHandleMiddle);
     }
 
     if (pDocView->m_pTextSelectionRectangles)
@@ -259,16 +262,16 @@ static gboolean renderOverlay(GtkWidget* pWidget, GdkEventExpose* pEvent, gpoint
         if (!lcl_isEmptyRectangle(&pDocView->m_aTextSelectionStart))
         {
             // Have a start position: we need a start handle.
-            cairo_surface_t* pHandle = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_start.png");
-            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionStart, pHandle);
-            cairo_surface_destroy(pHandle);
+            if (!pDocView->m_pHandleStart)
+                pDocView->m_pHandleStart = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_start.png");
+            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionStart, pDocView->m_pHandleStart);
         }
         if (!lcl_isEmptyRectangle(&pDocView->m_aTextSelectionEnd))
         {
             // Have a start position: we need an end handle.
-            cairo_surface_t* pHandle = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_end.png");
-            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionEnd, pHandle);
-            cairo_surface_destroy(pHandle);
+            if (!pDocView->m_pHandleEnd)
+                pDocView->m_pHandleEnd = cairo_image_surface_create_from_png(CURSOR_HANDLE_DIR "handle_end.png");
+            lcl_renderHandle(pCairo, &pDocView->m_aTextSelectionEnd, pDocView->m_pHandleEnd);
         }
     }
 


More information about the Libreoffice-commits mailing list