include/LibreOfficeKit/LibreOfficeKitGtk.h | 15 libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx | 66 +- libreofficekit/source/gtk/lokdocview.cxx | 533 ++++++++++++++++---- libreofficekit/source/gtk/tilebuffer.cxx | 65 +- libreofficekit/source/gtk/tilebuffer.hxx | 91 +++ 5 files changed, 626 insertions(+), 144 deletions(-)
New commits: commit 2d2b392dcda5bdfab61a358dc1dd725d65fba07f Author: Pranav Kant <pran...@gnome.org> Date: Mon Jul 27 22:13:39 2015 +0530 lokdocview: post_command arguments are not supposed to be const Change-Id: Ibc22d03d9eee9fd151ecf5773e36c2519141a5eb diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index a548261..7ce2764 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -1947,7 +1947,7 @@ lok_doc_view_post_command (LOKDocView* pDocView, GTask* task = g_task_new(pDocView, NULL, NULL, NULL); LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND); pLOEvent->m_pCommand = pCommand; - pLOEvent->m_pArguments = pArguments; + pLOEvent->m_pArguments = g_strdup(pArguments); g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index d2451b6..dabf72f 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -158,7 +158,7 @@ struct LOEvent /// @name post_command parameters ///@{ const gchar* m_pCommand; - const gchar* m_pArguments; + gchar* m_pArguments; ///@} /// @name open_document parameter commit 7c45a57081a921b8f56812dd37c2fcd4b86d2a1a Author: Pranav Kant <pran...@gnome.org> Date: Sun Jul 26 22:39:43 2015 +0530 lokdocview: setGraphicSelection in another thread Change-Id: Ib7a6bf63ee6f300c6c5d50d02a3465d0a075a5be diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 4745a82..a548261 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -889,7 +889,17 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) { g_info("LOKDocView_Impl::signalButton: end of drag graphic handle #%d", i); priv->m_bInDragGraphicHandles[i] = false; - priv->m_pDocument->pClass->setGraphicSelection(priv->m_pDocument, LOK_SETGRAPHICSELECTION_END, pixelToTwip(pEvent->x, priv->m_fZoom), pixelToTwip(pEvent->y, priv->m_fZoom)); + + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION); + pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_END; + pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom); + pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom); + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); + return FALSE; } } @@ -898,7 +908,17 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) { g_info("LOKDocView_Impl::signalButton: end of drag graphic selection"); priv->m_bInDragGraphicSelection = false; - priv->m_pDocument->pClass->setGraphicSelection(priv->m_pDocument, LOK_SETGRAPHICSELECTION_END, pixelToTwip(pEvent->x, priv->m_fZoom), pixelToTwip(pEvent->y, priv->m_fZoom)); + + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION); + pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_END; + pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom); + pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom); + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); + return FALSE; } } @@ -937,10 +957,17 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) { g_info("LOKDocView_Impl::signalButton: start of drag graphic handle #%d", i); priv->m_bInDragGraphicHandles[i] = true; - priv->m_pDocument->pClass->setGraphicSelection(priv->m_pDocument, - LOK_SETGRAPHICSELECTION_START, - pixelToTwip(priv->m_aGraphicHandleRects[i].x + priv->m_aGraphicHandleRects[i].width / 2, priv->m_fZoom), - pixelToTwip(priv->m_aGraphicHandleRects[i].y + priv->m_aGraphicHandleRects[i].height / 2, priv->m_fZoom)); + + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION); + pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_START; + pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(priv->m_aGraphicHandleRects[i].x + priv->m_aGraphicHandleRects[i].width / 2, priv->m_fZoom); + pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(priv->m_aGraphicHandleRects[i].y + priv->m_aGraphicHandleRects[i].height / 2, priv->m_fZoom); + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); + return FALSE; } } @@ -1063,7 +1090,17 @@ lok_doc_view_signal_motion (GtkWidget* pWidget, GdkEventMotion* pEvent) { g_info("lcl_signalMotion: start of drag graphic selection"); priv->m_bInDragGraphicSelection = true; - priv->m_pDocument->pClass->setGraphicSelection(priv->m_pDocument, LOK_SETGRAPHICSELECTION_START, pixelToTwip(pEvent->x, priv->m_fZoom), pixelToTwip(pEvent->y, priv->m_fZoom)); + + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_GRAPHIC_SELECTION); + pLOEvent->m_nSetGraphicSelectionType = LOK_SETGRAPHICSELECTION_START; + pLOEvent->m_nSetGraphicSelectionX = pixelToTwip(pEvent->x, priv->m_fZoom); + pLOEvent->m_nSetGraphicSelectionY = pixelToTwip(pEvent->y, priv->m_fZoom); + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); + return FALSE; } @@ -1084,6 +1121,20 @@ lok_doc_view_signal_motion (GtkWidget* pWidget, GdkEventMotion* pEvent) } static void +setGraphicSelectionInThread(gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + + priv->m_pDocument->pClass->setGraphicSelection(priv->m_pDocument, + pLOEvent->m_nSetGraphicSelectionType, + pLOEvent->m_nSetGraphicSelectionX, + pLOEvent->m_nSetGraphicSelectionY); +} + +static void postMouseEventInThread(gpointer data) { GTask* task = G_TASK(data); @@ -1282,6 +1333,9 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) case LOK_POST_MOUSE_EVENT: postMouseEventInThread(task); break; + case LOK_SET_GRAPHIC_SELECTION: + setGraphicSelectionInThread(task); + break; } g_object_unref(task); diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index aa496aa..d2451b6 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -139,7 +139,8 @@ enum LOK_SET_PART, LOK_POST_KEY, LOK_PAINT_TILE, - LOK_POST_MOUSE_EVENT + LOK_POST_MOUSE_EVENT, + LOK_SET_GRAPHIC_SELECTION }; /** @@ -196,6 +197,13 @@ struct LOEvent int m_nPostMouseEventCount; ///@} + /// @name setGraphicSelection parameters + ///@{ + int m_nSetGraphicSelectionType; + int m_nSetGraphicSelectionX; + int m_nSetGraphicSelectionY; + ///@} + /// Constructor to instantiate an object of type `type`. LOEvent(int type) : m_nType(type) {} commit de9224bf9686550e63876eb5ac1241b27c01bc25 Author: Pranav Kant <pran...@gnome.org> Date: Sun Jul 26 22:23:46 2015 +0530 lokdocview: Move postMouseEvent in separate LOK thread Change-Id: I9d1a08db2a91a596d3039a2388c22e6ea76dc2b1 diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index b2d3dbf..4745a82 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -958,7 +958,16 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) if ((pEvent->time - priv->m_nLastButtonPressTime) < 250) nCount++; priv->m_nLastButtonPressTime = pEvent->time; - priv->m_pDocument->pClass->postMouseEvent(priv->m_pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, pixelToTwip(pEvent->x, priv->m_fZoom), pixelToTwip(pEvent->y, priv->m_fZoom), nCount); + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_POST_MOUSE_EVENT); + pLOEvent->m_nPostMouseEventType = LOK_MOUSEEVENT_MOUSEBUTTONDOWN; + pLOEvent->m_nPostMouseEventX = pixelToTwip(pEvent->x, priv->m_fZoom); + pLOEvent->m_nPostMouseEventY = pixelToTwip(pEvent->y, priv->m_fZoom); + pLOEvent->m_nPostMouseEventCount = nCount; + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); break; } case GDK_BUTTON_RELEASE: @@ -967,7 +976,16 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250) nCount++; priv->m_nLastButtonReleaseTime = pEvent->time; - priv->m_pDocument->pClass->postMouseEvent(priv->m_pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, pixelToTwip(pEvent->x, priv->m_fZoom), pixelToTwip(pEvent->y, priv->m_fZoom), nCount); + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_POST_MOUSE_EVENT); + pLOEvent->m_nPostMouseEventType = LOK_MOUSEEVENT_MOUSEBUTTONUP; + pLOEvent->m_nPostMouseEventX = pixelToTwip(pEvent->x, priv->m_fZoom); + pLOEvent->m_nPostMouseEventY = pixelToTwip(pEvent->y, priv->m_fZoom); + pLOEvent->m_nPostMouseEventCount = nCount; + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); break; } default: @@ -1050,12 +1068,37 @@ lok_doc_view_signal_motion (GtkWidget* pWidget, GdkEventMotion* pEvent) } // Otherwise a mouse move, as on the desktop. - priv->m_pDocument->pClass->postMouseEvent(priv->m_pDocument, LOK_MOUSEEVENT_MOUSEMOVE, pixelToTwip(pEvent->x, priv->m_fZoom), pixelToTwip(pEvent->y, priv->m_fZoom), 1); + + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_POST_MOUSE_EVENT); + pLOEvent->m_nPostMouseEventType = LOK_MOUSEEVENT_MOUSEMOVE; + pLOEvent->m_nPostMouseEventX = pixelToTwip(pEvent->x, priv->m_fZoom); + pLOEvent->m_nPostMouseEventY = pixelToTwip(pEvent->y, priv->m_fZoom); + pLOEvent->m_nPostMouseEventCount = 1; + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); return FALSE; } static void +postMouseEventInThread(gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + + priv->m_pDocument->pClass->postMouseEvent(priv->m_pDocument, + pLOEvent->m_nPostMouseEventType, + pLOEvent->m_nPostMouseEventX, + pLOEvent->m_nPostMouseEventY, + pLOEvent->m_nPostMouseEventCount); +} + +static void openDocumentInThread (gpointer data) { GTask* task = G_TASK(data); @@ -1236,6 +1279,9 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) case LOK_PAINT_TILE: paintTileInThread(task); break; + case LOK_POST_MOUSE_EVENT: + postMouseEventInThread(task); + break; } g_object_unref(task); diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index 6e57d2f..aa496aa 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -138,7 +138,8 @@ enum LOK_SET_PARTMODE, LOK_SET_PART, LOK_POST_KEY, - LOK_PAINT_TILE + LOK_PAINT_TILE, + LOK_POST_MOUSE_EVENT }; /** @@ -187,6 +188,14 @@ struct LOEvent float m_fPaintTileZoom; ///@} + /// @name postMouseEvent parameters + ///@{ + int m_nPostMouseEventType; + int m_nPostMouseEventX; + int m_nPostMouseEventY; + int m_nPostMouseEventCount; + ///@} + /// Constructor to instantiate an object of type `type`. LOEvent(int type) : m_nType(type) {} commit 4fb3d2e6be39fb3a7323b11a02adf853ed37a3ca Author: Pranav Kant <pran...@gnome.org> Date: Sun Jul 26 18:24:02 2015 +0530 lokdocview: Use only one ctor for instantiating LOEvent ... and set each member variable manually. Additionally, improves documentation of the struct LOEvent. Change-Id: I2e8e1dc70298dc85943769e2f01c6127eedb8207 diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 289d954..b2d3dbf 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -39,8 +39,8 @@ /// Private struct used by this GObject type struct _LOKDocViewPrivate { - gchar* m_aLOPath; - gchar* m_aDocPath; + const gchar* m_aLOPath; + const gchar* m_aDocPath; gdouble m_nLoadProgress; gboolean m_bIsLoading; gboolean m_bCanZoomIn; @@ -302,7 +302,10 @@ signalKey (GtkWidget* pWidget, GdkEventKey* pEvent) if (pEvent->type == GDK_KEY_RELEASE) { GTask* task = g_task_new(pDocView, NULL, NULL, NULL); - LOEvent* pLOEvent = new LOEvent(LOK_POST_KEY, LOK_KEYEVENT_KEYUP, nCharCode, nKeyCode); + LOEvent* pLOEvent = new LOEvent(LOK_POST_KEY); + pLOEvent->m_nKeyEvent = LOK_KEYEVENT_KEYUP; + pLOEvent->m_nCharCode = nCharCode; + pLOEvent->m_nKeyCode = nKeyCode; g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); g_object_unref(task); @@ -310,7 +313,10 @@ signalKey (GtkWidget* pWidget, GdkEventKey* pEvent) else { GTask* task = g_task_new(pDocView, NULL, NULL, NULL); - LOEvent* pLOEvent = new LOEvent(LOK_POST_KEY, LOK_KEYEVENT_KEYINPUT, nCharCode, nKeyCode); + LOEvent* pLOEvent = new LOEvent(LOK_POST_KEY); + pLOEvent->m_nKeyEvent = LOK_KEYEVENT_KEYINPUT; + pLOEvent->m_nCharCode = nCharCode; + pLOEvent->m_nKeyCode = nKeyCode; g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); g_object_unref(task); @@ -1163,7 +1169,7 @@ paintTileInThread (gpointer data) LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); TileBuffer& buffer = priv->m_aTileBuffer; - int index = pLOEvent->m_nX * buffer.m_nWidth + pLOEvent->m_nY; + int index = pLOEvent->m_nPaintTileX * buffer.m_nWidth + pLOEvent->m_nPaintTileY; if (buffer.m_mTiles.find(index) != buffer.m_mTiles.end() && buffer.m_mTiles[index].valid) return; @@ -1177,21 +1183,21 @@ paintTileInThread (gpointer data) unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf); GdkRectangle aTileRectangle; - aTileRectangle.x = pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom) * pLOEvent->m_nY; - aTileRectangle.y = pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom) * pLOEvent->m_nX; + aTileRectangle.x = pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom) * pLOEvent->m_nPaintTileY; + aTileRectangle.y = pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom) * pLOEvent->m_nPaintTileX; g_test_timer_start(); priv->m_pDocument->pClass->paintTile(priv->m_pDocument, pBuffer, nTileSizePixels, nTileSizePixels, aTileRectangle.x, aTileRectangle.y, - pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom), - pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom)); + pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom), + pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom)); double elapsedTime = g_test_timer_elapsed(); g_info ("Rendered (%d, %d) in %f seconds", - pLOEvent->m_nX, - pLOEvent->m_nY, + pLOEvent->m_nPaintTileX, + pLOEvent->m_nPaintTileY, elapsedTime); //create a mapping for it @@ -1674,9 +1680,12 @@ lok_doc_view_open_document (LOKDocView* pDocView, gpointer userdata) { GTask* task = g_task_new(pDocView, cancellable, callback, userdata); - LOEvent* pLOEvent = new LOEvent(LOK_LOAD_DOC, pPath); LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); - priv->m_aDocPath = g_strdup(pPath); + + LOEvent* pLOEvent = new LOEvent(LOK_LOAD_DOC); + pLOEvent->m_pPath = pPath; + + priv->m_aDocPath = pPath; g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); @@ -1836,9 +1845,11 @@ lok_doc_view_post_command (LOKDocView* pDocView, { GTask* task = g_task_new(pDocView, NULL, NULL, NULL); - LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND, pCommand, pArguments); - g_task_set_task_data(task, pLOEvent, g_free); + LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND); + pLOEvent->m_pCommand = pCommand; + pLOEvent->m_pArguments = pArguments; + g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); g_object_unref(task); } diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx index a8594fc..21ea58b 100644 --- a/libreofficekit/source/gtk/tilebuffer.cxx +++ b/libreofficekit/source/gtk/tilebuffer.cxx @@ -70,26 +70,35 @@ void TileBuffer::setInvalid(int x, int y, float fZoom, GTask* task) { m_mTiles[index].valid = false; - LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, fZoom); + LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE); + pLOEvent->m_nPaintTileX = x; + pLOEvent->m_nPaintTileY = y; + pLOEvent->m_fPaintTileZoom = fZoom; g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); } } -Tile& TileBuffer::getTile(int x, int y, float aZoom, GTask* task) +Tile& TileBuffer::getTile(int x, int y, float fZoom, GTask* task) { int index = x * m_nWidth + y; if (m_mTiles.find(index) != m_mTiles.end() && !m_mTiles[index].valid) { - LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, aZoom); + LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE); + pLOEvent->m_nPaintTileX = x; + pLOEvent->m_nPaintTileY = y; + pLOEvent->m_fPaintTileZoom = fZoom; g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); return m_mTiles[index]; } else if(m_mTiles.find(index) == m_mTiles.end()) { - LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, aZoom); + LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE); + pLOEvent->m_nPaintTileX = x; + pLOEvent->m_nPaintTileY = y; + pLOEvent->m_fPaintTileZoom = fZoom; g_task_set_task_data(task, pLOEvent, g_free); g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); return m_DummyTile; diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index f23b023..6e57d2f 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -152,46 +152,44 @@ struct LOEvent { /// To identify the type of LOK call int m_nType; + + /// @name post_command parameters + ///@{ const gchar* m_pCommand; const gchar* m_pArguments; - gchar* m_pPath; + ///@} + + /// @name open_document parameter + ///@{ + const gchar* m_pPath; + ///@} + + /// set_edit parameter gboolean m_bEdit; + + /// set_partmode parameter int m_nPartMode; + + /// set_part parameter int m_nPart; + + /// @name postKeyEvent parameters + ///@{ int m_nKeyEvent; int m_nCharCode; int m_nKeyCode; + ///@} - int m_nX; - int m_nY; - float m_fZoom; + /// @name paintTile parameters + ///@{ + int m_nPaintTileX; + int m_nPaintTileY; + float m_fPaintTileZoom; + ///@} - /// Constructor to easily instantiate an object for LOK call of `type' type. + /// Constructor to instantiate an object of type `type`. LOEvent(int type) : m_nType(type) {} - - LOEvent(int type, const gchar* pCommand, const gchar* pArguments) - : m_nType(type), - m_pCommand(pCommand), - m_pArguments(pArguments) {} - - LOEvent(int type, const gchar* pPath) - : m_nType(type) - { - m_pPath = g_strdup(pPath); - } - - LOEvent(int type, int nKeyEvent, int nCharCode, int nKeyCode) - : m_nType(type), - m_nKeyEvent(nKeyEvent), - m_nCharCode(nCharCode), - m_nKeyCode(nKeyCode) {} - - LOEvent(int type, int x, int y, float zoom) - : m_nType(type), - m_nX(x), - m_nY(y), - m_fZoom(zoom) {} }; #endif // INCLUDED_TILEBUFFER_HXX commit ee0f4f75d2d95aaed8995337947c4cc665722aaf Author: Pranav Kant <pran...@gnome.org> Date: Sun Jul 26 17:22:13 2015 +0530 lokdocview: Follow the camelCase naming convention Change-Id: I05582d33ee3535d4b677fa8138c9d573585a4252 diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 825eb10..289d954 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -1050,7 +1050,7 @@ lok_doc_view_signal_motion (GtkWidget* pWidget, GdkEventMotion* pEvent) } static void -lok_doc_view_open_document_in_thread (gpointer data) +openDocumentInThread (gpointer data) { GTask* task = G_TASK(data); LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); @@ -1099,7 +1099,7 @@ lok_doc_view_open_document_in_thread (gpointer data) } static void -lok_doc_view_set_part_in_thread(gpointer data) +setPartInThread(gpointer data) { GTask* task = G_TASK(data); LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); @@ -1111,7 +1111,7 @@ lok_doc_view_set_part_in_thread(gpointer data) } static void -lok_doc_view_set_partmode_in_thread(gpointer data) +setPartmodeInThread(gpointer data) { GTask* task = G_TASK(data); LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); @@ -1123,7 +1123,7 @@ lok_doc_view_set_partmode_in_thread(gpointer data) } static void -lok_doc_view_set_edit_in_thread(gpointer data) +setEditInThread(gpointer data) { GTask* task = G_TASK(data); LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); @@ -1145,7 +1145,7 @@ lok_doc_view_set_edit_in_thread(gpointer data) } static void -lok_doc_view_post_command_in_thread (gpointer data) +postCommandInThread (gpointer data) { GTask* task = G_TASK(data); LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); @@ -1210,19 +1210,19 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) switch (pLOEvent->m_nType) { case LOK_LOAD_DOC: - lok_doc_view_open_document_in_thread (task); + openDocumentInThread(task); break; case LOK_POST_COMMAND: - lok_doc_view_post_command_in_thread (task); + postCommandInThread(task); break; case LOK_SET_EDIT: - lok_doc_view_set_edit_in_thread(task); + setEditInThread(task); break; case LOK_SET_PART: - lok_doc_view_set_part_in_thread(task); + setPartInThread(task); break; case LOK_SET_PARTMODE: - lok_doc_view_set_partmode_in_thread(task); + setPartmodeInThread(task); break; case LOK_POST_KEY: postKeyEventInThread(task); commit 57ec1780d654e335e09a6c64c4d48234f0556635 Author: Pranav Kant <pran...@gnome.org> Date: Sat Jul 25 21:21:34 2015 +0530 lokdocview: Cannot use same GTask object for all calls. Change-Id: I875d49a9e4360659087ae70456edefb15bc57b20 diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 60bdbd4..825eb10 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -475,12 +475,15 @@ setTilesInvalid (LOKDocView* pDocView, const GdkRectangle& rRectangle) aStart.y = aRectanglePixels.x / nTileSizePixels; aEnd.x = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels; aEnd.y = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels; - GTask* task = g_task_new(pDocView, NULL, NULL, NULL); for (int i = aStart.x; i < aEnd.x; i++) + { for (int j = aStart.y; j < aEnd.y; j++) + { + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); priv->m_aTileBuffer.setInvalid(i, j, priv->m_fZoom, task); - - g_object_unref(task); + g_object_unref(task); + } + } } static gboolean commit a7f12df929226ba43356d3d092851b07c84ae1c4 Author: Pranav Kant <pran...@gnome.org> Date: Fri Jul 24 01:10:42 2015 +0530 Use thread pool for LOK call: paintTile() Change-Id: I45e94248013277affa11e91439fbc16995b8ed8e diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 2259d5b..60bdbd4 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -135,16 +135,6 @@ enum PROP_CAN_ZOOM_OUT }; -enum -{ - LOK_LOAD_DOC, - LOK_POST_COMMAND, - LOK_SET_EDIT, - LOK_SET_PARTMODE, - LOK_SET_PART, - LOK_POST_KEY -}; - static guint doc_view_signals[LAST_SIGNAL] = { 0 }; static void lok_doc_view_initable_iface_init (GInitableIface *iface); @@ -161,7 +151,7 @@ G_DEFINE_TYPE_WITH_CODE (LOKDocView, lok_doc_view, GTK_TYPE_DRAWING_AREA, #pragma GCC diagnostic pop #endif -static GThreadPool* lokThreadPool; +GThreadPool* lokThreadPool; /// Helper struct used to pass the data from soffice thread -> main thread. struct CallbackData @@ -176,50 +166,6 @@ struct CallbackData m_pDocView(pDocView) {} }; -/** - A struct that we use to store the data about the LOK call. - - Object of this type is passed with all the LOK calls, - so that they can be idenitified. Additionally, it also contains - the data that LOK call needs. -*/ -struct LOEvent -{ - /// To identify the type of LOK call - int m_nType; - const gchar* m_pCommand; - const gchar* m_pArguments; - gchar* m_pPath; - gboolean m_bEdit; - int m_nPartMode; - int m_nPart; - int m_nKeyEvent; - int m_nCharCode; - int m_nKeyCode; - - - /// Constructor to easily instantiate an object for LOK call of `type' type. - LOEvent(int type) - : m_nType(type) {} - - LOEvent(int type, const gchar* pCommand, const gchar* pArguments) - : m_nType(type), - m_pCommand(pCommand), - m_pArguments(pArguments) {} - - LOEvent(int type, const gchar* pPath) - : m_nType(type) - { - m_pPath = g_strdup(pPath); - } - - LOEvent(int type, int nKeyEvent, int nCharCode, int nKeyCode) - : m_nType(type), - m_nKeyEvent(nKeyEvent), - m_nCharCode(nCharCode), - m_nKeyCode(nKeyCode) {} -}; - static void payloadToSize(const char* pPayload, long& rWidth, long& rHeight) { @@ -529,10 +475,12 @@ setTilesInvalid (LOKDocView* pDocView, const GdkRectangle& rRectangle) aStart.y = aRectanglePixels.x / nTileSizePixels; aEnd.x = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels; aEnd.y = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels; - + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); for (int i = aStart.x; i < aEnd.x; i++) for (int j = aStart.y; j < aEnd.y; j++) - priv->m_aTileBuffer.setInvalid(i, j, priv->m_fZoom); + priv->m_aTileBuffer.setInvalid(i, j, priv->m_fZoom, task); + + g_object_unref(task); } static gboolean @@ -753,13 +701,6 @@ renderGraphicHandle(LOKDocView* pDocView, } } -static void -renderDocumentCallback(GObject* source_object, GAsyncResult*, gpointer) -{ - LOKDocView* pDocView = LOK_DOC_VIEW(source_object); - gtk_widget_queue_draw(GTK_WIDGET(pDocView)); -} - static gboolean renderDocument(LOKDocView* pDocView, cairo_t* pCairo) { @@ -808,14 +749,14 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo) if (bPaint) { - GTask* task = g_task_new(pDocView, NULL, renderDocumentCallback, NULL); + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); Tile& currentTile = priv->m_aTileBuffer.getTile(nRow, nColumn, priv->m_fZoom, task); - GdkPixbuf* pPixBuf = currentTile.getBuffer(); gdk_cairo_set_source_pixbuf (pCairo, pPixBuf, twipToPixel(aTileRectangleTwips.x, priv->m_fZoom), twipToPixel(aTileRectangleTwips.y, priv->m_fZoom)); cairo_paint(pCairo); + g_object_unref(task); } } } @@ -1212,6 +1153,52 @@ lok_doc_view_post_command_in_thread (gpointer data) } static void +paintTileInThread (gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + TileBuffer& buffer = priv->m_aTileBuffer; + int index = pLOEvent->m_nX * buffer.m_nWidth + pLOEvent->m_nY; + if (buffer.m_mTiles.find(index) != buffer.m_mTiles.end() && + buffer.m_mTiles[index].valid) + return; + + GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels); + if (!pPixBuf) + { + g_info ("Error allocating memory to pixbuf"); + return; + } + + unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf); + GdkRectangle aTileRectangle; + aTileRectangle.x = pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom) * pLOEvent->m_nY; + aTileRectangle.y = pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom) * pLOEvent->m_nX; + + g_test_timer_start(); + priv->m_pDocument->pClass->paintTile(priv->m_pDocument, + pBuffer, + nTileSizePixels, nTileSizePixels, + aTileRectangle.x, aTileRectangle.y, + pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom), + pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom)); + + double elapsedTime = g_test_timer_elapsed(); + g_info ("Rendered (%d, %d) in %f seconds", + pLOEvent->m_nX, + pLOEvent->m_nY, + elapsedTime); + + //create a mapping for it + buffer.m_mTiles[index].setPixbuf(pPixBuf); + buffer.m_mTiles[index].valid = true; + gtk_widget_queue_draw(GTK_WIDGET(pDocView)); +} + + +static void lokThreadFunc(gpointer data, gpointer /*user_data*/) { GTask* task = G_TASK(data); @@ -1237,6 +1224,9 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) case LOK_POST_KEY: postKeyEventInThread(task); break; + case LOK_PAINT_TILE: + paintTileInThread(task); + break; } g_object_unref(task); diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx index d488f8b..a8594fc 100644 --- a/libreofficekit/source/gtk/tilebuffer.cxx +++ b/libreofficekit/source/gtk/tilebuffer.cxx @@ -13,6 +13,8 @@ #define g_info(...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__) #endif +extern GThreadPool* lokThreadPool; + /* ------------------ Utility functions ------------------ @@ -27,42 +29,6 @@ float twipToPixel(float fInput, float zoom) return fInput / 1440.0f * DPI * zoom; } -static void getTileFunc(GTask*, gpointer, gpointer task_data, GCancellable*) -{ - GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels); - GetTileCallbackData* pCallback = static_cast<GetTileCallbackData*>(task_data); - TileBuffer* buffer = pCallback->m_pBuffer; - int index = pCallback->m_nX * buffer->m_nWidth + pCallback->m_nY; - if (!pPixBuf) - { - g_info ("Error allocating memory to pixbuf"); - return; - } - - unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf); - GdkRectangle aTileRectangle; - aTileRectangle.x = pixelToTwip(nTileSizePixels, pCallback->m_fZoom) * pCallback->m_nY; - aTileRectangle.y = pixelToTwip(nTileSizePixels, pCallback->m_fZoom) * pCallback->m_nX; - - g_test_timer_start(); - buffer->m_pLOKDocument->pClass->paintTile(buffer->m_pLOKDocument, - pBuffer, - nTileSizePixels, nTileSizePixels, - aTileRectangle.x, aTileRectangle.y, - pixelToTwip(nTileSizePixels, pCallback->m_fZoom), - pixelToTwip(nTileSizePixels, pCallback->m_fZoom)); - - double elapsedTime = g_test_timer_elapsed(); - g_info ("Rendered (%d, %d) in %f seconds", - pCallback->m_nX, - pCallback->m_nY, - elapsedTime); - - //create a mapping for it - buffer->m_mTiles[index].setPixbuf(pPixBuf); - buffer->m_mTiles[index].valid = true; -} - /* ---------------------------- Tile class member functions ---------------------------- @@ -96,17 +62,17 @@ void TileBuffer::resetAllTiles() } } -void TileBuffer::setInvalid(int x, int y, float fZoom) +void TileBuffer::setInvalid(int x, int y, float fZoom, GTask* task) { int index = x * m_nWidth + y; g_info("Setting tile invalid (%d, %d)", x, y); if (m_mTiles.find(index) != m_mTiles.end()) { m_mTiles[index].valid = false; - GTask* task = g_task_new(this, NULL, NULL, NULL); - GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, fZoom, this); - g_task_set_task_data(task, pCallback, g_free); - g_task_run_in_thread(task, getTileFunc); + + LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, fZoom); + g_task_set_task_data(task, pLOEvent, g_free); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); } } @@ -116,17 +82,16 @@ Tile& TileBuffer::getTile(int x, int y, float aZoom, GTask* task) if (m_mTiles.find(index) != m_mTiles.end() && !m_mTiles[index].valid) { - GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, aZoom, this); - g_task_set_task_data(task, pCallback, g_free); - g_task_run_in_thread(task, getTileFunc); + LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, aZoom); + g_task_set_task_data(task, pLOEvent, g_free); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); return m_mTiles[index]; } else if(m_mTiles.find(index) == m_mTiles.end()) { - GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, aZoom, this); - g_task_set_task_data(task, pCallback, g_free); - g_info ("running in thread new tile"); - g_task_run_in_thread(task, getTileFunc); + LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, aZoom); + g_task_set_task_data(task, pLOEvent, g_free); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); return m_DummyTile; } diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index 40fb2ab..f23b023 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -107,7 +107,7 @@ class TileBuffer @return the tile at the mentioned position (x, y) */ - Tile& getTile(int x, int y, float aZoom, GTask*); + Tile& getTile(int x, int y, float aZoom, GTask* task); /// Destroys all the tiles in the tile buffer; also frees the memory allocated /// for all the Tile objects. void resetAllTiles(); @@ -118,8 +118,7 @@ class TileBuffer @param x the position of tile along x-axis @param y the position of tile along y-axis */ - void setInvalid(int x, int y, float zoom); - + void setInvalid(int x, int y, float zoom, GTask* task); /// Contains the reference to the LOK Document that this tile buffer is for. LibreOfficeKitDocument *m_pLOKDocument; @@ -131,26 +130,70 @@ class TileBuffer Tile m_DummyTile; }; +enum +{ + LOK_LOAD_DOC, + LOK_POST_COMMAND, + LOK_SET_EDIT, + LOK_SET_PARTMODE, + LOK_SET_PART, + LOK_POST_KEY, + LOK_PAINT_TILE +}; + /** - Helper struct used to pass the data from main thread to spawned threads. - Spawned threads are responsible for calling paintTile, and store the result - in tile buffer. + A struct that we use to store the data about the LOK call. + + Object of this type is passed with all the LOK calls, + so that they can be idenitified. Additionally, it also contains + the data that LOK call needs. */ -struct GetTileCallbackData +struct LOEvent { + /// To identify the type of LOK call + int m_nType; + const gchar* m_pCommand; + const gchar* m_pArguments; + gchar* m_pPath; + gboolean m_bEdit; + int m_nPartMode; + int m_nPart; + int m_nKeyEvent; + int m_nCharCode; + int m_nKeyCode; + int m_nX; int m_nY; float m_fZoom; - TileBuffer* m_pBuffer; - GetTileCallbackData(int x, int y, float zoom, TileBuffer* buffer) - : m_nX(x), + /// Constructor to easily instantiate an object for LOK call of `type' type. + LOEvent(int type) + : m_nType(type) {} + + LOEvent(int type, const gchar* pCommand, const gchar* pArguments) + : m_nType(type), + m_pCommand(pCommand), + m_pArguments(pArguments) {} + + LOEvent(int type, const gchar* pPath) + : m_nType(type) + { + m_pPath = g_strdup(pPath); + } + + LOEvent(int type, int nKeyEvent, int nCharCode, int nKeyCode) + : m_nType(type), + m_nKeyEvent(nKeyEvent), + m_nCharCode(nCharCode), + m_nKeyCode(nKeyCode) {} + + LOEvent(int type, int x, int y, float zoom) + : m_nType(type), + m_nX(x), m_nY(y), - m_fZoom(zoom), - m_pBuffer(buffer) { } + m_fZoom(zoom) {} }; - #endif // INCLUDED_TILEBUFFER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit e032b64451347f5079c2a5bfbfda8d843db91e2d Author: Pranav Kant <pran...@gnome.org> Date: Wed Jul 22 20:25:36 2015 +0530 lokdocview, tilebuffer: Add DOxygen comments Change-Id: I27377f0a758729a7877cfc6a56ea1b4bb3d1c3c9 diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 0e51b13..2259d5b 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -36,6 +36,7 @@ // Number of handles around a graphic selection. #define GRAPHIC_HANDLE_COUNT 8 +/// Private struct used by this GObject type struct _LOKDocViewPrivate { gchar* m_aLOPath; @@ -162,6 +163,7 @@ G_DEFINE_TYPE_WITH_CODE (LOKDocView, lok_doc_view, GTK_TYPE_DRAWING_AREA, static GThreadPool* lokThreadPool; +/// Helper struct used to pass the data from soffice thread -> main thread. struct CallbackData { int m_nType; @@ -174,8 +176,16 @@ struct CallbackData m_pDocView(pDocView) {} }; +/** + A struct that we use to store the data about the LOK call. + + Object of this type is passed with all the LOK calls, + so that they can be idenitified. Additionally, it also contains + the data that LOK call needs. +*/ struct LOEvent { + /// To identify the type of LOK call int m_nType; const gchar* m_pCommand; const gchar* m_pArguments; @@ -187,6 +197,8 @@ struct LOEvent int m_nCharCode; int m_nKeyCode; + + /// Constructor to easily instantiate an object for LOK call of `type' type. LOEvent(int type) : m_nType(type) {} diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index 50de72d..40fb2ab 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -131,6 +131,11 @@ class TileBuffer Tile m_DummyTile; }; +/** + Helper struct used to pass the data from main thread to spawned threads. + Spawned threads are responsible for calling paintTile, and store the result + in tile buffer. +*/ struct GetTileCallbackData { int m_nX; commit 4edbf5a01fb8d93f3e6f2b9f7100a0c3d2eafa6e Author: Pranav Kant <pran...@gnome.org> Date: Sun Jul 19 01:03:56 2015 +0530 lokdocview: Make paintTile() async Change-Id: I57db9e3adf26996e6e1e105b8b95f53e88e7760f diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 8054c8e..0e51b13 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -520,7 +520,7 @@ setTilesInvalid (LOKDocView* pDocView, const GdkRectangle& rRectangle) for (int i = aStart.x; i < aEnd.x; i++) for (int j = aStart.y; j < aEnd.y; j++) - priv->m_aTileBuffer.setInvalid(i, j); + priv->m_aTileBuffer.setInvalid(i, j, priv->m_fZoom); } static gboolean @@ -741,6 +741,12 @@ renderGraphicHandle(LOKDocView* pDocView, } } +static void +renderDocumentCallback(GObject* source_object, GAsyncResult*, gpointer) +{ + LOKDocView* pDocView = LOK_DOC_VIEW(source_object); + gtk_widget_queue_draw(GTK_WIDGET(pDocView)); +} static gboolean renderDocument(LOKDocView* pDocView, cairo_t* pCairo) @@ -790,7 +796,9 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo) if (bPaint) { - Tile& currentTile = priv->m_aTileBuffer.getTile(nRow, nColumn, priv->m_fZoom); + GTask* task = g_task_new(pDocView, NULL, renderDocumentCallback, NULL); + Tile& currentTile = priv->m_aTileBuffer.getTile(nRow, nColumn, priv->m_fZoom, task); + GdkPixbuf* pPixBuf = currentTile.getBuffer(); gdk_cairo_set_source_pixbuf (pCairo, pPixBuf, twipToPixel(aTileRectangleTwips.x, priv->m_fZoom), diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx index 60aa16f..d488f8b 100644 --- a/libreofficekit/source/gtk/tilebuffer.cxx +++ b/libreofficekit/source/gtk/tilebuffer.cxx @@ -27,6 +27,42 @@ float twipToPixel(float fInput, float zoom) return fInput / 1440.0f * DPI * zoom; } +static void getTileFunc(GTask*, gpointer, gpointer task_data, GCancellable*) +{ + GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels); + GetTileCallbackData* pCallback = static_cast<GetTileCallbackData*>(task_data); + TileBuffer* buffer = pCallback->m_pBuffer; + int index = pCallback->m_nX * buffer->m_nWidth + pCallback->m_nY; + if (!pPixBuf) + { + g_info ("Error allocating memory to pixbuf"); + return; + } + + unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf); + GdkRectangle aTileRectangle; + aTileRectangle.x = pixelToTwip(nTileSizePixels, pCallback->m_fZoom) * pCallback->m_nY; + aTileRectangle.y = pixelToTwip(nTileSizePixels, pCallback->m_fZoom) * pCallback->m_nX; + + g_test_timer_start(); + buffer->m_pLOKDocument->pClass->paintTile(buffer->m_pLOKDocument, + pBuffer, + nTileSizePixels, nTileSizePixels, + aTileRectangle.x, aTileRectangle.y, + pixelToTwip(nTileSizePixels, pCallback->m_fZoom), + pixelToTwip(nTileSizePixels, pCallback->m_fZoom)); + + double elapsedTime = g_test_timer_elapsed(); + g_info ("Rendered (%d, %d) in %f seconds", + pCallback->m_nX, + pCallback->m_nY, + elapsedTime); + + //create a mapping for it + buffer->m_mTiles[index].setPixbuf(pPixBuf); + buffer->m_mTiles[index].valid = true; +} + /* ---------------------------- Tile class member functions ---------------------------- @@ -56,55 +92,42 @@ void TileBuffer::resetAllTiles() std::map<int, Tile>::iterator it = m_mTiles.begin(); for (; it != m_mTiles.end(); ++it) { - it->second.release(); + it->second.valid = false; } - m_mTiles.clear(); } -void TileBuffer::setInvalid(int x, int y) +void TileBuffer::setInvalid(int x, int y, float fZoom) { int index = x * m_nWidth + y; g_info("Setting tile invalid (%d, %d)", x, y); if (m_mTiles.find(index) != m_mTiles.end()) { m_mTiles[index].valid = false; - m_mTiles[index].release(); - m_mTiles.erase(index); + GTask* task = g_task_new(this, NULL, NULL, NULL); + GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, fZoom, this); + g_task_set_task_data(task, pCallback, g_free); + g_task_run_in_thread(task, getTileFunc); } } -Tile& TileBuffer::getTile(int x, int y, float aZoom) +Tile& TileBuffer::getTile(int x, int y, float aZoom, GTask* task) { int index = x * m_nWidth + y; - if(m_mTiles.find(index) == m_mTiles.end() || !m_mTiles[index].valid) - { - GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels); - if (!pPixBuf) - { - g_info ("Error allocating memory to pixbuf"); - return m_mTiles[index]; - } - - unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf); - GdkRectangle aTileRectangle; - aTileRectangle.x = pixelToTwip(nTileSizePixels, aZoom) * y; - aTileRectangle.y = pixelToTwip(nTileSizePixels, aZoom) * x; - - g_test_timer_start(); - m_pLOKDocument->pClass->paintTile(m_pLOKDocument, - pBuffer, - nTileSizePixels, nTileSizePixels, - aTileRectangle.x, aTileRectangle.y, - pixelToTwip(nTileSizePixels, aZoom), - pixelToTwip(nTileSizePixels, aZoom)); - - double elapsedTime = g_test_timer_elapsed(); - g_info ("Rendered (%d, %d) in %f seconds", x, y, elapsedTime); - - //create a mapping for it - m_mTiles[index].setPixbuf(pPixBuf); - m_mTiles[index].valid = true; + if (m_mTiles.find(index) != m_mTiles.end() && !m_mTiles[index].valid) + { + GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, aZoom, this); + g_task_set_task_data(task, pCallback, g_free); + g_task_run_in_thread(task, getTileFunc); + return m_mTiles[index]; + } + else if(m_mTiles.find(index) == m_mTiles.end()) + { + GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, aZoom, this); + g_task_set_task_data(task, pCallback, g_free); + g_info ("running in thread new tile"); + g_task_run_in_thread(task, getTileFunc); + return m_DummyTile; } return m_mTiles[index]; diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx index 6e6c0be..50de72d 100644 --- a/libreofficekit/source/gtk/tilebuffer.hxx +++ b/libreofficekit/source/gtk/tilebuffer.hxx @@ -86,7 +86,10 @@ class TileBuffer int columns) : m_pLOKDocument(document) , m_nWidth(columns) - { } + { + GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels); + m_DummyTile.setPixbuf(pPixBuf); + } ~TileBuffer() {} @@ -104,7 +107,7 @@ class TileBuffer @return the tile at the mentioned position (x, y) */ - Tile& getTile(int x, int y, float aZoom); + Tile& getTile(int x, int y, float aZoom, GTask*); /// Destroys all the tiles in the tile buffer; also frees the memory allocated /// for all the Tile objects. void resetAllTiles(); @@ -115,17 +118,34 @@ class TileBuffer @param x the position of tile along x-axis @param y the position of tile along y-axis */ - void setInvalid(int x, int y); + void setInvalid(int x, int y, float zoom); + - private: /// Contains the reference to the LOK Document that this tile buffer is for. LibreOfficeKitDocument *m_pLOKDocument; /// Stores all the tiles cached by this tile buffer. std::map<int, Tile> m_mTiles; /// Width of the current tile buffer (number of columns) int m_nWidth; + /// Dummy tile + Tile m_DummyTile; }; +struct GetTileCallbackData +{ + int m_nX; + int m_nY; + float m_fZoom; + TileBuffer* m_pBuffer; + + GetTileCallbackData(int x, int y, float zoom, TileBuffer* buffer) + : m_nX(x), + m_nY(y), + m_fZoom(zoom), + m_pBuffer(buffer) { } +}; + + #endif // INCLUDED_TILEBUFFER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit a433ea9f46cc1cc0de7282f3d360d70ad215aaa8 Author: Pranav Kant <pran...@gnome.org> Date: Sun Jul 12 23:22:51 2015 +0530 lokdocview: Use a thread pool for most LOK calls This is a thread pool with just single thread because LOK is single threaded; using multiple threads in this case would be useless. Primary reason we are using a thread pool here is to avoid the overhead in spawning a new thread for each LOK call. Change-Id: Ibbfdb7cb0a8ef9f07bcc659e65ce8997716aa245 diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h index 3f56f08..02789ad 100644 --- a/include/LibreOfficeKit/LibreOfficeKitGtk.h +++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h @@ -81,8 +81,8 @@ gboolean lok_doc_view_get_edit (LOKDocView* /// Posts the .uno: command to the LibreOfficeKit. void lok_doc_view_post_command (LOKDocView* pDocView, - const char* pCommand, - const char* pArguments); + const gchar* pCommand, + const gchar* pArguments); float lok_doc_view_pixel_to_twip (LOKDocView* pDocView, float fInput); diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 5517dc4..8054c8e 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -134,6 +134,16 @@ enum PROP_CAN_ZOOM_OUT }; +enum +{ + LOK_LOAD_DOC, + LOK_POST_COMMAND, + LOK_SET_EDIT, + LOK_SET_PARTMODE, + LOK_SET_PART, + LOK_POST_KEY +}; + static guint doc_view_signals[LAST_SIGNAL] = { 0 }; static void lok_doc_view_initable_iface_init (GInitableIface *iface); @@ -150,6 +160,7 @@ G_DEFINE_TYPE_WITH_CODE (LOKDocView, lok_doc_view, GTK_TYPE_DRAWING_AREA, #pragma GCC diagnostic pop #endif +static GThreadPool* lokThreadPool; struct CallbackData { @@ -163,6 +174,40 @@ struct CallbackData m_pDocView(pDocView) {} }; +struct LOEvent +{ + int m_nType; + const gchar* m_pCommand; + const gchar* m_pArguments; + gchar* m_pPath; + gboolean m_bEdit; + int m_nPartMode; + int m_nPart; + int m_nKeyEvent; + int m_nCharCode; + int m_nKeyCode; + + LOEvent(int type) + : m_nType(type) {} + + LOEvent(int type, const gchar* pCommand, const gchar* pArguments) + : m_nType(type), + m_pCommand(pCommand), + m_pArguments(pArguments) {} + + LOEvent(int type, const gchar* pPath) + : m_nType(type) + { + m_pPath = g_strdup(pPath); + } + + LOEvent(int type, int nKeyEvent, int nCharCode, int nKeyCode) + : m_nType(type), + m_nKeyEvent(nKeyEvent), + m_nCharCode(nCharCode), + m_nKeyCode(nKeyCode) {} +}; + static void payloadToSize(const char* pPayload, long& rWidth, long& rHeight) { @@ -225,6 +270,20 @@ isEmptyRectangle(const GdkRectangle& rRectangle) return rRectangle.x == 0 && rRectangle.y == 0 && rRectangle.width == 0 && rRectangle.height == 0; } +static void +postKeyEventInThread(gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + + priv->m_pDocument->pClass->postKeyEvent(priv->m_pDocument, + pLOEvent->m_nKeyEvent, + pLOEvent->m_nCharCode, + pLOEvent->m_nKeyCode); +} + static gboolean signalKey (GtkWidget* pWidget, GdkEventKey* pEvent) { @@ -281,10 +340,23 @@ signalKey (GtkWidget* pWidget, GdkEventKey* pEvent) if (pEvent->state & GDK_SHIFT_MASK) nKeyCode |= KEY_SHIFT; + if (pEvent->type == GDK_KEY_RELEASE) - priv->m_pDocument->pClass->postKeyEvent(priv->m_pDocument, LOK_KEYEVENT_KEYUP, nCharCode, nKeyCode); + { + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_POST_KEY, LOK_KEYEVENT_KEYUP, nCharCode, nKeyCode); + g_task_set_task_data(task, pLOEvent, g_free); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); + } else - priv->m_pDocument->pClass->postKeyEvent(priv->m_pDocument, LOK_KEYEVENT_KEYINPUT, nCharCode, nKeyCode); + { + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_POST_KEY, LOK_KEYEVENT_KEYINPUT, nCharCode, nKeyCode); + g_task_set_task_data(task, pLOEvent, g_free); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); + } return FALSE; } @@ -1013,6 +1085,143 @@ lok_doc_view_signal_motion (GtkWidget* pWidget, GdkEventMotion* pEvent) return FALSE; } +static void +lok_doc_view_open_document_in_thread (gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + + if ( priv->m_pDocument ) + { + priv->m_pDocument->pClass->destroy( priv->m_pDocument ); + priv->m_pDocument = 0; + } + + priv->m_pOffice->pClass->registerCallback(priv->m_pOffice, globalCallbackWorker, pDocView); + priv->m_pDocument = priv->m_pOffice->pClass->documentLoad( priv->m_pOffice, priv->m_aDocPath ); + if ( !priv->m_pDocument ) + { + // FIXME: should have a GError parameter and populate it. + char *pError = priv->m_pOffice->pClass->getError( priv->m_pOffice ); + fprintf( stderr, "Error opening document '%s'\n", pError ); + g_task_return_new_error(task, 0, 0, pError); + } + else + { + priv->m_pDocument->pClass->initializeForRendering(priv->m_pDocument); + priv->m_pDocument->pClass->registerCallback(priv->m_pDocument, callbackWorker, pDocView); + priv->m_pDocument->pClass->getDocumentSize(priv->m_pDocument, &priv->m_nDocumentWidthTwips, &priv->m_nDocumentHeightTwips); + g_timeout_add(600, handleTimeout, pDocView); + + float zoom = priv->m_fZoom; + long nDocumentWidthTwips = priv->m_nDocumentWidthTwips; + long nDocumentHeightTwips = priv->m_nDocumentHeightTwips; + long nDocumentWidthPixels = twipToPixel(nDocumentWidthTwips, zoom); + long nDocumentHeightPixels = twipToPixel(nDocumentHeightTwips, zoom); + // Total number of columns in this document. + guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels); + + + priv->m_aTileBuffer = TileBuffer(priv->m_pDocument, + nColumns); + gtk_widget_set_size_request(GTK_WIDGET(pDocView), + nDocumentWidthPixels, + nDocumentHeightPixels); + gtk_widget_set_can_focus(GTK_WIDGET(pDocView), TRUE); + gtk_widget_grab_focus(GTK_WIDGET(pDocView)); + g_task_return_boolean (task, true); + } +} + +static void +lok_doc_view_set_part_in_thread(gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + int nPart = pLOEvent->m_nPart; + + priv->m_pDocument->pClass->setPart( priv->m_pDocument, nPart ); +} + +static void +lok_doc_view_set_partmode_in_thread(gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + int nPartMode = pLOEvent->m_nPartMode; + + priv->m_pDocument->pClass->setPartMode( priv->m_pDocument, nPartMode ); +} + +static void +lok_doc_view_set_edit_in_thread(gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + gboolean bWasEdit = priv->m_bEdit; + gboolean bEdit = pLOEvent->m_bEdit; + + if (!priv->m_bEdit && bEdit) + g_info("lok_doc_view_set_edit: entering edit mode"); + else if (priv->m_bEdit && !bEdit) + { + g_info("lok_doc_view_set_edit: leaving edit mode"); + priv->m_pDocument->pClass->resetSelection(priv->m_pDocument); + } + priv->m_bEdit = bEdit; + g_signal_emit(pDocView, doc_view_signals[EDIT_CHANGED], 0, bWasEdit); + gtk_widget_queue_draw(GTK_WIDGET(pDocView)); +} + +static void +lok_doc_view_post_command_in_thread (gpointer data) +{ + GTask* task = G_TASK(data); + LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + + priv->m_pDocument->pClass->postUnoCommand(priv->m_pDocument, pLOEvent->m_pCommand, pLOEvent->m_pArguments); +} + +static void +lokThreadFunc(gpointer data, gpointer /*user_data*/) +{ + GTask* task = G_TASK(data); + LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task)); + + switch (pLOEvent->m_nType) + { + case LOK_LOAD_DOC: + lok_doc_view_open_document_in_thread (task); + break; + case LOK_POST_COMMAND: + lok_doc_view_post_command_in_thread (task); + break; + case LOK_SET_EDIT: + lok_doc_view_set_edit_in_thread(task); + break; + case LOK_SET_PART: + lok_doc_view_set_part_in_thread(task); + break; + case LOK_SET_PARTMODE: + lok_doc_view_set_partmode_in_thread(task); + break; + case LOK_POST_KEY: + postKeyEventInThread(task); + break; + } + + g_object_unref(task); +} + static void lok_doc_view_init (LOKDocView* pDocView) { LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); @@ -1392,6 +1601,12 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + + lokThreadPool = g_thread_pool_new(lokThreadFunc, + NULL, + 1, + FALSE, + NULL); } /** @@ -1423,60 +1638,13 @@ lok_doc_view_open_document_finish (LOKDocView* pDocView, GAsyncResult* res, GErr GTask* task = G_TASK(res); g_return_val_if_fail(g_task_is_valid(res, pDocView), false); - //FIXME: make source_tag workx + //FIXME: make source_tag work //g_return_val_if_fail(g_task_get_source_tag(task) == lok_doc_view_open_document, NULL); g_return_val_if_fail(error == NULL || *error == NULL, false); return g_task_propagate_boolean(task, error); } -static void -lok_doc_view_open_document_func (GTask* task, gpointer source_object, gpointer /*task_data*/, GCancellable* /*cancellable*/) -{ - LOKDocView* pDocView = LOK_DOC_VIEW(source_object); - LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); - - if ( priv->m_pDocument ) - { - priv->m_pDocument->pClass->destroy( priv->m_pDocument ); - priv->m_pDocument = 0; - } - - priv->m_pOffice->pClass->registerCallback(priv->m_pOffice, globalCallbackWorker, pDocView); - priv->m_pDocument = priv->m_pOffice->pClass->documentLoad( priv->m_pOffice, priv->m_aDocPath ); - if ( !priv->m_pDocument ) - { - // FIXME: should have a GError parameter and populate it. - char *pError = priv->m_pOffice->pClass->getError( priv->m_pOffice ); - fprintf( stderr, "Error opening document '%s'\n", pError ); - g_task_return_new_error(task, 0, 0, pError); - } - else - { - priv->m_pDocument->pClass->initializeForRendering(priv->m_pDocument); - priv->m_pDocument->pClass->registerCallback(priv->m_pDocument, callbackWorker, pDocView); - priv->m_pDocument->pClass->getDocumentSize(priv->m_pDocument, &priv->m_nDocumentWidthTwips, &priv->m_nDocumentHeightTwips); - g_timeout_add(600, handleTimeout, pDocView); - - float zoom = priv->m_fZoom; - long nDocumentWidthTwips = priv->m_nDocumentWidthTwips; - long nDocumentHeightTwips = priv->m_nDocumentHeightTwips; - long nDocumentWidthPixels = twipToPixel(nDocumentWidthTwips, zoom); - long nDocumentHeightPixels = twipToPixel(nDocumentHeightTwips, zoom); - // Total number of columns in this document. - guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels); - - - priv->m_aTileBuffer = TileBuffer(priv->m_pDocument, - nColumns); - gtk_widget_set_size_request(GTK_WIDGET(pDocView), - nDocumentWidthPixels, - nDocumentHeightPixels); - gtk_widget_set_can_focus(GTK_WIDGET(pDocView), TRUE); - gtk_widget_grab_focus(GTK_WIDGET(pDocView)); - g_task_return_boolean (task, true); - } -} /** * lok_doc_view_open_document: @@ -1492,15 +1660,13 @@ lok_doc_view_open_document (LOKDocView* pDocView, GAsyncReadyCallback callback, gpointer userdata) { - GTask *task; + GTask* task = g_task_new(pDocView, cancellable, callback, userdata); + LOEvent* pLOEvent = new LOEvent(LOK_LOAD_DOC, pPath); LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); priv->m_aDocPath = g_strdup(pPath); + g_task_set_task_data(task, pLOEvent, g_free); - task = g_task_new(pDocView, cancellable, callback, userdata); - // FIXME: Use source_tag to check the task. - //g_task_set_source_tag(task, lok_doc_view_open_document); - - g_task_run_in_thread(task, lok_doc_view_open_document_func); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); g_object_unref(task); } @@ -1572,8 +1738,13 @@ lok_doc_view_get_part (LOKDocView* pDocView) SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_part (LOKDocView* pDocView, int nPart) { - LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); - priv->m_pDocument->pClass->setPart( priv->m_pDocument, nPart ); + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_PART); + pLOEvent->m_nPart = nPart; + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); } SAL_DLLPUBLIC_EXPORT char* @@ -1587,8 +1758,13 @@ SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_partmode(LOKDocView* pDocView, int nPartMode) { - LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); - priv->m_pDocument->pClass->setPartMode( priv->m_pDocument, nPartMode ); + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_PARTMODE); + pLOEvent->m_nPartMode = nPartMode; + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); } SAL_DLLPUBLIC_EXPORT void @@ -1610,19 +1786,13 @@ SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_edit(LOKDocView* pDocView, gboolean bEdit) { - LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); - gboolean bWasEdit = priv->m_bEdit; + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_SET_EDIT); + pLOEvent->m_bEdit = bEdit; + g_task_set_task_data(task, pLOEvent, g_free); - if (!priv->m_bEdit && bEdit) - g_info("lok_doc_view_set_edit: entering edit mode"); - else if (priv->m_bEdit && !bEdit) - { - g_info("lok_doc_view_set_edit: leaving edit mode"); - priv->m_pDocument->pClass->resetSelection(priv->m_pDocument); - } - priv->m_bEdit = bEdit; - g_signal_emit(pDocView, doc_view_signals[EDIT_CHANGED], 0, bWasEdit); - gtk_widget_queue_draw(GTK_WIDGET(pDocView)); + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); } /** @@ -1648,11 +1818,16 @@ lok_doc_view_get_edit (LOKDocView* pDocView) */ SAL_DLLPUBLIC_EXPORT void lok_doc_view_post_command (LOKDocView* pDocView, - const char* pCommand, - const char* pArguments) + const gchar* pCommand, + const gchar* pArguments) { - LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); - priv->m_pDocument->pClass->postUnoCommand(priv->m_pDocument, pCommand, pArguments); + + GTask* task = g_task_new(pDocView, NULL, NULL, NULL); + LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND, pCommand, pArguments); + g_task_set_task_data(task, pLOEvent, g_free); + + g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL); + g_object_unref(task); } /** commit cb94e003c066033db96da62596022385794f281c Author: Pranav Kant <pran...@gnome.org> Date: Sat Jul 11 21:29:53 2015 +0530 gtktiledviewer: Fill whole statusbar with progressbar We don't have anything yet to put in statusbar. Let progressbar fill the whole width of statusbar for now. Change-Id: I4cd8745e997a0d2b917bc5baf358b097174d0df9 diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx index e8091a7..46d3176 100644 --- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx @@ -370,6 +370,11 @@ static void changePart( GtkWidget* pSelector, gpointer /* pItem */ ) } } +static void removeChildrenFromStatusbar(GtkWidget* children, gpointer) +{ + gtk_container_remove(GTK_CONTAINER(pStatusBar), children); +} + static void populatePartModeSelector( GtkComboBoxText* pSelector ) { gtk_combo_box_text_append_text( pSelector, "Standard" ); @@ -577,8 +582,10 @@ int main( int argc, char* argv[] ) g_signal_connect(pDocView, "load-changed", G_CALLBACK(loadChanged), pProgressBar); pStatusBar = gtk_statusbar_new (); + gtk_container_forall(GTK_CONTAINER(pStatusBar), removeChildrenFromStatusbar, NULL); gtk_container_add (GTK_CONTAINER(pVBox), pStatusBar); gtk_container_add (GTK_CONTAINER(pStatusBar), pProgressBar); + gtk_widget_set_hexpand(pProgressBar, true); gtk_widget_show_all( pWindow ); // Hide the findbar by default. commit da129b682f81a8fdbc6be95142456f204b2b7951 Author: Pranav Kant <pran...@gnome.org> Date: Tue Jul 7 21:16:45 2015 +0530 lokdocview: Emit load-changed signal showing load progress Change-Id: I69b4c05d12c0c0b2ca6b7d1ad76ed74cc1f4346a diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx index a208051..e8091a7 100644 --- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx @@ -30,6 +30,7 @@ static int help() } static GtkWidget* pDocView; +static GtkWidget* pStatusBar; static GtkToolItem* pEnableEditing; static GtkToolItem* pBold; static GtkToolItem* pItalic; @@ -286,6 +287,12 @@ static void signalCommand(LOKDocView* /*pLOKDocView*/, char* pPayload, gpointer } } +static void loadChanged(LOKDocView* /*pLOKDocView*/, gdouble fValue, gpointer pData) +{ + GtkWidget* pProgressBar = GTK_WIDGET (pData); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(pProgressBar), fValue); +} + /// LOKDocView found no search matches -> set the search label accordingly. static void signalSearch(LOKDocView* /*pLOKDocView*/, char* /*pPayload*/, gpointer /*pData*/) { @@ -403,6 +410,8 @@ static void openDocumentCallback (GObject* source_object, GAsyncResult* res, gpo focusChain = g_list_append( focusChain, pDocView1 ); gtk_container_set_focus_chain ( GTK_CONTAINER (pVBox), focusChain ); + + gtk_widget_hide (pStatusBar); } int main( int argc, char* argv[] ) @@ -555,6 +564,7 @@ int main( int argc, char* argv[] ) g_signal_connect(pDocView, "part-changed", G_CALLBACK(signalPart), NULL); g_signal_connect(pDocView, "hyperlink-clicked", G_CALLBACK(signalHyperlink), NULL); + // Scrolled window for DocView pScrolledWindow = gtk_scrolled_window_new(0, 0); gtk_widget_set_hexpand (pScrolledWindow, TRUE); @@ -563,6 +573,13 @@ int main( int argc, char* argv[] ) gtk_container_add(GTK_CONTAINER(pScrolledWindow), pDocView); + GtkWidget* pProgressBar = gtk_progress_bar_new (); + g_signal_connect(pDocView, "load-changed", G_CALLBACK(loadChanged), pProgressBar); + + pStatusBar = gtk_statusbar_new (); + gtk_container_add (GTK_CONTAINER(pVBox), pStatusBar); + gtk_container_add (GTK_CONTAINER(pStatusBar), pProgressBar); + gtk_widget_show_all( pWindow ); // Hide the findbar by default. gtk_widget_hide(pFindbar); diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index b6b00afd..5517dc4 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -40,7 +40,7 @@ struct _LOKDocViewPrivate { gchar* m_aLOPath; gchar* m_aDocPath; - guint m_nLoadProgress; + gdouble m_nLoadProgress; gboolean m_bIsLoading; gboolean m_bCanZoomIn; gboolean m_bCanZoomOut; @@ -108,6 +108,7 @@ struct _LOKDocViewPrivate enum { + LOAD_CHANGED, EDIT_CHANGED, COMMAND_CHANGED, SEARCH_NOT_FOUND, @@ -341,17 +342,20 @@ globalCallback (gpointer pData) { case LOK_CALLBACK_STATUS_INDICATOR_START: { - priv->m_nLoadProgress = 0; + priv->m_nLoadProgress = 0.0; + g_signal_emit (pCallback->m_pDocView, doc_view_signals[LOAD_CHANGED], 0, 0.0); } break; case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE: { - priv->m_nLoadProgress = std::stoi(pCallback->m_aPayload); + priv->m_nLoadProgress = static_cast<gdouble>(std::stoi(pCallback->m_aPayload)/100.0); + g_signal_emit (pCallback->m_pDocView, doc_view_signals[LOAD_CHANGED], 0, priv->m_nLoadProgress); } break; case LOK_CALLBACK_STATUS_INDICATOR_FINISH: { - priv->m_nLoadProgress = 100; + priv->m_nLoadProgress = 1.0; + g_signal_emit (pCallback->m_pDocView, doc_view_signals[LOAD_CHANGED], 0, 1.0); } break; default: @@ -1069,7 +1073,7 @@ static void lok_doc_view_get_property (GObject* object, guint propId, GValue *va g_value_set_boolean (value, priv->m_bEdit); break; case PROP_LOAD_PROGRESS: - g_value_set_uint (value, priv->m_nLoadProgress); + g_value_set_double (value, priv->m_nLoadProgress); break; case PROP_ZOOM: g_value_set_float (value, priv->m_fZoom); @@ -1210,11 +1214,11 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) */ g_object_class_install_property (pGObjectClass, PROP_LOAD_PROGRESS, - g_param_spec_int("load-progress", - "Estimated Load Progress", - "Whether the content is in edit mode or not", - 0, 100, 0, - G_PARAM_READABLE)); + g_param_spec_double("load-progress", + "Estimated Load Progress", + "Shows the progress of the document load operation", + 0.0, 1.0, 0.0, + G_PARAM_READABLE)); /** * LOKDocView:zoom-level: @@ -1300,6 +1304,21 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) | G_PARAM_STATIC_STRINGS))); /** + * LOKDocView::load-changed: + * @pDocView: the #LOKDocView on which the signal is emitted + * @fLoadProgress: the new progress value + */ + doc_view_signals[LOAD_CHANGED] = + g_signal_new("load-changed", + G_TYPE_FROM_CLASS (pGObjectClass), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, + G_TYPE_DOUBLE); + + /** * LOKDocView::edit-changed: * @pDocView: the #LOKDocView on which the signal is emitted * @bEdit: the new edit value of the view @@ -1403,16 +1422,16 @@ lok_doc_view_open_document_finish (LOKDocView* pDocView, GAsyncResult* res, GErr { GTask* task = G_TASK(res); - g_return_val_if_fail(g_task_is_valid(res, pDocView), NULL); + g_return_val_if_fail(g_task_is_valid(res, pDocView), false); //FIXME: make source_tag workx //g_return_val_if_fail(g_task_get_source_tag(task) == lok_doc_view_open_document, NULL); - g_return_val_if_fail(error == NULL || *error == NULL, NULL); + g_return_val_if_fail(error == NULL || *error == NULL, false); return g_task_propagate_boolean(task, error); } static void -lok_doc_view_open_document_func (GTask* task, gpointer source_object, gpointer task_data, GCancellable* cancellable) +lok_doc_view_open_document_func (GTask* task, gpointer source_object, gpointer /*task_data*/, GCancellable* /*cancellable*/) { LOKDocView* pDocView = LOK_DOC_VIEW(source_object); LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); commit 645f00543405450cd3a3862482dc4e1cda65d098 Author: Pranav Kant <pran...@gnome.org> Date: Mon Jul 6 22:01:30 2015 +0530 lokdocview: Call open_document in another thread This is to keep the widget responsive during document load. Change-Id: I81acaffc75ca7deddd6cc2de6abae22d009d40cd diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h index b98a856..3f56f08 100644 --- a/include/LibreOfficeKit/LibreOfficeKitGtk.h +++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h @@ -45,8 +45,15 @@ GtkWidget* lok_doc_view_new (const gchar* GCancellable *cancellable, GError **error); -gboolean lok_doc_view_open_document (LOKDocView* pDocView, - const gchar* pPath); +void lok_doc_view_open_document (LOKDocView* pDocView, + const gchar* pPath, + GCancellable* cancellable, + GAsyncReadyCallback callback, + gpointer userdata); + +gboolean lok_doc_view_open_document_finish (LOKDocView* pDocView, + GAsyncResult* res, + GError** error); /// Gets the document the viewer displays. LibreOfficeKitDocument* lok_doc_view_get_document (LOKDocView* pDocView); diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx index 6c0de39..a208051 100644 --- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx +++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx @@ -41,6 +41,7 @@ std::map<std::string, GtkToolItem*> g_aCommandNameToolItems; bool g_bToolItemBroadcast = true; static GtkWidget* pVBox; static GtkComboBoxText* pPartSelector; +static GtkWidget* pPartModeComboBox; /// Should the part selector avoid calling lok::Document::setPart()? static bool g_bPartSelectorBroadcast = true; GtkWidget* pFindbar; @@ -291,6 +292,7 @@ static void signalSearch(LOKDocView* /*pLOKDocView*/, char* /*pPayload*/, gpoint gtk_label_set_text(GTK_LABEL(pFindbarLabel), "Search key not found"); } + static void signalPart(LOKDocView* /*pLOKDocView*/, int nPart, gpointer /*pData*/) { g_bPartSelectorBroadcast = false; @@ -381,6 +383,28 @@ static void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ ) } } +static void openDocumentCallback (GObject* source_object, GAsyncResult* res, gpointer /*userdata*/) +{ + LOKDocView* pDocView1 = LOK_DOC_VIEW (source_object); + GError* error = NULL; + GList *focusChain = NULL; + + if (!lok_doc_view_open_document_finish(pDocView1, res, &error)) + { + g_warning ("Error occurred while opening the document : %s", error->message); + g_error_free (error); + } + + populatePartSelector(); + populatePartModeSelector( GTK_COMBO_BOX_TEXT(pPartModeComboBox) ); + // Connect these signals after populating the selectors, to avoid re-rendering on setting the default part/partmode. + g_signal_connect(G_OBJECT(pPartModeComboBox), "changed", G_CALLBACK(changePartMode), 0); + g_signal_connect(G_OBJECT(pPartSelector), "changed", G_CALLBACK(changePart), 0); + + focusChain = g_list_append( focusChain, pDocView1 ); + gtk_container_set_focus_chain ( GTK_CONTAINER (pVBox), focusChain ); +} + int main( int argc, char* argv[] ) { if( argc < 3 || @@ -436,7 +460,7 @@ int main( int argc, char* argv[] ) gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator2, -1); GtkToolItem* pPartModeSelectorToolItem = gtk_tool_item_new(); - GtkWidget* pPartModeComboBox = gtk_combo_box_text_new(); + pPartModeComboBox = gtk_combo_box_text_new(); gtk_container_add( GTK_CONTAINER(pPartModeSelectorToolItem), pPartModeComboBox ); gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pPartModeSelectorToolItem, -1 ); @@ -543,21 +567,7 @@ int main( int argc, char* argv[] ) // Hide the findbar by default. gtk_widget_hide(pFindbar); - int bOpened = lok_doc_view_open_document( LOK_DOC_VIEW(pDocView), argv[2] ); - if (!bOpened) - g_error("main: lok_doc_view_open_document() failed"); - assert(lok_doc_view_get_document(LOK_DOC_VIEW(pDocView))); - - populatePartSelector(); - populatePartModeSelector( GTK_COMBO_BOX_TEXT(pPartModeComboBox) ); - // Connect these signals after populating the selectors, to avoid re-rendering on setting the default part/partmode. - g_signal_connect(G_OBJECT(pPartModeComboBox), "changed", G_CALLBACK(changePartMode), 0); - g_signal_connect(G_OBJECT(pPartSelector), "changed", G_CALLBACK(changePart), 0); - - // Make only LOKDocView widget as focussable - GList *focusChain = NULL; - focusChain = g_list_append( focusChain, pDocView ); - gtk_container_set_focus_chain ( GTK_CONTAINER (pVBox), focusChain ); + lok_doc_view_open_document( LOK_DOC_VIEW(pDocView), argv[2], NULL, openDocumentCallback, pDocView ); gtk_main(); diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx index 3823e94..b6b00afd 100644 --- a/libreofficekit/source/gtk/lokdocview.cxx +++ b/libreofficekit/source/gtk/lokdocview.cxx @@ -108,8 +108,6 @@ struct _LOKDocViewPrivate enum { - LOAD_CHANGED, - LOAD_FAILED, EDIT_CHANGED, COMMAND_CHANGED, SEARCH_NOT_FOUND, @@ -337,19 +335,23 @@ static gboolean globalCallback (gpointer pData) { CallbackData* pCallback = static_cast<CallbackData*>(pData); + LOKDocViewPrivate* priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pCallback->m_pDocView)); switch (pCallback->m_nType) { case LOK_CALLBACK_STATUS_INDICATOR_START: { + priv->m_nLoadProgress = 0; } break; case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE: { + priv->m_nLoadProgress = std::stoi(pCallback->m_aPayload); } break; case LOK_CALLBACK_STATUS_INDICATOR_FINISH: { + priv->m_nLoadProgress = 100; } break; default: @@ -1389,15 +1391,30 @@ lok_doc_view_new (const gchar* pPath, GCancellable *cancellable, GError **error) } /** - * lok_doc_view_open_document: + * lok_doc_view_open_document_finish: * @pDocView: The #LOKDocView instance - * @pPath: The path of the document that #LOKDocView widget should try to open + * @res: + * @error: * * Returns: %TRUE if the document is loaded succesfully, %FALSE otherwise */ SAL_DLLPUBLIC_EXPORT gboolean -lok_doc_view_open_document (LOKDocView* pDocView, const gchar* pPath) +lok_doc_view_open_document_finish (LOKDocView* pDocView, GAsyncResult* res, GError** error) +{ + GTask* task = G_TASK(res); + + g_return_val_if_fail(g_task_is_valid(res, pDocView), NULL); + //FIXME: make source_tag workx + //g_return_val_if_fail(g_task_get_source_tag(task) == lok_doc_view_open_document, NULL); + g_return_val_if_fail(error == NULL || *error == NULL, NULL); + + return g_task_propagate_boolean(task, error); +} + +static void +lok_doc_view_open_document_func (GTask* task, gpointer source_object, gpointer task_data, GCancellable* cancellable) { + LOKDocView* pDocView = LOK_DOC_VIEW(source_object); LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); if ( priv->m_pDocument ) @@ -1407,13 +1424,13 @@ lok_doc_view_open_document (LOKDocView* pDocView, const gchar* pPath) } priv->m_pOffice->pClass->registerCallback(priv->m_pOffice, globalCallbackWorker, pDocView); - priv->m_pDocument = priv->m_pOffice->pClass->documentLoad( priv->m_pOffice, pPath ); + priv->m_pDocument = priv->m_pOffice->pClass->documentLoad( priv->m_pOffice, priv->m_aDocPath ); if ( !priv->m_pDocument ) { // FIXME: should have a GError parameter and populate it. char *pError = priv->m_pOffice->pClass->getError( priv->m_pOffice ); fprintf( stderr, "Error opening document '%s'\n", pError ); - return FALSE; + g_task_return_new_error(task, 0, 0, pError); } else { @@ -1438,8 +1455,34 @@ lok_doc_view_open_document (LOKDocView* pDocView, const gchar* pPath) nDocumentHeightPixels); gtk_widget_set_can_focus(GTK_WIDGET(pDocView), TRUE); gtk_widget_grab_focus(GTK_WIDGET(pDocView)); + g_task_return_boolean (task, true); } - return TRUE; +} + +/** + * lok_doc_view_open_document: + * @pDocView: The #LOKDocView instance + * @pPath: The path of the document that #LOKDocView widget should try to open + * + * Returns: %TRUE if the document is loaded succesfully, %FALSE otherwise + */ +SAL_DLLPUBLIC_EXPORT void +lok_doc_view_open_document (LOKDocView* pDocView, + const gchar* pPath, + GCancellable* cancellable, + GAsyncReadyCallback callback, + gpointer userdata) +{ + GTask *task; + LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView)); + priv->m_aDocPath = g_strdup(pPath); + + task = g_task_new(pDocView, cancellable, callback, userdata); + // FIXME: Use source_tag to check the task. + //g_task_set_source_tag(task, lok_doc_view_open_document); + + g_task_run_in_thread(task, lok_doc_view_open_document_func); + g_object_unref(task); } /** _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits