1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sal/config.h>
26 #include <unx/salinst.h>
27 #include <unx/gensys.h>
28 #include <headless/svpinst.hxx>
29 #include <com/sun/star/datatransfer/DataFlavor.hpp>
30 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
31 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
32 #include <com/sun/star/lang/XInitialization.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/awt/XWindow.hpp>
35 #include <cppuhelper/compbase.hxx>
36 #include <vcl/weld.hxx>
37 #include <vcl/weldutils.hxx>
40 vcl::Font
pango_to_vcl(const PangoFontDescription
* font
, const css::lang::Locale
& rLocale
);
43 class GtkYieldMutex final
: public SalYieldMutex
45 thread_local
static std::stack
<sal_uInt32
> yieldCounts
;
55 #if GTK_CHECK_VERSION(4, 0, 0)
56 gint
gtk_dialog_run(GtkDialog
*dialog
);
58 struct read_transfer_result
60 enum { BlockSize
= 8192 };
64 std::vector
<sal_Int8
> aVector
;
66 static void read_block_async_completed(GObject
* source
, GAsyncResult
* res
, gpointer user_data
);
68 OUString
get_as_string() const;
69 css::uno::Sequence
<sal_Int8
> get_as_sequence() const;
76 std::vector
<css::datatransfer::DataFlavor
> aInfoToFlavor
;
77 #if GTK_CHECK_VERSION(4, 0, 0)
78 std::vector
<OString
> FormatsToGtk(const css::uno::Sequence
<css::datatransfer::DataFlavor
> &rFormats
);
80 std::vector
<GtkTargetEntry
> FormatsToGtk(const css::uno::Sequence
<css::datatransfer::DataFlavor
> &rFormats
);
82 #if GTK_CHECK_VERSION(4, 0, 0)
83 void setSelectionData(const css::uno::Reference
<css::datatransfer::XTransferable
> &rTrans
,
84 GdkContentProvider
* provider
,
85 const char* mime_type
,
86 GOutputStream
* stream
,
88 GCancellable
* cancellable
,
89 GAsyncReadyCallback callback
,
92 void setSelectionData(const css::uno::Reference
<css::datatransfer::XTransferable
> &rTrans
,
93 GtkSelectionData
*selection_data
, guint info
);
96 #if GTK_CHECK_VERSION(4, 0, 0)
97 OString
makeGtkTargetEntry(const css::datatransfer::DataFlavor
& rFlavor
);
99 GtkTargetEntry
makeGtkTargetEntry(const css::datatransfer::DataFlavor
& rFlavor
);
103 class GtkTransferable
: public cppu::WeakImplHelper
<css::datatransfer::XTransferable
>
106 #if GTK_CHECK_VERSION(4, 0, 0)
107 std::map
<OUString
, OString
> m_aMimeTypeToGtkType
;
109 std::map
<OUString
, GdkAtom
> m_aMimeTypeToGtkType
;
112 #if GTK_CHECK_VERSION(4, 0, 0)
113 std::vector
<css::datatransfer::DataFlavor
> getTransferDataFlavorsAsVector(const char * const *targets
, gint n_targets
);
115 std::vector
<css::datatransfer::DataFlavor
> getTransferDataFlavorsAsVector(GdkAtom
*targets
, gint n_targets
);
119 virtual css::uno::Any SAL_CALL
getTransferData(const css::datatransfer::DataFlavor
& rFlavor
) override
= 0;
120 virtual std::vector
<css::datatransfer::DataFlavor
> getTransferDataFlavorsAsVector() = 0;
121 virtual css::uno::Sequence
<css::datatransfer::DataFlavor
> SAL_CALL
getTransferDataFlavors() override
;
122 virtual sal_Bool SAL_CALL
isDataFlavorSupported(const css::datatransfer::DataFlavor
& rFlavor
) override
;
125 class GtkDnDTransferable
;
127 class GtkInstDropTarget final
: public cppu::WeakComponentImplHelper
<css::datatransfer::dnd::XDropTarget
,
128 css::lang::XInitialization
,
129 css::lang::XServiceInfo
>
132 GtkSalFrame
* m_pFrame
;
133 GtkDnDTransferable
* m_pFormatConversionRequest
;
136 sal_Int8 m_nDefaultActions
;
137 std::vector
<css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>> m_aListeners
;
140 virtual ~GtkInstDropTarget() override
;
143 virtual void SAL_CALL
initialize(const css::uno::Sequence
<css::uno::Any
>& rArgs
) override
;
147 virtual void SAL_CALL
addDropTargetListener(const css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>&) override
;
148 virtual void SAL_CALL
removeDropTargetListener(const css::uno::Reference
<css::datatransfer::dnd::XDropTargetListener
>&) override
;
149 virtual sal_Bool SAL_CALL
isActive() override
;
150 virtual void SAL_CALL
setActive(sal_Bool active
) override
;
151 virtual sal_Int8 SAL_CALL
getDefaultActions() override
;
152 virtual void SAL_CALL
setDefaultActions(sal_Int8 actions
) override
;
154 OUString SAL_CALL
getImplementationName() override
;
156 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
;
158 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
160 void fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent
& dtdee
);
161 void fire_dragOver(const css::datatransfer::dnd::DropTargetDragEvent
& dtde
);
162 void fire_drop(const css::datatransfer::dnd::DropTargetDropEvent
& dtde
);
163 void fire_dragExit(const css::datatransfer::dnd::DropTargetEvent
& dte
);
165 void SetFormatConversionRequest(GtkDnDTransferable
*pRequest
)
167 m_pFormatConversionRequest
= pRequest
;
170 #if !GTK_CHECK_VERSION(4, 0, 0)
171 gboolean
signalDragMotion(GtkWidget
* pWidget
, GdkDragContext
* context
, gint x
, gint y
, guint time
);
172 gboolean
signalDragDrop(GtkWidget
* pWidget
, GdkDragContext
* context
, gint x
, gint y
, guint time
);
174 GdkDragAction
signalDragMotion(GtkDropTargetAsync
*context
, GdkDrop
*drop
, double x
, double y
);
175 gboolean
signalDragDrop(GtkDropTargetAsync
*context
, GdkDrop
*drop
, double x
, double y
);
178 void signalDragLeave(GtkWidget
* pWidget
);
180 #if !GTK_CHECK_VERSION(4, 0, 0)
181 void signalDragDropReceived(GtkWidget
* pWidget
, GdkDragContext
* context
, gint x
, gint y
, GtkSelectionData
* data
, guint ttype
, guint time
);
185 class GtkInstDragSource final
: public cppu::WeakComponentImplHelper
<css::datatransfer::dnd::XDragSource
,
186 css::lang::XInitialization
,
187 css::lang::XServiceInfo
>
190 GtkSalFrame
* m_pFrame
;
191 css::uno::Reference
<css::datatransfer::dnd::XDragSourceListener
> m_xListener
;
192 css::uno::Reference
<css::datatransfer::XTransferable
> m_xTrans
;
193 VclToGtkHelper m_aConversionHelper
;
196 : WeakComponentImplHelper(m_aMutex
)
201 void set_datatransfer(const css::uno::Reference
<css::datatransfer::XTransferable
>& rTrans
,
202 const css::uno::Reference
<css::datatransfer::dnd::XDragSourceListener
>& rListener
);
204 #if !GTK_CHECK_VERSION(4, 0, 0)
205 std::vector
<GtkTargetEntry
> FormatsToGtk(const css::uno::Sequence
<css::datatransfer::DataFlavor
> &rFormats
);
208 void setActiveDragSource();
210 virtual ~GtkInstDragSource() override
;
213 virtual sal_Bool SAL_CALL
isDragImageSupported() override
;
214 virtual sal_Int32 SAL_CALL
getDefaultCursor(sal_Int8 dragAction
) override
;
215 virtual void SAL_CALL
startDrag(
216 const css::datatransfer::dnd::DragGestureEvent
& trigger
, sal_Int8 sourceActions
, sal_Int32 cursor
, sal_Int32 image
,
217 const css::uno::Reference
< css::datatransfer::XTransferable
>& transferable
,
218 const css::uno::Reference
< css::datatransfer::dnd::XDragSourceListener
>& listener
) override
;
221 virtual void SAL_CALL
initialize(const css::uno::Sequence
<css::uno::Any
>& rArguments
) override
;
224 OUString SAL_CALL
getImplementationName() override
;
226 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
;
228 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
232 #if GTK_CHECK_VERSION(4, 0, 0)
233 void dragEnd(GdkDrag
* drag
);
235 void dragEnd(GdkDragContext
* context
);
236 void dragDataGet(GtkSelectionData
*data
, guint info
);
239 // For LibreOffice internal D&D we provide the Transferable without Gtk
240 // intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this
241 static GtkInstDragSource
* g_ActiveDragSource
;
242 css::uno::Reference
<css::datatransfer::XTransferable
> const & GetTransferable() const { return m_xTrans
; }
245 enum SelectionType
{ SELECTION_CLIPBOARD
= 0, SELECTION_PRIMARY
= 1 };
248 class GtkInstance final
: public SvpSalInstance
251 GtkInstance( std::unique_ptr
<SalYieldMutex
> pMutex
);
252 virtual ~GtkInstance() override
;
254 virtual void AfterAppInit() override
;
256 virtual SalFrame
* CreateFrame( SalFrame
* pParent
, SalFrameStyleFlags nStyle
) override
;
257 virtual SalFrame
* CreateChildFrame( SystemParentData
* pParent
, SalFrameStyleFlags nStyle
) override
;
258 virtual SalObject
* CreateObject( SalFrame
* pParent
, SystemWindowData
* pWindowData
, bool bShow
) override
;
259 virtual SalSystem
* CreateSalSystem() override
;
260 virtual SalInfoPrinter
* CreateInfoPrinter(SalPrinterQueueInfo
* pPrinterQueueInfo
, ImplJobSetup
* pJobSetup
) override
;
261 virtual std::unique_ptr
<SalPrinter
> CreatePrinter( SalInfoPrinter
* pInfoPrinter
) override
;
262 virtual std::unique_ptr
<SalMenu
> CreateMenu( bool, Menu
* ) override
;
263 virtual std::unique_ptr
<SalMenuItem
> CreateMenuItem( const SalItemParams
& ) override
;
264 virtual SalTimer
* CreateSalTimer() override
;
265 virtual void AddToRecentDocumentList(const OUString
& rFileUrl
, const OUString
& rMimeType
, const OUString
& rDocumentService
) override
;
266 virtual std::unique_ptr
<SalVirtualDevice
>
267 CreateVirtualDevice( SalGraphics
&,
268 tools::Long
&nDX
, tools::Long
&nDY
,
269 DeviceFormat eFormat
,
270 const SystemGraphicsData
* = nullptr ) override
;
271 virtual std::shared_ptr
<SalBitmap
> CreateSalBitmap() override
;
273 virtual bool DoYield(bool bWait
, bool bHandleAllCurrentEvents
) override
;
274 virtual bool AnyInput( VclInputFlags nType
) override
;
275 // impossible to handle correctly, as "main thread" depends on the dispatch mutex
276 virtual bool IsMainThread() const override
{ return false; }
278 virtual std::unique_ptr
<GenPspGraphics
> CreatePrintGraphics() override
;
280 virtual bool hasNativeFileSelection() const override
{ return true; }
282 virtual css::uno::Reference
< css::ui::dialogs::XFilePicker2
>
283 createFilePicker( const css::uno::Reference
< css::uno::XComponentContext
>& ) override
;
284 virtual css::uno::Reference
< css::ui::dialogs::XFolderPicker2
>
285 createFolderPicker( const css::uno::Reference
< css::uno::XComponentContext
>& ) override
;
287 virtual css::uno::Reference
< css::uno::XInterface
> CreateClipboard( const css::uno::Sequence
< css::uno::Any
>& i_rArguments
) override
;
288 virtual css::uno::Reference
<css::uno::XInterface
> ImplCreateDragSource(const SystemEnvData
*) override
;
289 virtual css::uno::Reference
<css::uno::XInterface
> ImplCreateDropTarget(const SystemEnvData
*) override
;
290 virtual OpenGLContext
* CreateOpenGLContext() override
;
291 virtual std::unique_ptr
<weld::Builder
> CreateBuilder(weld::Widget
* pParent
, const OUString
& rUIRoot
, const OUString
& rUIFile
) override
;
292 virtual std::unique_ptr
<weld::Builder
> CreateInterimBuilder(vcl::Window
* pParent
, const OUString
& rUIRoot
, const OUString
& rUIFile
,
293 bool bAllowCycleFocusOut
, sal_uInt64 nLOKWindowId
= 0) override
;
294 virtual weld::MessageDialog
* CreateMessageDialog(weld::Widget
* pParent
, VclMessageType eMessageType
, VclButtonsType eButtonType
, const OUString
&rPrimaryMessage
) override
;
295 virtual weld::Window
* GetFrameWeld(const css::uno::Reference
<css::awt::XWindow
>& rWindow
) override
;
297 virtual const cairo_font_options_t
* GetCairoFontOptions() override
;
298 const cairo_font_options_t
* GetLastSeenCairoFontOptions() const;
299 void ResetLastSeenCairoFontOptions(const cairo_font_options_t
* pOptions
);
303 void* CreateGStreamerSink(const SystemChildWindow
*) override
;
306 GtkSalTimer
*m_pTimer
;
307 css::uno::Reference
<css::uno::XInterface
> m_aClipboards
[2];
308 bool IsTimerExpired();
310 cairo_font_options_t
* m_pLastCairoFontOptions
;
313 inline GtkInstance
* GetGtkInstance() { return static_cast<GtkInstance
*>(GetSalInstance()); }
315 class SalGtkXWindow final
: public weld::TransportAsXWindow
318 weld::Window
* m_pWeldWidget
;
319 GtkWidget
* m_pWidget
;
322 SalGtkXWindow(weld::Window
* pWeldWidget
, GtkWidget
* pWidget
)
323 : TransportAsXWindow(pWeldWidget
)
324 , m_pWeldWidget(pWeldWidget
)
329 virtual void clear() override
331 m_pWeldWidget
= nullptr;
333 TransportAsXWindow::clear();
336 GtkWidget
* getGtkWidget() const
341 weld::Window
* getFrameWeld() const
343 return m_pWeldWidget
;
347 GdkPixbuf
* load_icon_by_name(const OUString
& rIconName
);
349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */