From 9a1935211b00cd5e47d9c2b075dcc8635409863b Mon Sep 17 00:00:00 2001 From: David Tardon Date: Wed, 9 Dec 2015 14:23:52 +0100 Subject: [PATCH] add more LOKDevView related fixes --- ...16-Decouple-view-only-editable-modes.patch | 406 ++++++++++++++++++ 0002-tdf-96318-Add-searching-API.patch | 295 +++++++++++++ ...view-Set-a-default-path-for-LOK-init.patch | 64 +++ libreoffice.spec | 3 + 4 files changed, 768 insertions(+) create mode 100644 0001-tdf-96316-Decouple-view-only-editable-modes.patch create mode 100644 0002-tdf-96318-Add-searching-API.patch create mode 100644 0003-lokdocview-Set-a-default-path-for-LOK-init.patch diff --git a/0001-tdf-96316-Decouple-view-only-editable-modes.patch b/0001-tdf-96316-Decouple-view-only-editable-modes.patch new file mode 100644 index 0000000..e9129e5 --- /dev/null +++ b/0001-tdf-96316-Decouple-view-only-editable-modes.patch @@ -0,0 +1,406 @@ +From 0a28049853ce84aa8ef4f871065970c1220ae855 Mon Sep 17 00:00:00 2001 +From: Pranav Kant +Date: Wed, 9 Dec 2015 01:03:02 +0530 +Subject: [PATCH 1/3] tdf#96316: Decouple view-only/editable modes + +- Move text selection and graphic selection tasks into functions +- Merge GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE conditional code +- Do not change to 'move' cursor in view-only mode +- Ignore LOK_POST_COMMAND, LOK_SET_GRAPHIC_SELECTION in view-only + +As a consequence this commit also allows dragging handles during text +selection in view-only mode which was earlier not possible. + +Change-Id: Iffb668d5447dd646a1e40237dee8d8d3fa3314b6 +Reviewed-on: https://gerrit.libreoffice.org/20487 +Reviewed-by: David Tardon +Tested-by: David Tardon +(cherry picked from commit b3bfc26d0863b074bb990725718f2ab23d05425d) +--- + libreofficekit/source/gtk/lokdocview.cxx | 312 ++++++++++++++++++------------- + 1 file changed, 180 insertions(+), 132 deletions(-) + +diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx +index c808752..cbdac71 100644 +--- a/libreofficekit/source/gtk/lokdocview.cxx ++++ b/libreofficekit/source/gtk/lokdocview.cxx +@@ -312,6 +312,153 @@ isEmptyRectangle(const GdkRectangle& rRectangle) + return rRectangle.x == 0 && rRectangle.y == 0 && rRectangle.width == 0 && rRectangle.height == 0; + } + ++/// if handled, returns TRUE else FALSE ++static bool ++handleTextSelectionOnButtonPress(GdkRectangle& aClick, LOKDocView* pDocView) { ++ LOKDocViewPrivate& priv = getPrivate(pDocView); ++ ++ if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleStartRect, nullptr)) ++ { ++ g_info("LOKDocView_Impl::signalButton: start of drag start handle"); ++ priv->m_bInDragStartHandle = true; ++ return TRUE; ++ } ++ else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleMiddleRect, nullptr)) ++ { ++ g_info("LOKDocView_Impl::signalButton: start of drag middle handle"); ++ priv->m_bInDragMiddleHandle = true; ++ return TRUE; ++ } ++ else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleEndRect, nullptr)) ++ { ++ g_info("LOKDocView_Impl::signalButton: start of drag end handle"); ++ priv->m_bInDragEndHandle = true; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/// if handled, returns TRUE else FALSE ++static bool ++handleGraphicSelectionOnButtonPress(GdkRectangle& aClick, LOKDocView* pDocView) { ++ LOKDocViewPrivate& priv = getPrivate(pDocView); ++ GError* error = nullptr; ++ ++ for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i) ++ { ++ if (gdk_rectangle_intersect(&aClick, &priv->m_aGraphicHandleRects[i], nullptr)) ++ { ++ g_info("LOKDocView_Impl::signalButton: start of drag graphic handle #%d", i); ++ priv->m_bInDragGraphicHandles[i] = true; ++ ++ GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); ++ 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, LOEvent::destroy); ++ ++ g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); ++ if (error != nullptr) ++ { ++ g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message); ++ g_clear_error(&error); ++ } ++ g_object_unref(task); ++ ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++/// if handled, returns TRUE else FALSE ++static bool ++handleTextSelectionOnButtonRelease(LOKDocView* pDocView) { ++ LOKDocViewPrivate& priv = getPrivate(pDocView); ++ ++ if (priv->m_bInDragStartHandle) ++ { ++ g_info("LOKDocView_Impl::signalButton: end of drag start handle"); ++ priv->m_bInDragStartHandle = false; ++ return TRUE; ++ } ++ else if (priv->m_bInDragMiddleHandle) ++ { ++ g_info("LOKDocView_Impl::signalButton: end of drag middle handle"); ++ priv->m_bInDragMiddleHandle = false; ++ return TRUE; ++ } ++ else if (priv->m_bInDragEndHandle) ++ { ++ g_info("LOKDocView_Impl::signalButton: end of drag end handle"); ++ priv->m_bInDragEndHandle = false; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/// if handled, returns TRUE else FALSE ++static bool ++handleGraphicSelectionOnButtonRelease(LOKDocView* pDocView, GdkEventButton* pEvent) { ++ LOKDocViewPrivate& priv = getPrivate(pDocView); ++ GError* error = nullptr; ++ ++ for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i) ++ { ++ if (priv->m_bInDragGraphicHandles[i]) ++ { ++ g_info("LOKDocView_Impl::signalButton: end of drag graphic handle #%d", i); ++ priv->m_bInDragGraphicHandles[i] = false; ++ ++ GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); ++ 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, LOEvent::destroy); ++ ++ g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); ++ if (error != nullptr) ++ { ++ g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message); ++ g_clear_error(&error); ++ } ++ g_object_unref(task); ++ ++ return TRUE; ++ } ++ } ++ ++ if (priv->m_bInDragGraphicSelection) ++ { ++ g_info("LOKDocView_Impl::signalButton: end of drag graphic selection"); ++ priv->m_bInDragGraphicSelection = false; ++ ++ GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); ++ 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, LOEvent::destroy); ++ ++ g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); ++ if (error != nullptr) ++ { ++ g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message); ++ g_clear_error(&error); ++ } ++ g_object_unref(task); ++ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ + static void + postKeyEventInThread(gpointer data) + { +@@ -747,11 +894,17 @@ callback (gpointer pData) + break; + case LOK_CALLBACK_MOUSE_POINTER: + { +- // The gtk docs claim that most css cursors should be supported, however +- // on my system at least this is not true and many cursors are unsupported. +- // In this case pCursor = null, which results in the default cursor being set. +- GdkCursor* pCursor = gdk_cursor_new_from_name(gtk_widget_get_display(GTK_WIDGET(pDocView)), pCallback->m_aPayload.c_str()); +- gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(pDocView)), pCursor); ++ // We do not want the cursor to get changed in view-only mode ++ if (priv->m_bEdit) ++ { ++ // The gtk docs claim that most css cursors should be supported, however ++ // on my system at least this is not true and many cursors are unsupported. ++ // In this case pCursor = null, which results in the default cursor ++ // being set. ++ GdkCursor* pCursor = gdk_cursor_new_from_name(gtk_widget_get_display(GTK_WIDGET(pDocView)), ++ pCallback->m_aPayload.c_str()); ++ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(pDocView)), pCursor); ++ } + } + break; + case LOK_CALLBACK_GRAPHIC_SELECTION: +@@ -1176,140 +1329,21 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) + (int)pixelToTwip(pEvent->y, priv->m_fZoom)); + gtk_widget_grab_focus(GTK_WIDGET(pDocView)); + +- if (pEvent->type == GDK_BUTTON_RELEASE) ++ switch (pEvent->type) + { +- if (priv->m_bInDragStartHandle) +- { +- g_info("LOKDocView_Impl::signalButton: end of drag start handle"); +- priv->m_bInDragStartHandle = false; +- return FALSE; +- } +- else if (priv->m_bInDragMiddleHandle) +- { +- g_info("LOKDocView_Impl::signalButton: end of drag middle handle"); +- priv->m_bInDragMiddleHandle = false; +- return FALSE; +- } +- else if (priv->m_bInDragEndHandle) +- { +- g_info("LOKDocView_Impl::signalButton: end of drag end handle"); +- priv->m_bInDragEndHandle = false; +- return FALSE; +- } +- +- for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i) +- { +- if (priv->m_bInDragGraphicHandles[i]) +- { +- g_info("LOKDocView_Impl::signalButton: end of drag graphic handle #%d", i); +- priv->m_bInDragGraphicHandles[i] = false; +- +- GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); +- 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, LOEvent::destroy); +- +- g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); +- if (error != nullptr) +- { +- g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message); +- g_clear_error(&error); +- } +- g_object_unref(task); +- +- return FALSE; +- } +- } +- +- if (priv->m_bInDragGraphicSelection) +- { +- g_info("LOKDocView_Impl::signalButton: end of drag graphic selection"); +- priv->m_bInDragGraphicSelection = false; +- +- GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); +- 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, LOEvent::destroy); +- +- g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); +- if (error != nullptr) +- { +- g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message); +- g_clear_error(&error); +- } +- g_object_unref(task); +- +- return FALSE; +- } +- } +- +- if (priv->m_bEdit) ++ case GDK_BUTTON_PRESS: + { + GdkRectangle aClick; + aClick.x = pEvent->x; + aClick.y = pEvent->y; + aClick.width = 1; + aClick.height = 1; +- if (pEvent->type == GDK_BUTTON_PRESS) +- { +- if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleStartRect, nullptr)) +- { +- g_info("LOKDocView_Impl::signalButton: start of drag start handle"); +- priv->m_bInDragStartHandle = true; +- return FALSE; +- } +- else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleMiddleRect, nullptr)) +- { +- g_info("LOKDocView_Impl::signalButton: start of drag middle handle"); +- priv->m_bInDragMiddleHandle = true; +- return FALSE; +- } +- else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleEndRect, nullptr)) +- { +- g_info("LOKDocView_Impl::signalButton: start of drag end handle"); +- priv->m_bInDragEndHandle = true; +- return FALSE; +- } + +- for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i) +- { +- if (gdk_rectangle_intersect(&aClick, &priv->m_aGraphicHandleRects[i], nullptr)) +- { +- g_info("LOKDocView_Impl::signalButton: start of drag graphic handle #%d", i); +- priv->m_bInDragGraphicHandles[i] = true; +- +- GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); +- 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, LOEvent::destroy); +- +- g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); +- if (error != nullptr) +- { +- g_warning("Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message); +- g_clear_error(&error); +- } +- g_object_unref(task); +- +- return FALSE; +- } +- } +- } +- } +- +- if (!priv->m_bEdit) +- lok_doc_view_set_edit(pDocView, TRUE); ++ if (handleTextSelectionOnButtonPress(aClick, pDocView)) ++ return FALSE; ++ if (handleGraphicSelectionOnButtonPress(aClick, pDocView)) ++ return FALSE; + +- switch (pEvent->type) +- { +- case GDK_BUTTON_PRESS: +- { + int nCount = 1; + if ((pEvent->time - priv->m_nLastButtonPressTime) < 250) + nCount++; +@@ -1347,6 +1381,11 @@ lok_doc_view_signal_button(GtkWidget* pWidget, GdkEventButton* pEvent) + } + case GDK_BUTTON_RELEASE: + { ++ if (handleTextSelectionOnButtonRelease(pDocView)) ++ return FALSE; ++ if (handleGraphicSelectionOnButtonRelease(pDocView, pEvent)) ++ return FALSE; ++ + int nCount = 1; + if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250) + nCount++; +@@ -1722,6 +1761,8 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) + { + GTask* task = G_TASK(data); + LOEvent* pLOEvent = static_cast(g_task_get_task_data(task)); ++ LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task)); ++ LOKDocViewPrivate& priv = getPrivate(pDocView); + + switch (pLOEvent->m_nType) + { +@@ -1729,7 +1770,10 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) + openDocumentInThread(task); + break; + case LOK_POST_COMMAND: +- postCommandInThread(task); ++ if (priv->m_bEdit) ++ postCommandInThread(task); ++ else ++ g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode"); + break; + case LOK_SET_EDIT: + setEditInThread(task); +@@ -1741,6 +1785,7 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) + setPartmodeInThread(task); + break; + case LOK_POST_KEY: ++ // view-only/editable mode already checked during signal key signal emission + postKeyEventInThread(task); + break; + case LOK_PAINT_TILE: +@@ -1750,7 +1795,10 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) + postMouseEventInThread(task); + break; + case LOK_SET_GRAPHIC_SELECTION: +- setGraphicSelectionInThread(task); ++ if (priv->m_bEdit) ++ setGraphicSelectionInThread(task); ++ else ++ g_info ("LOK_SET_GRAPHIC_SELECTION: skipping graphical operation in view-only mode"); + break; + case LOK_SET_CLIENT_ZOOM: + setClientZoomInThread(task); +-- +2.5.0 + diff --git a/0002-tdf-96318-Add-searching-API.patch b/0002-tdf-96318-Add-searching-API.patch new file mode 100644 index 0000000..2edf6ed --- /dev/null +++ b/0002-tdf-96318-Add-searching-API.patch @@ -0,0 +1,295 @@ +From e7cdd6803485bbe4cfe27f5f466b427823318334 Mon Sep 17 00:00:00 2001 +From: Pranav Kant +Date: Wed, 9 Dec 2015 10:33:05 +0530 +Subject: [PATCH 2/3] tdf#96318: Add searching API + +Clients should now use these APIs to search for text in the +widget, rather than executing UNO commands directly on the +widget. This allows searching for text in the widget in view-only +mode too. + +Change-Id: I013b6f96e69a634ec33367394d39c0f645a4994d +Reviewed-on: https://gerrit.libreoffice.org/20488 +Tested-by: Jenkins +Reviewed-by: David Tardon +(cherry picked from commit 0f64cf72ff3b930e306e937bb18f4cbe55a8026a) +--- + include/LibreOfficeKit/LibreOfficeKitGtk.h | 38 ++++++++ + .../qa/gtktiledviewer/gtktiledviewer.cxx | 46 +++------ + libreofficekit/source/gtk/lokdocview.cxx | 107 +++++++++++++++++---- + 3 files changed, 139 insertions(+), 52 deletions(-) + +diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h +index 8b6092c..b2f17f1 100644 +--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h ++++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h +@@ -195,6 +195,44 @@ void lok_doc_view_post_command (LOKDocView* + const gchar* pArguments, + gboolean bNotifyWhenFinished); + ++ ++/** ++ * lok_doc_view_find_next: ++ * @pDocView: The #LOKDocView instance ++ * @pText: text to search for ++ * @bHighlightAll: Whether all the matches should be highlighted or not ++ * ++ * Highlights the next matching text in the view. `search-not-found` signal will ++ * be emitted when no search is found ++ */ ++void lok_doc_view_find_next (LOKDocView* pDocView, ++ const gchar* pText, ++ gboolean bHighlightAll); ++ ++/** ++ * lok_doc_view_find_prev: ++ * @pDocView: The #LOKDocView instance ++ * @pText: text to search for ++ * @bHighlightAll: Whether all the matches should be highlighted or not ++ * ++ * Highlights the previous matching text in the view. `search-not-found` signal ++ * will be emitted when no search is found ++ */ ++void lok_doc_view_find_prev (LOKDocView* pDocView, ++ const gchar* pText, ++ gboolean bHighlightAll); ++ ++/** ++ * lok_doc_view_highlight_all: ++ * @pDocView: The #LOKDocView instance ++ * @pText: text to search for ++ * ++ * Highlights all matching texts in the view. `search-not-found` signal ++ * will be emitted when no search is found ++ */ ++void lok_doc_view_highlight_all (LOKDocView* pDocView, ++ const gchar* pText); ++ + /** + * lok_doc_view_pixel_to_twip: + * @pDocView: The #LOKDocView instance +diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx +index 77021bf..ac04833 100644 +--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx ++++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx +@@ -439,7 +439,11 @@ static void toggleEditing(GtkWidget* pButton, gpointer /*pItem*/) + static void toggleFindAll(GtkWidget* pButton, gpointer /*pItem*/) + { + TiledWindow& rWindow = lcl_getTiledWindow(pButton); ++ GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry); ++ const char* pText = gtk_entry_get_text(pEntry); ++ + rWindow.m_bFindAll = !rWindow.m_bFindAll; ++ lok_doc_view_highlight_all(LOK_DOC_VIEW(rWindow.m_pDocView), pText); + } + + /// Toggle the visibility of the findbar. +@@ -598,48 +602,24 @@ static void doPaste(GtkWidget* pButton, gpointer /*pItem*/) + pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", pText, strlen(pText)); + } + +-/// Searches for the next or previous text of TiledWindow::m_pFindbarEntry. +-static void doSearch(GtkWidget* pButton, bool bBackwards) ++/// Click handler for the search next button. ++static void signalSearchNext(GtkWidget* pButton, gpointer /*pItem*/) + { + TiledWindow& rWindow = lcl_getTiledWindow(pButton); + GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry); + const char* pText = gtk_entry_get_text(pEntry); +- boost::property_tree::ptree aTree; +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/type", '/'), "string"); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/value", '/'), pText); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/type", '/'), "boolean"); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/value", '/'), bBackwards); +- if (rWindow.m_bFindAll) +- { +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/type", '/'), "unsigned short"); +- // SvxSearchCmd::FIND_ALL +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/value", '/'), "1"); +- } +- +- LOKDocView* pLOKDocView = LOK_DOC_VIEW(rWindow.m_pDocView); +- GdkRectangle aArea; +- getVisibleAreaTwips(rWindow.m_pDocView, &aArea); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/type", '/'), "long"); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/value", '/'), aArea.x); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/type", '/'), "long"); +- aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/value", '/'), aArea.y); +- +- std::stringstream aStream; +- boost::property_tree::write_json(aStream, aTree); + +- lok_doc_view_post_command(pLOKDocView, ".uno:ExecuteSearch", aStream.str().c_str(), false); +-} +- +-/// Click handler for the search next button. +-static void signalSearchNext(GtkWidget* pButton, gpointer /*pItem*/) +-{ +- doSearch(pButton, /*bBackwards=*/false); ++ lok_doc_view_find_next(LOK_DOC_VIEW(rWindow.m_pDocView), pText, rWindow.m_bFindAll); + } + + /// Click handler for the search previous button. + static void signalSearchPrev(GtkWidget* pButton, gpointer /*pItem*/) + { +- doSearch(pButton, /*bBackwards=*/true); ++ TiledWindow& rWindow = lcl_getTiledWindow(pButton); ++ GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry); ++ const char* pText = gtk_entry_get_text(pEntry); ++ ++ lok_doc_view_find_prev(LOK_DOC_VIEW(rWindow.m_pDocView), pText, rWindow.m_bFindAll); + } + + /// Handles the key-press-event of the search entry widget. +@@ -652,7 +632,7 @@ static gboolean signalFindbar(GtkWidget* pWidget, GdkEventKey* pEvent, gpointer + case GDK_KEY_Return: + { + // Search forward. +- doSearch(pWidget, /*bBackwards=*/false); ++ signalSearchNext(pWidget, nullptr); + return TRUE; + } + case GDK_KEY_Escape: +diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx +index cbdac71..488abc0 100644 +--- a/libreofficekit/source/gtk/lokdocview.cxx ++++ b/libreofficekit/source/gtk/lokdocview.cxx +@@ -306,6 +306,67 @@ callbackTypeToString (int nType) + return nullptr; + } + ++static void ++LOKPostCommand (LOKDocView* pDocView, ++ const gchar* pCommand, ++ const gchar* pArguments, ++ gboolean bNotifyWhenFinished) ++{ ++ LOKDocViewPrivate& priv = getPrivate(pDocView); ++ GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); ++ LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND); ++ GError* error = nullptr; ++ pLOEvent->m_pCommand = pCommand; ++ pLOEvent->m_pArguments = g_strdup(pArguments); ++ pLOEvent->m_bNotifyWhenFinished = bNotifyWhenFinished; ++ ++ g_task_set_task_data(task, pLOEvent, LOEvent::destroy); ++ g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); ++ if (error != nullptr) ++ { ++ g_warning("Unable to call LOK_POST_COMMAND: %s", error->message); ++ g_clear_error(&error); ++ } ++ g_object_unref(task); ++} ++ ++static void ++doSearch(LOKDocView* pDocView, const char* pText, bool bBackwards, bool highlightAll) ++{ ++ LOKDocViewPrivate& priv = getPrivate(pDocView); ++ boost::property_tree::ptree aTree; ++ GtkWidget* drawingWidget = GTK_WIDGET(pDocView); ++ GdkWindow* drawingWindow = gtk_widget_get_window(drawingWidget); ++ cairo_region_t* cairoVisRegion = gdk_window_get_visible_region(drawingWindow); ++ cairo_rectangle_int_t cairoVisRect; ++ int x, y; ++ ++ cairo_region_get_rectangle(cairoVisRegion, 0, &cairoVisRect); ++ x = pixelToTwip (cairoVisRect.x, priv->m_fZoom); ++ y = pixelToTwip (cairoVisRect.y, priv->m_fZoom); ++ ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/type", '/'), "string"); ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/value", '/'), pText); ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/type", '/'), "boolean"); ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/value", '/'), bBackwards); ++ if (highlightAll) ++ { ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/type", '/'), "unsigned short"); ++ // SvxSearchCmd::FIND_ALL ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/value", '/'), "1"); ++ } ++ ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/type", '/'), "long"); ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/value", '/'), x); ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/type", '/'), "long"); ++ aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/value", '/'), y); ++ ++ std::stringstream aStream; ++ boost::property_tree::write_json(aStream, aTree); ++ ++ LOKPostCommand (pDocView, ".uno:ExecuteSearch", aStream.str().c_str(), false); ++} ++ + static bool + isEmptyRectangle(const GdkRectangle& rRectangle) + { +@@ -1770,10 +1831,7 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) + openDocumentInThread(task); + break; + case LOK_POST_COMMAND: +- if (priv->m_bEdit) +- postCommandInThread(task); +- else +- g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode"); ++ postCommandInThread(task); + break; + case LOK_SET_EDIT: + setEditInThread(task); +@@ -2575,7 +2633,6 @@ lok_doc_view_get_edit (LOKDocView* pDocView) + return priv->m_bEdit; + } + +- + SAL_DLLPUBLIC_EXPORT void + lok_doc_view_post_command (LOKDocView* pDocView, + const gchar* pCommand, +@@ -2583,21 +2640,33 @@ lok_doc_view_post_command (LOKDocView* pDocView, + gboolean bNotifyWhenFinished) + { + LOKDocViewPrivate& priv = getPrivate(pDocView); +- GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); +- LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND); +- GError* error = nullptr; +- pLOEvent->m_pCommand = pCommand; +- pLOEvent->m_pArguments = g_strdup(pArguments); +- pLOEvent->m_bNotifyWhenFinished = bNotifyWhenFinished; ++ if (priv->m_bEdit) ++ LOKPostCommand(pDocView, pCommand, pArguments, bNotifyWhenFinished); ++ else ++ g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode"); ++} + +- g_task_set_task_data(task, pLOEvent, LOEvent::destroy); +- g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); +- if (error != nullptr) +- { +- g_warning("Unable to call LOK_POST_COMMAND: %s", error->message); +- g_clear_error(&error); +- } +- g_object_unref(task); ++SAL_DLLPUBLIC_EXPORT void ++lok_doc_view_find_prev (LOKDocView* pDocView, ++ const gchar* pText, ++ gboolean bHighlightAll) ++{ ++ doSearch(pDocView, pText, true, bHighlightAll); ++} ++ ++SAL_DLLPUBLIC_EXPORT void ++lok_doc_view_find_next (LOKDocView* pDocView, ++ const gchar* pText, ++ gboolean bHighlightAll) ++{ ++ doSearch(pDocView, pText, false, bHighlightAll); ++} ++ ++SAL_DLLPUBLIC_EXPORT void ++lok_doc_view_highlight_all (LOKDocView* pDocView, ++ const gchar* pText) ++{ ++ doSearch(pDocView, pText, false, true); + } + + SAL_DLLPUBLIC_EXPORT float +-- +2.5.0 + diff --git a/0003-lokdocview-Set-a-default-path-for-LOK-init.patch b/0003-lokdocview-Set-a-default-path-for-LOK-init.patch new file mode 100644 index 0000000..d0d4890 --- /dev/null +++ b/0003-lokdocview-Set-a-default-path-for-LOK-init.patch @@ -0,0 +1,64 @@ +From dabfa0ce06f605fd0e8de32774b6385fd6ffbd56 Mon Sep 17 00:00:00 2001 +From: Pranav Kant +Date: Tue, 8 Dec 2015 23:14:25 +0530 +Subject: [PATCH 3/3] lokdocview: Set a 'default' path for LOK init + +When passed NULL to lok_doc_view_new, use the default path : +$libdir/libreoffice/program as LOK install path + +Change-Id: I1e033c407184b29b1509cfb8c416b514591d67ce +Reviewed-on: https://gerrit.libreoffice.org/20476 +Tested-by: Jenkins +Reviewed-by: David Tardon +(cherry picked from commit 424c09b10d3d6ba6edfed2dcf560d5ce2c950b9d) +--- + include/LibreOfficeKit/LibreOfficeKitGtk.h | 3 ++- + libreofficekit/Library_libreofficekitgtk.mk | 4 ++++ + libreofficekit/source/gtk/lokdocview.cxx | 2 +- + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h +index b2f17f1..1b03e46 100644 +--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h ++++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h +@@ -42,7 +42,8 @@ GType lok_doc_view_get_type (void) G_GNUC + + /** + * lok_doc_view_new: +- * @pPath: LibreOffice install path. ++ * @pPath: (nullable): LibreOffice install path. Pass null to set it to default ++ * path which in most cases would be $libdir/libreoffice/program + * @cancellable: The cancellable object that you can use to cancel this + * operation. + * @error: The error that will be set if the object fails to initialize. +diff --git a/libreofficekit/Library_libreofficekitgtk.mk b/libreofficekit/Library_libreofficekitgtk.mk +index 3eba939..fc62e72 100644 +--- a/libreofficekit/Library_libreofficekitgtk.mk ++++ b/libreofficekit/Library_libreofficekitgtk.mk +@@ -28,6 +28,10 @@ $(eval $(call gb_Library_add_libs,libreofficekitgtk,\ + $(GTK3_LIBS) \ + )) + ++$(eval $(call gb_Library_add_defs,libreofficekitgtk,\ ++ -DLOK_PATH="\"$(LIBDIR)/libreoffice/$(LIBO_LIB_FOLDER)\"" \ ++)) ++ + ifeq ($(OS),$(filter LINUX %BSD SOLARIS, $(OS))) + $(eval $(call gb_Library_add_libs,libreofficekitgtk,\ + $(DLOPEN_LIBS) -lm \ +diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx +index 488abc0..f734baa 100644 +--- a/libreofficekit/source/gtk/lokdocview.cxx ++++ b/libreofficekit/source/gtk/lokdocview.cxx +@@ -2387,7 +2387,7 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) + SAL_DLLPUBLIC_EXPORT GtkWidget* + lok_doc_view_new (const gchar* pPath, GCancellable *cancellable, GError **error) + { +- return GTK_WIDGET (g_initable_new (LOK_TYPE_DOC_VIEW, cancellable, error, "lopath", pPath, NULL)); ++ return GTK_WIDGET (g_initable_new (LOK_TYPE_DOC_VIEW, cancellable, error, "lopath", pPath == NULL ? LOK_PATH : pPath, NULL)); + } + + SAL_DLLPUBLIC_EXPORT GtkWidget* lok_doc_view_new_from_widget(LOKDocView* pOldLOKDocView) +-- +2.5.0 + diff --git a/libreoffice.spec b/libreoffice.spec index 5e78308..d39f2a2 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -327,6 +327,9 @@ Patch20: 0001-update-the-appstream-files-to-most-recent-version-of.patch Patch21: 0001-tdf-96243-don-t-crash-if-LibO-install.-wasn-t-found.patch Patch22: 0001-tdf-96246-Make-pRenderingArguments-nullable.patch Patch23: 0001-tdf-96250-desktop-empty-str-is-the-same-as-0-str-in-.patch +Patch24: 0001-tdf-96316-Decouple-view-only-editable-modes.patch +Patch25: 0002-tdf-96318-Add-searching-API.patch +Patch26: 0003-lokdocview-Set-a-default-path-for-LOK-init.patch %define instdir %{_libdir} %define baseinstdir %{instdir}/libreoffice