summaryrefslogtreecommitdiffstats
path: root/vcl/inc/unx/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/inc/unx/gtk')
-rw-r--r--vcl/inc/unx/gtk/atkbridge.hxx25
-rw-r--r--vcl/inc/unx/gtk/gloactiongroup.h75
-rw-r--r--vcl/inc/unx/gtk/glomenu.h134
-rw-r--r--vcl/inc/unx/gtk/gtkbackend.hxx30
-rw-r--r--vcl/inc/unx/gtk/gtkdata.hxx367
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx694
-rw-r--r--vcl/inc/unx/gtk/gtkgdi.hxx245
-rw-r--r--vcl/inc/unx/gtk/gtkinst.hxx349
-rw-r--r--vcl/inc/unx/gtk/gtkobject.hxx120
-rw-r--r--vcl/inc/unx/gtk/gtksalmenu.hxx158
-rw-r--r--vcl/inc/unx/gtk/gtksys.hxx47
-rw-r--r--vcl/inc/unx/gtk/hudawareness.h29
12 files changed, 2273 insertions, 0 deletions
diff --git a/vcl/inc/unx/gtk/atkbridge.hxx b/vcl/inc/unx/gtk/atkbridge.hxx
new file mode 100644
index 0000000000..e77a9ab571
--- /dev/null
+++ b/vcl/inc/unx/gtk/atkbridge.hxx
@@ -0,0 +1,25 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+bool InitAtkBridge();
+void DeInitAtkBridge();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h
new file mode 100644
index 0000000000..fb84122a60
--- /dev/null
+++ b/vcl/inc/unx/gtk/gloactiongroup.h
@@ -0,0 +1,75 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_LO_ACTION_GROUP (g_lo_action_group_get_type ())
+#define G_LO_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
+ G_TYPE_LO_ACTION_GROUP, GLOActionGroup))
+#define G_IS_LO_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
+ G_TYPE_LO_ACTION_GROUP))
+
+struct GLOActionGroupPrivate;
+
+struct GLOActionGroup
+{
+ /*< private >*/
+ GObject parent_instance;
+
+ GLOActionGroupPrivate *priv;
+};
+
+struct GLOActionGroupClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /*< private >*/
+ gpointer padding[12];
+};
+
+GType g_lo_action_group_get_type (void) G_GNUC_CONST;
+
+GLOActionGroup * g_lo_action_group_new (void);
+
+void g_lo_action_group_set_top_menu (GLOActionGroup *group,
+ gpointer top_menu);
+
+void g_lo_action_group_insert (GLOActionGroup *group,
+ const gchar *action_name,
+ gint item_id,
+ gboolean submenu);
+
+void g_lo_action_group_insert_stateful (GLOActionGroup *group,
+ const gchar *action_name,
+ gint item_id,
+ gboolean submenu,
+ const GVariantType *parameter_type,
+ const GVariantType *state_type,
+ GVariant *state_hint,
+ GVariant *state);
+
+void g_lo_action_group_set_action_enabled (GLOActionGroup *group,
+ const gchar *action_name,
+ gboolean enabled);
+
+void g_lo_action_group_remove (GLOActionGroup *group,
+ const gchar *action_name);
+
+void g_lo_action_group_clear (GLOActionGroup *group);
+
+G_END_DECLS
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/glomenu.h b/vcl/inc/unx/gtk/glomenu.h
new file mode 100644
index 0000000000..da41e9e4b8
--- /dev/null
+++ b/vcl/inc/unx/gtk/glomenu.h
@@ -0,0 +1,134 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#define G_LO_MENU_ATTRIBUTE_ACCELERATOR "accel"
+#define G_LO_MENU_ATTRIBUTE_COMMAND "command"
+#define G_LO_MENU_ATTRIBUTE_SUBMENU_ACTION "submenu-action"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_LO_MENU (g_lo_menu_get_type ())
+#define G_LO_MENU(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
+ G_TYPE_LO_MENU, GLOMenu))
+#define G_IS_LO_MENU(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
+ G_TYPE_LO_MENU))
+
+struct GLOMenu;
+
+class GtkSalMenuItem;
+
+GLIB_AVAILABLE_IN_2_32
+GType g_lo_menu_get_type (void) G_GNUC_CONST;
+GLIB_AVAILABLE_IN_2_32
+GLOMenu * g_lo_menu_new (void);
+
+gint g_lo_menu_get_n_items_from_section (GLOMenu *menu,
+ gint section);
+
+void g_lo_menu_insert (GLOMenu *menu,
+ gint position,
+ const gchar *label);
+
+void g_lo_menu_insert_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *label);
+
+void g_lo_menu_new_section (GLOMenu *menu,
+ gint position,
+ const gchar *label);
+
+void g_lo_menu_insert_section (GLOMenu *menu,
+ gint position,
+ const gchar *label,
+ GMenuModel *section);
+
+GLOMenu * g_lo_menu_get_section (GLOMenu *menu,
+ gint section);
+
+void g_lo_menu_remove (GLOMenu *menu,
+ gint position);
+
+void g_lo_menu_remove_from_section (GLOMenu *menu,
+ gint section,
+ gint position);
+
+void g_lo_menu_set_label (GLOMenu *menu,
+ gint position,
+ const gchar *label);
+
+void g_lo_menu_set_icon (GLOMenu *menu,
+ gint position,
+ const GIcon *icon);
+
+
+void g_lo_menu_set_label_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *label);
+
+void g_lo_menu_set_icon_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const GIcon *icon);
+
+gchar * g_lo_menu_get_label_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position);
+
+void g_lo_menu_set_action_and_target_value (GLOMenu *menu,
+ gint position,
+ const gchar *command,
+ GVariant *target_value);
+
+void g_lo_menu_set_action_and_target_value_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *command,
+ GVariant *target_value);
+
+void g_lo_menu_set_command_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *command);
+
+gchar * g_lo_menu_get_command_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position);
+
+void g_lo_menu_set_accelerator_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *accelerator);
+
+gchar * g_lo_menu_get_accelerator_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position);
+
+void g_lo_menu_new_submenu_in_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position);
+
+GLOMenu * g_lo_menu_get_submenu_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position);
+
+void g_lo_menu_set_submenu_action_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *action);
+
+G_END_DECLS
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkbackend.hxx b/vcl/inc/unx/gtk/gtkbackend.hxx
new file mode 100644
index 0000000000..1317ad6f72
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtkbackend.hxx
@@ -0,0 +1,30 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#if defined(GDK_WINDOWING_X11)
+#if GTK_CHECK_VERSION(4, 0, 0)
+#include <gdk/x11/gdkx.h>
+#else
+#include <gdk/gdkx.h>
+#endif
+bool DLSYM_GDK_IS_X11_DISPLAY(GdkDisplay* pDisplay);
+#endif
+#if defined(GDK_WINDOWING_WAYLAND)
+#if GTK_CHECK_VERSION(4, 0, 0)
+#include <gdk/wayland/gdkwayland.h>
+#else
+#include <gdk/gdkwayland.h>
+#endif
+bool DLSYM_GDK_IS_WAYLAND_DISPLAY(GdkDisplay* pDisplay);
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkdata.hxx b/vcl/inc/unx/gtk/gtkdata.hxx
new file mode 100644
index 0000000000..704490e821
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtkdata.hxx
@@ -0,0 +1,367 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#if GTK_CHECK_VERSION(4,0,0)
+#include <gdk/x11/gdkx.h>
+#else
+#include <gdk/gdkx.h>
+#endif
+
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
+#include <unx/gendata.hxx>
+#include <unx/saldisp.hxx>
+#include <unx/gtk/gtksys.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <osl/conditn.hxx>
+#include <saltimer.hxx>
+#include <o3tl/enumarray.hxx>
+#include <unotools/weakref.hxx>
+
+#include <exception>
+#include <string_view>
+#include <vector>
+
+namespace com::sun::star::accessibility { class XAccessibleEventListener; }
+
+class GtkSalDisplay;
+class DocumentFocusListener;
+
+#if !GTK_CHECK_VERSION(4,0,0)
+typedef GdkWindow GdkSurface;
+typedef GdkWindowState GdkToplevelState;
+#endif
+
+inline void main_loop_run(GMainLoop* pLoop)
+{
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ gdk_threads_leave();
+#endif
+ g_main_loop_run(pLoop);
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ gdk_threads_enter();
+#endif
+}
+
+inline void css_provider_load_from_data(GtkCssProvider *css_provider,
+ const gchar *data,
+ gssize length)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ gtk_css_provider_load_from_data(css_provider, data, length);
+#else
+ gtk_css_provider_load_from_data(css_provider, data, length, nullptr);
+#endif
+}
+
+inline GtkWidget* widget_get_toplevel(GtkWidget* pWidget)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ GtkRoot* pRoot = gtk_widget_get_root(pWidget);
+ return pRoot ? GTK_WIDGET(pRoot) : pWidget;
+#else
+ return gtk_widget_get_toplevel(pWidget);
+#endif
+}
+
+inline const char* image_get_icon_name(GtkImage *pImage)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ return gtk_image_get_icon_name(pImage);
+#else
+ const gchar* icon_name;
+ gtk_image_get_icon_name(pImage, &icon_name, nullptr);
+ return icon_name;
+#endif
+}
+
+inline GtkWidget* widget_get_first_child(GtkWidget *pWidget)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ return gtk_widget_get_first_child(pWidget);
+#else
+ GList* pChildren = gtk_container_get_children(GTK_CONTAINER(pWidget));
+ GList* pChild = g_list_first(pChildren);
+ GtkWidget* pRet = pChild ? static_cast<GtkWidget*>(pChild->data) : nullptr;
+ g_list_free(pChildren);
+ return pRet;
+#endif
+}
+
+inline void style_context_get_color(GtkStyleContext *pStyle, GdkRGBA *pColor)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ return gtk_style_context_get_color(pStyle, pColor);
+#else
+ return gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), pColor);
+#endif
+}
+
+inline GdkSurface* widget_get_surface(GtkWidget* pWidget)
+{
+#if GTK_CHECK_VERSION(4,0,0)
+ return gtk_native_get_surface(gtk_widget_get_native(pWidget));
+#else
+ return gtk_widget_get_window(pWidget);
+#endif
+}
+
+inline void widget_set_cursor(GtkWidget *pWidget, GdkCursor *pCursor)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ gtk_widget_set_cursor(pWidget, pCursor);
+#else
+ gdk_window_set_cursor(gtk_widget_get_window(pWidget), pCursor);
+#endif
+}
+
+inline cairo_surface_t * surface_create_similar_surface(GdkSurface *pSurface,
+ cairo_content_t eContent,
+ int nWidth,
+ int nHeight)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ return gdk_surface_create_similar_surface(pSurface, eContent, nWidth, nHeight);
+#else
+ return gdk_window_create_similar_surface(pSurface, eContent, nWidth, nHeight);
+#endif
+}
+
+inline void im_context_set_client_widget(GtkIMContext *pIMContext, GtkWidget *pWidget)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ gtk_im_context_set_client_widget(pIMContext, pWidget);
+#else
+ gtk_im_context_set_client_window(pIMContext, pWidget ? gtk_widget_get_window(pWidget) : nullptr);
+#endif
+}
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+typedef double gtk_coord;
+#else
+typedef int gtk_coord;
+#endif
+
+inline bool surface_get_device_position(GdkSurface* pSurface,
+ GdkDevice* pDevice,
+ double& x,
+ double& y,
+ GdkModifierType* pMask)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ return gdk_surface_get_device_position(pSurface, pDevice,
+ &x, &y,
+ pMask);
+#else
+ int nX(x), nY(y);
+ bool bRet = gdk_window_get_device_position(pSurface, pDevice,
+ &nX, &nY,
+ pMask);
+ x = nX;
+ y = nY;
+ return bRet;
+#endif
+}
+
+inline GdkGLContext* surface_create_gl_context(GdkSurface* pSurface)
+{
+#if GTK_CHECK_VERSION(4, 0, 0)
+ return gdk_surface_create_gl_context(pSurface, nullptr);
+#else
+ return gdk_window_create_gl_context(pSurface, nullptr);
+#endif
+}
+
+void set_buildable_id(GtkBuildable* pWidget, const OUString& rId);
+OUString get_buildable_id(GtkBuildable* pWidget);
+
+void container_remove(GtkWidget* pContainer, GtkWidget* pChild);
+void container_add(GtkWidget* pContainer, GtkWidget* pChild);
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+typedef GtkClipboard GdkClipboard;
+#endif
+
+int getButtonPriority(std::u16string_view rType);
+
+class GtkSalTimer final : public SalTimer
+{
+ struct SalGtkTimeoutSource *m_pTimeout;
+public:
+ GtkSalTimer();
+ virtual ~GtkSalTimer() override;
+ virtual void Start( sal_uInt64 nMS ) override;
+ virtual void Stop() override;
+ bool Expired();
+
+ sal_uLong m_nTimeoutMS;
+};
+
+class DocumentFocusListener final :
+ public ::cppu::WeakImplHelper< css::accessibility::XAccessibleEventListener >
+{
+
+ o3tl::sorted_vector< css::uno::Reference< css::uno::XInterface > > m_aRefList;
+
+public:
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void attachRecursive(
+ const css::uno::Reference< css::accessibility::XAccessible >& xAccessible
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void attachRecursive(
+ const css::uno::Reference< css::accessibility::XAccessible >& xAccessible,
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void attachRecursive(
+ const css::uno::Reference< css::accessibility::XAccessible >& xAccessible,
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext,
+ sal_Int64 nStateSet
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void detachRecursive(
+ const css::uno::Reference< css::accessibility::XAccessible >& xAccessible
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void detachRecursive(
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void detachRecursive(
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext,
+ sal_Int64 nStateSet
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ static css::uno::Reference< css::accessibility::XAccessible > getAccessible(const css::lang::EventObject& aEvent );
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // XAccessibleEventListener
+ virtual void SAL_CALL notifyEvent( const css::accessibility::AccessibleEventObject& aEvent ) override;
+};
+
+class GtkSalData final : public GenericUnixSalData
+{
+ GSource* m_pUserEvent;
+ osl::Mutex m_aDispatchMutex;
+ osl::Condition m_aDispatchCondition;
+ std::exception_ptr m_aException;
+
+ unotools::WeakReference<DocumentFocusListener> m_xDocumentFocusListener;
+
+public:
+ GtkSalData();
+ virtual ~GtkSalData() override;
+
+ rtl::Reference<DocumentFocusListener> GetDocumentFocusListener();
+
+ void Init();
+ virtual void Dispose() override;
+
+ static void initNWF();
+ static void deInitNWF();
+
+ void TriggerUserEventProcessing();
+ void TriggerAllUserEventsProcessed();
+
+ bool Yield( bool bWait, bool bHandleAllCurrentEvents );
+ inline GdkDisplay *GetGdkDisplay();
+
+ virtual void ErrorTrapPush() override;
+ virtual bool ErrorTrapPop( bool bIgnoreError = true ) override;
+
+ inline GtkSalDisplay *GetGtkDisplay() const;
+ void setException(const std::exception_ptr& exception) { m_aException = exception; }
+};
+
+class GtkSalFrame;
+
+class GtkSalDisplay final : public SalGenericDisplay
+{
+ GtkSalSystem* m_pSys;
+ GdkDisplay* m_pGdkDisplay;
+ o3tl::enumarray<PointerStyle, GdkCursor*> m_aCursors;
+ bool m_bStartupCompleted;
+
+ GdkCursor* getFromSvg( OUString const & name, int nXHot, int nYHot );
+
+public:
+ GtkSalDisplay( GdkDisplay* pDisplay );
+ virtual ~GtkSalDisplay() override;
+
+ GdkDisplay* GetGdkDisplay() const { return m_pGdkDisplay; }
+
+ GtkSalSystem* getSystem() const { return m_pSys; }
+
+ GtkWidget* findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) const;
+
+ virtual void deregisterFrame( SalFrame* pFrame ) override;
+ GdkCursor *getCursor( PointerStyle ePointerStyle );
+ virtual int CaptureMouse( SalFrame* pFrame );
+
+ SalX11Screen GetDefaultXScreen() { return m_pSys->GetDisplayDefaultXScreen(); }
+ AbsoluteScreenPixelSize GetScreenSize( int nDisplayScreen );
+
+ void startupNotificationCompleted() { m_bStartupCompleted = true; }
+
+#if !GTK_CHECK_VERSION(4,0,0)
+ void screenSizeChanged( GdkScreen const * );
+ void monitorsChanged( GdkScreen const * );
+#endif
+
+ virtual void TriggerUserEventProcessing() override;
+ virtual void TriggerAllUserEventsProcessed() override;
+};
+
+inline GtkSalData* GetGtkSalData()
+{
+ return static_cast<GtkSalData*>(ImplGetSVData()->mpSalData);
+}
+inline GdkDisplay *GtkSalData::GetGdkDisplay()
+{
+ return GetGtkDisplay()->GetGdkDisplay();
+}
+
+GtkSalDisplay *GtkSalData::GetGtkDisplay() const
+{
+ return static_cast<GtkSalDisplay *>(GetDisplay());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
new file mode 100644
index 0000000000..5fbf441310
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -0,0 +1,694 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <cairo.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#if !GTK_CHECK_VERSION(4,0,0)
+#include <gtk/gtkx.h>
+#endif
+#include <gdk/gdkkeysyms.h>
+
+#include <salframe.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/sysdata.hxx>
+#include <unx/saltype.h>
+#include <unx/sessioninhibitor.hxx>
+
+#include <tools/link.hxx>
+
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/datatransfer/DataFlavor.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+
+#include <list>
+#include <vector>
+
+#include <config_dbus.h>
+#include <config_gio.h>
+
+#include <headless/svpgdi.hxx>
+
+#include "gtkdata.hxx"
+
+class GtkSalGraphics;
+class GtkSalDisplay;
+
+typedef sal_uIntPtr GdkNativeWindow;
+class GtkInstDropTarget;
+class GtkInstDragSource;
+class GtkDnDTransferable;
+
+class GtkSalMenu;
+
+struct VclToGtkHelper;
+
+class GtkSalFrame final : public SalFrame
+{
+ struct IMHandler
+ {
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ // Not all GTK Input Methods swallow key release
+ // events. Since they swallow the key press events and we
+ // are left with the key release events, we need to
+ // manually swallow those. To do this, we keep a list of
+ // the previous 10 key press events in each GtkSalFrame
+ // and when we get a key release that matches one of the
+ // key press events in our list, we swallow it.
+ struct PreviousKeyPress
+ {
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ guint state;
+ guint keyval;
+ guint16 hardware_keycode;
+ guint8 group;
+
+ PreviousKeyPress (GdkEventKey *event)
+ : window (nullptr),
+ send_event (0),
+ time (0),
+ state (0),
+ keyval (0),
+ hardware_keycode (0),
+ group (0)
+ {
+ if (event)
+ {
+ window = event->window;
+ send_event = event->send_event;
+ time = event->time;
+ state = event->state;
+ keyval = event->keyval;
+ hardware_keycode = event->hardware_keycode;
+ group = event->group;
+ }
+ }
+
+ PreviousKeyPress( const PreviousKeyPress& rPrev )
+ : window( rPrev.window ),
+ send_event( rPrev.send_event ),
+ time( rPrev.time ),
+ state( rPrev.state ),
+ keyval( rPrev.keyval ),
+ hardware_keycode( rPrev.hardware_keycode ),
+ group( rPrev.group )
+ {}
+
+ bool operator== (GdkEventKey const *event) const
+ {
+ return (event != nullptr)
+ && (event->window == window)
+ && (event->send_event == send_event)
+ // ignore non-Gdk state bits, e.g., these used by IBus
+ && ((event->state & GDK_MODIFIER_MASK) == (state & GDK_MODIFIER_MASK))
+ && (event->keyval == keyval)
+ && (event->hardware_keycode == hardware_keycode)
+ && (event->group == group)
+ && (event->time - time < 300)
+ ;
+ }
+ };
+#endif
+
+ GtkSalFrame* m_pFrame;
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ std::list< PreviousKeyPress > m_aPrevKeyPresses;
+#endif
+ int m_nPrevKeyPresses; // avoid using size()
+ GtkIMContext* m_pIMContext;
+ bool m_bFocused;
+ bool m_bPreeditJustChanged;
+ SalExtTextInputEvent m_aInputEvent;
+ std::vector< ExtTextInputAttr > m_aInputFlags;
+
+ IMHandler( GtkSalFrame* );
+ ~IMHandler();
+
+ void createIMContext();
+ void deleteIMContext();
+ void updateIMSpotLocation();
+ void endExtTextInput( EndExtTextInputFlags nFlags );
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ bool handleKeyEvent( GdkEventKey* pEvent );
+#endif
+ void focusChanged( bool bFocusIn );
+
+ void doCallEndExtTextInput();
+ void sendEmptyCommit();
+
+ static void signalIMCommit( GtkIMContext*, gchar*, gpointer );
+ static gboolean signalIMDeleteSurrounding( GtkIMContext*, gint, gint, gpointer );
+ static void signalIMPreeditChanged( GtkIMContext*, gpointer );
+ static void signalIMPreeditEnd( GtkIMContext*, gpointer );
+ static void signalIMPreeditStart( GtkIMContext*, gpointer );
+ static gboolean signalIMRetrieveSurrounding( GtkIMContext*, gpointer );
+ };
+ friend struct IMHandler;
+
+ friend class GtkSalObjectWidgetClip;
+
+ SalX11Screen m_nXScreen;
+ GtkWidget* m_pWindow;
+ GtkHeaderBar* m_pHeaderBar;
+ GtkGrid* m_pTopLevelGrid;
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ GtkEventBox* m_pEventBox;
+ GtkFixed* m_pFixedContainer;
+ GtkFixed* m_pDrawingArea;
+#else
+ GtkOverlay* m_pOverlay;
+ GtkFixed* m_pFixedContainer;
+ GtkDrawingArea* m_pDrawingArea;
+ GtkEventControllerKey* m_pKeyController;
+ gulong m_nSettingChangedSignalId;
+#endif
+ gulong m_nPortalSettingChangedSignalId;
+ GDBusProxy* m_pSettingsPortal;
+ gulong m_nSessionClientSignalId;
+ GDBusProxy* m_pSessionManager;
+ GDBusProxy* m_pSessionClient;
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ GdkWindow* m_pForeignParent;
+ GdkNativeWindow m_aForeignParentWindow;
+ GdkWindow* m_pForeignTopLevel;
+ GdkNativeWindow m_aForeignTopLevelWindow;
+#endif
+ SalFrameStyleFlags m_nStyle;
+ GtkSalFrame* m_pParent;
+ std::list< GtkSalFrame* > m_aChildren;
+ GdkToplevelState m_nState;
+ SystemEnvData m_aSystemData;
+ std::unique_ptr<GtkSalGraphics> m_pGraphics;
+ bool m_bGraphics;
+ ModKeyFlags m_nKeyModifiers;
+ PointerStyle m_ePointerStyle;
+ SessionManagerInhibitor m_SessionManagerInhibitor;
+ gulong m_nSetFocusSignalId;
+ bool m_bFullscreen;
+ bool m_bDefaultPos;
+ bool m_bDefaultSize;
+ bool m_bTooltipBlocked;
+ OUString m_sWMClass;
+
+ std::unique_ptr<IMHandler> m_pIMHandler;
+
+ Size m_aMaxSize;
+ Size m_aMinSize;
+ tools::Rectangle m_aRestorePosSize;
+
+ OUString m_aTooltip;
+ tools::Rectangle m_aHelpArea;
+ tools::Rectangle m_aFloatRect;
+ FloatWinPopupFlags m_nFloatFlags;
+ bool m_bFloatPositioned;
+ tools::Long m_nWidthRequest;
+ tools::Long m_nHeightRequest;
+ cairo_region_t* m_pRegion;
+ GtkInstDropTarget* m_pDropTarget;
+ GtkInstDragSource* m_pDragSource;
+ bool m_bGeometryIsProvisional;
+ bool m_bIconSetWhileUnmapped;
+
+ GtkSalMenu* m_pSalMenu;
+
+#if ENABLE_DBUS && ENABLE_GIO
+ private:
+ friend void on_registrar_available (GDBusConnection*, const gchar*, const gchar*, gpointer);
+ friend void on_registrar_unavailable (GDBusConnection*, const gchar*, gpointer);
+#endif
+ guint m_nWatcherId;
+
+ void Init( SalFrame* pParent, SalFrameStyleFlags nStyle );
+ void Init( SystemParentData* pSysData );
+ void InitCommon();
+ void InvalidateGraphics();
+
+ // signals
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static gboolean signalButton( GtkWidget*, GdkEventButton*, gpointer );
+ static void signalStyleUpdated(GtkWidget*, gpointer);
+#else
+ static void signalStyleUpdated(GtkWidget*, const gchar* pSetting, gpointer);
+#endif
+ void DrawingAreaResized(GtkWidget* pWidget, int nWidth, int nHeight);
+ void DrawingAreaDraw(cairo_t *cr);
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static gboolean signalDraw( GtkWidget*, cairo_t *cr, gpointer );
+ static void sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame);
+#else
+ static void signalDraw(GtkDrawingArea*, cairo_t *cr, int width, int height, gpointer);
+ static void sizeAllocated(GtkWidget*, int nWidth, int nHeight, gpointer frame);
+#endif
+ static void signalRealize(GtkWidget*, gpointer frame);
+ static gboolean signalTooltipQuery(GtkWidget*, gint x, gint y,
+ gboolean keyboard_mode, GtkTooltip *tooltip,
+ gpointer frame);
+#if GTK_CHECK_VERSION(4, 0, 0)
+ static GdkDragAction signalDragMotion(GtkDropTargetAsync *dest, GdkDrop *drop, double x, double y, gpointer frame);
+ static void signalDragLeave(GtkDropTargetAsync *dest, GdkDrop *drop, gpointer frame);
+ static gboolean signalDragDrop(GtkDropTargetAsync* context, GdkDrop* drop, double x, double y, gpointer frame);
+
+ static void signalDragFailed(GdkDrag* drag, GdkDragCancelReason reason, gpointer frame);
+ static void signalDragDelete(GdkDrag* drag, gpointer frame);
+ static void signalDragEnd(GdkDrag* drag, gpointer frame);
+#else
+ static gboolean signalDragMotion(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
+ guint time, gpointer frame);
+ static gboolean signalDragDrop(GtkWidget* widget, GdkDragContext *context, gint x, gint y,
+ guint time, gpointer frame);
+ static void signalDragDropReceived(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
+ GtkSelectionData *data, guint ttype, guint time, gpointer frame);
+ static void signalDragLeave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer frame);
+
+ static gboolean signalDragFailed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result, gpointer frame);
+ static void signalDragDelete(GtkWidget *widget, GdkDragContext *context, gpointer frame);
+ static void signalDragEnd(GtkWidget *widget, GdkDragContext *context, gpointer frame);
+ static void signalDragDataGet(GtkWidget* widget, GdkDragContext* context, GtkSelectionData *data, guint info,
+ guint time, gpointer frame);
+
+#endif
+ static void gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame);
+ static void gestureLongPress(GtkGestureLongPress* gesture, gdouble x, gdouble y, gpointer frame);
+ bool DrawingAreaButton(SalEvent nEventType, int nEventX, int nEventY, int nButton, guint32 nTime, guint nState);
+#if GTK_CHECK_VERSION(4, 0, 0)
+ static void gesturePressed(GtkGestureClick* gesture, int n_press, gdouble x, gdouble y, gpointer frame);
+ static void gestureReleased(GtkGestureClick* gesture, int n_press, gdouble x, gdouble y, gpointer frame);
+ void gestureButton(GtkGestureClick* gesture, SalEvent nEventType, gdouble x, gdouble y);
+#endif
+ void DrawingAreaFocusInOut(SalEvent nEventType);
+#if GTK_CHECK_VERSION(4, 0, 0)
+ static void signalFocusEnter(GtkEventControllerFocus* pController, gpointer frame);
+ static void signalFocusLeave(GtkEventControllerFocus* pController, gpointer frame);
+#else
+ static gboolean signalFocus( GtkWidget*, GdkEventFocus*, gpointer );
+#endif
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static void signalSetFocus(GtkWindow* pWindow, GtkWidget* pWidget, gpointer frame);
+#else
+ static void signalSetFocus(GtkWindow* pWindow, GParamSpec* pSpec, gpointer frame);
+#endif
+ void WindowMap();
+ void WindowUnmap();
+ bool WindowCloseRequest();
+ void DrawingAreaMotion(int nEventX, int nEventY, guint32 nTime, guint nState);
+ void DrawingAreaCrossing(SalEvent nEventType, int nEventX, int nEventY, guint32 nTime, guint nState);
+ void DrawingAreaScroll(double delta_x, double delta_y, int nEventX, int nEventY, guint32 nTime, guint nState);
+#if GTK_CHECK_VERSION(4, 0, 0)
+ bool DrawingAreaKey(GtkEventControllerKey* pController, SalEvent nEventType, guint keyval, guint keycode, guint nState);
+
+ static void signalMap(GtkWidget*, gpointer);
+ static void signalUnmap(GtkWidget*, gpointer);
+
+ static gboolean signalDelete(GtkWidget*, gpointer);
+
+ static void signalMotion(GtkEventControllerMotion *controller, double x, double y, gpointer);
+
+ static gboolean signalScroll(GtkEventControllerScroll* pController, double delta_x, double delta_y, gpointer);
+
+ static void signalEnter(GtkEventControllerMotion *controller, double x, double y, gpointer);
+ static void signalLeave(GtkEventControllerMotion *controller, gpointer);
+
+ static gboolean signalKeyPressed(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer);
+ static gboolean signalKeyReleased(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer);
+
+ static void signalWindowState(GdkToplevel*, GParamSpec*, gpointer);
+#else
+ static gboolean signalMap( GtkWidget*, GdkEvent*, gpointer );
+ static gboolean signalUnmap( GtkWidget*, GdkEvent*, gpointer );
+
+ static gboolean signalDelete( GtkWidget*, GdkEvent*, gpointer );
+
+ static gboolean signalMotion( GtkWidget*, GdkEventMotion*, gpointer );
+
+ static gboolean signalScroll( GtkWidget*, GdkEvent*, gpointer );
+
+ static gboolean signalCrossing( GtkWidget*, GdkEventCrossing*, gpointer );
+
+ static gboolean signalKey( GtkWidget*, GdkEventKey*, gpointer );
+
+ static gboolean signalWindowState( GtkWidget*, GdkEvent*, gpointer );
+#endif
+
+ static bool signalZoomBegin(GtkGesture*, GdkEventSequence*, gpointer);
+ static bool signalZoomUpdate(GtkGesture*, GdkEventSequence*, gpointer);
+ static bool signalZoomEnd(GtkGesture*, GdkEventSequence*, gpointer);
+
+ static bool signalRotateBegin(GtkGesture*, GdkEventSequence*, gpointer);
+ static bool signalRotateUpdate(GtkGesture*, GdkEventSequence*, gpointer);
+ static bool signalRotateEnd(GtkGesture*, GdkEventSequence*, gpointer);
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static gboolean signalConfigure( GtkWidget*, GdkEventConfigure*, gpointer );
+#endif
+ static void signalDestroy( GtkWidget*, gpointer );
+
+ void Center();
+ void SetDefaultSize();
+
+ bool doKeyCallback( guint state,
+ guint keyval,
+ guint16 hardware_keycode,
+ guint8 group,
+ sal_Unicode aOrigCode,
+ bool bDown,
+ bool bSendRelease
+ );
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static GdkNativeWindow findTopLevelSystemWindow( GdkNativeWindow aWindow );
+#endif
+
+ static int m_nFloats;
+
+ bool isFloatGrabWindow() const
+ {
+ return
+ (m_nStyle & SalFrameStyleFlags::FLOAT) && // only a float can be floatgrab
+ !(m_nStyle & SalFrameStyleFlags::TOOLTIP) && // tool tips are not
+ !(m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION); // toolbars are also not
+ }
+
+ bool isChild( bool bPlug = true, bool bSysChild = true )
+ {
+ SalFrameStyleFlags nMask = SalFrameStyleFlags::NONE;
+ if( bPlug )
+ nMask |= SalFrameStyleFlags::PLUG;
+ if( bSysChild )
+ nMask |= SalFrameStyleFlags::SYSTEMCHILD;
+ return bool(m_nStyle & nMask);
+ }
+
+ //call gtk_window_resize
+ void window_resize(tools::Long nWidth, tools::Long nHeight);
+ //call gtk_widget_set_size_request
+ void widget_set_size_request(tools::Long nWidth, tools::Long nHeight);
+
+ void resizeWindow( tools::Long nWidth, tools::Long nHeight );
+ void moveWindow( tools::Long nX, tools::Long nY );
+
+ Size calcDefaultSize();
+
+ void setMinMaxSize();
+
+ void AllocateFrame();
+ void TriggerPaintEvent();
+
+ void updateWMClass();
+
+ enum class SetType { RetainSize, Fullscreen, UnFullscreen };
+
+ void SetScreen( unsigned int nNewScreen, SetType eType, tools::Rectangle const *pSize = nullptr );
+
+ void SetIcon(const char* pIcon);
+
+ bool HandleMenubarMnemonic(guint eState, guint nKeyval);
+
+ void ListenPortalSettings();
+
+ void ListenSessionManager();
+
+ void UpdateGeometryFromEvent(int x_root, int y_root, int nEventX, int nEventY);
+
+public:
+ cairo_surface_t* m_pSurface;
+ basegfx::B2IVector m_aFrameSize;
+ DamageHandler m_aDamageHandler;
+ std::vector<GdkEvent*> m_aPendingScrollEvents;
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ Idle m_aSmoothScrollIdle;
+#endif
+ int m_nGrabLevel;
+ bool m_bSalObjectSetPosSize;
+ GtkSalFrame( SalFrame* pParent, SalFrameStyleFlags nStyle );
+ GtkSalFrame( SystemParentData* pSysData );
+
+ guint m_nMenuExportId;
+ guint m_nActionGroupExportId;
+ guint m_nHudAwarenessId;
+ std::vector<gulong> m_aMouseSignalIds;
+
+ void grabPointer(bool bGrab, bool bKeyboardAlso, bool bOwnerEvents);
+
+ static GtkSalDisplay* getDisplay();
+ static GdkDisplay* getGdkDisplay();
+ GtkWidget* getWindow() const { return m_pWindow; }
+ GtkFixed* getFixedContainer() const { return GTK_FIXED(m_pFixedContainer); }
+ GtkWidget* getMouseEventWidget() const;
+ GtkGrid* getTopLevelGridWidget() const { return m_pTopLevelGrid; }
+ const SalX11Screen& getXScreenNumber() const { return m_nXScreen; }
+ int GetDisplayScreen() const { return maGeometry.screen(); }
+ void updateScreenNumber();
+
+ cairo_t* getCairoContext() const;
+ void damaged(sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop,
+ sal_Int32 nExtentsRight, sal_Int32 nExtentsBottom) const;
+
+ void registerDropTarget(GtkInstDropTarget* pDropTarget)
+ {
+ assert(!m_pDropTarget);
+ m_pDropTarget = pDropTarget;
+ }
+
+ void deregisterDropTarget(GtkInstDropTarget const * pDropTarget)
+ {
+ assert(m_pDropTarget == pDropTarget); (void)pDropTarget;
+ m_pDropTarget = nullptr;
+ }
+
+ void registerDragSource(GtkInstDragSource* pDragSource)
+ {
+ assert(!m_pDragSource);
+ m_pDragSource = pDragSource;
+ }
+
+ void deregisterDragSource(GtkInstDragSource const * pDragSource)
+ {
+ assert(m_pDragSource == pDragSource); (void)pDragSource;
+ m_pDragSource = nullptr;
+ }
+
+ void startDrag(const css::datatransfer::dnd::DragGestureEvent& rEvent,
+ const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
+ VclToGtkHelper& rConversionHelper,
+ GdkDragAction sourceActions);
+
+ void closePopup();
+
+ void addGrabLevel();
+ void removeGrabLevel();
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ void nopaint_container_resize_children(GtkContainer*);
+
+ void LaunchAsyncScroll(GdkEvent const * pEvent);
+ DECL_LINK(AsyncScroll, Timer *, void);
+#endif
+
+ virtual ~GtkSalFrame() override;
+
+ // SalGraphics or NULL, but two Graphics for all SalFrames
+ // must be returned
+ virtual SalGraphics* AcquireGraphics() override;
+ virtual void ReleaseGraphics( SalGraphics* pGraphics ) override;
+
+ // Event must be destroyed, when Frame is destroyed
+ // When Event is called, SalInstance::Yield() must be returned
+ virtual bool PostEvent(std::unique_ptr<ImplSVEvent> pData) override;
+
+ virtual void SetTitle( const OUString& rTitle ) override;
+ virtual void SetIcon( sal_uInt16 nIcon ) override;
+ virtual void SetMenu( SalMenu *pSalMenu ) override;
+ SalMenu* GetMenu();
+ void EnsureAppMenuWatch();
+
+ virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle ) override;
+ // Before the window is visible, a resize event
+ // must be sent with the correct size
+ virtual void Show( bool bVisible, bool bNoActivate = false ) override;
+ // Set ClientSize and Center the Window to the desktop
+ // and send/post a resize message
+ virtual void SetMinClientSize( tools::Long nWidth, tools::Long nHeight ) override;
+ virtual void SetMaxClientSize( tools::Long nWidth, tools::Long nHeight ) override;
+ virtual void SetPosSize( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt16 nFlags ) override;
+ virtual void GetClientSize( tools::Long& rWidth, tools::Long& rHeight ) override;
+ virtual void GetWorkArea( AbsoluteScreenPixelRectangle& rRect ) override;
+ virtual SalFrame* GetParent() const override;
+ virtual void SetWindowState(const vcl::WindowData*) override;
+ virtual bool GetWindowState(vcl::WindowData*) override;
+ virtual void ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay ) override;
+ // Enable/Disable ScreenSaver, SystemAgents, ...
+ virtual void StartPresentation( bool bStart ) override;
+ // Show Window over all other Windows
+ virtual void SetAlwaysOnTop( bool bOnTop ) override;
+
+ // Window to top and grab focus
+ virtual void ToTop( SalFrameToTop nFlags ) override;
+
+ // this function can call with the same
+ // pointer style
+ virtual void SetPointer( PointerStyle ePointerStyle ) override;
+ virtual void CaptureMouse( bool bMouse ) override;
+ virtual void GrabFocus() override;
+ virtual void SetPointerPos( tools::Long nX, tools::Long nY ) override;
+
+ // flush output buffer
+ using SalFrame::Flush;
+ virtual void Flush() override;
+ // flush output buffer, wait till outstanding operations are done
+
+ virtual void SetInputContext( SalInputContext* pContext ) override;
+ virtual void EndExtTextInput( EndExtTextInputFlags nFlags ) override;
+
+ virtual OUString GetKeyName( sal_uInt16 nKeyCode ) override;
+ virtual bool MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, vcl::KeyCode& rKeyCode ) override;
+
+ // returns the input language used for the last key stroke
+ // may be LANGUAGE_DONTKNOW if not supported by the OS
+ virtual LanguageType GetInputLanguage() override;
+
+ virtual void UpdateSettings( AllSettings& rSettings ) override;
+
+ virtual void Beep() override;
+
+ // returns system data (most prominent: window handle)
+ virtual const SystemEnvData* GetSystemData() const override;
+
+ virtual void ResolveWindowHandle(SystemEnvData& rData) const override;
+
+ // get current modifier and button mask
+ virtual SalPointerState GetPointerState() override;
+
+ virtual KeyIndicatorState GetIndicatorState() override;
+
+ virtual void SimulateKeyPress( sal_uInt16 nKeyCode ) override;
+
+ // set new parent window
+ virtual void SetParent( SalFrame* pNewParent ) override;
+ // reparent window to act as a plugin; implementation
+ // may choose to use a new system window internally
+ // return false to indicate failure
+ virtual void SetPluginParent( SystemParentData* pNewParent ) override;
+
+ virtual void SetScreenNumber( unsigned int ) override;
+ virtual void SetApplicationID( const OUString &rWMClass ) override;
+
+ // shaped system windows
+ // set clip region to none (-> rectangular windows, normal state)
+ virtual void ResetClipRegion() override;
+ // start setting the clipregion consisting of nRects rectangles
+ virtual void BeginSetClipRegion( sal_uInt32 nRects ) override;
+ // add a rectangle to the clip region
+ virtual void UnionClipRegion( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) override;
+ // done setting up the clipregion
+ virtual void EndSetClipRegion() override;
+
+ virtual void PositionByToolkit(const tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override;
+ virtual void SetModal(bool bModal) override;
+ virtual bool GetModal() const override;
+ void HideTooltip();
+ void BlockTooltip();
+ void UnblockTooltip();
+ virtual bool ShowTooltip(const OUString& rHelpText, const tools::Rectangle& rHelpArea) override;
+ virtual void* ShowPopover(const OUString& rHelpText, vcl::Window* pParent, const tools::Rectangle& rHelpArea, QuickHelpFlags nFlags) override;
+ virtual bool UpdatePopover(void* nId, const OUString& rHelpText, vcl::Window* pParent, const tools::Rectangle& rHelpArea) override;
+ virtual bool HidePopover(void* nId) override;
+ virtual weld::Window* GetFrameWeld() const override;
+ virtual void UpdateDarkMode() override;
+ virtual bool GetUseDarkMode() const override;
+ virtual bool GetUseReducedAnimation() const override;
+
+ static GtkSalFrame *getFromWindow( GtkWidget *pWindow );
+
+ static sal_uIntPtr GetNativeWindowHandle(GtkWidget *pWidget);
+
+ //Call the usual SalFrame Callback, but catch uno exceptions and delegate
+ //to GtkSalData to rethrow them after the gsignal is processed when its safe
+ //to do so again in our own code after the g_main_context_iteration call
+ //which triggers the gsignals.
+ bool CallCallbackExc(SalEvent nEvent, const void* pEvent) const;
+
+ // call gtk_widget_queue_draw on the drawing widget
+ void queue_draw();
+
+ static void KeyCodeToGdkKey(const vcl::KeyCode& rKeyCode,
+ guint* pGdkKeyCode, GdkModifierType *pGdkModifiers);
+
+ static guint32 GetLastInputEventTime();
+ static void UpdateLastInputEventTime(guint32 nUserInputTime);
+ static sal_uInt16 GetMouseModCode(guint nState);
+ static sal_uInt16 GetKeyCode(guint nKeyVal);
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static guint GetKeyValFor(GdkKeymap* pKeyMap, guint16 hardware_keycode, guint8 group);
+#endif
+ static sal_uInt16 GetKeyModCode(guint nState);
+ static GdkEvent* makeFakeKeyPress(GtkWidget* pWidget);
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static SalWheelMouseEvent GetWheelEvent(const GdkEventScroll& rEvent);
+ static gboolean NativeWidgetHelpPressed(GtkAccelGroup*, GObject*, guint,
+ GdkModifierType, gpointer pFrame);
+#endif
+ static OUString GetPreeditDetails(GtkIMContext* pIMContext, std::vector<ExtTextInputAttr>& rInputFlags, sal_Int32& rCursorPos, sal_uInt8& rCursorFlags);
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+ gboolean event_controller_scroll_forward(GtkEventControllerScroll* pController, double delta_x, double delta_y);
+#endif
+
+ const cairo_font_options_t* get_font_options();
+
+ void SetColorScheme(GVariant* variant);
+
+ void SessionManagerInhibit(bool bStart, ApplicationInhibitFlags eType, std::u16string_view sReason, const char* application_id);
+
+ void DisallowCycleFocusOut();
+ bool IsCycleFocusOutDisallowed() const;
+ void AllowCycleFocusOut();
+};
+
+extern "C" {
+
+GType ooo_fixed_get_type();
+#if !GTK_CHECK_VERSION(4, 0, 0)
+AtkObject* ooo_fixed_get_accessible(GtkWidget *obj);
+#endif
+
+} // extern "C"
+
+#if !GTK_CHECK_VERSION(3, 22, 0)
+enum GdkAnchorHints
+{
+ GDK_ANCHOR_FLIP_X = 1 << 0,
+ GDK_ANCHOR_FLIP_Y = 1 << 1,
+ GDK_ANCHOR_SLIDE_X = 1 << 2,
+ GDK_ANCHOR_SLIDE_Y = 1 << 3,
+ GDK_ANCHOR_RESIZE_X = 1 << 4,
+ GDK_ANCHOR_RESIZE_Y = 1 << 5,
+ GDK_ANCHOR_FLIP = GDK_ANCHOR_FLIP_X | GDK_ANCHOR_FLIP_Y,
+ GDK_ANCHOR_SLIDE = GDK_ANCHOR_SLIDE_X | GDK_ANCHOR_SLIDE_Y,
+ GDK_ANCHOR_RESIZE = GDK_ANCHOR_RESIZE_X | GDK_ANCHOR_RESIZE_Y
+};
+#endif
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
new file mode 100644
index 0000000000..9d8bb26ce7
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -0,0 +1,245 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <config_cairo_canvas.h>
+
+#include <gtk/gtk.h>
+#include "gtkbackend.hxx"
+#include <gdk/gdkkeysyms.h>
+
+#include <unx/gtk/gtkframe.hxx>
+#include <ControlCacheKey.hxx>
+
+#include <headless/svpgdi.hxx>
+#include <textrender.hxx>
+
+enum class GtkControlPart
+{
+ ToplevelWindow,
+ Button,
+ LinkButton,
+ CheckButton,
+ CheckButtonCheck,
+ RadioButton,
+ RadioButtonRadio,
+ Entry,
+ Combobox,
+ ComboboxBox,
+ ComboboxBoxEntry,
+ ComboboxBoxButton,
+ ComboboxBoxButtonBox,
+ ComboboxBoxButtonBoxArrow,
+ Listbox,
+ ListboxBox,
+ ListboxBoxButton,
+ ListboxBoxButtonBox,
+ ListboxBoxButtonBoxArrow,
+ SpinButton,
+ SpinButtonUpButton,
+ SpinButtonDownButton,
+ ScrollbarVertical,
+ ScrollbarVerticalContents,
+ ScrollbarVerticalTrough,
+ ScrollbarVerticalSlider,
+ ScrollbarVerticalButton,
+ ScrollbarHorizontal,
+ ScrollbarHorizontalContents,
+ ScrollbarHorizontalTrough,
+ ScrollbarHorizontalSlider,
+ ScrollbarHorizontalButton,
+ ProgressBar,
+ ProgressBarTrough,
+ ProgressBarProgress,
+ Notebook,
+ NotebookHeader,
+ NotebookStack,
+ NotebookHeaderTabs,
+ NotebookHeaderTabsTab,
+ NotebookHeaderTabsTabLabel,
+ NotebookHeaderTabsTabActiveLabel,
+ NotebookHeaderTabsTabHoverLabel,
+ FrameBorder,
+ MenuBar,
+ MenuBarItem,
+ MenuWindow,
+ Menu,
+ MenuItem,
+ MenuItemLabel,
+ MenuItemArrow,
+ CheckMenuItem,
+ CheckMenuItemCheck,
+ RadioMenuItem,
+ RadioMenuItemRadio,
+ SeparatorMenuItem,
+ SeparatorMenuItemSeparator,
+};
+
+class GtkSalGraphics final : public SvpSalGraphics
+{
+ GtkSalFrame * const mpFrame;
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ bool isNativeControlSupported(ControlType, ControlPart) override;
+ virtual bool drawNativeControl( ControlType nType, ControlPart nPart,
+ const tools::Rectangle& rControlRegion,
+ ControlState nState, const ImplControlValue& aValue,
+ const OUString& rCaption,
+ const Color& rBackgroundColor ) override;
+ virtual bool getNativeControlRegion( ControlType nType, ControlPart nPart,
+ const tools::Rectangle& rControlRegion,
+ ControlState nState,
+ const ImplControlValue& aValue,
+ const OUString& rCaption,
+ tools::Rectangle &rNativeBoundingRegion,
+ tools::Rectangle &rNativeContentRegion ) override;
+#endif
+ bool updateSettings(AllSettings&) override;
+ void handleDamage(const tools::Rectangle&) override;
+
+public:
+ GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow );
+
+#if ENABLE_CAIRO_CANVAS
+ virtual bool SupportsCairo() const override;
+ virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const override;
+ virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const override;
+#endif
+
+ void WidgetQueueDraw() const;
+
+ virtual void GetResolution(sal_Int32& rDPIX, sal_Int32& rDPIY) override;
+
+ virtual OUString getRenderBackendName() const override { return "gtk3svp"; }
+
+ GtkStyleContext* createStyleContext(GtkControlPart ePart);
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ GtkStyleContext* makeContext(GtkWidgetPath *pPath, GtkStyleContext *pParent);
+#endif
+private:
+ GtkWidget *mpWindow;
+ static GtkStyleContext *mpWindowStyle;
+ static GtkStyleContext *mpButtonStyle;
+ static GtkStyleContext *mpLinkButtonStyle;
+ static GtkStyleContext *mpEntryStyle;
+ static GtkStyleContext *mpTextViewStyle;
+ static GtkStyleContext *mpVScrollbarStyle;
+ static GtkStyleContext *mpVScrollbarContentsStyle;
+ static GtkStyleContext *mpVScrollbarTroughStyle;
+ static GtkStyleContext *mpVScrollbarSliderStyle;
+ static GtkStyleContext *mpVScrollbarButtonStyle;
+ static GtkStyleContext *mpHScrollbarStyle;
+ static GtkStyleContext *mpHScrollbarContentsStyle;
+ static GtkStyleContext *mpHScrollbarTroughStyle;
+ static GtkStyleContext *mpHScrollbarSliderStyle;
+ static GtkStyleContext *mpHScrollbarButtonStyle;
+ static GtkStyleContext *mpToolbarStyle;
+ static GtkStyleContext *mpToolButtonStyle;
+ static GtkStyleContext *mpToolbarSeparatorStyle;
+ static GtkStyleContext *mpCheckButtonStyle;
+ static GtkStyleContext *mpCheckButtonCheckStyle;
+ static GtkStyleContext *mpRadioButtonStyle;
+ static GtkStyleContext *mpRadioButtonRadioStyle;
+ static GtkStyleContext *mpSpinStyle;
+ static GtkStyleContext *mpSpinUpStyle;
+ static GtkStyleContext *mpSpinDownStyle;
+ static GtkStyleContext *mpComboboxStyle;
+ static GtkStyleContext *mpComboboxBoxStyle;
+ static GtkStyleContext *mpComboboxEntryStyle;
+ static GtkStyleContext *mpComboboxButtonStyle;
+ static GtkStyleContext *mpComboboxButtonBoxStyle;
+ static GtkStyleContext *mpComboboxButtonArrowStyle;
+ static GtkStyleContext *mpListboxStyle;
+ static GtkStyleContext *mpListboxBoxStyle;
+ static GtkStyleContext *mpListboxButtonStyle;
+ static GtkStyleContext *mpListboxButtonBoxStyle;
+ static GtkStyleContext *mpListboxButtonArrowStyle;
+ static GtkStyleContext *mpFrameInStyle;
+ static GtkStyleContext *mpFrameOutStyle;
+ static GtkStyleContext *mpFixedHoriLineStyle;
+ static GtkStyleContext *mpFixedVertLineStyle;
+ static GtkStyleContext *mpTreeHeaderButtonStyle;
+ static GtkStyleContext *mpProgressBarStyle;
+ static GtkStyleContext *mpProgressBarTroughStyle;
+ static GtkStyleContext *mpProgressBarProgressStyle;
+ static GtkStyleContext *mpNotebookStyle;
+ static GtkStyleContext *mpNotebookStackStyle;
+ static GtkStyleContext *mpNotebookHeaderStyle;
+ static GtkStyleContext *mpNotebookHeaderTabsStyle;
+ static GtkStyleContext *mpNotebookHeaderTabsTabStyle;
+ static GtkStyleContext *mpNotebookHeaderTabsTabLabelStyle;
+ static GtkStyleContext *mpNotebookHeaderTabsTabActiveLabelStyle;
+ static GtkStyleContext *mpNotebookHeaderTabsTabHoverLabelStyle;
+ static GtkStyleContext *mpMenuBarStyle;
+ static GtkStyleContext *mpMenuBarItemStyle;
+ static GtkStyleContext *mpMenuWindowStyle;
+ static GtkStyleContext *mpMenuStyle;
+ static GtkStyleContext *mpMenuItemStyle;
+ static GtkStyleContext *mpMenuItemLabelStyle;
+ static GtkStyleContext *mpMenuItemArrowStyle;
+ static GtkStyleContext *mpCheckMenuItemStyle;
+ static GtkStyleContext *mpCheckMenuItemCheckStyle;
+ static GtkStyleContext *mpRadioMenuItemStyle;
+ static GtkStyleContext *mpRadioMenuItemRadioStyle;
+ static GtkStyleContext *mpSeparatorMenuItemStyle;
+ static GtkStyleContext *mpSeparatorMenuItemSeparatorStyle;
+ static gint mnVerticalSeparatorMinWidth;
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static tools::Rectangle NWGetScrollButtonRect( ControlPart nPart, tools::Rectangle aAreaRect );
+ static tools::Rectangle NWGetSpinButtonRect( ControlPart nPart, tools::Rectangle aAreaRect);
+ static tools::Rectangle NWGetComboBoxButtonRect(ControlType nType, ControlPart nPart, tools::Rectangle aAreaRect);
+
+ static void PaintScrollbar(GtkStyleContext *context,
+ cairo_t *cr,
+ const tools::Rectangle& rControlRectangle,
+ ControlPart nPart,
+ const ImplControlValue& aValue );
+ void PaintOneSpinButton( GtkStyleContext *context,
+ cairo_t *cr,
+ ControlPart nPart,
+ tools::Rectangle aAreaRect,
+ ControlState nState );
+ void PaintSpinButton(GtkStateFlags flags,
+ cairo_t *cr,
+ const tools::Rectangle& rControlRectangle,
+ ControlPart nPart,
+ const ImplControlValue& aValue);
+ static void PaintCombobox(GtkStateFlags flags,
+ cairo_t *cr,
+ const tools::Rectangle& rControlRectangle,
+ ControlType nType,
+ ControlPart nPart);
+ static void PaintCheckOrRadio(cairo_t *cr, GtkStyleContext *context,
+ const tools::Rectangle& rControlRectangle,
+ bool bIsCheck, bool bInMenu);
+
+ static void PaintCheck(cairo_t *cr, GtkStyleContext *context,
+ const tools::Rectangle& rControlRectangle, bool bInMenu);
+
+ static void PaintRadio(cairo_t *cr, GtkStyleContext *context,
+ const tools::Rectangle& rControlRectangle, bool bInMenu);
+#endif
+
+ static bool style_loaded;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
new file mode 100644
index 0000000000..1f9e328bb8
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -0,0 +1,349 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <stack>
+
+#include <unx/salinst.h>
+#include <unx/gensys.h>
+#include <headless/svpinst.hxx>
+#include <com/sun/star/datatransfer/DataFlavor.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/weldutils.hxx>
+#include <gtk/gtk.h>
+
+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<sal_uInt32> 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<sal_Int8> aVector;
+
+ static void read_block_async_completed(GObject* source, GAsyncResult* res, gpointer user_data);
+
+ OUString get_as_string() const;
+ css::uno::Sequence<sal_Int8> get_as_sequence() const;
+};
+
+#endif
+
+struct VclToGtkHelper
+{
+ std::vector<css::datatransfer::DataFlavor> aInfoToFlavor;
+#if GTK_CHECK_VERSION(4, 0, 0)
+ std::vector<OString> FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats);
+#else
+ std::vector<GtkTargetEntry> FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &rFormats);
+#endif
+#if GTK_CHECK_VERSION(4, 0, 0)
+ void setSelectionData(const css::uno::Reference<css::datatransfer::XTransferable> &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<css::datatransfer::XTransferable> &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<css::datatransfer::XTransferable>
+{
+protected:
+#if GTK_CHECK_VERSION(4, 0, 0)
+ std::map<OUString, OString> m_aMimeTypeToGtkType;
+#else
+ std::map<OUString, GdkAtom> m_aMimeTypeToGtkType;
+#endif
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+ std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector(const char * const *targets, gint n_targets);
+#else
+ std::vector<css::datatransfer::DataFlavor> 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<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector() = 0;
+ virtual css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override;
+ virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor) override;
+};
+
+class GtkDnDTransferable;
+
+class GtkInstDropTarget final : public cppu::WeakComponentImplHelper<css::datatransfer::dnd::XDropTarget,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo>
+{
+ osl::Mutex m_aMutex;
+ GtkSalFrame* m_pFrame;
+ GtkDnDTransferable* m_pFormatConversionRequest;
+ bool m_bActive;
+ bool m_bInDrag;
+ sal_Int8 m_nDefaultActions;
+ std::vector<css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>> m_aListeners;
+public:
+ GtkInstDropTarget();
+ virtual ~GtkInstDropTarget() override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArgs) override;
+ void deinitialize();
+
+ // XDropTarget
+ virtual void SAL_CALL addDropTargetListener(const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>&) override;
+ virtual void SAL_CALL removeDropTargetListener(const css::uno::Reference<css::datatransfer::dnd::XDropTargetListener>&) 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<OUString> 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<css::datatransfer::dnd::XDragSource,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo>
+{
+ osl::Mutex m_aMutex;
+ GtkSalFrame* m_pFrame;
+ css::uno::Reference<css::datatransfer::dnd::XDragSourceListener> m_xListener;
+ css::uno::Reference<css::datatransfer::XTransferable> m_xTrans;
+ VclToGtkHelper m_aConversionHelper;
+public:
+ GtkInstDragSource()
+ : WeakComponentImplHelper(m_aMutex)
+ , m_pFrame(nullptr)
+ {
+ }
+
+ void set_datatransfer(const css::uno::Reference<css::datatransfer::XTransferable>& rTrans,
+ const css::uno::Reference<css::datatransfer::dnd::XDragSourceListener>& rListener);
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ std::vector<GtkTargetEntry> FormatsToGtk(const css::uno::Sequence<css::datatransfer::DataFlavor> &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<css::uno::Any >& rArguments) override;
+ void deinitialize();
+
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ css::uno::Sequence<OUString> 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<css::datatransfer::XTransferable> const & GetTransferable() const { return m_xTrans; }
+};
+
+enum SelectionType { SELECTION_CLIPBOARD = 0, SELECTION_PRIMARY = 1 };
+
+class GtkSalTimer;
+class GtkInstance final : public SvpSalInstance
+{
+public:
+ GtkInstance( std::unique_ptr<SalYieldMutex> 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<SalPrinter> CreatePrinter( SalInfoPrinter* pInfoPrinter ) override;
+ virtual std::unique_ptr<SalMenu> CreateMenu( bool, Menu* ) override;
+ virtual std::unique_ptr<SalMenuItem> 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<SalVirtualDevice>
+ CreateVirtualDevice( SalGraphics&,
+ tools::Long &nDX, tools::Long &nDY,
+ DeviceFormat eFormat,
+ const SystemGraphicsData* = nullptr ) override;
+ virtual std::shared_ptr<SalBitmap> 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<GenPspGraphics> 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<css::uno::XInterface> ImplCreateDragSource(const SystemEnvData*) override;
+ virtual css::uno::Reference<css::uno::XInterface> ImplCreateDropTarget(const SystemEnvData*) override;
+ virtual OpenGLContext* CreateOpenGLContext() override;
+ virtual std::unique_ptr<weld::Builder> CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile) override;
+ virtual std::unique_ptr<weld::Builder> 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<css::awt::XWindow>& 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<css::uno::XInterface> m_aClipboards[2];
+ bool IsTimerExpired();
+ bool bNeedsInit;
+ cairo_font_options_t* m_pLastCairoFontOptions;
+};
+
+inline GtkInstance* GetGtkInstance() { return static_cast<GtkInstance*>(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);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkobject.hxx b/vcl/inc/unx/gtk/gtkobject.hxx
new file mode 100644
index 0000000000..63544f56f8
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtkobject.hxx
@@ -0,0 +1,120 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <tools/solar.h>
+#include <vcl/sysdata.hxx>
+#include <salobj.hxx>
+#include <unx/gtk/gtkframe.hxx>
+
+class GtkSalObjectBase : public SalObject
+{
+protected:
+ SystemEnvData m_aSystemData;
+ GtkWidget* m_pSocket;
+ GtkSalFrame* m_pParent;
+ cairo_region_t* m_pRegion;
+
+ void Init();
+
+public:
+ GtkSalObjectBase(GtkSalFrame* pParent);
+ virtual ~GtkSalObjectBase() override;
+
+ virtual void BeginSetClipRegion( sal_uInt32 nRects ) override;
+ virtual void UnionClipRegion( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) override;
+
+ virtual void SetForwardKey( bool bEnable ) override;
+
+ virtual const SystemEnvData* GetSystemData() const override;
+
+ virtual Size GetOptimalSize() const override;
+
+private:
+ // signals
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static gboolean signalButton( GtkWidget*, GdkEventButton*, gpointer );
+ static gboolean signalFocus( GtkWidget*, GdkEventFocus*, gpointer );
+#endif
+};
+
+// this attempts to clip the hosted native window using gdk_window_shape_combine_region
+class GtkSalObject final : public GtkSalObjectBase
+{
+ // signals
+ static void signalDestroy( GtkWidget*, gpointer );
+
+public:
+ GtkSalObject(GtkSalFrame* pParent, bool bShow);
+ virtual ~GtkSalObject() override;
+
+ // override all pure virtual methods
+ virtual void ResetClipRegion() override;
+ virtual void EndSetClipRegion() override;
+
+ virtual void SetPosSize( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) override;
+ virtual void Show( bool bVisible ) override;
+ virtual void Reparent(SalFrame* pFrame) override;
+};
+
+// this attempts to clip the hosted native GtkWidget by using a GtkScrolledWindow as a viewport
+// only a rectangular area is going to work
+class GtkSalObjectWidgetClip final : public GtkSalObjectBase
+{
+ tools::Rectangle m_aRect;
+ tools::Rectangle m_aClipRect;
+ GtkWidget* m_pScrolledWindow;
+ GtkWidget* m_pViewPort;
+ GtkCssProvider* m_pBgCssProvider;
+
+ // signals
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ static gboolean signalScroll(GtkWidget*, GdkEvent*, gpointer);
+#else
+ static gboolean signalScroll(GtkEventControllerScroll* pController, double delta_x, double delta_y, gpointer object);
+#endif
+ static void signalDestroy( GtkWidget*, gpointer );
+
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ bool signal_scroll(GtkWidget* pScrolledWindow, GdkEvent* pEvent);
+#else
+ bool signal_scroll(GtkEventControllerScroll* pController, double delta_x, double delta_y);
+#endif
+
+ void ApplyClipRegion();
+
+ void SetViewPortBackground();
+
+ DECL_LINK(SettingsChangedHdl, VclWindowEvent&, void);
+
+public:
+ GtkSalObjectWidgetClip(GtkSalFrame* pParent, bool bShow);
+ virtual ~GtkSalObjectWidgetClip() override;
+
+ // override all pure virtual methods
+ virtual void ResetClipRegion() override;
+ virtual void EndSetClipRegion() override;
+
+ virtual void SetPosSize( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight ) override;
+ virtual void Show( bool bVisible ) override;
+ virtual void Reparent(SalFrame* pFrame) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
new file mode 100644
index 0000000000..4157df9d3b
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -0,0 +1,158 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <config_dbus.h>
+#include <config_gio.h>
+
+#include <vector>
+#if ENABLE_GIO
+#include <gio/gio.h>
+#endif
+
+#include <salmenu.hxx>
+#include <unx/gtk/gtkframe.hxx>
+#include <unotools/tempfile.hxx>
+#include <vcl/idle.hxx>
+
+#include <unx/gtk/glomenu.h>
+#include <unx/gtk/gloactiongroup.h>
+
+class MenuItemList;
+class GtkSalMenuItem;
+
+class GtkSalMenu final : public SalMenu
+{
+private:
+ std::vector< GtkSalMenuItem* > maItems;
+ std::vector<std::pair<sal_uInt16, GtkWidget*>> maExtraButtons;
+ Idle maUpdateMenuBarIdle;
+
+ bool mbInActivateCallback;
+ bool mbMenuBar;
+ bool mbNeedsUpdate;
+ bool mbReturnFocusToDocument;
+ bool mbAddedGrab;
+ /// Even setting null icon on a menuitem can be expensive, so cache state to avoid that call
+ bool mbHasNullItemIcon = true;
+ GtkWidget* mpMenuBarContainerWidget;
+ std::unique_ptr<utl::TempFileNamed> mxPersonaImage;
+ BitmapEx maPersonaBitmap;
+ GtkWidget* mpMenuAllowShrinkWidget;
+ GtkWidget* mpMenuBarWidget;
+ GtkWidget* mpMenuWidget;
+ GtkCssProvider* mpMenuBarContainerProvider;
+ GtkCssProvider* mpMenuBarProvider;
+ GtkWidget* mpCloseButton;
+ VclPtr<Menu> mpVCLMenu;
+ GtkSalMenu* mpParentSalMenu;
+ GtkSalFrame* mpFrame;
+
+ // GMenuModel and GActionGroup attributes
+ GMenuModel* mpMenuModel;
+ GActionGroup* mpActionGroup;
+
+ void ImplUpdate(bool bRecurse, bool bRemoveDisabledEntries);
+ void ActivateAllSubmenus(Menu* pMenuBar);
+
+ DECL_LINK(MenuBarHierarchyChangeHandler, Timer*, void);
+
+ static GtkWidget* AddButton(GtkWidget *pImage);
+
+public:
+ GtkSalMenu( bool bMenuBar );
+ virtual ~GtkSalMenu() override;
+
+ virtual bool VisibleMenuBar() override; // must return TRUE to actually DISPLAY native menu bars
+ // otherwise only menu messages are processed (eg, OLE on Windows)
+
+ virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) override;
+ virtual void RemoveItem( unsigned nPos ) override;
+ virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ) override;
+ virtual void SetFrame( const SalFrame* pFrame ) override;
+ const GtkSalFrame* GetFrame() const;
+ virtual void CheckItem( unsigned nPos, bool bCheck ) override;
+ virtual void EnableItem( unsigned nPos, bool bEnable ) override;
+ virtual void ShowItem( unsigned nPos, bool bShow ) override;
+ virtual void SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const OUString& rText ) override;
+ virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage) override;
+ virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const vcl::KeyCode& rKeyCode, const OUString& rKeyName ) override;
+ virtual void GetSystemMenuData( SystemMenuData* pData ) override;
+
+ void SetMenu( Menu* pMenu ) { mpVCLMenu = pMenu; }
+ Menu* GetMenu() { return mpVCLMenu; }
+ void SetMenuModel(GMenuModel* pMenuModel);
+ unsigned GetItemCount() const { return maItems.size(); }
+ GtkSalMenuItem* GetItemAtPos( unsigned nPos ) { return maItems[ nPos ]; }
+ void SetActionGroup( GActionGroup* pActionGroup ) { mpActionGroup = pActionGroup; }
+ bool IsItemVisible( unsigned nPos );
+
+ void NativeSetItemText( unsigned nSection, unsigned nItemPos, const OUString& rText );
+ void NativeSetItemIcon( unsigned nSection, unsigned nItemPos, const Image& rImage );
+ bool NativeSetItemCommand( unsigned nSection,
+ unsigned nItemPos,
+ sal_uInt16 nId,
+ const gchar* aCommand,
+ MenuItemBits nBits,
+ bool bChecked,
+ bool bIsSubmenu );
+ void NativeSetEnableItem( gchar const * aCommand, gboolean bEnable );
+ void NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck );
+ void NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const vcl::KeyCode& rKeyCode, std::u16string_view rKeyName );
+
+ static void DispatchCommand(const gchar* pMenuCommand);
+ static void Activate(const gchar* pMenuCommand);
+ static void Deactivate(const gchar* pMenuCommand);
+ void EnableUnity(bool bEnable);
+ virtual void ShowMenuBar( bool bVisible ) override;
+ bool PrepUpdate() const;
+ virtual void Update() override; // Update this menu only.
+ // Update full menu hierarchy from this menu.
+ void UpdateFull () { ActivateAllSubmenus(mpVCLMenu); }
+ // Clear ActionGroup and MenuModel from full menu hierarchy
+ void ClearActionGroupAndMenuModel();
+ GtkSalMenu* GetTopLevel();
+ void SetNeedsUpdate();
+
+ GtkWidget* GetMenuBarWidget() const { return mpMenuBarWidget; }
+ GtkWidget* GetMenuBarContainerWidget() const { return mpMenuBarContainerWidget; }
+
+ void CreateMenuBarWidget();
+ void DestroyMenuBarWidget();
+#if !GTK_CHECK_VERSION(4, 0, 0)
+ gboolean SignalKey(GdkEventKey const * pEvent);
+#endif
+ void ReturnFocus();
+
+ virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override;
+ virtual void ShowCloseButton(bool bShow) override;
+ virtual bool AddMenuBarButton( const SalMenuButtonItem& rNewItem ) override;
+ virtual void RemoveMenuBarButton( sal_uInt16 nId ) override;
+ virtual tools::Rectangle GetMenuBarButtonRectPixel( sal_uInt16 i_nItemId, SalFrame* i_pReferenceFrame ) override;
+ virtual bool CanGetFocus() const override;
+ virtual bool TakeFocus() override;
+ virtual int GetMenuBarHeight() const override;
+ virtual void ApplyPersona() override;
+};
+
+class GtkSalMenuItem final : public SalMenuItem
+{
+public:
+ GtkSalMenuItem( const SalItemParams* );
+ virtual ~GtkSalMenuItem() override;
+
+ GtkSalMenu* mpParentMenu; // The menu into which this menu item is inserted
+ GtkSalMenu* mpSubMenu; // Submenu of this item (if defined)
+ MenuItemType mnType; // Item type
+ sal_uInt16 mnId; // Item ID
+ bool mbVisible; // Item visibility.
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtksys.hxx b/vcl/inc/unx/gtk/gtksys.hxx
new file mode 100644
index 0000000000..0dd756f7a7
--- /dev/null
+++ b/vcl/inc/unx/gtk/gtksys.hxx
@@ -0,0 +1,47 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <unx/gensys.h>
+#include <gtk/gtk.h>
+#include <unx/saltype.h>
+#include <deque>
+
+class GtkSalSystem final : public SalGenericSystem
+{
+ GdkDisplay *mpDisplay;
+#if !GTK_CHECK_VERSION(4,0,0)
+ // Number of monitors for every active screen.
+ std::deque<std::pair<GdkScreen*, int> > maScreenMonitors;
+#endif
+public:
+ GtkSalSystem();
+ virtual ~GtkSalSystem() override;
+ static GtkSalSystem *GetSingleton();
+
+ virtual unsigned int GetDisplayScreenCount() override;
+ virtual unsigned int GetDisplayBuiltInScreen() override;
+ virtual AbsoluteScreenPixelRectangle GetDisplayScreenPosSizePixel(unsigned int nScreen) override;
+ virtual int ShowNativeDialog (const OUString& rTitle,
+ const OUString& rMessage,
+ const std::vector< OUString >& rButtons) override;
+ SalX11Screen GetDisplayDefaultXScreen()
+ { return getXScreenFromDisplayScreen( GetDisplayBuiltInScreen() ); }
+ SalX11Screen getXScreenFromDisplayScreen(unsigned int nDisplayScreen);
+#if !GTK_CHECK_VERSION(4,0,0)
+ void countScreenMonitors();
+ // We have a 'screen' number that is combined from screen-idx + monitor-idx
+ int getScreenIdxFromPtr (GdkScreen *pScreen);
+ int getScreenMonitorIdx (GdkScreen *pScreen, int nX, int nY);
+ GdkScreen *getScreenMonitorFromIdx (int nIdx, gint &nMonitor);
+#endif
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/hudawareness.h b/vcl/inc/unx/gtk/hudawareness.h
new file mode 100644
index 0000000000..6c9c015d6a
--- /dev/null
+++ b/vcl/inc/unx/gtk/hudawareness.h
@@ -0,0 +1,29 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef void (* HudAwarenessCallback) (gboolean hud_active,
+ gpointer user_data);
+
+guint hud_awareness_register (GDBusConnection *connection,
+ const gchar *object_path,
+ HudAwarenessCallback callback,
+ gpointer user_data,
+ GDestroyNotify notify,
+ GError **error);
+
+void hud_awareness_unregister (GDBusConnection *connection,
+ guint awareness_id);
+
+G_END_DECLS