diff options
Diffstat (limited to 'vcl/inc/unx/gtk')
-rw-r--r-- | vcl/inc/unx/gtk/atkbridge.hxx | 25 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gloactiongroup.h | 75 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/glomenu.h | 134 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkbackend.hxx | 30 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkdata.hxx | 367 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkframe.hxx | 694 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkgdi.hxx | 245 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkinst.hxx | 349 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkobject.hxx | 120 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtksalmenu.hxx | 158 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtksys.hxx | 47 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/hudawareness.h | 29 |
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 |