/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #ifndef INCLUDED_VCL_INC_UNX_GTK_GTKINST_HXX #define INCLUDED_VCL_INC_UNX_GTK_GTKINST_HXX #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include vcl::Font pango_to_vcl(const PangoFontDescription* font, const css::lang::Locale& rLocale); class GenPspGraphics; class GtkYieldMutex final : public SalYieldMutex { thread_local static std::stack yieldCounts; public: GtkYieldMutex() {} void ThreadsEnter(); void ThreadsLeave(); }; class GtkSalFrame; #if GTK_CHECK_VERSION(4, 0, 0) gint gtk_dialog_run(GtkDialog *dialog); struct read_transfer_result { enum { BlockSize = 8192 }; size_t nRead = 0; bool bDone = false; std::vector aVector; static void read_block_async_completed(GObject* source, GAsyncResult* res, gpointer user_data); OUString get_as_string() const; css::uno::Sequence get_as_sequence() const; }; #endif struct VclToGtkHelper { std::vector aInfoToFlavor; #if GTK_CHECK_VERSION(4, 0, 0) std::vector FormatsToGtk(const css::uno::Sequence &rFormats); #else std::vector FormatsToGtk(const css::uno::Sequence &rFormats); #endif #if GTK_CHECK_VERSION(4, 0, 0) void setSelectionData(const css::uno::Reference &rTrans, GdkContentProvider* provider, const char* mime_type, GOutputStream* stream, int io_priority, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data); #else void setSelectionData(const css::uno::Reference &rTrans, GtkSelectionData *selection_data, guint info); #endif private: #if GTK_CHECK_VERSION(4, 0, 0) OString makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor); #else GtkTargetEntry makeGtkTargetEntry(const css::datatransfer::DataFlavor& rFlavor); #endif }; class GtkTransferable : public cppu::WeakImplHelper { protected: #if GTK_CHECK_VERSION(4, 0, 0) std::map m_aMimeTypeToGtkType; #else std::map m_aMimeTypeToGtkType; #endif #if GTK_CHECK_VERSION(4, 0, 0) std::vector getTransferDataFlavorsAsVector(const char * const *targets, gint n_targets); #else std::vector getTransferDataFlavorsAsVector(GdkAtom *targets, gint n_targets); #endif public: virtual css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor) override = 0; virtual std::vector getTransferDataFlavorsAsVector() = 0; virtual css::uno::Sequence SAL_CALL getTransferDataFlavors() override; virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor) override; }; class GtkDnDTransferable; class GtkInstDropTarget final : public cppu::WeakComponentImplHelper { osl::Mutex m_aMutex; GtkSalFrame* m_pFrame; GtkDnDTransferable* m_pFormatConversionRequest; bool m_bActive; bool m_bInDrag; sal_Int8 m_nDefaultActions; std::vector> m_aListeners; public: GtkInstDropTarget(); virtual ~GtkInstDropTarget() override; // XInitialization virtual void SAL_CALL initialize(const css::uno::Sequence& rArgs) override; void deinitialize(); // XDropTarget virtual void SAL_CALL addDropTargetListener(const css::uno::Reference&) override; virtual void SAL_CALL removeDropTargetListener(const css::uno::Reference&) override; virtual sal_Bool SAL_CALL isActive() override; virtual void SAL_CALL setActive(sal_Bool active) override; virtual sal_Int8 SAL_CALL getDefaultActions() override; virtual void SAL_CALL setDefaultActions(sal_Int8 actions) override; OUString SAL_CALL getImplementationName() override; sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; css::uno::Sequence SAL_CALL getSupportedServiceNames() override; void fire_dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent& dtdee); void fire_dragOver(const css::datatransfer::dnd::DropTargetDragEvent& dtde); void fire_drop(const css::datatransfer::dnd::DropTargetDropEvent& dtde); void fire_dragExit(const css::datatransfer::dnd::DropTargetEvent& dte); void SetFormatConversionRequest(GtkDnDTransferable *pRequest) { m_pFormatConversionRequest = pRequest; } #if !GTK_CHECK_VERSION(4, 0, 0) gboolean signalDragMotion(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time); gboolean signalDragDrop(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, guint time); #else GdkDragAction signalDragMotion(GtkDropTargetAsync *context, GdkDrop *drop, double x, double y); gboolean signalDragDrop(GtkDropTargetAsync *context, GdkDrop *drop, double x, double y); #endif void signalDragLeave(GtkWidget* pWidget); #if !GTK_CHECK_VERSION(4, 0, 0) void signalDragDropReceived(GtkWidget* pWidget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint ttype, guint time); #endif }; class GtkInstDragSource final : public cppu::WeakComponentImplHelper { osl::Mutex m_aMutex; GtkSalFrame* m_pFrame; css::uno::Reference m_xListener; css::uno::Reference m_xTrans; VclToGtkHelper m_aConversionHelper; public: GtkInstDragSource() : WeakComponentImplHelper(m_aMutex) , m_pFrame(nullptr) { } void set_datatransfer(const css::uno::Reference& rTrans, const css::uno::Reference& rListener); #if !GTK_CHECK_VERSION(4, 0, 0) std::vector FormatsToGtk(const css::uno::Sequence &rFormats); #endif void setActiveDragSource(); virtual ~GtkInstDragSource() override; // XDragSource virtual sal_Bool SAL_CALL isDragImageSupported() override; virtual sal_Int32 SAL_CALL getDefaultCursor(sal_Int8 dragAction) override; virtual void SAL_CALL startDrag( const css::datatransfer::dnd::DragGestureEvent& trigger, sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image, const css::uno::Reference< css::datatransfer::XTransferable >& transferable, const css::uno::Reference< css::datatransfer::dnd::XDragSourceListener >& listener) override; // XInitialization virtual void SAL_CALL initialize(const css::uno::Sequence& rArguments) override; void deinitialize(); OUString SAL_CALL getImplementationName() override; sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; css::uno::Sequence SAL_CALL getSupportedServiceNames() override; void dragFailed(); void dragDelete(); #if GTK_CHECK_VERSION(4, 0, 0) void dragEnd(GdkDrag* drag); #else void dragEnd(GdkDragContext* context); void dragDataGet(GtkSelectionData *data, guint info); #endif // For LibreOffice internal D&D we provide the Transferable without Gtk // intermediaries as a shortcut, see tdf#100097 for how dbaccess depends on this static GtkInstDragSource* g_ActiveDragSource; css::uno::Reference const & GetTransferrable() const { return m_xTrans; } }; enum SelectionType { SELECTION_CLIPBOARD = 0, SELECTION_PRIMARY = 1 }; class GtkSalTimer; class GtkInstance final : public SvpSalInstance { public: GtkInstance( std::unique_ptr pMutex ); virtual ~GtkInstance() override; void EnsureInit(); virtual void AfterAppInit() override; virtual SalFrame* CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle ) override; virtual SalFrame* CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) override; virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow ) override; virtual SalSystem* CreateSalSystem() override; virtual SalInfoPrinter* CreateInfoPrinter(SalPrinterQueueInfo* pPrinterQueueInfo, ImplJobSetup* pJobSetup) override; virtual std::unique_ptr CreatePrinter( SalInfoPrinter* pInfoPrinter ) override; virtual std::unique_ptr CreateMenu( bool, Menu* ) override; virtual std::unique_ptr CreateMenuItem( const SalItemParams& ) override; virtual SalTimer* CreateSalTimer() override; virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override; virtual std::unique_ptr CreateVirtualDevice( SalGraphics&, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData* = nullptr ) override; virtual std::shared_ptr CreateSalBitmap() override; virtual bool DoYield(bool bWait, bool bHandleAllCurrentEvents) override; virtual bool AnyInput( VclInputFlags nType ) override; // impossible to handle correctly, as "main thread" depends on the dispatch mutex virtual bool IsMainThread() const override { return false; } virtual std::unique_ptr CreatePrintGraphics() override; virtual bool hasNativeFileSelection() const override { return true; } virtual css::uno::Reference< css::ui::dialogs::XFilePicker2 > createFilePicker( const css::uno::Reference< css::uno::XComponentContext >& ) override; virtual css::uno::Reference< css::ui::dialogs::XFolderPicker2 > createFolderPicker( const css::uno::Reference< css::uno::XComponentContext >& ) override; virtual css::uno::Reference< css::uno::XInterface > CreateClipboard( const css::uno::Sequence< css::uno::Any >& i_rArguments ) override; virtual css::uno::Reference ImplCreateDragSource(const SystemEnvData*) override; virtual css::uno::Reference ImplCreateDropTarget(const SystemEnvData*) override; virtual OpenGLContext* CreateOpenGLContext() override; virtual std::unique_ptr CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile) override; virtual std::unique_ptr CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile, bool bAllowCycleFocusOut, sal_uInt64 nLOKWindowId = 0) override; virtual weld::MessageDialog* CreateMessageDialog(weld::Widget* pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage) override; virtual weld::Window* GetFrameWeld(const css::uno::Reference& rWindow) override; virtual const cairo_font_options_t* GetCairoFontOptions() override; const cairo_font_options_t* GetLastSeenCairoFontOptions() const; void ResetLastSeenCairoFontOptions(const cairo_font_options_t* pOptions); void RemoveTimer (); void* CreateGStreamerSink(const SystemChildWindow*) override; private: GtkSalTimer *m_pTimer; css::uno::Reference m_aClipboards[2]; bool IsTimerExpired(); bool bNeedsInit; cairo_font_options_t* m_pLastCairoFontOptions; }; inline GtkInstance* GetGtkInstance() { return static_cast(GetSalInstance()); } class SalGtkXWindow final : public weld::TransportAsXWindow { private: weld::Window* m_pWeldWidget; GtkWidget* m_pWidget; public: SalGtkXWindow(weld::Window* pWeldWidget, GtkWidget* pWidget) : TransportAsXWindow(pWeldWidget) , m_pWeldWidget(pWeldWidget) , m_pWidget(pWidget) { } virtual void clear() override { m_pWeldWidget = nullptr; m_pWidget = nullptr; TransportAsXWindow::clear(); } GtkWidget* getGtkWidget() const { return m_pWidget; } weld::Window* getFrameWeld() const { return m_pWeldWidget; } }; GdkPixbuf* load_icon_by_name(const OUString& rIconName); #endif // INCLUDED_VCL_INC_UNX_GTK_GTKINST_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */