19#include <boost/property_tree/json_parser.hpp>
21#include <com/sun/star/awt/Key.hpp>
22#include <LibreOfficeKit/LibreOfficeKit.h>
23#include <LibreOfficeKit/LibreOfficeKitInit.h>
24#include <LibreOfficeKit/LibreOfficeKitEnums.h>
25#include <LibreOfficeKit/LibreOfficeKitGtk.h>
30#if !GLIB_CHECK_VERSION(2,32,0)
31#define G_SOURCE_REMOVE FALSE
32#define G_SOURCE_CONTINUE TRUE
34#if !GLIB_CHECK_VERSION(2,40,0)
35#define g_info(...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__)
39#define CURSOR_HANDLE_DIR "/../share/libreofficekit/"
41#define GRAPHIC_HANDLE_COUNT 8
56 GdkRectangle m_aRectangle;
58 ViewRectangle(
int nPart = 0,
const GdkRectangle& rRectangle = GdkRectangle())
60 m_aRectangle(rRectangle)
69 std::vector<GdkRectangle> m_aRectangles;
71 ViewRectangles(
int nPart = 0, std::vector<GdkRectangle>&& rRectangles = std::vector<GdkRectangle>())
73 m_aRectangles(std::move(rRectangles))
79struct LOKDocViewPrivateImpl
81 std::string m_aLOPath;
82 std::string m_aUserProfileURL;
83 std::string m_aDocPath;
84 std::string m_aRenderingArguments;
85 gdouble m_nLoadProgress;
91 LibreOfficeKit* m_pOffice;
92 LibreOfficeKitDocument* m_pDocument;
94 std::unique_ptr<TileBuffer> m_pTileBuffer;
95 GThreadPool* lokThreadPool;
98 glong m_nDocumentWidthTwips;
99 glong m_nDocumentHeightTwips;
103 guint64 m_nLOKFeatures;
107 GdkRectangle m_aVisibleCursor;
110 std::map<int, ViewRectangle> m_aViewCursors;
112 bool m_bCursorOverlayVisible;
114 bool m_bCursorVisible;
117 std::map<int, bool> m_aViewCursorVisibilities;
119 guint32 m_nLastButtonPressTime;
121 guint32 m_nLastButtonReleaseTime;
123 guint32 m_nLastButtonPressed;
125 guint32 m_nKeyModifier;
127 std::vector<GdkRectangle> m_aTextSelectionRectangles;
129 std::vector<GdkRectangle> m_aContentControlRectangles;
131 std::string m_aContentControlAlias;
134 std::map<int, ViewRectangles> m_aTextViewSelectionRectangles;
136 GdkRectangle m_aTextSelectionStart;
138 GdkRectangle m_aTextSelectionEnd;
139 GdkRectangle m_aGraphicSelection;
142 std::map<int, ViewRectangle> m_aGraphicViewSelections;
143 GdkRectangle m_aCellCursor;
146 std::map<int, ViewRectangle> m_aCellViewCursors;
147 bool m_bInDragGraphicSelection;
150 std::vector<std::pair<ViewRectangle, sal_uInt32>> m_aReferenceMarks;
157 GdkRectangle m_aHandleStartRect;
159 bool m_bInDragStartHandle;
163 GdkRectangle m_aHandleMiddleRect;
165 bool m_bInDragMiddleHandle;
169 GdkRectangle m_aHandleEndRect;
171 bool m_bInDragEndHandle;
177 GdkRectangle m_aGraphicHandleRects[8];
179 bool m_bInDragGraphicHandles[8];
189 LibreOfficeKitDocumentType m_eDocumentType;
193 int m_nTileSizeTwips;
195 GdkRectangle m_aVisibleArea;
196 bool m_bVisibleAreaSet;
203 std::map<int, ViewRectangle> m_aViewLockRectangles;
205 LOKDocViewPrivateImpl()
206 : m_nLoadProgress(0),
213 m_pDocument(
nullptr),
214 lokThreadPool(
nullptr),
216 m_nDocumentWidthTwips(0),
217 m_nDocumentHeightTwips(0),
221 m_aVisibleCursor({0, 0, 0, 0}),
222 m_bCursorOverlayVisible(
false),
223 m_bCursorVisible(
true),
224 m_nLastButtonPressTime(0),
225 m_nLastButtonReleaseTime(0),
226 m_nLastButtonPressed(0),
228 m_aTextSelectionStart({0, 0, 0, 0}),
229 m_aTextSelectionEnd({0, 0, 0, 0}),
230 m_aGraphicSelection({0, 0, 0, 0}),
231 m_aCellCursor({0, 0, 0, 0}),
232 m_bInDragGraphicSelection(
false),
233 m_pHandleStart(
nullptr),
234 m_aHandleStartRect({0, 0, 0, 0}),
235 m_bInDragStartHandle(
false),
236 m_pHandleMiddle(
nullptr),
237 m_aHandleMiddleRect({0, 0, 0, 0}),
238 m_bInDragMiddleHandle(
false),
239 m_pHandleEnd(
nullptr),
240 m_aHandleEndRect({0, 0, 0, 0}),
241 m_bInDragEndHandle(
false),
244 m_eDocumentType(LOK_DOCTYPE_OTHER),
246 m_aVisibleArea({0, 0, 0, 0}),
247 m_bVisibleAreaSet(
false),
250 memset(&m_aGraphicHandleRects, 0,
sizeof(m_aGraphicHandleRects));
251 memset(&m_bInDragGraphicHandles, 0,
sizeof(m_bInDragGraphicHandles));
254 ~LOKDocViewPrivateImpl()
257 g_source_remove(m_nTimeoutId);
262void setDocumentView(LibreOfficeKitDocument* pDoc,
int viewId)
265 std::stringstream ss;
266 ss <<
"lok::Document::setView(" << viewId <<
")";
267 g_info(
"%s", ss.str().c_str());
268 pDoc->pClass->setView(pDoc, viewId);
338static void callbackWorker (
int nType,
const char* pPayload,
void* pData);
342#pragma GCC diagnostic push
343#pragma GCC diagnostic ignored "-Wunused-function"
345#if __has_warning("-Wdeprecated-volatile")
346#pragma clang diagnostic ignored "-Wdeprecated-volatile"
351 G_ADD_PRIVATE (LOKDocView)
354#pragma GCC diagnostic pop
359 LOKDocViewPrivate* priv =
static_cast<LOKDocViewPrivate*
>(lok_doc_view_get_instance_private(pDocView));
369 std::string m_aPayload;
370 LOKDocView* m_pDocView;
372 CallbackData(
int nType, std::string aPayload, LOKDocView* pDocView)
374 m_aPayload(
std::move(aPayload)),
375 m_pDocView(pDocView) {}
382 const gchar* pCommand,
383 const gchar* pArguments,
384 bool bNotifyWhenFinished)
386 LOKDocViewPrivate& priv =
getPrivate(pDocView);
387 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
389 GError* error =
nullptr;
395 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
396 if (error !=
nullptr)
398 g_warning(
"Unable to call LOK_POST_COMMAND: %s", error->message);
399 g_clear_error(&error);
401 g_object_unref(task);
405doSearch(LOKDocView* pDocView,
const char* pText,
bool bBackwards,
bool highlightAll)
407 LOKDocViewPrivate& priv =
getPrivate(pDocView);
408 if (!priv->m_pDocument)
411 boost::property_tree::ptree aTree;
412 GtkWidget* drawingWidget = GTK_WIDGET(pDocView);
413 GdkWindow* drawingWindow = gtk_widget_get_window(drawingWidget);
416 std::shared_ptr<cairo_region_t> cairoVisRegion( gdk_window_get_visible_region(drawingWindow),
417 cairo_region_destroy);
418 cairo_rectangle_int_t cairoVisRect;
419 cairo_region_get_rectangle(cairoVisRegion.get(), 0, &cairoVisRect);
423 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.SearchString/type",
'/'),
"string");
424 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.SearchString/value",
'/'), pText);
425 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.Backward/type",
'/'),
"boolean");
426 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.Backward/value",
'/'), bBackwards);
429 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.Command/type",
'/'),
"unsigned short");
431 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.Command/value",
'/'),
"1");
434 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.SearchStartPointX/type",
'/'),
"long");
435 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.SearchStartPointX/value",
'/'),
x);
436 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.SearchStartPointY/type",
'/'),
"long");
437 aTree.put(boost::property_tree::ptree::path_type(
"SearchItem.SearchStartPointY/value",
'/'),
y);
439 std::stringstream aStream;
440 boost::property_tree::write_json(aStream, aTree);
442 LOKPostCommand (pDocView,
".uno:ExecuteSearch", aStream.str().c_str(),
false);
448 return rRectangle.x == 0 && rRectangle.y == 0 && rRectangle.width == 0 && rRectangle.height == 0;
454 LOKDocViewPrivate& priv =
getPrivate(pDocView);
456 if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleStartRect,
nullptr))
458 g_info(
"LOKDocView_Impl::signalButton: start of drag start handle");
459 priv->m_bInDragStartHandle =
true;
462 else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleMiddleRect,
nullptr))
464 g_info(
"LOKDocView_Impl::signalButton: start of drag middle handle");
465 priv->m_bInDragMiddleHandle =
true;
468 else if (gdk_rectangle_intersect(&aClick, &priv->m_aHandleEndRect,
nullptr))
470 g_info(
"LOKDocView_Impl::signalButton: start of drag end handle");
471 priv->m_bInDragEndHandle =
true;
481 LOKDocViewPrivate& priv =
getPrivate(pDocView);
482 GError* error =
nullptr;
486 if (gdk_rectangle_intersect(&aClick, &priv->m_aGraphicHandleRects[
i],
nullptr))
488 g_info(
"LOKDocView_Impl::signalButton: start of drag graphic handle #%d",
i);
489 priv->m_bInDragGraphicHandles[
i] =
true;
491 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
498 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
499 if (error !=
nullptr)
501 g_warning(
"Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
502 g_clear_error(&error);
504 g_object_unref(task);
516 LOKDocViewPrivate& priv =
getPrivate(pDocView);
518 if (priv->m_bInDragStartHandle)
520 g_info(
"LOKDocView_Impl::signalButton: end of drag start handle");
521 priv->m_bInDragStartHandle =
false;
524 else if (priv->m_bInDragMiddleHandle)
526 g_info(
"LOKDocView_Impl::signalButton: end of drag middle handle");
527 priv->m_bInDragMiddleHandle =
false;
530 else if (priv->m_bInDragEndHandle)
532 g_info(
"LOKDocView_Impl::signalButton: end of drag end handle");
533 priv->m_bInDragEndHandle =
false;
543 LOKDocViewPrivate& priv =
getPrivate(pDocView);
544 GError* error =
nullptr;
548 if (priv->m_bInDragGraphicHandles[
i])
550 g_info(
"LOKDocView_Impl::signalButton: end of drag graphic handle #%d",
i);
551 priv->m_bInDragGraphicHandles[
i] =
false;
553 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
560 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
561 if (error !=
nullptr)
563 g_warning(
"Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
564 g_clear_error(&error);
566 g_object_unref(task);
572 if (!priv->m_bInDragGraphicSelection)
575 g_info(
"LOKDocView_Impl::signalButton: end of drag graphic selection");
576 priv->m_bInDragGraphicSelection =
false;
578 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
585 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
586 if (error !=
nullptr)
588 g_warning(
"Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
589 g_clear_error(&error);
591 g_object_unref(task);
599 GTask* task = G_TASK(data);
600 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
601 LOKDocViewPrivate& priv =
getPrivate(pDocView);
602 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
603 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
607 setDocumentView(priv->m_pDocument, priv->m_nViewId);
608 std::stringstream ss;
610 if (priv->m_nTileSizeTwips)
612 ss.str(std::string());
613 ss <<
"lok::Document::setClientZoom(" << nTileSizePixelsScaled <<
", " << nTileSizePixelsScaled <<
", " << priv->m_nTileSizeTwips <<
", " << priv->m_nTileSizeTwips <<
")";
614 g_info(
"%s", ss.str().c_str());
615 priv->m_pDocument->pClass->setClientZoom(priv->m_pDocument,
616 nTileSizePixelsScaled,
617 nTileSizePixelsScaled,
618 priv->m_nTileSizeTwips,
619 priv->m_nTileSizeTwips);
620 priv->m_nTileSizeTwips = 0;
622 if (priv->m_bVisibleAreaSet)
624 ss.str(std::string());
625 ss <<
"lok::Document::setClientVisibleArea(" << priv->m_aVisibleArea.x <<
", " << priv->m_aVisibleArea.y <<
", ";
626 ss << priv->m_aVisibleArea.width <<
", " << priv->m_aVisibleArea.height <<
")";
627 g_info(
"%s", ss.str().c_str());
628 priv->m_pDocument->pClass->setClientVisibleArea(priv->m_pDocument,
629 priv->m_aVisibleArea.x,
630 priv->m_aVisibleArea.y,
631 priv->m_aVisibleArea.width,
632 priv->m_aVisibleArea.height);
633 priv->m_bVisibleAreaSet =
false;
636 ss.str(std::string());
638 g_info(
"%s", ss.str().c_str());
639 priv->m_pDocument->pClass->postKeyEvent(priv->m_pDocument,
648 LOKDocView* pDocView = LOK_DOC_VIEW(pWidget);
649 LOKDocViewPrivate& priv =
getPrivate(pDocView);
652 GError* error =
nullptr;
656 g_info(
"signalKey: not in edit mode, ignore");
661 switch (pEvent->keyval)
663 case GDK_KEY_BackSpace:
664 nKeyCode = com::sun::star::awt::Key::BACKSPACE;
667 nKeyCode = com::sun::star::awt::Key::DELETE;
670 case GDK_KEY_KP_Enter:
671 nKeyCode = com::sun::star::awt::Key::RETURN;
674 nKeyCode = com::sun::star::awt::Key::ESCAPE;
677 nKeyCode = com::sun::star::awt::Key::TAB;
680 nKeyCode = com::sun::star::awt::Key::DOWN;
683 nKeyCode = com::sun::star::awt::Key::UP;
686 nKeyCode = com::sun::star::awt::Key::LEFT;
689 nKeyCode = com::sun::star::awt::Key::RIGHT;
691 case GDK_KEY_Page_Down:
692 nKeyCode = com::sun::star::awt::Key::PAGEDOWN;
694 case GDK_KEY_Page_Up:
695 nKeyCode = com::sun::star::awt::Key::PAGEUP;
698 nKeyCode = com::sun::star::awt::Key::INSERT;
700 case GDK_KEY_Shift_L:
701 case GDK_KEY_Shift_R:
702 if (pEvent->type == GDK_KEY_PRESS)
705 case GDK_KEY_Control_L:
706 case GDK_KEY_Control_R:
707 if (pEvent->type == GDK_KEY_PRESS)
712 if (pEvent->type == GDK_KEY_PRESS)
715 priv->m_nKeyModifier &= ~KEY_MOD2;
718 if (pEvent->keyval >= GDK_KEY_F1 && pEvent->keyval <= GDK_KEY_F26)
719 nKeyCode = com::sun::star::awt::Key::F1 + (pEvent->keyval - GDK_KEY_F1);
721 nCharCode = gdk_keyval_to_unicode(pEvent->keyval);
727 if (pEvent->state & GDK_SHIFT_MASK)
730 if (pEvent->state & GDK_CONTROL_MASK)
733 if (priv->m_nKeyModifier &
KEY_MOD2)
737 if (pEvent->keyval >= GDK_KEY_a && pEvent->keyval <= GDK_KEY_z)
739 nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_a);
741 else if (pEvent->keyval >= GDK_KEY_A && pEvent->keyval <= GDK_KEY_Z) {
742 nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_A);
744 else if (pEvent->keyval >= GDK_KEY_0 && pEvent->keyval <= GDK_KEY_9) {
745 nKeyCode |= 256 + (pEvent->keyval - GDK_KEY_0);
749 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
751 pLOEvent->
m_nKeyEvent = pEvent->type == GDK_KEY_RELEASE ? LOK_KEYEVENT_KEYUP : LOK_KEYEVENT_KEYINPUT;
755 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
756 if (error !=
nullptr)
758 g_warning(
"Unable to call LOK_POST_KEY: %s", error->message);
759 g_clear_error(&error);
761 g_object_unref(task);
769 LOKDocView* pDocView = LOK_DOC_VIEW (
pData);
770 LOKDocViewPrivate& priv =
getPrivate(pDocView);
774 if (priv->m_bCursorOverlayVisible)
775 priv->m_bCursorOverlayVisible =
false;
777 priv->m_bCursorOverlayVisible =
true;
778 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
818 GtkWidget *dialog = gtk_message_dialog_new(
nullptr,
819 GTK_DIALOG_DESTROY_WITH_PARENT,
824 gtk_dialog_run(GTK_DIALOG(dialog));
825 gtk_widget_destroy(dialog);
829setPart(LOKDocView* pDocView,
const std::string& rString)
831 LOKDocViewPrivate& priv =
getPrivate(pDocView);
832 priv->m_nPartId = std::stoi(rString);
847 gtk_widget_queue_draw(pWidget);
855 std::stringstream aStream;
856 aStream << priv->m_aRenderingArguments;
857 boost::property_tree::ptree aTree;
858 boost::property_tree::read_json(aStream, aTree);
860 for (
const auto& rPair : aTree)
862 if (rPair.first ==
".uno:Author")
864 aRet = rPair.second.get<std::string>(
"value");
876 LOKDocViewPrivate& priv =
getPrivate(pDocView);
878 priv->m_pDocument->pClass->getDocumentSize(priv->m_pDocument, &priv->m_nDocumentWidthTwips, &priv->m_nDocumentHeightTwips);
879 float zoom = priv->m_fZoom;
880 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
882 long nDocumentWidthTwips = priv->m_nDocumentWidthTwips;
883 long nDocumentHeightTwips = priv->m_nDocumentHeightTwips;
884 long nDocumentWidthPixels =
twipToPixel(nDocumentWidthTwips, zoom);
885 long nDocumentHeightPixels =
twipToPixel(nDocumentHeightTwips, zoom);
888 guint nColumns = ceil(
static_cast<double>(nDocumentWidthPixels) / nTileSizePixelsScaled);
889 priv->m_pTileBuffer = std::make_unique<TileBuffer>(nColumns, nScaleFactor);
890 gtk_widget_set_size_request(GTK_WIDGET(pDocView),
891 nDocumentWidthPixels,
892 nDocumentHeightPixels);
898 LOKDocView* pLOKDocView =
static_cast<LOKDocView*
>(
pData);
899 LOKDocViewPrivate& priv =
getPrivate(pLOKDocView);
902 priv->m_pDocument->pClass->initializeForRendering(priv->m_pDocument, priv->m_aRenderingArguments.c_str());
906 priv->m_nViewId = priv->m_pDocument->pClass->getView(priv->m_pDocument);
908 priv->m_pDocument->pClass->registerCallback(priv->m_pDocument,
callbackWorker, pLOKDocView);
909 priv->m_nParts = priv->m_pDocument->pClass->getParts(priv->m_pDocument);
911 priv->m_nTimeoutId = g_timeout_add(600,
handleTimeout, pLOKDocView);
915 gtk_widget_set_can_focus(GTK_WIDGET(pLOKDocView),
true);
916 gtk_widget_grab_focus(GTK_WIDGET(pLOKDocView));
920 priv->m_bInit =
true;
930 CallbackData* pCallback =
static_cast<CallbackData*
>(
pData);
931 LOKDocViewPrivate& priv =
getPrivate(pCallback->m_pDocView);
932 bool bModify =
false;
934 switch (pCallback->m_nType)
936 case LOK_CALLBACK_STATUS_INDICATOR_START:
938 priv->m_nLoadProgress = 0.0;
942 case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
944 priv->m_nLoadProgress =
static_cast<gdouble
>(std::stoi(pCallback->m_aPayload)/100.0);
948 case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
950 priv->m_nLoadProgress = 1.0;
954 case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
957 case LOK_CALLBACK_DOCUMENT_PASSWORD:
959 char const*
const pURL(pCallback->m_aPayload.c_str());
963 case LOK_CALLBACK_ERROR:
965 reportError(pCallback->m_pDocView, pCallback->m_aPayload);
968 case LOK_CALLBACK_SIGNATURE_STATUS:
985 LOKDocView* pDocView = LOK_DOC_VIEW (
pData);
987 CallbackData* pCallback =
new CallbackData(
nType, pPayload ? pPayload :
"(nil)", pDocView);
988 g_info(
"LOKDocView_Impl::globalCallbackWorkerImpl: %s, '%s'", lokCallbackTypeToString(
nType), pPayload);
995 LOKDocViewPrivate& priv =
getPrivate(pDocView);
998 gchar** ppCoordinates = g_strsplit(pPayload,
", ", 5);
999 gchar** ppCoordinate = ppCoordinates;
1001 aRet.width = aRet.height = aRet.x = aRet.y = 0;
1005 g_strfreev(ppCoordinates);
1008 aRet.x = atoi(*ppCoordinate);
1014 g_strfreev(ppCoordinates);
1017 aRet.y = atoi(*ppCoordinate);
1023 g_strfreev(ppCoordinates);
1026 long l = atol(*ppCoordinate);
1027 if (l > std::numeric_limits<int>::max())
1028 aRet.width = std::numeric_limits<int>::max();
1031 if (aRet.x + aRet.width > priv->m_nDocumentWidthTwips)
1032 aRet.width = priv->m_nDocumentWidthTwips - aRet.x;
1036 g_strfreev(ppCoordinates);
1039 l = atol(*ppCoordinate);
1040 if (l > std::numeric_limits<int>::max())
1041 aRet.height = std::numeric_limits<int>::max();
1044 if (aRet.y + aRet.height > priv->m_nDocumentHeightTwips)
1045 aRet.height = priv->m_nDocumentHeightTwips - aRet.y;
1047 g_strfreev(ppCoordinates);
1051static std::vector<GdkRectangle>
1054 std::vector<GdkRectangle> aRet;
1056 if (g_strcmp0(pPayload,
"EMPTY") == 0)
1059 gchar** ppRectangles = g_strsplit(pPayload,
"; ", 0);
1060 for (gchar** ppRectangle = ppRectangles; *ppRectangle; ++ppRectangle)
1062 g_strfreev(ppRectangles);
1071 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1072 GdkRectangle aRectanglePixels;
1073 GdkPoint aStart, aEnd;
1074 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
1077 aRectanglePixels.x =
twipToPixel(rRectangle.x, priv->m_fZoom) * nScaleFactor;
1078 aRectanglePixels.y =
twipToPixel(rRectangle.y, priv->m_fZoom) * nScaleFactor;
1079 aRectanglePixels.width =
twipToPixel(rRectangle.width, priv->m_fZoom) * nScaleFactor;
1080 aRectanglePixels.height =
twipToPixel(rRectangle.height, priv->m_fZoom) * nScaleFactor;
1082 aStart.x = aRectanglePixels.y / nTileSizePixelsScaled;
1083 aStart.y = aRectanglePixels.x / nTileSizePixelsScaled;
1084 aEnd.x = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixelsScaled) / nTileSizePixelsScaled;
1085 aEnd.y = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixelsScaled) / nTileSizePixelsScaled;
1086 for (
int i = aStart.x;
i < aEnd.x;
i++)
1088 for (
int j = aStart.y; j < aEnd.y; j++)
1090 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
1091 priv->m_pTileBuffer->setInvalid(
i, j, priv->m_fZoom, task, priv->lokThreadPool);
1092 g_object_unref(task);
1100 CallbackData* pCallback =
static_cast<CallbackData*
>(
pData);
1101 LOKDocView* pDocView = LOK_DOC_VIEW (pCallback->m_pDocView);
1102 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1106 if (!priv->lokThreadPool)
1112 switch (
static_cast<LibreOfficeKitCallbackType
>(pCallback->m_nType))
1114 case LOK_CALLBACK_INVALIDATE_TILES:
1116 if (pCallback->m_aPayload.compare(0, 5,
"EMPTY") != 0)
1118 GdkRectangle aRectangle =
payloadToRectangle(pDocView, pCallback->m_aPayload.c_str());
1122 priv->m_pTileBuffer->resetAllTiles();
1124 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1127 case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
1130 std::stringstream aStream(pCallback->m_aPayload);
1131 boost::property_tree::ptree aTree;
1132 boost::property_tree::read_json(aStream, aTree);
1133 const std::string& rRectangle = aTree.get<std::string>(
"rectangle");
1134 int nViewId = aTree.get<
int>(
"viewId");
1137 priv->m_bCursorOverlayVisible =
true;
1138 if(nViewId == priv->m_nViewId)
1141 priv->m_aVisibleCursor.x,
1142 priv->m_aVisibleCursor.y,
1143 priv->m_aVisibleCursor.width,
1144 priv->m_aVisibleCursor.height);
1146 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1149 case LOK_CALLBACK_TEXT_SELECTION:
1151 priv->m_aTextSelectionRectangles =
payloadToRectangles(pDocView, pCallback->m_aPayload.c_str());
1152 bool bIsTextSelected = !priv->m_aTextSelectionRectangles.empty();
1154 if (!bIsTextSelected)
1156 memset(&priv->m_aTextSelectionStart, 0,
sizeof(priv->m_aTextSelectionStart));
1157 memset(&priv->m_aHandleStartRect, 0,
sizeof(priv->m_aHandleStartRect));
1158 memset(&priv->m_aTextSelectionEnd, 0,
sizeof(priv->m_aTextSelectionEnd));
1159 memset(&priv->m_aHandleEndRect, 0,
sizeof(priv->m_aHandleEndRect));
1162 memset(&priv->m_aHandleMiddleRect, 0,
sizeof(priv->m_aHandleMiddleRect));
1165 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1168 case LOK_CALLBACK_TEXT_SELECTION_START:
1170 priv->m_aTextSelectionStart =
payloadToRectangle(pDocView, pCallback->m_aPayload.c_str());
1173 case LOK_CALLBACK_TEXT_SELECTION_END:
1175 priv->m_aTextSelectionEnd =
payloadToRectangle(pDocView, pCallback->m_aPayload.c_str());
1178 case LOK_CALLBACK_CURSOR_VISIBLE:
1180 priv->m_bCursorVisible = pCallback->m_aPayload ==
"true";
1183 case LOK_CALLBACK_MOUSE_POINTER:
1192 GdkCursor* pCursor = gdk_cursor_new_from_name(gtk_widget_get_display(GTK_WIDGET(pDocView)),
1193 pCallback->m_aPayload.c_str());
1194 gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(pDocView)), pCursor);
1198 case LOK_CALLBACK_GRAPHIC_SELECTION:
1200 if (pCallback->m_aPayload !=
"EMPTY")
1201 priv->m_aGraphicSelection =
payloadToRectangle(pDocView, pCallback->m_aPayload.c_str());
1203 memset(&priv->m_aGraphicSelection, 0,
sizeof(priv->m_aGraphicSelection));
1204 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1207 case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
1209 std::stringstream aStream(pCallback->m_aPayload);
1210 boost::property_tree::ptree aTree;
1211 boost::property_tree::read_json(aStream, aTree);
1212 int nViewId = aTree.get<
int>(
"viewId");
1213 int nPart = aTree.get<
int>(
"part");
1214 const std::string& rRectangle = aTree.get<std::string>(
"selection");
1215 if (rRectangle !=
"EMPTY")
1216 priv->m_aGraphicViewSelections[nViewId] = ViewRectangle(nPart,
payloadToRectangle(pDocView, rRectangle.c_str()));
1219 auto it = priv->m_aGraphicViewSelections.find(nViewId);
1220 if (it != priv->m_aGraphicViewSelections.end())
1221 priv->m_aGraphicViewSelections.erase(it);
1223 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1227 case LOK_CALLBACK_CELL_CURSOR:
1229 if (pCallback->m_aPayload !=
"EMPTY")
1232 memset(&priv->m_aCellCursor, 0,
sizeof(priv->m_aCellCursor));
1233 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1236 case LOK_CALLBACK_HYPERLINK_CLICKED:
1241 case LOK_CALLBACK_STATE_CHANGED:
1246 case LOK_CALLBACK_SEARCH_NOT_FOUND:
1251 case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
1257 case LOK_CALLBACK_SET_PART:
1259 setPart(pDocView, pCallback->m_aPayload);
1262 case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
1264 boost::property_tree::ptree aTree;
1265 std::stringstream aStream(pCallback->m_aPayload);
1266 boost::property_tree::read_json(aStream, aTree);
1267 int nCount = aTree.get_child(
"searchResultSelection").size();
1271 case LOK_CALLBACK_UNO_COMMAND_RESULT:
1276 case LOK_CALLBACK_CELL_ADDRESS:
1281 case LOK_CALLBACK_CELL_FORMULA:
1286 case LOK_CALLBACK_ERROR:
1291 case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
1293 std::stringstream aStream(pCallback->m_aPayload);
1294 boost::property_tree::ptree aTree;
1295 boost::property_tree::read_json(aStream, aTree);
1296 int nViewId = aTree.get<
int>(
"viewId");
1297 int nPart = aTree.get<
int>(
"part");
1298 const std::string& rRectangle = aTree.get<std::string>(
"rectangle");
1299 priv->m_aViewCursors[nViewId] = ViewRectangle(nPart,
payloadToRectangle(pDocView, rRectangle.c_str()));
1300 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1303 case LOK_CALLBACK_TEXT_VIEW_SELECTION:
1305 std::stringstream aStream(pCallback->m_aPayload);
1306 boost::property_tree::ptree aTree;
1307 boost::property_tree::read_json(aStream, aTree);
1308 int nViewId = aTree.get<
int>(
"viewId");
1309 int nPart = aTree.get<
int>(
"part");
1310 const std::string& rSelection = aTree.get<std::string>(
"selection");
1311 priv->m_aTextViewSelectionRectangles[nViewId] = ViewRectangles(nPart,
payloadToRectangles(pDocView, rSelection.c_str()));
1312 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1315 case LOK_CALLBACK_VIEW_CURSOR_VISIBLE:
1317 std::stringstream aStream(pCallback->m_aPayload);
1318 boost::property_tree::ptree aTree;
1319 boost::property_tree::read_json(aStream, aTree);
1320 int nViewId = aTree.get<
int>(
"viewId");
1321 const std::string& rVisible = aTree.get<std::string>(
"visible");
1322 priv->m_aViewCursorVisibilities[nViewId] = rVisible ==
"true";
1323 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1327 case LOK_CALLBACK_CELL_VIEW_CURSOR:
1329 std::stringstream aStream(pCallback->m_aPayload);
1330 boost::property_tree::ptree aTree;
1331 boost::property_tree::read_json(aStream, aTree);
1332 int nViewId = aTree.get<
int>(
"viewId");
1333 int nPart = aTree.get<
int>(
"part");
1334 const std::string& rRectangle = aTree.get<std::string>(
"rectangle");
1335 if (rRectangle !=
"EMPTY")
1336 priv->m_aCellViewCursors[nViewId] = ViewRectangle(nPart,
payloadToRectangle(pDocView, rRectangle.c_str()));
1339 auto it = priv->m_aCellViewCursors.find(nViewId);
1340 if (it != priv->m_aCellViewCursors.end())
1341 priv->m_aCellViewCursors.erase(it);
1343 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1346 case LOK_CALLBACK_VIEW_LOCK:
1348 std::stringstream aStream(pCallback->m_aPayload);
1349 boost::property_tree::ptree aTree;
1350 boost::property_tree::read_json(aStream, aTree);
1351 int nViewId = aTree.get<
int>(
"viewId");
1352 int nPart = aTree.get<
int>(
"part");
1353 const std::string& rRectangle = aTree.get<std::string>(
"rectangle");
1354 if (rRectangle !=
"EMPTY")
1355 priv->m_aViewLockRectangles[nViewId] = ViewRectangle(nPart,
payloadToRectangle(pDocView, rRectangle.c_str()));
1358 auto it = priv->m_aViewLockRectangles.find(nViewId);
1359 if (it != priv->m_aViewLockRectangles.end())
1360 priv->m_aViewLockRectangles.erase(it);
1362 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1365 case LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED:
1369 case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED:
1373 case LOK_CALLBACK_COMMENT:
1376 case LOK_CALLBACK_RULER_UPDATE:
1379 case LOK_CALLBACK_WINDOW:
1382 case LOK_CALLBACK_INVALIDATE_HEADER:
1385 case LOK_CALLBACK_REFERENCE_MARKS:
1387 std::stringstream aStream(pCallback->m_aPayload);
1388 boost::property_tree::ptree aTree;
1389 boost::property_tree::read_json(aStream, aTree);
1391 priv->m_aReferenceMarks.clear();
1393 for(
const auto& rMark : aTree.get_child(
"marks"))
1395 sal_uInt32 nColor = std::stoi(rMark.second.get<std::string>(
"color"),
nullptr, 16);
1396 std::string sRect = rMark.second.get<std::string>(
"rectangle");
1397 sal_uInt32 nPart = std::stoi(rMark.second.get<std::string>(
"part"));
1400 priv->m_aReferenceMarks.push_back(std::pair<ViewRectangle, sal_uInt32>(ViewRectangle(nPart, aRect), nColor));
1403 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1407 case LOK_CALLBACK_CONTENT_CONTROL:
1409 std::stringstream aPayloadStream(pCallback->m_aPayload);
1410 boost::property_tree::ptree aTree;
1411 boost::property_tree::read_json(aPayloadStream, aTree);
1412 auto aAction = aTree.get<std::string>(
"action");
1413 if (aAction ==
"show")
1415 auto aRectangles = aTree.get<std::string>(
"rectangles");
1418 auto it = aTree.find(
"alias");
1419 if (it == aTree.not_found())
1421 priv->m_aContentControlAlias.clear();
1425 priv->m_aContentControlAlias = it->second.get_value<std::string>();
1428 else if (aAction ==
"hide")
1430 priv->m_aContentControlRectangles.clear();
1431 priv->m_aContentControlAlias.clear();
1433 else if (aAction ==
"change-picture")
1435 GtkWidget* pDialog = gtk_file_chooser_dialog_new(
1436 "Open File", GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView))),
1437 GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL,
"Open",
1438 GTK_RESPONSE_ACCEPT,
nullptr);
1439 gint nRet = gtk_dialog_run(GTK_DIALOG(pDialog));
1440 if (nRet == GTK_RESPONSE_ACCEPT)
1442 GtkFileChooser* pChooser = GTK_FILE_CHOOSER(pDialog);
1443 char* pFilename = gtk_file_chooser_get_uri(pChooser);
1444 boost::property_tree::ptree aValues;
1445 aValues.put(
"type",
"picture");
1446 aValues.put(
"changed", pFilename);
1447 std::stringstream aStream;
1448 boost::property_tree::write_json(aStream, aValues);
1449 std::string aJson = aStream.str();
1454 gtk_widget_destroy(pDialog);
1457 pCallback->m_aPayload.c_str());
1458 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
1462 case LOK_CALLBACK_STATUS_INDICATOR_START:
1463 case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
1464 case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
1465 case LOK_CALLBACK_DOCUMENT_PASSWORD:
1466 case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
1467 case LOK_CALLBACK_VALIDITY_LIST_BUTTON:
1468 case LOK_CALLBACK_VALIDITY_INPUT_HELP:
1469 case LOK_CALLBACK_SIGNATURE_STATUS:
1470 case LOK_CALLBACK_CONTEXT_MENU:
1471 case LOK_CALLBACK_PROFILE_FRAME:
1472 case LOK_CALLBACK_CLIPBOARD_CHANGED:
1473 case LOK_CALLBACK_CONTEXT_CHANGED:
1474 case LOK_CALLBACK_CELL_SELECTION_AREA:
1475 case LOK_CALLBACK_CELL_AUTO_FILL_AREA:
1476 case LOK_CALLBACK_TABLE_SELECTED:
1477 case LOK_CALLBACK_JSDIALOG:
1478 case LOK_CALLBACK_CALC_FUNCTION_LIST:
1479 case LOK_CALLBACK_TAB_STOP_LIST:
1480 case LOK_CALLBACK_FORM_FIELD_BUTTON:
1481 case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY:
1482 case LOK_CALLBACK_DOCUMENT_BACKGROUND_COLOR:
1483 case LOK_COMMAND_BLOCKED:
1484 case LOK_CALLBACK_SC_FOLLOW_JUMP:
1485 case LOK_CALLBACK_PRINT_RANGES:
1486 case LOK_CALLBACK_FONTS_MISSING:
1487 case LOK_CALLBACK_MEDIA_SHAPE:
1488 case LOK_CALLBACK_EXPORT_FILE:
1489 case LOK_CALLBACK_VIEW_RENDER_STATE:
1490 case LOK_CALLBACK_APPLICATION_BACKGROUND_COLOR:
1491 case LOK_CALLBACK_A11Y_FOCUS_CHANGED:
1492 case LOK_CALLBACK_A11Y_CARET_CHANGED:
1493 case LOK_CALLBACK_A11Y_TEXT_SELECTION_CHANGED:
1494 case LOK_CALLBACK_COLOR_PALETTES:
1495 case LOK_CALLBACK_DOCUMENT_PASSWORD_RESET:
1508 LOKDocView* pDocView = LOK_DOC_VIEW (
pData);
1510 CallbackData* pCallback =
new CallbackData(
nType, pPayload ? pPayload :
"(nil)", pDocView);
1511 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1512 std::stringstream ss;
1513 ss <<
"callbackWorker, view #" << priv->m_nViewId <<
": " << lokCallbackTypeToString(
nType) <<
", '" << (pPayload ? pPayload :
"(nil)") <<
"'";
1514 g_info(
"%s", ss.str().c_str());
1515 gdk_threads_add_idle(
callback, pCallback);
1521 const GdkRectangle& rCursor,
1523 GdkRectangle& rRectangle)
1525 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1526 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
1527 GdkPoint aCursorBottom;
1528 int nHandleWidth, nHandleHeight;
1529 double fHandleScale;
1531 nHandleWidth = cairo_image_surface_get_width(pHandle);
1532 nHandleHeight = cairo_image_surface_get_height(pHandle);
1534 fHandleScale =
twipToPixel(rCursor.height, priv->m_fZoom) / nHandleHeight;
1536 aCursorBottom.x =
twipToPixel(rCursor.x, priv->m_fZoom) +
twipToPixel(rCursor.width, priv->m_fZoom) / 2 - (nHandleWidth * fHandleScale) / 2;
1539 cairo_save (pCairo);
1540 cairo_scale(pCairo, 1.0 / nScaleFactor, 1.0 / nScaleFactor);
1541 cairo_translate(pCairo, aCursorBottom.x * nScaleFactor, aCursorBottom.y * nScaleFactor);
1542 cairo_scale(pCairo, fHandleScale * nScaleFactor, fHandleScale * nScaleFactor);
1543 cairo_set_source_surface(pCairo, pHandle, 0, 0);
1544 cairo_paint(pCairo);
1545 cairo_restore (pCairo);
1547 rRectangle.x = aCursorBottom.x;
1548 rRectangle.y = aCursorBottom.y;
1549 rRectangle.width = nHandleWidth * fHandleScale;
1550 rRectangle.height = nHandleHeight * fHandleScale;
1557 const GdkRectangle& rSelection,
1558 const GdkRGBA& rColor)
1560 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1561 int nHandleWidth = 9, nHandleHeight = 9;
1562 GdkRectangle aSelection;
1564 aSelection.x =
twipToPixel(rSelection.x, priv->m_fZoom);
1565 aSelection.y =
twipToPixel(rSelection.y, priv->m_fZoom);
1566 aSelection.width =
twipToPixel(rSelection.width, priv->m_fZoom);
1567 aSelection.height =
twipToPixel(rSelection.height, priv->m_fZoom);
1571 int x = aSelection.x,
y = aSelection.y;
1578 x += aSelection.width / 2;
1581 x += aSelection.width;
1584 y += aSelection.height / 2;
1587 x += aSelection.width;
1588 y += aSelection.height / 2;
1591 y += aSelection.height;
1594 x += aSelection.width / 2;
1595 y += aSelection.height;
1598 x += aSelection.width;
1599 y += aSelection.height;
1604 x -= nHandleWidth / 2;
1605 y -= nHandleHeight / 2;
1607 priv->m_aGraphicHandleRects[
i].x =
x;
1608 priv->m_aGraphicHandleRects[
i].y =
y;
1609 priv->m_aGraphicHandleRects[
i].width = nHandleWidth;
1610 priv->m_aGraphicHandleRects[
i].height = nHandleHeight;
1612 cairo_set_source_rgb(pCairo, rColor.red, rColor.green, rColor.blue);
1613 cairo_rectangle(pCairo,
x,
y, nHandleWidth, nHandleHeight);
1622 GTask* task = G_TASK(res);
1624 g_return_val_if_fail(LOK_IS_DOC_VIEW(pDocView),
nullptr);
1625 g_return_val_if_fail(g_task_is_valid(res, pDocView),
nullptr);
1626 g_return_val_if_fail(error ==
nullptr || *error ==
nullptr,
nullptr);
1628 return g_task_propagate_pointer(task, error);
1635 LOKDocView* pDocView = LOK_DOC_VIEW(sourceObject);
1636 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1643 if (error !=
nullptr)
1647 g_info(
"Skipping paint tile request because corresponding"
1648 "tile buffer has been destroyed");
1650 g_warning(
"Unable to get painted GdkPixbuf: %s", error->message);
1651 g_error_free(error);
1656 gdk_threads_add_idle(
queueDraw, GTK_WIDGET(pDocView));
1658 cairo_surface_destroy(pSurface);
1665 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1666 GdkRectangle aVisibleArea;
1667 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
1669 long nDocumentWidthPixels =
twipToPixel(priv->m_nDocumentWidthTwips, priv->m_fZoom) * nScaleFactor;
1670 long nDocumentHeightPixels =
twipToPixel(priv->m_nDocumentHeightTwips, priv->m_fZoom) * nScaleFactor;
1672 guint nRows = ceil(
static_cast<double>(nDocumentHeightPixels) / nTileSizePixelsScaled);
1673 guint nColumns = ceil(
static_cast<double>(nDocumentWidthPixels) / nTileSizePixelsScaled);
1675 cairo_save (pCairo);
1676 cairo_scale (pCairo, 1.0/nScaleFactor, 1.0/nScaleFactor);
1677 gdk_cairo_get_clip_rectangle (pCairo, &aVisibleArea);
1678 aVisibleArea.x =
pixelToTwip (aVisibleArea.x, priv->m_fZoom);
1679 aVisibleArea.y =
pixelToTwip (aVisibleArea.y, priv->m_fZoom);
1680 aVisibleArea.width =
pixelToTwip (aVisibleArea.width, priv->m_fZoom);
1681 aVisibleArea.height =
pixelToTwip (aVisibleArea.height, priv->m_fZoom);
1684 for (guint nRow = 0; nRow < nRows; ++nRow)
1686 for (guint nColumn = 0; nColumn < nColumns; ++nColumn)
1688 GdkRectangle aTileRectangleTwips, aTileRectanglePixels;
1693 if (nColumn == nColumns - 1)
1694 aTileRectanglePixels.width = nDocumentWidthPixels - nColumn * nTileSizePixelsScaled;
1696 aTileRectanglePixels.width = nTileSizePixelsScaled;
1697 if (nRow == nRows - 1)
1698 aTileRectanglePixels.height = nDocumentHeightPixels - nRow * nTileSizePixelsScaled;
1700 aTileRectanglePixels.height = nTileSizePixelsScaled;
1704 aTileRectangleTwips.x =
pixelToTwip(nTileSizePixelsScaled, priv->m_fZoom) * nColumn;
1705 aTileRectangleTwips.y =
pixelToTwip(nTileSizePixelsScaled, priv->m_fZoom) * nRow;
1706 aTileRectangleTwips.width =
pixelToTwip(aTileRectanglePixels.width, priv->m_fZoom);
1707 aTileRectangleTwips.height =
pixelToTwip(aTileRectanglePixels.height, priv->m_fZoom);
1709 if (!gdk_rectangle_intersect(&aVisibleArea, &aTileRectangleTwips,
nullptr))
1722 Tile& currentTile = priv->m_pTileBuffer->getTile(nRow, nColumn, task, priv->lokThreadPool);
1724 cairo_set_source_surface(pCairo, pSurface,
1725 twipToPixel(aTileRectangleTwips.x, priv->m_fZoom),
1726 twipToPixel(aTileRectangleTwips.y, priv->m_fZoom));
1727 cairo_paint(pCairo);
1728 g_object_unref(task);
1733 cairo_restore (pCairo);
1739 static std::map<int, GdkRGBA> aColorMap;
1740 auto it = aColorMap.find(nViewId);
1741 if (it != aColorMap.end())
1744 if (priv->m_eDocumentType == LOK_DOCTYPE_TEXT)
1746 char*
pValues = priv->m_pDocument->pClass->getCommandValues(priv->m_pDocument,
".uno:TrackedChangeAuthors");
1747 std::stringstream aInfo;
1748 aInfo <<
"lok::Document::getCommandValues('.uno:TrackedChangeAuthors') returned '" <<
pValues <<
"'" << std::endl;
1749 g_info(
"%s", aInfo.str().c_str());
1751 std::stringstream aStream(
pValues);
1752 boost::property_tree::ptree aTree;
1753 boost::property_tree::read_json(aStream, aTree);
1754 for (
const auto& rValue : aTree.get_child(
"authors"))
1756 const std::string& rName = rValue.second.get<std::string>(
"name");
1757 guint32 nColor = rValue.second.get<guint32>(
"color");
1758 GdkRGBA aColor{
static_cast<double>(
static_cast<guint8
>(nColor>>16))/255,
static_cast<double>(
static_cast<guint8
>(
static_cast<guint16
>(nColor) >> 8))/255,
static_cast<double>(
static_cast<guint8
>(nColor))/255, 0};
1761 aColorMap[itAuthorViews->second] = aColor;
1767 static std::vector<GdkRGBA> aColors =
1769 {(double(198))/255, (
double(146))/255, (
double(0))/255, 0},
1770 {(double(6))/255, (
double(70))/255, (
double(162))/255, 0},
1771 {(double(87))/255, (
double(157))/255, (
double(28))/255, 0},
1772 {(double(105))/255, (
double(43))/255, (
double(157))/255, 0},
1773 {(double(197))/255, (
double(0))/255, (
double(11))/255, 0},
1774 {(double(0))/255, (
double(128))/255, (
double(128))/255, 0},
1775 {(double(140))/255, (
double(132))/255, (
double(0))/255, 0},
1776 {(double(43))/255, (
double(85))/255, (
double(107))/255, 0},
1777 {(double(209))/255, (
double(118))/255, (
double(0))/255, 0},
1779 static int nColorCounter = 0;
1780 GdkRGBA aColor = aColors[nColorCounter++ % aColors.size()];
1781 aColorMap[nViewId] = aColor;
1783 assert(aColorMap.find(nViewId) != aColorMap.end());
1784 return aColorMap[nViewId];
1790 LOKDocViewPrivate& priv =
getPrivate(pDocView);
1792 if (priv->m_bEdit && priv->m_bCursorVisible && priv->m_bCursorOverlayVisible && !
isEmptyRectangle(priv->m_aVisibleCursor))
1794 if (priv->m_aVisibleCursor.width < 30)
1796 priv->m_aVisibleCursor.width = 30;
1798 cairo_set_source_rgb(pCairo, 0, 0, 0);
1799 cairo_rectangle(pCairo,
1800 twipToPixel(priv->m_aVisibleCursor.x, priv->m_fZoom),
1801 twipToPixel(priv->m_aVisibleCursor.y, priv->m_fZoom),
1802 twipToPixel(priv->m_aVisibleCursor.width, priv->m_fZoom),
1803 twipToPixel(priv->m_aVisibleCursor.height, priv->m_fZoom));
1808 if (priv->m_bEdit && !priv->m_aViewCursors.empty())
1810 for (
auto& rPair : priv->m_aViewCursors)
1812 auto itVisibility = priv->m_aViewCursorVisibilities.find(rPair.first);
1813 if (itVisibility != priv->m_aViewCursorVisibilities.end() && !itVisibility->second)
1817 if (rPair.second.m_nPart != priv->m_nPartId && priv->m_eDocumentType != LOK_DOCTYPE_TEXT)
1820 GdkRectangle& rCursor = rPair.second.m_aRectangle;
1821 if (rCursor.width < 30)
1825 const GdkRGBA& rDark =
getDarkColor(rPair.first, priv);
1826 cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
1827 cairo_rectangle(pCairo,
1836 if (priv->m_bEdit && priv->m_bCursorVisible && !
isEmptyRectangle(priv->m_aVisibleCursor) && priv->m_aTextSelectionRectangles.empty())
1839 gchar* handleMiddlePath = g_strconcat (priv->m_aLOPath.c_str(),
CURSOR_HANDLE_DIR,
"handle_image_middle.png",
nullptr);
1840 if (!priv->m_pHandleMiddle)
1842 priv->m_pHandleMiddle = cairo_image_surface_create_from_png(handleMiddlePath);
1843 assert(cairo_surface_status(priv->m_pHandleMiddle) == CAIRO_STATUS_SUCCESS);
1845 g_free (handleMiddlePath);
1846 renderHandle(pDocView, pCairo, priv->m_aVisibleCursor, priv->m_pHandleMiddle, priv->m_aHandleMiddleRect);
1849 if (!priv->m_aTextSelectionRectangles.empty())
1851 for (
const GdkRectangle& rRectangle : priv->m_aTextSelectionRectangles)
1854 cairo_set_source_rgba(pCairo, (
double(0x43))/255, (
double(0xac))/255, (
double(0xe8))/255, 0.25);
1855 cairo_rectangle(pCairo,
1867 gchar* handleStartPath = g_strconcat (priv->m_aLOPath.c_str(),
CURSOR_HANDLE_DIR,
"handle_image_start.png",
nullptr);
1868 if (!priv->m_pHandleStart)
1870 priv->m_pHandleStart = cairo_image_surface_create_from_png(handleStartPath);
1871 assert(cairo_surface_status(priv->m_pHandleStart) == CAIRO_STATUS_SUCCESS);
1873 renderHandle(pDocView, pCairo, priv->m_aTextSelectionStart, priv->m_pHandleStart, priv->m_aHandleStartRect);
1874 g_free (handleStartPath);
1879 gchar* handleEndPath = g_strconcat (priv->m_aLOPath.c_str(),
CURSOR_HANDLE_DIR,
"handle_image_end.png",
nullptr);
1880 if (!priv->m_pHandleEnd)
1882 priv->m_pHandleEnd = cairo_image_surface_create_from_png(handleEndPath);
1883 assert(cairo_surface_status(priv->m_pHandleEnd) == CAIRO_STATUS_SUCCESS);
1885 renderHandle(pDocView, pCairo, priv->m_aTextSelectionEnd, priv->m_pHandleEnd, priv->m_aHandleEndRect);
1886 g_free (handleEndPath);
1890 if (!priv->m_aContentControlRectangles.empty())
1892 for (
const GdkRectangle& rRectangle : priv->m_aContentControlRectangles)
1895 cairo_set_source_rgba(pCairo, (
double(0x7f))/255, (
double(0x7f))/255, (
double(0x7f))/255, 0.25);
1896 cairo_rectangle(pCairo,
1904 if (!priv->m_aContentControlAlias.empty())
1906 cairo_text_extents_t aExtents;
1907 cairo_text_extents(pCairo, priv->m_aContentControlAlias.c_str(), &aExtents);
1909 cairo_set_source_rgba(pCairo, 0, 0, 1, 0.25);
1910 cairo_rectangle(pCairo,
1911 twipToPixel(priv->m_aContentControlRectangles[0].x, priv->m_fZoom) + aExtents.x_bearing,
1912 twipToPixel(priv->m_aContentControlRectangles[0].y, priv->m_fZoom) + aExtents.y_bearing,
1917 cairo_move_to(pCairo,
1918 twipToPixel(priv->m_aContentControlRectangles[0].x, priv->m_fZoom),
1919 twipToPixel(priv->m_aContentControlRectangles[0].y, priv->m_fZoom));
1920 cairo_set_source_rgb(pCairo, 0, 0, 0);
1921 cairo_show_text(pCairo, priv->m_aContentControlAlias.c_str());
1927 for (
const auto& rPair : priv->m_aTextViewSelectionRectangles)
1929 if (rPair.second.m_nPart != priv->m_nPartId && priv->m_eDocumentType != LOK_DOCTYPE_TEXT)
1932 for (
const GdkRectangle& rRectangle : rPair.second.m_aRectangles)
1934 const GdkRGBA& rDark =
getDarkColor(rPair.first, priv);
1936 cairo_set_source_rgba(pCairo, rDark.red, rDark.green, rDark.blue, 0.25);
1937 cairo_rectangle(pCairo,
1948 GdkRGBA
const aBlack{0, 0, 0, 0};
1953 for (
const auto& rPair : priv->m_aGraphicViewSelections)
1955 const ViewRectangle& rRectangle = rPair.second;
1956 if (rRectangle.m_nPart != priv->m_nPartId && priv->m_eDocumentType != LOK_DOCTYPE_TEXT)
1959 const GdkRGBA& rDark =
getDarkColor(rPair.first, priv);
1966 cairo_set_source_rgb(pCairo, 0, 0, 0);
1967 cairo_rectangle(pCairo,
1968 twipToPixel(priv->m_aCellCursor.x, priv->m_fZoom),
1969 twipToPixel(priv->m_aCellCursor.y, priv->m_fZoom),
1970 twipToPixel(priv->m_aCellCursor.width, priv->m_fZoom),
1971 twipToPixel(priv->m_aCellCursor.height, priv->m_fZoom));
1972 cairo_set_line_width(pCairo, 2.0);
1973 cairo_stroke(pCairo);
1977 for (
const auto& rPair : priv->m_aCellViewCursors)
1979 const ViewRectangle& rCursor = rPair.second;
1980 if (rCursor.m_nPart != priv->m_nPartId)
1983 const GdkRGBA& rDark =
getDarkColor(rPair.first, priv);
1984 cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
1985 cairo_rectangle(pCairo,
1986 twipToPixel(rCursor.m_aRectangle.x, priv->m_fZoom),
1987 twipToPixel(rCursor.m_aRectangle.y, priv->m_fZoom),
1988 twipToPixel(rCursor.m_aRectangle.width, priv->m_fZoom),
1989 twipToPixel(rCursor.m_aRectangle.height, priv->m_fZoom));
1990 cairo_set_line_width(pCairo, 2.0);
1991 cairo_stroke(pCairo);
1995 for (
const auto& rPair : priv->m_aReferenceMarks)
1997 const ViewRectangle& rMark = rPair.first;
1998 if (rMark.m_nPart != priv->m_nPartId)
2001 sal_uInt32 nColor = rPair.second;
2003 sal_uInt8 nGreen = (nColor >> 8) & 0xff;
2005 cairo_set_source_rgb(pCairo, nRed, nGreen, nBlue);
2006 cairo_rectangle(pCairo,
2009 twipToPixel(rMark.m_aRectangle.width, priv->m_fZoom),
2010 twipToPixel(rMark.m_aRectangle.height, priv->m_fZoom));
2011 cairo_set_line_width(pCairo, 2.0);
2012 cairo_stroke(pCairo);
2016 for (
const auto& rPair : priv->m_aViewLockRectangles)
2018 const ViewRectangle& rRectangle = rPair.second;
2019 if (rRectangle.m_nPart != priv->m_nPartId)
2023 const GdkRGBA& rDark =
getDarkColor(rPair.first, priv);
2024 cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
2025 cairo_rectangle(pCairo,
2026 twipToPixel(rRectangle.m_aRectangle.x, priv->m_fZoom),
2027 twipToPixel(rRectangle.m_aRectangle.y, priv->m_fZoom),
2028 twipToPixel(rRectangle.m_aRectangle.width, priv->m_fZoom),
2029 twipToPixel(rRectangle.m_aRectangle.height, priv->m_fZoom));
2030 cairo_set_line_width(pCairo, 2.0);
2031 cairo_stroke(pCairo);
2034 cairo_rectangle(pCairo,
2035 twipToPixel(rRectangle.m_aRectangle.x + rRectangle.m_aRectangle.width, priv->m_fZoom) - 25,
2036 twipToPixel(rRectangle.m_aRectangle.y + rRectangle.m_aRectangle.height, priv->m_fZoom) - 15,
2041 twipToPixel(rRectangle.m_aRectangle.x + rRectangle.m_aRectangle.width, priv->m_fZoom) - 15,
2042 twipToPixel(rRectangle.m_aRectangle.y + rRectangle.m_aRectangle.height, priv->m_fZoom) - 15,
2046 cairo_stroke(pCairo);
2055 LOKDocView* pDocView = LOK_DOC_VIEW (pWidget);
2056 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2057 GError* error =
nullptr;
2059 g_info(
"LOKDocView_Impl::signalButton: %d, %d (in twips: %d, %d)",
2060 static_cast<int>(pEvent->x),
static_cast<int>(pEvent->y),
2061 static_cast<int>(
pixelToTwip(pEvent->x, priv->m_fZoom)),
2062 static_cast<int>(
pixelToTwip(pEvent->y, priv->m_fZoom)));
2063 gtk_widget_grab_focus(GTK_WIDGET(pDocView));
2065 switch (pEvent->type)
2067 case GDK_BUTTON_PRESS:
2069 GdkRectangle aClick;
2070 aClick.x = pEvent->x;
2071 aClick.y = pEvent->y;
2081 if ((pEvent->time - priv->m_nLastButtonPressTime) < 250)
2083 priv->m_nLastButtonPressTime = pEvent->time;
2084 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
2090 switch (pEvent->button)
2106 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
2107 if (error !=
nullptr)
2109 g_warning(
"Unable to call LOK_POST_MOUSE_EVENT: %s", error->message);
2110 g_clear_error(&error);
2112 g_object_unref(task);
2115 case GDK_BUTTON_RELEASE:
2123 if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250)
2125 priv->m_nLastButtonReleaseTime = pEvent->time;
2126 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
2132 switch (pEvent->button)
2148 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
2149 if (error !=
nullptr)
2151 g_warning(
"Unable to call LOK_POST_MOUSE_EVENT: %s", error->message);
2152 g_clear_error(&error);
2154 g_object_unref(task);
2165 GdkEventMotion* pEvent,
2168 GdkPoint aCursor, aHandle;
2171 aCursor.x = pHandle->x + pHandle->width / 2;
2172 aCursor.y = pHandle->y - pHandle->height / 2;
2174 aHandle.x = pHandle->x + pHandle->width / 2;
2175 aHandle.y = pHandle->y + pHandle->height / 2;
2177 pPoint->x = aCursor.x + (pEvent->x - aHandle.x);
2178 pPoint->y = aCursor.y + (pEvent->y - aHandle.y);
2184 LOKDocView* pDocView = LOK_DOC_VIEW (pWidget);
2185 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2187 GError* error =
nullptr;
2190 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2191 if (priv->m_bInDragMiddleHandle)
2193 g_info(
"lcl_signalMotion: dragging the middle handle");
2194 getDragPoint(&priv->m_aHandleMiddleRect, pEvent, &aPoint);
2195 priv->m_pDocument->pClass->setTextSelection(priv->m_pDocument, LOK_SETTEXTSELECTION_RESET,
pixelToTwip(aPoint.x, priv->m_fZoom),
pixelToTwip(aPoint.y, priv->m_fZoom));
2198 if (priv->m_bInDragStartHandle)
2200 g_info(
"lcl_signalMotion: dragging the start handle");
2201 getDragPoint(&priv->m_aHandleStartRect, pEvent, &aPoint);
2202 priv->m_pDocument->pClass->setTextSelection(priv->m_pDocument, LOK_SETTEXTSELECTION_START,
pixelToTwip(aPoint.x, priv->m_fZoom),
pixelToTwip(aPoint.y, priv->m_fZoom));
2205 if (priv->m_bInDragEndHandle)
2207 g_info(
"lcl_signalMotion: dragging the end handle");
2208 getDragPoint(&priv->m_aHandleEndRect, pEvent, &aPoint);
2209 priv->m_pDocument->pClass->setTextSelection(priv->m_pDocument, LOK_SETTEXTSELECTION_END,
pixelToTwip(aPoint.x, priv->m_fZoom),
pixelToTwip(aPoint.y, priv->m_fZoom));
2215 if (priv->m_bInDragGraphicHandles[
i])
2217 g_info(
"lcl_signalMotion: dragging the graphic handle #%d",
i);
2221 if (priv->m_bInDragGraphicSelection)
2223 g_info(
"lcl_signalMotion: dragging the graphic selection");
2227 GdkRectangle aMotionInTwipsInTwips;
2228 aMotionInTwipsInTwips.x =
pixelToTwip(pEvent->x, priv->m_fZoom);
2229 aMotionInTwipsInTwips.y =
pixelToTwip(pEvent->y, priv->m_fZoom);
2230 aMotionInTwipsInTwips.width = 1;
2231 aMotionInTwipsInTwips.height = 1;
2232 if (gdk_rectangle_intersect(&aMotionInTwipsInTwips, &priv->m_aGraphicSelection,
nullptr))
2234 g_info(
"lcl_signalMotion: start of drag graphic selection");
2235 priv->m_bInDragGraphicSelection =
true;
2237 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
2244 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
2245 if (error !=
nullptr)
2247 g_warning(
"Unable to call LOK_SET_GRAPHIC_SELECTION: %s", error->message);
2248 g_clear_error(&error);
2250 g_object_unref(task);
2257 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
2268 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
2269 if (error !=
nullptr)
2271 g_warning(
"Unable to call LOK_MOUSEEVENT_MOUSEMOVE: %s", error->message);
2272 g_clear_error(&error);
2274 g_object_unref(task);
2282 GTask* task = G_TASK(data);
2283 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2284 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2285 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2288 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2289 std::stringstream ss;
2293 g_info(
"%s", ss.str().c_str());
2294 priv->m_pDocument->pClass->setGraphicSelection(priv->m_pDocument,
2303 GTask* task = G_TASK(data);
2304 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2305 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2306 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2309 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2310 priv->m_pDocument->pClass->setClientZoom(priv->m_pDocument,
2320 GTask* task = G_TASK(data);
2321 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2322 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2323 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2326 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2327 std::stringstream ss;
2334 g_info(
"%s", ss.str().c_str());
2335 priv->m_pDocument->pClass->postMouseEvent(priv->m_pDocument,
2347 GTask* task = G_TASK(data);
2348 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2349 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2352 if ( priv->m_pDocument )
2354 priv->m_pDocument->pClass->destroy( priv->m_pDocument );
2355 priv->m_pDocument =
nullptr;
2359 std::string url = priv->m_aDocPath;
2360 if (gchar* pURL = g_filename_to_uri(url.c_str(),
nullptr,
nullptr))
2365 priv->m_pDocument = priv->m_pOffice->pClass->documentLoadWithOptions( priv->m_pOffice, url.c_str(),
"en-US" );
2366 if ( !priv->m_pDocument )
2368 char *pError = priv->m_pOffice->pClass->getError( priv->m_pOffice );
2369 g_task_return_new_error(task, g_quark_from_static_string (
"LOK error"), 0,
"%s", pError);
2373 priv->m_eDocumentType =
static_cast<LibreOfficeKitDocumentType
>(priv->m_pDocument->pClass->getDocumentType(priv->m_pDocument));
2375 g_task_return_boolean (task,
true);
2382 GTask* task = G_TASK(data);
2383 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2384 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2385 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2386 int nPart = pLOEvent->
m_nPart;
2389 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2390 priv->m_pDocument->pClass->setPart( priv->m_pDocument, nPart );
2399 GTask* task = G_TASK(data);
2400 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2401 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2402 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2406 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2407 priv->m_pDocument->pClass->setPartMode( priv->m_pDocument, nPartMode );
2413 GTask* task = G_TASK(data);
2414 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2415 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2416 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2417 bool bWasEdit = priv->
m_bEdit;
2418 bool bEdit = pLOEvent->
m_bEdit;
2420 if (!priv->m_bEdit && bEdit)
2421 g_info(
"lok_doc_view_set_edit: entering edit mode");
2422 else if (priv->m_bEdit && !bEdit)
2424 g_info(
"lok_doc_view_set_edit: leaving edit mode");
2426 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2427 priv->m_pDocument->pClass->resetSelection(priv->m_pDocument);
2429 priv->m_bEdit = bEdit;
2431 gdk_threads_add_idle(
queueDraw, GTK_WIDGET(pDocView));
2437 GTask* task = G_TASK(data);
2438 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2439 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2440 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2443 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2444 std::stringstream ss;
2446 g_info(
"%s", ss.str().c_str());
2453 GTask* task = G_TASK(data);
2454 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2455 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2456 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2457 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
2464 g_task_return_new_error(task,
2467 "TileBuffer has changed");
2470 std::unique_ptr<TileBuffer>& buffer = priv->m_pTileBuffer;
2474 cairo_surface_t *pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nTileSizePixelsScaled, nTileSizePixelsScaled);
2475 if (cairo_surface_status(pSurface) != CAIRO_STATUS_SUCCESS)
2477 cairo_surface_destroy(pSurface);
2478 g_task_return_new_error(task,
2481 "Error allocating Surface");
2485 unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
2486 GdkRectangle aTileRectangle;
2491 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2492 std::stringstream ss;
2493 GTimer* aTimer = g_timer_new();
2495 ss <<
"lok::Document::paintTile(" <<
static_cast<void*
>(pBuffer) <<
", "
2496 << nTileSizePixelsScaled <<
", " << nTileSizePixelsScaled <<
", "
2497 << aTileRectangle.x <<
", " << aTileRectangle.y <<
", "
2501 priv->m_pDocument->pClass->paintTile(priv->m_pDocument,
2503 nTileSizePixelsScaled, nTileSizePixelsScaled,
2504 aTileRectangle.x, aTileRectangle.y,
2509 g_timer_elapsed(aTimer, &nElapsedMs);
2510 ss <<
" rendered in " << (nElapsedMs / 1000.) <<
" milliseconds";
2511 g_info(
"%s", ss.str().c_str());
2512 g_timer_destroy(aTimer);
2514 cairo_surface_mark_dirty(pSurface);
2523 g_task_return_new_error(task,
2526 "TileBuffer has changed");
2530 g_task_return_pointer(task, pSurface,
reinterpret_cast<GDestroyNotify
>(cairo_surface_destroy));
2537 GTask* task = G_TASK(data);
2538 LOEvent* pLOEvent =
static_cast<LOEvent*
>(g_task_get_task_data(task));
2539 LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
2540 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2573 g_info (
"LOK_SET_GRAPHIC_SELECTION: skipping graphical operation in view-only mode");
2580 g_object_unref(task);
2588 gtk_widget_queue_draw (GTK_WIDGET (pDocView));
2593 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2594 priv.m_pImpl =
new LOKDocViewPrivateImpl();
2596 gtk_widget_add_events(GTK_WIDGET(pDocView),
2597 GDK_BUTTON_PRESS_MASK
2598 |GDK_BUTTON_RELEASE_MASK
2599 |GDK_BUTTON_MOTION_MASK
2601 |GDK_KEY_RELEASE_MASK);
2614 LOKDocView* pDocView = LOK_DOC_VIEW (
object);
2615 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2616 bool bDocPasswordEnabled = priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD;
2617 bool bDocPasswordToModifyEnabled = priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY;
2618 bool bTiledAnnotationsEnabled = !(priv->m_nLOKFeatures & LOK_FEATURE_NO_TILED_ANNOTATIONS);
2623 priv->m_aLOPath = g_value_get_string (
value);
2626 priv->m_bUnipoll = g_value_get_boolean (
value);
2629 priv->m_pOffice =
static_cast<LibreOfficeKit*
>(g_value_get_pointer(
value));
2632 if (
const gchar* pUserProfile = g_value_get_string(
value))
2633 priv->m_aUserProfileURL = pUserProfile;
2636 priv->m_aDocPath = g_value_get_string (
value);
2639 priv->m_pDocument =
static_cast<LibreOfficeKitDocument*
>(g_value_get_pointer(
value));
2640 priv->m_eDocumentType =
static_cast<LibreOfficeKitDocumentType
>(priv->m_pDocument->pClass->getDocumentType(priv->m_pDocument));
2649 priv->m_nDocumentWidthTwips = g_value_get_long (
value);
2652 priv->m_nDocumentHeightTwips = g_value_get_long (
value);
2655 if (
bool(g_value_get_boolean (
value)) != bDocPasswordEnabled)
2657 priv->m_nLOKFeatures = priv->m_nLOKFeatures ^ LOK_FEATURE_DOCUMENT_PASSWORD;
2658 priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
2662 if (
bool(g_value_get_boolean (
value)) != bDocPasswordToModifyEnabled)
2664 priv->m_nLOKFeatures = priv->m_nLOKFeatures ^ LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY;
2665 priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
2669 if (
bool(g_value_get_boolean (
value)) != bTiledAnnotationsEnabled)
2671 priv->m_nLOKFeatures = priv->m_nLOKFeatures ^ LOK_FEATURE_NO_TILED_ANNOTATIONS;
2672 priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
2676 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, propId, pspec);
2682 LOKDocView* pDocView = LOK_DOC_VIEW (
object);
2683 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2688 g_value_set_string (
value, priv->m_aLOPath.c_str());
2691 g_value_set_boolean (
value, priv->m_bUnipoll);
2694 g_value_set_pointer(
value, priv->m_pOffice);
2697 g_value_set_string(
value, priv->m_aUserProfileURL.c_str());
2700 g_value_set_string (
value, priv->m_aDocPath.c_str());
2703 g_value_set_pointer(
value, priv->m_pDocument);
2706 g_value_set_boolean (
value, priv->m_bEdit);
2709 g_value_set_double (
value, priv->m_nLoadProgress);
2712 g_value_set_float (
value, priv->m_fZoom);
2715 g_value_set_boolean (
value, priv->m_bIsLoading);
2718 g_value_set_boolean (
value, priv->m_bInit);
2721 g_value_set_long (
value, priv->m_nDocumentWidthTwips);
2724 g_value_set_long (
value, priv->m_nDocumentHeightTwips);
2727 g_value_set_boolean (
value, priv->m_bCanZoomIn);
2730 g_value_set_boolean (
value, priv->m_bCanZoomOut);
2733 g_value_set_boolean (
value, (priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD) != 0);
2736 g_value_set_boolean (
value, (priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY) != 0);
2739 g_value_set_boolean (
value, !(priv->m_nLOKFeatures & LOK_FEATURE_NO_TILED_ANNOTATIONS));
2742 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, propId, pspec);
2748 LOKDocView *pDocView = LOK_DOC_VIEW (pWidget);
2761 LOKDocView* pDocView = LOK_DOC_VIEW (widget);
2762 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2766 if (priv->m_pDocument)
2768 setDocumentView(priv->m_pDocument, priv->m_nViewId);
2769 priv->m_pDocument->pClass->registerCallback(priv->m_pDocument,
nullptr,
nullptr);
2772 if (priv->lokThreadPool)
2774 g_thread_pool_free(priv->lokThreadPool,
true,
true);
2775 priv->lokThreadPool =
nullptr;
2780 if (priv->m_pDocument)
2783 priv->m_pDocument->pClass->destroyView(priv->m_pDocument, priv->m_nViewId);
2784 if (priv->m_pDocument->pClass->getViewsCount(priv->m_pDocument) == 0)
2787 priv->m_pDocument->pClass->destroy (priv->m_pDocument);
2788 priv->m_pDocument =
nullptr;
2789 if (priv->m_pOffice)
2791 priv->m_pOffice->pClass->destroy (priv->m_pOffice);
2792 priv->m_pOffice =
nullptr;
2797 GTK_WIDGET_CLASS (lok_doc_view_parent_class)->destroy (widget);
2802 LOKDocView* pDocView = LOK_DOC_VIEW (
object);
2803 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2805 delete priv.m_pImpl;
2806 priv.m_pImpl =
nullptr;
2808 G_OBJECT_CLASS (lok_doc_view_parent_class)->finalize (
object);
2820 bool bWasEvent(
false);
2823 guint timeout = g_timeout_add(timeoutUs / 1000,
timeout_wakeup,
nullptr);
2824 bWasEvent = g_main_context_iteration(
nullptr,
true);
2825 g_source_remove(timeout);
2828 bWasEvent = g_main_context_iteration(
nullptr, timeoutUs < 0);
2830 return bWasEvent ? 1 : 0;
2836 g_main_context_wakeup(
nullptr);
2841 LOKDocView *pDocView = LOK_DOC_VIEW (
pData);
2842 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2850 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2853 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
2855 GError* error =
nullptr;
2857 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
2865 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
2866 if (error !=
nullptr)
2868 g_warning(
"Unable to call LOK_SET_CLIENT_ZOOM: %s", error->message);
2869 g_clear_error(&error);
2871 g_object_unref(task);
2873 priv->m_nTileSizeTwips =
pixelToTwip(nTileSizePixelsScaled, priv->m_fZoom * nScaleFactor);
2878 LOKDocView *pDocView = LOK_DOC_VIEW (initable);
2879 LOKDocViewPrivate& priv =
getPrivate(pDocView);
2881 if (priv->m_pOffice !=
nullptr)
2884 if (priv->m_bUnipoll)
2885 (void)g_setenv(
"SAL_LOK_OPTIONS",
"unipoll",
FALSE);
2887 static const char testingLangs[] =
"de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru";
2888 (void)g_setenv(
"LOK_ALLOWLIST_LANGUAGES", testingLangs,
FALSE);
2890 priv->m_pOffice = lok_init_2(priv->m_aLOPath.c_str(), priv->m_aUserProfileURL.empty() ?
nullptr : priv->m_aUserProfileURL.c_str());
2892 if (priv->m_pOffice ==
nullptr)
2895 g_quark_from_static_string (
"LOK initialization error"), 0,
2896 "Failed to get LibreOfficeKit context. Make sure path (%s) is correct",
2897 priv->m_aLOPath.c_str());
2900 priv->m_nLOKFeatures |= LOK_FEATURE_PART_IN_INVALIDATION_CALLBACK;
2901 priv->m_nLOKFeatures |= LOK_FEATURE_VIEWID_IN_VISCURSOR_INVALIDATION_CALLBACK;
2902 priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
2904 if (priv->m_bUnipoll)
2917 GObjectClass *pGObjectClass = G_OBJECT_CLASS(pClass);
2918 GtkWidgetClass *pWidgetClass = GTK_WIDGET_CLASS(pClass);
2927 pWidgetClass->key_press_event =
signalKey;
2928 pWidgetClass->key_release_event =
signalKey;
2938 g_param_spec_string(
"lopath",
2940 "LibreOffice Install Path",
2942 static_cast<GParamFlags
>(G_PARAM_READWRITE |
2943 G_PARAM_CONSTRUCT_ONLY |
2944 G_PARAM_STATIC_STRINGS));
2952 g_param_spec_boolean(
"unipoll",
2954 "Whether we use a custom unified polling loop",
2956 static_cast<GParamFlags
>(G_PARAM_READWRITE |
2957 G_PARAM_CONSTRUCT_ONLY |
2958 G_PARAM_STATIC_STRINGS));
2966 g_param_spec_pointer(
"lopointer",
2968 "A LibreOfficeKit* from lok_init()",
2969 static_cast<GParamFlags
>(G_PARAM_READWRITE |
2970 G_PARAM_CONSTRUCT_ONLY |
2971 G_PARAM_STATIC_STRINGS));
2979 g_param_spec_string(
"userprofileurl",
2980 "User profile path",
2981 "LibreOffice user profile path",
2983 static_cast<GParamFlags
>(G_PARAM_READWRITE |
2984 G_PARAM_CONSTRUCT_ONLY |
2985 G_PARAM_STATIC_STRINGS));
2993 g_param_spec_string(
"docpath",
2995 "The URI of the document to open",
2997 static_cast<GParamFlags
>(G_PARAM_READWRITE |
2998 G_PARAM_STATIC_STRINGS));
3007 g_param_spec_pointer(
"docpointer",
3009 "A LibreOfficeKitDocument* from documentLoad()",
3010 static_cast<GParamFlags
>(G_PARAM_READWRITE |
3011 G_PARAM_STATIC_STRINGS));
3019 g_param_spec_boolean(
"editable",
3021 "Whether the content is in edit mode or not",
3023 static_cast<GParamFlags
>(G_PARAM_READWRITE |
3024 G_PARAM_STATIC_STRINGS));
3035 g_param_spec_double(
"load-progress",
3036 "Estimated Load Progress",
3037 "Shows the progress of the document load operation",
3039 static_cast<GParamFlags
>(G_PARAM_READABLE |
3040 G_PARAM_STATIC_STRINGS));
3049 g_param_spec_float(
"zoom-level",
3051 "The current zoom level of the content",
3053 static_cast<GParamFlags
>(G_PARAM_READWRITE |
3054 G_PARAM_STATIC_STRINGS));
3063 g_param_spec_boolean(
"is-loading",
3065 "Whether the view is loading a document",
3067 static_cast<GParamFlags
>(G_PARAM_READABLE |
3068 G_PARAM_STATIC_STRINGS));
3076 g_param_spec_boolean(
"is-initialized",
3078 "Whether the view has completely initialized",
3080 static_cast<GParamFlags
>(G_PARAM_READABLE |
3081 G_PARAM_STATIC_STRINGS));
3089 g_param_spec_long(
"doc-width",
3091 "Width of the document in twips",
3093 static_cast<GParamFlags
>(G_PARAM_READWRITE |
3094 G_PARAM_STATIC_STRINGS));
3102 g_param_spec_long(
"doc-height",
3104 "Height of the document in twips",
3106 static_cast<GParamFlags
>(G_PARAM_READWRITE |
3107 G_PARAM_STATIC_STRINGS));
3115 g_param_spec_boolean(
"can-zoom-in",
3117 "Whether the view can be zoomed in further",
3119 static_cast<GParamFlags
>(G_PARAM_READABLE
3120 | G_PARAM_STATIC_STRINGS));
3128 g_param_spec_boolean(
"can-zoom-out",
3130 "Whether the view can be zoomed out further",
3132 static_cast<GParamFlags
>(G_PARAM_READABLE
3133 | G_PARAM_STATIC_STRINGS));
3142 g_param_spec_boolean(
"doc-password",
3143 "Document password capability",
3144 "Whether client supports providing document passwords",
3146 static_cast<GParamFlags
>(G_PARAM_READWRITE
3147 | G_PARAM_STATIC_STRINGS));
3155 g_param_spec_boolean(
"doc-password-to-modify",
3156 "Edit document password capability",
3157 "Whether the client supports providing passwords to edit documents",
3159 static_cast<GParamFlags
>(G_PARAM_READWRITE
3160 | G_PARAM_STATIC_STRINGS));
3169 g_param_spec_boolean(
"tiled-annotations",
3170 "Render comments in tiles",
3171 "Whether the client wants in tile comment rendering",
3173 static_cast<GParamFlags
>(G_PARAM_READWRITE
3174 | G_PARAM_STATIC_STRINGS));
3184 g_signal_new(
"load-changed",
3185 G_TYPE_FROM_CLASS (pGObjectClass),
3189 g_cclosure_marshal_VOID__DOUBLE,
3199 g_signal_new(
"edit-changed",
3200 G_TYPE_FROM_CLASS (pGObjectClass),
3204 g_cclosure_marshal_VOID__BOOLEAN,
3214 g_signal_new(
"command-changed",
3215 G_TYPE_FROM_CLASS(pGObjectClass),
3219 g_cclosure_marshal_VOID__STRING,
3229 g_signal_new(
"search-not-found",
3230 G_TYPE_FROM_CLASS(pGObjectClass),
3234 g_cclosure_marshal_VOID__STRING,
3244 g_signal_new(
"part-changed",
3245 G_TYPE_FROM_CLASS(pGObjectClass),
3249 g_cclosure_marshal_VOID__INT,
3259 g_signal_new(
"size-changed",
3260 G_TYPE_FROM_CLASS(pGObjectClass),
3264 g_cclosure_marshal_VOID__VOID,
3274 g_signal_new(
"hyperlink-clicked",
3275 G_TYPE_FROM_CLASS(pGObjectClass),
3279 g_cclosure_marshal_VOID__STRING,
3292 g_signal_new(
"cursor-changed",
3293 G_TYPE_FROM_CLASS(pGObjectClass),
3297 g_cclosure_marshal_generic,
3299 G_TYPE_INT, G_TYPE_INT,
3300 G_TYPE_INT, G_TYPE_INT);
3308 g_signal_new(
"search-result-count",
3309 G_TYPE_FROM_CLASS(pGObjectClass),
3313 g_cclosure_marshal_VOID__STRING,
3324 g_signal_new(
"command-result",
3325 G_TYPE_FROM_CLASS(pGObjectClass),
3329 g_cclosure_marshal_VOID__STRING,
3339 g_signal_new(
"address-changed",
3340 G_TYPE_FROM_CLASS(pGObjectClass),
3344 g_cclosure_marshal_VOID__STRING,
3354 g_signal_new(
"formula-changed",
3355 G_TYPE_FROM_CLASS(pGObjectClass),
3359 g_cclosure_marshal_VOID__STRING,
3369 g_signal_new(
"text-selection",
3370 G_TYPE_FROM_CLASS(pGObjectClass),
3374 g_cclosure_marshal_VOID__BOOLEAN,
3384 g_signal_new(
"content-control",
3385 G_TYPE_FROM_CLASS(pGObjectClass),
3389 g_cclosure_marshal_generic,
3414 g_signal_new(
"password-required",
3415 G_TYPE_FROM_CLASS(pGObjectClass),
3419 g_cclosure_marshal_generic,
3449 g_signal_new(
"comment",
3450 G_TYPE_FROM_CLASS(pGObjectClass),
3454 g_cclosure_marshal_generic,
3475 g_signal_new(
"ruler",
3476 G_TYPE_FROM_CLASS(pGObjectClass),
3480 g_cclosure_marshal_generic,
3516 g_signal_new(
"window",
3517 G_TYPE_FROM_CLASS(pGObjectClass),
3521 g_cclosure_marshal_generic,
3536 g_signal_new(
"invalidate-header",
3537 G_TYPE_FROM_CLASS(pGObjectClass),
3541 g_cclosure_marshal_generic,
3549 return GTK_WIDGET (g_initable_new (LOK_TYPE_DOC_VIEW, cancellable, error,
3550 "lopath", pPath ==
nullptr ? LOK_PATH : pPath,
3551 "halign", GTK_ALIGN_CENTER,
3552 "valign", GTK_ALIGN_CENTER,
3559 return GTK_WIDGET(g_initable_new(LOK_TYPE_DOC_VIEW, cancellable, error,
3560 "lopath", pPath ==
nullptr ? LOK_PATH : pPath,
3561 "userprofileurl", pUserProfile,
3562 "halign", GTK_ALIGN_CENTER,
3563 "valign", GTK_ALIGN_CENTER,
3568 const gchar* pRenderingArguments)
3570 LOKDocViewPrivate& pOldPriv =
getPrivate(pOldLOKDocView);
3571 GtkWidget* pNewDocView = GTK_WIDGET(g_initable_new(LOK_TYPE_DOC_VIEW,
nullptr,
nullptr,
3572 "lopath", pOldPriv->m_aLOPath.c_str(),
3573 "userprofileurl", pOldPriv->m_aUserProfileURL.c_str(),
3574 "lopointer", pOldPriv->m_pOffice,
3575 "docpointer", pOldPriv->m_pDocument,
3576 "halign", GTK_ALIGN_CENTER,
3577 "valign", GTK_ALIGN_CENTER,
3582 LOKDocViewPrivate& pNewPriv =
getPrivate(LOK_DOC_VIEW(pNewDocView));
3585 pDocument->pClass->createView(pDocument);
3586 pNewPriv->m_aRenderingArguments = pRenderingArguments;
3592SAL_DLLPUBLIC_EXPORT gboolean
3595 GTask* task = G_TASK(res);
3597 g_return_val_if_fail(g_task_is_valid(res, pDocView),
false);
3599 g_return_val_if_fail(error ==
nullptr || *error ==
nullptr,
false);
3601 return g_task_propagate_boolean(task, error);
3604SAL_DLLPUBLIC_EXPORT
void
3607 const gchar* pRenderingArguments,
3612 GTask* task = g_task_new(pDocView, cancellable,
callback, userdata);
3613 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3614 GError* error =
nullptr;
3618 g_object_set(G_OBJECT(pDocView),
"docpath", pPath,
nullptr);
3619 if (pRenderingArguments)
3620 priv->m_aRenderingArguments = pRenderingArguments;
3624 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
3625 if (error !=
nullptr)
3627 g_warning(
"Unable to call LOK_LOAD_DOC: %s", error->message);
3628 g_clear_error(&error);
3630 g_object_unref(task);
3633SAL_DLLPUBLIC_EXPORT LibreOfficeKitDocument*
3636 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3637 return priv->m_pDocument;
3640SAL_DLLPUBLIC_EXPORT
void
3646 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3647 priv->m_aVisibleArea = *pVisibleArea;
3648 priv->m_bVisibleAreaSet =
true;
3657bool lok_approxEqual(
double a,
double b)
3659 static const double e48 = 1.0 / (16777216.0 * 16777216.0);
3662 if (a == 0.0 || b == 0.0)
3664 const double d = fabs(a - b);
3665 return (d < fabs(a) * e48 && d < fabs(b) * e48);
3669SAL_DLLPUBLIC_EXPORT
void
3672 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3674 if (!priv->m_pDocument)
3681 if (lok_approxEqual(fZoom, priv->m_fZoom))
3684 gint nScaleFactor = gtk_widget_get_scale_factor(GTK_WIDGET(pDocView));
3686 priv->m_fZoom = fZoom;
3687 long nDocumentWidthPixels =
twipToPixel(priv->m_nDocumentWidthTwips, fZoom * nScaleFactor);
3688 long nDocumentHeightPixels =
twipToPixel(priv->m_nDocumentHeightTwips, fZoom * nScaleFactor);
3690 guint nColumns = ceil(
static_cast<double>(nDocumentWidthPixels) / nTileSizePixelsScaled);
3691 priv->m_pTileBuffer = std::make_unique<TileBuffer>(nColumns, nScaleFactor);
3692 gtk_widget_set_size_request(GTK_WIDGET(pDocView),
3693 nDocumentWidthPixels / nScaleFactor,
3694 nDocumentHeightPixels / nScaleFactor);
3699 bool bCanZoomIn = priv->m_fZoom <
MAX_ZOOM;
3700 bool bCanZoomOut = priv->m_fZoom >
MIN_ZOOM;
3701 if (bCanZoomIn !=
bool(priv->m_bCanZoomIn))
3703 priv->m_bCanZoomIn = bCanZoomIn;
3706 if (bCanZoomOut !=
bool(priv->m_bCanZoomOut))
3708 priv->m_bCanZoomOut = bCanZoomOut;
3715SAL_DLLPUBLIC_EXPORT gfloat
3718 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3719 return priv->m_fZoom;
3722SAL_DLLPUBLIC_EXPORT gint
3725 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3726 if (!priv->m_pDocument)
3730 setDocumentView(priv->m_pDocument, priv->m_nViewId);
3731 return priv->m_pDocument->pClass->getParts( priv->m_pDocument );
3734SAL_DLLPUBLIC_EXPORT gint
3737 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3738 if (!priv->m_pDocument)
3742 setDocumentView(priv->m_pDocument, priv->m_nViewId);
3743 return priv->m_pDocument->pClass->getPart( priv->m_pDocument );
3746SAL_DLLPUBLIC_EXPORT
void
3749 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3750 if (!priv->m_pDocument)
3753 if (nPart < 0 || nPart >= priv->m_nParts)
3755 g_warning(
"Invalid part request : %d", nPart);
3759 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
3761 GError* error =
nullptr;
3766 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
3767 if (error !=
nullptr)
3769 g_warning(
"Unable to call LOK_SET_PART: %s", error->message);
3770 g_clear_error(&error);
3772 g_object_unref(task);
3773 priv->m_nPartId = nPart;
3777 const gchar* pArguments)
3779 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3780 if (!priv->m_pDocument)
3786 setDocumentView(priv->m_pDocument, priv->m_nViewId);
3787 return priv->m_pDocument->pClass->sendContentControlEvent(priv->m_pDocument, pArguments);
3790SAL_DLLPUBLIC_EXPORT gchar*
3793 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3794 if (!priv->m_pDocument)
3798 setDocumentView(priv->m_pDocument, priv->m_nViewId);
3799 return priv->m_pDocument->pClass->getPartName( priv->m_pDocument, nPart );
3802SAL_DLLPUBLIC_EXPORT
void
3806 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3807 if (!priv->m_pDocument)
3810 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
3812 GError* error =
nullptr;
3817 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
3818 if (error !=
nullptr)
3820 g_warning(
"Unable to call LOK_SET_PARTMODE: %s", error->message);
3821 g_clear_error(&error);
3823 g_object_unref(task);
3826SAL_DLLPUBLIC_EXPORT
void
3829 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3831 if (priv->m_pTileBuffer !=
nullptr)
3832 priv->m_pTileBuffer->resetAllTiles();
3833 priv->m_nLoadProgress = 0.0;
3835 memset(&priv->m_aVisibleCursor, 0,
sizeof(priv->m_aVisibleCursor));
3836 priv->m_bCursorOverlayVisible =
false;
3837 priv->m_bCursorVisible =
false;
3839 priv->m_nLastButtonPressTime = 0;
3840 priv->m_nLastButtonReleaseTime = 0;
3841 priv->m_aTextSelectionRectangles.clear();
3842 priv->m_aContentControlRectangles.clear();
3844 memset(&priv->m_aTextSelectionStart, 0,
sizeof(priv->m_aTextSelectionStart));
3845 memset(&priv->m_aTextSelectionEnd, 0,
sizeof(priv->m_aTextSelectionEnd));
3846 memset(&priv->m_aGraphicSelection, 0,
sizeof(priv->m_aGraphicSelection));
3847 priv->m_bInDragGraphicSelection =
false;
3848 memset(&priv->m_aCellCursor, 0,
sizeof(priv->m_aCellCursor));
3850 cairo_surface_destroy(priv->m_pHandleStart);
3851 priv->m_pHandleStart =
nullptr;
3852 memset(&priv->m_aHandleStartRect, 0,
sizeof(priv->m_aHandleStartRect));
3853 priv->m_bInDragStartHandle =
false;
3855 cairo_surface_destroy(priv->m_pHandleMiddle);
3856 priv->m_pHandleMiddle =
nullptr;
3857 memset(&priv->m_aHandleMiddleRect, 0,
sizeof(priv->m_aHandleMiddleRect));
3858 priv->m_bInDragMiddleHandle =
false;
3860 cairo_surface_destroy(priv->m_pHandleEnd);
3861 priv->m_pHandleEnd =
nullptr;
3862 memset(&priv->m_aHandleEndRect, 0,
sizeof(priv->m_aHandleEndRect));
3863 priv->m_bInDragEndHandle =
false;
3865 memset(&priv->m_aGraphicHandleRects, 0,
sizeof(priv->m_aGraphicHandleRects));
3866 memset(&priv->m_bInDragGraphicHandles, 0,
sizeof(priv->m_bInDragGraphicHandles));
3868 gtk_widget_queue_draw(GTK_WIDGET(pDocView));
3871SAL_DLLPUBLIC_EXPORT
void
3875 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3876 if (!priv->m_pDocument)
3879 GTask* task = g_task_new(pDocView,
nullptr,
nullptr,
nullptr);
3881 GError* error =
nullptr;
3886 g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
3887 if (error !=
nullptr)
3889 g_warning(
"Unable to call LOK_SET_EDIT: %s", error->message);
3890 g_clear_error(&error);
3892 g_object_unref(task);
3895SAL_DLLPUBLIC_EXPORT gboolean
3898 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3899 return priv->m_bEdit;
3902SAL_DLLPUBLIC_EXPORT
void
3904 const gchar* pCommand,
3905 const gchar* pArguments,
3906 gboolean bNotifyWhenFinished)
3908 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3909 if (!priv->m_pDocument)
3913 LOKPostCommand(pDocView, pCommand, pArguments, bNotifyWhenFinished);
3915 g_info (
"LOK_POST_COMMAND: ignoring commands in view-only mode");
3918SAL_DLLPUBLIC_EXPORT gchar *
3920 const gchar* pCommand)
3922 g_return_val_if_fail (LOK_IS_DOC_VIEW (pDocView),
nullptr);
3923 g_return_val_if_fail (pCommand !=
nullptr,
nullptr);
3929 return pDocument->pClass->getCommandValues(pDocument, pCommand);
3932SAL_DLLPUBLIC_EXPORT
void
3935 gboolean bHighlightAll)
3937 doSearch(pDocView, pText,
true, bHighlightAll);
3940SAL_DLLPUBLIC_EXPORT
void
3943 gboolean bHighlightAll)
3945 doSearch(pDocView, pText,
false, bHighlightAll);
3948SAL_DLLPUBLIC_EXPORT
void
3952 doSearch(pDocView, pText,
false,
true);
3955SAL_DLLPUBLIC_EXPORT gchar*
3957 const gchar* pMimeType,
3958 gchar** pUsedMimeType)
3964 std::stringstream ss;
3965 ss <<
"lok::Document::getTextSelection('" << pMimeType <<
"')";
3966 g_info(
"%s", ss.str().c_str());
3967 return pDocument->pClass->getTextSelection(pDocument, pMimeType, pUsedMimeType);
3970SAL_DLLPUBLIC_EXPORT gboolean
3972 const gchar* pMimeType,
3976 LOKDocViewPrivate& priv =
getPrivate(pDocView);
3977 LibreOfficeKitDocument* pDocument = priv->m_pDocument;
3985 g_info (
"ignoring paste in view-only mode");
3991 std::stringstream ss;
3992 ss <<
"lok::Document::paste('" << pMimeType <<
"', '" << std::string(
pData, nSize) <<
", "<<nSize<<
"')";
3993 g_info(
"%s", ss.str().c_str());
3994 ret = pDocument->pClass->paste(pDocument, pMimeType,
pData, nSize);
4000SAL_DLLPUBLIC_EXPORT
void
4003 const gchar* pPassword)
4005 LOKDocViewPrivate& priv =
getPrivate(pDocView);
4007 priv->m_pOffice->pClass->setDocumentPassword(priv->m_pOffice, pURL, pPassword);
4010SAL_DLLPUBLIC_EXPORT gchar*
4013 LOKDocViewPrivate& priv =
getPrivate(pDocView);
4015 return priv->m_pOffice->pClass->getVersionInfo(priv->m_pOffice);
4019SAL_DLLPUBLIC_EXPORT gfloat
4022 LOKDocViewPrivate& priv =
getPrivate(pDocView);
4026SAL_DLLPUBLIC_EXPORT gfloat
4029 LOKDocViewPrivate& priv =
getPrivate(pDocView);
const PropertyValue * pValues
struct _cairo_surface cairo_surface_t
This class represents a single tile in the tile buffer.
cairo_surface_t * getBuffer()
Function to get the pointer to enclosing cairo_surface_t.
struct _GtkWidget GtkWidget
constexpr sal_uInt16 KEY_MOD2
constexpr sal_uInt16 KEY_MOD1
constexpr sal_uInt16 KEY_SHIFT
static std::string getAuthorRenderingArgument(LOKDocViewPrivate &priv)
Looks up the author string from initializeForRendering()'s rendering arguments.
static GdkRectangle payloadToRectangle(LOKDocView *pDocView, const char *pPayload)
static void setGraphicSelectionInThread(gpointer data)
G_DEFINE_TYPE_WITH_CODE(LOKDocView, lok_doc_view, GTK_TYPE_DRAWING_AREA, G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, lok_doc_view_initable_iface_init))
SAL_DLLPUBLIC_EXPORT void lok_doc_view_open_document(LOKDocView *pDocView, const gchar *pPath, const gchar *pRenderingArguments, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer userdata)
static void refreshSize(LOKDocView *pDocView)
static gboolean postDocumentLoad(gpointer pData)
Set up LOKDocView after the document is loaded, invoked on the main thread by openDocumentInThread() ...
static int lok_poll_callback(void *, int timeoutUs)
static void renderGraphicHandle(LOKDocView *pDocView, cairo_t *pCairo, const GdkRectangle &rSelection, const GdkRGBA &rColor)
Renders handles around an rSelection rectangle on pCairo.
static void openDocumentInThread(gpointer data)
static bool handleTextSelectionOnButtonPress(GdkRectangle &aClick, LOKDocView *pDocView)
if handled, returns TRUE else FALSE
SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_partmode(LOKDocView *pDocView, int nPartMode)
static gboolean signalKey(GtkWidget *pWidget, GdkEventKey *pEvent)
static void postMouseEventInThread(gpointer data)
static bool handleGraphicSelectionOnButtonPress(GdkRectangle &aClick, LOKDocView *pDocView)
if handled, returns TRUE else FALSE
SAL_DLLPUBLIC_EXPORT void lok_doc_view_post_command(LOKDocView *pDocView, const gchar *pCommand, const gchar *pArguments, gboolean bNotifyWhenFinished)
static void setTilesInvalid(LOKDocView *pDocView, const GdkRectangle &rRectangle)
static gboolean lok_doc_view_draw(GtkWidget *pWidget, cairo_t *pCairo)
static void lokThreadFunc(gpointer data, gpointer)
static bool handleTextSelectionOnButtonRelease(LOKDocView *pDocView)
if handled, returns TRUE else FALSE
static void lok_wake_callback(void *)
static void reportError(LOKDocView *, const std::string &rString)
SAL_DLLPUBLIC_EXPORT gfloat lok_doc_view_twip_to_pixel(LOKDocView *pDocView, float fInput)
static gboolean lok_doc_view_signal_button(GtkWidget *pWidget, GdkEventButton *pEvent)
static void commandChanged(LOKDocView *pDocView, const std::string &rString)
static gboolean lok_doc_view_signal_motion(GtkWidget *pWidget, GdkEventMotion *pEvent)
static void formulaChanged(LOKDocView *pDocView, const std::string &rString)
static void setEditInThread(gpointer data)
static void lok_doc_view_init(LOKDocView *pDocView)
static void postCommandInThread(gpointer data)
static guint doc_view_signals[LAST_SIGNAL]
SAL_DLLPUBLIC_EXPORT gint lok_doc_view_get_parts(LOKDocView *pDocView)
#define GRAPHIC_HANDLE_COUNT
SAL_DLLPUBLIC_EXPORT void lok_doc_view_find_prev(LOKDocView *pDocView, const gchar *pText, gboolean bHighlightAll)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_highlight_all(LOKDocView *pDocView, const gchar *pText)
static bool handleGraphicSelectionOnButtonRelease(LOKDocView *pDocView, GdkEventButton *pEvent)
if handled, returns TRUE else FALSE
static void renderHandle(LOKDocView *pDocView, cairo_t *pCairo, const GdkRectangle &rCursor, cairo_surface_t *pHandle, GdkRectangle &rRectangle)
static void doSearch(LOKDocView *pDocView, const char *pText, bool bBackwards, bool highlightAll)
static void updateClientZoom(LOKDocView *pDocView)
static void commandResult(LOKDocView *pDocView, const std::string &rString)
SAL_DLLPUBLIC_EXPORT LibreOfficeKitDocument * lok_doc_view_get_document(LOKDocView *pDocView)
SAL_DLLPUBLIC_EXPORT gchar * lok_doc_view_get_version_info(LOKDocView *pDocView)
static bool renderDocument(LOKDocView *pDocView, cairo_t *pCairo)
static void searchResultCount(LOKDocView *pDocView, const std::string &rString)
static void lok_doc_view_finalize(GObject *object)
static void getDragPoint(GdkRectangle *pHandle, GdkEventMotion *pEvent, GdkPoint *pPoint)
static void lok_doc_view_destroy(GtkWidget *widget)
static void lok_doc_view_class_init(LOKDocViewClass *pClass)
static void LOKPostCommand(LOKDocView *pDocView, const gchar *pCommand, const gchar *pArguments, bool bNotifyWhenFinished)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_part(LOKDocView *pDocView, int nPart)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_find_next(LOKDocView *pDocView, const gchar *pText, gboolean bHighlightAll)
static void searchNotFound(LOKDocView *pDocView, const std::string &rString)
static std::map< std::string, int > g_aAuthorViews
Author string <-> View ID map.
#define CURSOR_HANDLE_DIR
static void setPart(LOKDocView *pDocView, const std::string &rString)
SAL_DLLPUBLIC_EXPORT gboolean lok_doc_view_open_document_finish(LOKDocView *pDocView, GAsyncResult *res, GError **error)
SAL_DLLPUBLIC_EXPORT GtkWidget * lok_doc_view_new(const gchar *pPath, GCancellable *cancellable, GError **error)
static gboolean queueDraw(gpointer pData)
Trigger a redraw, invoked on the main thread by other functions running in a thread.
SAL_DLLPUBLIC_EXPORT GtkWidget * lok_doc_view_new_from_widget(LOKDocView *pOldLOKDocView, const gchar *pRenderingArguments)
static void hyperlinkClicked(LOKDocView *pDocView, const std::string &rString)
static void lok_doc_view_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_send_content_control_event(LOKDocView *pDocView, const gchar *pArguments)
SAL_DLLPUBLIC_EXPORT gchar * lok_doc_view_get_command_values(LOKDocView *pDocView, const gchar *pCommand)
static void globalCallbackWorker(int nType, const char *pPayload, void *pData)
static void setClientZoomInThread(gpointer data)
static void lok_doc_view_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec)
SAL_DLLPUBLIC_EXPORT gboolean lok_doc_view_get_edit(LOKDocView *pDocView)
static gboolean globalCallback(gpointer pData)
Implementation of the global callback handler, invoked by globalCallback();.
SAL_DLLPUBLIC_EXPORT gfloat lok_doc_view_get_zoom(LOKDocView *pDocView)
static void lok_doc_view_initable_iface_init(GInitableIface *iface)
static std::mutex g_aLOKMutex
This is expected to be locked during setView(), doSomethingElse() LOK calls.
static gboolean lok_doc_view_initable_init(GInitable *initable, GCancellable *, GError **error)
static gboolean callback(gpointer pData)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_document_password(LOKDocView *pDocView, const gchar *pURL, const gchar *pPassword)
static void callbackWorker(int nType, const char *pPayload, void *pData)
static void setPartInThread(gpointer data)
SAL_DLLPUBLIC_EXPORT GtkWidget * lok_doc_view_new_from_user_profile(const gchar *pPath, const gchar *pUserProfile, GCancellable *cancellable, GError **error)
static void onStyleContextChanged(LOKDocView *pDocView)
static void addressChanged(LOKDocView *pDocView, const std::string &rString)
static gboolean timeout_wakeup(void *)
static void setPartmodeInThread(gpointer data)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_edit(LOKDocView *pDocView, gboolean bEdit)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_visible_area(LOKDocView *pDocView, GdkRectangle *pVisibleArea)
static std::vector< GdkRectangle > payloadToRectangles(LOKDocView *pDocView, const char *pPayload)
static void postKeyEventInThread(gpointer data)
static void paintTileInThread(gpointer data)
SAL_DLLPUBLIC_EXPORT gchar * lok_doc_view_copy_selection(LOKDocView *pDocView, const gchar *pMimeType, gchar **pUsedMimeType)
@ PROP_DOC_PASSWORD_TO_MODIFY
static gboolean handleTimeout(gpointer pData)
static gboolean spin_lok_loop(void *pData)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_set_zoom(LOKDocView *pDocView, float fZoom)
SAL_DLLPUBLIC_EXPORT gchar * lok_doc_view_get_part_name(LOKDocView *pDocView, int nPart)
SAL_DLLPUBLIC_EXPORT gfloat lok_doc_view_pixel_to_twip(LOKDocView *pDocView, float fInput)
static LOKDocViewPrivate & getPrivate(LOKDocView *pDocView)
static bool isEmptyRectangle(const GdkRectangle &rRectangle)
SAL_DLLPUBLIC_EXPORT gboolean lok_doc_view_paste(LOKDocView *pDocView, const gchar *pMimeType, const gchar *pData, gsize nSize)
SAL_DLLPUBLIC_EXPORT gint lok_doc_view_get_part(LOKDocView *pDocView)
#define G_SOURCE_CONTINUE
static void paintTileCallback(GObject *sourceObject, GAsyncResult *res, gpointer userData)
Callback called in the main UI thread when paintTileInThread in LOK thread has finished.
static bool renderOverlay(LOKDocView *pDocView, cairo_t *pCairo)
static const GdkRGBA & getDarkColor(int nViewId, LOKDocViewPrivate &priv)
SAL_DLLPUBLIC_EXPORT void lok_doc_view_reset_view(LOKDocView *pDocView)
static gpointer paintTileFinish(LOKDocView *pDocView, GAsyncResult *res, GError **error)
Finishes the paint tile operation and returns the result, if any.
std::unique_ptr< sal_Int32[]> pData
A struct that we use to store the data about the LOK call.
int m_nSetGraphicSelectionX
int m_nPostMouseEventButton
static void destroy(void *pMemory)
Wrapper around delete to help GLib.
gboolean m_bEdit
set_edit parameter
int m_nPartMode
set_partmode parameter
int m_nPart
set_part parameter
TileBuffer * m_pTileBuffer
int m_nSetGraphicSelectionType
int m_nSetGraphicSelectionY
int m_nPostMouseEventModifier
int m_nPostMouseEventType
int m_nType
To identify the type of LOK call.
gboolean m_bNotifyWhenFinished
int m_nPostMouseEventCount
Wrapper around LOKDocViewPrivateImpl, managed by malloc/memset/free.
LOKDocViewPrivateImpl * operator->()
LOKDocViewPrivateImpl * m_pImpl
float pixelToTwip(float fInput, float zoom)
Converts the pixel value to zoom independent twip value.
float twipToPixel(float fInput, float zoom)
Converts the zoom independent twip value pixel value.
#define LOK_TILEBUFFER_ERROR
const int nTileSizePixels
@ LOK_SET_GRAPHIC_SELECTION