summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Executable_xid_fullscreen_on_all_monitors.mk22
-rw-r--r--vcl/Library_vclplug_gtk.mk132
-rw-r--r--vcl/Library_vclplug_gtk3.mk6
-rw-r--r--vcl/Library_vclplug_gtk3_kde5.mk1
-rw-r--r--vcl/Module_vcl.mk6
-rw-r--r--vcl/inc/unx/gtk/gtkdata.hxx40
-rw-r--r--vcl/inc/unx/gtk/gtkframe.hxx36
-rw-r--r--vcl/inc/unx/gtk/gtkgdi.hxx4
-rw-r--r--vcl/inc/unx/gtk/gtkinst.hxx17
-rw-r--r--vcl/inc/unx/gtk/gtkobject.hxx4
-rw-r--r--vcl/inc/unx/gtk/gtkprintwrapper.hxx57
-rw-r--r--vcl/inc/unx/gtk/gtksalmenu.hxx23
-rw-r--r--vcl/source/app/salplug.cxx8
-rw-r--r--vcl/unx/gtk/a11y/atkaction.cxx275
-rw-r--r--vcl/unx/gtk/a11y/atkbridge.cxx72
-rw-r--r--vcl/unx/gtk/a11y/atkcomponent.cxx387
-rw-r--r--vcl/unx/gtk/a11y/atkeditabletext.cxx194
-rw-r--r--vcl/unx/gtk/a11y/atkfactory.cxx195
-rw-r--r--vcl/unx/gtk/a11y/atkhypertext.cxx273
-rw-r--r--vcl/unx/gtk/a11y/atkimage.cxx131
-rw-r--r--vcl/unx/gtk/a11y/atklistener.cxx739
-rw-r--r--vcl/unx/gtk/a11y/atkregistry.cxx66
-rw-r--r--vcl/unx/gtk/a11y/atkselection.cxx190
-rw-r--r--vcl/unx/gtk/a11y/atktable.cxx580
-rw-r--r--vcl/unx/gtk/a11y/atktext.cxx838
-rw-r--r--vcl/unx/gtk/a11y/atktextattributes.cxx1383
-rw-r--r--vcl/unx/gtk/a11y/atkutil.cxx789
-rw-r--r--vcl/unx/gtk/a11y/atkvalue.cxx138
-rw-r--r--vcl/unx/gtk/a11y/atkwindow.cxx330
-rw-r--r--vcl/unx/gtk/a11y/atkwrapper.cxx959
-rw-r--r--vcl/unx/gtk/gloactiongroup.cxx398
-rw-r--r--vcl/unx/gtk/glomenu.cxx691
-rw-r--r--vcl/unx/gtk/gtkdata.cxx890
-rw-r--r--vcl/unx/gtk/gtkinst.cxx478
-rw-r--r--vcl/unx/gtk/gtkobject.cxx192
-rw-r--r--vcl/unx/gtk/gtkprintwrapper.cxx349
-rw-r--r--vcl/unx/gtk/gtksalframe.cxx3606
-rw-r--r--vcl/unx/gtk/gtksalmenu.cxx1444
-rw-r--r--vcl/unx/gtk/gtksys.cxx296
-rw-r--r--vcl/unx/gtk/hudawareness.cxx112
-rw-r--r--vcl/unx/gtk/salnativewidgets-gtk.cxx4480
-rw-r--r--vcl/unx/gtk/salprn-gtk.cxx970
-rw-r--r--vcl/unx/gtk/xid_fullscreen_on_all_monitors.c101
-rw-r--r--vcl/unx/gtk3/a11y/TODO (renamed from vcl/unx/gtk/a11y/TODO)0
-rw-r--r--vcl/unx/gtk3/a11y/atkfactory.hxx (renamed from vcl/unx/gtk/a11y/atkfactory.hxx)0
-rw-r--r--vcl/unx/gtk3/a11y/atklistener.hxx (renamed from vcl/unx/gtk/a11y/atklistener.hxx)0
-rw-r--r--vcl/unx/gtk3/a11y/atkregistry.hxx (renamed from vcl/unx/gtk/a11y/atkregistry.hxx)0
-rw-r--r--vcl/unx/gtk3/a11y/atktextattributes.hxx (renamed from vcl/unx/gtk/a11y/atktextattributes.hxx)0
-rw-r--r--vcl/unx/gtk3/a11y/atkutil.hxx (renamed from vcl/unx/gtk/a11y/atkutil.hxx)0
-rw-r--r--vcl/unx/gtk3/a11y/atkwindow.hxx (renamed from vcl/unx/gtk/a11y/atkwindow.hxx)0
-rw-r--r--vcl/unx/gtk3/a11y/atkwrapper.hxx (renamed from vcl/unx/gtk/a11y/atkwrapper.hxx)6
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkaction.cxx265
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkbridge.cxx27
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkcomponent.cxx373
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkeditabletext.cxx184
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkfactory.cxx176
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkhypertext.cxx263
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkimage.cxx122
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atklistener.cxx729
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkregistry.cxx56
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkselection.cxx180
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atktable.cxx570
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atktext.cxx827
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx1373
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkutil.cxx779
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkvalue.cxx128
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkwindow.cxx320
-rw-r--r--vcl/unx/gtk3/a11y/gtk3atkwrapper.cxx949
-rw-r--r--vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx (renamed from vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx)15
-rw-r--r--vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx (renamed from vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx)2
-rw-r--r--vcl/unx/gtk3/fpicker/SalGtkFolderPicker.cxx (renamed from vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx)2
-rw-r--r--vcl/unx/gtk3/fpicker/SalGtkFolderPicker.hxx (renamed from vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx)2
-rw-r--r--vcl/unx/gtk3/fpicker/SalGtkPicker.cxx (renamed from vcl/unx/gtk/fpicker/SalGtkPicker.cxx)2
-rw-r--r--vcl/unx/gtk3/fpicker/SalGtkPicker.hxx (renamed from vcl/unx/gtk/fpicker/SalGtkPicker.hxx)0
-rw-r--r--vcl/unx/gtk3/fpicker/eventnotification.hxx (renamed from vcl/unx/gtk/fpicker/eventnotification.hxx)0
-rw-r--r--vcl/unx/gtk3/fpicker/resourceprovider.cxx (renamed from vcl/unx/gtk/fpicker/resourceprovider.cxx)2
-rw-r--r--vcl/unx/gtk3/gtk3fpicker.cxx15
-rw-r--r--vcl/unx/gtk3/gtk3gloactiongroup.cxx400
-rw-r--r--vcl/unx/gtk3/gtk3glomenu.cxx683
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx401
-rw-r--r--vcl/unx/gtk3/gtk3gtkprintwrapper.cxx150
-rw-r--r--vcl/unx/gtk3/gtk3gtksalmenu.cxx1393
-rw-r--r--vcl/unx/gtk3/gtk3gtksys.cxx273
-rw-r--r--vcl/unx/gtk3/gtk3hudawareness.cxx105
-rw-r--r--vcl/unx/gtk3/gtk3salprn-gtk.cxx952
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkaction.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkbridge.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkcomponent.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkeditabletext.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkfactory.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkhypertext.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkimage.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atklistener.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkregistry.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkselection.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktable.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktext.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktextattributes.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkutil.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkvalue.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwindow.cxx2
-rw-r--r--vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwrapper.cxx2
102 files changed, 11686 insertions, 21974 deletions
diff --git a/vcl/Executable_xid_fullscreen_on_all_monitors.mk b/vcl/Executable_xid_fullscreen_on_all_monitors.mk
deleted file mode 100644
index 296436abd106..000000000000
--- a/vcl/Executable_xid_fullscreen_on_all_monitors.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
-#
-# 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/.
-#
-
-$(eval $(call gb_Executable_Executable,xid-fullscreen-on-all-monitors))
-
-ifeq ($(filter ANDROID WNT DRAGONFLY FREEBSD NETBSD OPENBSD MACOSX,$(OS)),)
-$(eval $(call gb_Executable_add_libs,xid-fullscreen-on-all-monitors,\
- -ldl \
-))
-endif
-
-$(eval $(call gb_Executable_add_cobjects,xid-fullscreen-on-all-monitors,\
- vcl/unx/gtk/xid_fullscreen_on_all_monitors \
-))
-
-# vim: set noet sw=4 ts=4:
diff --git a/vcl/Library_vclplug_gtk.mk b/vcl/Library_vclplug_gtk.mk
deleted file mode 100644
index 360eabf46020..000000000000
--- a/vcl/Library_vclplug_gtk.mk
+++ /dev/null
@@ -1,132 +0,0 @@
-# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
-#
-# 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 .
-#
-
-$(eval $(call gb_Library_Library,vclplug_gtk))
-
-$(eval $(call gb_Library_set_include,vclplug_gtk,\
- $$(INCLUDE) \
- -I$(SRCDIR)/vcl/inc \
- -I$(SRCDIR)/vcl/unx \
- -I$(SRCDIR)/vcl/unx/gtk \
-))
-
-$(eval $(call gb_Library_add_defs,vclplug_gtk,\
- -DVCLPLUG_GTK_IMPLEMENTATION \
-))
-
-$(eval $(call gb_Library_use_custom_headers,vclplug_gtk,\
- officecfg/registry \
-))
-
-$(eval $(call gb_Library_use_sdk_api,vclplug_gtk))
-
-$(eval $(call gb_Library_use_libraries,vclplug_gtk,\
- vclplug_gen \
- vcl \
- tl \
- utl \
- sot \
- ucbhelper \
- basegfx \
- comphelper \
- cppuhelper \
- i18nlangtag \
- i18nutil \
- $(if $(ENABLE_JAVA), \
- jvmaccess) \
- cppu \
- sal \
-))
-
-$(eval $(call gb_Library_use_externals,vclplug_gtk,\
- boost_headers \
- cairo \
- dbus \
- epoxy \
- gio \
- graphite \
- gthread \
- gtk \
- harfbuzz \
- icuuc \
-))
-
-$(eval $(call gb_Library_add_libs,vclplug_gtk,\
- -lX11 \
- -lXext \
- -lSM \
- -lICE \
-))
-
-$(eval $(call gb_Library_add_exception_objects,vclplug_gtk,\
- vcl/unx/gtk/a11y/atkaction \
- vcl/unx/gtk/a11y/atkbridge \
- vcl/unx/gtk/a11y/atkcomponent \
- vcl/unx/gtk/a11y/atkeditabletext \
- vcl/unx/gtk/a11y/atkfactory \
- vcl/unx/gtk/a11y/atkhypertext \
- vcl/unx/gtk/a11y/atkimage \
- vcl/unx/gtk/a11y/atklistener \
- vcl/unx/gtk/a11y/atkregistry \
- vcl/unx/gtk/a11y/atkselection \
- vcl/unx/gtk/a11y/atktable \
- vcl/unx/gtk/a11y/atktextattributes \
- vcl/unx/gtk/a11y/atktext \
- vcl/unx/gtk/a11y/atkutil \
- vcl/unx/gtk/a11y/atkvalue \
- vcl/unx/gtk/a11y/atkwindow \
- vcl/unx/gtk/a11y/atkwrapper \
- vcl/unx/gtk/gtkdata \
- vcl/unx/gtk/gtkinst \
- vcl/unx/gtk/gtksys \
- vcl/unx/gtk/salnativewidgets-gtk \
- vcl/unx/gtk/gtksalframe \
- vcl/unx/gtk/gtkobject \
- vcl/unx/gtk/fpicker/resourceprovider \
- vcl/unx/gtk/fpicker/SalGtkPicker \
- vcl/unx/gtk/fpicker/SalGtkFilePicker \
- vcl/unx/gtk/fpicker/SalGtkFolderPicker \
-))
-
-ifneq ($(ENABLE_DBUS),)
-ifneq ($(ENABLE_GIO),)
-$(eval $(call gb_Library_add_exception_objects,vclplug_gtk,\
- vcl/unx/gtk/gloactiongroup \
- vcl/unx/gtk/gtksalmenu \
- vcl/unx/gtk/glomenu \
- vcl/unx/gtk/hudawareness \
-))
-endif
-endif
-
-ifeq ($(ENABLE_GTK_PRINT),TRUE)
-$(eval $(call gb_Library_add_exception_objects,vclplug_gtk,\
- vcl/unx/gtk/gtkprintwrapper \
- vcl/unx/gtk/salprn-gtk \
-))
-endif
-
-ifeq ($(OS),LINUX)
-$(eval $(call gb_Library_add_libs,vclplug_gtk,\
- -lm \
- -ldl \
-))
-endif
-
-# vim: set noet sw=4 ts=4:
diff --git a/vcl/Library_vclplug_gtk3.mk b/vcl/Library_vclplug_gtk3.mk
index c0ad6cd21e52..9f6504c38f56 100644
--- a/vcl/Library_vclplug_gtk3.mk
+++ b/vcl/Library_vclplug_gtk3.mk
@@ -46,7 +46,6 @@ $(eval $(call gb_Library_use_sdk_api,vclplug_gtk3))
$(eval $(call gb_Library_add_libs,vclplug_gtk3,\
$(GTK3_LIBS) \
- $(GTHREAD_LIBS) \
-lX11 \
-lXext \
-lSM \
@@ -97,10 +96,13 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk3,\
vcl/unx/gtk3/a11y/gtk3atkvalue \
vcl/unx/gtk3/a11y/gtk3atkwindow \
vcl/unx/gtk3/a11y/gtk3atkwrapper \
+ vcl/unx/gtk3/fpicker/resourceprovider \
+ vcl/unx/gtk3/fpicker/SalGtkFilePicker \
+ vcl/unx/gtk3/fpicker/SalGtkFolderPicker \
+ vcl/unx/gtk3/fpicker/SalGtkPicker \
vcl/unx/gtk3/gtk3gtkdata \
vcl/unx/gtk3/gtk3gtkinst \
vcl/unx/gtk3/gtk3gtksys \
- vcl/unx/gtk3/gtk3fpicker \
vcl/unx/gtk3/cairo_gtk3_cairo \
vcl/unx/gtk3/gtk3gtkprintwrapper \
vcl/unx/gtk3/gtk3salnativewidgets-gtk \
diff --git a/vcl/Library_vclplug_gtk3_kde5.mk b/vcl/Library_vclplug_gtk3_kde5.mk
index d67c53e2a6f5..231726449c4e 100644
--- a/vcl/Library_vclplug_gtk3_kde5.mk
+++ b/vcl/Library_vclplug_gtk3_kde5.mk
@@ -51,7 +51,6 @@ $(eval $(call gb_Library_use_sdk_api,vclplug_gtk3_kde5))
$(eval $(call gb_Library_add_libs,vclplug_gtk3_kde5,\
$(GTK3_LIBS) \
- $(GTHREAD_LIBS) \
-lX11 \
-lXext \
-lSM \
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 54e3fbd6b07f..859702ca4032 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -66,12 +66,6 @@ $(eval $(call gb_Module_add_targets,vcl,\
Package_fontunxpsprint \
))
-ifneq ($(ENABLE_GTK),)
-$(eval $(call gb_Module_add_targets,vcl,\
- Executable_xid_fullscreen_on_all_monitors \
- Library_vclplug_gtk \
-))
-endif
ifneq ($(ENABLE_GTK3),)
$(eval $(call gb_Module_add_targets,vcl,\
Library_vclplug_gtk3 \
diff --git a/vcl/inc/unx/gtk/gtkdata.hxx b/vcl/inc/unx/gtk/gtkdata.hxx
index f1750b7dc3a6..84e2d19f6c94 100644
--- a/vcl/inc/unx/gtk/gtkdata.hxx
+++ b/vcl/inc/unx/gtk/gtkdata.hxx
@@ -42,44 +42,22 @@ class DocumentFocusListener;
inline GdkWindow * widget_get_window(GtkWidget *widget)
{
-#if GTK_CHECK_VERSION(3,0,0)
return gtk_widget_get_window(widget);
-#else
- return widget->window;
-#endif
}
inline ::Window widget_get_xid(GtkWidget *widget)
{
-#if GTK_CHECK_VERSION(3,0,0)
return GDK_WINDOW_XID(gtk_widget_get_window(widget));
-#else
- return GDK_WINDOW_XWINDOW(widget->window);
-#endif
}
inline void widget_set_can_focus(GtkWidget *widget, gboolean can_focus)
{
-#if GTK_CHECK_VERSION(3,0,0)
return gtk_widget_set_can_focus(widget, can_focus);
-#else
- if (can_focus)
- GTK_WIDGET_SET_FLAGS( widget, GTK_CAN_FOCUS );
- else
- GTK_WIDGET_UNSET_FLAGS( widget, GTK_CAN_FOCUS );
-#endif
}
inline void widget_set_can_default(GtkWidget *widget, gboolean can_default)
{
-#if GTK_CHECK_VERSION(3,0,0)
return gtk_widget_set_can_default(widget, can_default);
-#else
- if (can_default)
- GTK_WIDGET_SET_FLAGS( widget, GTK_CAN_DEFAULT );
- else
- GTK_WIDGET_UNSET_FLAGS( widget, GTK_CAN_DEFAULT );
-#endif
}
class GtkSalTimer final : public SalTimer
@@ -132,11 +110,7 @@ public:
class GtkSalFrame;
-#if GTK_CHECK_VERSION(3,0,0)
class GtkSalDisplay : public SalGenericDisplay
-#else
-class GtkSalDisplay : public SalDisplay
-#endif
{
GtkSalSystem* m_pSys;
GdkDisplay* const m_pGdkDisplay;
@@ -161,20 +135,11 @@ public:
virtual void deregisterFrame( SalFrame* pFrame ) override;
GdkCursor *getCursor( PointerStyle ePointerStyle );
-#if GTK_CHECK_VERSION(3,0,0)
virtual int CaptureMouse( SalFrame* pFrame );
-#else
- virtual int CaptureMouse( SalFrame* pFrame ) override;
-#endif
SalX11Screen GetDefaultXScreen() { return m_pSys->GetDisplayDefaultXScreen(); }
Size GetScreenSize( int nDisplayScreen );
int GetXScreenCount() { return m_pSys->GetDisplayXScreenCount(); }
-#if GTK_CHECK_VERSION(3,0,0)
-// int GetScreenCount() { return m_pSys->GetDisplayScreenCount(); }
-#else
- virtual ScreenData *initScreen( SalX11Screen nXScreen ) const override;
-#endif
GdkFilterReturn filterGdkEvent( GdkXEvent* sys_event );
void startupNotificationCompleted() { m_bStartupCompleted = true; }
@@ -185,12 +150,7 @@ public:
virtual void TriggerUserEventProcessing() override;
virtual void TriggerAllUserEventsProcessed() override;
-#if !GTK_CHECK_VERSION(3,0,0)
- virtual bool Dispatch( XEvent *pEvent ) override;
-#endif
-#if GTK_CHECK_VERSION(3,0,0)
void RefreshMenusUnity();
-#endif
};
inline GtkSalData* GetGtkSalData()
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 084339f96d70..f9a41c6c3cf6 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -24,9 +24,7 @@
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
-#if GTK_CHECK_VERSION(3,0,0)
-# include <gtk/gtkx.h>
-#endif
+#include <gtk/gtkx.h>
#include <gdk/gdkkeysyms.h>
#include <salframe.hxx>
@@ -54,7 +52,6 @@
class GtkSalGraphics;
class GtkSalDisplay;
-#if GTK_CHECK_VERSION(3,0,0)
typedef sal_uIntPtr GdkNativeWindow;
#define GDK_WINDOW_XWINDOW(o) GDK_WINDOW_XID(o)
#define gdk_set_sm_client_id(i) gdk_x11_set_sm_client_id(i)
@@ -62,11 +59,6 @@ typedef sal_uIntPtr GdkNativeWindow;
class GtkDropTarget;
class GtkDragSource;
class GtkDnDTransferable;
-#endif
-
-#if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 26)
- typedef void GDBusConnection;
-#endif
class GtkSalMenu;
@@ -172,10 +164,8 @@ class GtkSalFrame : public SalFrame
SalX11Screen m_nXScreen;
GtkWidget* m_pWindow;
-#if GTK_CHECK_VERSION(3,0,0)
GtkHeaderBar* m_pHeaderBar;
GtkGrid* m_pTopLevelGrid;
-#endif
GtkEventBox* m_pEventBox;
GtkFixed* m_pFixedContainer;
GdkWindow* m_pForeignParent;
@@ -208,7 +198,6 @@ class GtkSalFrame : public SalFrame
Size m_aMinSize;
tools::Rectangle m_aRestorePosSize;
-#if GTK_CHECK_VERSION(3,0,0)
OUString m_aTooltip;
tools::Rectangle m_aHelpArea;
tools::Rectangle m_aFloatRect;
@@ -220,10 +209,6 @@ class GtkSalFrame : public SalFrame
GtkDropTarget* m_pDropTarget;
GtkDragSource* m_pDragSource;
bool m_bGeometryIsProvisional;
-#else
- GdkRegion* m_pRegion;
- bool m_bSetFocusOnMap;
-#endif
GtkSalMenu* m_pSalMenu;
@@ -242,12 +227,7 @@ class GtkSalFrame : public SalFrame
// signals
static gboolean signalButton( GtkWidget*, GdkEventButton*, gpointer );
-#if GTK_CHECK_VERSION(3,0,0)
static void signalStyleUpdated(GtkWidget*, gpointer);
-#else
- static void signalStyleSet(GtkWidget*, GtkStyle* pPrevious, gpointer);
-#endif
-#if GTK_CHECK_VERSION(3,0,0)
static gboolean signalDraw( GtkWidget*, cairo_t *cr, gpointer );
static void signalRealize(GtkWidget*, gpointer frame);
static void sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame);
@@ -270,11 +250,6 @@ class GtkSalFrame : public SalFrame
static void gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame);
static void gestureLongPress(GtkGestureLongPress* gesture, gdouble x, gdouble y, gpointer frame);
-#else
- static gboolean signalExpose( GtkWidget*, GdkEventExpose*, gpointer );
- void askForXEmbedFocus( sal_Int32 nTimecode );
- void grabKeyboard(bool bGrab);
-#endif
static gboolean signalFocus( GtkWidget*, GdkEventFocus*, gpointer );
static gboolean signalMap( GtkWidget*, GdkEvent*, gpointer );
static gboolean signalUnmap( GtkWidget*, GdkEvent*, gpointer );
@@ -345,7 +320,6 @@ class GtkSalFrame : public SalFrame
void SetScreen( unsigned int nNewScreen, SetType eType, tools::Rectangle const *pSize = nullptr );
public:
-#if GTK_CHECK_VERSION(3,0,0)
cairo_surface_t* m_pSurface;
basegfx::B2IVector m_aFrameSize;
DamageHandler m_aDamageHandler;
@@ -353,7 +327,6 @@ public:
Idle m_aSmoothScrollIdle;
int m_nGrabLevel;
bool m_bSalObjectSetPosSize;
-#endif
GtkSalFrame( SalFrame* pParent, SalFrameStyleFlags nStyle );
GtkSalFrame( SystemParentData* pSysData );
@@ -374,9 +347,7 @@ public:
GtkFixed* getFixedContainer() const { return m_pFixedContainer; }
GtkEventBox* getEventBox() const { return m_pEventBox; }
GtkWidget* getMouseEventWidget() const;
-#if GTK_CHECK_VERSION(3,0,0)
GtkGrid* getTopLevelGridWidget() const { return m_pTopLevelGrid; }
-#endif
GdkWindow* getForeignParent() const { return m_pForeignParent; }
GdkNativeWindow getForeignParentWindow() const { return m_aForeignParentWindow; }
GdkWindow* getForeignTopLevel() const { return m_pForeignTopLevel; }
@@ -385,8 +356,6 @@ public:
int GetDisplayScreen() const { return maGeometry.nDisplayScreenNumber; }
void updateScreenNumber();
-#if GTK_CHECK_VERSION(3,0,0)
- // only for gtk3 ...
cairo_t* getCairoContext() const;
void damaged(sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop,
sal_Int32 nExtentsRight, sal_Int32 nExtentsBottom) const;
@@ -428,7 +397,6 @@ public:
void LaunchAsyncScroll(GdkEvent const * pEvent);
DECL_LINK(AsyncScroll, Timer *, void);
-#endif
virtual ~GtkSalFrame() override;
// SalGraphics or NULL, but two Graphics for all SalFrames
@@ -525,7 +493,6 @@ public:
// done setting up the clipregion
virtual void EndSetClipRegion() override;
-#if GTK_CHECK_VERSION(3,0,0)
virtual void PositionByToolkit(const tools::Rectangle& rRect, FloatWinPopupFlags nFlags) override;
virtual void SetModal(bool bModal) override;
virtual bool GetModal() const override;
@@ -535,7 +502,6 @@ public:
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;
-#endif
static GtkSalFrame *getFromWindow( GtkWindow *pWindow );
diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
index c9b7be49f13e..e19d01205e49 100644
--- a/vcl/inc/unx/gtk/gtkgdi.hxx
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -29,8 +29,6 @@
#include <unx/gtk/gtkframe.hxx>
#include <ControlCacheKey.hxx>
-#if GTK_CHECK_VERSION(3,0,0)
-
#include <headless/svpgdi.hxx>
#include <textrender.hxx>
@@ -394,8 +392,6 @@ protected:
ControlState nState, const ImplControlValue& aValue );
};
-#endif // !gtk3
-
#endif // INCLUDED_VCL_INC_UNX_GTK_GTKGDI_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx
index 65caa384c0ae..78dd9bc6e8b9 100644
--- a/vcl/inc/unx/gtk/gtkinst.hxx
+++ b/vcl/inc/unx/gtk/gtkinst.hxx
@@ -57,7 +57,6 @@ public:
void ThreadsLeave();
};
-#if GTK_CHECK_VERSION(3,0,0)
class GtkSalFrame;
struct VclToGtkHelper
@@ -182,20 +181,10 @@ public:
css::uno::Reference<css::datatransfer::XTransferable> const & GetTransferrable() const { return m_xTrans; }
};
-#endif
-
class GtkSalTimer;
-#if GTK_CHECK_VERSION(3,0,0)
class GtkInstance : public SvpSalInstance
-#else
-class GtkInstance : public X11SalInstance
-#endif
{
-#if GTK_CHECK_VERSION(3,0,0)
typedef SvpSalInstance Superclass_t;
-#else
- typedef X11SalInstance Superclass_t;
-#endif
public:
GtkInstance( std::unique_ptr<SalYieldMutex> pMutex );
virtual ~GtkInstance() override;
@@ -233,7 +222,6 @@ public:
virtual css::uno::Reference< css::ui::dialogs::XFolderPicker2 >
createFolderPicker( const css::uno::Reference< css::uno::XComponentContext >& ) override;
-#if GTK_CHECK_VERSION(3,0,0)
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 > CreateDragSource() override;
virtual css::uno::Reference< css::uno::XInterface > CreateDropTarget() override;
@@ -241,7 +229,6 @@ public:
virtual weld::Builder* CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile) 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;
-#endif
virtual const cairo_font_options_t* GetCairoFontOptions() override;
const cairo_font_options_t* GetLastSeenCairoFontOptions() const;
@@ -251,15 +238,11 @@ public:
std::shared_ptr<vcl::unx::GtkPrintWrapper> const & getPrintWrapper() const;
-#if GTK_CHECK_VERSION(3,0,0)
void* CreateGStreamerSink(const SystemChildWindow*) override;
-#endif
private:
GtkSalTimer *m_pTimer;
-#if GTK_CHECK_VERSION(3,0,0)
std::unordered_map< GdkAtom, css::uno::Reference<css::uno::XInterface> > m_aClipboards;
-#endif
bool IsTimerExpired();
bool bNeedsInit;
cairo_font_options_t* m_pLastCairoFontOptions;
diff --git a/vcl/inc/unx/gtk/gtkobject.hxx b/vcl/inc/unx/gtk/gtkobject.hxx
index 4523e9998abd..f54d7af3f04c 100644
--- a/vcl/inc/unx/gtk/gtkobject.hxx
+++ b/vcl/inc/unx/gtk/gtkobject.hxx
@@ -29,12 +29,8 @@ class GtkSalObject : public SalObject
{
SystemEnvData m_aSystemData;
GtkWidget* m_pSocket;
-#if GTK_CHECK_VERSION(3,0,0)
GtkSalFrame* m_pParent;
cairo_region_t* m_pRegion;
-#else
- GdkRegion* m_pRegion;
-#endif
// signals
static gboolean signalButton( GtkWidget*, GdkEventButton*, gpointer );
diff --git a/vcl/inc/unx/gtk/gtkprintwrapper.hxx b/vcl/inc/unx/gtk/gtkprintwrapper.hxx
index 4862c8cc2fbc..589c800d77d1 100644
--- a/vcl/inc/unx/gtk/gtkprintwrapper.hxx
+++ b/vcl/inc/unx/gtk/gtkprintwrapper.hxx
@@ -12,14 +12,11 @@
#include <gtk/gtk.h>
-#if defined ENABLE_GTK_PRINT || GTK_CHECK_VERSION(3,0,0)
#include <gtk/gtkunixprint.h>
#include <osl/module.hxx>
#include <sal/types.h>
-#endif
-
namespace vcl
{
namespace unx
@@ -30,7 +27,6 @@ class GtkPrintWrapper
private:
GtkPrintWrapper(const GtkPrintWrapper&) = delete;
GtkPrintWrapper& operator=(const GtkPrintWrapper&) = delete;
-#if defined ENABLE_GTK_PRINT || GTK_CHECK_VERSION(3,0,0)
public:
GtkPrintWrapper();
~GtkPrintWrapper();
@@ -63,59 +59,6 @@ public:
// print selection support, since 2.17.4
void print_unix_dialog_set_support_selection(GtkPrintUnixDialog* dialog, gboolean support_selection) const;
void print_unix_dialog_set_has_selection(GtkPrintUnixDialog* dialog, gboolean has_selection) const;
-
-#if !GTK_CHECK_VERSION(3,0,0)
-private:
- void impl_load();
-
-private:
- typedef GtkPageSetup* (* page_setup_new_t)();
- typedef GtkPrintJob* (* print_job_new_t)(const gchar*, GtkPrinter*, GtkPrintSettings*, GtkPageSetup*);
- typedef void (* print_job_send_t)(GtkPrintJob*, GtkPrintJobCompleteFunc, gpointer, GDestroyNotify);
- typedef gboolean (* print_job_set_source_file_t)(GtkPrintJob*, const gchar*, GError**);
- typedef const gchar* (* print_settings_get_t)(GtkPrintSettings*, const gchar*);
- typedef gboolean (* print_settings_get_collate_t)(GtkPrintSettings*);
- typedef void (* print_settings_set_collate_t)(GtkPrintSettings*, gboolean);
- typedef gint (* print_settings_get_n_copies_t)(GtkPrintSettings*);
- typedef void (* print_settings_set_n_copies_t)(GtkPrintSettings*, gint);
- typedef GtkPageRange* (* print_settings_get_page_ranges_t)(GtkPrintSettings*, gint*);
- typedef void (* print_settings_set_print_pages_t)(GtkPrintSettings*, GtkPrintPages);
- typedef GtkWidget* (* print_unix_dialog_new_t)(const gchar*, GtkWindow*);
- typedef void (* print_unix_dialog_add_custom_tab_t)(GtkPrintUnixDialog*, GtkWidget*, GtkWidget*);
- typedef GtkPrinter* (* print_unix_dialog_get_selected_printer_t)(GtkPrintUnixDialog*);
- typedef void (* print_unix_dialog_set_manual_capabilities_t)(GtkPrintUnixDialog*, GtkPrintCapabilities);
- typedef GtkPrintSettings* (* print_unix_dialog_get_settings_t)(GtkPrintUnixDialog*);
- typedef void (* print_unix_dialog_set_settings_t)(GtkPrintUnixDialog*, GtkPrintSettings*);
- typedef void (* print_unix_dialog_set_support_selection_t)(GtkPrintUnixDialog*, gboolean);
- typedef void (* print_unix_dialog_set_has_selection_t)(GtkPrintUnixDialog*, gboolean);
-
-private:
- osl::Module m_aModule;
-
- // general printing support, since 2.10.0
- page_setup_new_t m_page_setup_new;
- print_job_new_t m_print_job_new;
- print_job_send_t m_print_job_send;
- print_job_set_source_file_t m_print_job_set_source_file;
- print_settings_get_t m_print_settings_get;
- print_settings_get_collate_t m_print_settings_get_collate;
- print_settings_set_collate_t m_print_settings_set_collate;
- print_settings_get_n_copies_t m_print_settings_get_n_copies;
- print_settings_set_n_copies_t m_print_settings_set_n_copies;
- print_settings_get_page_ranges_t m_print_settings_get_page_ranges;
- print_settings_set_print_pages_t m_print_settings_set_print_pages;
- print_unix_dialog_new_t m_print_unix_dialog_new;
- print_unix_dialog_add_custom_tab_t m_print_unix_dialog_add_custom_tab;
- print_unix_dialog_get_selected_printer_t m_print_unix_dialog_get_selected_printer;
- print_unix_dialog_set_manual_capabilities_t m_print_unix_dialog_set_manual_capabilities;
- print_unix_dialog_get_settings_t m_print_unix_dialog_get_settings;
- print_unix_dialog_set_settings_t m_print_unix_dialog_set_settings;
-
- // print selection support, since 2.17.4
- print_unix_dialog_set_support_selection_t m_print_unix_dialog_set_support_selection;
- print_unix_dialog_set_has_selection_t m_print_unix_dialog_set_has_selection;
-#endif
-#endif
};
}
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index 2d812cad3962..ddef9ef42310 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -23,27 +23,8 @@
#include <unotools/tempfile.hxx>
#include <vcl/idle.hxx>
-#if GTK_CHECK_VERSION(3,0,0)
-# define ENABLE_GMENU_INTEGRATION
-# include <unx/gtk/glomenu.h>
-# include <unx/gtk/gloactiongroup.h>
-#elif ENABLE_DBUS && ENABLE_GIO && \
- (GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 36)
-# define ENABLE_GMENU_INTEGRATION
-# include <unx/gtk/glomenu.h>
-# include <unx/gtk/gloactiongroup.h>
-#else
-# if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 32)
- typedef void GMenuModel;
-# endif
-# if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 28)
- typedef void GActionGroup;
-# endif
-#endif
-
-#if !GTK_CHECK_VERSION(3,0,0)
-typedef void GtkCssProvider;
-#endif
+#include <unx/gtk/glomenu.h>
+#include <unx/gtk/gloactiongroup.h>
class MenuItemList;
class GtkSalMenuItem;
diff --git a/vcl/source/app/salplug.cxx b/vcl/source/app/salplug.cxx
index 20604edb7f46..ce3fb551d6af 100644
--- a/vcl/source/app/salplug.cxx
+++ b/vcl/source/app/salplug.cxx
@@ -95,7 +95,7 @@ SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = false )
* So make sure libgtk+ & co are still mapped into memory when
* atk-bridge's atexit handler gets called.
*/
- if( aUsedModuleBase == "gtk" || aUsedModuleBase == "gtk3" || aUsedModuleBase == "gtk3_kde5" || aUsedModuleBase == "win" )
+ if( aUsedModuleBase == "gtk3" || aUsedModuleBase == "gtk3_kde5" || aUsedModuleBase == "win" )
{
pCloseModule = nullptr;
}
@@ -154,12 +154,12 @@ SalInstance* autodetect_plugin()
#if ENABLE_GTK3_KDE5
"gtk3_kde5",
#endif
- "gtk3", "gtk", "gen", nullptr
+ "gtk3", "gen", nullptr
};
static const char* const pStandardFallbackList[] =
{
- "gtk3", "gtk", "gen", nullptr
+ "gtk3", "gen", nullptr
};
#ifdef HEADLESS_VCLPLUG
@@ -259,7 +259,7 @@ SalInstance *CreateSalInstance()
#ifdef MACOSX
"osx"
#else
- "gtk3", "gtk", "kf5", "gen"
+ "gtk3", "kf5", "gen"
#endif
#endif
};
diff --git a/vcl/unx/gtk/a11y/atkaction.cxx b/vcl/unx/gtk/a11y/atkaction.cxx
deleted file mode 100644
index 14a172fe6ae3..000000000000
--- a/vcl/unx/gtk/a11y/atkaction.cxx
+++ /dev/null
@@ -1,275 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleAction.hpp>
-#include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
-
-#include <com/sun/star/awt/Key.hpp>
-#include <com/sun/star/awt/KeyModifier.hpp>
-
-#include <rtl/strbuf.hxx>
-#include <algorithm>
-#include <map>
-
-using namespace ::com::sun::star;
-
-// FIXME
-static const gchar *
-getAsConst( const OString& rString )
-{
- static const int nMax = 10;
- static OString aUgly[nMax];
- static int nIdx = 0;
- nIdx = (nIdx + 1) % nMax;
- aUgly[nIdx] = rString;
- return aUgly[ nIdx ].getStr();
-}
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleAction>
- getAction( AtkAction *action )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( action );
-
- if( pWrap )
- {
- if( !pWrap->mpAction.is() )
- {
- pWrap->mpAction.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpAction;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleAction>();
-}
-
-extern "C" {
-
-static gboolean
-action_wrapper_do_action (AtkAction *action,
- gint i)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleAction> pAction
- = getAction( action );
- if( pAction.is() )
- return pAction->doAccessibleAction( i );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in doAccessibleAction()" );
- }
-
- return FALSE;
-}
-
-static gint
-action_wrapper_get_n_actions (AtkAction *action)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleAction> pAction
- = getAction( action );
- if( pAction.is() )
- return pAction->getAccessibleActionCount();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleActionCount()" );
- }
-
- return 0;
-}
-
-static const gchar *
-action_wrapper_get_description (AtkAction *, gint)
-{
- // GAIL implement this only for cells
- g_warning( "Not implemented: get_description()" );
- return "";
-}
-
-static const gchar *
-action_wrapper_get_localized_name (AtkAction *, gint)
-{
- // GAIL doesn't implement this as well
- g_warning( "Not implemented: get_localized_name()" );
- return "";
-}
-
-#define ACTION_NAME_PAIR( OOoName, AtkName ) \
- std::pair< const OUString, const gchar * > ( OUString( OOoName ), AtkName )
-
-static const gchar *
-action_wrapper_get_name (AtkAction *action,
- gint i)
-{
- static std::map< OUString, const gchar * > aNameMap;
-
- if( aNameMap.empty() )
- {
- aNameMap.insert( ACTION_NAME_PAIR( "click", "click" ) );
- aNameMap.insert( ACTION_NAME_PAIR( "select", "click" ) );
- aNameMap.insert( ACTION_NAME_PAIR( "togglePopup", "push" ) );
- }
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleAction> pAction
- = getAction( action );
- if( pAction.is() )
- {
- std::map< OUString, const gchar * >::iterator iter;
-
- OUString aDesc( pAction->getAccessibleActionDescription( i ) );
-
- iter = aNameMap.find( aDesc );
- if( iter != aNameMap.end() )
- return iter->second;
-
- std::pair< const OUString, const gchar * > aNewVal( aDesc,
- g_strdup( OUStringToConstGChar(aDesc) ) );
-
- if( aNameMap.insert( aNewVal ).second )
- return aNewVal.second;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleActionDescription()" );
- }
-
- return "";
-}
-
-/*
-* GNOME Expects a string in the format:
-*
-* <mnemonic>;<full-path>;<accelerator>
-*
-* The keybindings in <full-path> should be separated by ":"
-*/
-
-static void
-appendKeyStrokes(OStringBuffer& rBuffer, const uno::Sequence< awt::KeyStroke >& rKeyStrokes)
-{
- for( const auto& rKeyStroke : rKeyStrokes )
- {
- if( rKeyStroke.Modifiers & awt::KeyModifier::SHIFT )
- rBuffer.append("<Shift>");
- if( rKeyStroke.Modifiers & awt::KeyModifier::MOD1 )
- rBuffer.append("<Control>");
- if( rKeyStroke.Modifiers & awt::KeyModifier::MOD2 )
- rBuffer.append("<Alt>");
-
- if( ( rKeyStroke.KeyCode >= awt::Key::A ) && ( rKeyStroke.KeyCode <= awt::Key::Z ) )
- rBuffer.append( static_cast<sal_Char>( 'a' + ( rKeyStroke.KeyCode - awt::Key::A ) ) );
- else
- {
- sal_Char c = '\0';
-
- switch( rKeyStroke.KeyCode )
- {
- case awt::Key::TAB: c = '\t'; break;
- case awt::Key::SPACE: c = ' '; break;
- case awt::Key::ADD: c = '+'; break;
- case awt::Key::SUBTRACT: c = '-'; break;
- case awt::Key::MULTIPLY: c = '*'; break;
- case awt::Key::DIVIDE: c = '/'; break;
- case awt::Key::POINT: c = '.'; break;
- case awt::Key::COMMA: c = ','; break;
- case awt::Key::LESS: c = '<'; break;
- case awt::Key::GREATER: c = '>'; break;
- case awt::Key::EQUAL: c = '='; break;
- case 0:
- break;
- default:
- g_warning( "Unmapped KeyCode: %d", rKeyStroke.KeyCode );
- break;
- }
-
- if( c != '\0' )
- rBuffer.append( c );
- else
- {
- // The KeyCode approach did not work, probably a non ascii character
- // let's hope that there is a character given in KeyChar.
- rBuffer.append( OUStringToGChar( OUString( rKeyStroke.KeyChar ) ) );
- }
- }
- }
-}
-
-static const gchar *
-action_wrapper_get_keybinding (AtkAction *action,
- gint i)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleAction> pAction
- = getAction( action );
- if( pAction.is() )
- {
- uno::Reference< accessibility::XAccessibleKeyBinding > xBinding( pAction->getAccessibleActionKeyBinding( i ));
-
- if( xBinding.is() )
- {
- OStringBuffer aRet;
-
- sal_Int32 nmax = std::min( xBinding->getAccessibleKeyBindingCount(), sal_Int32(3) );
- for( sal_Int32 n = 0; n < nmax; n++ )
- {
- appendKeyStrokes( aRet, xBinding->getAccessibleKeyBinding( n ) );
-
- if( n < 2 )
- aRet.append( ';' );
- }
-
- // !! FIXME !! remember keystroke in wrapper object ?
- return getAsConst( aRet.makeStringAndClear() );
- }
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in get_keybinding()" );
- }
-
- return "";
-}
-
-static gboolean
-action_wrapper_set_description (AtkAction *, gint, const gchar *)
-{
- return FALSE;
-}
-
-} // extern "C"
-
-void
-actionIfaceInit (AtkActionIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->do_action = action_wrapper_do_action;
- iface->get_n_actions = action_wrapper_get_n_actions;
- iface->get_description = action_wrapper_get_description;
- iface->get_keybinding = action_wrapper_get_keybinding;
- iface->get_name = action_wrapper_get_name;
- iface->get_localized_name = action_wrapper_get_localized_name;
- iface->set_description = action_wrapper_set_description;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkbridge.cxx b/vcl/unx/gtk/a11y/atkbridge.cxx
deleted file mode 100644
index a74f1a91885f..000000000000
--- a/vcl/unx/gtk/a11y/atkbridge.cxx
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- 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 .
- */
-
-#include <unx/gtk/atkbridge.hxx>
-#include <unx/gtk/gtkframe.hxx>
-
-#include "atkfactory.hxx"
-#include "atkutil.hxx"
-#include "atkwindow.hxx"
-
-bool InitAtkBridge()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- ooo_atk_util_ensure_event_listener();
-#else
- const char* pVersion = atk_get_toolkit_version();
- if( ! pVersion )
- return false;
-
- unsigned int major, minor, micro;
-
- /* check gail minimum version requirements */
- if( sscanf( pVersion, "%u.%u.%u", &major, &minor, &micro) < 3 )
- {
- // g_warning( "unable to parse gail version number" );
- return false;
- }
-
- if( ( (major << 16) | (minor << 8) | micro ) < ( (1 << 16) | 8 << 8 | 6 ) )
- {
- g_warning( "libgail >= 1.8.6 required for accessibility support" );
- return false;
- }
-
- /* Initialize the AtkUtilityWrapper class */
- g_type_class_unref( g_type_class_ref( ooo_atk_util_get_type() ) );
-
- /* Initialize the GailWindow wrapper class */
- g_type_class_unref( g_type_class_ref( ooo_window_wrapper_get_type() ) );
-
- /* Register AtkObject wrapper factory */
- AtkRegistry * registry = atk_get_default_registry();
- if( registry )
- atk_registry_set_factory_type( registry, OOO_TYPE_FIXED, wrapper_factory_get_type() );
-#endif
- return true;
-}
-
-void DeInitAtkBridge()
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- restore_gail_window_vtable();
-#endif
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkcomponent.cxx b/vcl/unx/gtk/a11y/atkcomponent.cxx
deleted file mode 100644
index da5a48eca1f2..000000000000
--- a/vcl/unx/gtk/a11y/atkcomponent.cxx
+++ /dev/null
@@ -1,387 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
-#include <gtk/gtk.h>
-
-using namespace ::com::sun::star;
-
-static AtkObjectWrapper* getObjectWrapper(AtkComponent *pComponent)
-{
- AtkObjectWrapper *pWrap = nullptr;
- if (ATK_IS_OBJECT_WRAPPER(pComponent))
- pWrap = ATK_OBJECT_WRAPPER(pComponent);
- else if (GTK_IS_DRAWING_AREA(pComponent)) //when using a GtkDrawingArea as a custom widget in welded gtk3
- {
- GtkWidget* pDrawingArea = GTK_WIDGET(pComponent);
- AtkObject* pAtkObject = gtk_widget_get_accessible(pDrawingArea);
- pWrap = ATK_IS_OBJECT_WRAPPER(pAtkObject) ? ATK_OBJECT_WRAPPER(pAtkObject) : nullptr;
- }
- return pWrap;
-}
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleComponent>
- getComponent(AtkObjectWrapper *pWrap)
-{
- if (pWrap)
- {
- if (!pWrap->mpComponent.is())
- pWrap->mpComponent.set(pWrap->mpContext, css::uno::UNO_QUERY);
- return pWrap->mpComponent;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleComponent>();
-}
-
-/*****************************************************************************/
-
-static awt::Point
-translatePoint( css::uno::Reference<accessibility::XAccessibleComponent> const & pComponent,
- gint x, gint y, AtkCoordType t)
-{
- awt::Point aOrigin( 0, 0 );
- if( t == ATK_XY_SCREEN )
- aOrigin = pComponent->getLocationOnScreen();
- return awt::Point( x - aOrigin.X, y - aOrigin.Y );
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-static gboolean
-component_wrapper_grab_focus (AtkComponent *component)
-{
- AtkObjectWrapper* obj = getObjectWrapper(component);
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
- if (obj && obj->mpOrig)
- return atk_component_grab_focus(ATK_COMPONENT(obj->mpOrig));
-
- try
- {
- css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
- = getComponent(obj);
- if( pComponent.is() )
- {
- pComponent->grabFocus();
- return TRUE;
- }
- }
- catch( const uno::Exception & )
- {
- g_warning( "Exception in grabFocus()" );
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-component_wrapper_contains (AtkComponent *component,
- gint x,
- gint y,
- AtkCoordType coord_type)
-{
- AtkObjectWrapper* obj = getObjectWrapper(component);
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
- if (obj && obj->mpOrig)
- return atk_component_contains(ATK_COMPONENT(obj->mpOrig), x, y, coord_type);
-
- try
- {
- css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
- = getComponent(obj);
- if( pComponent.is() )
- return pComponent->containsPoint( translatePoint( pComponent, x, y, coord_type ) );
- }
- catch( const uno::Exception & )
- {
- g_warning( "Exception in containsPoint()" );
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static AtkObject *
-component_wrapper_ref_accessible_at_point (AtkComponent *component,
- gint x,
- gint y,
- AtkCoordType coord_type)
-{
- AtkObjectWrapper* obj = getObjectWrapper(component);
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
- if (obj && obj->mpOrig)
- return atk_component_ref_accessible_at_point(ATK_COMPONENT(obj->mpOrig), x, y, coord_type);
-
- try
- {
- css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
- = getComponent(obj);
-
- if( pComponent.is() )
- {
- uno::Reference< accessibility::XAccessible > xAccessible = pComponent->getAccessibleAtPoint(
- translatePoint( pComponent, x, y, coord_type ) );
- return atk_object_wrapper_ref( xAccessible );
- }
- }
- catch( const uno::Exception & )
- {
- g_warning( "Exception in getAccessibleAtPoint()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static void
-component_wrapper_get_position (AtkComponent *component,
- gint *x,
- gint *y,
- AtkCoordType coord_type)
-{
- AtkObjectWrapper* obj = getObjectWrapper(component);
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
- if (obj && obj->mpOrig)
- {
- atk_component_get_extents(ATK_COMPONENT(obj->mpOrig), x, y, nullptr, nullptr, coord_type);
- return;
- }
-
- *x = *y = -1;
-
- try
- {
- css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
- = getComponent(obj);
- if( pComponent.is() )
- {
- awt::Point aPos;
-
- if( coord_type == ATK_XY_SCREEN )
- aPos = pComponent->getLocationOnScreen();
- else
- aPos = pComponent->getLocation();
-
- *x = aPos.X;
- *y = aPos.Y;
- }
- }
- catch( const uno::Exception & )
- {
- g_warning( "Exception in getLocation[OnScreen]()" );
- }
-}
-
-/*****************************************************************************/
-
-static void
-component_wrapper_get_size (AtkComponent *component,
- gint *width,
- gint *height)
-{
- AtkObjectWrapper* obj = getObjectWrapper(component);
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
- if (obj && obj->mpOrig)
- {
- atk_component_get_extents(ATK_COMPONENT(obj->mpOrig), nullptr, nullptr, width, height, ATK_XY_WINDOW);
- return;
- }
-
- *width = *height = -1;
-
- try
- {
- css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
- = getComponent(obj);
- if( pComponent.is() )
- {
- awt::Size aSize = pComponent->getSize();
- *width = aSize.Width;
- *height = aSize.Height;
- }
- }
- catch( const uno::Exception & )
- {
- g_warning( "Exception in getSize()" );
- }
-}
-
-/*****************************************************************************/
-
-static void
-component_wrapper_get_extents (AtkComponent *component,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- AtkCoordType coord_type)
-{
- component_wrapper_get_position( component, x, y, coord_type );
- component_wrapper_get_size( component, width, height );
-}
-
-/*****************************************************************************/
-
-static gboolean
-component_wrapper_set_extents (AtkComponent *, gint, gint, gint, gint, AtkCoordType)
-{
- g_warning( "AtkComponent::set_extents unimplementable" );
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-component_wrapper_set_position (AtkComponent *, gint, gint, AtkCoordType)
-{
- g_warning( "AtkComponent::set_position unimplementable" );
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-component_wrapper_set_size (AtkComponent *, gint, gint)
-{
- g_warning( "AtkComponent::set_size unimplementable" );
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static AtkLayer
-component_wrapper_get_layer (AtkComponent *component)
-{
- AtkRole role = atk_object_get_role( ATK_OBJECT( component ) );
- AtkLayer layer = ATK_LAYER_WIDGET;
-
- switch (role)
- {
- case ATK_ROLE_POPUP_MENU:
- case ATK_ROLE_MENU_ITEM:
- case ATK_ROLE_CHECK_MENU_ITEM:
- case ATK_ROLE_SEPARATOR:
- case ATK_ROLE_LIST_ITEM:
- layer = ATK_LAYER_POPUP;
- break;
- case ATK_ROLE_MENU:
- {
- AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
- if( atk_object_get_role( parent ) != ATK_ROLE_MENU_BAR )
- layer = ATK_LAYER_POPUP;
- }
- break;
-
- case ATK_ROLE_LIST:
- {
- AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
- if( atk_object_get_role( parent ) == ATK_ROLE_COMBO_BOX )
- layer = ATK_LAYER_POPUP;
- }
- break;
-
- default:
- ;
- }
-
- return layer;
-}
-
-/*****************************************************************************/
-
-static gint
-component_wrapper_get_mdi_zorder (AtkComponent *)
-{
- // only needed for ATK_LAYER_MDI (not used) or ATK_LAYER_WINDOW (inherited from GAIL)
- return G_MININT;
-}
-
-/*****************************************************************************/
-
-// This code is mostly stolen from libgail ..
-
-static guint
-component_wrapper_add_focus_handler (AtkComponent *component,
- AtkFocusHandler handler)
-{
- GSignalMatchType match_type;
- gulong ret;
- guint signal_id;
-
- match_type = GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC);
- signal_id = g_signal_lookup( "focus-event", ATK_TYPE_OBJECT );
-
- ret = g_signal_handler_find( component, match_type, signal_id, 0, nullptr,
- static_cast<gpointer>(&handler), nullptr);
- if (!ret)
- {
- return g_signal_connect_closure_by_id (component,
- signal_id, 0,
- g_cclosure_new (
- G_CALLBACK (handler), nullptr,
- nullptr),
- FALSE);
- }
- else
- {
- return 0;
- }
-}
-
-/*****************************************************************************/
-
-static void
-component_wrapper_remove_focus_handler (AtkComponent *component,
- guint handler_id)
-{
- g_signal_handler_disconnect (component, handler_id);
-}
-
-/*****************************************************************************/
-
-} // extern "C"
-
-void
-componentIfaceInit (AtkComponentIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->add_focus_handler = component_wrapper_add_focus_handler;
- iface->contains = component_wrapper_contains;
- iface->get_extents = component_wrapper_get_extents;
- iface->get_layer = component_wrapper_get_layer;
- iface->get_mdi_zorder = component_wrapper_get_mdi_zorder;
- iface->get_position = component_wrapper_get_position;
- iface->get_size = component_wrapper_get_size;
- iface->grab_focus = component_wrapper_grab_focus;
- iface->ref_accessible_at_point = component_wrapper_ref_accessible_at_point;
- iface->remove_focus_handler = component_wrapper_remove_focus_handler;
- iface->set_extents = component_wrapper_set_extents;
- iface->set_position = component_wrapper_set_position;
- iface->set_size = component_wrapper_set_size;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkeditabletext.cxx b/vcl/unx/gtk/a11y/atkeditabletext.cxx
deleted file mode 100644
index 49d3eb9ccfc9..000000000000
--- a/vcl/unx/gtk/a11y/atkeditabletext.cxx
+++ /dev/null
@@ -1,194 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-#include "atktextattributes.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
-#include <com/sun/star/accessibility/TextSegment.hpp>
-
-#include <string.h>
-
-using namespace ::com::sun::star;
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleEditableText>
- getEditableText( AtkEditableText *pEditableText )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pEditableText );
- if( pWrap )
- {
- if( !pWrap->mpEditableText.is() )
- {
- pWrap->mpEditableText.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpEditableText;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleEditableText>();
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-static gboolean
-editable_text_wrapper_set_run_attributes( AtkEditableText *text,
- AtkAttributeSet *attribute_set,
- gint nStartOffset,
- gint nEndOffset)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- {
- uno::Sequence< beans::PropertyValue > aAttributeList;
-
- if( attribute_set_map_to_property_values( attribute_set, aAttributeList ) )
- return pEditableText->setAttributes(nStartOffset, nEndOffset, aAttributeList);
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in setAttributes()" );
- }
-
- return FALSE;
-}
-
-static void
-editable_text_wrapper_set_text_contents( AtkEditableText *text,
- const gchar *string )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- {
- OUString aString ( string, strlen(string), RTL_TEXTENCODING_UTF8 );
- pEditableText->setText( aString );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in setText()" );
- }
-}
-
-static void
-editable_text_wrapper_insert_text( AtkEditableText *text,
- const gchar *string,
- gint length,
- gint *pos )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- {
- OUString aString ( string, length, RTL_TEXTENCODING_UTF8 );
- if( pEditableText->insertText( aString, *pos ) )
- *pos += length;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in insertText()" );
- }
-}
-
-static void
-editable_text_wrapper_cut_text( AtkEditableText *text,
- gint start,
- gint end )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- pEditableText->cutText( start, end );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in cutText()" );
- }
-}
-
-static void
-editable_text_wrapper_delete_text( AtkEditableText *text,
- gint start,
- gint end )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- pEditableText->deleteText( start, end );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in deleteText()" );
- }
-}
-
-static void
-editable_text_wrapper_paste_text( AtkEditableText *text,
- gint pos )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- pEditableText->pasteText( pos );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in pasteText()" );
- }
-}
-
-static void
-editable_text_wrapper_copy_text( AtkEditableText *text,
- gint start,
- gint end )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleEditableText>
- pEditableText = getEditableText( text );
- if( pEditableText.is() )
- pEditableText->copyText( start, end );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in copyText()" );
- }
-}
-
-} // extern "C"
-
-void
-editableTextIfaceInit (AtkEditableTextIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->set_text_contents = editable_text_wrapper_set_text_contents;
- iface->insert_text = editable_text_wrapper_insert_text;
- iface->copy_text = editable_text_wrapper_copy_text;
- iface->cut_text = editable_text_wrapper_cut_text;
- iface->delete_text = editable_text_wrapper_delete_text;
- iface->paste_text = editable_text_wrapper_paste_text;
- iface->set_run_attributes = editable_text_wrapper_set_run_attributes;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkfactory.cxx b/vcl/unx/gtk/a11y/atkfactory.cxx
deleted file mode 100644
index 3a776b20dcc7..000000000000
--- a/vcl/unx/gtk/a11y/atkfactory.cxx
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -*- 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 .
- */
-
-#include <unx/gtk/gtkframe.hxx>
-#include <vcl/window.hxx>
-#include "atkwrapper.hxx"
-#include "atkfactory.hxx"
-#include "atkregistry.hxx"
-
-using namespace ::com::sun::star;
-
-extern "C" {
-
-/*
- * Instances of this dummy object class are returned whenever we have to
- * create an AtkObject, but can't touch the OOo object anymore since it
- * is already disposed.
- */
-
-static AtkStateSet *
-noop_wrapper_ref_state_set( AtkObject * )
-{
- AtkStateSet *state_set = atk_state_set_new();
- atk_state_set_add_state( state_set, ATK_STATE_DEFUNCT );
- return state_set;
-}
-
-static void
-atk_noop_object_wrapper_class_init(AtkNoOpObjectClass *klass)
-{
- AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
- atk_class->ref_state_set = noop_wrapper_ref_state_set;
-}
-
-static GType
-atk_noop_object_wrapper_get_type()
-{
- static GType type = 0;
-
- if (!type)
- {
- static const GTypeInfo typeInfo =
- {
- sizeof (AtkNoOpObjectClass),
- nullptr,
- nullptr,
- reinterpret_cast<GClassInitFunc>(atk_noop_object_wrapper_class_init),
- nullptr,
- nullptr,
- sizeof (AtkObjectWrapper),
- 0,
- nullptr,
- nullptr
- } ;
-
- type = g_type_register_static (ATK_TYPE_OBJECT, "OOoAtkNoOpObj", &typeInfo, GTypeFlags(0)) ;
- }
- return type;
-}
-
-static AtkObject*
-atk_noop_object_wrapper_new()
-{
- AtkObject *accessible;
-
- accessible = static_cast<AtkObject *>(g_object_new (atk_noop_object_wrapper_get_type(), nullptr));
- g_return_val_if_fail (accessible != nullptr, nullptr);
-
- accessible->role = ATK_ROLE_INVALID;
- accessible->layer = ATK_LAYER_INVALID;
-
- return accessible;
-}
-
-/*
- * The wrapper factory
- */
-
-static GType
-wrapper_factory_get_accessible_type()
-{
- return atk_object_wrapper_get_type();
-}
-
-static AtkObject*
-wrapper_factory_create_accessible( GObject *obj )
-{
-#if GTK_CHECK_VERSION(3,0,0)
- GtkWidget* pEventBox = gtk_widget_get_parent(GTK_WIDGET(obj));
-
- // gail_container_real_remove_gtk tries to re-instantiate an accessible
- // for a widget that is about to vanish ..
- if (!pEventBox)
- return atk_noop_object_wrapper_new();
-
- GtkWidget* pTopLevelGrid = gtk_widget_get_parent(pEventBox);
- if (!pTopLevelGrid)
- return atk_noop_object_wrapper_new();
-
- GtkWidget* pTopLevel = gtk_widget_get_parent(pTopLevelGrid);
- if (!pTopLevel)
- return atk_noop_object_wrapper_new();
-#else
- GtkWidget* pTopLevel = gtk_widget_get_parent(GTK_WIDGET(obj));
-
- // gail_container_real_remove_gtk tries to re-instantiate an accessible
- // for a widget that is about to vanish ..
- if (!pTopLevel)
- return atk_noop_object_wrapper_new();
-#endif
-
- GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(GTK_WINDOW(pTopLevel));
- g_return_val_if_fail( pFrame != nullptr, nullptr );
-
- vcl::Window* pFrameWindow = pFrame->GetWindow();
- if( pFrameWindow )
- {
- vcl::Window* pWindow = pFrameWindow;
-
- // skip accessible objects already exposed by the frame objects
- if( WindowType::BORDERWINDOW == pWindow->GetType() )
- pWindow = pFrameWindow->GetAccessibleChildWindow(0);
-
- if( pWindow )
- {
- uno::Reference< accessibility::XAccessible > xAccessible = pWindow->GetAccessible();
- if( xAccessible.is() )
- {
- AtkObject *accessible = ooo_wrapper_registry_get( xAccessible );
-
- if( accessible )
- g_object_ref( G_OBJECT(accessible) );
- else
- accessible = atk_object_wrapper_new( xAccessible, gtk_widget_get_accessible(pTopLevel) );
-
- return accessible;
- }
- }
- }
-
- return nullptr;
-}
-
-AtkObject* ooo_fixed_get_accessible(GtkWidget *obj)
-{
- return wrapper_factory_create_accessible(G_OBJECT(obj));
-}
-
-static void
-wrapper_factory_class_init( AtkObjectFactoryClass *klass )
-{
- klass->create_accessible = wrapper_factory_create_accessible;
- klass->get_accessible_type = wrapper_factory_get_accessible_type;
-}
-
-GType
-wrapper_factory_get_type()
-{
- static GType t = 0;
-
- if (!t) {
- static const GTypeInfo tinfo =
- {
- sizeof (AtkObjectFactoryClass),
- nullptr, nullptr, reinterpret_cast<GClassInitFunc>(wrapper_factory_class_init),
- nullptr, nullptr, sizeof (AtkObjectFactory), 0, nullptr, nullptr
- };
-
- t = g_type_register_static (
- ATK_TYPE_OBJECT_FACTORY, "OOoAtkObjectWrapperFactory",
- &tinfo, GTypeFlags(0));
- }
-
- return t;
-}
-
-} // extern C
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkhypertext.cxx b/vcl/unx/gtk/a11y/atkhypertext.cxx
deleted file mode 100644
index ab94126dfc51..000000000000
--- a/vcl/unx/gtk/a11y/atkhypertext.cxx
+++ /dev/null
@@ -1,273 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
-
-using namespace ::com::sun::star;
-
-// ---------------------- AtkHyperlink ----------------------
-
-struct HyperLink {
- AtkHyperlink const atk_hyper_link;
-
- uno::Reference< accessibility::XAccessibleHyperlink > xLink;
-};
-
-static uno::Reference< accessibility::XAccessibleHyperlink > const &
- getHyperlink( AtkHyperlink *pHyperlink )
-{
- HyperLink *pLink = reinterpret_cast<HyperLink *>(pHyperlink);
- return pLink->xLink;
-}
-
-static GObjectClass *hyper_parent_class = nullptr;
-
-extern "C" {
-
-static void
-hyper_link_finalize (GObject *obj)
-{
- HyperLink *hl = reinterpret_cast<HyperLink *>(obj);
- hl->xLink.clear();
- hyper_parent_class->finalize (obj);
-}
-
-static gchar *
-hyper_link_get_uri( AtkHyperlink *pLink,
- gint i )
-{
- try {
- uno::Any aAny = getHyperlink( pLink )->getAccessibleActionObject( i );
- OUString aUri = aAny.get< OUString > ();
- return OUStringToGChar(aUri);
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in hyper_link_get_uri" );
- }
- return nullptr;
-}
-
-static AtkObject *
-hyper_link_get_object( AtkHyperlink *,
- gint )
-{
- g_warning( "FIXME: hyper_link_get_object unimplemented" );
- return nullptr;
-}
-static gint
-hyper_link_get_end_index( AtkHyperlink *pLink )
-{
- try {
- return getHyperlink( pLink )->getEndIndex();
- }
- catch(const uno::Exception&) {
- }
- return -1;
-}
-static gint
-hyper_link_get_start_index( AtkHyperlink *pLink )
-{
- try {
- return getHyperlink( pLink )->getStartIndex();
- }
- catch(const uno::Exception&) {
- }
- return -1;
-}
-static gboolean
-hyper_link_is_valid( AtkHyperlink *pLink )
-{
- try {
- return getHyperlink( pLink )->isValid();
- }
- catch(const uno::Exception&) {
- }
- return FALSE;
-}
-static gint
-hyper_link_get_n_anchors( AtkHyperlink *pLink )
-{
- try {
- return getHyperlink( pLink )->getAccessibleActionCount();
- }
- catch(const uno::Exception&) {
- }
- return 0;
-}
-
-static guint
-hyper_link_link_state( AtkHyperlink * )
-{
- g_warning( "FIXME: hyper_link_link_state unimplemented" );
- return 0;
-}
-static gboolean
-hyper_link_is_selected_link( AtkHyperlink * )
-{
- g_warning( "FIXME: hyper_link_is_selected_link unimplemented" );
- return FALSE;
-}
-
-static void
-hyper_link_class_init (AtkHyperlinkClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->finalize = hyper_link_finalize;
-
- hyper_parent_class = static_cast<GObjectClass *>(g_type_class_peek_parent (klass));
-
- klass->get_uri = hyper_link_get_uri;
- klass->get_object = hyper_link_get_object;
- klass->get_end_index = hyper_link_get_end_index;
- klass->get_start_index = hyper_link_get_start_index;
- klass->is_valid = hyper_link_is_valid;
- klass->get_n_anchors = hyper_link_get_n_anchors;
- klass->link_state = hyper_link_link_state;
- klass->is_selected_link = hyper_link_is_selected_link;
-}
-
-static GType
-hyper_link_get_type()
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo tinfo = {
- sizeof (AtkHyperlinkClass),
- nullptr, /* base init */
- nullptr, /* base finalize */
- reinterpret_cast<GClassInitFunc>(hyper_link_class_init),
- nullptr, /* class finalize */
- nullptr, /* class data */
- sizeof (HyperLink), /* instance size */
- 0, /* nb preallocs */
- nullptr, /* instance init */
- nullptr /* value table */
- };
-
- static const GInterfaceInfo atk_action_info = {
- reinterpret_cast<GInterfaceInitFunc>(actionIfaceInit),
- nullptr,
- nullptr
- };
-
- type = g_type_register_static (ATK_TYPE_HYPERLINK,
- "OOoAtkObjHyperLink", &tinfo,
- GTypeFlags(0));
- g_type_add_interface_static (type, ATK_TYPE_ACTION,
- &atk_action_info);
- }
-
- return type;
-}
-
-// ---------------------- AtkHyperText ----------------------
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleHypertext>
- getHypertext( AtkHypertext *pHypertext )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pHypertext );
- if( pWrap )
- {
- if( !pWrap->mpHypertext.is() )
- {
- pWrap->mpHypertext.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpHypertext;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleHypertext>();
-}
-
-static AtkHyperlink *
-hypertext_get_link( AtkHypertext *hypertext,
- gint link_index)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleHypertext> pHypertext
- = getHypertext( hypertext );
- if( pHypertext.is() )
- {
- HyperLink *pLink = static_cast<HyperLink *>(g_object_new( hyper_link_get_type(), nullptr ));
- pLink->xLink = pHypertext->getHyperLink( link_index );
- if( !pLink->xLink.is() ) {
- g_object_unref( G_OBJECT( pLink ) );
- pLink = nullptr;
- }
- return ATK_HYPERLINK( pLink );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getHyperLink()" );
- }
-
- return nullptr;
-}
-
-static gint
-hypertext_get_n_links( AtkHypertext *hypertext )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleHypertext> pHypertext
- = getHypertext( hypertext );
- if( pHypertext.is() )
- return pHypertext->getHyperLinkCount();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getHyperLinkCount()" );
- }
-
- return 0;
-}
-
-static gint
-hypertext_get_link_index( AtkHypertext *hypertext,
- gint index)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleHypertext> pHypertext
- = getHypertext( hypertext );
- if( pHypertext.is() )
- return pHypertext->getHyperLinkIndex( index );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getHyperLinkIndex()" );
- }
-
- return 0;
-}
-
-} // extern "C"
-
-void
-hypertextIfaceInit (AtkHypertextIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->get_link = hypertext_get_link;
- iface->get_n_links = hypertext_get_n_links;
- iface->get_link_index = hypertext_get_link_index;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkimage.cxx b/vcl/unx/gtk/a11y/atkimage.cxx
deleted file mode 100644
index acd43f467690..000000000000
--- a/vcl/unx/gtk/a11y/atkimage.cxx
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleImage.hpp>
-
-using namespace ::com::sun::star;
-
-// FIXME
-static const gchar *
-getAsConst( const OUString& rString )
-{
- static const int nMax = 10;
- static OString aUgly[nMax];
- static int nIdx = 0;
- nIdx = (nIdx + 1) % nMax;
- aUgly[nIdx] = OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
- return aUgly[ nIdx ].getStr();
-}
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleImage>
- getImage( AtkImage *pImage )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pImage );
- if( pWrap )
- {
- if( !pWrap->mpImage.is() )
- {
- pWrap->mpImage.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpImage;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleImage>();
-}
-
-extern "C" {
-
-static const gchar *
-image_get_image_description( AtkImage *image )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleImage> pImage
- = getImage( image );
- if( pImage.is() )
- return getAsConst( pImage->getAccessibleImageDescription() );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleImageDescription()" );
- }
-
- return nullptr;
-}
-
-static void
-image_get_image_position( AtkImage *image,
- gint *x,
- gint *y,
- AtkCoordType coord_type )
-{
- *x = *y = -1;
- if( ATK_IS_COMPONENT( image ) )
- {
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- atk_component_get_position( ATK_COMPONENT( image ), x, y, coord_type );
- SAL_WNODEPRECATED_DECLARATIONS_POP
- }
- else
- g_warning( "FIXME: no image position information" );
-}
-
-static void
-image_get_image_size( AtkImage *image,
- gint *width,
- gint *height )
-{
- *width = *height = -1;
- try {
- css::uno::Reference<css::accessibility::XAccessibleImage> pImage
- = getImage( image );
- if( pImage.is() )
- {
- *width = pImage->getAccessibleImageWidth();
- *height = pImage->getAccessibleImageHeight();
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleImageHeight() or Width" );
- }
-}
-
-static gboolean
-image_set_image_description( AtkImage *, const gchar * )
-{
- g_warning ("FIXME: no set image description");
- return FALSE;
-}
-
-} // extern "C"
-
-void
-imageIfaceInit (AtkImageIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->set_image_description = image_set_image_description;
- iface->get_image_description = image_get_image_description;
- iface->get_image_position = image_get_image_position;
- iface->get_image_size = image_get_image_size;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atklistener.cxx b/vcl/unx/gtk/a11y/atklistener.cxx
deleted file mode 100644
index c30bc638bced..000000000000
--- a/vcl/unx/gtk/a11y/atklistener.cxx
+++ /dev/null
@@ -1,739 +0,0 @@
-/* -*- 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 .
- */
-
-#ifdef AIX
-#define _LINUX_SOURCE_COMPAT
-#include <sys/timer.h>
-#undef _LINUX_SOURCE_COMPAT
-#endif
-
-#include <com/sun/star/accessibility/TextSegment.hpp>
-#include <com/sun/star/accessibility/AccessibleEventId.hpp>
-#include <com/sun/star/accessibility/AccessibleStateType.hpp>
-#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
-#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
-#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
-#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
-
-#include "atklistener.hxx"
-#include "atkwrapper.hxx"
-#include <vcl/svapp.hxx>
-
-#include <rtl/ref.hxx>
-#include <sal/log.hxx>
-
-#define DEBUG_ATK_LISTENER 0
-
-#if DEBUG_ATK_LISTENER
-#include <iostream>
-#include <sstream>
-#endif
-
-using namespace com::sun::star;
-
-AtkListener::AtkListener( AtkObjectWrapper* pWrapper ) : mpWrapper( pWrapper )
-{
- if( mpWrapper )
- {
- g_object_ref( mpWrapper );
- updateChildList( mpWrapper->mpContext );
- }
-}
-
-AtkListener::~AtkListener()
-{
- if( mpWrapper )
- g_object_unref( mpWrapper );
-}
-
-/*****************************************************************************/
-
-static AtkStateType mapState( const uno::Any &rAny )
-{
- sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
- rAny >>= nState;
- return mapAtkState( nState );
-}
-
-/*****************************************************************************/
-
-extern "C" {
- // rhbz#1001768 - down to horrific problems releasing the solar mutex
- // while destroying a Window - which occurs inside these notifications.
- static gboolean
- idle_defunc_state_change( AtkObject *atk_obj )
- {
- SolarMutexGuard aGuard;
-
- // This is an equivalent to a state change to DEFUNC(T).
- atk_object_notify_state_change( atk_obj, ATK_STATE_DEFUNCT, TRUE );
- if( atk_get_focus_object() == atk_obj )
- {
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- atk_focus_tracker_notify( nullptr );
- SAL_WNODEPRECATED_DECLARATIONS_POP
- }
- g_object_unref( G_OBJECT( atk_obj ) );
- return false;
- }
-}
-
-// XEventListener implementation
-void AtkListener::disposing( const lang::EventObject& )
-{
- if( mpWrapper )
- {
- AtkObject *atk_obj = ATK_OBJECT( mpWrapper );
-
- // Release all interface references to avoid shutdown problems with
- // global mutex
- atk_object_wrapper_dispose( mpWrapper );
-
- g_idle_add( reinterpret_cast<GSourceFunc>(idle_defunc_state_change),
- g_object_ref( G_OBJECT( atk_obj ) ) );
-
- // Release the wrapper object so that it can vanish ..
- g_object_unref( mpWrapper );
- mpWrapper = nullptr;
- }
-}
-
-/*****************************************************************************/
-
-static AtkObject *getObjFromAny( const uno::Any &rAny )
-{
- uno::Reference< accessibility::XAccessible > xAccessible;
- rAny >>= xAccessible;
- return xAccessible.is() ? atk_object_wrapper_ref( xAccessible ) : nullptr;
-}
-
-/*****************************************************************************/
-
-// Updates the child list held to provide the old IndexInParent on children_changed::remove
-void AtkListener::updateChildList(
- css::uno::Reference<css::accessibility::XAccessibleContext> const &
- pContext)
-{
- m_aChildList.clear();
-
- uno::Reference< accessibility::XAccessibleStateSet > xStateSet = pContext->getAccessibleStateSet();
- if( xStateSet.is()
- && !xStateSet->contains(accessibility::AccessibleStateType::DEFUNC)
- && !xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS) )
- {
- sal_Int32 nChildren = pContext->getAccessibleChildCount();
- m_aChildList.resize(nChildren);
- for(sal_Int32 n = 0; n < nChildren; n++)
- {
- try
- {
- m_aChildList[n] = pContext->getAccessibleChild(n);
- }
- catch (lang::IndexOutOfBoundsException const&)
- {
- sal_Int32 nChildren2 = pContext->getAccessibleChildCount();
- assert(nChildren2 <= n && "consistency?");
- m_aChildList.resize(std::min(nChildren2, n));
- break;
- }
- }
- }
-}
-
-/*****************************************************************************/
-
-void AtkListener::handleChildAdded(
- const uno::Reference< accessibility::XAccessibleContext >& rxParent,
- const uno::Reference< accessibility::XAccessible>& rxAccessible)
-{
- AtkObject * pChild = rxAccessible.is() ? atk_object_wrapper_ref( rxAccessible ) : nullptr;
-
- if( pChild )
- {
- updateChildList(rxParent);
-
- atk_object_wrapper_add_child( mpWrapper, pChild,
- atk_object_get_index_in_parent( pChild ));
-
- g_object_unref( pChild );
- }
-}
-
-/*****************************************************************************/
-
-void AtkListener::handleChildRemoved(
- const uno::Reference< accessibility::XAccessibleContext >& rxParent,
- const uno::Reference< accessibility::XAccessible>& rxChild)
-{
- sal_Int32 nIndex = -1;
-
- // Locate the child in the children list
- size_t n, nmax = m_aChildList.size();
- for( n = 0; n < nmax; ++n )
- {
- if( rxChild == m_aChildList[n] )
- {
- nIndex = n;
- break;
- }
- }
-
- // FIXME: two problems here:
- // a) we get child-removed events for objects that are no real children
- // in the accessibility hierarchy or have been removed before due to
- // some child removing batch.
- // b) spi_atk_bridge_signal_listener ignores the given parameters
- // for children_changed events and always asks the parent for the
- // 0. child, which breaks somehow on vanishing list boxes.
- // Ignoring "remove" events for objects not in the m_aChildList
- // for now.
- if( nIndex >= 0 )
- {
- uno::Reference<accessibility::XAccessibleEventBroadcaster> xBroadcaster(
- rxChild->getAccessibleContext(), uno::UNO_QUERY);
-
- if (xBroadcaster.is())
- {
- uno::Reference<accessibility::XAccessibleEventListener> xListener(this);
- xBroadcaster->removeAccessibleEventListener(xListener);
- }
-
- updateChildList(rxParent);
-
- AtkObject * pChild = atk_object_wrapper_ref( rxChild, false );
- if( pChild )
- {
- atk_object_wrapper_remove_child( mpWrapper, pChild, nIndex );
- g_object_unref( pChild );
- }
- }
-}
-
-/*****************************************************************************/
-
-void AtkListener::handleInvalidateChildren(
- const uno::Reference< accessibility::XAccessibleContext >& rxParent)
-{
- // Send notifications for all previous children
- size_t n = m_aChildList.size();
- while( n-- > 0 )
- {
- if( m_aChildList[n].is() )
- {
- AtkObject * pChild = atk_object_wrapper_ref( m_aChildList[n], false );
- if( pChild )
- {
- atk_object_wrapper_remove_child( mpWrapper, pChild, n );
- g_object_unref( pChild );
- }
- }
- }
-
- updateChildList(rxParent);
-
- // Send notifications for all new children
- size_t nmax = m_aChildList.size();
- for( n = 0; n < nmax; ++n )
- {
- if( m_aChildList[n].is() )
- {
- AtkObject * pChild = atk_object_wrapper_ref( m_aChildList[n] );
-
- if( pChild )
- {
- atk_object_wrapper_add_child( mpWrapper, pChild, n );
- g_object_unref( pChild );
- }
- }
- }
-}
-
-/*****************************************************************************/
-
-static uno::Reference< accessibility::XAccessibleContext >
-getAccessibleContextFromSource( const uno::Reference< uno::XInterface >& rxSource )
-{
- uno::Reference< accessibility::XAccessibleContext > xContext(rxSource, uno::UNO_QUERY);
- if( ! xContext.is() )
- {
- g_warning( "ERROR: Event source does not implement XAccessibleContext" );
-
- // Second try - query for XAccessible, which should give us access to
- // XAccessibleContext.
- uno::Reference< accessibility::XAccessible > xAccessible(rxSource, uno::UNO_QUERY);
- if( xAccessible.is() )
- xContext = xAccessible->getAccessibleContext();
- }
-
- return xContext;
-}
-
-#if DEBUG_ATK_LISTENER
-
-namespace {
-
-void printNotifyEvent( const accessibility::AccessibleEventObject& rEvent )
-{
- static std::vector<const char*> aLabels = {
- 0,
- "NAME_CHANGED", // 01
- "DESCRIPTION_CHANGED", // 02
- "ACTION_CHANGED", // 03
- "STATE_CHANGED", // 04
- "ACTIVE_DESCENDANT_CHANGED", // 05
- "BOUNDRECT_CHANGED", // 06
- "CHILD", // 07
- "INVALIDATE_ALL_CHILDREN", // 08
- "SELECTION_CHANGED", // 09
- "VISIBLE_DATA_CHANGED", // 10
- "VALUE_CHANGED", // 11
- "CONTENT_FLOWS_FROM_RELATION_CHANGED", // 12
- "CONTENT_FLOWS_TO_RELATION_CHANGED", // 13
- "CONTROLLED_BY_RELATION_CHANGED", // 14
- "CONTROLLER_FOR_RELATION_CHANGED", // 15
- "LABEL_FOR_RELATION_CHANGED", // 16
- "LABELED_BY_RELATION_CHANGED", // 17
- "MEMBER_OF_RELATION_CHANGED", // 18
- "SUB_WINDOW_OF_RELATION_CHANGED", // 19
- "CARET_CHANGED", // 20
- "TEXT_SELECTION_CHANGED", // 21
- "TEXT_CHANGED", // 22
- "TEXT_ATTRIBUTE_CHANGED", // 23
- "HYPERTEXT_CHANGED", // 24
- "TABLE_CAPTION_CHANGED", // 25
- "TABLE_COLUMN_DESCRIPTION_CHANGED", // 26
- "TABLE_COLUMN_HEADER_CHANGED", // 27
- "TABLE_MODEL_CHANGED", // 28
- "TABLE_ROW_DESCRIPTION_CHANGED", // 29
- "TABLE_ROW_HEADER_CHANGED", // 30
- "TABLE_SUMMARY_CHANGED", // 31
- "LISTBOX_ENTRY_EXPANDED", // 32
- "LISTBOX_ENTRY_COLLAPSED", // 33
- "ACTIVE_DESCENDANT_CHANGED_NOFOCUS", // 34
- "SELECTION_CHANGED_ADD", // 35
- "SELECTION_CHANGED_REMOVE", // 36
- "SELECTION_CHANGED_WITHIN", // 37
- "PAGE_CHANGED", // 38
- "SECTION_CHANGED", // 39
- "COLUMN_CHANGED", // 40
- "ROLE_CHANGED", // 41
- };
-
- static std::vector<const char*> aStates = {
- "INVALID", // 00
- "ACTIVE", // 01
- "ARMED", // 02
- "BUSY", // 03
- "CHECKED", // 04
- "DEFUNC", // 05
- "EDITABLE", // 06
- "ENABLED", // 07
- "EXPANDABLE", // 08
- "EXPANDED", // 09
- "FOCUSABLE", // 10
- "FOCUSED", // 11
- "HORIZONTAL", // 12
- "ICONIFIED", // 13
- "INDETERMINATE", // 14
- "MANAGES_DESCENDANTS", // 15
- "MODAL", // 16
- "MULTI_LINE", // 17
- "MULTI_SELECTABLE", // 18
- "OPAQUE", // 19
- "PRESSED", // 20
- "RESIZABLE", // 21
- "SELECTABLE", // 22
- "SELECTED", // 23
- "SENSITIVE", // 24
- "SHOWING", // 25
- "SINGLE_LINE", // 26
- "STALE", // 27
- "TRANSIENT", // 28
- "VERTICAL", // 29
- "VISIBLE", // 30
- "MOVEABLE", // 31
- "DEFAULT", // 32
- "OFFSCREEN", // 33
- "COLLAPSE", // 34
- };
-
- auto getOrUnknown = [](const std::vector<const char*>& rCont, size_t nIndex) -> std::string
- {
- return (nIndex < rCont.size()) ? rCont[nIndex] : "<unknown>";
- };
-
- std::ostringstream os;
- os << "--" << std::endl;
- os << "* event = " << getOrUnknown(aLabels, rEvent.EventId) << std::endl;
-
- switch (rEvent.EventId)
- {
- case accessibility::AccessibleEventId::STATE_CHANGED:
- {
- sal_Int16 nState;
- if (rEvent.OldValue >>= nState)
- os << " * old state = " << getOrUnknown(aStates, nState);
- if (rEvent.NewValue >>= nState)
- os << " * new state = " << getOrUnknown(aStates, nState);
-
- os << std::endl;
- break;
- }
- default:
- ;
- }
-
- std::cout << os.str();
-}
-
-}
-
-#endif
-
-void AtkListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
-{
- if( !mpWrapper )
- return;
-
- AtkObject *atk_obj = ATK_OBJECT( mpWrapper );
-
- switch( aEvent.EventId )
- {
- // AtkObject signals:
- // Hierarchy signals
- case accessibility::AccessibleEventId::CHILD:
- {
- uno::Reference< accessibility::XAccessibleContext > xParent;
- uno::Reference< accessibility::XAccessible > xChild;
-
- xParent = getAccessibleContextFromSource(aEvent.Source);
- g_return_if_fail( xParent.is() );
-
- if( aEvent.OldValue >>= xChild )
- handleChildRemoved(xParent, xChild);
-
- if( aEvent.NewValue >>= xChild )
- handleChildAdded(xParent, xChild);
- break;
- }
-
- case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
- {
- uno::Reference< accessibility::XAccessibleContext > xParent = getAccessibleContextFromSource(aEvent.Source);
- g_return_if_fail( xParent.is() );
-
- handleInvalidateChildren(xParent);
- break;
- }
-
- case accessibility::AccessibleEventId::NAME_CHANGED:
- {
- OUString aName;
- if( aEvent.NewValue >>= aName )
- {
- atk_object_set_name(atk_obj,
- OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
- }
- break;
- }
-
- case accessibility::AccessibleEventId::DESCRIPTION_CHANGED:
- {
- OUString aDescription;
- if( aEvent.NewValue >>= aDescription )
- {
- atk_object_set_description(atk_obj,
- OUStringToOString(aDescription, RTL_TEXTENCODING_UTF8).getStr());
- }
- break;
- }
-
- case accessibility::AccessibleEventId::STATE_CHANGED:
- {
- AtkStateType eOldState = mapState( aEvent.OldValue );
- AtkStateType eNewState = mapState( aEvent.NewValue );
-
- gboolean bState = eNewState != ATK_STATE_INVALID;
- AtkStateType eRealState = bState ? eNewState : eOldState;
-
- atk_object_notify_state_change( atk_obj, eRealState, bState );
- break;
- }
-
- case accessibility::AccessibleEventId::BOUNDRECT_CHANGED:
-
-#ifdef HAS_ATKRECTANGLE
- if( ATK_IS_COMPONENT( atk_obj ) )
- {
- AtkRectangle rect;
-
- atk_component_get_extents( ATK_COMPONENT( atk_obj ),
- &rect.x,
- &rect.y,
- &rect.width,
- &rect.height,
- ATK_XY_SCREEN );
-
- g_signal_emit_by_name( atk_obj, "bounds_changed", &rect );
- }
- else
- g_warning( "bounds_changed event for object not implementing AtkComponent\n");
-#endif
-
- break;
-
- case accessibility::AccessibleEventId::VISIBLE_DATA_CHANGED:
- g_signal_emit_by_name( atk_obj, "visible-data-changed" );
- break;
-
- case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
- {
- AtkObject *pChild = getObjFromAny( aEvent.NewValue );
- if( pChild )
- {
- g_signal_emit_by_name( atk_obj, "active-descendant-changed", pChild );
- g_object_unref( pChild );
- }
- break;
- }
-
- //ACTIVE_DESCENDANT_CHANGED_NOFOCUS (sic) appears to have been added
- //as a workaround or an aid for the ia2 winaccessibility implementation
- //so ignore it silently without warning here
- case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS:
- break;
-
- // #i92103#
- case accessibility::AccessibleEventId::LISTBOX_ENTRY_EXPANDED:
- {
- AtkObject *pChild = getObjFromAny( aEvent.NewValue );
- if( pChild )
- {
- atk_object_notify_state_change( pChild, ATK_STATE_EXPANDED, true );
- g_object_unref( pChild );
- }
- break;
- }
-
- case accessibility::AccessibleEventId::LISTBOX_ENTRY_COLLAPSED:
- {
- AtkObject *pChild = getObjFromAny( aEvent.NewValue );
- if( pChild )
- {
- atk_object_notify_state_change( pChild, ATK_STATE_EXPANDED, false );
- g_object_unref( pChild );
- }
- break;
- }
-
- // AtkAction signals ...
- case accessibility::AccessibleEventId::ACTION_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-actions");
- break;
-
- // AtkText
- case accessibility::AccessibleEventId::CARET_CHANGED:
- {
- sal_Int32 nPos=0;
- aEvent.NewValue >>= nPos;
- g_signal_emit_by_name( atk_obj, "text_caret_moved", nPos );
- break;
- }
- case accessibility::AccessibleEventId::TEXT_CHANGED:
- {
- // TESTME: and remove this comment:
- // cf. comphelper/source/misc/accessibletexthelper.cxx (implInitTextChangedEvent)
- accessibility::TextSegment aDeletedText;
- accessibility::TextSegment aInsertedText;
-
- // TODO: when GNOME starts to send "update" kind of events, change
- // we need to re-think this implementation as well
- if( aEvent.OldValue >>= aDeletedText )
- {
- /* Remember the text segment here to be able to return removed text in get_text().
- * This is clearly a hack to be used until appropriate API exists in atk to pass
- * the string value directly or we find a compelling reason to start caching the
- * UTF-8 converted strings in the atk wrapper object.
- */
-
- g_object_set_data( G_OBJECT(atk_obj), "ooo::text_changed::delete", &aDeletedText);
-
- g_signal_emit_by_name( atk_obj, "text_changed::delete",
- static_cast<gint>(aDeletedText.SegmentStart),
- static_cast<gint>( aDeletedText.SegmentEnd - aDeletedText.SegmentStart ) );
-
- g_object_steal_data( G_OBJECT(atk_obj), "ooo::text_changed::delete" );
- }
-
- if( aEvent.NewValue >>= aInsertedText )
- g_signal_emit_by_name( atk_obj, "text_changed::insert",
- static_cast<gint>(aInsertedText.SegmentStart),
- static_cast<gint>( aInsertedText.SegmentEnd - aInsertedText.SegmentStart ) );
- break;
- }
-
- case accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED:
- {
- g_signal_emit_by_name( atk_obj, "text-selection-changed" );
- break;
- }
-
- case accessibility::AccessibleEventId::TEXT_ATTRIBUTE_CHANGED:
- g_signal_emit_by_name( atk_obj, "text-attributes-changed" );
- break;
-
- // AtkValue
- case accessibility::AccessibleEventId::VALUE_CHANGED:
- g_object_notify( G_OBJECT( atk_obj ), "accessible-value" );
- break;
-
- case accessibility::AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
- case accessibility::AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
- case accessibility::AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
- case accessibility::AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
- case accessibility::AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
- case accessibility::AccessibleEventId::LABELED_BY_RELATION_CHANGED:
- case accessibility::AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
- case accessibility::AccessibleEventId::SUB_WINDOW_OF_RELATION_CHANGED:
- // FIXME: ask Bill how Atk copes with this little lot ...
- break;
-
- // AtkTable
- case accessibility::AccessibleEventId::TABLE_MODEL_CHANGED:
- {
- accessibility::AccessibleTableModelChange aChange;
- aEvent.NewValue >>= aChange;
-
- sal_Int32 nRowsChanged = aChange.LastRow - aChange.FirstRow + 1;
- sal_Int32 nColumnsChanged = aChange.LastColumn - aChange.FirstColumn + 1;
-
- static const struct {
- const char *row;
- const char *col;
- } aSignalNames[] =
- {
- { nullptr, nullptr }, // dummy
- { "row_inserted", "column_inserted" }, // INSERT = 1
- { "row_deleted", "column_deleted" } // DELETE = 2
- };
- switch( aChange.Type )
- {
- case accessibility::AccessibleTableModelChangeType::INSERT:
- case accessibility::AccessibleTableModelChangeType::DELETE:
- if( nRowsChanged > 0 )
- g_signal_emit_by_name( G_OBJECT( atk_obj ),
- aSignalNames[aChange.Type].row,
- aChange.FirstRow, nRowsChanged );
- if( nColumnsChanged > 0 )
- g_signal_emit_by_name( G_OBJECT( atk_obj ),
- aSignalNames[aChange.Type].col,
- aChange.FirstColumn, nColumnsChanged );
- break;
-
- case accessibility::AccessibleTableModelChangeType::UPDATE:
- // This is not really a model change, is it ?
- break;
- default:
- g_warning( "TESTME: unusual table model change %d\n", aChange.Type );
- break;
- }
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "model-changed" );
- break;
- }
-
- case accessibility::AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
- {
- accessibility::AccessibleTableModelChange aChange;
- aEvent.NewValue >>= aChange;
-
- AtkPropertyValues values;
- memset(&values, 0, sizeof(AtkPropertyValues));
- g_value_init (&values.new_value, G_TYPE_INT);
- values.property_name = "accessible-table-column-header";
-
- for (sal_Int32 nChangedColumn = aChange.FirstColumn; nChangedColumn <= aChange.LastColumn; ++nChangedColumn)
- {
- g_value_set_int (&values.new_value, nChangedColumn);
- g_signal_emit_by_name(G_OBJECT(atk_obj), "property_change::accessible-table-column-header", &values, nullptr);
- }
- break;
- }
-
- case accessibility::AccessibleEventId::TABLE_CAPTION_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-caption");
- break;
-
- case accessibility::AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-column-description");
- break;
-
- case accessibility::AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-row-description");
- break;
-
- case accessibility::AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-row-header");
- break;
-
- case accessibility::AccessibleEventId::TABLE_SUMMARY_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-summary");
- break;
-
- case accessibility::AccessibleEventId::SELECTION_CHANGED:
- case accessibility::AccessibleEventId::SELECTION_CHANGED_ADD:
- case accessibility::AccessibleEventId::SELECTION_CHANGED_REMOVE:
- case accessibility::AccessibleEventId::SELECTION_CHANGED_WITHIN:
- if (ATK_IS_SELECTION(atk_obj))
- g_signal_emit_by_name(G_OBJECT(atk_obj), "selection_changed");
- else
- {
- // e.g. tdf#122353, when such dialogs become native the problem will go away anyway
- SAL_INFO("vcl.gtk", "selection change from obj which doesn't support XAccessibleSelection");
- }
- break;
-
- case accessibility::AccessibleEventId::HYPERTEXT_CHANGED:
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-hypertext-offset");
- break;
-
- case accessibility::AccessibleEventId::ROLE_CHANGED:
- {
- uno::Reference< accessibility::XAccessibleContext > xContext = getAccessibleContextFromSource( aEvent.Source );
- atk_object_wrapper_set_role( mpWrapper, xContext->getAccessibleRole() );
- break;
- }
-
- case accessibility::AccessibleEventId::PAGE_CHANGED:
- {
- /* // If we implemented AtkDocument then I imagine this is what this
- // handler should look like
- sal_Int32 nPos=0;
- aEvent.NewValue >>= nPos;
- g_signal_emit_by_name( G_OBJECT( atk_obj ), "page_changed", nPos );
- */
- break;
- }
-
- default:
- SAL_WARN("vcl.gtk", "Unknown event notification: " << aEvent.EventId);
- break;
- }
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkregistry.cxx b/vcl/unx/gtk/a11y/atkregistry.cxx
deleted file mode 100644
index ff96378c41dc..000000000000
--- a/vcl/unx/gtk/a11y/atkregistry.cxx
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkregistry.hxx"
-
-using namespace ::com::sun::star::accessibility;
-using namespace ::com::sun::star::uno;
-
-static GHashTable *uno_to_gobject = nullptr;
-
-/*****************************************************************************/
-
-AtkObject *
-ooo_wrapper_registry_get(const Reference< XAccessible >& rxAccessible)
-{
- if( uno_to_gobject )
- {
- gpointer cached =
- g_hash_table_lookup(uno_to_gobject, static_cast<gpointer>(rxAccessible.get()));
-
- if( cached )
- return ATK_OBJECT( cached );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-void
-ooo_wrapper_registry_add(const Reference< XAccessible >& rxAccessible, AtkObject *obj)
-{
- if( !uno_to_gobject )
- uno_to_gobject = g_hash_table_new (nullptr, nullptr);
-
- g_hash_table_insert( uno_to_gobject, static_cast<gpointer>(rxAccessible.get()), obj );
-}
-
-/*****************************************************************************/
-
-void
-ooo_wrapper_registry_remove(
- css::uno::Reference<css::accessibility::XAccessible> const & pAccessible)
-{
- if( uno_to_gobject )
- g_hash_table_remove(
- uno_to_gobject, static_cast<gpointer>(pAccessible.get()) );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkselection.cxx b/vcl/unx/gtk/a11y/atkselection.cxx
deleted file mode 100644
index 1d9772bc1587..000000000000
--- a/vcl/unx/gtk/a11y/atkselection.cxx
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
-
-using namespace ::com::sun::star;
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleSelection>
- getSelection( AtkSelection *pSelection )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pSelection );
- if( pWrap )
- {
- if( !pWrap->mpSelection.is() )
- {
- pWrap->mpSelection.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpSelection;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleSelection>();
-}
-
-extern "C" {
-
-static gboolean
-selection_add_selection( AtkSelection *selection,
- gint i )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- {
- pSelection->selectAccessibleChild( i );
- return TRUE;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in selectAccessibleChild()" );
- }
-
- return FALSE;
-}
-
-static gboolean
-selection_clear_selection( AtkSelection *selection )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- {
- pSelection->clearAccessibleSelection();
- return TRUE;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in selectAccessibleChild()" );
- }
-
- return FALSE;
-}
-
-static AtkObject*
-selection_ref_selection( AtkSelection *selection,
- gint i )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- return atk_object_wrapper_ref( pSelection->getSelectedAccessibleChild( i ) );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleChild()" );
- }
-
- return nullptr;
-}
-
-static gint
-selection_get_selection_count( AtkSelection *selection)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- return pSelection->getSelectedAccessibleChildCount();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleChildCount()" );
- }
-
- return -1;
-}
-
-static gboolean
-selection_is_child_selected( AtkSelection *selection,
- gint i)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- return pSelection->isAccessibleChildSelected( i );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleChildCount()" );
- }
-
- return FALSE;
-}
-
-static gboolean
-selection_remove_selection( AtkSelection *selection,
- gint i )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- {
- pSelection->deselectAccessibleChild( i );
- return TRUE;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleChildCount()" );
- }
-
- return FALSE;
-}
-
-static gboolean
-selection_select_all_selection( AtkSelection *selection)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
- = getSelection( selection );
- if( pSelection.is() )
- {
- pSelection->selectAllAccessibleChildren();
- return TRUE;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleChildCount()" );
- }
-
- return FALSE;
-}
-
-} // extern "C"
-
-void
-selectionIfaceInit( AtkSelectionIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->add_selection = selection_add_selection;
- iface->clear_selection = selection_clear_selection;
- iface->ref_selection = selection_ref_selection;
- iface->get_selection_count = selection_get_selection_count;
- iface->is_child_selected = selection_is_child_selected;
- iface->remove_selection = selection_remove_selection;
- iface->select_all_selection = selection_select_all_selection;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atktable.cxx b/vcl/unx/gtk/a11y/atktable.cxx
deleted file mode 100644
index 221e55d2b287..000000000000
--- a/vcl/unx/gtk/a11y/atktable.cxx
+++ /dev/null
@@ -1,580 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleTable.hpp>
-#include <comphelper/sequence.hxx>
-
-using namespace ::com::sun::star;
-
-static AtkObject *
-atk_object_wrapper_conditional_ref( const uno::Reference< accessibility::XAccessible >& rxAccessible )
-{
- if( rxAccessible.is() )
- return atk_object_wrapper_ref( rxAccessible );
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-// FIXME
-static const gchar *
-getAsConst( const OUString& rString )
-{
- static const int nMax = 10;
- static OString aUgly[nMax];
- static int nIdx = 0;
- nIdx = (nIdx + 1) % nMax;
- aUgly[nIdx] = OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
- return aUgly[ nIdx ].getStr();
-}
-
-/*****************************************************************************/
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleTable>
- getTable( AtkTable *pTable )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pTable );
- if( pWrap )
- {
- if( !pWrap->mpTable.is() )
- {
- pWrap->mpTable.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpTable;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleTable>();
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-static AtkObject*
-table_wrapper_ref_at (AtkTable *table,
- gint row,
- gint column)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable = getTable( table );
- if( pTable.is() )
- return atk_object_wrapper_conditional_ref( pTable->getAccessibleCellAt( row, column ) );
- }
-
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleCellAt()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_index_at (AtkTable *table,
- gint row,
- gint column)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleIndex( row, column );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleIndex()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_column_at_index (AtkTable *table,
- gint nIndex)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleColumn( nIndex );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleColumn()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_row_at_index( AtkTable *table,
- gint nIndex )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleRow( nIndex );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleRow()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_n_columns( AtkTable *table )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleColumnCount();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleColumnCount()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_n_rows( AtkTable *table )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleRowCount();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleRowCount()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_column_extent_at( AtkTable *table,
- gint row,
- gint column )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleColumnExtentAt( row, column );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleColumnExtentAt()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_row_extent_at( AtkTable *table,
- gint row,
- gint column )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->getAccessibleRowExtentAt( row, column );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleRowExtentAt()" );
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-static AtkObject *
-table_wrapper_get_caption( AtkTable *table )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return atk_object_wrapper_conditional_ref( pTable->getAccessibleCaption() );
- }
-
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleCaption()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static const gchar *
-table_wrapper_get_row_description( AtkTable *table,
- gint row )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return getAsConst( pTable->getAccessibleRowDescription( row ) );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleRowDescription()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static const gchar *
-table_wrapper_get_column_description( AtkTable *table,
- gint column )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return getAsConst( pTable->getAccessibleColumnDescription( column ) );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleColumnDescription()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static AtkObject *
-table_wrapper_get_row_header( AtkTable *table,
- gint row )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- {
- uno::Reference< accessibility::XAccessibleTable > xRowHeaders( pTable->getAccessibleRowHeaders() );
- if( xRowHeaders.is() )
- return atk_object_wrapper_conditional_ref( xRowHeaders->getAccessibleCellAt( row, 0 ) );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleRowHeaders()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static AtkObject *
-table_wrapper_get_column_header( AtkTable *table,
- gint column )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- {
- uno::Reference< accessibility::XAccessibleTable > xColumnHeaders( pTable->getAccessibleColumnHeaders() );
- if( xColumnHeaders.is() )
- return atk_object_wrapper_conditional_ref( xColumnHeaders->getAccessibleCellAt( 0, column ) );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleColumnHeaders()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static AtkObject *
-table_wrapper_get_summary( AtkTable *table )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- {
- return atk_object_wrapper_conditional_ref( pTable->getAccessibleSummary() );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleSummary()" );
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-static gint
-convertToGIntArray( const uno::Sequence< ::sal_Int32 >& aSequence, gint **pSelected )
-{
- if( aSequence.hasElements() )
- {
- *pSelected = g_new( gint, aSequence.getLength() );
-
- *pSelected = comphelper::sequenceToArray(*pSelected, aSequence);
- }
-
- return aSequence.getLength();
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_selected_columns( AtkTable *table,
- gint **pSelected )
-{
- *pSelected = nullptr;
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return convertToGIntArray( pTable->getSelectedAccessibleColumns(), pSelected );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleColumns()" );
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-static gint
-table_wrapper_get_selected_rows( AtkTable *table,
- gint **pSelected )
-{
- *pSelected = nullptr;
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return convertToGIntArray( pTable->getSelectedAccessibleRows(), pSelected );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectedAccessibleRows()" );
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_is_column_selected( AtkTable *table,
- gint column )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->isAccessibleColumnSelected( column );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in isAccessibleColumnSelected()" );
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_is_row_selected( AtkTable *table,
- gint row )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->isAccessibleRowSelected( row );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in isAccessibleRowSelected()" );
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_is_selected( AtkTable *table,
- gint row,
- gint column )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleTable> pTable
- = getTable( table );
- if( pTable.is() )
- return pTable->isAccessibleSelected( row, column );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in isAccessibleSelected()" );
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_add_row_selection( AtkTable *, gint )
-{
- g_warning( "FIXME: no simple analogue for add_row_selection" );
- return 0;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_remove_row_selection( AtkTable *, gint )
-{
- g_warning( "FIXME: no simple analogue for remove_row_selection" );
- return 0;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_add_column_selection( AtkTable *, gint )
-{
- g_warning( "FIXME: no simple analogue for add_column_selection" );
- return 0;
-}
-
-/*****************************************************************************/
-
-static gboolean
-table_wrapper_remove_column_selection( AtkTable *, gint )
-{
- g_warning( "FIXME: no simple analogue for remove_column_selection" );
- return 0;
-}
-
-/*****************************************************************************/
-
-static void
-table_wrapper_set_caption( AtkTable *, AtkObject * )
-{ // meaningless helper
-}
-
-/*****************************************************************************/
-
-static void
-table_wrapper_set_column_description( AtkTable *, gint, const gchar * )
-{ // meaningless helper
-}
-
-/*****************************************************************************/
-
-static void
-table_wrapper_set_column_header( AtkTable *, gint, AtkObject * )
-{ // meaningless helper
-}
-
-/*****************************************************************************/
-
-static void
-table_wrapper_set_row_description( AtkTable *, gint, const gchar * )
-{ // meaningless helper
-}
-
-/*****************************************************************************/
-
-static void
-table_wrapper_set_row_header( AtkTable *, gint, AtkObject * )
-{ // meaningless helper
-}
-
-/*****************************************************************************/
-
-static void
-table_wrapper_set_summary( AtkTable *, AtkObject * )
-{ // meaningless helper
-}
-
-/*****************************************************************************/
-
-} // extern "C"
-
-void
-tableIfaceInit (AtkTableIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->ref_at = table_wrapper_ref_at;
- iface->get_n_rows = table_wrapper_get_n_rows;
- iface->get_n_columns = table_wrapper_get_n_columns;
- iface->get_index_at = table_wrapper_get_index_at;
- iface->get_column_at_index = table_wrapper_get_column_at_index;
- iface->get_row_at_index = table_wrapper_get_row_at_index;
- iface->is_row_selected = table_wrapper_is_row_selected;
- iface->is_selected = table_wrapper_is_selected;
- iface->get_selected_rows = table_wrapper_get_selected_rows;
- iface->add_row_selection = table_wrapper_add_row_selection;
- iface->remove_row_selection = table_wrapper_remove_row_selection;
- iface->add_column_selection = table_wrapper_add_column_selection;
- iface->remove_column_selection = table_wrapper_remove_column_selection;
- iface->get_selected_columns = table_wrapper_get_selected_columns;
- iface->is_column_selected = table_wrapper_is_column_selected;
- iface->get_column_extent_at = table_wrapper_get_column_extent_at;
- iface->get_row_extent_at = table_wrapper_get_row_extent_at;
- iface->get_row_header = table_wrapper_get_row_header;
- iface->set_row_header = table_wrapper_set_row_header;
- iface->get_column_header = table_wrapper_get_column_header;
- iface->set_column_header = table_wrapper_set_column_header;
- iface->get_caption = table_wrapper_get_caption;
- iface->set_caption = table_wrapper_set_caption;
- iface->get_summary = table_wrapper_get_summary;
- iface->set_summary = table_wrapper_set_summary;
- iface->get_row_description = table_wrapper_get_row_description;
- iface->set_row_description = table_wrapper_set_row_description;
- iface->get_column_description = table_wrapper_get_column_description;
- iface->set_column_description = table_wrapper_set_column_description;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atktext.cxx b/vcl/unx/gtk/a11y/atktext.cxx
deleted file mode 100644
index 1406ceea5544..000000000000
--- a/vcl/unx/gtk/a11y/atktext.cxx
+++ /dev/null
@@ -1,838 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-#include "atktextattributes.hxx"
-#include <algorithm>
-
-#include <osl/diagnose.h>
-
-#include <com/sun/star/accessibility/AccessibleTextType.hpp>
-#include <com/sun/star/accessibility/TextSegment.hpp>
-#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
-#include <com/sun/star/accessibility/XAccessibleText.hpp>
-#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
-#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
-#include <com/sun/star/text/TextMarkupType.hpp>
-
-using namespace ::com::sun::star;
-
-static sal_Int16
-text_type_from_boundary(AtkTextBoundary boundary_type)
-{
- switch(boundary_type)
- {
- case ATK_TEXT_BOUNDARY_CHAR:
- return accessibility::AccessibleTextType::CHARACTER;
- case ATK_TEXT_BOUNDARY_WORD_START:
- case ATK_TEXT_BOUNDARY_WORD_END:
- return accessibility::AccessibleTextType::WORD;
- case ATK_TEXT_BOUNDARY_SENTENCE_START:
- case ATK_TEXT_BOUNDARY_SENTENCE_END:
- return accessibility::AccessibleTextType::SENTENCE;
- case ATK_TEXT_BOUNDARY_LINE_START:
- case ATK_TEXT_BOUNDARY_LINE_END:
- return accessibility::AccessibleTextType::LINE;
- default:
- return -1;
- }
-}
-
-/*****************************************************************************/
-
-static gchar *
-adjust_boundaries( css::uno::Reference<css::accessibility::XAccessibleText> const & pText,
- accessibility::TextSegment const & rTextSegment,
- AtkTextBoundary boundary_type,
- gint * start_offset, gint * end_offset )
-{
- accessibility::TextSegment aTextSegment;
- OUString aString;
- gint start = 0, end = 0;
-
- if( !rTextSegment.SegmentText.isEmpty() )
- {
- switch(boundary_type)
- {
- case ATK_TEXT_BOUNDARY_CHAR:
- case ATK_TEXT_BOUNDARY_LINE_START:
- case ATK_TEXT_BOUNDARY_LINE_END:
- case ATK_TEXT_BOUNDARY_SENTENCE_START:
- start = rTextSegment.SegmentStart;
- end = rTextSegment.SegmentEnd;
- aString = rTextSegment.SegmentText;
- break;
-
- // the OOo break iterator behaves as SENTENCE_START
- case ATK_TEXT_BOUNDARY_SENTENCE_END:
- start = rTextSegment.SegmentStart;
- end = rTextSegment.SegmentEnd;
-
- if( start > 0 )
- --start;
- if( end > 0 && end < pText->getCharacterCount() - 1 )
- --end;
-
- aString = pText->getTextRange(start, end);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_START:
- start = rTextSegment.SegmentStart;
-
- // Determine the start index of the next segment
- aTextSegment = pText->getTextBehindIndex(rTextSegment.SegmentEnd,
- text_type_from_boundary(boundary_type));
- if( !aTextSegment.SegmentText.isEmpty() )
- end = aTextSegment.SegmentStart;
- else
- end = pText->getCharacterCount();
-
- aString = pText->getTextRange(start, end);
- break;
-
- case ATK_TEXT_BOUNDARY_WORD_END:
- end = rTextSegment.SegmentEnd;
-
- // Determine the end index of the previous segment
- aTextSegment = pText->getTextBeforeIndex(rTextSegment.SegmentStart,
- text_type_from_boundary(boundary_type));
- if( !aTextSegment.SegmentText.isEmpty() )
- start = aTextSegment.SegmentEnd;
- else
- start = 0;
-
- aString = pText->getTextRange(start, end);
- break;
-
- default:
- return nullptr;
- }
- }
-
- *start_offset = start;
- *end_offset = end;
-
- return OUStringToGChar(aString);
-}
-
-/*****************************************************************************/
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleText>
- getText( AtkText *pText )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
- if( pWrap )
- {
- if( !pWrap->mpText.is() )
- {
- pWrap->mpText.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpText;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleText>();
-}
-
-/*****************************************************************************/
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
- getTextMarkup( AtkText *pText )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
- if( pWrap )
- {
- if( !pWrap->mpTextMarkup.is() )
- {
- pWrap->mpTextMarkup.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpTextMarkup;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleTextMarkup>();
-}
-
-/*****************************************************************************/
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
- getTextAttributes( AtkText *pText )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
- if( pWrap )
- {
- if( !pWrap->mpTextAttributes.is() )
- {
- pWrap->mpTextAttributes.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpTextAttributes;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleTextAttributes>();
-}
-
-/*****************************************************************************/
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleMultiLineText>
- getMultiLineText( AtkText *pText )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
- if( pWrap )
- {
- if( !pWrap->mpMultiLineText.is() )
- {
- pWrap->mpMultiLineText.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpMultiLineText;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleMultiLineText>();
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-static gchar *
-text_wrapper_get_text (AtkText *text,
- gint start_offset,
- gint end_offset)
-{
- gchar * ret = nullptr;
-
- g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), nullptr );
-
- /* at-spi expects the delete event to be send before the deletion happened
- * so we save the deleted string object in the UNO event notification and
- * fool libatk-bridge.so here ..
- */
- void * pData = g_object_get_data( G_OBJECT(text), "ooo::text_changed::delete" );
- if( pData != nullptr )
- {
- accessibility::TextSegment * pTextSegment =
- static_cast <accessibility::TextSegment *> (pData);
-
- if( pTextSegment->SegmentStart == start_offset &&
- pTextSegment->SegmentEnd == end_offset )
- {
- OString aUtf8 = OUStringToOString( pTextSegment->SegmentText, RTL_TEXTENCODING_UTF8 );
- return g_strdup( aUtf8.getStr() );
- }
- }
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- OUString aText;
- sal_Int32 n = pText->getCharacterCount();
-
- if( -1 == end_offset )
- aText = pText->getText();
- else if( start_offset < n )
- aText = pText->getTextRange(start_offset, end_offset);
-
- ret = g_strdup( OUStringToOString(aText, RTL_TEXTENCODING_UTF8 ).getStr() );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getText()" );
- }
-
- return ret;
-}
-
-static gchar *
-text_wrapper_get_text_after_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- accessibility::TextSegment aTextSegment = pText->getTextBehindIndex(offset, text_type_from_boundary(boundary_type));
- return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in get_text_after_offset()" );
- }
-
- return nullptr;
-}
-
-static gchar *
-text_wrapper_get_text_at_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- /* If the user presses the 'End' key, the caret will be placed behind the last character,
- * which is the same index as the first character of the next line. In atk the magic offset
- * '-2' is used to cover this special case.
- */
- if (
- -2 == offset &&
- (ATK_TEXT_BOUNDARY_LINE_START == boundary_type ||
- ATK_TEXT_BOUNDARY_LINE_END == boundary_type)
- )
- {
- css::uno::Reference<
- css::accessibility::XAccessibleMultiLineText> pMultiLineText
- = getMultiLineText( text );
- if( pMultiLineText.is() )
- {
- accessibility::TextSegment aTextSegment = pMultiLineText->getTextAtLineWithCaret();
- return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
- }
- }
-
- accessibility::TextSegment aTextSegment = pText->getTextAtIndex(offset, text_type_from_boundary(boundary_type));
- return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in get_text_at_offset()" );
- }
-
- return nullptr;
-}
-
-static gunichar
-text_wrapper_get_character_at_offset (AtkText *text,
- gint offset)
-{
- gint start, end;
- gunichar uc = 0;
-
- gchar * char_as_string =
- text_wrapper_get_text_at_offset(text, offset, ATK_TEXT_BOUNDARY_CHAR,
- &start, &end);
- if( char_as_string )
- {
- uc = g_utf8_get_char( char_as_string );
- g_free( char_as_string );
- }
-
- return uc;
-}
-
-static gchar *
-text_wrapper_get_text_before_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- accessibility::TextSegment aTextSegment = pText->getTextBeforeIndex(offset, text_type_from_boundary(boundary_type));
- return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in text_before_offset()" );
- }
-
- return nullptr;
-}
-
-static gint
-text_wrapper_get_caret_offset (AtkText *text)
-{
- gint offset = -1;
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- offset = pText->getCaretPosition();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCaretPosition()" );
- }
-
- return offset;
-}
-
-static gboolean
-text_wrapper_set_caret_offset (AtkText *text,
- gint offset)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- return pText->setCaretPosition( offset );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in setCaretPosition()" );
- }
-
- return FALSE;
-}
-
-// #i92232#
-static AtkAttributeSet*
-handle_text_markup_as_run_attribute( css::uno::Reference<css::accessibility::XAccessibleTextMarkup> const & pTextMarkup,
- const gint nTextMarkupType,
- const gint offset,
- AtkAttributeSet* pSet,
- gint *start_offset,
- gint *end_offset )
-{
- const gint nTextMarkupCount( pTextMarkup->getTextMarkupCount( nTextMarkupType ) );
- if ( nTextMarkupCount > 0 )
- {
- for ( gint nTextMarkupIndex = 0;
- nTextMarkupIndex < nTextMarkupCount;
- ++nTextMarkupIndex )
- {
- accessibility::TextSegment aTextSegment =
- pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
- const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
- const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
- if ( nStartOffsetTextMarkup <= offset )
- {
- if ( offset < nEndOffsetTextMarkup )
- {
- // text markup at <offset>
- *start_offset = ::std::max( *start_offset,
- nStartOffsetTextMarkup );
- *end_offset = ::std::min( *end_offset,
- nEndOffsetTextMarkup );
- switch ( nTextMarkupType )
- {
- case css::text::TextMarkupType::SPELLCHECK:
- {
- pSet = attribute_set_prepend_misspelled( pSet );
- }
- break;
- case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
- {
- pSet = attribute_set_prepend_tracked_change_insertion( pSet );
- }
- break;
- case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
- {
- pSet = attribute_set_prepend_tracked_change_deletion( pSet );
- }
- break;
- case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
- {
- pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
- }
- break;
- default:
- {
- OSL_ASSERT( false );
- }
- }
- break; // no further iteration needed.
- }
- else
- {
- *start_offset = ::std::max( *start_offset,
- nEndOffsetTextMarkup );
- // continue iteration.
- }
- }
- else
- {
- *end_offset = ::std::min( *end_offset,
- nStartOffsetTextMarkup );
- break; // no further iteration.
- }
- } // eof iteration over text markups
- }
-
- return pSet;
-}
-
-static AtkAttributeSet *
-text_wrapper_get_run_attributes( AtkText *text,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- AtkAttributeSet *pSet = nullptr;
-
- try {
- bool bOffsetsAreValid = false;
-
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is())
- {
- uno::Sequence< beans::PropertyValue > aAttributeList;
-
- css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
- pTextAttributes = getTextAttributes( text );
- if(pTextAttributes.is()) // Text attributes are available for paragraphs only
- {
- aAttributeList = pTextAttributes->getRunAttributes( offset, uno::Sequence< OUString > () );
- }
- else // For other text objects use character attributes
- {
- aAttributeList = pText->getCharacterAttributes( offset, uno::Sequence< OUString > () );
- }
-
- pSet = attribute_set_new_from_property_values( aAttributeList, true, text );
- // #i100938#
- // - always provide start_offset and end_offset
- {
- accessibility::TextSegment aTextSegment =
- pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
-
- *start_offset = aTextSegment.SegmentStart;
- // #i100938#
- // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
- *end_offset = aTextSegment.SegmentEnd;
- bOffsetsAreValid = true;
- }
- }
-
- // Special handling for misspelled text
- // #i92232#
- // - add special handling for tracked changes and refactor the
- // corresponding code for handling misspelled text.
- css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
- pTextMarkup = getTextMarkup( text );
- if( pTextMarkup.is() )
- {
- // Get attribute run here if it hasn't been done before
- if (!bOffsetsAreValid && pText.is())
- {
- accessibility::TextSegment aAttributeTextSegment =
- pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
- *start_offset = aAttributeTextSegment.SegmentStart;
- *end_offset = aAttributeTextSegment.SegmentEnd;
- }
- // handle misspelled text
- pSet = handle_text_markup_as_run_attribute(
- pTextMarkup,
- css::text::TextMarkupType::SPELLCHECK,
- offset, pSet, start_offset, end_offset );
- // handle tracked changes
- pSet = handle_text_markup_as_run_attribute(
- pTextMarkup,
- css::text::TextMarkupType::TRACK_CHANGE_INSERTION,
- offset, pSet, start_offset, end_offset );
- pSet = handle_text_markup_as_run_attribute(
- pTextMarkup,
- css::text::TextMarkupType::TRACK_CHANGE_DELETION,
- offset, pSet, start_offset, end_offset );
- pSet = handle_text_markup_as_run_attribute(
- pTextMarkup,
- css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
- offset, pSet, start_offset, end_offset );
- }
- }
- catch(const uno::Exception&){
-
- g_warning( "Exception in get_run_attributes()" );
-
- if( pSet )
- {
- atk_attribute_set_free( pSet );
- pSet = nullptr;
- }
- }
-
- return pSet;
-}
-
-/*****************************************************************************/
-
-static AtkAttributeSet *
-text_wrapper_get_default_attributes( AtkText *text )
-{
- AtkAttributeSet *pSet = nullptr;
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
- pTextAttributes = getTextAttributes( text );
- if( pTextAttributes.is() )
- {
- uno::Sequence< beans::PropertyValue > aAttributeList =
- pTextAttributes->getDefaultAttributes( uno::Sequence< OUString > () );
-
- pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
- }
- }
- catch(const uno::Exception&) {
-
- g_warning( "Exception in get_default_attributes()" );
-
- if( pSet )
- {
- atk_attribute_set_free( pSet );
- pSet = nullptr;
- }
- }
-
- return pSet;
-}
-
-/*****************************************************************************/
-
-static void
-text_wrapper_get_character_extents( AtkText *text,
- gint offset,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- AtkCoordType coords )
-{
- *x = *y = *width = *height = -1;
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- awt::Rectangle aRect = pText->getCharacterBounds( offset );
-
- gint origin_x = 0;
- gint origin_y = 0;
-
- if( coords == ATK_XY_SCREEN )
- {
- g_return_if_fail( ATK_IS_COMPONENT( text ) );
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
- SAL_WNODEPRECATED_DECLARATIONS_POP
- }
-
- *x = aRect.X + origin_x;
- *y = aRect.Y + origin_y;
- *width = aRect.Width;
- *height = aRect.Height;
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCharacterBounds" );
- }
-}
-
-static gint
-text_wrapper_get_character_count (AtkText *text)
-{
- gint rv = 0;
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- rv = pText->getCharacterCount();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCharacterCount" );
- }
-
- return rv;
-}
-
-static gint
-text_wrapper_get_offset_at_point (AtkText *text,
- gint x,
- gint y,
- AtkCoordType coords)
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- gint origin_x = 0;
- gint origin_y = 0;
-
- if( coords == ATK_XY_SCREEN )
- {
- g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
- SAL_WNODEPRECATED_DECLARATIONS_POP
- }
-
- return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getIndexAtPoint" );
- }
-
- return -1;
-}
-
-// FIXME: the whole series of selections API is problematic ...
-
-static gint
-text_wrapper_get_n_selections (AtkText *text)
-{
- gint rv = 0;
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
- }
-
- return rv;
-}
-
-static gchar *
-text_wrapper_get_selection (AtkText *text,
- gint selection_num,
- gint *start_offset,
- gint *end_offset)
-{
- g_return_val_if_fail( selection_num == 0, FALSE );
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- {
- *start_offset = pText->getSelectionStart();
- *end_offset = pText->getSelectionEnd();
-
- return OUStringToGChar( pText->getSelectedText() );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
- }
-
- return nullptr;
-}
-
-static gboolean
-text_wrapper_add_selection (AtkText *text,
- gint start_offset,
- gint end_offset)
-{
- // FIXME: can we try to be more compatible by expanding an
- // existing adjacent selection ?
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- return pText->setSelection( start_offset, end_offset ); // ?
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in setSelection()" );
- }
-
- return FALSE;
-}
-
-static gboolean
-text_wrapper_remove_selection (AtkText *text,
- gint selection_num)
-{
- g_return_val_if_fail( selection_num == 0, FALSE );
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- return pText->setSelection( 0, 0 ); // ?
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in setSelection()" );
- }
-
- return FALSE;
-}
-
-static gboolean
-text_wrapper_set_selection (AtkText *text,
- gint selection_num,
- gint start_offset,
- gint end_offset)
-{
- g_return_val_if_fail( selection_num == 0, FALSE );
-
- try {
- css::uno::Reference<css::accessibility::XAccessibleText> pText
- = getText( text );
- if( pText.is() )
- return pText->setSelection( start_offset, end_offset );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in setSelection()" );
- }
-
- return FALSE;
-}
-
-} // extern "C"
-
-void
-textIfaceInit (AtkTextIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->get_text = text_wrapper_get_text;
- iface->get_character_at_offset = text_wrapper_get_character_at_offset;
- iface->get_text_before_offset = text_wrapper_get_text_before_offset;
- iface->get_text_at_offset = text_wrapper_get_text_at_offset;
- iface->get_text_after_offset = text_wrapper_get_text_after_offset;
- iface->get_caret_offset = text_wrapper_get_caret_offset;
- iface->set_caret_offset = text_wrapper_set_caret_offset;
- iface->get_character_count = text_wrapper_get_character_count;
- iface->get_n_selections = text_wrapper_get_n_selections;
- iface->get_selection = text_wrapper_get_selection;
- iface->add_selection = text_wrapper_add_selection;
- iface->remove_selection = text_wrapper_remove_selection;
- iface->set_selection = text_wrapper_set_selection;
- iface->get_run_attributes = text_wrapper_get_run_attributes;
- iface->get_default_attributes = text_wrapper_get_default_attributes;
- iface->get_character_extents = text_wrapper_get_character_extents;
- iface->get_offset_at_point = text_wrapper_get_offset_at_point;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atktextattributes.cxx b/vcl/unx/gtk/a11y/atktextattributes.cxx
deleted file mode 100644
index 0ba7fd561862..000000000000
--- a/vcl/unx/gtk/a11y/atktextattributes.cxx
+++ /dev/null
@@ -1,1383 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atktextattributes.hxx"
-
-#include <com/sun/star/awt/FontSlant.hpp>
-#include <com/sun/star/awt/FontStrikeout.hpp>
-#include <com/sun/star/awt/FontUnderline.hpp>
-
-#include <com/sun/star/style/CaseMap.hpp>
-#include <com/sun/star/style/LineSpacing.hpp>
-#include <com/sun/star/style/LineSpacingMode.hpp>
-#include <com/sun/star/style/ParagraphAdjust.hpp>
-#include <com/sun/star/style/TabAlign.hpp>
-#include <com/sun/star/style/TabStop.hpp>
-
-#include <com/sun/star/text/WritingMode2.hpp>
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
-
-#include <i18nlangtag/languagetag.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/outdev.hxx>
-
-#include <stdio.h>
-#include <string.h>
-
-using namespace ::com::sun::star;
-
-typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
-typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
-
-#define STRNCMP_PARAM( s ) s,sizeof( s )-1
-
-/*****************************************************************************/
-
-static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
-static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
-// #i92232#
-static AtkTextAttribute atk_text_attribute_tracked_change = ATK_TEXT_ATTR_INVALID;
-// #i92233#
-static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio = ATK_TEXT_ATTR_INVALID;
-
-/*****************************************************************************/
-
-/**
- * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
- * and re-arrange the enum values accordingly.
- */
-
-enum ExportedAttribute
-{
- TEXT_ATTRIBUTE_BACKGROUND_COLOR = 0,
- TEXT_ATTRIBUTE_CASEMAP,
- TEXT_ATTRIBUTE_FOREGROUND_COLOR,
- TEXT_ATTRIBUTE_CONTOURED,
- TEXT_ATTRIBUTE_CHAR_ESCAPEMENT,
- TEXT_ATTRIBUTE_BLINKING,
- TEXT_ATTRIBUTE_FONT_NAME,
- TEXT_ATTRIBUTE_HEIGHT,
- TEXT_ATTRIBUTE_HIDDEN,
- TEXT_ATTRIBUTE_KERNING,
- TEXT_ATTRIBUTE_LOCALE,
- TEXT_ATTRIBUTE_POSTURE,
- TEXT_ATTRIBUTE_RELIEF,
- TEXT_ATTRIBUTE_ROTATION,
- TEXT_ATTRIBUTE_SCALE,
- TEXT_ATTRIBUTE_SHADOWED,
- TEXT_ATTRIBUTE_STRIKETHROUGH,
- TEXT_ATTRIBUTE_UNDERLINE,
- TEXT_ATTRIBUTE_WEIGHT,
- // #i92233#
- TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO,
- TEXT_ATTRIBUTE_JUSTIFICATION,
- TEXT_ATTRIBUTE_BOTTOM_MARGIN,
- TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
- TEXT_ATTRIBUTE_LEFT_MARGIN,
- TEXT_ATTRIBUTE_LINE_SPACING,
- TEXT_ATTRIBUTE_RIGHT_MARGIN,
- TEXT_ATTRIBUTE_STYLE_NAME,
- TEXT_ATTRIBUTE_TAB_STOPS,
- TEXT_ATTRIBUTE_TOP_MARGIN,
- TEXT_ATTRIBUTE_WRITING_MODE,
- TEXT_ATTRIBUTE_LAST
-};
-
-static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
-{
- "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
- "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
- "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
- "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
- "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
- "CharFlash", // TEXT_ATTRIBUTE_BLINKING
- "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
- "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
- "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
- "CharKerning", // TEXT_ATTRIBUTE_KERNING
- "CharLocale", // TEXT_ATTRIBUTE_LOCALE
- "CharPosture", // TEXT_ATTRIBUTE_POSTURE
- "CharRelief", // TEXT_ATTRIBUTE_RELIEF
- "CharRotation", // TEXT_ATTRIBUTE_ROTATION
- "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
- "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
- "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
- "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
- "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
- // #i92233#
- "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
- "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
- "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
- "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
- "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
- "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
- "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
- "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
- "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
- "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
- "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
-};
-
-/*****************************************************************************/
-
-static gchar*
-get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
- sal_Int32 nIndex, AtkTextAttrFunc func )
-{
- if( nIndex != -1 )
- return func(rAttributeList[nIndex].Value);
-
- return nullptr;
-}
-
-#define get_bool_value( list, index ) get_value( list, index, Bool2String )
-#define get_height_value( list, index ) get_value( list, index, Float2String )
-#define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
-#define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
-#define get_scale_width( list, index ) get_value( list, index, Scale2String )
-#define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
-#define get_string_value( list, index ) get_value( list, index, GetString )
-#define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
-#define get_underline_value( list, index ) get_value( list, index, Underline2String )
-#define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
-#define get_weight_value( list, index ) get_value( list, index, Weight2String )
-#define get_language_string( list, index ) get_value( list, index, Locale2String )
-
-static double toPoint(sal_Int16 n)
-{
- // 100th mm -> pt
- return static_cast<double>(n * 72) / 2540;
-}
-
-/*****************************************************************************/
-
-static bool
-InvalidValue( uno::Any&, const gchar * )
-{
- return false;
-}
-
-/*****************************************************************************/
-
-static gchar*
-Float2String(const uno::Any& rAny)
-{
- return g_strdup_printf( "%g", rAny.get<float>() );
-}
-
-static bool
-String2Float( uno::Any& rAny, const gchar * value )
-{
- float fval;
-
- if( 1 != sscanf( value, "%g", &fval ) )
- return false;
-
- rAny <<= fval;
- return true;
-}
-
-/*****************************************************************************/
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleComponent>
- getComponent( AtkText *pText )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
- if( pWrap )
- {
- if( !pWrap->mpComponent.is() )
- {
- pWrap->mpComponent.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpComponent;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleComponent>();
-}
-
-static gchar*
-get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
- const sal_Int32 * pIndexArray,
- ExportedAttribute attr,
- AtkText * text)
-{
- sal_Int32 nColor = -1; // AUTOMATIC
- sal_Int32 nIndex = pIndexArray[attr];
-
- if( nIndex != -1 )
- nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
-
- /*
- * Check for color value for 100% alpha white, which means
- * "automatic". Grab the RGB value from XAccessibleComponent
- * in this case.
- */
-
- if( (nColor == -1) && text )
- {
- try
- {
- css::uno::Reference<css::accessibility::XAccessibleComponent>
- pComponent = getComponent( text );
- if( pComponent.is() )
- {
- switch( attr )
- {
- case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
- nColor = pComponent->getBackground();
- break;
- case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
- nColor = pComponent->getForeground();
- break;
- default:
- break;
- }
- }
- }
-
- catch(const uno::Exception&) {
- g_warning( "Exception in get[Fore|Back]groundColor()" );
- }
- }
-
- if( nColor != -1 )
- {
- sal_uInt8 blue = nColor & 0xFF;
- sal_uInt8 green = (nColor >> 8) & 0xFF;
- sal_uInt8 red = (nColor >> 16) & 0xFF;
-
- return g_strdup_printf( "%u,%u,%u", red, green, blue );
- }
-
- return nullptr;
-}
-
-static bool
-String2Color( uno::Any& rAny, const gchar * value )
-{
- int red, green, blue;
-
- if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
- return false;
-
- sal_Int32 nColor = static_cast<sal_Int32>(blue) | ( static_cast<sal_Int32>(green) << 8 ) | ( static_cast<sal_Int32>(red) << 16 );
- rAny <<= nColor;
- return true;
-}
-
-/*****************************************************************************/
-
-static gchar*
-FontSlant2Style(const uno::Any& rAny)
-{
- const gchar * value = nullptr;
-
- awt::FontSlant aFontSlant;
- if(!(rAny >>= aFontSlant))
- return nullptr;
-
- switch( aFontSlant )
- {
- case awt::FontSlant_NONE:
- value = "normal";
- break;
-
- case awt::FontSlant_OBLIQUE:
- value = "oblique";
- break;
-
- case awt::FontSlant_ITALIC:
- value = "italic";
- break;
-
- case awt::FontSlant_REVERSE_OBLIQUE:
- value = "reverse oblique";
- break;
-
- case awt::FontSlant_REVERSE_ITALIC:
- value = "reverse italic";
- break;
-
- default:
- break;
- }
-
- if( value )
- return g_strdup( value );
-
- return nullptr;
-}
-
-static bool
-Style2FontSlant( uno::Any& rAny, const gchar * value )
-{
- awt::FontSlant aFontSlant;
-
- if( strncmp( value, STRNCMP_PARAM( "normal" ) ) == 0 )
- aFontSlant = awt::FontSlant_NONE;
- else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) == 0 )
- aFontSlant = awt::FontSlant_OBLIQUE;
- else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) == 0 )
- aFontSlant = awt::FontSlant_ITALIC;
- else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) == 0 )
- aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
- else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) == 0 )
- aFontSlant = awt::FontSlant_REVERSE_ITALIC;
- else
- return false;
-
- rAny <<= aFontSlant;
- return true;
-}
-
-/*****************************************************************************/
-
-static gchar*
-Weight2String(const uno::Any& rAny)
-{
- return g_strdup_printf( "%g", rAny.get<float>() * 4 );
-}
-
-static bool
-String2Weight( uno::Any& rAny, const gchar * value )
-{
- float weight;
-
- if( 1 != sscanf( value, "%g", &weight ) )
- return false;
-
- rAny <<= weight / 4;
- return true;
-}
-
-/*****************************************************************************/
-
-static gchar*
-Adjust2Justification(const uno::Any& rAny)
-{
- const gchar * value = nullptr;
-
- switch( static_cast<style::ParagraphAdjust>(rAny.get<short>()) )
- {
- case style::ParagraphAdjust_LEFT:
- value = "left";
- break;
-
- case style::ParagraphAdjust_RIGHT:
- value = "right";
- break;
-
- case style::ParagraphAdjust_BLOCK:
- case style::ParagraphAdjust_STRETCH:
- value = "fill";
- break;
-
- case style::ParagraphAdjust_CENTER:
- value = "center";
- break;
-
- default:
- break;
- }
-
- if( value )
- return g_strdup( value );
-
- return nullptr;
-}
-
-static bool
-Justification2Adjust( uno::Any& rAny, const gchar * value )
-{
- style::ParagraphAdjust nParagraphAdjust;
-
- if( strncmp( value, STRNCMP_PARAM( "left" ) ) == 0 )
- nParagraphAdjust = style::ParagraphAdjust_LEFT;
- else if( strncmp( value, STRNCMP_PARAM( "right" ) ) == 0 )
- nParagraphAdjust = style::ParagraphAdjust_RIGHT;
- else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) == 0 )
- nParagraphAdjust = style::ParagraphAdjust_BLOCK;
- else if( strncmp( value, STRNCMP_PARAM( "center" ) ) == 0 )
- nParagraphAdjust = style::ParagraphAdjust_CENTER;
- else
- return false;
-
- rAny <<= static_cast<short>(nParagraphAdjust);
- return true;
-}
-
-/*****************************************************************************/
-
-const gchar * const font_strikethrough[] = {
- "none", // FontStrikeout::NONE
- "single", // FontStrikeout::SINGLE
- "double", // FontStrikeout::DOUBLE
- nullptr, // FontStrikeout::DONTKNOW
- "bold", // FontStrikeout::BOLD
- "with /", // FontStrikeout::SLASH
- "with X" // FontStrikeout::X
-};
-
-static gchar*
-Strikeout2String(const uno::Any& rAny)
-{
- sal_Int16 n = rAny.get<sal_Int16>();
-
- if( n >= 0 && n < sal_Int16(SAL_N_ELEMENTS(font_strikethrough)) )
- return g_strdup( font_strikethrough[n] );
-
- return nullptr;
-}
-
-static bool
-String2Strikeout( uno::Any& rAny, const gchar * value )
-{
- for( sal_Int16 n=0; n < sal_Int16(SAL_N_ELEMENTS(font_strikethrough)); ++n )
- {
- if( ( nullptr != font_strikethrough[n] ) &&
- 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
- {
- rAny <<= n;
- return true;
- }
- }
-
- return false;
-}
-
-/*****************************************************************************/
-
-static gchar*
-Underline2String(const uno::Any& rAny)
-{
- const gchar * value = nullptr;
-
- switch( rAny.get<sal_Int16>() )
- {
- case awt::FontUnderline::NONE:
- value = "none";
- break;
-
- case awt::FontUnderline::SINGLE:
- value = "single";
- break;
-
- case awt::FontUnderline::DOUBLE:
- value = "double";
- break;
-
- default:
- break;
- }
-
- if( value )
- return g_strdup( value );
-
- return nullptr;
-}
-
-static bool
-String2Underline( uno::Any& rAny, const gchar * value )
-{
- short nUnderline;
-
- if( strncmp( value, STRNCMP_PARAM( "none" ) ) == 0 )
- nUnderline = awt::FontUnderline::NONE;
- else if( strncmp( value, STRNCMP_PARAM( "single" ) ) == 0 )
- nUnderline = awt::FontUnderline::SINGLE;
- else if( strncmp( value, STRNCMP_PARAM( "double" ) ) == 0 )
- nUnderline = awt::FontUnderline::DOUBLE;
- else
- return false;
-
- rAny <<= nUnderline;
- return true;
-}
-
-/*****************************************************************************/
-
-static gchar*
-GetString(const uno::Any& rAny)
-{
- OString aFontName = OUStringToOString( rAny.get< OUString > (), RTL_TEXTENCODING_UTF8 );
-
- if( !aFontName.isEmpty() )
- return g_strdup( aFontName.getStr() );
-
- return nullptr;
-}
-
-static bool
-SetString( uno::Any& rAny, const gchar * value )
-{
- OString aFontName( value );
-
- if( !aFontName.isEmpty() )
- {
- rAny <<= OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 );
- return true;
- }
-
- return false;
-}
-
-/*****************************************************************************/
-
-// @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
-
-// CMM = 100th of mm
-static gchar*
-CMM2UnitString(const uno::Any& rAny)
-{
- double fValue = rAny.get<sal_Int32>();
- fValue = fValue * 0.01;
-
- return g_strdup_printf( "%gmm", fValue );
-}
-
-static bool
-UnitString2CMM( uno::Any& rAny, const gchar * value )
-{
- float fValue = 0.0; // pb: don't use double here because of warning on linux
-
- if( 1 != sscanf( value, "%gmm", &fValue ) )
- return false;
-
- fValue = fValue * 100;
-
- rAny <<= static_cast<sal_Int32>(fValue);
- return true;
-}
-
-/*****************************************************************************/
-
-static const gchar * bool_values[] = { "true", "false" };
-
-static gchar *
-Bool2String( const uno::Any& rAny )
-{
- int n = 1;
-
- if( rAny.get<bool>() )
- n = 0;
-
- return g_strdup( bool_values[n] );
-}
-
-static bool
-String2Bool( uno::Any& rAny, const gchar * value )
-{
- bool bValue;
-
- if( strncmp( value, STRNCMP_PARAM( "true" ) ) == 0 )
- bValue = true;
- else if( strncmp( value, STRNCMP_PARAM( "false" ) ) == 0 )
- bValue = false;
- else
- return false;
-
- rAny <<= bValue;
- return true;
-}
-
-/*****************************************************************************/
-
-static gchar*
-Scale2String( const uno::Any& rAny )
-{
- return g_strdup_printf( "%g", static_cast<double>(rAny.get< sal_Int16 > ()) / 100 );
-}
-
-static bool
-String2Scale( uno::Any& rAny, const gchar * value )
-{
- double dval;
-
- if( 1 != sscanf( value, "%lg", &dval ) )
- return false;
-
- rAny <<= static_cast<sal_Int16>(dval * 100);
- return true;
-}
-
-/*****************************************************************************/
-
-static gchar *
-CaseMap2String( const uno::Any& rAny )
-{
- const gchar * value;
-
- switch( rAny.get<short>() )
- {
- case style::CaseMap::SMALLCAPS:
- value = "small_caps";
- break;
-
- default:
- value = "normal";
- break;
- }
-
- return g_strdup(value);
-}
-
-static bool
-String2CaseMap( uno::Any& rAny, const gchar * value )
-{
- short nCaseMap;
-
- if( strncmp( value, STRNCMP_PARAM( "normal" ) ) == 0 )
- nCaseMap = style::CaseMap::NONE;
- else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) == 0 )
- nCaseMap = style::CaseMap::SMALLCAPS;
- else
- return false;
-
- rAny <<= nCaseMap;
- return true;
-}
-
-/*****************************************************************************/
-
-const gchar * const font_stretch[] = {
- "ultra_condensed",
- "extra_condensed",
- "condensed",
- "semi_condensed",
- "normal",
- "semi_expanded",
- "expanded",
- "extra_expanded",
- "ultra_expanded"
-};
-
-static gchar*
-Kerning2Stretch(const uno::Any& rAny)
-{
- sal_Int16 n = rAny.get<sal_Int16>();
- int i = 4;
-
- // No good idea for a mapping - just return the basic info
- if( n < 0 )
- i=2;
- else if( n > 0 )
- i=6;
-
- return g_strdup(font_stretch[i]);
-}
-
-/*****************************************************************************/
-
-static gchar*
-Locale2String(const uno::Any& rAny)
-{
- /* FIXME-BCP47: support language tags? And why is country lowercase? */
- lang::Locale aLocale = rAny.get<lang::Locale> ();
- LanguageTag aLanguageTag( aLocale);
- return g_strdup_printf( "%s-%s",
- OUStringToOString( aLanguageTag.getLanguage(), RTL_TEXTENCODING_ASCII_US).getStr(),
- OUStringToOString( aLanguageTag.getCountry(), RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
-}
-
-static bool
-String2Locale( uno::Any& rAny, const gchar * value )
-{
- /* FIXME-BCP47: support language tags? */
- bool ret = false;
-
- gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
- if( str_array[0] != nullptr )
- {
- ret = true;
-
- lang::Locale aLocale;
-
- aLocale.Language = OUString::createFromAscii(str_array[0]);
- if( str_array[1] != nullptr )
- {
- gchar * country = g_ascii_strup(str_array[1], -1);
- aLocale.Country = OUString::createFromAscii(country);
- g_free(country);
- }
-
- rAny <<= aLocale;
- }
-
- g_strfreev(str_array);
- return ret;
-}
-
-/*****************************************************************************/
-
-// @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
-static const gchar * relief[] = { "none", "emboss", "engrave" };
-static const gchar * const outline = "outline";
-
-static gchar *
-get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
- sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
-{
- if( nContourIndex != -1 )
- {
- if( rAttributeList[nContourIndex].Value.get<bool>() )
- return g_strdup(outline);
- }
-
- if( nReliefIndex != -1 )
- {
- sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
- if( n < 3)
- return g_strdup(relief[n]);
- }
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-// @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
-
-enum
-{
- DECORATION_NONE = 0,
- DECORATION_BLINK,
- DECORATION_UNDERLINE,
- DECORATION_LINE_THROUGH
-};
-
-static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
-
-static gchar *
-get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
- sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
- sal_Int16 nStrikeoutIndex)
-{
- gchar * value_list[4] = { nullptr, nullptr, nullptr, nullptr };
- gint count = 0;
-
- // no property value found
- if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
- return nullptr;
-
- if( nBlinkIndex != -1 )
- {
- if( rAttributeList[nBlinkIndex].Value.get<bool>() )
- value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
- }
- if( nUnderlineIndex != -1 )
- {
- sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
- if( n != awt::FontUnderline::NONE )
- value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
- }
- if( nStrikeoutIndex != -1 )
- {
- sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
- if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
- value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
- }
-
- if( count == 0 )
- value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
-
- return g_strjoinv(" ", value_list);
-}
-
-/*****************************************************************************/
-
-// @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
-
-static const gchar * shadow_values[] = { "none", "black" };
-
-static gchar *
-Bool2Shadow( const uno::Any& rAny )
-{
- int n = 0;
-
- if( rAny.get<bool>() )
- n = 1;
-
- return g_strdup( shadow_values[n] );
-}
-
-/*****************************************************************************/
-
-static gchar *
-Short2Degree( const uno::Any& rAny )
-{
- float f = rAny.get<sal_Int16>() / 10.0;
- return g_strdup_printf( "%g", f );
-}
-
-/*****************************************************************************/
-
-const gchar * const directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
-
-static gchar *
-WritingMode2Direction( const uno::Any& rAny )
-{
- sal_Int16 n = rAny.get<sal_Int16>();
-
- if( 0 <= n && n <= text::WritingMode2::PAGE )
- return g_strdup(directions[n]);
-
- return nullptr;
-}
-
-// @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
-
-const gchar * const writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
-static gchar *
-WritingMode2String( const uno::Any& rAny )
-{
- sal_Int16 n = rAny.get<sal_Int16>();
-
- if( 0 <= n && n <= text::WritingMode2::PAGE )
- return g_strdup(writing_modes[n]);
-
- return nullptr;
-}
-
-/*****************************************************************************/
-
-const char * const baseline_values[] = { "baseline", "sub", "super" };
-
-// @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
-static gchar *
-Escapement2VerticalAlign( const uno::Any& rAny )
-{
- sal_Int16 n = rAny.get<sal_Int16>();
- gchar * ret = nullptr;
-
- // Values are in %, 101% means "automatic"
- if( n == 0 )
- ret = g_strdup(baseline_values[0]);
- else if( n == 101 )
- ret = g_strdup(baseline_values[2]);
- else if( n == -101 )
- ret = g_strdup(baseline_values[1]);
- else
- ret = g_strdup_printf( "%d%%", n );
-
- return ret;
-}
-
-/*****************************************************************************/
-
-// @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
-static gchar *
-LineSpacing2LineHeight( const uno::Any& rAny )
-{
- style::LineSpacing ls;
- gchar * ret = nullptr;
-
- if( rAny >>= ls )
- {
- if( ls.Mode == style::LineSpacingMode::PROP )
- ret = g_strdup_printf( "%d%%", ls.Height );
- else if( ls.Mode == style::LineSpacingMode::FIX )
- ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
- }
-
- return ret;
-}
-
-/*****************************************************************************/
-
-// @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
-static gchar *
-TabStopList2String( const uno::Any& rAny, bool default_tabs )
-{
- uno::Sequence< style::TabStop > theTabStops;
- gchar * ret = nullptr;
-
- if( rAny >>= theTabStops)
- {
- sal_Unicode lastFillChar = ' ';
-
- for( const auto& rTabStop : std::as_const(theTabStops) )
- {
- bool is_default_tab = (style::TabAlign_DEFAULT == rTabStop.Alignment);
-
- if( is_default_tab != default_tabs )
- continue;
-
- double fValue = rTabStop.Position;
- fValue = fValue * 0.01;
-
- const gchar * tab_align = "";
- switch( rTabStop.Alignment )
- {
- case style::TabAlign_LEFT :
- tab_align = "left ";
- break;
- case style::TabAlign_CENTER :
- tab_align = "center ";
- break;
- case style::TabAlign_RIGHT :
- tab_align = "right ";
- break;
- case style::TabAlign_DECIMAL :
- tab_align = "decimal ";
- break;
- default:
- break;
- }
-
- const gchar * lead_char = "";
-
- if( rTabStop.FillChar != lastFillChar )
- {
- lastFillChar = rTabStop.FillChar;
- switch (lastFillChar)
- {
- case ' ':
- lead_char = "blank ";
- break;
-
- case '.':
- lead_char = "dotted ";
- break;
-
- case '-':
- lead_char = "dashed ";
- break;
-
- case '_':
- lead_char = "lined ";
- break;
-
- default:
- lead_char = "custom ";
- break;
- }
- }
-
- gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
-
- if( ret )
- {
- gchar * old_tab_str = ret;
- ret = g_strconcat(old_tab_str, " ", tab_str, nullptr);
- g_free( old_tab_str );
- }
- else
- ret = tab_str;
- }
- }
-
- return ret;
-}
-
-static gchar *
-TabStops2String( const uno::Any& rAny )
-{
- return TabStopList2String(rAny, false);
-}
-
-static gchar *
-DefaultTabStops2String( const uno::Any& rAny )
-{
- return TabStopList2String(rAny, true);
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-static int
-attr_compare(const void *p1,const void *p2)
-{
- const rtl_uString * pustr = static_cast<const rtl_uString *>(p1);
- const char * pc = *static_cast<const char * const *>(p2);
-
- return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
-}
-
-}
-
-static void
-find_exported_attributes( sal_Int32 *pArray,
- const css::uno::Sequence< css::beans::PropertyValue >& rAttributeList )
-{
- for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
- {
- const char ** pAttr = static_cast<const char **>(bsearch(rAttributeList[i].Name.pData,
- ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
- attr_compare));
-
- if( pAttr )
- {
- sal_Int32 nIndex = pAttr - ExportedTextAttributes;
- pArray[nIndex] = i;
- }
- }
-}
-
-/*****************************************************************************/
-
-static AtkAttributeSet*
-attribute_set_prepend( AtkAttributeSet* attribute_set,
- AtkTextAttribute attribute,
- gchar * value )
-{
- if( value )
- {
- AtkAttribute *at = static_cast<AtkAttribute *>(g_malloc( sizeof (AtkAttribute) ));
- at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
- at->value = value;
-
- return g_slist_prepend(attribute_set, at);
- }
-
- return attribute_set;
-}
-
-/*****************************************************************************/
-
-AtkAttributeSet*
-attribute_set_new_from_property_values(
- const uno::Sequence< beans::PropertyValue >& rAttributeList,
- bool run_attributes_only,
- AtkText *text)
-{
- AtkAttributeSet* attribute_set = nullptr;
-
- sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
-
- // Initialize index array with -1
- for(sal_Int32 & rn : aIndexList)
- rn = -1;
-
- find_exported_attributes(aIndexList, rAttributeList);
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
- get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? nullptr : text ) );
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
- get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? nullptr : text) );
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
- get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
- get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
- get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
- get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
- get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
- get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
- get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
- get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
- get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
- get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
- atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
- get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
- atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
- get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
- aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
- atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
- atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
- atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
- atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
-
- if( run_attributes_only )
- return attribute_set;
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
- get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
- get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
- get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
- get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
- get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
-
- attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
- get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
- atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
- get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
- atk_text_attribute_line_height = atk_text_attribute_register("line-height");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
- atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
-
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
- atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
-
- attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
-
- // #i92233#
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_mm_to_pixel_ratio )
- atk_text_attribute_mm_to_pixel_ratio = atk_text_attribute_register("mm-to-pixel-ratio");
-
- attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_mm_to_pixel_ratio,
- get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO], Float2String));
-
- return attribute_set;
-}
-
-AtkAttributeSet*
-attribute_set_new_from_extended_attributes(
- const css::uno::Reference< css::accessibility::XAccessibleExtendedAttributes >& rExtendedAttributes )
-{
- AtkAttributeSet *pSet = nullptr;
-
- // extended attributes is a string of colon-separated pairs of property and value,
- // with pairs separated by semicolons. Example: "heading-level:2;weight:bold;"
- uno::Any anyVal = rExtendedAttributes->getExtendedAttributes();
- OUString sExtendedAttrs;
- anyVal >>= sExtendedAttrs;
- sal_Int32 nIndex = 0;
- do
- {
- OUString sProperty = sExtendedAttrs.getToken( 0, ';', nIndex );
-
- sal_Int32 nColonPos = 0;
- OString sPropertyName = OUStringToOString( sProperty.getToken( 0, ':', nColonPos ),
- RTL_TEXTENCODING_UTF8 );
- OString sPropertyValue = OUStringToOString( sProperty.getToken( 0, ':', nColonPos ),
- RTL_TEXTENCODING_UTF8 );
-
- pSet = attribute_set_prepend( pSet,
- atk_text_attribute_register( sPropertyName.getStr() ),
- g_strdup_printf( "%s", sPropertyValue.getStr() ) );
- }
- while ( nIndex >= 0 && nIndex < sExtendedAttrs.getLength() );
-
- return pSet;
-}
-
-AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
-{
- if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
- atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
-
- attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
- g_strdup_printf( "misspelled" ) );
-
- return attribute_set;
-}
-
-// #i92232#
-AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set )
-{
- if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
- {
- atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
- }
-
- attribute_set = attribute_set_prepend( attribute_set,
- atk_text_attribute_tracked_change,
- g_strdup_printf( "insertion" ) );
-
- return attribute_set;
-}
-
-AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set )
-{
- if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
- {
- atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
- }
-
- attribute_set = attribute_set_prepend( attribute_set,
- atk_text_attribute_tracked_change,
- g_strdup_printf( "deletion" ) );
-
- return attribute_set;
-}
-
-AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set )
-{
- if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
- {
- atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
- }
-
- attribute_set = attribute_set_prepend( attribute_set,
- atk_text_attribute_tracked_change,
- g_strdup_printf( "attribute-change" ) );
-
- return attribute_set;
-}
-
-/*****************************************************************************/
-
-struct AtkTextAttrMapping
-{
- const char * name;
- TextPropertyValueFunc const toPropertyValue;
-};
-
-const AtkTextAttrMapping g_TextAttrMap[] =
-{
- { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
- { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
- { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
- { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
- { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
- { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
- { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
- { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
- { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
- { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
- { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
- { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
- { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
- { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
- { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
- { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
- { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
- { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
- { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
- { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
- { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
- { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
- { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
- { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
- { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
- { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
- { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
- { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
-};
-
-/*****************************************************************************/
-
-bool
-attribute_set_map_to_property_values(
- AtkAttributeSet* attribute_set,
- uno::Sequence< beans::PropertyValue >& rValueList )
-{
- // Ensure enough space ..
- uno::Sequence< beans::PropertyValue > aAttributeList (SAL_N_ELEMENTS(g_TextAttrMap));
-
- sal_Int32 nIndex = 0;
- for( GSList * item = attribute_set; item != nullptr; item = g_slist_next( item ) )
- {
- AtkAttribute* attribute = reinterpret_cast<AtkAttribute *>(item);
-
- AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
- if( text_attr < SAL_N_ELEMENTS(g_TextAttrMap) )
- {
- if( g_TextAttrMap[text_attr].name[0] != '\0' )
- {
- if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
- return false;
-
- aAttributeList[nIndex].Name = OUString::createFromAscii( g_TextAttrMap[text_attr].name );
- aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
- ++nIndex;
- }
- }
- else
- {
- // Unsupported text attribute
- return false;
- }
- }
-
- aAttributeList.realloc( nIndex );
- rValueList = aAttributeList;
- return true;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkutil.cxx b/vcl/unx/gtk/a11y/atkutil.cxx
deleted file mode 100644
index 50ed2793bbf0..000000000000
--- a/vcl/unx/gtk/a11y/atkutil.cxx
+++ /dev/null
@@ -1,789 +0,0 @@
-/* -*- 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 .
- */
-
-#ifdef AIX
-#define _LINUX_SOURCE_COMPAT
-#include <sys/timer.h>
-#undef _LINUX_SOURCE_COMPAT
-#endif
-
-#include <com/sun/star/accessibility/XAccessibleContext.hpp>
-#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
-#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
-#include <com/sun/star/accessibility/AccessibleEventId.hpp>
-#include <com/sun/star/accessibility/AccessibleStateType.hpp>
-#include <com/sun/star/accessibility/XAccessibleText.hpp>
-#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
-#include <cppuhelper/implbase.hxx>
-#include <cppuhelper/weakref.hxx>
-#include <rtl/ref.hxx>
-#include <sal/log.hxx>
-
-#include <vcl/svapp.hxx>
-#include <vcl/window.hxx>
-#include <vcl/menu.hxx>
-#include <vcl/toolbox.hxx>
-
-#include <unx/gtk/gtkdata.hxx>
-#include "atkwrapper.hxx"
-#include "atkutil.hxx"
-
-#include <gtk/gtk.h>
-#include <config_version.h>
-
-#include <cassert>
-#include <set>
-
-using namespace ::com::sun::star;
-
-namespace
-{
- struct theNextFocusObject :
- public rtl::Static< uno::WeakReference< accessibility::XAccessible >, theNextFocusObject>
- {
- };
-}
-
-static guint focus_notify_handler = 0;
-
-/*****************************************************************************/
-
-extern "C" {
-
-static gboolean
-atk_wrapper_focus_idle_handler (gpointer data)
-{
- SolarMutexGuard aGuard;
-
- focus_notify_handler = 0;
-
- uno::Reference< accessibility::XAccessible > xAccessible = theNextFocusObject::get();
- if( xAccessible.get() == static_cast < accessibility::XAccessible * > (data) )
- {
- AtkObject *atk_obj = xAccessible.is() ? atk_object_wrapper_ref( xAccessible ) : nullptr;
- // Gail does not notify focus changes to NULL, so do we ..
- if( atk_obj )
- {
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- atk_focus_tracker_notify(atk_obj);
- SAL_WNODEPRECATED_DECLARATIONS_POP
- // #i93269#
- // emit text_caret_moved event for <XAccessibleText> object,
- // if cursor is inside the <XAccessibleText> object.
- // also emit state-changed:focused event under the same condition.
- {
- AtkObjectWrapper* wrapper_obj = ATK_OBJECT_WRAPPER (atk_obj);
- if( wrapper_obj && !wrapper_obj->mpText.is() )
- {
- wrapper_obj->mpText.set(wrapper_obj->mpContext, css::uno::UNO_QUERY);
- if ( wrapper_obj->mpText.is() )
- {
- gint caretPos = -1;
-
- try {
- caretPos = wrapper_obj->mpText->getCaretPosition();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCaretPosition()" );
- }
-
- if ( caretPos != -1 )
- {
- atk_object_notify_state_change( atk_obj, ATK_STATE_FOCUSED, TRUE );
- g_signal_emit_by_name( atk_obj, "text_caret_moved", caretPos );
- }
- }
- }
- }
- g_object_unref(atk_obj);
- }
- }
-
- return false;
-}
-
-} // extern "C"
-
-/*****************************************************************************/
-
-static void
-atk_wrapper_focus_tracker_notify_when_idle( const uno::Reference< accessibility::XAccessible > &xAccessible )
-{
- if( focus_notify_handler )
- g_source_remove(focus_notify_handler);
-
- theNextFocusObject::get() = xAccessible;
-
- focus_notify_handler = g_idle_add (atk_wrapper_focus_idle_handler, xAccessible.get());
-}
-
-/*****************************************************************************/
-
-class DocumentFocusListener :
- public ::cppu::WeakImplHelper< accessibility::XAccessibleEventListener >
-{
-
- std::set< uno::Reference< uno::XInterface > > m_aRefList;
-
-public:
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- void attachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible
- );
-
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- void attachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible,
- const uno::Reference< accessibility::XAccessibleContext >& xContext
- );
-
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- void attachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible,
- const uno::Reference< accessibility::XAccessibleContext >& xContext,
- const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
- );
-
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- void detachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible
- );
-
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- void detachRecursive(
- const uno::Reference< accessibility::XAccessibleContext >& xContext
- );
-
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- void detachRecursive(
- const uno::Reference< accessibility::XAccessibleContext >& xContext,
- const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
- );
-
- /// @throws lang::IndexOutOfBoundsException
- /// @throws uno::RuntimeException
- static uno::Reference< accessibility::XAccessible > getAccessible(const lang::EventObject& aEvent );
-
- // XEventListener
- virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
-
- // XAccessibleEventListener
- virtual void SAL_CALL notifyEvent( const accessibility::AccessibleEventObject& aEvent ) override;
-};
-
-/*****************************************************************************/
-
-void DocumentFocusListener::disposing( const lang::EventObject& aEvent )
-{
-
- // Unref the object here, but do not remove as listener since the object
- // might no longer be in a state that safely allows this.
- if( aEvent.Source.is() )
- m_aRefList.erase(aEvent.Source);
-
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
-{
- try {
- switch( aEvent.EventId )
- {
- case accessibility::AccessibleEventId::STATE_CHANGED:
- {
- sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
- aEvent.NewValue >>= nState;
-
- if( accessibility::AccessibleStateType::FOCUSED == nState )
- atk_wrapper_focus_tracker_notify_when_idle( getAccessible(aEvent) );
-
- break;
- }
-
- case accessibility::AccessibleEventId::CHILD:
- {
- uno::Reference< accessibility::XAccessible > xChild;
- if( (aEvent.OldValue >>= xChild) && xChild.is() )
- detachRecursive(xChild);
-
- if( (aEvent.NewValue >>= xChild) && xChild.is() )
- attachRecursive(xChild);
-
- break;
- }
-
- case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
- SAL_INFO("vcl.a11y", "Invalidate all children called");
- break;
-
- default:
- break;
- }
- }
- catch( const lang::IndexOutOfBoundsException& e )
- {
- g_warning("Focused object has invalid index in parent");
- }
-}
-
-/*****************************************************************************/
-
-uno::Reference< accessibility::XAccessible > DocumentFocusListener::getAccessible(const lang::EventObject& aEvent )
-{
- uno::Reference< accessibility::XAccessible > xAccessible(aEvent.Source, uno::UNO_QUERY);
-
- if( xAccessible.is() )
- return xAccessible;
-
- uno::Reference< accessibility::XAccessibleContext > xContext(aEvent.Source, uno::UNO_QUERY);
-
- if( xContext.is() )
- {
- uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
- if( xParent.is() )
- {
- uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
- if( xParentContext.is() )
- {
- return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() );
- }
- }
- }
-
- return uno::Reference< accessibility::XAccessible >();
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::attachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible
-)
-{
- uno::Reference< accessibility::XAccessibleContext > xContext =
- xAccessible->getAccessibleContext();
-
- if( xContext.is() )
- attachRecursive(xAccessible, xContext);
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::attachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible,
- const uno::Reference< accessibility::XAccessibleContext >& xContext
-)
-{
- uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
- xContext->getAccessibleStateSet();
-
- if( xStateSet.is() )
- attachRecursive(xAccessible, xContext, xStateSet);
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::attachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible,
- const uno::Reference< accessibility::XAccessibleContext >& xContext,
- const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
-)
-{
- if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED ) )
- atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
-
- uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
-
- if (!xBroadcaster.is())
- return;
-
- // If not already done, add the broadcaster to the list and attach as listener.
- const uno::Reference< uno::XInterface >& xInterface = xBroadcaster;
- if( m_aRefList.insert(xInterface).second )
- {
- xBroadcaster->addAccessibleEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
-
- if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
- {
- sal_Int32 n, nmax = xContext->getAccessibleChildCount();
- for( n = 0; n < nmax; n++ )
- {
- uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
-
- if( xChild.is() )
- attachRecursive(xChild);
- }
- }
- }
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::detachRecursive(
- const uno::Reference< accessibility::XAccessible >& xAccessible
-)
-{
- uno::Reference< accessibility::XAccessibleContext > xContext =
- xAccessible->getAccessibleContext();
-
- if( xContext.is() )
- detachRecursive(xContext);
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::detachRecursive(
- const uno::Reference< accessibility::XAccessibleContext >& xContext
-)
-{
- uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
- xContext->getAccessibleStateSet();
-
- if( xStateSet.is() )
- detachRecursive(xContext, xStateSet);
-}
-
-/*****************************************************************************/
-
-void DocumentFocusListener::detachRecursive(
- const uno::Reference< accessibility::XAccessibleContext >& xContext,
- const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
-)
-{
- uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
-
- if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) )
- {
- xBroadcaster->removeAccessibleEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
-
- if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
- {
- sal_Int32 n, nmax = xContext->getAccessibleChildCount();
- for( n = 0; n < nmax; n++ )
- {
- uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
-
- if( xChild.is() )
- detachRecursive(xChild);
- }
- }
- }
-}
-
-/*****************************************************************************/
-
-/*
- * page tabs in gtk are widgets, so we need to simulate focus events for those
- */
-
-static void handle_tabpage_activated(vcl::Window *pWindow)
-{
- uno::Reference< accessibility::XAccessible > xAccessible =
- pWindow->GetAccessible();
-
- if( ! xAccessible.is() )
- return;
-
- uno::Reference< accessibility::XAccessibleSelection > xSelection(
- xAccessible->getAccessibleContext(), uno::UNO_QUERY);
-
- if( xSelection.is() )
- atk_wrapper_focus_tracker_notify_when_idle( xSelection->getSelectedAccessibleChild(0) );
-}
-
-/*****************************************************************************/
-
-/*
- * toolbar items in gtk are widgets, so we need to simulate focus events for those
- */
-
-static void notify_toolbox_item_focus(ToolBox *pToolBox)
-{
- uno::Reference< accessibility::XAccessible > xAccessible =
- pToolBox->GetAccessible();
-
- if( ! xAccessible.is() )
- return;
-
- uno::Reference< accessibility::XAccessibleContext > xContext =
- xAccessible->getAccessibleContext();
-
- if( ! xContext.is() )
- return;
-
- ToolBox::ImplToolItems::size_type nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
- if( nPos != ToolBox::ITEM_NOTFOUND )
- atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
- //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32
-}
-
-static void handle_toolbox_highlight(vcl::Window *pWindow)
-{
- ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
-
- // Make sure either the toolbox or its parent toolbox has the focus
- if ( ! pToolBox->HasFocus() )
- {
- ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
- if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
- return;
- }
-
- notify_toolbox_item_focus(pToolBox);
-}
-
-static void handle_toolbox_highlightoff(vcl::Window const *pWindow)
-{
- ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pWindow->GetParent() );
-
- // Notify when leaving sub toolboxes
- if( pToolBoxParent && pToolBoxParent->HasFocus() )
- notify_toolbox_item_focus( pToolBoxParent );
-}
-
-/*****************************************************************************/
-
-static void create_wrapper_for_child(
- const uno::Reference< accessibility::XAccessibleContext >& xContext,
- sal_Int32 index)
-{
- if( xContext.is() )
- {
- uno::Reference< accessibility::XAccessible > xChild(xContext->getAccessibleChild(index));
- if( xChild.is() )
- {
- // create the wrapper object - it will survive the unref unless it is a transient object
- g_object_unref( atk_object_wrapper_ref( xChild ) );
- }
- }
-}
-
-/*****************************************************************************/
-
-static void handle_toolbox_buttonchange(VclWindowEvent const *pEvent)
-{
- vcl::Window* pWindow = pEvent->GetWindow();
- sal_Int32 index = static_cast<sal_Int32>(reinterpret_cast<sal_IntPtr>(pEvent->GetData()));
-
- if( pWindow && pWindow->IsReallyVisible() )
- {
- uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
- if( xAccessible.is() )
- {
- create_wrapper_for_child(xAccessible->getAccessibleContext(), index);
- }
- }
-}
-
-/*****************************************************************************/
-
-namespace {
-
-struct WindowList {
- ~WindowList() { assert(list.empty()); };
- // needs to be empty already on DeInitVCL, but at least check it's empty
- // on exit
-
- std::set< VclPtr<vcl::Window> > list;
-};
-
-WindowList g_aWindowList;
-
-}
-
-DocumentFocusListener & GtkSalData::GetDocumentFocusListener()
-{
- if (!m_pDocumentFocusListener)
- {
- m_pDocumentFocusListener = new DocumentFocusListener;
- m_xDocumentFocusListener.set(m_pDocumentFocusListener);
- }
- return *m_pDocumentFocusListener;
-}
-
-static void handle_get_focus(::VclWindowEvent const * pEvent)
-{
- GtkSalData *const pSalData(GetGtkSalData());
- assert(pSalData);
-
- DocumentFocusListener & rDocumentFocusListener(pSalData->GetDocumentFocusListener());
-
- vcl::Window *pWindow = pEvent->GetWindow();
-
- // The menu bar is handled through VclEventId::MenuHighlightED
- if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WindowType::MENUBARWINDOW )
- return;
-
- // ToolBoxes are handled through VclEventId::ToolboxHighlight
- if( pWindow->GetType() == WindowType::TOOLBOX )
- return;
-
- if( pWindow->GetType() == WindowType::TABCONTROL )
- {
- handle_tabpage_activated( pWindow );
- return;
- }
-
- uno::Reference< accessibility::XAccessible > xAccessible =
- pWindow->GetAccessible();
-
- if( ! xAccessible.is() )
- return;
-
- uno::Reference< accessibility::XAccessibleContext > xContext =
- xAccessible->getAccessibleContext();
-
- if( ! xContext.is() )
- return;
-
- uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
- xContext->getAccessibleStateSet();
-
- if( ! xStateSet.is() )
- return;
-
-/* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
- * need to add listeners to the children instead of re-using the tabpage stuff
- */
- if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED) &&
- ( pWindow->GetType() != WindowType::TREELISTBOX ) )
- {
- atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
- }
- else
- {
- if( g_aWindowList.list.insert(pWindow).second )
- {
- try
- {
- rDocumentFocusListener.attachRecursive(xAccessible, xContext, xStateSet);
- }
- catch (const uno::Exception&)
- {
- g_warning( "Exception caught processing focus events" );
- }
- }
- }
-}
-
-/*****************************************************************************/
-
-static void handle_menu_highlighted(::VclMenuEvent const * pEvent)
-{
- try
- {
- Menu* pMenu = pEvent->GetMenu();
- sal_uInt16 nPos = pEvent->GetItemPos();
-
- if( pMenu && nPos != 0xFFFF)
- {
- uno::Reference< accessibility::XAccessible > xAccessible ( pMenu->GetAccessible() );
-
- if( xAccessible.is() )
- {
- uno::Reference< accessibility::XAccessibleContext > xContext ( xAccessible->getAccessibleContext() );
-
- if( xContext.is() )
- atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
- }
- }
- }
- catch (const uno::Exception&)
- {
- g_warning( "Exception caught processing menu highlight events" );
- }
-}
-
-/*****************************************************************************/
-
-static void WindowEventHandler(void *, VclSimpleEvent& rEvent)
-{
- try
- {
- switch (rEvent.GetId())
- {
- case VclEventId::WindowShow:
- break;
- case VclEventId::WindowHide:
- break;
- case VclEventId::WindowClose:
- break;
- case VclEventId::WindowGetFocus:
- handle_get_focus(static_cast< ::VclWindowEvent const * >(&rEvent));
- break;
- case VclEventId::WindowLoseFocus:
- break;
- case VclEventId::WindowMinimize:
- break;
- case VclEventId::WindowNormalize:
- break;
- case VclEventId::WindowKeyInput:
- case VclEventId::WindowKeyUp:
- case VclEventId::WindowCommand:
- case VclEventId::WindowMouseMove:
- break;
-
- case VclEventId::MenuHighlight:
- if (const VclMenuEvent* pMenuEvent = dynamic_cast<const VclMenuEvent*>(&rEvent))
- {
- handle_menu_highlighted(pMenuEvent);
- }
- else if (const VclAccessibleEvent* pAccEvent = dynamic_cast<const VclAccessibleEvent*>(&rEvent))
- {
- const uno::Reference< accessibility::XAccessible >& xAccessible = pAccEvent->GetAccessible();
- if (xAccessible.is())
- atk_wrapper_focus_tracker_notify_when_idle(xAccessible);
- }
- break;
-
- case VclEventId::ToolboxHighlight:
- handle_toolbox_highlight(static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow());
- break;
-
- case VclEventId::ToolboxButtonStateChanged:
- handle_toolbox_buttonchange(static_cast< ::VclWindowEvent const * >(&rEvent));
- break;
-
- case VclEventId::ObjectDying:
- g_aWindowList.list.erase( static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow() );
- [[fallthrough]];
- case VclEventId::ToolboxHighlightOff:
- handle_toolbox_highlightoff(static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow());
- break;
-
- case VclEventId::TabpageActivate:
- handle_tabpage_activated(static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow());
- break;
-
- case VclEventId::ComboboxSetText:
- // This looks quite strange to me. Stumbled over this when fixing #i104290#.
- // This kicked in when leaving the combobox in the toolbar, after that the events worked.
- // I guess this was a try to work around missing combobox events, which didn't do the full job, and shouldn't be necessary anymore.
- // Fix for #i104290# was done in toolkit/source/awt/vclxaccessiblecomponent, FOCUSED state for compound controls in general.
- // create_wrapper_for_children(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
- break;
-
- default:
- break;
- }
- }
- catch (const lang::IndexOutOfBoundsException&)
- {
- g_warning("Focused object has invalid index in parent");
- }
-}
-
-static Link<VclSimpleEvent&,void> g_aEventListenerLink( nullptr, WindowEventHandler );
-
-/*****************************************************************************/
-
-extern "C" {
-
-static const gchar *
-ooo_atk_util_get_toolkit_name()
-{
- return "VCL";
-}
-
-/*****************************************************************************/
-
-static const gchar *
-ooo_atk_util_get_toolkit_version()
-{
- return LIBO_VERSION_DOTTED;
-}
-
-/*****************************************************************************/
-
-/*
- * GObject inheritance
- */
-
-static void
-ooo_atk_util_class_init (AtkUtilClass *)
-{
- AtkUtilClass *atk_class;
- gpointer data;
-
- data = g_type_class_peek (ATK_TYPE_UTIL);
- atk_class = ATK_UTIL_CLASS (data);
-
- atk_class->get_toolkit_name = ooo_atk_util_get_toolkit_name;
- atk_class->get_toolkit_version = ooo_atk_util_get_toolkit_version;
-
- ooo_atk_util_ensure_event_listener();
-}
-
-} // extern "C"
-
-void ooo_atk_util_ensure_event_listener()
-{
- static bool bInited;
- if (!bInited)
- {
- Application::AddEventListener( g_aEventListenerLink );
- bInited = true;
- }
-}
-
-GType
-ooo_atk_util_get_type()
-{
- static GType type = 0;
-
- if (!type)
- {
- GType parent_type = g_type_from_name( "GailUtil" );
-
- if( ! parent_type )
- {
- g_warning( "Unknown type: GailUtil" );
- parent_type = ATK_TYPE_UTIL;
- }
-
- GTypeQuery type_query;
- g_type_query( parent_type, &type_query );
-
- static const GTypeInfo typeInfo =
- {
- static_cast<guint16>(type_query.class_size),
- nullptr,
- nullptr,
- reinterpret_cast<GClassInitFunc>(ooo_atk_util_class_init),
- nullptr,
- nullptr,
- static_cast<guint16>(type_query.instance_size),
- 0,
- nullptr,
- nullptr
- } ;
-
- type = g_type_register_static (parent_type, "OOoUtil", &typeInfo, GTypeFlags(0)) ;
- }
-
- return type;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkvalue.cxx b/vcl/unx/gtk/a11y/atkvalue.cxx
deleted file mode 100644
index f5e45d3b2556..000000000000
--- a/vcl/unx/gtk/a11y/atkvalue.cxx
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- 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 .
- */
-
-#include "atkwrapper.hxx"
-
-#include <com/sun/star/accessibility/XAccessibleValue.hpp>
-
-#include <string.h>
-
-using namespace ::com::sun::star;
-
-/// @throws uno::RuntimeException
-static css::uno::Reference<css::accessibility::XAccessibleValue>
- getValue( AtkValue *pValue )
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pValue );
- if( pWrap )
- {
- if( !pWrap->mpValue.is() )
- {
- pWrap->mpValue.set(pWrap->mpContext, css::uno::UNO_QUERY);
- }
-
- return pWrap->mpValue;
- }
-
- return css::uno::Reference<css::accessibility::XAccessibleValue>();
-}
-
-static void anyToGValue( const uno::Any& aAny, GValue *pValue )
-{
- // FIXME: expand to lots of types etc.
- double aDouble=0;
- aAny >>= aDouble;
-
- memset( pValue, 0, sizeof( GValue ) );
- g_value_init( pValue, G_TYPE_DOUBLE );
- g_value_set_double( pValue, aDouble );
-}
-
-extern "C" {
-
-static void
-value_wrapper_get_current_value( AtkValue *value,
- GValue *gval )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleValue> pValue
- = getValue( value );
- if( pValue.is() )
- anyToGValue( pValue->getCurrentValue(), gval );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCurrentValue()" );
- }
-}
-
-static void
-value_wrapper_get_maximum_value( AtkValue *value,
- GValue *gval )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleValue> pValue
- = getValue( value );
- if( pValue.is() )
- anyToGValue( pValue->getMaximumValue(), gval );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCurrentValue()" );
- }
-}
-
-static void
-value_wrapper_get_minimum_value( AtkValue *value,
- GValue *gval )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleValue> pValue
- = getValue( value );
- if( pValue.is() )
- anyToGValue( pValue->getMinimumValue(), gval );
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCurrentValue()" );
- }
-}
-
-static gboolean
-value_wrapper_set_current_value( AtkValue *value,
- const GValue *gval )
-{
- try {
- css::uno::Reference<css::accessibility::XAccessibleValue> pValue
- = getValue( value );
- if( pValue.is() )
- {
- // FIXME - this needs expanding
- double aDouble = g_value_get_double( gval );
- return pValue->setCurrentValue( uno::Any(aDouble) );
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getCurrentValue()" );
- }
-
- return FALSE;
-}
-
-} // extern "C"
-
-void
-valueIfaceInit (AtkValueIface *iface)
-{
- g_return_if_fail (iface != nullptr);
-
- iface->get_current_value = value_wrapper_get_current_value;
- iface->get_maximum_value = value_wrapper_get_maximum_value;
- iface->get_minimum_value = value_wrapper_get_minimum_value;
- iface->set_current_value = value_wrapper_set_current_value;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkwindow.cxx b/vcl/unx/gtk/a11y/atkwindow.cxx
deleted file mode 100644
index eb72edf4908c..000000000000
--- a/vcl/unx/gtk/a11y/atkwindow.cxx
+++ /dev/null
@@ -1,330 +0,0 @@
-/* -*- 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 .
- */
-
-#include <unx/gtk/gtkframe.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/window.hxx>
-#include <vcl/popupmenuwindow.hxx>
-#include <sal/log.hxx>
-
-#include "atkwindow.hxx"
-#include "atkwrapper.hxx"
-#include "atkregistry.hxx"
-
-#include <com/sun/star/accessibility/AccessibleRole.hpp>
-
-using namespace ::com::sun::star::accessibility;
-using namespace ::com::sun::star::uno;
-
-extern "C" {
-
-static void (* window_real_initialize) (AtkObject *obj, gpointer data) = nullptr;
-static void (* window_real_finalize) (GObject *obj) = nullptr;
-
-static void
-init_from_window( AtkObject *accessible, vcl::Window const *pWindow )
-{
- static AtkRole aDefaultRole = ATK_ROLE_INVALID;
-
- // Special role for sub-menu and combo-box popups that are exposed directly
- // by their parents already.
- if( aDefaultRole == ATK_ROLE_INVALID )
- {
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- aDefaultRole = atk_role_register( "redundant object" );
- SAL_WNODEPRECATED_DECLARATIONS_POP
- }
-
- AtkRole role = aDefaultRole;
-
- // Determine the appropriate role for the GtkWindow
- switch( pWindow->GetAccessibleRole() )
- {
- case AccessibleRole::ALERT:
- role = ATK_ROLE_ALERT;
- break;
-
- case AccessibleRole::DIALOG:
- role = ATK_ROLE_DIALOG;
- break;
-
- case AccessibleRole::FRAME:
- role = ATK_ROLE_FRAME;
- break;
-
- /* Ignore window objects for sub-menus, combo- and list boxes,
- * which are exposed as children of their parents.
- */
- case AccessibleRole::WINDOW:
- {
- WindowType type = WindowType::WINDOW;
- bool parentIsMenuFloatingWindow = false;
-
- vcl::Window *pParent = pWindow->GetParent();
- if( pParent ) {
- type = pParent->GetType();
- parentIsMenuFloatingWindow = pParent->IsMenuFloatingWindow();
- }
-
- if( (WindowType::LISTBOX != type) && (WindowType::COMBOBOX != type) &&
- (WindowType::MENUBARWINDOW != type) && ! parentIsMenuFloatingWindow )
- {
- role = ATK_ROLE_WINDOW;
- }
- }
- break;
-
- default:
- {
- vcl::Window *pChild = pWindow->GetWindow(GetWindowType::FirstChild);
- if( pChild )
- {
- if( WindowType::HELPTEXTWINDOW == pChild->GetType() )
- {
- role = ATK_ROLE_TOOL_TIP;
- pChild->SetAccessibleRole( AccessibleRole::LABEL );
- accessible->name = g_strdup( OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
- }
- else if ( pWindow->GetType() == WindowType::BORDERWINDOW && pChild->GetType() == WindowType::FLOATINGWINDOW )
- {
- PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
- if (p && p->IsPopupMenu() && p->GetMenuStackLevel() == 0)
- {
- // This is a top-level menu popup. Register it.
- role = ATK_ROLE_POPUP_MENU;
- pChild->SetAccessibleRole( AccessibleRole::POPUP_MENU );
- accessible->name = g_strdup( OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
- }
- }
- }
- break;
- }
- }
-
- accessible->role = role;
-}
-
-/*****************************************************************************/
-
-static gboolean
-ooo_window_wrapper_clear_focus(gpointer)
-{
- SolarMutexGuard aGuard;
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- atk_focus_tracker_notify( nullptr );
- SAL_WNODEPRECATED_DECLARATIONS_POP
- return false;
-}
-
-/*****************************************************************************/
-
-static gboolean
-ooo_window_wrapper_real_focus_gtk (GtkWidget *, GdkEventFocus *)
-{
- g_idle_add( ooo_window_wrapper_clear_focus, nullptr );
- return false;
-}
-
-static gboolean ooo_tooltip_map( GtkWidget* pToolTip, gpointer )
-{
- AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
- if( pAccessible )
- atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, TRUE );
- return FALSE;
-}
-
-static gboolean ooo_tooltip_unmap( GtkWidget* pToolTip, gpointer )
-{
- AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
- if( pAccessible )
- atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, FALSE );
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static bool
-isChildPopupMenu(vcl::Window* pWindow)
-{
- vcl::Window* pChild = pWindow->GetAccessibleChildWindow(0);
- if (!pChild)
- return false;
-
- if (WindowType::FLOATINGWINDOW != pChild->GetType())
- return false;
-
- PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
- if (!p)
- return false;
-
- return p->IsPopupMenu();
-}
-
-static void
-ooo_window_wrapper_real_initialize(AtkObject *obj, gpointer data)
-{
- window_real_initialize(obj, data);
-
- GtkSalFrame *pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( data ) );
- if( pFrame )
- {
- vcl::Window *pWindow = pFrame->GetWindow();
- if( pWindow )
- {
- init_from_window( obj, pWindow );
-
- Reference< XAccessible > xAccessible( pWindow->GetAccessible() );
-
- /* We need the wrapper object for the top-level XAccessible to be
- * in the wrapper registry when atk traverses the hierarchy up on
- * focus events
- */
- if( WindowType::BORDERWINDOW == pWindow->GetType() )
- {
- if ( isChildPopupMenu(pWindow) )
- {
- AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
- ooo_wrapper_registry_add( xAccessible, child );
- }
- else
- {
- ooo_wrapper_registry_add( xAccessible, obj );
- g_object_set_data( G_OBJECT(obj), "ooo:atk-wrapper-key", xAccessible.get() );
- }
- }
- else
- {
- AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
- child->role = ATK_ROLE_FILLER;
- if( (ATK_ROLE_DIALOG == obj->role) || (ATK_ROLE_ALERT == obj->role) )
- child->role = ATK_ROLE_OPTION_PANE;
- ooo_wrapper_registry_add( xAccessible, child );
- }
- }
- }
-
- g_signal_connect_after( GTK_WIDGET( data ), "focus-out-event",
- G_CALLBACK (ooo_window_wrapper_real_focus_gtk),
- nullptr);
-
- if( obj->role == ATK_ROLE_TOOL_TIP )
- {
- g_signal_connect_after( GTK_WIDGET( data ), "map-event",
- G_CALLBACK (ooo_tooltip_map),
- nullptr);
- g_signal_connect_after( GTK_WIDGET( data ), "unmap-event",
- G_CALLBACK (ooo_tooltip_unmap),
- nullptr);
- }
-}
-
-/*****************************************************************************/
-
-static void
-ooo_window_wrapper_real_finalize (GObject *obj)
-{
- ooo_wrapper_registry_remove( static_cast<XAccessible *>(g_object_get_data( obj, "ooo:atk-wrapper-key" )));
- window_real_finalize( obj );
-}
-
-/*****************************************************************************/
-
-static void
-ooo_window_wrapper_class_init (AtkObjectClass *klass, gpointer)
-{
- AtkObjectClass *atk_class;
- GObjectClass *gobject_class;
- gpointer data;
-
- /*
- * Patch the gobject vtable of GailWindow to refer to our instance of
- * "initialize".
- */
-
- data = g_type_class_peek_parent( klass );
- atk_class = ATK_OBJECT_CLASS (data);
-
- window_real_initialize = atk_class->initialize;
- atk_class->initialize = ooo_window_wrapper_real_initialize;
-
- gobject_class = G_OBJECT_CLASS (data);
-
- window_real_finalize = gobject_class->finalize;
- gobject_class->finalize = ooo_window_wrapper_real_finalize;
-}
-
-} // extern "C"
-
-/*****************************************************************************/
-
-GType
-ooo_window_wrapper_get_type()
-{
- static GType type = 0;
-
- if (!type)
- {
- GType parent_type = g_type_from_name( "GailWindow" );
-
- if( ! parent_type )
- {
- SAL_INFO("vcl.a11y", "Unknown type: GailWindow");
- parent_type = ATK_TYPE_OBJECT;
- }
-
- GTypeQuery type_query;
- g_type_query( parent_type, &type_query );
-
- static const GTypeInfo typeInfo =
- {
- static_cast<guint16>(type_query.class_size),
- nullptr,
- nullptr,
- reinterpret_cast<GClassInitFunc>(ooo_window_wrapper_class_init),
- nullptr,
- nullptr,
- static_cast<guint16>(type_query.instance_size),
- 0,
- nullptr,
- nullptr
- } ;
-
- type = g_type_register_static (parent_type, "OOoWindowAtkObject", &typeInfo, GTypeFlags(0)) ;
- }
-
- return type;
-}
-
-void restore_gail_window_vtable()
-{
- AtkObjectClass *atk_class;
- gpointer data;
-
- GType type = g_type_from_name( "GailWindow" );
-
- if( type == G_TYPE_INVALID )
- return;
-
- data = g_type_class_peek( type );
- atk_class = ATK_OBJECT_CLASS (data);
-
- atk_class->initialize = window_real_initialize;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/a11y/atkwrapper.cxx b/vcl/unx/gtk/a11y/atkwrapper.cxx
deleted file mode 100644
index cd439022cf2a..000000000000
--- a/vcl/unx/gtk/a11y/atkwrapper.cxx
+++ /dev/null
@@ -1,959 +0,0 @@
-/* -*- 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 .
- */
-
-#include <com/sun/star/uno/Any.hxx>
-#include <com/sun/star/uno/Type.hxx>
-#include <com/sun/star/uno/Sequence.hxx>
-#include <com/sun/star/accessibility/AccessibleRole.hpp>
-#include <com/sun/star/accessibility/AccessibleRelation.hpp>
-#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
-#include <com/sun/star/accessibility/AccessibleStateType.hpp>
-#include <com/sun/star/accessibility/XAccessible.hpp>
-#include <com/sun/star/accessibility/XAccessibleText.hpp>
-#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
-#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
-#include <com/sun/star/accessibility/XAccessibleValue.hpp>
-#include <com/sun/star/accessibility/XAccessibleAction.hpp>
-#include <com/sun/star/accessibility/XAccessibleContext.hpp>
-#include <com/sun/star/accessibility/XAccessibleContext2.hpp>
-#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
-#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
-#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
-#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
-#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
-#include <com/sun/star/accessibility/XAccessibleTable.hpp>
-#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
-#include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
-#include <com/sun/star/accessibility/XAccessibleImage.hpp>
-#include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
-#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
-#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
-#include <com/sun/star/awt/XExtendedToolkit.hpp>
-#include <com/sun/star/awt/XTopWindow.hpp>
-#include <com/sun/star/awt/XTopWindowListener.hpp>
-#include <com/sun/star/awt/XWindow.hpp>
-#include <com/sun/star/lang/XComponent.hpp>
-#include <com/sun/star/lang/XServiceInfo.hpp>
-#include <com/sun/star/lang/XInitialization.hpp>
-#include <com/sun/star/lang/XMultiServiceFactory.hpp>
-#include <com/sun/star/lang/XSingleServiceFactory.hpp>
-#include <com/sun/star/beans/Property.hpp>
-
-#include <rtl/ref.hxx>
-#include <rtl/strbuf.hxx>
-#include <osl/diagnose.h>
-#include <cppuhelper/factory.hxx>
-#include <cppuhelper/queryinterface.hxx>
-
-#include "atkwrapper.hxx"
-#include "atkregistry.hxx"
-#include "atklistener.hxx"
-#include "atktextattributes.hxx"
-
-#include <string.h>
-#include <vector>
-
-using namespace ::com::sun::star;
-
-static GObjectClass *parent_class = nullptr;
-
-static AtkRelationType mapRelationType( sal_Int16 nRelation )
-{
- AtkRelationType type = ATK_RELATION_NULL;
-
- switch( nRelation )
- {
- case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
- type = ATK_RELATION_FLOWS_FROM;
- break;
-
- case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
- type = ATK_RELATION_FLOWS_TO;
- break;
-
- case accessibility::AccessibleRelationType::CONTROLLED_BY:
- type = ATK_RELATION_CONTROLLED_BY;
- break;
-
- case accessibility::AccessibleRelationType::CONTROLLER_FOR:
- type = ATK_RELATION_CONTROLLER_FOR;
- break;
-
- case accessibility::AccessibleRelationType::LABEL_FOR:
- type = ATK_RELATION_LABEL_FOR;
- break;
-
- case accessibility::AccessibleRelationType::LABELED_BY:
- type = ATK_RELATION_LABELLED_BY;
- break;
-
- case accessibility::AccessibleRelationType::MEMBER_OF:
- type = ATK_RELATION_MEMBER_OF;
- break;
-
- case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
- type = ATK_RELATION_SUBWINDOW_OF;
- break;
-
- case accessibility::AccessibleRelationType::NODE_CHILD_OF:
- type = ATK_RELATION_NODE_CHILD_OF;
- break;
-
- default:
- break;
- }
-
- return type;
-}
-
-AtkStateType mapAtkState( sal_Int16 nState )
-{
- AtkStateType type = ATK_STATE_INVALID;
-
- // A perfect / complete mapping ...
- switch( nState )
- {
-#define MAP_DIRECT( a ) \
- case accessibility::AccessibleStateType::a: \
- type = ATK_STATE_##a; break
-
- MAP_DIRECT( INVALID );
- MAP_DIRECT( ACTIVE );
- MAP_DIRECT( ARMED );
- MAP_DIRECT( BUSY );
- MAP_DIRECT( CHECKED );
- MAP_DIRECT( EDITABLE );
- MAP_DIRECT( ENABLED );
- MAP_DIRECT( EXPANDABLE );
- MAP_DIRECT( EXPANDED );
- MAP_DIRECT( FOCUSABLE );
- MAP_DIRECT( FOCUSED );
- MAP_DIRECT( HORIZONTAL );
- MAP_DIRECT( ICONIFIED );
- MAP_DIRECT( INDETERMINATE );
- MAP_DIRECT( MANAGES_DESCENDANTS );
- MAP_DIRECT( MODAL );
- MAP_DIRECT( MULTI_LINE );
- MAP_DIRECT( OPAQUE );
- MAP_DIRECT( PRESSED );
- MAP_DIRECT( RESIZABLE );
- MAP_DIRECT( SELECTABLE );
- MAP_DIRECT( SELECTED );
- MAP_DIRECT( SENSITIVE );
- MAP_DIRECT( SHOWING );
- MAP_DIRECT( SINGLE_LINE );
- MAP_DIRECT( STALE );
- MAP_DIRECT( TRANSIENT );
- MAP_DIRECT( VERTICAL );
- MAP_DIRECT( VISIBLE );
- MAP_DIRECT( DEFAULT );
- // a spelling error ...
- case accessibility::AccessibleStateType::DEFUNC:
- type = ATK_STATE_DEFUNCT; break;
- case accessibility::AccessibleStateType::MULTI_SELECTABLE:
- type = ATK_STATE_MULTISELECTABLE; break;
- default:
- //Mis-use ATK_STATE_LAST_DEFINED to check if a state is unmapped
- //NOTE! Do not report it
- type = ATK_STATE_LAST_DEFINED;
- break;
- }
-
- return type;
-}
-
-static AtkRole getRoleForName( const gchar * name )
-{
- AtkRole ret = atk_role_for_name( name );
- if( ATK_ROLE_INVALID == ret )
- {
- // this should only happen in old ATK versions
- SAL_WNODEPRECATED_DECLARATIONS_PUSH
- ret = atk_role_register( name );
- SAL_WNODEPRECATED_DECLARATIONS_POP
- }
-
- return ret;
-}
-
-static AtkRole mapToAtkRole( sal_Int16 nRole )
-{
- AtkRole role = ATK_ROLE_UNKNOWN;
-
- static AtkRole roleMap[] = {
- ATK_ROLE_UNKNOWN,
- ATK_ROLE_ALERT,
- ATK_ROLE_COLUMN_HEADER,
- ATK_ROLE_CANVAS,
- ATK_ROLE_CHECK_BOX,
- ATK_ROLE_CHECK_MENU_ITEM,
- ATK_ROLE_COLOR_CHOOSER,
- ATK_ROLE_COMBO_BOX,
- ATK_ROLE_DATE_EDITOR,
- ATK_ROLE_DESKTOP_ICON,
- ATK_ROLE_DESKTOP_FRAME, // ? pane
- ATK_ROLE_DIRECTORY_PANE,
- ATK_ROLE_DIALOG,
- ATK_ROLE_UNKNOWN, // DOCUMENT - registered below
- ATK_ROLE_UNKNOWN, // EMBEDDED_OBJECT - registered below
- ATK_ROLE_UNKNOWN, // END_NOTE - registered below
- ATK_ROLE_FILE_CHOOSER,
- ATK_ROLE_FILLER,
- ATK_ROLE_FONT_CHOOSER,
- ATK_ROLE_FOOTER,
- ATK_ROLE_UNKNOWN, // FOOTNOTE - registered below
- ATK_ROLE_FRAME,
- ATK_ROLE_GLASS_PANE,
- ATK_ROLE_IMAGE, // GRAPHIC
- ATK_ROLE_UNKNOWN, // GROUP_BOX - registered below
- ATK_ROLE_HEADER,
- ATK_ROLE_HEADING,
- ATK_ROLE_TEXT, // HYPER_LINK - registered below
- ATK_ROLE_ICON,
- ATK_ROLE_INTERNAL_FRAME,
- ATK_ROLE_LABEL,
- ATK_ROLE_LAYERED_PANE,
- ATK_ROLE_LIST,
- ATK_ROLE_LIST_ITEM,
- ATK_ROLE_MENU,
- ATK_ROLE_MENU_BAR,
- ATK_ROLE_MENU_ITEM,
- ATK_ROLE_OPTION_PANE,
- ATK_ROLE_PAGE_TAB,
- ATK_ROLE_PAGE_TAB_LIST,
- ATK_ROLE_PANEL,
- ATK_ROLE_PARAGRAPH,
- ATK_ROLE_PASSWORD_TEXT,
- ATK_ROLE_POPUP_MENU,
- ATK_ROLE_PUSH_BUTTON,
- ATK_ROLE_PROGRESS_BAR,
- ATK_ROLE_RADIO_BUTTON,
- ATK_ROLE_RADIO_MENU_ITEM,
- ATK_ROLE_ROW_HEADER,
- ATK_ROLE_ROOT_PANE,
- ATK_ROLE_SCROLL_BAR,
- ATK_ROLE_SCROLL_PANE,
- ATK_ROLE_PANEL, // SHAPE
- ATK_ROLE_SEPARATOR,
- ATK_ROLE_SLIDER,
- ATK_ROLE_SPIN_BUTTON, // SPIN_BOX ?
- ATK_ROLE_SPLIT_PANE,
- ATK_ROLE_STATUSBAR,
- ATK_ROLE_TABLE,
- ATK_ROLE_TABLE_CELL,
- ATK_ROLE_TEXT,
- ATK_ROLE_PANEL, // TEXT_FRAME
- ATK_ROLE_TOGGLE_BUTTON,
- ATK_ROLE_TOOL_BAR,
- ATK_ROLE_TOOL_TIP,
- ATK_ROLE_TREE,
- ATK_ROLE_VIEWPORT,
- ATK_ROLE_WINDOW,
- ATK_ROLE_PUSH_BUTTON, // BUTTON_DROPDOWN
- ATK_ROLE_PUSH_BUTTON, // BUTTON_MENU
- ATK_ROLE_UNKNOWN, // CAPTION - registered below
- ATK_ROLE_UNKNOWN, // CHART - registered below
- ATK_ROLE_UNKNOWN, // EDIT_BAR - registered below
- ATK_ROLE_UNKNOWN, // FORM - registered below
- ATK_ROLE_UNKNOWN, // IMAGE_MAP - registered below
- ATK_ROLE_UNKNOWN, // NOTE - registered below
- ATK_ROLE_UNKNOWN, // PAGE - registered below
- ATK_ROLE_RULER,
- ATK_ROLE_UNKNOWN, // SECTION - registered below
- ATK_ROLE_UNKNOWN, // TREE_ITEM - registered below
- ATK_ROLE_TREE_TABLE,
- ATK_ROLE_SCROLL_PANE, // COMMENT - mapped to atk_role_scroll_pane
- ATK_ROLE_UNKNOWN // COMMENT_END - mapped to atk_role_unknown
-#if defined(ATK_CHECK_VERSION)
- //older ver that doesn't define ATK_CHECK_VERSION doesn't have the following
- , ATK_ROLE_DOCUMENT_PRESENTATION
- , ATK_ROLE_DOCUMENT_SPREADSHEET
- , ATK_ROLE_DOCUMENT_TEXT
-#if ATK_CHECK_VERSION(2,15,2)
- , ATK_ROLE_STATIC
-#else
- , ATK_ROLE_LABEL
-#endif
-#else
- //older version should fallback to DOCUMENT_FRAME role
- , ATK_ROLE_DOCUMENT_FRAME
- , ATK_ROLE_DOCUMENT_FRAME
- , ATK_ROLE_DOCUMENT_FRAME
- , ATK_ROLE_LABEL
-#endif
- };
-
- static bool initialized = false;
-
- if( ! initialized )
- {
- // the accessible roles below were added to ATK in later versions,
- // with role_for_name we will know if they exist in runtime.
- roleMap[accessibility::AccessibleRole::EDIT_BAR] = getRoleForName("edit bar");
- roleMap[accessibility::AccessibleRole::EMBEDDED_OBJECT] = getRoleForName("embedded");
- roleMap[accessibility::AccessibleRole::CHART] = getRoleForName("chart");
- roleMap[accessibility::AccessibleRole::CAPTION] = getRoleForName("caption");
- roleMap[accessibility::AccessibleRole::DOCUMENT] = getRoleForName("document frame");
- roleMap[accessibility::AccessibleRole::PAGE] = getRoleForName("page");
- roleMap[accessibility::AccessibleRole::SECTION] = getRoleForName("section");
- roleMap[accessibility::AccessibleRole::FORM] = getRoleForName("form");
- roleMap[accessibility::AccessibleRole::GROUP_BOX] = getRoleForName("grouping");
- roleMap[accessibility::AccessibleRole::COMMENT] = getRoleForName("comment");
- roleMap[accessibility::AccessibleRole::IMAGE_MAP] = getRoleForName("image map");
- roleMap[accessibility::AccessibleRole::TREE_ITEM] = getRoleForName("tree item");
- roleMap[accessibility::AccessibleRole::HYPER_LINK] = getRoleForName("link");
- roleMap[accessibility::AccessibleRole::END_NOTE] = getRoleForName("footnote");
- roleMap[accessibility::AccessibleRole::FOOTNOTE] = getRoleForName("footnote");
- roleMap[accessibility::AccessibleRole::NOTE] = getRoleForName("comment");
-
- initialized = true;
- }
-
- static const sal_Int32 nMapSize = SAL_N_ELEMENTS(roleMap);
- if( 0 <= nRole && nMapSize > nRole )
- role = roleMap[nRole];
-
- return role;
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-/*****************************************************************************/
-
-static const gchar*
-wrapper_get_name( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
-
- if( obj->mpContext.is() )
- {
- try {
- OString aName =
- OUStringToOString(
- obj->mpContext->getAccessibleName(),
- RTL_TEXTENCODING_UTF8);
-
- int nCmp = atk_obj->name ? rtl_str_compare( atk_obj->name, aName.getStr() ) : -1;
- if( nCmp != 0 )
- {
- if( atk_obj->name )
- g_free(atk_obj->name);
- atk_obj->name = g_strdup(aName.getStr());
- }
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleName()" );
- }
- }
-
- return ATK_OBJECT_CLASS (parent_class)->get_name(atk_obj);
-}
-
-/*****************************************************************************/
-
-static const gchar*
-wrapper_get_description( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
-
- if( obj->mpContext.is() )
- {
- try {
- OString aDescription =
- OUStringToOString(
- obj->mpContext->getAccessibleDescription(),
- RTL_TEXTENCODING_UTF8);
-
- g_free(atk_obj->description);
- atk_obj->description = g_strdup(aDescription.getStr());
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleDescription()" );
- }
- }
-
- return ATK_OBJECT_CLASS (parent_class)->get_description(atk_obj);
-
-}
-
-/*****************************************************************************/
-
-static AtkAttributeSet *
-wrapper_get_attributes( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER( atk_obj );
- AtkAttributeSet *pSet = nullptr;
-
- try
- {
- uno::Reference< accessibility::XAccessibleExtendedAttributes >
- xExtendedAttrs( obj->mpContext, uno::UNO_QUERY );
- if( xExtendedAttrs.is() )
- pSet = attribute_set_new_from_extended_attributes( xExtendedAttrs );
- }
- catch(const uno::Exception&)
- {
- g_warning( "Exception in getAccessibleAttributes()" );
- }
-
- return pSet;
-}
-
-/*****************************************************************************/
-
-static gint
-wrapper_get_n_children( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
- gint n = 0;
-
- if( obj->mpContext.is() )
- {
- try {
- n = obj->mpContext->getAccessibleChildCount();
- }
- catch(const uno::Exception&) {
- OSL_FAIL("Exception in getAccessibleChildCount()" );
- }
- }
-
- return n;
-}
-
-/*****************************************************************************/
-
-static AtkObject *
-wrapper_ref_child( AtkObject *atk_obj,
- gint i )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
- AtkObject* child = nullptr;
-
- // see comments above atk_object_wrapper_remove_child
- if( -1 < i && obj->index_of_child_about_to_be_removed == i )
- {
- g_object_ref( obj->child_about_to_be_removed );
- return obj->child_about_to_be_removed;
- }
-
- if( obj->mpContext.is() )
- {
- try {
- uno::Reference< accessibility::XAccessible > xAccessible =
- obj->mpContext->getAccessibleChild( i );
-
- child = atk_object_wrapper_ref( xAccessible );
- }
- catch(const uno::Exception&) {
- OSL_FAIL("Exception in getAccessibleChild");
- }
- }
-
- return child;
-}
-
-/*****************************************************************************/
-
-static gint
-wrapper_get_index_in_parent( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
-
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
- if (obj->mpOrig)
- return atk_object_get_index_in_parent(obj->mpOrig);
-
- gint i = -1;
-
- if( obj->mpContext.is() )
- {
- try {
- i = obj->mpContext->getAccessibleIndexInParent();
- }
- catch(const uno::Exception&) {
- g_warning( "Exception in getAccessibleIndexInParent()" );
- }
- }
- return i;
-}
-
-/*****************************************************************************/
-
-AtkRelation*
-atk_object_wrapper_relation_new(const accessibility::AccessibleRelation& rRelation)
-{
- sal_uInt32 nTargetCount = rRelation.TargetSet.getLength();
-
- std::vector<AtkObject*> aTargets;
-
- for (const auto& rTarget : rRelation.TargetSet)
- {
- uno::Reference< accessibility::XAccessible > xAccessible( rTarget, uno::UNO_QUERY );
- aTargets.push_back(atk_object_wrapper_ref(xAccessible));
- }
-
- AtkRelation *pRel =
- atk_relation_new(
- aTargets.data(), nTargetCount,
- mapRelationType( rRelation.RelationType )
- );
-
- return pRel;
-}
-
-static AtkRelationSet *
-wrapper_ref_relation_set( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
-
- //if we're a native GtkDrawingArea with custom a11y, use the default toolkit relation set impl
- if (obj->mpOrig)
- return atk_object_ref_relation_set(obj->mpOrig);
-
- AtkRelationSet *pSet = atk_relation_set_new();
-
- if( obj->mpContext.is() )
- {
- try {
- uno::Reference< accessibility::XAccessibleRelationSet > xRelationSet(
- obj->mpContext->getAccessibleRelationSet()
- );
-
- sal_Int32 nRelations = xRelationSet.is() ? xRelationSet->getRelationCount() : 0;
- for( sal_Int32 n = 0; n < nRelations; n++ )
- {
- AtkRelation *pRel = atk_object_wrapper_relation_new(xRelationSet->getRelation(n));
- atk_relation_set_add(pSet, pRel);
- g_object_unref(pRel);
- }
- }
- catch(const uno::Exception &) {
- g_object_unref( G_OBJECT( pSet ) );
- pSet = nullptr;
- }
- }
-
- return pSet;
-}
-
-static AtkStateSet *
-wrapper_ref_state_set( AtkObject *atk_obj )
-{
- AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
- AtkStateSet *pSet = atk_state_set_new();
-
- if( obj->mpContext.is() )
- {
- try {
- uno::Reference< accessibility::XAccessibleStateSet > xStateSet(
- obj->mpContext->getAccessibleStateSet());
-
- if( xStateSet.is() )
- {
- uno::Sequence< sal_Int16 > aStates = xStateSet->getStates();
-
- for( const auto nState : aStates )
- {
- // ATK_STATE_LAST_DEFINED is used to check if the state
- // is unmapped, do not report it to Atk
- if ( mapAtkState( nState ) != ATK_STATE_LAST_DEFINED )
- atk_state_set_add_state( pSet, mapAtkState( nState ) );
- }
-
- // We need to emulate FOCUS state for menus, menu-items etc.
- if( atk_obj == atk_get_focus_object() )
- atk_state_set_add_state( pSet, ATK_STATE_FOCUSED );
-/* FIXME - should we do this ?
- else
- atk_state_set_remove_state( pSet, ATK_STATE_FOCUSED );
-*/
- }
- }
-
- catch(const uno::Exception &) {
- g_warning( "Exception in wrapper_ref_state_set" );
- atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
- }
- }
- else
- atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
-
- return pSet;
-}
-
-/*****************************************************************************/
-
-static void
-atk_object_wrapper_finalize (GObject *obj)
-{
- AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER (obj);
-
- if( pWrap->mpAccessible.is() )
- {
- ooo_wrapper_registry_remove( pWrap->mpAccessible );
- pWrap->mpAccessible.clear();
- }
-
- atk_object_wrapper_dispose( pWrap );
-
- parent_class->finalize( obj );
-}
-
-static void
-atk_object_wrapper_class_init (AtkObjectWrapperClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
- AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
-
- parent_class = static_cast<GObjectClass *>(g_type_class_peek_parent (klass));
-
- // GObject methods
- gobject_class->finalize = atk_object_wrapper_finalize;
-
- // AtkObject methods
- atk_class->get_name = wrapper_get_name;
- atk_class->get_description = wrapper_get_description;
- atk_class->get_attributes = wrapper_get_attributes;
- atk_class->get_n_children = wrapper_get_n_children;
- atk_class->ref_child = wrapper_ref_child;
- atk_class->get_index_in_parent = wrapper_get_index_in_parent;
- atk_class->ref_relation_set = wrapper_ref_relation_set;
- atk_class->ref_state_set = wrapper_ref_state_set;
-}
-
-static void
-atk_object_wrapper_init (AtkObjectWrapper *wrapper,
- AtkObjectWrapperClass*)
-{
- wrapper->mpAction = nullptr;
- wrapper->mpComponent = nullptr;
- wrapper->mpEditableText = nullptr;
- wrapper->mpHypertext = nullptr;
- wrapper->mpImage = nullptr;
- wrapper->mpSelection = nullptr;
- wrapper->mpTable = nullptr;
- wrapper->mpText = nullptr;
- wrapper->mpValue = nullptr;
-}
-
-} // extern "C"
-
-GType
-atk_object_wrapper_get_type()
-{
- static GType type = 0;
-
- if (!type)
- {
- static const GTypeInfo typeInfo =
- {
- sizeof (AtkObjectWrapperClass),
- nullptr,
- nullptr,
- reinterpret_cast<GClassInitFunc>(atk_object_wrapper_class_init),
- nullptr,
- nullptr,
- sizeof (AtkObjectWrapper),
- 0,
- reinterpret_cast<GInstanceInitFunc>(atk_object_wrapper_init),
- nullptr
- } ;
- type = g_type_register_static (ATK_TYPE_OBJECT,
- "OOoAtkObj",
- &typeInfo, GTypeFlags(0)) ;
- }
- return type;
-}
-
-static bool
-isOfType( uno::XInterface *pInterface, const uno::Type & rType )
-{
- g_return_val_if_fail( pInterface != nullptr, false );
-
- bool bIs = false;
- try {
- uno::Any aRet = pInterface->queryInterface( rType );
-
- bIs = ( ( typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass ) &&
- ( aRet.pReserved != nullptr ) );
- } catch( const uno::Exception &) { }
-
- return bIs;
-}
-
-extern "C" {
-typedef GType (* GetGIfaceType ) ();
-}
-const struct {
- const char *name;
- GInterfaceInitFunc const aInit;
- GetGIfaceType const aGetGIfaceType;
- const uno::Type & (*aGetUnoType) ();
-} aTypeTable[] = {
-// re-location heaven:
- {
- "Comp", reinterpret_cast<GInterfaceInitFunc>(componentIfaceInit),
- atk_component_get_type,
- cppu::UnoType<accessibility::XAccessibleComponent>::get
- },
- {
- "Act", reinterpret_cast<GInterfaceInitFunc>(actionIfaceInit),
- atk_action_get_type,
- cppu::UnoType<accessibility::XAccessibleAction>::get
- },
- {
- "Txt", reinterpret_cast<GInterfaceInitFunc>(textIfaceInit),
- atk_text_get_type,
- cppu::UnoType<accessibility::XAccessibleText>::get
- },
- {
- "Val", reinterpret_cast<GInterfaceInitFunc>(valueIfaceInit),
- atk_value_get_type,
- cppu::UnoType<accessibility::XAccessibleValue>::get
- },
- {
- "Tab", reinterpret_cast<GInterfaceInitFunc>(tableIfaceInit),
- atk_table_get_type,
- cppu::UnoType<accessibility::XAccessibleTable>::get
- },
- {
- "Edt", reinterpret_cast<GInterfaceInitFunc>(editableTextIfaceInit),
- atk_editable_text_get_type,
- cppu::UnoType<accessibility::XAccessibleEditableText>::get
- },
- {
- "Img", reinterpret_cast<GInterfaceInitFunc>(imageIfaceInit),
- atk_image_get_type,
- cppu::UnoType<accessibility::XAccessibleImage>::get
- },
- {
- "Hyp", reinterpret_cast<GInterfaceInitFunc>(hypertextIfaceInit),
- atk_hypertext_get_type,
- cppu::UnoType<accessibility::XAccessibleHypertext>::get
- },
- {
- "Sel", reinterpret_cast<GInterfaceInitFunc>(selectionIfaceInit),
- atk_selection_get_type,
- cppu::UnoType<accessibility::XAccessibleSelection>::get
- }
- // AtkDocument is a nastily broken interface (so far)
- // we could impl. get_document_type perhaps though.
-};
-
-const int aTypeTableSize = G_N_ELEMENTS( aTypeTable );
-
-static GType
-ensureTypeFor( uno::XInterface *pAccessible )
-{
- int i;
- bool bTypes[ aTypeTableSize ] = { false, };
- OStringBuffer aTypeNameBuf( "OOoAtkObj" );
-
- for( i = 0; i < aTypeTableSize; i++ )
- {
- if( isOfType( pAccessible, aTypeTable[i].aGetUnoType() ) )
- {
- aTypeNameBuf.append(aTypeTable[i].name);
- bTypes[i] = true;
- }
- }
-
- OString aTypeName = aTypeNameBuf.makeStringAndClear();
- GType nType = g_type_from_name( aTypeName.getStr() );
- if( nType == G_TYPE_INVALID )
- {
- GTypeInfo aTypeInfo = {
- sizeof( AtkObjectWrapperClass ),
- nullptr, nullptr, nullptr, nullptr, nullptr,
- sizeof( AtkObjectWrapper ),
- 0, nullptr, nullptr
- } ;
- nType = g_type_register_static( ATK_TYPE_OBJECT_WRAPPER,
- aTypeName.getStr(), &aTypeInfo,
- GTypeFlags(0) ) ;
-
- for( int j = 0; j < aTypeTableSize; j++ )
- if( bTypes[j] )
- {
- GInterfaceInfo aIfaceInfo = { nullptr, nullptr, nullptr };
- aIfaceInfo.interface_init = aTypeTable[j].aInit;
- g_type_add_interface_static (nType, aTypeTable[j].aGetGIfaceType(),
- &aIfaceInfo);
- }
- }
- return nType;
-}
-
-AtkObject *
-atk_object_wrapper_ref( const uno::Reference< accessibility::XAccessible > &rxAccessible, bool create )
-{
- g_return_val_if_fail( rxAccessible.get() != nullptr, nullptr );
-
- AtkObject *obj = ooo_wrapper_registry_get(rxAccessible);
- if( obj )
- {
- g_object_ref( obj );
- return obj;
- }
-
- if( create )
- return atk_object_wrapper_new( rxAccessible );
-
- return nullptr;
-}
-
-AtkObject *
-atk_object_wrapper_new( const css::uno::Reference< css::accessibility::XAccessible >& rxAccessible,
- AtkObject* parent, AtkObject* orig )
-{
- g_return_val_if_fail( rxAccessible.get() != nullptr, nullptr );
-
- AtkObjectWrapper *pWrap = nullptr;
-
- try {
- uno::Reference< accessibility::XAccessibleContext > xContext(rxAccessible->getAccessibleContext());
-
- g_return_val_if_fail( xContext.get() != nullptr, nullptr );
-
- GType nType = ensureTypeFor( xContext.get() );
- gpointer obj = g_object_new( nType, nullptr);
-
- pWrap = ATK_OBJECT_WRAPPER( obj );
- pWrap->mpAccessible = rxAccessible;
-
- pWrap->index_of_child_about_to_be_removed = -1;
- pWrap->child_about_to_be_removed = nullptr;
-
- pWrap->mpContext = xContext;
- pWrap->mpOrig = orig;
-
- AtkObject* atk_obj = ATK_OBJECT(pWrap);
- atk_obj->role = mapToAtkRole( xContext->getAccessibleRole() );
- atk_obj->accessible_parent = parent;
-
- ooo_wrapper_registry_add( rxAccessible, atk_obj );
-
- if( parent )
- g_object_ref( atk_obj->accessible_parent );
- else
- {
- /* gail_focus_tracker remembers the focused object at the first
- * parent in the hierarchy that is a Gtk+ widget, but at the time the
- * event gets processed (at idle), it may be too late to create the
- * hierarchy, so doing it now ..
- */
- uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
-
- if( xParent.is() )
- atk_obj->accessible_parent = atk_object_wrapper_ref( xParent );
- }
-
- // Attach a listener to the UNO object if it's not TRANSIENT
- uno::Reference< accessibility::XAccessibleStateSet > xStateSet( xContext->getAccessibleStateSet() );
- if( xStateSet.is() && ! xStateSet->contains( accessibility::AccessibleStateType::TRANSIENT ) )
- {
- uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
- if( xBroadcaster.is() )
- {
- uno::Reference<accessibility::XAccessibleEventListener> xListener(new AtkListener(pWrap));
- xBroadcaster->addAccessibleEventListener(xListener);
- }
- else
- OSL_ASSERT( false );
- }
-
-#if ATK_CHECK_VERSION(2,33,1)
- {
- css::uno::Reference<css::accessibility::XAccessibleContext2> xContext2(xContext, css::uno::UNO_QUERY);
- if( xContext2.is() )
- {
- OString aId = OUStringToOString( xContext2->getAccessibleId(), RTL_TEXTENCODING_UTF8);
- atk_object_set_accessible_id(atk_obj, aId.getStr());
- }
- }
-#endif
-
- return ATK_OBJECT( pWrap );
- }
- catch (const uno::Exception &)
- {
- if( pWrap )
- g_object_unref( pWrap );
-
- return nullptr;
- }
-}
-
-/*****************************************************************************/
-
-void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
-{
- AtkObject *atk_obj = ATK_OBJECT( wrapper );
-
- atk_object_set_parent( child, atk_obj );
- g_signal_emit_by_name( atk_obj, "children_changed::add", index, child, nullptr );
-}
-
-/*****************************************************************************/
-
-void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
-{
- /*
- * the atk-bridge GTK+ module gets back to the event source to ref the child just
- * vanishing, so we keep this reference because the semantic on OOo side is different.
- */
- wrapper->child_about_to_be_removed = child;
- wrapper->index_of_child_about_to_be_removed = index;
-
- g_signal_emit_by_name( ATK_OBJECT( wrapper ), "children_changed::remove", index, child, nullptr );
-
- wrapper->index_of_child_about_to_be_removed = -1;
- wrapper->child_about_to_be_removed = nullptr;
-}
-
-/*****************************************************************************/
-
-void atk_object_wrapper_set_role(AtkObjectWrapper* wrapper, sal_Int16 role)
-{
- AtkObject *atk_obj = ATK_OBJECT( wrapper );
- atk_object_set_role( atk_obj, mapToAtkRole( role ) );
-}
-
-/*****************************************************************************/
-
-void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
-{
- wrapper->mpContext.clear();
- wrapper->mpAction.clear();
- wrapper->mpComponent.clear();
- wrapper->mpEditableText.clear();
- wrapper->mpHypertext.clear();
- wrapper->mpImage.clear();
- wrapper->mpSelection.clear();
- wrapper->mpMultiLineText.clear();
- wrapper->mpTable.clear();
- wrapper->mpText.clear();
- wrapper->mpTextMarkup.clear();
- wrapper->mpTextAttributes.clear();
- wrapper->mpValue.clear();
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gloactiongroup.cxx b/vcl/unx/gtk/gloactiongroup.cxx
deleted file mode 100644
index 56782e2cd46f..000000000000
--- a/vcl/unx/gtk/gloactiongroup.cxx
+++ /dev/null
@@ -1,398 +0,0 @@
-/* -*- 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/.
- */
-
-#include <unx/gtk/gtksalmenu.hxx>
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-#include <unx/gtk/gloactiongroup.h>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkframe.hxx>
-
-#include <sal/log.hxx>
-
-/*
- * GLOAction
- */
-
-#define G_TYPE_LO_ACTION (g_lo_action_get_type ())
-#define G_LO_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
- G_TYPE_LO_ACTION, GLOAction))
-
-struct GLOAction
-{
- GObject parent_instance;
-
- gint item_id; // Menu item ID.
- gboolean submenu; // TRUE if action is a submenu action.
- gboolean enabled; // TRUE if action is enabled.
- GVariantType* parameter_type; // A GVariantType with the action parameter type.
- GVariantType* state_type; // A GVariantType with item state type
- GVariant* state_hint; // A GVariant with state hints.
- GVariant* state; // A GVariant with current item state
-};
-
-typedef GObjectClass GLOActionClass;
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-G_DEFINE_TYPE (GLOAction, g_lo_action, G_TYPE_OBJECT);
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-static GLOAction*
-g_lo_action_new()
-{
- return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION, nullptr));
-}
-
-static void
-g_lo_action_init (GLOAction *action)
-{
- action->item_id = -1;
- action->submenu = FALSE;
- action->enabled = TRUE;
- action->parameter_type = nullptr;
- action->state_type = nullptr;
- action->state_hint = nullptr;
- action->state = nullptr;
-}
-
-static void
-g_lo_action_finalize (GObject *object)
-{
- GLOAction* action = G_LO_ACTION(object);
-
- if (action->parameter_type)
- g_variant_type_free (action->parameter_type);
-
- if (action->state_type)
- g_variant_type_free (action->state_type);
-
- if (action->state_hint)
- g_variant_unref (action->state_hint);
-
- if (action->state)
- g_variant_unref (action->state);
-
- G_OBJECT_CLASS (g_lo_action_parent_class)->finalize (object);
-}
-
-static void
-g_lo_action_class_init (GLOActionClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- object_class->finalize = g_lo_action_finalize;
-}
-
-/*
- * GLOActionGroup
- */
-
-struct GLOActionGroupPrivate
-{
- GHashTable *table; /* string -> GLOAction */
-};
-
-static void g_lo_action_group_iface_init (GActionGroupInterface *);
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-G_DEFINE_TYPE_WITH_CODE (GLOActionGroup,
- g_lo_action_group, G_TYPE_OBJECT,
- G_ADD_PRIVATE(GLOActionGroup)
- G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
- g_lo_action_group_iface_init));
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-static gchar **
-g_lo_action_group_list_actions (GActionGroup *group)
-{
- GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
- GHashTableIter iter;
- gint n, i = 0;
- gchar **keys;
- gpointer key;
-
- n = g_hash_table_size (loGroup->priv->table);
- keys = g_new (gchar *, n + 1);
-
- g_hash_table_iter_init (&iter, loGroup->priv->table);
- while (g_hash_table_iter_next (&iter, &key, nullptr))
- keys[i++] = g_strdup (static_cast<gchar*>(key));
- g_assert_cmpint (i, ==, n);
- keys[n] = nullptr;
-
- return keys;
-}
-
-static gboolean
-g_lo_action_group_query_action (GActionGroup *group,
- const gchar *action_name,
- gboolean *enabled,
- const GVariantType **parameter_type,
- const GVariantType **state_type,
- GVariant **state_hint,
- GVariant **state)
-{
- //SAL_INFO("vcl.unity", "g_lo_action_group_query_action on " << group);
- GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
- GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
-
- if (action == nullptr)
- return FALSE;
-
- if (enabled)
- {
- *enabled = action->enabled;
- }
-
- if (parameter_type)
- *parameter_type = action->parameter_type;
-
- if (state_type)
- *state_type = action->state_type;
-
- if (state_hint)
- *state_hint = (action->state_hint) ? g_variant_ref (action->state_hint) : nullptr;
-
- if (state)
- *state = (action->state) ? g_variant_ref (action->state) : nullptr;
-
- return TRUE;
-}
-
-static void
-g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
- const gchar *action_name,
- GVariant *state)
-{
- gboolean bState = g_variant_get_boolean (state);
- SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " to " << bState);
-
- if (bState)
- GtkSalMenu::Activate(action_name);
- else
- GtkSalMenu::Deactivate(action_name);
-}
-
-static void
-g_lo_action_group_change_state (GActionGroup *group,
- const gchar *action_name,
- GVariant *value)
-{
- SAL_INFO("vcl.unity", "g_lo_action_group_change_state on " << group );
- g_return_if_fail (value != nullptr);
-
- g_variant_ref_sink (value);
-
- if (action_name != nullptr)
- {
- GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
- GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
-
- if (action != nullptr)
- {
- if (action->submenu)
- g_lo_action_group_perform_submenu_action (lo_group, action_name, value);
- else
- {
- gboolean is_new = FALSE;
-
- /* If action already exists but has no state, it should be removed and added again. */
- if (action->state_type == nullptr)
- {
- g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
- action->state_type = g_variant_type_copy (g_variant_get_type(value));
- is_new = TRUE;
- }
-
- if (g_variant_is_of_type (value, action->state_type))
- {
- if (action->state)
- g_variant_unref(action->state);
-
- action->state = g_variant_ref (value);
-
- if (is_new)
- g_action_group_action_added (G_ACTION_GROUP (group), action_name);
- else
- g_action_group_action_state_changed (group, action_name, value);
- }
- }
- }
- }
-
- g_variant_unref (value);
-}
-
-static void
-g_lo_action_group_activate (GActionGroup *group,
- const gchar *action_name,
- GVariant *parameter)
-{
- if (parameter != nullptr)
- g_action_group_change_action_state(group, action_name, parameter);
- GtkSalMenu::DispatchCommand(action_name);
-}
-
-void
-g_lo_action_group_insert (GLOActionGroup *group,
- const gchar *action_name,
- gint item_id,
- gboolean submenu)
-{
- g_lo_action_group_insert_stateful (group, action_name, item_id, submenu, nullptr, nullptr, nullptr, nullptr);
-}
-
-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)
-{
- g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
-
- GLOAction* old_action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
-
- if (old_action == nullptr || old_action->item_id != item_id)
- {
- if (old_action != nullptr)
- g_lo_action_group_remove (group, action_name);
-
- GLOAction* action = g_lo_action_new();
-
- g_hash_table_insert (group->priv->table, g_strdup (action_name), action);
-
- action->item_id = item_id;
- action->submenu = submenu;
-
- if (parameter_type)
- action->parameter_type = const_cast<GVariantType*>(parameter_type);
-
- if (state_type)
- action->state_type = const_cast<GVariantType*>(state_type);
-
- if (state_hint)
- action->state_hint = g_variant_ref_sink (state_hint);
-
- if (state)
- action->state = g_variant_ref_sink (state);
-
- g_action_group_action_added (G_ACTION_GROUP (group), action_name);
- }
-}
-
-static void
-g_lo_action_group_finalize (GObject *object)
-{
- GLOActionGroup *lo_group = G_LO_ACTION_GROUP (object);
-
- g_hash_table_unref (lo_group->priv->table);
-
- G_OBJECT_CLASS (g_lo_action_group_parent_class)->finalize (object);
-}
-
-static void
-g_lo_action_group_init (GLOActionGroup *group)
-{
- SAL_INFO("vcl.unity", "g_lo_action_group_init on " << group);
- group->priv = static_cast<GLOActionGroupPrivate *>(g_lo_action_group_get_instance_private (group));
- group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-}
-
-static void
-g_lo_action_group_class_init (GLOActionGroupClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = g_lo_action_group_finalize;
-}
-
-static void
-g_lo_action_group_iface_init (GActionGroupInterface *iface)
-{
- iface->list_actions = g_lo_action_group_list_actions;
- iface->query_action = g_lo_action_group_query_action;
- iface->change_action_state = g_lo_action_group_change_state;
- iface->activate_action = g_lo_action_group_activate;
-}
-
-GLOActionGroup *
-g_lo_action_group_new()
-{
- GLOActionGroup* group = G_LO_ACTION_GROUP (g_object_new (G_TYPE_LO_ACTION_GROUP, nullptr));
- return group;
-}
-
-void
-g_lo_action_group_set_action_enabled (GLOActionGroup *group,
- const gchar *action_name,
- gboolean enabled)
-{
- SAL_INFO("vcl.unity", "g_lo_action_group_set_action_enabled on " << group);
- g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
- g_return_if_fail (action_name != nullptr);
-
- GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
-
- if (action == nullptr)
- return;
-
- action->enabled = enabled;
-
- g_action_group_action_enabled_changed (G_ACTION_GROUP (group), action_name, enabled);
-}
-
-void
-g_lo_action_group_remove (GLOActionGroup *group,
- const gchar *action_name)
-{
- SAL_INFO("vcl.unity", "g_lo_action_group_remove on " << group);
- g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
-
- if (action_name != nullptr)
- {
- g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
- g_hash_table_remove (group->priv->table, action_name);
- }
-}
-
-void
-g_lo_action_group_clear (GLOActionGroup *group)
-{
- SAL_INFO("vcl.unity", "g_lo_action_group_clear on " << group);
- g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
-
- GList* keys = g_hash_table_get_keys (group->priv->table);
-
- for (GList* element = g_list_first (keys); element != nullptr; element = g_list_next (element))
- {
- g_lo_action_group_remove (group, static_cast<gchar*>(element->data));
- }
-
- g_list_free (keys);
-}
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/glomenu.cxx b/vcl/unx/gtk/glomenu.cxx
deleted file mode 100644
index 5457ac6eaa05..000000000000
--- a/vcl/unx/gtk/glomenu.cxx
+++ /dev/null
@@ -1,691 +0,0 @@
-/* -*- 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/.
- */
-
-#include <string.h>
-
-#include <unx/gtk/gtksalmenu.hxx>
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-#include <unx/gtk/glomenu.h>
-
-struct GLOMenu
-{
- GMenuModel const parent_instance;
-
- GArray *items;
-};
-
-typedef GMenuModelClass GLOMenuClass;
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-G_DEFINE_TYPE (GLOMenu, g_lo_menu, G_TYPE_MENU_MODEL);
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-struct item
-{
- GHashTable* attributes; // Item attributes.
- GHashTable* links; // Item links.
-};
-
-static void
-g_lo_menu_struct_item_init (struct item *menu_item)
-{
- menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, reinterpret_cast<GDestroyNotify>(g_variant_unref));
- menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-}
-
-/* We treat attribute names the same as GSettings keys:
- * - only lowercase ascii, digits and '-'
- * - must start with lowercase
- * - must not end with '-'
- * - no consecutive '-'
- * - not longer than 1024 chars
- */
-static gboolean
-valid_attribute_name (const gchar *name)
-{
- gint i;
-
- if (!g_ascii_islower (name[0]))
- return FALSE;
-
- for (i = 1; name[i]; i++)
- {
- if (name[i] != '-' &&
- !g_ascii_islower (name[i]) &&
- !g_ascii_isdigit (name[i]))
- return FALSE;
-
- if (name[i] == '-' && name[i + 1] == '-')
- return FALSE;
- }
-
- if (name[i - 1] == '-')
- return FALSE;
-
- if (i > 1024)
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * GLOMenu
- */
-
-static gboolean
-g_lo_menu_is_mutable (GMenuModel*)
-{
- // Menu is always mutable.
- return TRUE;
-}
-
-static gint
-g_lo_menu_get_n_items (GMenuModel *model)
-{
- g_return_val_if_fail (model != nullptr, 0);
- GLOMenu *menu = G_LO_MENU (model);
- g_return_val_if_fail (menu->items != nullptr, 0);
-
- return menu->items->len;
-}
-
-gint
-g_lo_menu_get_n_items_from_section (GLOMenu *menu,
- gint section)
-{
- g_return_val_if_fail (0 <= section && section < static_cast<gint>(menu->items->len), 0);
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_val_if_fail (model != nullptr, 0);
-
- gint length = model->items->len;
-
- g_object_unref (model);
-
- return length;
-}
-
-static void
-g_lo_menu_get_item_attributes (GMenuModel *model,
- gint position,
- GHashTable **table)
-{
- GLOMenu *menu = G_LO_MENU (model);
- *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes);
-}
-
-static void
-g_lo_menu_get_item_links (GMenuModel *model,
- gint position,
- GHashTable **table)
-{
- GLOMenu *menu = G_LO_MENU (model);
- *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links);
-}
-
-void
-g_lo_menu_insert (GLOMenu *menu,
- gint position,
- const gchar *label)
-{
- g_lo_menu_insert_section (menu, position, label, nullptr);
-}
-
-void
-g_lo_menu_insert_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const gchar *label)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
- g_return_if_fail (0 <= section && section < static_cast<gint>(menu->items->len));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- g_lo_menu_insert (model, position, label);
-
- g_object_unref (model);
-}
-
-GLOMenu *
-g_lo_menu_new()
-{
- return G_LO_MENU( g_object_new (G_TYPE_LO_MENU, nullptr) );
-}
-
-static void
-g_lo_menu_set_attribute_value (GLOMenu *menu,
- gint position,
- const gchar *attribute,
- GVariant *value)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
- g_return_if_fail (attribute != nullptr);
- g_return_if_fail (valid_attribute_name (attribute));
-
- if (position >= static_cast<gint>(menu->items->len))
- return;
-
- struct item menu_item = g_array_index (menu->items, struct item, position);
-
- if (value != nullptr)
- g_hash_table_insert (menu_item.attributes, g_strdup (attribute), g_variant_ref_sink (value));
- else
- g_hash_table_remove (menu_item.attributes, attribute);
-}
-
-static GVariant*
-g_lo_menu_get_attribute_value_from_item_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const gchar *attribute,
- const GVariantType *type)
-{
- GMenuModel *model = G_MENU_MODEL (g_lo_menu_get_section (menu, section));
-
- g_return_val_if_fail (model != nullptr, nullptr);
-
- GVariant *value = g_menu_model_get_item_attribute_value (model,
- position,
- attribute,
- type);
-
- g_object_unref (model);
-
- return value;
-}
-
-void
-g_lo_menu_set_label (GLOMenu *menu,
- gint position,
- const gchar *label)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GVariant *value;
-
- if (label != nullptr)
- value = g_variant_new_string (label);
- else
- value = nullptr;
-
- g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_LABEL, value);
-}
-
-void
-g_lo_menu_set_icon (GLOMenu *menu,
- gint position,
- const GIcon *icon)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GVariant *value;
-
- if (icon != nullptr)
- {
-#if GLIB_CHECK_VERSION(2,38,0)
- value = g_icon_serialize (const_cast<GIcon*>(icon));
-#else
- value = nullptr;
-#endif
- }
- else
- value = nullptr;
-
-#ifndef G_MENU_ATTRIBUTE_ICON
-# define G_MENU_ATTRIBUTE_ICON "icon"
-#endif
-
- g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_ICON, value);
- if (value)
- g_variant_unref (value);
-}
-
-void
-g_lo_menu_set_label_to_item_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const gchar *label)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- g_lo_menu_set_label (model, position, label);
-
- // Notify the update.
- g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
-
- g_object_unref (model);
-}
-
-void
-g_lo_menu_set_icon_to_item_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const GIcon *icon)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- g_lo_menu_set_icon (model, position, icon);
-
- // Notify the update.
- g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
-
- g_object_unref (model);
-}
-
-gchar *
-g_lo_menu_get_label_from_item_in_section (GLOMenu *menu,
- gint section,
- gint position)
-{
- g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
-
- GVariant *label_value = g_lo_menu_get_attribute_value_from_item_in_section (menu,
- section,
- position,
- G_MENU_ATTRIBUTE_LABEL,
- G_VARIANT_TYPE_STRING);
-
- gchar *label = nullptr;
-
- if (label_value)
- {
- label = g_variant_dup_string (label_value, nullptr);
- g_variant_unref (label_value);
- }
-
- return label;
-}
-
-void
-g_lo_menu_set_action_and_target_value (GLOMenu *menu,
- gint position,
- const gchar *action,
- GVariant *target_value)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GVariant *action_value;
-
- if (action != nullptr)
- {
- action_value = g_variant_new_string (action);
- }
- else
- {
- action_value = nullptr;
- target_value = nullptr;
- }
-
- g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_ACTION, action_value);
- g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_TARGET, target_value);
- g_lo_menu_set_attribute_value (menu, position, G_LO_MENU_ATTRIBUTE_SUBMENU_ACTION, nullptr);
-
- g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 1);
-}
-
-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)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- g_lo_menu_set_action_and_target_value (model, position, command, target_value);
-
- g_object_unref (model);
-}
-
-void
-g_lo_menu_set_accelerator_to_item_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const gchar *accelerator)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- GVariant *value;
-
- if (accelerator != nullptr)
- value = g_variant_new_string (accelerator);
- else
- value = nullptr;
-
- g_lo_menu_set_attribute_value (model, position, G_LO_MENU_ATTRIBUTE_ACCELERATOR, value);
-
- // Notify the update.
- g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
-
- g_object_unref (model);
-}
-
-gchar *
-g_lo_menu_get_accelerator_from_item_in_section (GLOMenu *menu,
- gint section,
- gint position)
-{
- g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
-
- GVariant *accel_value = g_lo_menu_get_attribute_value_from_item_in_section (menu,
- section,
- position,
- G_LO_MENU_ATTRIBUTE_ACCELERATOR,
- G_VARIANT_TYPE_STRING);
-
- gchar *accel = nullptr;
-
- if (accel_value != nullptr)
- {
- accel = g_variant_dup_string (accel_value, nullptr);
- g_variant_unref (accel_value);
- }
-
- return accel;
-}
-
-void
-g_lo_menu_set_command_to_item_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const gchar *command)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- GVariant *value;
-
- if (command != nullptr)
- value = g_variant_new_string (command);
- else
- value = nullptr;
-
- g_lo_menu_set_attribute_value (model, position, G_LO_MENU_ATTRIBUTE_COMMAND, value);
-
- // Notify the update.
- g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
-
- g_object_unref (model);
-}
-
-gchar *
-g_lo_menu_get_command_from_item_in_section (GLOMenu *menu,
- gint section,
- gint position)
-{
- g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
-
- GVariant *command_value = g_lo_menu_get_attribute_value_from_item_in_section (menu,
- section,
- position,
- G_LO_MENU_ATTRIBUTE_COMMAND,
- G_VARIANT_TYPE_STRING);
-
- gchar *command = nullptr;
-
- if (command_value != nullptr)
- {
- command = g_variant_dup_string (command_value, nullptr);
- g_variant_unref (command_value);
- }
-
- return command;
-}
-
-static void
-g_lo_menu_set_link (GLOMenu *menu,
- gint position,
- const gchar *link,
- GMenuModel *model)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
- g_return_if_fail (link != nullptr);
- g_return_if_fail (valid_attribute_name (link));
-
- if (position < 0 || position >= static_cast<gint>(menu->items->len))
- position = menu->items->len - 1;
-
- struct item menu_item = g_array_index (menu->items, struct item, position);
-
- if (model != nullptr)
- g_hash_table_insert (menu_item.links, g_strdup (link), g_object_ref (model));
- else
- g_hash_table_remove (menu_item.links, link);
-}
-
-void
-g_lo_menu_insert_section (GLOMenu *menu,
- gint position,
- const gchar *label,
- GMenuModel *section)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- if (position < 0 || position > static_cast<gint>(menu->items->len))
- position = menu->items->len;
-
- struct item menu_item;
-
- g_lo_menu_struct_item_init(&menu_item);
-
- g_array_insert_val (menu->items, position, menu_item);
-
- g_lo_menu_set_label (menu, position, label);
- g_lo_menu_set_link (menu, position, G_MENU_LINK_SECTION, section);
-
- g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
-}
-
-void
-g_lo_menu_new_section (GLOMenu *menu,
- gint position,
- const gchar *label)
-{
- GMenuModel *section = G_MENU_MODEL (g_lo_menu_new());
-
- g_lo_menu_insert_section (menu, position, label, section);
-
- g_object_unref (section);
-}
-
-GLOMenu *
-g_lo_menu_get_section (GLOMenu *menu,
- gint section)
-{
- g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
-
- return G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
- ->get_item_link (G_MENU_MODEL (menu), section, G_MENU_LINK_SECTION));
-}
-
-void
-g_lo_menu_new_submenu_in_item_in_section (GLOMenu *menu,
- gint section,
- gint position)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
- g_return_if_fail (0 <= section && section < static_cast<gint>(menu->items->len));
-
- GLOMenu* model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- if (0 <= position && position < static_cast<gint>(model->items->len)) {
- GMenuModel* submenu = G_MENU_MODEL (g_lo_menu_new());
-
- g_lo_menu_set_link (model, position, G_MENU_LINK_SUBMENU, submenu);
-
- g_object_unref (submenu);
-
- g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
-
- g_object_unref (model);
- }
-}
-
-GLOMenu *
-g_lo_menu_get_submenu_from_item_in_section (GLOMenu *menu,
- gint section,
- gint position)
-{
- g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
- g_return_val_if_fail (0 <= section && section < static_cast<gint>(menu->items->len), nullptr);
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_val_if_fail (model != nullptr, nullptr);
-
- GLOMenu *submenu = nullptr;
-
- if (0 <= position && position < static_cast<gint>(model->items->len))
- submenu = G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
- ->get_item_link (G_MENU_MODEL (model), position, G_MENU_LINK_SUBMENU));
- //submenu = g_menu_model_get_item_link (G_MENU_MODEL (model), position, G_MENU_LINK_SUBMENU);
-
- g_object_unref (model);
-
- return submenu;
-}
-
-void
-g_lo_menu_set_submenu_action_to_item_in_section (GLOMenu *menu,
- gint section,
- gint position,
- const gchar *action)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
-
- GMenuModel *model = G_MENU_MODEL (g_lo_menu_get_section (menu, section));
-
- g_return_if_fail (model != nullptr);
-
- GVariant *value;
-
- if (action != nullptr)
- value = g_variant_new_string (action);
- else
- value = nullptr;
-
- g_lo_menu_set_attribute_value (G_LO_MENU (model), position, G_LO_MENU_ATTRIBUTE_SUBMENU_ACTION, value);
-
- // Notify the update.
- g_menu_model_items_changed (model, position, 1, 1);
-
- g_object_unref (model);
-}
-
-static void
-g_lo_menu_clear_item (struct item *menu_item)
-{
- if (menu_item->attributes != nullptr)
- g_hash_table_unref (menu_item->attributes);
- if (menu_item->links != nullptr)
- g_hash_table_unref (menu_item->links);
-}
-
-void
-g_lo_menu_remove (GLOMenu *menu,
- gint position)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
- g_return_if_fail (0 <= position && position < static_cast<gint>(menu->items->len));
-
- g_lo_menu_clear_item (&g_array_index (menu->items, struct item, position));
- g_array_remove_index (menu->items, position);
- g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
-}
-
-void
-g_lo_menu_remove_from_section (GLOMenu *menu,
- gint section,
- gint position)
-{
- g_return_if_fail (G_IS_LO_MENU (menu));
- g_return_if_fail (0 <= section && section < static_cast<gint>(menu->items->len));
-
- GLOMenu *model = g_lo_menu_get_section (menu, section);
-
- g_return_if_fail (model != nullptr);
-
- g_lo_menu_remove (model, position);
-
- g_object_unref (model);
-}
-
-static void
-g_lo_menu_finalize (GObject *object)
-{
- GLOMenu *menu = G_LO_MENU (object);
- struct item *items;
- gint n_items;
- gint i;
-
- n_items = menu->items->len;
- items = reinterpret_cast<struct item *>(g_array_free (menu->items, FALSE));
- for (i = 0; i < n_items; i++)
- g_lo_menu_clear_item (&items[i]);
- g_free (items);
-
- G_OBJECT_CLASS (g_lo_menu_parent_class)
- ->finalize (object);
-}
-
-static void
-g_lo_menu_init (GLOMenu *menu)
-{
- menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
-}
-
-static void
-g_lo_menu_class_init (GLOMenuClass *klass)
-{
- GMenuModelClass *model_class = G_MENU_MODEL_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = g_lo_menu_finalize;
-
- model_class->is_mutable = g_lo_menu_is_mutable;
- model_class->get_n_items = g_lo_menu_get_n_items;
- model_class->get_item_attributes = g_lo_menu_get_item_attributes;
- model_class->get_item_links = g_lo_menu_get_item_links;
-}
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
deleted file mode 100644
index ca7a567f7402..000000000000
--- a/vcl/unx/gtk/gtkdata.cxx
+++ /dev/null
@@ -1,890 +0,0 @@
-/* -*- 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 .
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <errno.h>
-#include <poll.h>
-#if defined(FREEBSD) || defined(NETBSD)
-#include <sys/types.h>
-#include <sys/time.h>
-#endif
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtksalmenu.hxx>
-#include <unx/salobj.h>
-#include <unx/geninst.h>
-#include <osl/thread.h>
-#include <osl/process.h>
-#include <sal/log.hxx>
-
-#include <unx/i18n_im.hxx>
-#include <unx/i18n_xkb.hxx>
-#include <unx/wmadaptor.hxx>
-
-#include <unx/x11_cursors/salcursors.h>
-
-#include <vcl/svapp.hxx>
-#include <chrono>
-
-using namespace vcl_sal;
-
-/***************************************************************
- * class GtkSalDisplay *
- ***************************************************************/
-extern "C" {
-static GdkFilterReturn call_filterGdkEvent( GdkXEvent* sys_event,
- GdkEvent* /*event*/,
- gpointer data )
-{
- GtkSalDisplay *pDisplay = static_cast<GtkSalDisplay *>(data);
- return pDisplay->filterGdkEvent( sys_event );
-}
-}
-
-GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay ) :
- SalDisplay( gdk_x11_display_get_xdisplay( pDisplay ) ),
- m_pSys( GtkSalSystem::GetSingleton() ),
- m_pGdkDisplay( pDisplay ),
- m_bStartupCompleted( false )
-{
- for(GdkCursor* & rpCsr : m_aCursors)
- rpCsr = nullptr;
- m_bUseRandRWrapper = false; // use gdk signal instead
- Init ();
-
- // FIXME: unify this with SalInst's filter too ?
- gdk_window_add_filter( nullptr, call_filterGdkEvent, this );
-
- if ( getenv( "SAL_IGNOREXERRORS" ) )
- GetGenericUnixSalData()->ErrorTrapPush(); // and leak the trap
-
- m_bX11Display = true;
-
- gtk_widget_set_default_direction(AllSettings::GetLayoutRTL() ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
-}
-
-GtkSalDisplay::~GtkSalDisplay()
-{
- gdk_window_remove_filter( nullptr, call_filterGdkEvent, this );
-
- if( !m_bStartupCompleted )
- gdk_notify_startup_complete();
-
- doDestruct();
- pDisp_ = nullptr;
-
- for(GdkCursor* & rpCsr : m_aCursors)
- if( rpCsr )
- gdk_cursor_unref( rpCsr );
-}
-
-extern "C" {
-
-static void signalScreenSizeChanged( GdkScreen* pScreen, gpointer data )
-{
- GtkSalDisplay* pDisp = static_cast<GtkSalDisplay*>(data);
- pDisp->screenSizeChanged( pScreen );
-}
-
-static void signalMonitorsChanged( GdkScreen* pScreen, gpointer data )
-{
- GtkSalDisplay* pDisp = static_cast<GtkSalDisplay*>(data);
- pDisp->monitorsChanged( pScreen );
-}
-
-}
-
-GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event )
-{
- GdkFilterReturn aFilterReturn = GDK_FILTER_CONTINUE;
- XEvent *pEvent = static_cast<XEvent *>(sys_event);
-
- // dispatch all XEvents to event callback
- if( GetSalData()->m_pInstance->
- CallEventCallback( pEvent, sizeof( XEvent ) ) )
- aFilterReturn = GDK_FILTER_REMOVE;
-
- if (GetDisplay() == pEvent->xany.display )
- {
- // #i53471# gtk has no callback mechanism that lets us be notified
- // when settings (as in XSETTING and opposed to styles) are changed.
- // so we need to listen for corresponding property notifications here
- // these should be rare enough so that we can assume that the settings
- // actually change when a corresponding PropertyNotify occurs
- SalFrame *pAnyFrame = anyFrame();
- if( pAnyFrame && pEvent->type == PropertyNotify &&
- pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::XSETTINGS ) )
- {
- PostEvent( pAnyFrame, nullptr, SalEvent::SettingsChanged );
- }
- // let's see if one of our frames wants to swallow these events
- // get the frame
- for (auto pSalFrame : m_aFrames )
- {
- GtkSalFrame* pFrame = static_cast<GtkSalFrame*>( pSalFrame );
- if( pFrame->GetSystemData()->aWindow == pEvent->xany.window ||
- ( pFrame->getForeignParent() && pFrame->getForeignParentWindow() == pEvent->xany.window ) ||
- ( pFrame->getForeignTopLevel() && pFrame->getForeignTopLevelWindow() == pEvent->xany.window )
- )
- {
- if( ! pFrame->Dispatch( pEvent ) )
- aFilterReturn = GDK_FILTER_REMOVE;
- break;
- }
- }
- X11SalObject::Dispatch( pEvent );
- }
-
- return aFilterReturn;
-}
-
-void GtkSalDisplay::screenSizeChanged( GdkScreen const * pScreen )
-{
- m_pSys->countScreenMonitors();
- if (pScreen)
- emitDisplayChanged();
-}
-
-void GtkSalDisplay::monitorsChanged( GdkScreen const * pScreen )
-{
- m_pSys->countScreenMonitors();
- if (pScreen)
- emitDisplayChanged();
-}
-
-SalDisplay::ScreenData *
-GtkSalDisplay::initScreen( SalX11Screen nXScreen ) const
-{
- // choose visual for screen
- ScreenData *pSD;
- if (!(pSD = SalDisplay::initScreen( nXScreen )))
- return nullptr;
-
- // now set a gdk default colormap matching the chosen visual to the screen
- GdkScreen* pScreen = gdk_display_get_screen( m_pGdkDisplay, nXScreen.getXScreen() );
-// should really use this:
-// GdkVisual* pVis = gdk_x11_screen_lookup_visual_get( screen, pSD->m_aVisual.visualid );
-// and not this:
- GdkVisual* pVis = gdkx_visual_get( pSD->m_aVisual.visualid );
- if( pVis )
- {
- GdkColormap* pDefCol = gdk_screen_get_default_colormap( pScreen );
- GdkVisual* pDefVis = gdk_colormap_get_visual( pDefCol );
- if( pDefVis != pVis )
- {
- pDefCol = gdk_x11_colormap_foreign_new( pVis, pSD->m_aColormap.GetXColormap() );
- gdk_screen_set_default_colormap( pScreen, pDefCol );
- SAL_INFO( "vcl.gtk", "set new gdk color map for screen " << nXScreen.getXScreen() );
- }
- }
- else
- SAL_INFO( "vcl.gtk", "not GdkVisual for visual id " << pSD->m_aVisual.visualid );
-
- return pSD;
-}
-
-bool GtkSalDisplay::Dispatch( XEvent* pEvent )
-{
- if( GetDisplay() == pEvent->xany.display )
- {
- // let's see if one of our frames wants to swallow these events
- // get the child frame
- for (auto pSalFrame : m_aFrames )
- {
- if (pSalFrame->GetSystemData()->aWindow == pEvent->xany.window)
- return static_cast<GtkSalFrame*>( pSalFrame )->Dispatch( pEvent );
- }
- }
-
- return false;
-}
-
-GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
- const unsigned char *pMask,
- int nWidth, int nHeight,
- int nXHot, int nYHot )
-{
- GdkScreen *pScreen = gdk_display_get_default_screen( m_pGdkDisplay );
- GdkDrawable *pDrawable = GDK_DRAWABLE( gdk_screen_get_root_window (pScreen) );
- GdkBitmap *pBitmapPix = gdk_bitmap_create_from_data
- ( pDrawable, reinterpret_cast<const char*>(pBitmap), nWidth, nHeight );
- GdkBitmap *pMaskPix = gdk_bitmap_create_from_data
- ( pDrawable, reinterpret_cast<const char*>(pMask), nWidth, nHeight );
- GdkColormap *pColormap = gdk_drawable_get_colormap( pDrawable );
-
- GdkColor aWhite = { 0, 0xffff, 0xffff, 0xffff };
- GdkColor aBlack = { 0, 0, 0, 0 };
-
- gdk_colormap_alloc_color( pColormap, &aBlack, FALSE, TRUE);
- gdk_colormap_alloc_color( pColormap, &aWhite, FALSE, TRUE);
-
- return gdk_cursor_new_from_pixmap
- ( pBitmapPix, pMaskPix,
- &aBlack, &aWhite, nXHot, nYHot);
-}
-
-static unsigned char nullmask_bits[] = { 0x00, 0x00, 0x00, 0x00 };
-static unsigned char nullcurs_bits[] = { 0x00, 0x00, 0x00, 0x00 };
-
-#define MAKE_CURSOR( vcl_name, name ) \
- case vcl_name: \
- pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
- name##curs_width, name##curs_height, \
- name##curs_x_hot, name##curs_y_hot ); \
- break
-#define MAP_BUILTIN( vcl_name, gdk_name ) \
- case vcl_name: \
- pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, gdk_name ); \
- break
-
-GdkCursor *GtkSalDisplay::getCursor( PointerStyle ePointerStyle )
-{
- if ( !m_aCursors[ ePointerStyle ] )
- {
- GdkCursor *pCursor = nullptr;
-
- switch( ePointerStyle )
- {
- MAP_BUILTIN( PointerStyle::Arrow, GDK_LEFT_PTR );
- MAP_BUILTIN( PointerStyle::Text, GDK_XTERM );
- MAP_BUILTIN( PointerStyle::Help, GDK_QUESTION_ARROW );
- MAP_BUILTIN( PointerStyle::Cross, GDK_CROSSHAIR );
- MAP_BUILTIN( PointerStyle::Wait, GDK_WATCH );
-
- MAP_BUILTIN( PointerStyle::NSize, GDK_SB_V_DOUBLE_ARROW );
- MAP_BUILTIN( PointerStyle::SSize, GDK_SB_V_DOUBLE_ARROW );
- MAP_BUILTIN( PointerStyle::WSize, GDK_SB_H_DOUBLE_ARROW );
- MAP_BUILTIN( PointerStyle::ESize, GDK_SB_H_DOUBLE_ARROW );
-
- MAP_BUILTIN( PointerStyle::NWSize, GDK_TOP_LEFT_CORNER );
- MAP_BUILTIN( PointerStyle::NESize, GDK_TOP_RIGHT_CORNER );
- MAP_BUILTIN( PointerStyle::SWSize, GDK_BOTTOM_LEFT_CORNER );
- MAP_BUILTIN( PointerStyle::SESize, GDK_BOTTOM_RIGHT_CORNER );
-
- MAP_BUILTIN( PointerStyle::WindowNSize, GDK_TOP_SIDE );
- MAP_BUILTIN( PointerStyle::WindowSSize, GDK_BOTTOM_SIDE );
- MAP_BUILTIN( PointerStyle::WindowWSize, GDK_LEFT_SIDE );
- MAP_BUILTIN( PointerStyle::WindowESize, GDK_RIGHT_SIDE );
-
- MAP_BUILTIN( PointerStyle::WindowNWSize, GDK_TOP_LEFT_CORNER );
- MAP_BUILTIN( PointerStyle::WindowNESize, GDK_TOP_RIGHT_CORNER );
- MAP_BUILTIN( PointerStyle::WindowSWSize, GDK_BOTTOM_LEFT_CORNER );
- MAP_BUILTIN( PointerStyle::WindowSESize, GDK_BOTTOM_RIGHT_CORNER );
-
- MAP_BUILTIN( PointerStyle::HSizeBar, GDK_SB_H_DOUBLE_ARROW );
- MAP_BUILTIN( PointerStyle::VSizeBar, GDK_SB_V_DOUBLE_ARROW );
-
- MAP_BUILTIN( PointerStyle::RefHand, GDK_HAND2 );
- MAP_BUILTIN( PointerStyle::Hand, GDK_HAND2 );
- MAP_BUILTIN( PointerStyle::Pen, GDK_PENCIL );
-
- MAP_BUILTIN( PointerStyle::HSplit, GDK_SB_H_DOUBLE_ARROW );
- MAP_BUILTIN( PointerStyle::VSplit, GDK_SB_V_DOUBLE_ARROW );
-
- MAP_BUILTIN( PointerStyle::Move, GDK_FLEUR );
-
- MAKE_CURSOR( PointerStyle::Null, null );
- MAKE_CURSOR( PointerStyle::Magnify, magnify_ );
- MAKE_CURSOR( PointerStyle::Fill, fill_ );
- MAKE_CURSOR( PointerStyle::MoveData, movedata_ );
- MAKE_CURSOR( PointerStyle::CopyData, copydata_ );
- MAKE_CURSOR( PointerStyle::MoveFile, movefile_ );
- MAKE_CURSOR( PointerStyle::CopyFile, copyfile_ );
- MAKE_CURSOR( PointerStyle::MoveFiles, movefiles_ );
- MAKE_CURSOR( PointerStyle::CopyFiles, copyfiles_ );
- MAKE_CURSOR( PointerStyle::NotAllowed, nodrop_ );
- MAKE_CURSOR( PointerStyle::Rotate, rotate_ );
- MAKE_CURSOR( PointerStyle::HShear, hshear_ );
- MAKE_CURSOR( PointerStyle::VShear, vshear_ );
- MAKE_CURSOR( PointerStyle::DrawLine, drawline_ );
- MAKE_CURSOR( PointerStyle::DrawRect, drawrect_ );
- MAKE_CURSOR( PointerStyle::DrawPolygon, drawpolygon_ );
- MAKE_CURSOR( PointerStyle::DrawBezier, drawbezier_ );
- MAKE_CURSOR( PointerStyle::DrawArc, drawarc_ );
- MAKE_CURSOR( PointerStyle::DrawPie, drawpie_ );
- MAKE_CURSOR( PointerStyle::DrawCircleCut, drawcirclecut_ );
- MAKE_CURSOR( PointerStyle::DrawEllipse, drawellipse_ );
- MAKE_CURSOR( PointerStyle::DrawConnect, drawconnect_ );
- MAKE_CURSOR( PointerStyle::DrawText, drawtext_ );
- MAKE_CURSOR( PointerStyle::Mirror, mirror_ );
- MAKE_CURSOR( PointerStyle::Crook, crook_ );
- MAKE_CURSOR( PointerStyle::Crop, crop_ );
- MAKE_CURSOR( PointerStyle::MovePoint, movepoint_ );
- MAKE_CURSOR( PointerStyle::MoveBezierWeight, movebezierweight_ );
- MAKE_CURSOR( PointerStyle::DrawFreehand, drawfreehand_ );
- MAKE_CURSOR( PointerStyle::DrawCaption, drawcaption_ );
- MAKE_CURSOR( PointerStyle::LinkData, linkdata_ );
- MAKE_CURSOR( PointerStyle::MoveDataLink, movedlnk_ );
- MAKE_CURSOR( PointerStyle::CopyDataLink, copydlnk_ );
- MAKE_CURSOR( PointerStyle::LinkFile, linkfile_ );
- MAKE_CURSOR( PointerStyle::MoveFileLink, moveflnk_ );
- MAKE_CURSOR( PointerStyle::CopyFileLink, copyflnk_ );
- MAKE_CURSOR( PointerStyle::Chart, chart_ );
- MAKE_CURSOR( PointerStyle::Detective, detective_ );
- MAKE_CURSOR( PointerStyle::PivotCol, pivotcol_ );
- MAKE_CURSOR( PointerStyle::PivotRow, pivotrow_ );
- MAKE_CURSOR( PointerStyle::PivotField, pivotfld_ );
- MAKE_CURSOR( PointerStyle::PivotDelete, pivotdel_ );
- MAKE_CURSOR( PointerStyle::Chain, chain_ );
- MAKE_CURSOR( PointerStyle::ChainNotAllowed, chainnot_ );
- MAKE_CURSOR( PointerStyle::AutoScrollN, asn_ );
- MAKE_CURSOR( PointerStyle::AutoScrollS, ass_ );
- MAKE_CURSOR( PointerStyle::AutoScrollW, asw_ );
- MAKE_CURSOR( PointerStyle::AutoScrollE, ase_ );
- MAKE_CURSOR( PointerStyle::AutoScrollNW, asnw_ );
- MAKE_CURSOR( PointerStyle::AutoScrollNE, asne_ );
- MAKE_CURSOR( PointerStyle::AutoScrollSW, assw_ );
- MAKE_CURSOR( PointerStyle::AutoScrollSE, asse_ );
- MAKE_CURSOR( PointerStyle::AutoScrollNS, asns_ );
- MAKE_CURSOR( PointerStyle::AutoScrollWE, aswe_ );
- MAKE_CURSOR( PointerStyle::AutoScrollNSWE, asnswe_ );
- MAKE_CURSOR( PointerStyle::TextVertical, vertcurs_ );
-
- // #i32329#
- MAKE_CURSOR( PointerStyle::TabSelectS, tblsels_ );
- MAKE_CURSOR( PointerStyle::TabSelectE, tblsele_ );
- MAKE_CURSOR( PointerStyle::TabSelectSE, tblselse_ );
- MAKE_CURSOR( PointerStyle::TabSelectW, tblselw_ );
- MAKE_CURSOR( PointerStyle::TabSelectSW, tblselsw_ );
-
- MAKE_CURSOR( PointerStyle::HideWhitespace, hidewhitespace_ );
- MAKE_CURSOR( PointerStyle::ShowWhitespace, showwhitespace_ );
-
- default:
- SAL_WARN( "vcl.gtk", "pointer " << static_cast<int>(ePointerStyle) << "not implemented" );
- break;
- }
- if( !pCursor )
- pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, GDK_LEFT_PTR );
-
- m_aCursors[ ePointerStyle ] = pCursor;
- }
-
- return m_aCursors[ ePointerStyle ];
-}
-
-int GtkSalDisplay::CaptureMouse( SalFrame* pSFrame )
-{
- GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(pSFrame);
-
- if( !pFrame )
- {
- if( m_pCapture )
- static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
- m_pCapture = nullptr;
- return 0;
- }
-
- if( m_pCapture )
- {
- if( pFrame == m_pCapture )
- return 1;
- static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
- }
-
- m_pCapture = pFrame;
- pFrame->grabPointer( TRUE );
- return 1;
-}
-
-/**********************************************************************
- * class GtkSalData *
- **********************************************************************/
-
-GtkSalData::GtkSalData( SalInstance *pInstance )
- : GenericUnixSalData( SAL_DATA_GTK, pInstance )
- , m_aDispatchMutex()
- , m_aDispatchCondition()
- , m_pDocumentFocusListener(nullptr)
-{
- m_pUserEvent = nullptr;
-}
-
-static XIOErrorHandler aOrigXIOErrorHandler = nullptr;
-
-extern "C" {
-
-static int XIOErrorHdl(Display *)
-{
- fprintf(stderr, "X IO Error\n");
- _exit(1);
- // avoid crashes in unrelated threads that still run while atexit
- // handlers are in progress
-}
-
-}
-
-GtkSalData::~GtkSalData()
-{
- Yield( true, true );
- g_warning ("TESTME: We used to have a stop-timer here, but the central code should do this");
-
- // sanity check: at this point nobody should be yielding, but wake them
- // up anyway before the condition they're waiting on gets destroyed.
- m_aDispatchCondition.set();
-
- osl::MutexGuard g( m_aDispatchMutex );
- if (m_pUserEvent)
- {
- g_source_destroy (m_pUserEvent);
- g_source_unref (m_pUserEvent);
- m_pUserEvent = nullptr;
- }
- XSetIOErrorHandler(aOrigXIOErrorHandler);
-}
-
-void GtkSalData::Dispose()
-{
- deInitNWF();
-}
-
-/// Allows events to be processed, returns true if we processed an event.
-bool GtkSalData::Yield( bool bWait, bool bHandleAllCurrentEvents )
-{
- /* #i33212# only enter g_main_context_iteration in one thread at any one
- * time, else one of them potentially will never end as long as there is
- * another thread in there. Having only one yielding thread actually dispatch
- * fits the vcl event model (see e.g. the generic plugin).
- */
- bool bDispatchThread = false;
- bool bWasEvent = false;
- {
- // release YieldMutex (and re-acquire at block end)
- SolarMutexReleaser aReleaser;
- if( m_aDispatchMutex.tryToAcquire() )
- bDispatchThread = true;
- else if( ! bWait )
- {
- return false; // someone else is waiting already, return
- }
-
- if( bDispatchThread )
- {
- int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
- gboolean wasOneEvent = TRUE;
- while( nMaxEvents-- && wasOneEvent )
- {
- wasOneEvent = g_main_context_iteration( nullptr, bWait && !bWasEvent );
- if( wasOneEvent )
- bWasEvent = true;
- }
- }
- else if( bWait )
- {
- /* #i41693# in case the dispatch thread hangs in join
- * for this thread the condition will never be set
- * workaround: timeout of 1 second an emergency exit
- */
- // we are the dispatch thread
- m_aDispatchCondition.reset();
- m_aDispatchCondition.wait( std::chrono::seconds(1) );
- }
- }
-
- if( bDispatchThread )
- {
- m_aDispatchMutex.release();
- if( bWasEvent )
- m_aDispatchCondition.set(); // trigger non dispatch thread yields
- }
-
- return bWasEvent;
-}
-
-void GtkSalData::Init()
-{
- int i;
- SAL_INFO( "vcl.gtk", "GtkMainloop::Init()" );
- XrmInitialize();
-
- gtk_set_locale();
-
- /*
- * open connection to X11 Display
- * try in this order:
- * o -display command line parameter,
- * o $DISPLAY environment variable
- * o default display
- */
-
- GdkDisplay *pGdkDisp = nullptr;
-
- // is there a -display command line parameter?
- rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
- int nParams = osl_getCommandArgCount();
- OString aDisplay;
- OUString aParam, aBin;
- char** pCmdLineAry = new char*[ nParams+1 ];
- osl_getExecutableFile( &aParam.pData );
- osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
- pCmdLineAry[0] = g_strdup( OUStringToOString( aBin, aEnc ).getStr() );
- for (i=0; i<nParams; i++)
- {
- osl_getCommandArg(i, &aParam.pData );
- OString aBParam( OUStringToOString( aParam, aEnc ) );
-
- if( aParam == "-display" || aParam == "--display" )
- {
- pCmdLineAry[i+1] = g_strdup( "--display" );
- osl_getCommandArg(i+1, &aParam.pData );
- aDisplay = OUStringToOString( aParam, aEnc );
- }
- else
- pCmdLineAry[i+1] = g_strdup( aBParam.getStr() );
- }
- // add executable
- nParams++;
-
- g_set_application_name(SalGenericSystem::getFrameClassName());
-
- // Set consistent name of the root accessible
- OUString aAppName = Application::GetAppName();
- if( !aAppName.isEmpty() )
- {
- OString aPrgName = OUStringToOString(aAppName, aEnc);
- g_set_prgname(aPrgName.getStr());
- }
-
- // init gtk/gdk
- gtk_init_check( &nParams, &pCmdLineAry );
- gdk_error_trap_push();
-
- for (i = 0; i < nParams; i++ )
- g_free( pCmdLineAry[i] );
- delete [] pCmdLineAry;
-
-#if OSL_DEBUG_LEVEL > 1
- if (g_getenv ("SAL_DEBUG_UPDATES"))
- gdk_window_set_debug_updates (TRUE);
-#endif
-
- pGdkDisp = gdk_display_get_default();
- if ( !pGdkDisp )
- {
- OUString aProgramFileURL;
- osl_getExecutableFile( &aProgramFileURL.pData );
- OUString aProgramSystemPath;
- osl_getSystemPathFromFileURL (aProgramFileURL.pData, &aProgramSystemPath.pData);
- OString aProgramName = OUStringToOString(
- aProgramSystemPath,
- osl_getThreadTextEncoding() );
- fprintf( stderr, "%s X11 error: Can't open display: %s\n",
- aProgramName.getStr(), aDisplay.getStr());
- fprintf( stderr, " Set DISPLAY environment variable, use -display option\n");
- fprintf( stderr, " or check permissions of your X-Server\n");
- fprintf( stderr, " (See \"man X\" resp. \"man xhost\" for details)\n");
- fflush( stderr );
- exit(0);
- }
-
- aOrigXIOErrorHandler = XSetIOErrorHandler(XIOErrorHdl);
-
- /*
- * if a -display switch was used, we need
- * to set the environment accordingly since
- * the clipboard build another connection
- * to the xserver using $DISPLAY
- */
- OUString envVar("DISPLAY");
- const gchar *name = gdk_display_get_name( pGdkDisp );
- OUString envValue(name, strlen(name), aEnc);
- osl_setEnvironment(envVar.pData, envValue.pData);
-
- GtkSalDisplay *pDisplay = new GtkSalDisplay( pGdkDisp );
- SetDisplay( pDisplay );
-
- Display *pDisp = gdk_x11_display_get_xdisplay( pGdkDisp );
-
- gdk_error_trap_push();
- SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
- bool bErrorOccured = gdk_error_trap_pop() != 0;
- gdk_error_trap_push();
- pKbdExtension->UseExtension( bErrorOccured );
- gdk_error_trap_pop();
- GetGtkDisplay()->SetKbdExtension( pKbdExtension );
-
- // add signal handler to notify screen size changes
- int nScreens = gdk_display_get_n_screens( pGdkDisp );
- for( int n = 0; n < nScreens; n++ )
- {
- GdkScreen *pScreen = gdk_display_get_screen( pGdkDisp, n );
- if( pScreen )
- {
- pDisplay->screenSizeChanged( pScreen );
- pDisplay->monitorsChanged( pScreen );
- g_signal_connect( G_OBJECT(pScreen), "size-changed",
- G_CALLBACK(signalScreenSizeChanged), pDisplay );
- g_signal_connect( G_OBJECT(pScreen), "monitors-changed",
- G_CALLBACK(signalMonitorsChanged), GetGtkDisplay() );
- }
- }
-}
-
-void GtkSalData::ErrorTrapPush()
-{
- gdk_error_trap_push ();
-}
-
-bool GtkSalData::ErrorTrapPop( bool )
-{
- return gdk_error_trap_pop () != 0;
-}
-
-#if !GLIB_CHECK_VERSION(2,32,0)
-#define G_SOURCE_REMOVE FALSE
-#endif
-
-extern "C" {
-
- struct SalGtkTimeoutSource {
- GSource aParent;
- GTimeVal aFireTime;
- GtkSalTimer *pInstance;
- };
-
- static void sal_gtk_timeout_defer( SalGtkTimeoutSource *pTSource )
- {
- g_get_current_time( &pTSource->aFireTime );
- g_time_val_add( &pTSource->aFireTime, pTSource->pInstance->m_nTimeoutMS * 1000 );
- }
-
- static gboolean sal_gtk_timeout_expired( SalGtkTimeoutSource *pTSource,
- gint *nTimeoutMS, GTimeVal const *pTimeNow )
- {
- glong nDeltaSec = pTSource->aFireTime.tv_sec - pTimeNow->tv_sec;
- glong nDeltaUSec = pTSource->aFireTime.tv_usec - pTimeNow->tv_usec;
- if( nDeltaSec < 0 || ( nDeltaSec == 0 && nDeltaUSec < 0) )
- {
- *nTimeoutMS = 0;
- return TRUE;
- }
- if( nDeltaUSec < 0 )
- {
- nDeltaUSec += 1000000;
- nDeltaSec -= 1;
- }
- // if the clock changes backwards we need to cope ...
- if( static_cast<unsigned long>(nDeltaSec) > 1 + ( pTSource->pInstance->m_nTimeoutMS / 1000 ) )
- {
- sal_gtk_timeout_defer( pTSource );
- return TRUE;
- }
-
- *nTimeoutMS = MIN( G_MAXINT, ( nDeltaSec * 1000 + (nDeltaUSec + 999) / 1000 ) );
-
- return *nTimeoutMS == 0;
- }
-
- static gboolean sal_gtk_timeout_prepare( GSource *pSource, gint *nTimeoutMS )
- {
- SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
-
- GTimeVal aTimeNow;
- g_get_current_time( &aTimeNow );
-
- return sal_gtk_timeout_expired( pTSource, nTimeoutMS, &aTimeNow );
- }
-
- static gboolean sal_gtk_timeout_check( GSource *pSource )
- {
- SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
-
- GTimeVal aTimeNow;
- g_get_current_time( &aTimeNow );
-
- return ( pTSource->aFireTime.tv_sec < aTimeNow.tv_sec ||
- ( pTSource->aFireTime.tv_sec == aTimeNow.tv_sec &&
- pTSource->aFireTime.tv_usec < aTimeNow.tv_usec ) );
- }
-
- static gboolean sal_gtk_timeout_dispatch( GSource *pSource, GSourceFunc, gpointer )
- {
- SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
-
- if( !pTSource->pInstance )
- return FALSE;
-
- SolarMutexGuard aGuard;
-
- sal_gtk_timeout_defer( pTSource );
-
- ImplSVData* pSVData = ImplGetSVData();
- if( pSVData->maSchedCtx.mpSalTimer )
- pSVData->maSchedCtx.mpSalTimer->CallCallback();
-
- return G_SOURCE_REMOVE;
- }
-
- static GSourceFuncs sal_gtk_timeout_funcs =
- {
- sal_gtk_timeout_prepare,
- sal_gtk_timeout_check,
- sal_gtk_timeout_dispatch,
- nullptr, nullptr, nullptr
- };
-}
-
-static SalGtkTimeoutSource *
-create_sal_gtk_timeout( GtkSalTimer *pTimer )
-{
- GSource *pSource = g_source_new( &sal_gtk_timeout_funcs, sizeof( SalGtkTimeoutSource ) );
- SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
- pTSource->pInstance = pTimer;
-
- // #i36226# timers should be executed with lower priority
- // than XEvents like in generic plugin
- g_source_set_priority( pSource, G_PRIORITY_LOW );
- g_source_set_can_recurse( pSource, TRUE );
- g_source_set_callback( pSource,
- /* unused dummy */ g_idle_remove_by_data,
- nullptr, nullptr );
- g_source_attach( pSource, g_main_context_default() );
-#ifdef DBG_UTIL
- g_source_set_name( pSource, "VCL timeout source" );
-#endif
-
- sal_gtk_timeout_defer( pTSource );
-
- return pTSource;
-}
-
-GtkSalTimer::GtkSalTimer()
- : m_pTimeout(nullptr)
- , m_nTimeoutMS(0)
-{
-}
-
-GtkSalTimer::~GtkSalTimer()
-{
- GtkInstance *pInstance = static_cast<GtkInstance *>(GetSalData()->m_pInstance);
- pInstance->RemoveTimer();
- Stop();
-}
-
-bool GtkSalTimer::Expired()
-{
- if( !m_pTimeout || g_source_is_destroyed( &m_pTimeout->aParent ) )
- return false;
-
- gint nDummy = 0;
- GTimeVal aTimeNow;
- g_get_current_time( &aTimeNow );
- return !!sal_gtk_timeout_expired( m_pTimeout, &nDummy, &aTimeNow);
-}
-
-void GtkSalTimer::Start( sal_uInt64 nMS )
-{
- // glib is not 64bit safe in this regard.
- assert( nMS <= G_MAXINT );
- if ( nMS > G_MAXINT )
- nMS = G_MAXINT;
- m_nTimeoutMS = nMS; // for restarting
- Stop(); // FIXME: ideally re-use an existing m_pTimeout
- m_pTimeout = create_sal_gtk_timeout( this );
-}
-
-void GtkSalTimer::Stop()
-{
- if( m_pTimeout )
- {
- g_source_destroy( &m_pTimeout->aParent );
- g_source_unref( &m_pTimeout->aParent );
- m_pTimeout = nullptr;
- }
-}
-
-extern "C" {
- static gboolean call_userEventFn( void *data )
- {
- SolarMutexGuard aGuard;
- const SalGenericDisplay *pDisplay = GetGenericUnixSalData()->GetDisplay();
- if ( pDisplay )
- {
- GtkSalDisplay *pThisDisplay = static_cast<GtkSalData *>(data)->GetGtkDisplay();
- assert(static_cast<const SalGenericDisplay *>(pThisDisplay) == pDisplay);
- pThisDisplay->DispatchInternalEvent();
- }
- return TRUE;
- }
-}
-
-void GtkSalData::TriggerUserEventProcessing()
-{
- if (m_pUserEvent)
- g_main_context_wakeup (nullptr); // really needed ?
- else // nothing pending anyway
- {
- m_pUserEvent = g_idle_source_new();
- // tdf#112890 some dialog don't appear under gtk2, use the same
- // priority for user-events as gtk3 does since tdf#110737
- g_source_set_priority (m_pUserEvent, G_PRIORITY_HIGH_IDLE + 30);
- g_source_set_can_recurse (m_pUserEvent, TRUE);
- g_source_set_callback (m_pUserEvent, call_userEventFn,
- static_cast<gpointer>(this), nullptr);
- g_source_attach (m_pUserEvent, g_main_context_default ());
- }
-}
-
-void GtkSalData::TriggerAllUserEventsProcessed()
-{
- assert( m_pUserEvent );
- g_source_destroy( m_pUserEvent );
- g_source_unref( m_pUserEvent );
- m_pUserEvent = nullptr;
-}
-
-void GtkSalDisplay::TriggerUserEventProcessing()
-{
- GetGtkSalData()->TriggerUserEventProcessing();
-}
-
-void GtkSalDisplay::TriggerAllUserEventsProcessed()
-{
- GetGtkSalData()->TriggerAllUserEventsProcessed();
-}
-
-GtkWidget* GtkSalDisplay::findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) const
-{
- for (auto pFrame : m_aFrames)
- {
- const SystemEnvData* pEnvData = pFrame->GetSystemData();
- if (pEnvData->aWindow == hWindow)
- return GTK_WIDGET(pEnvData->pWidget);
- }
- return nullptr;
-}
-
-void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
-{
- if( m_pCapture == pFrame )
- {
- static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
- m_pCapture = nullptr;
- }
- SalGenericDisplay::deregisterFrame( pFrame );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtkinst.cxx b/vcl/unx/gtk/gtkinst.cxx
deleted file mode 100644
index 2a31b87e45cf..000000000000
--- a/vcl/unx/gtk/gtkinst.cxx
+++ /dev/null
@@ -1,478 +0,0 @@
-/* -*- 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 .
- */
-
-#include <stack>
-#include <string.h>
-#include <osl/process.h>
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/salobj.h>
-#include <unx/gtk/gtkgdi.hxx>
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtkobject.hxx>
-#include <unx/gtk/atkbridge.hxx>
-#include <unx/gtk/gtkprn.hxx>
-#include <unx/gtk/gtksalmenu.hxx>
-#include <headless/svpvd.hxx>
-#include <headless/svpbmp.hxx>
-#include <vcl/inputtypes.hxx>
-#include <unx/genpspgraphics.h>
-#include <rtl/strbuf.hxx>
-#include <sal/log.hxx>
-#include <rtl/uri.hxx>
-
-#include <vcl/settings.hxx>
-
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <unx/gtk/gtkprintwrapper.hxx>
-
-extern "C"
-{
- #define GET_YIELD_MUTEX() static_cast<GtkYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())
- static void GdkThreadsEnter()
- {
- GtkYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
- pYieldMutex->ThreadsEnter();
- }
- static void GdkThreadsLeave()
- {
- GtkYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
- pYieldMutex->ThreadsLeave();
- }
-
- VCLPLUG_GTK_PUBLIC SalInstance* create_SalInstance()
- {
- SAL_INFO(
- "vcl.gtk",
- "create vcl plugin instance with gtk version " << gtk_major_version
- << " " << gtk_minor_version << " " << gtk_micro_version);
-
-#if !GTK_CHECK_VERSION(3,0,0)
- if( gtk_major_version < 2 || // very unlikely sanity check
- ( gtk_major_version == 2 && gtk_minor_version < 4 ) )
- {
- g_warning("require a newer gtk than %d.%d for gdk_threads_set_lock_functions", static_cast<int>(gtk_major_version), gtk_minor_version);
- return nullptr;
- }
-#else
- if (gtk_major_version == 3 && gtk_minor_version < 18)
- {
- g_warning("require gtk >= 3.18 for theme expectations");
- return nullptr;
- }
-#endif
-
- // for gtk2 it is always built with X support, so this is always called
- // for gtk3 it is normally built with X and Wayland support, if
- // X is supported GDK_WINDOWING_X11 is defined and this is always
- // called, regardless of if we're running under X or Wayland.
- // We can't use (DLSYM_GDK_IS_X11_DISPLAY(pDisplay)) to only do it under
- // X, because we need to do it earlier than we have a display
-#if !GTK_CHECK_VERSION(3,0,0) || defined(GDK_WINDOWING_X11)
- /* #i92121# workaround deadlocks in the X11 implementation
- */
- static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
- /* #i90094#
- from now on we know that an X connection will be
- established, so protect X against itself
- */
- if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
- XInitThreads();
-#endif
-
- // init gdk thread protection
- bool const sup = g_thread_supported();
- // extracted from the 'if' to avoid Clang -Wunreachable-code
- if ( !sup )
- g_thread_init( nullptr );
-
- gdk_threads_set_lock_functions (GdkThreadsEnter, GdkThreadsLeave);
- SAL_INFO("vcl.gtk", "Hooked gdk threads locks");
-
- auto pYieldMutex = std::make_unique<GtkYieldMutex>();
-
- gdk_threads_init();
-
- GtkInstance* pInstance = new GtkInstance( std::move(pYieldMutex) );
- SAL_INFO("vcl.gtk", "creating GtkInstance " << pInstance);
-
- // Create SalData, this does not leak
- new GtkSalData( pInstance );
-
- return pInstance;
- }
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-static VclInputFlags categorizeEvent(const GdkEvent *pEvent)
-{
- VclInputFlags nType = VclInputFlags::NONE;
- switch( pEvent->type )
- {
- case GDK_MOTION_NOTIFY:
- case GDK_BUTTON_PRESS:
- case GDK_2BUTTON_PRESS:
- case GDK_3BUTTON_PRESS:
- case GDK_BUTTON_RELEASE:
- case GDK_ENTER_NOTIFY:
- case GDK_LEAVE_NOTIFY:
- case GDK_SCROLL:
- nType = VclInputFlags::MOUSE;
- break;
- case GDK_KEY_PRESS:
- // case GDK_KEY_RELEASE: //similar to the X11SalInstance one
- nType = VclInputFlags::KEYBOARD;
- break;
- case GDK_EXPOSE:
- nType = VclInputFlags::PAINT;
- break;
- default:
- nType = VclInputFlags::OTHER;
- break;
- }
- return nType;
-}
-#endif
-
-GtkInstance::GtkInstance( std::unique_ptr<SalYieldMutex> pMutex )
-#if GTK_CHECK_VERSION(3,0,0)
- : SvpSalInstance( std::move(pMutex) )
-#else
- : X11SalInstance( std::move(pMutex) )
-#endif
- , m_pTimer(nullptr)
- , bNeedsInit(true)
- , m_pLastCairoFontOptions(nullptr)
-{
-}
-
-//We want to defer initializing gtk until we are after uno has been
-//bootstrapped so we can ask the config what the UI language is so that we can
-//force that in as $LANGUAGE to get gtk to render widgets RTL if we have a RTL
-//UI in a LTR locale
-void GtkInstance::AfterAppInit()
-{
- EnsureInit();
-}
-
-void GtkInstance::EnsureInit()
-{
- if (!bNeedsInit)
- return;
- // initialize SalData
- GtkSalData *pSalData = GetGtkSalData();
- pSalData->Init();
- GtkSalData::initNWF();
-
- InitAtkBridge();
-
- ImplSVData* pSVData = ImplGetSVData();
-#ifdef GTK_TOOLKIT_NAME
- pSVData->maAppData.mxToolkitName = OUString(GTK_TOOLKIT_NAME);
-#elif GTK_CHECK_VERSION(3,0,0)
- pSVData->maAppData.mxToolkitName = OUString("gtk3");
-#else
- pSVData->maAppData.mxToolkitName = OUString("gtk2");
-#endif
-
- bNeedsInit = false;
-}
-
-GtkInstance::~GtkInstance()
-{
- assert( nullptr == m_pTimer );
- DeInitAtkBridge();
- ResetLastSeenCairoFontOptions(nullptr);
-}
-
-SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle )
-{
- EnsureInit();
- return new GtkSalFrame( pParent, nStyle );
-}
-
-SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, SalFrameStyleFlags )
-{
- EnsureInit();
- return new GtkSalFrame( pParentData );
-}
-
-SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow )
-{
- EnsureInit();
-#if !GTK_CHECK_VERSION(3,0,0)
- // there is no method to set a visual for a GtkWidget
- // so we need the X11SalObject in that case
- if( pWindowData )
- return X11SalObject::CreateObject( pParent, pWindowData, bShow );
-#else
- (void)pWindowData;
- //FIXME: Missing CreateObject functionality ...
-#endif
-
- return new GtkSalObject( static_cast<GtkSalFrame*>(pParent), bShow );
-}
-
-extern "C"
-{
- typedef void*(* getDefaultFnc)();
- typedef void(* addItemFnc)(void *, const char *);
-}
-
-void GtkInstance::AddToRecentDocumentList(const OUString& rFileUrl, const OUString&, const OUString&)
-{
- EnsureInit();
- OString sGtkURL;
- rtl_TextEncoding aSystemEnc = osl_getThreadTextEncoding();
- if ((aSystemEnc == RTL_TEXTENCODING_UTF8) || !rFileUrl.startsWith( "file://" ))
- sGtkURL = OUStringToOString(rFileUrl, RTL_TEXTENCODING_UTF8);
- else
- {
- //Non-utf8 locales are a bad idea if trying to work with non-ascii filenames
- //Decode %XX components
- OUString sDecodedUri = rtl::Uri::decode(rFileUrl.copy(7), rtl_UriDecodeToIuri, RTL_TEXTENCODING_UTF8);
- //Convert back to system locale encoding
- OString sSystemUrl = OUStringToOString(sDecodedUri, aSystemEnc);
- //Encode to an escaped ASCII-encoded URI
- gchar *g_uri = g_filename_to_uri(sSystemUrl.getStr(), nullptr, nullptr);
- sGtkURL = OString(g_uri);
- g_free(g_uri);
- }
- GtkRecentManager *manager = gtk_recent_manager_get_default ();
- gtk_recent_manager_add_item (manager, sGtkURL.getStr());
-}
-
-SalInfoPrinter* GtkInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
- ImplJobSetup* pSetupData )
-{
- EnsureInit();
-#if defined ENABLE_GTK_PRINT || GTK_CHECK_VERSION(3,0,0)
- mbPrinterInit = true;
- // create and initialize SalInfoPrinter
- PspSalInfoPrinter* pPrinter = new GtkSalInfoPrinter;
- configurePspInfoPrinter(pPrinter, pQueueInfo, pSetupData);
- return pPrinter;
-#else
- return Superclass_t::CreateInfoPrinter( pQueueInfo, pSetupData );
-#endif
-}
-
-std::unique_ptr<SalPrinter> GtkInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
-{
- EnsureInit();
-#if defined ENABLE_GTK_PRINT || GTK_CHECK_VERSION(3,0,0)
- mbPrinterInit = true;
- return std::unique_ptr<SalPrinter>(new GtkSalPrinter( pInfoPrinter ));
-#else
- return Superclass_t::CreatePrinter( pInfoPrinter );
-#endif
-}
-
-/*
- * These methods always occur in pairs
- * A ThreadsEnter is followed by a ThreadsLeave
- * We need to queue up the recursive lock count
- * for each pair, so we can accurately restore
- * it later.
- */
-thread_local std::stack<sal_uInt32> GtkYieldMutex::yieldCounts;
-
-void GtkYieldMutex::ThreadsEnter()
-{
- acquire();
- if (!yieldCounts.empty()) {
- auto n = yieldCounts.top();
- yieldCounts.pop();
- assert(n > 0);
- n--;
- if (n > 0)
- acquire(n);
- }
-}
-
-void GtkYieldMutex::ThreadsLeave()
-{
- assert(m_nCount != 0);
- yieldCounts.push(m_nCount);
- release(true);
-}
-
-std::unique_ptr<SalVirtualDevice> GtkInstance::CreateVirtualDevice( SalGraphics *pG,
- long &nDX, long &nDY,
- DeviceFormat eFormat,
- const SystemGraphicsData *pGd )
-{
- EnsureInit();
-#if GTK_CHECK_VERSION(3,0,0)
- (void) pGd;
- SvpSalGraphics *pSvpSalGraphics = dynamic_cast<SvpSalGraphics*>(pG);
- assert(pSvpSalGraphics);
- std::unique_ptr<SalVirtualDevice> pNew(new SvpSalVirtualDevice(eFormat, pSvpSalGraphics->getSurface()));
- pNew->SetSize( nDX, nDY );
- return pNew;
-#else
- GtkSalGraphics *pGtkSalGraphics = dynamic_cast<GtkSalGraphics*>(pG);
- assert(pGtkSalGraphics);
- return CreateX11VirtualDevice(pG, nDX, nDY, eFormat, pGd,
- std::make_unique<GtkSalGraphics>(pGtkSalGraphics->GetGtkFrame(),
- pGtkSalGraphics->GetGtkWidget(),
- pGtkSalGraphics->GetScreenNumber()));
-#endif
-}
-
-std::shared_ptr<SalBitmap> GtkInstance::CreateSalBitmap()
-{
- EnsureInit();
-#if GTK_CHECK_VERSION(3,0,0)
- return SvpSalInstance::CreateSalBitmap();//new SvpSalBitmap();
-#else
- return X11SalInstance::CreateSalBitmap();
-#endif
-}
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-std::unique_ptr<SalMenu> GtkInstance::CreateMenu( bool bMenuBar, Menu* pVCLMenu )
-{
- EnsureInit();
- GtkSalMenu* pSalMenu = new GtkSalMenu( bMenuBar );
- pSalMenu->SetMenu( pVCLMenu );
- return std::unique_ptr<SalMenu>(pSalMenu);
-}
-
-std::unique_ptr<SalMenuItem> GtkInstance::CreateMenuItem( const SalItemParams & rItemData )
-{
- EnsureInit();
- return std::unique_ptr<SalMenuItem>(new GtkSalMenuItem( &rItemData ));
-}
-
-#else // not ENABLE_GMENU_INTEGRATION
-
-std::unique_ptr<SalMenu> GtkInstance::CreateMenu( bool, Menu* ) { return nullptr; }
-std::unique_ptr<SalMenuItem> GtkInstance::CreateMenuItem( const SalItemParams & ) { return nullptr; }
-
-#endif
-
-SalTimer* GtkInstance::CreateSalTimer()
-{
- EnsureInit();
- assert( nullptr == m_pTimer );
- if ( nullptr == m_pTimer )
- m_pTimer = new GtkSalTimer();
- return m_pTimer;
-}
-
-void GtkInstance::RemoveTimer ()
-{
- EnsureInit();
- m_pTimer = nullptr;
-}
-
-bool GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
-{
- EnsureInit();
- return GetGtkSalData()->Yield( bWait, bHandleAllCurrentEvents );
-}
-
-bool GtkInstance::IsTimerExpired()
-{
- EnsureInit();
- return (m_pTimer && m_pTimer->Expired());
-}
-
-bool GtkInstance::AnyInput( VclInputFlags nType )
-{
- EnsureInit();
- if( (nType & VclInputFlags::TIMER) && IsTimerExpired() )
- return true;
-#if !GTK_CHECK_VERSION(3,0,0)
- bool bRet = X11SalInstance::AnyInput(nType);
-#else
- if (!gdk_events_pending())
- return false;
-
- if (nType == VCL_INPUT_ANY)
- return true;
-
- bool bRet = false;
- std::stack<GdkEvent*> aEvents;
- GdkEvent *pEvent = nullptr;
- while ((pEvent = gdk_event_get()))
- {
- aEvents.push(pEvent);
- VclInputFlags nEventType = categorizeEvent(pEvent);
- if ( (nEventType & nType) || ( nEventType == VclInputFlags::NONE && (nType & VclInputFlags::OTHER) ) )
- {
- bRet = true;
- break;
- }
- }
-
- while (!aEvents.empty())
- {
- pEvent = aEvents.top();
- gdk_event_put(pEvent);
- gdk_event_free(pEvent);
- aEvents.pop();
- }
-#endif
- return bRet;
-}
-
-std::unique_ptr<GenPspGraphics> GtkInstance::CreatePrintGraphics()
-{
- EnsureInit();
- return std::make_unique<GenPspGraphics>();
-}
-
-std::shared_ptr<vcl::unx::GtkPrintWrapper> const &
-GtkInstance::getPrintWrapper() const
-{
- if (!m_xPrintWrapper)
- m_xPrintWrapper.reset(new vcl::unx::GtkPrintWrapper);
- return m_xPrintWrapper;
-}
-
-const cairo_font_options_t* GtkInstance::GetCairoFontOptions()
-{
- const cairo_font_options_t* pCairoFontOptions = gdk_screen_get_font_options(gdk_screen_get_default());
- if (!m_pLastCairoFontOptions && pCairoFontOptions)
- m_pLastCairoFontOptions = cairo_font_options_copy(pCairoFontOptions);
- return pCairoFontOptions;
-}
-
-const cairo_font_options_t* GtkInstance::GetLastSeenCairoFontOptions() const
-{
- return m_pLastCairoFontOptions;
-}
-
-void GtkInstance::ResetLastSeenCairoFontOptions(const cairo_font_options_t* pCairoFontOptions)
-{
- if (m_pLastCairoFontOptions)
- cairo_font_options_destroy(m_pLastCairoFontOptions);
- if (pCairoFontOptions)
- m_pLastCairoFontOptions = cairo_font_options_copy(pCairoFontOptions);
- else
- m_pLastCairoFontOptions = nullptr;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtkobject.cxx b/vcl/unx/gtk/gtkobject.cxx
deleted file mode 100644
index 38302c60ef74..000000000000
--- a/vcl/unx/gtk/gtkobject.cxx
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*- 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 .
- */
-
-#ifdef AIX
-#define _LINUX_SOURCE_COMPAT
-#include <sys/timer.h>
-#undef _LINUX_SOURCE_COMPAT
-#endif
-
-#include <unx/gtk/gtkobject.hxx>
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkgdi.hxx>
-
-GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
- : m_pSocket( nullptr ),
- m_pRegion( nullptr )
-{
- if( !pParent )
- return;
-
- // our plug window
- m_pSocket = gtk_drawing_area_new();
- Show( bShow );
- // insert into container
- gtk_fixed_put( pParent->getFixedContainer(),
- m_pSocket,
- 0, 0 );
- // realize so we can get a window id
- gtk_widget_realize( m_pSocket );
-
- // make it transparent; some plugins may not insert
- // their own window here but use the socket window itself
- gtk_widget_set_app_paintable( m_pSocket, TRUE );
-
- // system data
- m_aSystemData.nSize = sizeof( SystemEnvData );
- SalDisplay* pDisp = vcl_sal::getSalDisplay(GetGenericUnixSalData());
- m_aSystemData.pDisplay = pDisp->GetDisplay();
- m_aSystemData.pVisual = pDisp->GetVisual(pParent->getXScreenNumber()).GetVisual();
- m_aSystemData.aWindow = GDK_WINDOW_XWINDOW(widget_get_window(m_pSocket));
- m_aSystemData.aShellWindow = GDK_WINDOW_XWINDOW(widget_get_window(GTK_WIDGET(pParent->getWindow())));
- m_aSystemData.pSalFrame = nullptr;
- m_aSystemData.pWidget = m_pSocket;
- m_aSystemData.nScreen = pParent->getXScreenNumber().getXScreen();
- m_aSystemData.pToolkit = "gtk2";
- m_aSystemData.pPlatformName = "xcb";
-
- g_signal_connect( G_OBJECT(m_pSocket), "button-press-event", G_CALLBACK(signalButton), this );
- g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );
- g_signal_connect( G_OBJECT(m_pSocket), "focus-in-event", G_CALLBACK(signalFocus), this );
- g_signal_connect( G_OBJECT(m_pSocket), "focus-out-event", G_CALLBACK(signalFocus), this );
- g_signal_connect( G_OBJECT(m_pSocket), "destroy", G_CALLBACK(signalDestroy), this );
-
- // #i59255# necessary due to sync effects with java child windows
- pParent->Flush();
-
-}
-
-GtkSalObject::~GtkSalObject()
-{
- if( m_pRegion )
- {
- gdk_region_destroy( m_pRegion );
- }
- if( m_pSocket )
- {
- // remove socket from parent frame's fixed container
- gtk_container_remove( GTK_CONTAINER(gtk_widget_get_parent(m_pSocket)),
- m_pSocket );
- // get rid of the socket
- // actually the gtk_container_remove should let the ref count
- // of the socket sink to 0 and destroy it (see signalDestroy)
- // this is just a sanity check
- if( m_pSocket )
- gtk_widget_destroy( m_pSocket );
- }
-}
-
-void GtkSalObject::ResetClipRegion()
-{
- if( m_pSocket )
- gdk_window_shape_combine_region( widget_get_window(m_pSocket), nullptr, 0, 0 );
-}
-
-void GtkSalObject::BeginSetClipRegion( sal_uInt32 )
-{
- if( m_pRegion )
- gdk_region_destroy( m_pRegion );
- m_pRegion = gdk_region_new();
-}
-
-void GtkSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
-{
- GdkRectangle aRect;
- aRect.x = nX;
- aRect.y = nY;
- aRect.width = nWidth;
- aRect.height = nHeight;
-
- gdk_region_union_with_rect( m_pRegion, &aRect );
-}
-
-void GtkSalObject::EndSetClipRegion()
-{
- if( m_pSocket )
- gdk_window_shape_combine_region( widget_get_window(m_pSocket), m_pRegion, 0, 0 );
-}
-
-void GtkSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
-{
- if( m_pSocket )
- {
- GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pSocket));
- gtk_fixed_move( pContainer, m_pSocket, nX, nY );
- gtk_widget_set_size_request( m_pSocket, nWidth, nHeight );
- gtk_container_resize_children( GTK_CONTAINER(pContainer) );
- }
-}
-
-void GtkSalObject::Show( bool bVisible )
-{
- if( m_pSocket )
- {
- if( bVisible )
- gtk_widget_show( m_pSocket );
- else
- gtk_widget_hide( m_pSocket );
- }
-}
-
-const SystemEnvData* GtkSalObject::GetSystemData() const
-{
- return &m_aSystemData;
-}
-
-gboolean GtkSalObject::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer object )
-{
- GtkSalObject* pThis = static_cast<GtkSalObject*>(object);
-
- if( pEvent->type == GDK_BUTTON_PRESS )
- {
- pThis->CallCallback( SalObjEvent::ToTop );
- }
-
- return FALSE;
-}
-
-gboolean GtkSalObject::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer object )
-{
- GtkSalObject* pThis = static_cast<GtkSalObject*>(object);
-
- pThis->CallCallback( pEvent->in ? SalObjEvent::GetFocus : SalObjEvent::LoseFocus );
-
- return FALSE;
-}
-
-void GtkSalObject::signalDestroy( GtkWidget* pObj, gpointer object )
-{
- GtkSalObject* pThis = static_cast<GtkSalObject*>(object);
- if( pObj == pThis->m_pSocket )
- {
- pThis->m_pSocket = nullptr;
- }
-}
-
-void GtkSalObject::SetForwardKey( bool bEnable )
-{
- if( bEnable )
- gtk_widget_add_events( GTK_WIDGET( m_pSocket ), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE );
- else
- gtk_widget_set_events( GTK_WIDGET( m_pSocket ), ~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE) & gtk_widget_get_events( GTK_WIDGET( m_pSocket ) ) );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtkprintwrapper.cxx b/vcl/unx/gtk/gtkprintwrapper.cxx
deleted file mode 100644
index 7e2241304f26..000000000000
--- a/vcl/unx/gtk/gtkprintwrapper.cxx
+++ /dev/null
@@ -1,349 +0,0 @@
-/* -*- 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/.
- */
-
-#include <cassert>
-
-#include <rtl/ustring.hxx>
-
-#include <unx/gtk/gtkprintwrapper.hxx>
-
-namespace vcl
-{
-namespace unx
-{
-
-#if !GTK_CHECK_VERSION(3,0,0)
-
-GtkPrintWrapper::GtkPrintWrapper()
- : m_page_setup_new(nullptr)
- , m_print_job_new(nullptr)
- , m_print_job_send(nullptr)
- , m_print_job_set_source_file(nullptr)
- , m_print_settings_get(nullptr)
- , m_print_settings_get_collate(nullptr)
- , m_print_settings_set_collate(nullptr)
- , m_print_settings_get_n_copies(nullptr)
- , m_print_settings_set_n_copies(nullptr)
- , m_print_settings_get_page_ranges(nullptr)
- , m_print_settings_set_print_pages(nullptr)
- , m_print_unix_dialog_new(nullptr)
- , m_print_unix_dialog_add_custom_tab(nullptr)
- , m_print_unix_dialog_get_selected_printer(nullptr)
- , m_print_unix_dialog_set_manual_capabilities(nullptr)
- , m_print_unix_dialog_get_settings(nullptr)
- , m_print_unix_dialog_set_settings(nullptr)
- , m_print_unix_dialog_set_support_selection(nullptr)
- , m_print_unix_dialog_set_has_selection(nullptr)
-{
- impl_load();
-}
-
-#else
-
-GtkPrintWrapper::GtkPrintWrapper()
-{
-}
-
-#endif
-
-GtkPrintWrapper::~GtkPrintWrapper()
-{
-}
-
-#if !GTK_CHECK_VERSION(3,0,0)
-
-void GtkPrintWrapper::impl_load()
-{
- m_aModule.load("libgtk-x11-2.0.so.0");
- if (!m_aModule.is())
- m_aModule.load("libgtk-x11-2.0.so");
- if (!m_aModule.is())
- return;
-
- m_page_setup_new = reinterpret_cast<page_setup_new_t>(m_aModule.getFunctionSymbol("gtk_page_setup_new"));
- m_print_job_new = reinterpret_cast<print_job_new_t>(m_aModule.getFunctionSymbol("gtk_print_job_new"));
- m_print_job_send = reinterpret_cast<print_job_send_t>(m_aModule.getFunctionSymbol("gtk_print_job_send"));
- m_print_job_set_source_file = reinterpret_cast<print_job_set_source_file_t>(m_aModule.getFunctionSymbol("gtk_print_job_set_source_file"));
- m_print_settings_get = reinterpret_cast<print_settings_get_t>(m_aModule.getFunctionSymbol("gtk_print_settings_get"));
- m_print_settings_get_collate = reinterpret_cast<print_settings_get_collate_t>(m_aModule.getFunctionSymbol("gtk_print_settings_get_collate"));
- m_print_settings_set_collate = reinterpret_cast<print_settings_set_collate_t>(m_aModule.getFunctionSymbol("gtk_print_settings_set_collate"));
- m_print_settings_get_n_copies = reinterpret_cast<print_settings_get_n_copies_t>(m_aModule.getFunctionSymbol("gtk_print_settings_get_n_copies"));
- m_print_settings_set_n_copies = reinterpret_cast<print_settings_set_n_copies_t>(m_aModule.getFunctionSymbol("gtk_print_settings_set_n_copies"));
- m_print_settings_get_page_ranges = reinterpret_cast<print_settings_get_page_ranges_t>(m_aModule.getFunctionSymbol("gtk_print_settings_get_page_ranges"));
- m_print_settings_set_print_pages = reinterpret_cast<print_settings_set_print_pages_t>(m_aModule.getFunctionSymbol("gtk_print_settings_set_print_pages"));
- m_print_unix_dialog_new = reinterpret_cast<print_unix_dialog_new_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_new"));
- m_print_unix_dialog_add_custom_tab = reinterpret_cast<print_unix_dialog_add_custom_tab_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_add_custom_tab"));
- m_print_unix_dialog_get_selected_printer = reinterpret_cast<print_unix_dialog_get_selected_printer_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_get_selected_printer"));
- m_print_unix_dialog_set_manual_capabilities = reinterpret_cast<print_unix_dialog_set_manual_capabilities_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_set_manual_capabilities"));
- m_print_unix_dialog_get_settings = reinterpret_cast<print_unix_dialog_get_settings_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_get_settings"));
- m_print_unix_dialog_set_settings = reinterpret_cast<print_unix_dialog_set_settings_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_set_settings"));
- m_print_unix_dialog_set_support_selection = reinterpret_cast<print_unix_dialog_set_support_selection_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_set_support_selection"));
- m_print_unix_dialog_set_has_selection = reinterpret_cast<print_unix_dialog_set_has_selection_t>(m_aModule.getFunctionSymbol("gtk_print_unix_dialog_set_has_selection"));
-}
-
-#endif
-
-bool GtkPrintWrapper::supportsPrinting() const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- return
- m_page_setup_new
- && m_print_job_new
- && m_print_job_send
- && m_print_job_set_source_file
- && m_print_settings_get
- && m_print_settings_get_collate
- && m_print_settings_set_collate
- && m_print_settings_get_n_copies
- && m_print_settings_set_n_copies
- && m_print_settings_get_page_ranges
- && m_print_settings_set_print_pages
- && m_print_unix_dialog_new
- && m_print_unix_dialog_add_custom_tab
- && m_print_unix_dialog_get_selected_printer
- && m_print_unix_dialog_set_manual_capabilities
- && m_print_unix_dialog_get_settings
- && m_print_unix_dialog_set_settings
- ;
-#else
- (void) this; // loplugin:staticmethods
- return true;
-#endif
-}
-
-bool GtkPrintWrapper::supportsPrintSelection() const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- return
- supportsPrinting()
- && m_print_unix_dialog_set_support_selection
- && m_print_unix_dialog_set_has_selection
- ;
-#else
- (void) this; // loplugin:staticmethods
- return true;
-#endif
-}
-
-GtkPageSetup* GtkPrintWrapper::page_setup_new() const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_page_setup_new);
- return (*m_page_setup_new)();
-#else
- (void) this; // loplugin:staticmethods
- return gtk_page_setup_new();
-#endif
-}
-
-GtkPrintJob* GtkPrintWrapper::print_job_new(const gchar* title, GtkPrinter* printer, GtkPrintSettings* settings, GtkPageSetup* page_setup) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_job_new);
- return (*m_print_job_new)(title, printer, settings, page_setup);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_job_new(title, printer, settings, page_setup);
-#endif
-}
-
-void GtkPrintWrapper::print_job_send(GtkPrintJob* job, GtkPrintJobCompleteFunc callback, gpointer user_data, GDestroyNotify dnotify) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_job_send);
- (*m_print_job_send)(job, callback, user_data, dnotify);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_job_send(job, callback, user_data, dnotify);
-#endif
-}
-
-gboolean GtkPrintWrapper::print_job_set_source_file(GtkPrintJob* job, const gchar* filename, GError** error) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_job_set_source_file);
- return (*m_print_job_set_source_file)(job, filename, error);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_job_set_source_file(job, filename, error);
-#endif
-}
-
-const gchar* GtkPrintWrapper::print_settings_get(GtkPrintSettings* settings, const gchar* key) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_get);
- return (*m_print_settings_get)(settings, key);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_settings_get(settings, key);
-#endif
-}
-
-gboolean GtkPrintWrapper::print_settings_get_collate(GtkPrintSettings* settings) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_get_collate);
- return (*m_print_settings_get_collate)(settings);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_settings_get_collate(settings);
-#endif
-}
-
-void GtkPrintWrapper::print_settings_set_collate(GtkPrintSettings* settings, gboolean collate) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_set_collate);
- (*m_print_settings_set_collate)(settings, collate);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_settings_set_collate(settings, collate);
-#endif
-}
-
-gint GtkPrintWrapper::print_settings_get_n_copies(GtkPrintSettings* settings) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_get_n_copies);
- return (*m_print_settings_get_n_copies)(settings);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_settings_get_n_copies(settings);
-#endif
-}
-
-void GtkPrintWrapper::print_settings_set_n_copies(GtkPrintSettings* settings, gint num_copies) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_set_n_copies);
- (*m_print_settings_set_n_copies)(settings, num_copies);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_settings_set_n_copies(settings, num_copies);
-#endif
-}
-
-GtkPageRange* GtkPrintWrapper::print_settings_get_page_ranges(GtkPrintSettings* settings, gint* num_ranges) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_get_page_ranges);
- return (*m_print_settings_get_page_ranges)(settings, num_ranges);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_settings_get_page_ranges(settings, num_ranges);
-#endif
-}
-
-void GtkPrintWrapper::print_settings_set_print_pages(GtkPrintSettings* settings, GtkPrintPages pages) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_settings_set_print_pages);
- (*m_print_settings_set_print_pages)(settings, pages);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_settings_set_print_pages(settings, pages);
-#endif
-}
-
-GtkWidget* GtkPrintWrapper::print_unix_dialog_new() const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_new);
- return (*m_print_unix_dialog_new)(nullptr, nullptr);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_unix_dialog_new(nullptr, nullptr);
-#endif
-}
-
-void GtkPrintWrapper::print_unix_dialog_add_custom_tab(GtkPrintUnixDialog* dialog, GtkWidget* child, GtkWidget* tab_label) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_add_custom_tab);
- (*m_print_unix_dialog_add_custom_tab)(dialog, child, tab_label);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_unix_dialog_add_custom_tab(dialog, child, tab_label);
-#endif
-}
-
-GtkPrinter* GtkPrintWrapper::print_unix_dialog_get_selected_printer(GtkPrintUnixDialog* dialog) const
-{
- GtkPrinter* pRet = nullptr;
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_get_selected_printer);
- pRet = (*m_print_unix_dialog_get_selected_printer)(dialog);
-#else
- (void) this; // loplugin:staticmethods
- pRet = gtk_print_unix_dialog_get_selected_printer(dialog);
-#endif
- g_object_ref(G_OBJECT(pRet));
- return pRet;
-}
-
-void GtkPrintWrapper::print_unix_dialog_set_manual_capabilities(GtkPrintUnixDialog* dialog, GtkPrintCapabilities capabilities) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_set_manual_capabilities);
- (*m_print_unix_dialog_set_manual_capabilities)(dialog, capabilities);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_unix_dialog_set_manual_capabilities(dialog, capabilities);
-#endif
-}
-
-GtkPrintSettings* GtkPrintWrapper::print_unix_dialog_get_settings(GtkPrintUnixDialog* dialog) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_get_settings);
- return (*m_print_unix_dialog_get_settings)(dialog);
-#else
- (void) this; // loplugin:staticmethods
- return gtk_print_unix_dialog_get_settings(dialog);
-#endif
-}
-
-void GtkPrintWrapper::print_unix_dialog_set_settings(GtkPrintUnixDialog* dialog, GtkPrintSettings* settings) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_set_settings);
- (*m_print_unix_dialog_set_settings)(dialog, settings);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_unix_dialog_set_settings(dialog, settings);
-#endif
-}
-
-void GtkPrintWrapper::print_unix_dialog_set_support_selection(GtkPrintUnixDialog* dialog, gboolean support_selection) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_set_support_selection);
- (*m_print_unix_dialog_set_support_selection)(dialog, support_selection);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_unix_dialog_set_support_selection(dialog, support_selection);
-#endif
-}
-
-void GtkPrintWrapper::print_unix_dialog_set_has_selection(GtkPrintUnixDialog* dialog, gboolean has_selection) const
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- assert(m_print_unix_dialog_set_has_selection);
- (*m_print_unix_dialog_set_has_selection)(dialog, has_selection);
-#else
- (void) this; // loplugin:staticmethods
- gtk_print_unix_dialog_set_has_selection(dialog, has_selection);
-#endif
-}
-
-}
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
deleted file mode 100644
index 2601d7d675fb..000000000000
--- a/vcl/unx/gtk/gtksalframe.cxx
+++ /dev/null
@@ -1,3606 +0,0 @@
-/* -*- 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 .
- */
-
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkgdi.hxx>
-#include <unx/gtk/gtksalmenu.hxx>
-#include <vcl/keycodes.hxx>
-#include <vcl/layout.hxx>
-#include <unx/wmadaptor.hxx>
-#include <unx/sm.hxx>
-#include <unx/salbmp.h>
-#include <unx/genprn.h>
-#include <unx/geninst.h>
-#include <headless/svpgdi.hxx>
-#include <osl/file.hxx>
-#include <rtl/bootstrap.hxx>
-#include <rtl/process.h>
-#include <sal/log.hxx>
-#include <tools/diagnose_ex.h>
-#include <vcl/floatwin.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/window.hxx>
-#include <vcl/settings.hxx>
-#include <vcl/opengl/OpenGLHelper.hxx>
-
-#include <config_gio.h>
-
-#include <unx/x11/xlimits.hxx>
-#if defined ENABLE_GMENU_INTEGRATION // defined in gtksalmenu.hxx above
-# include <unx/gtk/hudawareness.h>
-#endif
-
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <X11/Xatom.h>
-
-#include <dlfcn.h>
-#include <window.h>
-#include <strings.hrc>
-#include <bitmaps.hlst>
-#include <sal/macros.h>
-
-#include <basegfx/range/b2ibox.hxx>
-#include <basegfx/vector/b2ivector.hxx>
-
-#include <algorithm>
-#include <glib/gprintf.h>
-
-#if OSL_DEBUG_LEVEL > 1
-# include <cstdio>
-#endif
-
-#include <com/sun/star/accessibility/XAccessibleContext.hpp>
-#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
-
-#include <config_folders.h>
-
-#define IS_WIDGET_REALIZED GTK_WIDGET_REALIZED
-#define IS_WIDGET_MAPPED GTK_WIDGET_MAPPED
-
-using namespace com::sun::star;
-
-int GtkSalFrame::m_nFloats = 0;
-
-#if defined ENABLE_GMENU_INTEGRATION
-static GDBusConnection* pSessionBus = nullptr;
-#endif
-
-sal_uInt16 GtkSalFrame::GetKeyModCode( guint state )
-{
- sal_uInt16 nCode = 0;
- if( state & GDK_SHIFT_MASK )
- nCode |= KEY_SHIFT;
- if( state & GDK_CONTROL_MASK )
- nCode |= KEY_MOD1;
- if( state & GDK_MOD1_MASK )
- nCode |= KEY_MOD2;
-
- // Map Meta/Super keys to MOD3 modifier on all Unix systems
- // except macOS
- if ( (state & GDK_META_MASK ) || ( state & GDK_SUPER_MASK ) )
- nCode |= KEY_MOD3;
- return nCode;
-}
-
-sal_uInt16 GtkSalFrame::GetMouseModCode( guint state )
-{
- sal_uInt16 nCode = GetKeyModCode( state );
- if( state & GDK_BUTTON1_MASK )
- nCode |= MOUSE_LEFT;
- if( state & GDK_BUTTON2_MASK )
- nCode |= MOUSE_MIDDLE;
- if( state & GDK_BUTTON3_MASK )
- nCode |= MOUSE_RIGHT;
-
- return nCode;
-}
-
-sal_uInt16 GtkSalFrame::GetKeyCode(guint keyval)
-{
- sal_uInt16 nCode = 0;
- if( keyval >= GDK_KEY_0 && keyval <= GDK_KEY_9 )
- nCode = KEY_0 + (keyval-GDK_KEY_0);
- else if( keyval >= GDK_KEY_KP_0 && keyval <= GDK_KEY_KP_9 )
- nCode = KEY_0 + (keyval-GDK_KEY_KP_0);
- else if( keyval >= GDK_KEY_A && keyval <= GDK_KEY_Z )
- nCode = KEY_A + (keyval-GDK_KEY_A );
- else if( keyval >= GDK_KEY_a && keyval <= GDK_KEY_z )
- nCode = KEY_A + (keyval-GDK_KEY_a );
- else if( keyval >= GDK_KEY_F1 && keyval <= GDK_KEY_F26 )
- // KEY_F26 is the last function key known to keycodes.hxx
- {
- if( GetGtkSalData()->GetGtkDisplay()->IsNumLockFromXS() )
- {
- nCode = KEY_F1 + (keyval-GDK_KEY_F1);
- }
- else
- {
- switch( keyval )
- {
- // - - - - - Sun keyboard, see vcl/unx/source/app/saldisp.cxx
- // although GDK_KEY_F1 ... GDK_KEY_L10 are known to
- // gdk/gdkkeysyms.h, they are unlikely to be generated
- // except possibly by Solaris systems
- // this whole section needs review
- case GDK_KEY_L2:
- if( GetGtkSalData()->GetGtkDisplay()->GetServerVendor() == vendor_sun )
- nCode = KEY_REPEAT;
- else
- nCode = KEY_F12;
- break;
- case GDK_KEY_L3: nCode = KEY_PROPERTIES; break;
- case GDK_KEY_L4: nCode = KEY_UNDO; break;
- case GDK_KEY_L6: nCode = KEY_COPY; break; // KEY_F16
- case GDK_KEY_L8: nCode = KEY_PASTE; break; // KEY_F18
- case GDK_KEY_L10: nCode = KEY_CUT; break; // KEY_F20
- default:
- nCode = KEY_F1 + (keyval-GDK_KEY_F1); break;
- }
- }
- }
- else
- {
- switch( keyval )
- {
- case GDK_KEY_KP_Down:
- case GDK_KEY_Down: nCode = KEY_DOWN; break;
- case GDK_KEY_KP_Up:
- case GDK_KEY_Up: nCode = KEY_UP; break;
- case GDK_KEY_KP_Left:
- case GDK_KEY_Left: nCode = KEY_LEFT; break;
- case GDK_KEY_KP_Right:
- case GDK_KEY_Right: nCode = KEY_RIGHT; break;
- case GDK_KEY_KP_Begin:
- case GDK_KEY_KP_Home:
- case GDK_KEY_Begin:
- case GDK_KEY_Home: nCode = KEY_HOME; break;
- case GDK_KEY_KP_End:
- case GDK_KEY_End: nCode = KEY_END; break;
- case GDK_KEY_KP_Page_Up:
- case GDK_KEY_Page_Up: nCode = KEY_PAGEUP; break;
- case GDK_KEY_KP_Page_Down:
- case GDK_KEY_Page_Down: nCode = KEY_PAGEDOWN; break;
- case GDK_KEY_KP_Enter:
- case GDK_KEY_Return: nCode = KEY_RETURN; break;
- case GDK_KEY_Escape: nCode = KEY_ESCAPE; break;
- case GDK_KEY_ISO_Left_Tab:
- case GDK_KEY_KP_Tab:
- case GDK_KEY_Tab: nCode = KEY_TAB; break;
- case GDK_KEY_BackSpace: nCode = KEY_BACKSPACE; break;
- case GDK_KEY_KP_Space:
- case GDK_KEY_space: nCode = KEY_SPACE; break;
- case GDK_KEY_KP_Insert:
- case GDK_KEY_Insert: nCode = KEY_INSERT; break;
- case GDK_KEY_KP_Delete:
- case GDK_KEY_Delete: nCode = KEY_DELETE; break;
- case GDK_KEY_plus:
- case GDK_KEY_KP_Add: nCode = KEY_ADD; break;
- case GDK_KEY_minus:
- case GDK_KEY_KP_Subtract: nCode = KEY_SUBTRACT; break;
- case GDK_KEY_asterisk:
- case GDK_KEY_KP_Multiply: nCode = KEY_MULTIPLY; break;
- case GDK_KEY_slash:
- case GDK_KEY_KP_Divide: nCode = KEY_DIVIDE; break;
- case GDK_KEY_period: nCode = KEY_POINT; break;
- case GDK_KEY_decimalpoint: nCode = KEY_POINT; break;
- case GDK_KEY_comma: nCode = KEY_COMMA; break;
- case GDK_KEY_less: nCode = KEY_LESS; break;
- case GDK_KEY_greater: nCode = KEY_GREATER; break;
- case GDK_KEY_KP_Equal:
- case GDK_KEY_equal: nCode = KEY_EQUAL; break;
- case GDK_KEY_Find: nCode = KEY_FIND; break;
- case GDK_KEY_Menu: nCode = KEY_CONTEXTMENU;break;
- case GDK_KEY_Help: nCode = KEY_HELP; break;
- case GDK_KEY_Undo: nCode = KEY_UNDO; break;
- case GDK_KEY_Redo: nCode = KEY_REPEAT; break;
- // on a sun keyboard this actually is usually SunXK_Stop = 0x0000FF69 (XK_Cancel),
- // but VCL doesn't have a key definition for that
- case GDK_KEY_Cancel: nCode = KEY_F11; break;
- case GDK_KEY_KP_Decimal:
- case GDK_KEY_KP_Separator: nCode = KEY_DECIMAL; break;
- case GDK_KEY_asciitilde: nCode = KEY_TILDE; break;
- case GDK_KEY_leftsinglequotemark:
- case GDK_KEY_quoteleft: nCode = KEY_QUOTELEFT; break;
- case GDK_KEY_bracketleft: nCode = KEY_BRACKETLEFT; break;
- case GDK_KEY_bracketright: nCode = KEY_BRACKETRIGHT; break;
- case GDK_KEY_semicolon: nCode = KEY_SEMICOLON; break;
- case GDK_KEY_quoteright: nCode = KEY_QUOTERIGHT; break;
- // some special cases, also see saldisp.cxx
- // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
- // These can be found in ap_keysym.h
- case 0x1000FF02: // apXK_Copy
- nCode = KEY_COPY;
- break;
- case 0x1000FF03: // apXK_Cut
- nCode = KEY_CUT;
- break;
- case 0x1000FF04: // apXK_Paste
- nCode = KEY_PASTE;
- break;
- case 0x1000FF14: // apXK_Repeat
- nCode = KEY_REPEAT;
- break;
- // Exit, Save
- // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
- // These can be found in DECkeysym.h
- case 0x1000FF00:
- nCode = KEY_DELETE;
- break;
- // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
- // These can be found in HPkeysym.h
- case 0x1000FF73: // hpXK_DeleteChar
- nCode = KEY_DELETE;
- break;
- case 0x1000FF74: // hpXK_BackTab
- case 0x1000FF75: // hpXK_KP_BackTab
- nCode = KEY_TAB;
- break;
- // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
- // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
- // These also can be found in HPkeysym.h
- case 0x1004FF02: // osfXK_Copy
- nCode = KEY_COPY;
- break;
- case 0x1004FF03: // osfXK_Cut
- nCode = KEY_CUT;
- break;
- case 0x1004FF04: // osfXK_Paste
- nCode = KEY_PASTE;
- break;
- case 0x1004FF07: // osfXK_BackTab
- nCode = KEY_TAB;
- break;
- case 0x1004FF08: // osfXK_BackSpace
- nCode = KEY_BACKSPACE;
- break;
- case 0x1004FF1B: // osfXK_Escape
- nCode = KEY_ESCAPE;
- break;
- // Up, Down, Left, Right, PageUp, PageDown
- // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
- // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
- // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
- // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
- // These can be found in Sunkeysym.h
- case 0x1005FF10: // SunXK_F36
- nCode = KEY_F11;
- break;
- case 0x1005FF11: // SunXK_F37
- nCode = KEY_F12;
- break;
- case 0x1005FF70: // SunXK_Props
- nCode = KEY_PROPERTIES;
- break;
- case 0x1005FF71: // SunXK_Front
- nCode = KEY_FRONT;
- break;
- case 0x1005FF72: // SunXK_Copy
- nCode = KEY_COPY;
- break;
- case 0x1005FF73: // SunXK_Open
- nCode = KEY_OPEN;
- break;
- case 0x1005FF74: // SunXK_Paste
- nCode = KEY_PASTE;
- break;
- case 0x1005FF75: // SunXK_Cut
- nCode = KEY_CUT;
- break;
- // - - - - - - - - - - - - - X F 8 6 - - - - - - - - - - - - - 0x1008
- // These can be found in XF86keysym.h
- // but more importantly they are also available GTK/Gdk version 3
- // and hence are already provided in gdk/gdkkeysyms.h, and hence
- // in gdk/gdk.h
- case GDK_KEY_Copy: nCode = KEY_COPY; break; // 0x1008ff57
- case GDK_KEY_Cut: nCode = KEY_CUT; break; // 0x1008ff58
- case GDK_KEY_Open: nCode = KEY_OPEN; break; // 0x1008ff6b
- case GDK_KEY_Paste: nCode = KEY_PASTE; break; // 0x1008ff6d
- }
- }
-
- return nCode;
-}
-
-guint GtkSalFrame::GetKeyValFor(GdkKeymap* pKeyMap, guint16 hardware_keycode, guint8 group)
-{
- guint updated_keyval = 0;
- gdk_keymap_translate_keyboard_state(pKeyMap, hardware_keycode,
- GdkModifierType(0), group, &updated_keyval, nullptr, nullptr, nullptr);
- return updated_keyval;
-}
-
-// F10 means either KEY_F10 or KEY_MENU, which has to be decided
-// in the independent part.
-struct KeyAlternate
-{
- sal_uInt16 nKeyCode;
- sal_Unicode nCharCode;
- KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
- KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
-};
-
-static KeyAlternate
-GetAlternateKeyCode( const sal_uInt16 nKeyCode )
-{
- KeyAlternate aAlternate;
-
- switch( nKeyCode )
- {
- case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
- case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
- }
-
- return aAlternate;
-}
-
-bool GtkSalFrame::doKeyCallback( guint state,
- guint keyval,
- guint16 hardware_keycode,
- guint8 group,
- sal_Unicode aOrigCode,
- bool bDown,
- bool bSendRelease
- )
-{
- SalKeyEvent aEvent;
-
- aEvent.mnCharCode = aOrigCode;
- aEvent.mnRepeat = 0;
-
- vcl::DeletionListener aDel( this );
-
- /*
- * #i42122# translate all keys with Ctrl and/or Alt to group 0 else
- * shortcuts (e.g. Ctrl-o) will not work but be inserted by the
- * application
- *
- * #i52338# do this for all keys that the independent part has no key code
- * for
- *
- * fdo#41169 rather than use group 0, detect if there is a group which can
- * be used to input Latin text and use that if possible
- */
- aEvent.mnCode = GetKeyCode( keyval );
- if( aEvent.mnCode == 0 )
- {
- gint best_group = SAL_MAX_INT32;
-
- // Try and find Latin layout
- GdkKeymap* keymap = gdk_keymap_get_default();
- GdkKeymapKey *keys;
- gint n_keys;
- if (gdk_keymap_get_entries_for_keyval(keymap, GDK_KEY_A, &keys, &n_keys))
- {
- // Find the lowest group that supports Latin layout
- for (gint i = 0; i < n_keys; ++i)
- {
- if (keys[i].level != 0 && keys[i].level != 1)
- continue;
- best_group = std::min(best_group, keys[i].group);
- if (best_group == 0)
- break;
- }
- g_free(keys);
- }
-
- //Unavailable, go with original group then I suppose
- if (best_group == SAL_MAX_INT32)
- best_group = group;
-
- guint updated_keyval = GetKeyValFor(keymap, hardware_keycode, best_group);
- aEvent.mnCode = GetKeyCode(updated_keyval);
- }
-
- aEvent.mnCode |= GetKeyModCode( state );
-
- if( bDown )
- {
- bool bHandled = CallCallback( SalEvent::KeyInput, &aEvent );
- // #i46889# copy AlternateKeyCode handling from generic plugin
- if( ! bHandled )
- {
- KeyAlternate aAlternate = GetAlternateKeyCode( aEvent.mnCode );
- if( aAlternate.nKeyCode )
- {
- aEvent.mnCode = aAlternate.nKeyCode;
- if( aAlternate.nCharCode )
- aEvent.mnCharCode = aAlternate.nCharCode;
- CallCallback( SalEvent::KeyInput, &aEvent );
- }
- }
- if( bSendRelease && ! aDel.isDeleted() )
- {
- CallCallback( SalEvent::KeyUp, &aEvent );
- }
- }
- else
- CallCallback( SalEvent::KeyUp, &aEvent );
-
- return false;
-}
-
-GtkSalFrame::GtkSalFrame( SalFrame* pParent, SalFrameStyleFlags nStyle )
- : m_nXScreen( getDisplay()->GetDefaultXScreen() )
- , m_bGraphics(false)
-{
- getDisplay()->registerFrame( this );
- m_bDefaultPos = true;
- m_bDefaultSize = ( (nStyle & SalFrameStyleFlags::SIZEABLE) && ! pParent );
- m_bWindowIsGtkPlug = false;
- Init( pParent, nStyle );
-}
-
-GtkSalFrame::GtkSalFrame( SystemParentData* pSysData )
- : m_nXScreen( getDisplay()->GetDefaultXScreen() )
- , m_bGraphics(false)
-{
- getDisplay()->registerFrame( this );
- // permanently ignore errors from our unruly children ...
- GetGenericUnixSalData()->ErrorTrapPush();
- m_bDefaultPos = true;
- m_bDefaultSize = true;
- Init( pSysData );
-}
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-static void
-gdk_x11_window_set_utf8_property (GdkWindow *window,
- const gchar *name,
- const gchar *value)
-{
- GdkDisplay* display = gdk_window_get_display (window);
-
- if (value != nullptr)
- {
- XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
- gdk_x11_get_xatom_by_name_for_display (display, name),
- gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
- PropModeReplace, reinterpret_cast<guchar const *>(value), strlen (value));
- }
- else
- {
- XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
- gdk_x11_get_xatom_by_name_for_display (display, name));
- }
-}
-
-// AppMenu watch functions.
-
-static void ObjectDestroyedNotify( gpointer data )
-{
- if ( data ) {
- g_object_unref( data );
- }
-}
-
-static void hud_activated( gboolean hud_active, gpointer user_data )
-{
- if ( hud_active )
- {
- SolarMutexGuard aGuard;
- GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
- GtkSalMenu* pSalMenu = reinterpret_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
-
- if ( pSalMenu )
- pSalMenu->UpdateFull();
- }
-}
-
-static gboolean ensure_dbus_setup( gpointer data )
-{
- GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( data );
- GdkWindow* gdkWindow = widget_get_window( pSalFrame->getWindow() );
-
- if ( gdkWindow != nullptr && g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) == nullptr )
- {
- // Get a DBus session connection.
- if(!pSessionBus)
- pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr);
- if( !pSessionBus )
- {
- return FALSE;
- }
-
- // Create menu model and action group attached to this frame.
- GMenuModel* pMenuModel = G_MENU_MODEL( g_lo_menu_new() );
- GActionGroup* pActionGroup = reinterpret_cast<GActionGroup*>(g_lo_action_group_new());
-
- // Generate menu paths.
- ::Window windowId = GDK_WINDOW_XID( gdkWindow );
- gchar* aDBusWindowPath = g_strdup_printf( "/org/libreoffice/window/%lu", windowId );
- gchar* aDBusMenubarPath = g_strdup_printf( "/org/libreoffice/window/%lu/menus/menubar", windowId );
-
- // Set window properties.
- g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", pMenuModel, ObjectDestroyedNotify );
- g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", pActionGroup, ObjectDestroyedNotify );
-
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_APPLICATION_ID", "org.libreoffice" );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_UNIQUE_BUS_NAME", g_dbus_connection_get_unique_name( pSessionBus ) );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", "/org/libreoffice" );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_WINDOW_OBJECT_PATH", aDBusWindowPath );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", aDBusMenubarPath );
-
- // Publish the menu model and the action group.
- SAL_INFO("vcl.unity", "exporting menu model at " << pMenuModel << " for window " << windowId);
- pSalFrame->m_nMenuExportId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, pMenuModel, nullptr);
- SAL_INFO("vcl.unity", "exporting action group at " << pActionGroup << " for window " << windowId);
- pSalFrame->m_nActionGroupExportId = g_dbus_connection_export_action_group( pSessionBus, aDBusWindowPath, pActionGroup, nullptr);
- pSalFrame->m_nHudAwarenessId = hud_awareness_register( pSessionBus, aDBusMenubarPath, hud_activated, pSalFrame, nullptr, nullptr );
-
- g_free( aDBusWindowPath );
- g_free( aDBusMenubarPath );
- }
-
- return FALSE;
-}
-
-void on_registrar_available( GDBusConnection * /*connection*/,
- const gchar * /*name*/,
- const gchar * /*name_owner*/,
- gpointer user_data )
-{
- SolarMutexGuard aGuard;
-
- GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
-
- SalMenu* pSalMenu = pSalFrame->GetMenu();
-
- if ( pSalMenu != nullptr )
- {
- GtkSalMenu* pGtkSalMenu = static_cast<GtkSalMenu*>(pSalMenu);
- pGtkSalMenu->EnableUnity(true);
- }
-}
-
-// This is called when the registrar becomes unavailable. It shows the menubar.
-void on_registrar_unavailable( GDBusConnection * /*connection*/,
- const gchar * /*name*/,
- gpointer user_data )
-{
- SolarMutexGuard aGuard;
-
- SAL_INFO("vcl.unity", "on_registrar_unavailable");
-
- //pSessionBus = NULL;
- GtkSalFrame* pSalFrame = static_cast< GtkSalFrame* >( user_data );
-
- SalMenu* pSalMenu = pSalFrame->GetMenu();
-
- if ( pSalMenu ) {
- GtkSalMenu* pGtkSalMenu = static_cast< GtkSalMenu* >( pSalMenu );
- pGtkSalMenu->EnableUnity(false);
- }
-}
-#endif
-
-void GtkSalFrame::EnsureAppMenuWatch()
-{
-#ifdef ENABLE_GMENU_INTEGRATION
- if ( !m_nWatcherId )
- {
- // Get a DBus session connection.
- if ( pSessionBus == nullptr )
- {
- pSessionBus = g_bus_get_sync( G_BUS_TYPE_SESSION, nullptr, nullptr );
-
- if ( pSessionBus == nullptr )
- return;
- }
-
- // Publish the menu only if AppMenu registrar is available.
- m_nWatcherId = g_bus_watch_name_on_connection( pSessionBus,
- "com.canonical.AppMenu.Registrar",
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- on_registrar_available,
- on_registrar_unavailable,
- this,
- nullptr );
- }
-#else
- (void) this; // loplugin:staticmethods
-#endif
-}
-
-void GtkSalFrame::InvalidateGraphics()
-{
- if( m_pGraphics )
- {
- m_pGraphics->DeInit();
- m_pGraphics->SetWindow(nullptr);
- m_pGraphics.reset();
- }
-}
-
-GtkSalFrame::~GtkSalFrame()
-{
- InvalidateGraphics();
-
- if( m_pParent )
- m_pParent->m_aChildren.remove( this );
-
- getDisplay()->deregisterFrame( this );
-
- if( m_pRegion )
- {
- gdk_region_destroy( m_pRegion );
- }
-
- m_pIMHandler.reset();
-
- GtkWidget *pEventWidget = getMouseEventWidget();
- for (auto handler_id : m_aMouseSignalIds)
- g_signal_handler_disconnect(G_OBJECT(pEventWidget), handler_id);
- if( m_pFixedContainer )
- gtk_widget_destroy( GTK_WIDGET( m_pFixedContainer ) );
- if( m_pEventBox )
- gtk_widget_destroy( GTK_WIDGET(m_pEventBox) );
- {
- SolarMutexGuard aGuard;
-#if defined ENABLE_GMENU_INTEGRATION
- if(m_nWatcherId)
- g_bus_unwatch_name(m_nWatcherId);
-#endif
- if( m_pWindow )
- {
- g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", nullptr );
-
-#if defined ENABLE_GMENU_INTEGRATION
- if ( pSessionBus )
- {
- if ( m_nHudAwarenessId )
- hud_awareness_unregister( pSessionBus, m_nHudAwarenessId );
- if ( m_nMenuExportId )
- g_dbus_connection_unexport_menu_model( pSessionBus, m_nMenuExportId );
- if ( m_nActionGroupExportId )
- g_dbus_connection_unexport_action_group( pSessionBus, m_nActionGroupExportId );
- }
-#endif
- gtk_widget_destroy( m_pWindow );
- }
- }
- if( m_pForeignParent )
- g_object_unref( G_OBJECT( m_pForeignParent ) );
- if( m_pForeignTopLevel )
- g_object_unref( G_OBJECT( m_pForeignTopLevel) );
-}
-
-void GtkSalFrame::moveWindow( long nX, long nY )
-{
- if( isChild( false ) )
- {
- if( m_pParent )
- gtk_fixed_move( m_pParent->getFixedContainer(),
- m_pWindow,
- nX - m_pParent->maGeometry.nX, nY - m_pParent->maGeometry.nY );
- }
- else
- gtk_window_move( GTK_WINDOW(m_pWindow), nX, nY );
-}
-
-void GtkSalFrame::widget_set_size_request(long nWidth, long nHeight)
-{
- gtk_widget_set_size_request(m_pWindow, nWidth, nHeight );
-}
-
-void GtkSalFrame::window_resize(long nWidth, long nHeight)
-{
- gtk_window_resize(GTK_WINDOW(m_pWindow), nWidth, nHeight);
-}
-
-void GtkSalFrame::resizeWindow( long nWidth, long nHeight )
-{
- if( isChild( false ) )
- {
- widget_set_size_request(nWidth, nHeight);
- }
- else if( ! isChild( true, false ) )
- window_resize(nWidth, nHeight);
-}
-
-// tdf#124694 GtkFixed takes the max size of all its children as its
-// preferred size, causing it to not clip its child, but grow instead.
-
-static void
-ooo_fixed_size_request(GtkWidget*, GtkRequisition* req)
-{
- req->width = 0;
- req->height = 0;
-}
-
-static void
-ooo_fixed_class_init(GtkFixedClass *klass)
-{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
- widget_class->size_request = ooo_fixed_size_request;
-}
-
-/*
- * Always use a sub-class of GtkFixed we can tag for a11y. This allows us to
- * utilize GAIL for the toplevel window and toolkit implementation incl.
- * key event listener support ..
- */
-
-GType
-ooo_fixed_get_type()
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo tinfo =
- {
- sizeof (GtkFixedClass),
- nullptr, /* base init */
- nullptr, /* base finalize */
- reinterpret_cast<GClassInitFunc>(ooo_fixed_class_init), /* class init */
- nullptr, /* class finalize */
- nullptr, /* class data */
- sizeof (GtkFixed), /* instance size */
- 0, /* nb preallocs */
- nullptr, /* instance init */
- nullptr /* value table */
- };
-
- type = g_type_register_static( GTK_TYPE_FIXED, "OOoFixed",
- &tinfo, GTypeFlags(0));
- }
-
- return type;
-}
-
-void GtkSalFrame::updateScreenNumber()
-{
- int nScreen = 0;
- GdkScreen *pScreen = gtk_widget_get_screen( m_pWindow );
- if( pScreen )
- nScreen = getDisplay()->getSystem()->getScreenMonitorIdx( pScreen, maGeometry.nX, maGeometry.nY );
- maGeometry.nDisplayScreenNumber = nScreen;
-}
-
-GtkWidget *GtkSalFrame::getMouseEventWidget() const
-{
- return m_pWindow;
-}
-
-void GtkSalFrame::InitCommon()
-{
- m_pEventBox = nullptr;
- // add the fixed container child,
- // fixed is needed since we have to position plugin windows
- m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), nullptr ));
- gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pFixedContainer) );
-
- GtkWidget *pEventWidget = getMouseEventWidget();
-
- gtk_widget_set_app_paintable(GTK_WIDGET(m_pFixedContainer), true);
- gtk_widget_set_double_buffered(GTK_WIDGET(m_pFixedContainer), false);
- gtk_widget_set_redraw_on_allocate(GTK_WIDGET(m_pFixedContainer), false);
-
-
- // connect signals
- g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this );
- m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-press-event", G_CALLBACK(signalButton), this ));
- m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "motion-notify-event", G_CALLBACK(signalMotion), this ));
- m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "button-release-event", G_CALLBACK(signalButton), this ));
- g_signal_connect( G_OBJECT(m_pFixedContainer), "expose-event", G_CALLBACK(signalExpose), this );
- g_signal_connect( G_OBJECT(m_pWindow), "focus-in-event", G_CALLBACK(signalFocus), this );
- g_signal_connect( G_OBJECT(m_pWindow), "focus-out-event", G_CALLBACK(signalFocus), this );
- g_signal_connect( G_OBJECT(m_pWindow), "map-event", G_CALLBACK(signalMap), this );
- g_signal_connect( G_OBJECT(m_pWindow), "unmap-event", G_CALLBACK(signalUnmap), this );
- g_signal_connect( G_OBJECT(m_pWindow), "configure-event", G_CALLBACK(signalConfigure), this );
- g_signal_connect( G_OBJECT(m_pWindow), "key-press-event", G_CALLBACK(signalKey), this );
- g_signal_connect( G_OBJECT(m_pWindow), "key-release-event", G_CALLBACK(signalKey), this );
- g_signal_connect( G_OBJECT(m_pWindow), "delete-event", G_CALLBACK(signalDelete), this );
- g_signal_connect( G_OBJECT(m_pWindow), "window-state-event", G_CALLBACK(signalWindowState), this );
- g_signal_connect( G_OBJECT(m_pWindow), "scroll-event", G_CALLBACK(signalScroll), this );
- g_signal_connect( G_OBJECT(m_pWindow), "leave-notify-event", G_CALLBACK(signalCrossing), this );
- g_signal_connect( G_OBJECT(m_pWindow), "enter-notify-event", G_CALLBACK(signalCrossing), this );
- g_signal_connect( G_OBJECT(m_pWindow), "visibility-notify-event", G_CALLBACK(signalVisibility), this );
- g_signal_connect( G_OBJECT(m_pWindow), "destroy", G_CALLBACK(signalDestroy), this );
-
- // init members
- m_pCurrentCursor = nullptr;
- m_nKeyModifiers = ModKeyFlags::NONE;
- m_bFullscreen = false;
- m_bSpanMonitorsWhenFullscreen = false;
- m_nState = GDK_WINDOW_STATE_WITHDRAWN;
- m_pIMHandler = nullptr;
- m_pRegion = nullptr;
- m_ePointerStyle = static_cast<PointerStyle>(0xffff);
- m_bSetFocusOnMap = false;
- m_pSalMenu = nullptr;
- m_nWatcherId = 0;
- m_nMenuExportId = 0;
- m_nActionGroupExportId = 0;
- m_nHudAwarenessId = 0;
-
- gtk_widget_add_events( m_pWindow,
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
- GDK_VISIBILITY_NOTIFY_MASK | GDK_SCROLL_MASK
- );
-
- // show the widgets
- gtk_widget_show_all( GTK_WIDGET(m_pFixedContainer) );
-
- // realize the window, we need an XWindow id
- gtk_widget_realize( m_pWindow );
-
- //system data
- m_aSystemData.nSize = sizeof( SystemEnvData );
- GtkSalDisplay* pDisp = GetGtkSalData()->GetGtkDisplay();
- m_aSystemData.pDisplay = pDisp->GetDisplay();
- m_aSystemData.pVisual = pDisp->GetVisual( m_nXScreen ).GetVisual();
- m_aSystemData.aWindow = widget_get_xid(m_pWindow);
- m_aSystemData.aShellWindow = m_aSystemData.aWindow;
- m_aSystemData.pSalFrame = this;
- m_aSystemData.pWidget = m_pWindow;
- m_aSystemData.nScreen = m_nXScreen.getXScreen();
- m_aSystemData.pToolkit = "gtk2";
- m_aSystemData.pPlatformName = "xcb";
-
- m_bGraphics = false;
- m_pGraphics = nullptr;
-
- // fake an initial geometry, gets updated via configure event or SetPosSize
- if( m_bDefaultPos || m_bDefaultSize )
- {
- Size aDefSize = calcDefaultSize();
- maGeometry.nX = -1;
- maGeometry.nY = -1;
- maGeometry.nWidth = aDefSize.Width();
- maGeometry.nHeight = aDefSize.Height();
- if( m_pParent )
- {
- // approximation
- maGeometry.nTopDecoration = m_pParent->maGeometry.nTopDecoration;
- maGeometry.nBottomDecoration = m_pParent->maGeometry.nBottomDecoration;
- maGeometry.nLeftDecoration = m_pParent->maGeometry.nLeftDecoration;
- maGeometry.nRightDecoration = m_pParent->maGeometry.nRightDecoration;
- }
- else
- {
- maGeometry.nTopDecoration = 0;
- maGeometry.nBottomDecoration = 0;
- maGeometry.nLeftDecoration = 0;
- maGeometry.nRightDecoration = 0;
- }
- }
- else
- {
- resizeWindow( maGeometry.nWidth, maGeometry.nHeight );
- moveWindow( maGeometry.nX, maGeometry.nY );
- }
- updateScreenNumber();
-
- SetIcon(SV_ICON_ID_OFFICE);
-
- m_nWorkArea = pDisp->getWMAdaptor()->getCurrentWorkArea();
- /* #i64117# gtk sets a nice background pixmap
- * but we actually don't really want that, so save
- * some time on the Xserver as well as prevent
- * some paint issues
- */
- XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- None );
-}
-
-static void lcl_set_accept_focus( GtkWindow* pWindow )
-{
- if (GetGtkSalData()->GetGtkDisplay()->getWMAdaptor()->getWindowManagerName().startsWith("Metacity"))
- {
- /* Metacity considers a toolbar type window as should not
- * have focus on mapping, yet it believes it should unfocus
- * the parent window... So convince Metacity to not do so,
- * by disabling the focus until the window is mapped. We
- * will restore the focus later in the map signal.
- */
- gtk_window_set_accept_focus( pWindow, false );
-
- /* remove WM_TAKE_FOCUS protocol; this would usually be the
- * right thing, but gtk handles it internally whereas we
- * want to handle it ourselves (as to sometimes not get
- * the focus)
- */
- Display* pDisplay = GetGtkSalData()->GetGtkDisplay()->GetDisplay();
- ::Window aWindow = widget_get_xid(GTK_WIDGET(pWindow));
- Atom* pProtocols = nullptr;
- int nProtocols = 0;
- XGetWMProtocols( pDisplay,
- aWindow,
- &pProtocols, &nProtocols );
- if( pProtocols )
- {
- bool bSet = false;
- Atom nTakeFocus = XInternAtom( pDisplay, "WM_TAKE_FOCUS", True );
- if( nTakeFocus )
- {
- for( int i = 0; i < nProtocols; i++ )
- {
- if( pProtocols[i] == nTakeFocus )
- {
- for( int n = i; n < nProtocols-1; n++ )
- pProtocols[n] = pProtocols[n+1];
- nProtocols--;
- i--;
- bSet = true;
- }
- }
- }
- if( bSet )
- XSetWMProtocols( pDisplay, aWindow, pProtocols, nProtocols );
- XFree( pProtocols );
- }
- }
- else
- {
- // Only needed for Compiz. The toolbar type hint seems to be enough for other WMs.
- gtk_window_set_focus_on_map( pWindow, false );
- }
-}
-
-GtkSalFrame *GtkSalFrame::getFromWindow( GtkWindow *pWindow )
-{
- return static_cast<GtkSalFrame *>(g_object_get_data( G_OBJECT( pWindow ), "SalFrame" ));
-}
-
-void GtkSalFrame::Init( SalFrame* pParent, SalFrameStyleFlags nStyle )
-{
- if( nStyle & SalFrameStyleFlags::DEFAULT ) // ensure default style
- {
- nStyle |= SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::CLOSEABLE;
- nStyle &= ~SalFrameStyleFlags::FLOAT;
- }
-
- m_pParent = static_cast<GtkSalFrame*>(pParent);
- m_pForeignParent = nullptr;
- m_aForeignParentWindow = None;
- m_pForeignTopLevel = nullptr;
- m_aForeignTopLevelWindow = None;
- m_nStyle = nStyle;
-
- GtkWindowType eWinType = ( (nStyle & SalFrameStyleFlags::FLOAT) &&
- ! (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)
- )
- ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL;
-
- if( nStyle & SalFrameStyleFlags::SYSTEMCHILD )
- {
- m_pWindow = gtk_event_box_new();
- if( m_pParent )
- {
- // insert into container
- gtk_fixed_put( m_pParent->getFixedContainer(),
- m_pWindow, 0, 0 );
-
- }
- }
- else
- {
- m_pWindow = gtk_widget_new( GTK_TYPE_WINDOW, "type", eWinType,
- "visible", FALSE, nullptr );
- }
- g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", this );
- g_object_set_data( G_OBJECT( m_pWindow ), "libo-version", const_cast<char *>(LIBO_VERSION_DOTTED));
-
- // force wm class hint
- if (!isChild())
- {
- if (m_pParent)
- m_sWMClass = m_pParent->m_sWMClass;
- updateWMClass();
- }
-
- if( m_pParent && m_pParent->m_pWindow && ! isChild() )
- gtk_window_set_screen( GTK_WINDOW(m_pWindow), gtk_window_get_screen( GTK_WINDOW(m_pParent->m_pWindow) ) );
-
- if (m_pParent)
- {
- if (!(m_pParent->m_nStyle & SalFrameStyleFlags::PLUG))
- gtk_window_set_transient_for( GTK_WINDOW(m_pWindow), GTK_WINDOW(m_pParent->m_pWindow) );
- m_pParent->m_aChildren.push_back( this );
- }
-
- InitCommon();
-
- // set window type
- bool bDecoHandling =
- ! isChild() &&
- ( ! (nStyle & SalFrameStyleFlags::FLOAT) ||
- (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) );
-
- if( bDecoHandling )
- {
- GdkWindowTypeHint eType = GDK_WINDOW_TYPE_HINT_NORMAL;
- if( (nStyle & SalFrameStyleFlags::DIALOG) && m_pParent != nullptr )
- eType = GDK_WINDOW_TYPE_HINT_DIALOG;
- if( nStyle & SalFrameStyleFlags::INTRO )
- {
- gtk_window_set_role( GTK_WINDOW(m_pWindow), "splashscreen" );
- eType = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
- }
- else if( nStyle & SalFrameStyleFlags::TOOLWINDOW )
- {
- eType = GDK_WINDOW_TYPE_HINT_UTILITY;
- gtk_window_set_skip_taskbar_hint( GTK_WINDOW(m_pWindow), true );
- }
- else if( nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION )
- {
- eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
- lcl_set_accept_focus( GTK_WINDOW(m_pWindow) );
- gtk_window_set_decorated( GTK_WINDOW(m_pWindow), false );
- }
- if( (nStyle & SalFrameStyleFlags::PARTIAL_FULLSCREEN )
- && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
- {
- eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
- gtk_window_set_keep_above( GTK_WINDOW(m_pWindow), true );
- }
- gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), eType );
- gtk_window_set_gravity( GTK_WINDOW(m_pWindow), GDK_GRAVITY_STATIC );
- gtk_window_set_resizable( GTK_WINDOW(m_pWindow), bool(nStyle & SalFrameStyleFlags::SIZEABLE) );
- }
- else if( nStyle & SalFrameStyleFlags::FLOAT )
- gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), GDK_WINDOW_TYPE_HINT_POPUP_MENU );
-
-#ifdef ENABLE_GMENU_INTEGRATION
- if( eWinType == GTK_WINDOW_TOPLEVEL )
- {
- // Enable DBus native menu if available.
- ensure_dbus_setup( this );
- }
-#endif
-}
-
-GdkNativeWindow GtkSalFrame::findTopLevelSystemWindow(GdkNativeWindow aWindow)
-{
- ::Window aRoot, aParent;
- ::Window* pChildren;
- unsigned int nChildren;
- bool bBreak = false;
- do
- {
- pChildren = nullptr;
- nChildren = 0;
- aParent = aRoot = None;
- XQueryTree( getDisplay()->GetDisplay(), aWindow,
- &aRoot, &aParent, &pChildren, &nChildren );
- XFree( pChildren );
- if( aParent != aRoot )
- aWindow = aParent;
- int nCount = 0;
- Atom* pProps = XListProperties( getDisplay()->GetDisplay(),
- aWindow,
- &nCount );
- for( int i = 0; i < nCount && ! bBreak; ++i )
- bBreak = (pProps[i] == XA_WM_HINTS);
- if( pProps )
- XFree( pProps );
- } while( aParent != aRoot && ! bBreak );
-
- return aWindow;
-}
-
-void GtkSalFrame::Init( SystemParentData* pSysData )
-{
- m_pParent = nullptr;
- m_aForeignParentWindow = pSysData->aWindow;
- m_pForeignParent = nullptr;
- m_aForeignTopLevelWindow = findTopLevelSystemWindow(pSysData->aWindow);
- m_pForeignTopLevel = gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignTopLevelWindow );
- gdk_window_set_events( m_pForeignTopLevel, GDK_STRUCTURE_MASK );
-
- if( pSysData->nSize > sizeof(pSysData->nSize)+sizeof(pSysData->aWindow) && pSysData->bXEmbedSupport )
- {
- m_pWindow = gtk_plug_new( pSysData->aWindow );
- m_bWindowIsGtkPlug = true;
- widget_set_can_default( m_pWindow, true );
- widget_set_can_focus( m_pWindow, true );
- gtk_widget_set_sensitive( m_pWindow, true );
- }
- else
- {
- m_pWindow = gtk_window_new( GTK_WINDOW_POPUP );
- m_bWindowIsGtkPlug = false;
- }
- m_nStyle = SalFrameStyleFlags::PLUG;
- InitCommon();
-
- m_pForeignParent = gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignParentWindow );
- gdk_window_set_events( m_pForeignParent, GDK_STRUCTURE_MASK );
-
- int x_ret, y_ret;
- unsigned int w, h, bw, d;
- ::Window aRoot;
- XGetGeometry( getDisplay()->GetDisplay(), pSysData->aWindow,
- &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
- maGeometry.nWidth = w;
- maGeometry.nHeight = h;
- window_resize(w, h);
- gtk_window_move( GTK_WINDOW(m_pWindow), 0, 0 );
- if( ! m_bWindowIsGtkPlug )
- {
- XReparentWindow( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- static_cast<::Window>(pSysData->aWindow),
- 0, 0 );
- }
-}
-
-void GtkSalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
-{
- XEvent aEvent;
-
- memset( &aEvent, 0, sizeof(aEvent) );
- aEvent.xclient.window = m_aForeignParentWindow;
- aEvent.xclient.type = ClientMessage;
- aEvent.xclient.message_type = getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED );
- aEvent.xclient.format = 32;
- aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime;
- aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
- aEvent.xclient.data.l[2] = 0;
- aEvent.xclient.data.l[3] = 0;
- aEvent.xclient.data.l[4] = 0;
-
- GetGenericUnixSalData()->ErrorTrapPush();
- XSendEvent( getDisplay()->GetDisplay(),
- m_aForeignParentWindow,
- False, NoEventMask, &aEvent );
- GetGenericUnixSalData()->ErrorTrapPop();
-}
-
-void GtkSalFrame::SetExtendedFrameStyle(SalExtStyle)
-{
-}
-
-SalGraphics* GtkSalFrame::AcquireGraphics()
-{
- if( m_bGraphics )
- return nullptr;
-
- if( !m_pGraphics )
- {
- m_pGraphics.reset( new GtkSalGraphics( this, m_pWindow, m_nXScreen ) );
- }
- m_bGraphics = true;
- return m_pGraphics.get();
-}
-
-void GtkSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
-{
- (void) pGraphics;
- assert( pGraphics == m_pGraphics.get() );
- m_bGraphics = false;
-}
-
-bool GtkSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
-{
- getDisplay()->SendInternalEvent( this, pData.release() );
- return true;
-}
-
-void GtkSalFrame::SetTitle( const OUString& rTitle )
-{
- m_aTitle = rTitle;
- if( m_pWindow && ! isChild() )
- gtk_window_set_title( GTK_WINDOW(m_pWindow), OUStringToOString( rTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
-}
-
-void GtkSalFrame::SetIcon( sal_uInt16 nIcon )
-{
- if( (m_nStyle & (SalFrameStyleFlags::PLUG|SalFrameStyleFlags::SYSTEMCHILD|SalFrameStyleFlags::FLOAT|SalFrameStyleFlags::INTRO|SalFrameStyleFlags::OWNERDRAWDECORATION))
- || ! m_pWindow )
- return;
-
- gchar* appicon;
-
- if (nIcon == SV_ICON_ID_TEXT)
- appicon = g_strdup ("libreoffice-writer");
- else if (nIcon == SV_ICON_ID_SPREADSHEET)
- appicon = g_strdup ("libreoffice-calc");
- else if (nIcon == SV_ICON_ID_DRAWING)
- appicon = g_strdup ("libreoffice-draw");
- else if (nIcon == SV_ICON_ID_PRESENTATION)
- appicon = g_strdup ("libreoffice-impress");
- else if (nIcon == SV_ICON_ID_DATABASE)
- appicon = g_strdup ("libreoffice-base");
- else if (nIcon == SV_ICON_ID_FORMULA)
- appicon = g_strdup ("libreoffice-math");
- else
- appicon = g_strdup ("libreoffice-startcenter");
-
- gtk_window_set_icon_name (GTK_WINDOW (m_pWindow), appicon);
-}
-
-void GtkSalFrame::SetMenu( SalMenu* pSalMenu )
-{
- m_pSalMenu = static_cast<GtkSalMenu*>(pSalMenu);
-}
-
-SalMenu* GtkSalFrame::GetMenu()
-{
- return m_pSalMenu;
-}
-
-void GtkSalFrame::DrawMenuBar()
-{
-}
-
-void GtkSalFrame::Center()
-{
- long nX, nY;
-
- if( m_pParent )
- {
- nX = (static_cast<long>(m_pParent->maGeometry.nWidth) - static_cast<long>(maGeometry.nWidth))/2;
- nY = (static_cast<long>(m_pParent->maGeometry.nHeight) - static_cast<long>(maGeometry.nHeight))/2;
- }
- else
- {
- GdkScreen *pScreen = nullptr;
- gint px, py;
- GdkModifierType nMask;
- gdk_display_get_pointer( getGdkDisplay(), &pScreen, &px, &py, &nMask );
- if( !pScreen )
- pScreen = gtk_widget_get_screen( m_pWindow );
-
- gint nMonitor;
- nMonitor = gdk_screen_get_monitor_at_point( pScreen, px, py );
-
- GdkRectangle aMonitor;
- gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aMonitor );
-
- nX = aMonitor.x + (aMonitor.width - static_cast<long>(maGeometry.nWidth))/2;
- nY = aMonitor.y + (aMonitor.height - static_cast<long>(maGeometry.nHeight))/2;
- }
- SetPosSize( nX, nY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
-}
-
-Size GtkSalFrame::calcDefaultSize()
-{
- return bestmaxFrameSizeForScreenSize(getDisplay()->GetScreenSize(GetDisplayScreen()));
-}
-
-void GtkSalFrame::SetDefaultSize()
-{
- Size aDefSize = calcDefaultSize();
-
- SetPosSize( 0, 0, aDefSize.Width(), aDefSize.Height(),
- SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
-
- if( (m_nStyle & SalFrameStyleFlags::DEFAULT) && m_pWindow )
- gtk_window_maximize( GTK_WINDOW(m_pWindow) );
-}
-
-static void initClientId()
-{
- static bool bOnce = false;
- if (!bOnce)
- {
- bOnce = true;
- const OString& rID = SessionManagerClient::getSessionID();
- if (!rID.isEmpty())
- gdk_set_sm_client_id(rID.getStr());
- }
-}
-
-void GtkSalFrame::Show( bool bVisible, bool bNoActivate )
-{
- if( m_pWindow )
- {
- if( m_pParent && (m_pParent->m_nStyle & SalFrameStyleFlags::PARTIAL_FULLSCREEN)
- && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
- gtk_window_set_keep_above( GTK_WINDOW(m_pWindow), bVisible );
- if( bVisible )
- {
- initClientId();
- getDisplay()->startupNotificationCompleted();
-
- if( m_bDefaultPos )
- Center();
- if( m_bDefaultSize )
- SetDefaultSize();
- setMinMaxSize();
-
- // #i45160# switch to desktop where a dialog with parent will appear
- if( m_pParent && m_pParent->m_nWorkArea != m_nWorkArea && IS_WIDGET_MAPPED(m_pParent->m_pWindow) )
- getDisplay()->getWMAdaptor()->switchToWorkArea( m_pParent->m_nWorkArea );
-
- if( isFloatGrabWindow() &&
- m_pParent &&
- m_nFloats == 0 &&
- ! getDisplay()->GetCaptureFrame() )
- {
- /* #i63086#
- * outsmart Metacity's "focus:mouse" mode
- * which insists on taking the focus from the document
- * to the new float. Grab focus to parent frame BEFORE
- * showing the float (cannot grab it to the float
- * before show).
- */
- m_pParent->grabPointer( true, true );
- }
-
- if( ! bNoActivate && (m_nStyle & SalFrameStyleFlags::TOOLWINDOW) )
- m_bSetFocusOnMap = true;
-
- gtk_widget_show( m_pWindow );
-
- if( isFloatGrabWindow() )
- {
- m_nFloats++;
- if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 1 )
- {
- grabPointer(true, true);
- GtkSalFrame *pKeyboardFrame = m_pParent ? m_pParent : this;
- pKeyboardFrame->grabKeyboard(true);
- }
- // #i44068# reset parent's IM context
- if( m_pParent )
- m_pParent->EndExtTextInput(EndExtTextInputFlags::NONE);
- }
- if( m_bWindowIsGtkPlug )
- askForXEmbedFocus( 0 );
- }
- else
- {
- if( isFloatGrabWindow() )
- {
- m_nFloats--;
- if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 0)
- {
- GtkSalFrame *pKeyboardFrame = m_pParent ? m_pParent : this;
- pKeyboardFrame->grabKeyboard(false);
- grabPointer(false);
- }
- }
- gtk_widget_hide( m_pWindow );
- if( m_pIMHandler )
- m_pIMHandler->focusChanged( false );
- // flush here; there may be a very seldom race between
- // the display connection used for clipboard and our connection
- Flush();
- }
- CallCallback( SalEvent::Resize, nullptr );
- TriggerPaintEvent();
- }
-}
-
-void GtkSalFrame::setMinMaxSize()
-{
- /* #i34504# metacity (and possibly others) do not treat
- * _NET_WM_STATE_FULLSCREEN and max_width/height independently;
- * whether they should is undefined. So don't set the max size hint
- * for a full screen window.
- */
- if( m_pWindow && ! isChild() )
- {
- GdkGeometry aGeo;
- int aHints = 0;
- if( m_nStyle & SalFrameStyleFlags::SIZEABLE )
- {
- if( m_aMinSize.Width() && m_aMinSize.Height() && ! m_bFullscreen )
- {
- aGeo.min_width = m_aMinSize.Width();
- aGeo.min_height = m_aMinSize.Height();
- aHints |= GDK_HINT_MIN_SIZE;
- }
- if( m_aMaxSize.Width() && m_aMaxSize.Height() && ! m_bFullscreen )
- {
- aGeo.max_width = m_aMaxSize.Width();
- aGeo.max_height = m_aMaxSize.Height();
- aHints |= GDK_HINT_MAX_SIZE;
- }
- }
- else
- {
- if( ! m_bFullscreen )
- {
- aGeo.min_width = maGeometry.nWidth;
- aGeo.min_height = maGeometry.nHeight;
- aHints |= GDK_HINT_MIN_SIZE;
-
- aGeo.max_width = maGeometry.nWidth;
- aGeo.max_height = maGeometry.nHeight;
- aHints |= GDK_HINT_MAX_SIZE;
- }
- }
- if( m_bFullscreen && m_aMaxSize.Width() && m_aMaxSize.Height() )
- {
- aGeo.max_width = m_aMaxSize.Width();
- aGeo.max_height = m_aMaxSize.Height();
- aHints |= GDK_HINT_MAX_SIZE;
- }
- if( aHints )
- {
- gtk_window_set_geometry_hints( GTK_WINDOW(m_pWindow),
- nullptr,
- &aGeo,
- GdkWindowHints( aHints ) );
- }
- }
-}
-
-void GtkSalFrame::SetMaxClientSize( long nWidth, long nHeight )
-{
- if( ! isChild() )
- {
- m_aMaxSize = Size( nWidth, nHeight );
- // Show does a setMinMaxSize
- if( IS_WIDGET_MAPPED( m_pWindow ) )
- setMinMaxSize();
- }
-}
-void GtkSalFrame::SetMinClientSize( long nWidth, long nHeight )
-{
- if( ! isChild() )
- {
- m_aMinSize = Size( nWidth, nHeight );
- if( m_pWindow )
- {
- widget_set_size_request(nWidth, nHeight );
- // Show does a setMinMaxSize
- if( IS_WIDGET_MAPPED( m_pWindow ) )
- setMinMaxSize();
- }
- }
-}
-
-void GtkSalFrame::AllocateFrame()
-{
-}
-
-void GtkSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
-{
- if( !m_pWindow || isChild( true, false ) )
- return;
-
- bool bSized = false, bMoved = false;
-
- if( (nFlags & ( SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT )) &&
- (nWidth > 0 && nHeight > 0 ) // sometimes stupid things happen
- )
- {
- m_bDefaultSize = false;
-
- if( static_cast<unsigned long>(nWidth) != maGeometry.nWidth || static_cast<unsigned long>(nHeight) != maGeometry.nHeight )
- bSized = true;
- maGeometry.nWidth = nWidth;
- maGeometry.nHeight = nHeight;
-
- if( isChild( false ) )
- widget_set_size_request(nWidth, nHeight);
- else if( ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) )
- window_resize(nWidth, nHeight);
- setMinMaxSize();
- }
- else if( m_bDefaultSize )
- SetDefaultSize();
-
- m_bDefaultSize = false;
-
- if( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) )
- {
- if( m_pParent )
- {
- if( AllSettings::GetLayoutRTL() )
- nX = m_pParent->maGeometry.nWidth-maGeometry.nWidth-1-nX;
- nX += m_pParent->maGeometry.nX;
- nY += m_pParent->maGeometry.nY;
- }
-
- if( nX != maGeometry.nX || nY != maGeometry.nY )
- bMoved = true;
- maGeometry.nX = nX;
- maGeometry.nY = nY;
-
- m_bDefaultPos = false;
-
- moveWindow( maGeometry.nX, maGeometry.nY );
-
- updateScreenNumber();
- }
- else if( m_bDefaultPos )
- Center();
-
- m_bDefaultPos = false;
-
- if( bSized )
- AllocateFrame();
-
- if( bSized && ! bMoved )
- CallCallback( SalEvent::Resize, nullptr );
- else if( bMoved && ! bSized )
- CallCallback( SalEvent::Move, nullptr );
- else if( bMoved && bSized )
- CallCallback( SalEvent::MoveResize, nullptr );
-
- if (bSized)
- TriggerPaintEvent();
-}
-
-void GtkSalFrame::GetClientSize( long& rWidth, long& rHeight )
-{
- if( m_pWindow && !(m_nState & GDK_WINDOW_STATE_ICONIFIED) )
- {
- rWidth = maGeometry.nWidth;
- rHeight = maGeometry.nHeight;
- }
- else
- rWidth = rHeight = 0;
-}
-
-void GtkSalFrame::GetWorkArea( tools::Rectangle& rRect )
-{
- rRect = GetGtkSalData()->GetGtkDisplay()->getWMAdaptor()->getWorkArea( 0 );
-}
-
-SalFrame* GtkSalFrame::GetParent() const
-{
- return m_pParent;
-}
-
-void GtkSalFrame::SetWindowState( const SalFrameState* pState )
-{
- if( ! m_pWindow || ! pState || isChild( true, false ) )
- return;
-
- const WindowStateMask nMaxGeometryMask =
- WindowStateMask::X | WindowStateMask::Y |
- WindowStateMask::Width | WindowStateMask::Height |
- WindowStateMask::MaximizedX | WindowStateMask::MaximizedY |
- WindowStateMask::MaximizedWidth | WindowStateMask::MaximizedHeight;
-
- if( (pState->mnMask & WindowStateMask::State) &&
- ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) &&
- (pState->mnState & WindowStateState::Maximized) &&
- (pState->mnMask & nMaxGeometryMask) == nMaxGeometryMask )
- {
- resizeWindow( pState->mnWidth, pState->mnHeight );
- moveWindow( pState->mnX, pState->mnY );
- m_bDefaultPos = m_bDefaultSize = false;
-
- maGeometry.nX = pState->mnMaximizedX;
- maGeometry.nY = pState->mnMaximizedY;
- maGeometry.nWidth = pState->mnMaximizedWidth;
- maGeometry.nHeight = pState->mnMaximizedHeight;
- updateScreenNumber();
-
- m_nState = GdkWindowState( m_nState | GDK_WINDOW_STATE_MAXIMIZED );
- m_aRestorePosSize = tools::Rectangle( Point( pState->mnX, pState->mnY ),
- Size( pState->mnWidth, pState->mnHeight ) );
- CallCallback( SalEvent::Resize, nullptr );
- }
- else if( pState->mnMask & (WindowStateMask::X | WindowStateMask::Y |
- WindowStateMask::Width | WindowStateMask::Height ) )
- {
- sal_uInt16 nPosSizeFlags = 0;
- long nX = pState->mnX - (m_pParent ? m_pParent->maGeometry.nX : 0);
- long nY = pState->mnY - (m_pParent ? m_pParent->maGeometry.nY : 0);
- if( pState->mnMask & WindowStateMask::X )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_X;
- else
- nX = maGeometry.nX - (m_pParent ? m_pParent->maGeometry.nX : 0);
- if( pState->mnMask & WindowStateMask::Y )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_Y;
- else
- nY = maGeometry.nY - (m_pParent ? m_pParent->maGeometry.nY : 0);
- if( pState->mnMask & WindowStateMask::Width )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH;
- if( pState->mnMask & WindowStateMask::Height )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT;
- SetPosSize( nX, nY, pState->mnWidth, pState->mnHeight, nPosSizeFlags );
- }
- if( pState->mnMask & WindowStateMask::State && ! isChild() )
- {
- if( pState->mnState & WindowStateState::Maximized )
- gtk_window_maximize( GTK_WINDOW(m_pWindow) );
- else
- gtk_window_unmaximize( GTK_WINDOW(m_pWindow) );
- /* #i42379# there is no rollup state in GDK; and rolled up windows are
- * (probably depending on the WM) reported as iconified. If we iconify a
- * window here that was e.g. a dialog, then it will be unmapped but still
- * not be displayed in the task list, so it's an iconified window that
- * the user cannot get out of this state. So do not set the iconified state
- * on windows with a parent (that is transient frames) since these tend
- * to not be represented in an icon task list.
- */
- if( (pState->mnState & WindowStateState::Minimized)
- && ! m_pParent )
- gtk_window_iconify( GTK_WINDOW(m_pWindow) );
- else
- gtk_window_deiconify( GTK_WINDOW(m_pWindow) );
- }
- TriggerPaintEvent();
-}
-
-bool GtkSalFrame::GetWindowState( SalFrameState* pState )
-{
- pState->mnState = WindowStateState::Normal;
- pState->mnMask = WindowStateMask::State;
- // rollup ? gtk 2.2 does not seem to support the shaded state
- if( m_nState & GDK_WINDOW_STATE_ICONIFIED )
- pState->mnState |= WindowStateState::Minimized;
- if( m_nState & GDK_WINDOW_STATE_MAXIMIZED )
- {
- pState->mnState |= WindowStateState::Maximized;
- pState->mnX = m_aRestorePosSize.Left();
- pState->mnY = m_aRestorePosSize.Top();
- pState->mnWidth = m_aRestorePosSize.GetWidth();
- pState->mnHeight = m_aRestorePosSize.GetHeight();
- pState->mnMaximizedX = maGeometry.nX;
- pState->mnMaximizedY = maGeometry.nY;
- pState->mnMaximizedWidth = maGeometry.nWidth;
- pState->mnMaximizedHeight = maGeometry.nHeight;
- pState->mnMask |= WindowStateMask::MaximizedX |
- WindowStateMask::MaximizedY |
- WindowStateMask::MaximizedWidth |
- WindowStateMask::MaximizedHeight;
- }
- else
- {
- pState->mnX = maGeometry.nX;
- pState->mnY = maGeometry.nY;
- pState->mnWidth = maGeometry.nWidth;
- pState->mnHeight = maGeometry.nHeight;
- }
- pState->mnMask |= WindowStateMask::X |
- WindowStateMask::Y |
- WindowStateMask::Width |
- WindowStateMask::Height;
-
- return true;
-}
-
-void GtkSalFrame::SetScreen( unsigned int nNewScreen, SetType eType, tools::Rectangle const *pSize )
-{
- if( !m_pWindow )
- return;
-
- if (maGeometry.nDisplayScreenNumber == nNewScreen && eType == SetType::RetainSize)
- return;
-
- GdkScreen *pScreen = nullptr;
- GdkRectangle aNewMonitor;
-
- bool bSpanAllScreens = nNewScreen == static_cast<unsigned int>(-1);
- m_bSpanMonitorsWhenFullscreen = bSpanAllScreens && getDisplay()->getSystem()->GetDisplayScreenCount() > 1;
-
- if (m_bSpanMonitorsWhenFullscreen) //span all screens
- {
- pScreen = gtk_widget_get_screen( m_pWindow );
- aNewMonitor.x = 0;
- aNewMonitor.y = 0;
- aNewMonitor.width = gdk_screen_get_width(pScreen);
- aNewMonitor.height = gdk_screen_get_height(pScreen);
- }
- else
- {
- gint nMonitor;
- bool bSameMonitor = false;
-
- if (!bSpanAllScreens)
- {
- pScreen = getDisplay()->getSystem()->getScreenMonitorFromIdx( nNewScreen, nMonitor );
- if (!pScreen)
- {
- g_warning ("Attempt to move GtkSalFrame to invalid screen %d => "
- "fallback to current\n", nNewScreen);
- }
- }
-
- if (!pScreen)
- {
- pScreen = gtk_widget_get_screen( m_pWindow );
- bSameMonitor = true;
- }
-
- // Heavy lifting, need to move screen ...
- if( pScreen != gtk_widget_get_screen( m_pWindow ))
- gtk_window_set_screen( GTK_WINDOW( m_pWindow ), pScreen );
-
- gint nOldMonitor = gdk_screen_get_monitor_at_window(
- pScreen, widget_get_window( m_pWindow ) );
- if (bSameMonitor)
- nMonitor = nOldMonitor;
-
- #if OSL_DEBUG_LEVEL > 1
- if( nMonitor == nOldMonitor )
- g_warning( "An apparently pointless SetScreen - should we elide it ?" );
- #endif
-
- GdkRectangle aOldMonitor;
- gdk_screen_get_monitor_geometry( pScreen, nOldMonitor, &aOldMonitor );
- gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aNewMonitor );
-
- maGeometry.nX = aNewMonitor.x + maGeometry.nX - aOldMonitor.x;
- maGeometry.nY = aNewMonitor.y + maGeometry.nY - aOldMonitor.y;
- }
-
- bool bResize = false;
- bool bVisible = IS_WIDGET_MAPPED( m_pWindow );
- if( bVisible )
- Show( false );
-
- if( eType == SetType::Fullscreen )
- {
- maGeometry.nX = aNewMonitor.x;
- maGeometry.nY = aNewMonitor.y;
- maGeometry.nWidth = aNewMonitor.width;
- maGeometry.nHeight = aNewMonitor.height;
- m_nStyle |= SalFrameStyleFlags::PARTIAL_FULLSCREEN;
- bResize = true;
-
- // #i110881# for the benefit of compiz set a max size here
- // else setting to fullscreen fails for unknown reasons
- m_aMaxSize.setWidth( aNewMonitor.width );
- m_aMaxSize.setHeight( aNewMonitor.height );
- }
-
- if( pSize && eType == SetType::UnFullscreen )
- {
- maGeometry.nX = pSize->Left();
- maGeometry.nY = pSize->Top();
- maGeometry.nWidth = pSize->GetWidth();
- maGeometry.nHeight = pSize->GetHeight();
- m_nStyle &= ~SalFrameStyleFlags::PARTIAL_FULLSCREEN;
- bResize = true;
- }
-
- if (bResize)
- {
- // temporarily re-sizeable
- if( !(m_nStyle & SalFrameStyleFlags::SIZEABLE) )
- gtk_window_set_resizable( GTK_WINDOW(m_pWindow), TRUE );
- window_resize(maGeometry.nWidth, maGeometry.nHeight);
- //I wonder if we should instead leave maGeometry alone and rely on
- //configure-event to trigger signalConfigure and set it there
- AllocateFrame();
- TriggerPaintEvent();
- }
-
- gtk_window_move( GTK_WINDOW( m_pWindow ), maGeometry.nX, maGeometry.nY );
-
- // _NET_WM_STATE_FULLSCREEN (Metacity <-> KWin)
- if( ! getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
- {
- if( eType == SetType::Fullscreen )
- gtk_window_fullscreen( GTK_WINDOW( m_pWindow ) );
- else if( eType == SetType::UnFullscreen )
- gtk_window_unfullscreen( GTK_WINDOW( m_pWindow ) );
- }
-
- if( eType == SetType::UnFullscreen &&
- !(m_nStyle & SalFrameStyleFlags::SIZEABLE) )
- gtk_window_set_resizable( GTK_WINDOW( m_pWindow ), FALSE );
-
- // FIXME: we should really let gtk+ handle our widget hierarchy ...
- if( m_pParent && gtk_widget_get_screen( m_pParent->m_pWindow ) != pScreen )
- SetParent( nullptr );
- std::list< GtkSalFrame* > aChildren = m_aChildren;
- for (auto const& child : aChildren)
- child->SetScreen( nNewScreen, SetType::RetainSize );
-
- m_bDefaultPos = m_bDefaultSize = false;
- updateScreenNumber();
- CallCallback( SalEvent::MoveResize, nullptr );
-
- if( bVisible )
- Show( true );
-}
-
-void GtkSalFrame::SetScreenNumber( unsigned int nNewScreen )
-{
- SetScreen( nNewScreen, SetType::RetainSize );
-}
-
-void GtkSalFrame::updateWMClass()
-{
- OString aResClass = OUStringToOString(m_sWMClass, RTL_TEXTENCODING_ASCII_US);
- const char *pResClass = !aResClass.isEmpty() ? aResClass.getStr() :
- SalGenericSystem::getFrameClassName();
- Display *display;
-
- if (!getDisplay()->IsX11Display())
- return;
-
- display = getDisplay()->GetDisplay();
-
- if( IS_WIDGET_REALIZED( m_pWindow ) )
- {
- XClassHint* pClass = XAllocClassHint();
- OString aResName = SalGenericSystem::getFrameResName();
- pClass->res_name = const_cast<char*>(aResName.getStr());
- pClass->res_class = const_cast<char*>(pResClass);
- XSetClassHint( display,
- widget_get_xid(m_pWindow),
- pClass );
- XFree( pClass );
- }
-}
-
-void GtkSalFrame::SetApplicationID( const OUString &rWMClass )
-{
- if( rWMClass != m_sWMClass && ! isChild() )
- {
- m_sWMClass = rWMClass;
- updateWMClass();
-
- for (auto const& child : m_aChildren)
- child->SetApplicationID(rWMClass);
- }
-}
-
-void GtkSalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nScreen )
-{
- m_bFullscreen = bFullScreen;
-
- if( !m_pWindow || isChild() )
- return;
-
- if( bFullScreen )
- {
- m_aRestorePosSize = tools::Rectangle( Point( maGeometry.nX, maGeometry.nY ),
- Size( maGeometry.nWidth, maGeometry.nHeight ) );
- SetScreen( nScreen, SetType::Fullscreen );
- }
- else
- {
- SetScreen( nScreen, SetType::UnFullscreen,
- !m_aRestorePosSize.IsEmpty() ? &m_aRestorePosSize : nullptr );
- m_aRestorePosSize = tools::Rectangle();
- }
-}
-
-void GtkSalFrame::StartPresentation( bool bStart )
-{
- boost::optional<guint> aWindow;
- boost::optional<Display*> aDisplay;
- if( getDisplay()->IsX11Display() )
- {
- aWindow = widget_get_xid(m_pWindow);
- aDisplay = GDK_DISPLAY_XDISPLAY( getGdkDisplay() );
- }
-
- m_ScreenSaverInhibitor.inhibit( bStart,
- "presentation",
- getDisplay()->IsX11Display(),
- aWindow,
- aDisplay );
-}
-
-void GtkSalFrame::SetAlwaysOnTop( bool bOnTop )
-{
- if( m_pWindow )
- gtk_window_set_keep_above( GTK_WINDOW( m_pWindow ), bOnTop );
-}
-
-void GtkSalFrame::ToTop( SalFrameToTop nFlags )
-{
- if( m_pWindow )
- {
- if( isChild( false ) )
- gtk_widget_grab_focus( m_pWindow );
- else if( IS_WIDGET_MAPPED( m_pWindow ) )
- {
- if( ! (nFlags & SalFrameToTop::GrabFocusOnly) )
- gtk_window_present( GTK_WINDOW(m_pWindow) );
- else
- {
- guint32 nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
- gdk_window_focus( widget_get_window(m_pWindow), nUserTime );
- }
- }
- else
- {
- if( nFlags & SalFrameToTop::RestoreWhenMin )
- gtk_window_present( GTK_WINDOW(m_pWindow) );
- }
- }
-}
-
-void GtkSalFrame::SetPointer( PointerStyle ePointerStyle )
-{
- if( m_pWindow && ePointerStyle != m_ePointerStyle )
- {
- m_ePointerStyle = ePointerStyle;
- GdkCursor *pCursor = getDisplay()->getCursor( ePointerStyle );
- gdk_window_set_cursor( widget_get_window(m_pWindow), pCursor );
- m_pCurrentCursor = pCursor;
-
- // #i80791# use grabPointer the same way as CaptureMouse, respective float grab
- if( getDisplay()->MouseCaptured( this ) )
- grabPointer( true );
- else if( m_nFloats > 0 )
- grabPointer( true, true );
- }
-}
-
-void GtkSalFrame::grabPointer( bool bGrab, bool bOwnerEvents )
-{
- static const char* pEnv = getenv( "SAL_NO_MOUSEGRABS" );
- if (pEnv && *pEnv)
- return;
-
- if (!m_pWindow)
- return;
-
- const int nMask = (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
-
- if( bGrab )
- {
- bool bUseGdkGrab = true;
- for (auto pSalFrame : getDisplay()->getFrames() )
- {
- const GtkSalFrame* pFrame = static_cast< const GtkSalFrame* >( pSalFrame );
- if( pFrame->m_bWindowIsGtkPlug )
- {
- bUseGdkGrab = false;
- break;
- }
- }
- if( bUseGdkGrab )
- {
- gdk_pointer_grab( widget_get_window( m_pWindow ), bOwnerEvents,
- GdkEventMask(nMask), nullptr, m_pCurrentCursor,
- GDK_CURRENT_TIME );
- }
- else
- {
- // FIXME: for some unknown reason gdk_pointer_grab does not
- // really produce owner events for GtkPlug windows
- // the cause is yet unknown
-
- // this is of course a bad hack, especially as we cannot
- // set the right cursor this way
- XGrabPointer( getDisplay()->GetDisplay(),
- widget_get_xid( m_pWindow ),
- bOwnerEvents,
- PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
- GrabModeAsync,
- GrabModeAsync,
- None,
- None,
- CurrentTime
- );
- }
- }
- else
- {
- // Two GdkDisplays may be open
- gdk_display_pointer_ungrab( getGdkDisplay(), GDK_CURRENT_TIME);
- }
-}
-
-void GtkSalFrame::grabKeyboard( bool bGrab )
-{
- static const char* pEnv = getenv("SAL_NO_MOUSEGRABS"); // let's not introduce a special var for this
- if (pEnv && *pEnv)
- return;
-
- if (!m_pWindow)
- return;
-
- if( bGrab )
- {
- gdk_keyboard_grab(widget_get_window(m_pWindow), true,
- GDK_CURRENT_TIME);
- }
- else
- {
- gdk_keyboard_ungrab(GDK_CURRENT_TIME);
- }
-}
-
-void GtkSalFrame::CaptureMouse( bool bCapture )
-{
- getDisplay()->CaptureMouse( bCapture ? this : nullptr );
-}
-
-void GtkSalFrame::SetPointerPos( long nX, long nY )
-{
- GtkSalFrame* pFrame = this;
- while( pFrame && pFrame->isChild( false ) )
- pFrame = pFrame->m_pParent;
- if( ! pFrame )
- return;
-
- GdkScreen *pScreen = gtk_window_get_screen( GTK_WINDOW(pFrame->m_pWindow) );
- GdkDisplay *pDisplay = gdk_screen_get_display( pScreen );
-
- /* when the application tries to center the mouse in the dialog the
- * window isn't mapped already. So use coordinates relative to the root window.
- */
- unsigned int nWindowLeft = maGeometry.nX + nX;
- unsigned int nWindowTop = maGeometry.nY + nY;
-
- XWarpPointer( GDK_DISPLAY_XDISPLAY (pDisplay), None,
- GDK_WINDOW_XID (gdk_screen_get_root_window( pScreen ) ),
- 0, 0, 0, 0, nWindowLeft, nWindowTop);
- // #i38648# ask for the next motion hint
- gint x, y;
- GdkModifierType mask;
- gdk_window_get_pointer( widget_get_window(pFrame->m_pWindow) , &x, &y, &mask );
-}
-
-void GtkSalFrame::Flush()
-{
- XFlush (GDK_DISPLAY_XDISPLAY (getGdkDisplay()));
-}
-
-void GtkSalFrame::KeyCodeToGdkKey(const vcl::KeyCode& rKeyCode,
- guint* pGdkKeyCode, GdkModifierType *pGdkModifiers)
-{
- if ( pGdkKeyCode == nullptr || pGdkModifiers == nullptr )
- return;
-
- // Get GDK key modifiers
- GdkModifierType nModifiers = GdkModifierType(0);
-
- if ( rKeyCode.IsShift() )
- nModifiers = static_cast<GdkModifierType>( nModifiers | GDK_SHIFT_MASK );
-
- if ( rKeyCode.IsMod1() )
- nModifiers = static_cast<GdkModifierType>( nModifiers | GDK_CONTROL_MASK );
-
- if ( rKeyCode.IsMod2() )
- nModifiers = static_cast<GdkModifierType>( nModifiers | GDK_MOD1_MASK );
-
- *pGdkModifiers = nModifiers;
-
- // Get GDK keycode.
- guint nKeyCode = 0;
-
- guint nCode = rKeyCode.GetCode();
-
- if ( nCode >= KEY_0 && nCode <= KEY_9 )
- nKeyCode = ( nCode - KEY_0 ) + GDK_KEY_0;
- else if ( nCode >= KEY_A && nCode <= KEY_Z )
- nKeyCode = ( nCode - KEY_A ) + GDK_KEY_A;
- else if ( nCode >= KEY_F1 && nCode <= KEY_F26 )
- nKeyCode = ( nCode - KEY_F1 ) + GDK_KEY_F1;
- else
- {
- switch (nCode)
- {
- case KEY_DOWN: nKeyCode = GDK_KEY_Down; break;
- case KEY_UP: nKeyCode = GDK_KEY_Up; break;
- case KEY_LEFT: nKeyCode = GDK_KEY_Left; break;
- case KEY_RIGHT: nKeyCode = GDK_KEY_Right; break;
- case KEY_HOME: nKeyCode = GDK_KEY_Home; break;
- case KEY_END: nKeyCode = GDK_KEY_End; break;
- case KEY_PAGEUP: nKeyCode = GDK_KEY_Page_Up; break;
- case KEY_PAGEDOWN: nKeyCode = GDK_KEY_Page_Down; break;
- case KEY_RETURN: nKeyCode = GDK_KEY_Return; break;
- case KEY_ESCAPE: nKeyCode = GDK_KEY_Escape; break;
- case KEY_TAB: nKeyCode = GDK_KEY_Tab; break;
- case KEY_BACKSPACE: nKeyCode = GDK_KEY_BackSpace; break;
- case KEY_SPACE: nKeyCode = GDK_KEY_space; break;
- case KEY_INSERT: nKeyCode = GDK_KEY_Insert; break;
- case KEY_DELETE: nKeyCode = GDK_KEY_Delete; break;
- case KEY_ADD: nKeyCode = GDK_KEY_plus; break;
- case KEY_SUBTRACT: nKeyCode = GDK_KEY_minus; break;
- case KEY_MULTIPLY: nKeyCode = GDK_KEY_asterisk; break;
- case KEY_DIVIDE: nKeyCode = GDK_KEY_slash; break;
- case KEY_POINT: nKeyCode = GDK_KEY_period; break;
- case KEY_COMMA: nKeyCode = GDK_KEY_comma; break;
- case KEY_LESS: nKeyCode = GDK_KEY_less; break;
- case KEY_GREATER: nKeyCode = GDK_KEY_greater; break;
- case KEY_EQUAL: nKeyCode = GDK_KEY_equal; break;
- case KEY_FIND: nKeyCode = GDK_KEY_Find; break;
- case KEY_CONTEXTMENU: nKeyCode = GDK_KEY_Menu; break;
- case KEY_HELP: nKeyCode = GDK_KEY_Help; break;
- case KEY_UNDO: nKeyCode = GDK_KEY_Undo; break;
- case KEY_REPEAT: nKeyCode = GDK_KEY_Redo; break;
- case KEY_DECIMAL: nKeyCode = GDK_KEY_KP_Decimal; break;
- case KEY_TILDE: nKeyCode = GDK_KEY_asciitilde; break;
- case KEY_QUOTELEFT: nKeyCode = GDK_KEY_quoteleft; break;
- case KEY_BRACKETLEFT: nKeyCode = GDK_KEY_bracketleft; break;
- case KEY_BRACKETRIGHT: nKeyCode = GDK_KEY_bracketright; break;
- case KEY_SEMICOLON: nKeyCode = GDK_KEY_semicolon; break;
- case KEY_QUOTERIGHT: nKeyCode = GDK_KEY_quoteright; break;
-
- // Special cases
- case KEY_COPY: nKeyCode = GDK_KEY_Copy; break;
- case KEY_CUT: nKeyCode = GDK_KEY_Cut; break;
- case KEY_PASTE: nKeyCode = GDK_KEY_Paste; break;
- case KEY_OPEN: nKeyCode = GDK_KEY_Open; break;
- }
- }
-
- *pGdkKeyCode = nKeyCode;
-}
-
-OUString GtkSalFrame::GetKeyName( sal_uInt16 nKeyCode )
-{
- return getDisplay()->GetKeyName( nKeyCode );
-}
-
-GdkDisplay *GtkSalFrame::getGdkDisplay()
-{
- return GetGtkSalData()->GetGdkDisplay();
-}
-
-GtkSalDisplay *GtkSalFrame::getDisplay()
-{
- return GetGtkSalData()->GetGtkDisplay();
-}
-
-SalFrame::SalPointerState GtkSalFrame::GetPointerState()
-{
- SalPointerState aState;
- GdkScreen* pScreen;
- gint x, y;
- GdkModifierType aMask;
- gdk_display_get_pointer( getGdkDisplay(), &pScreen, &x, &y, &aMask );
- aState.maPos = Point( x - maGeometry.nX, y - maGeometry.nY );
- aState.mnState = GetMouseModCode( aMask );
- return aState;
-}
-
-KeyIndicatorState GtkSalFrame::GetIndicatorState()
-{
- return GetGtkSalData()->GetGtkDisplay()->GetIndicatorState();
-}
-
-void GtkSalFrame::SimulateKeyPress( sal_uInt16 nKeyCode )
-{
- GetGtkSalData()->GetGtkDisplay()->SimulateKeyPress(nKeyCode);
-}
-
-void GtkSalFrame::SetInputContext( SalInputContext* pContext )
-{
- if( ! pContext )
- return;
-
- if( ! (pContext->mnOptions & InputContextFlags::Text) )
- return;
-
- // create a new im context
- if( ! m_pIMHandler )
- m_pIMHandler.reset( new IMHandler( this ) );
-}
-
-void GtkSalFrame::EndExtTextInput( EndExtTextInputFlags nFlags )
-{
- if( m_pIMHandler )
- m_pIMHandler->endExtTextInput( nFlags );
-}
-
-bool GtkSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , vcl::KeyCode& )
-{
- // not supported yet
- return false;
-}
-
-LanguageType GtkSalFrame::GetInputLanguage()
-{
- return LANGUAGE_DONTKNOW;
-}
-
-void GtkSalFrame::UpdateSettings( AllSettings& rSettings )
-{
- if( ! m_pWindow )
- return;
-
- GtkSalGraphics* pGraphics = m_pGraphics.get();
- bool bFreeGraphics = false;
- if( ! pGraphics )
- {
- pGraphics = static_cast<GtkSalGraphics*>(AcquireGraphics());
- if ( !pGraphics )
- {
- SAL_WARN("vcl.gtk", "Could not get graphics - unable to update settings");
- return;
- }
- bFreeGraphics = true;
- }
-
- pGraphics->UpdateSettings( rSettings );
-
- if( bFreeGraphics )
- ReleaseGraphics( pGraphics );
-}
-
-void GtkSalFrame::Beep()
-{
- gdk_display_beep( getGdkDisplay() );
-}
-
-const SystemEnvData* GtkSalFrame::GetSystemData() const
-{
- return &m_aSystemData;
-}
-
-void GtkSalFrame::SetParent( SalFrame* pNewParent )
-{
- if( m_pParent )
- m_pParent->m_aChildren.remove( this );
- m_pParent = static_cast<GtkSalFrame*>(pNewParent);
- if( m_pParent )
- m_pParent->m_aChildren.push_back( this );
- if( ! isChild() )
- gtk_window_set_transient_for( GTK_WINDOW(m_pWindow),
- (m_pParent && ! m_pParent->isChild(true,false)) ? GTK_WINDOW(m_pParent->m_pWindow) : nullptr
- );
-}
-
-void GtkSalFrame::createNewWindow( ::Window aNewParent, bool bXEmbed, SalX11Screen nXScreen )
-{
- bool bWasVisible = m_pWindow && IS_WIDGET_MAPPED(m_pWindow);
- if( bWasVisible )
- Show( false );
-
- if( static_cast<int>(nXScreen.getXScreen()) >= getDisplay()->GetXScreenCount() )
- nXScreen = m_nXScreen;
-
- SystemParentData aParentData;
- aParentData.nSize = sizeof(SystemParentData);
- aParentData.aWindow = aNewParent;
- aParentData.bXEmbedSupport = bXEmbed;
- if( aNewParent == None )
- {
- aParentData.aWindow = None;
- aParentData.bXEmbedSupport = false;
- }
- else
- {
- // is new parent a root window ?
- Display* pDisp = getDisplay()->GetDisplay();
- int nScreens = getDisplay()->GetXScreenCount();
- for( int i = 0; i < nScreens; i++ )
- {
- if( aNewParent == RootWindow( pDisp, i ) )
- {
- nXScreen = SalX11Screen( i );
- aParentData.aWindow = None;
- aParentData.bXEmbedSupport = false;
- break;
- }
- }
- }
-
- // free xrender resources
- if( m_pGraphics )
- m_pGraphics->SetDrawable( None, m_nXScreen );
-
- // first deinit frame
- m_pIMHandler.reset();
- if( m_pRegion )
- {
- gdk_region_destroy( m_pRegion );
- }
-
- GtkWidget *pEventWidget = getMouseEventWidget();
- for (auto handler_id : m_aMouseSignalIds)
- g_signal_handler_disconnect(G_OBJECT(pEventWidget), handler_id);
- if( m_pFixedContainer )
- gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer) );
- if( m_pEventBox )
- gtk_widget_destroy( GTK_WIDGET(m_pEventBox) );
- if( m_pWindow )
- gtk_widget_destroy( m_pWindow );
- if( m_pForeignParent )
- g_object_unref( G_OBJECT( m_pForeignParent ) );
- if( m_pForeignTopLevel )
- g_object_unref( G_OBJECT( m_pForeignTopLevel ) );
-
- // init new window
- m_bDefaultPos = m_bDefaultSize = false;
- if( aParentData.aWindow != None )
- {
- m_nStyle |= SalFrameStyleFlags::PLUG;
- Init( &aParentData );
- }
- else
- {
- m_nStyle &= ~SalFrameStyleFlags::PLUG;
- Init( (m_pParent && m_pParent->m_nXScreen == m_nXScreen) ? m_pParent : nullptr, m_nStyle );
- }
-
- // update graphics
- if( m_pGraphics )
- {
- m_pGraphics->SetDrawable( widget_get_xid(m_pWindow), m_nXScreen );
- m_pGraphics->SetWindow( m_pWindow );
- }
-
- if( ! m_aTitle.isEmpty() )
- SetTitle( m_aTitle );
-
- if( bWasVisible )
- Show( true );
-
- std::list< GtkSalFrame* > aChildren;
- aChildren.swap(m_aChildren);
- for (auto const& child : aChildren)
- child->createNewWindow( None, false, m_nXScreen );
-
- // FIXME: SalObjects
-}
-
-bool GtkSalFrame::SetPluginParent( SystemParentData* pSysParent )
-{
- GetGenericUnixSalData()->ErrorTrapPush(); // permanently ignore unruly children's errors
- createNewWindow( pSysParent->aWindow, (pSysParent->nSize > sizeof(long)) && pSysParent->bXEmbedSupport, m_nXScreen );
- return true;
-}
-
-void GtkSalFrame::ResetClipRegion()
-{
- if( m_pWindow )
- gdk_window_shape_combine_region( widget_get_window( m_pWindow ), nullptr, 0, 0 );
-}
-
-void GtkSalFrame::BeginSetClipRegion( sal_uInt32 )
-{
- if( m_pRegion )
- gdk_region_destroy( m_pRegion );
- m_pRegion = gdk_region_new();
-}
-
-void GtkSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
-{
- if( m_pRegion )
- {
- GdkRectangle aRect;
- aRect.x = nX;
- aRect.y = nY;
- aRect.width = nWidth;
- aRect.height = nHeight;
- gdk_region_union_with_rect( m_pRegion, &aRect );
- }
-}
-
-void GtkSalFrame::EndSetClipRegion()
-{
- if( m_pWindow && m_pRegion )
- gdk_window_shape_combine_region( widget_get_window(m_pWindow), m_pRegion, 0, 0 );
-}
-
-bool GtkSalFrame::Dispatch( const XEvent* pEvent )
-{
- bool bContinueDispatch = true;
-
- if( pEvent->type == PropertyNotify )
- {
- vcl_sal::WMAdaptor* pAdaptor = getDisplay()->getWMAdaptor();
- Atom nDesktopAtom = pAdaptor->getAtom( vcl_sal::WMAdaptor::NET_WM_DESKTOP );
- if( pEvent->xproperty.atom == nDesktopAtom &&
- pEvent->xproperty.state == PropertyNewValue )
- {
- m_nWorkArea = pAdaptor->getWindowWorkArea( widget_get_xid(m_pWindow) );
- }
- }
- else if( pEvent->type == ConfigureNotify )
- {
- if( m_pForeignParent && pEvent->xconfigure.window == m_aForeignParentWindow )
- {
- bContinueDispatch = false;
- gtk_window_resize( GTK_WINDOW(m_pWindow), pEvent->xconfigure.width, pEvent->xconfigure.height );
- if( ( sal::static_int_cast< int >(maGeometry.nWidth) !=
- pEvent->xconfigure.width ) ||
- ( sal::static_int_cast< int >(maGeometry.nHeight) !=
- pEvent->xconfigure.height ) )
- {
- maGeometry.nWidth = pEvent->xconfigure.width;
- maGeometry.nHeight = pEvent->xconfigure.height;
- setMinMaxSize();
- getDisplay()->SendInternalEvent( this, nullptr, SalEvent::Resize );
- }
- }
- else if( m_pForeignTopLevel && pEvent->xconfigure.window == m_aForeignTopLevelWindow )
- {
- bContinueDispatch = false;
- // update position
- int x = 0, y = 0;
- ::Window aChild;
- XTranslateCoordinates( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- getDisplay()->GetRootWindow( getDisplay()->GetDefaultXScreen() ),
- 0, 0,
- &x, &y,
- &aChild );
- if( x != maGeometry.nX || y != maGeometry.nY )
- {
- maGeometry.nX = x;
- maGeometry.nY = y;
- getDisplay()->SendInternalEvent( this, nullptr, SalEvent::Move );
- }
- }
- }
- else if( pEvent->type == ClientMessage &&
- pEvent->xclient.message_type == getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED ) &&
- pEvent->xclient.window == widget_get_xid(m_pWindow) &&
- m_bWindowIsGtkPlug
- )
- {
- // FIXME: this should not be necessary, GtkPlug should do this
- // transparently for us
- if( pEvent->xclient.data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
- pEvent->xclient.data.l[1] == 2 // XEMBED_WINDOW_DEACTIVATE
- )
- {
- GdkEventFocus aEvent;
- aEvent.type = GDK_FOCUS_CHANGE;
- aEvent.window = widget_get_window( m_pWindow );
- aEvent.send_event = gint8(TRUE);
- aEvent.in = gint16(pEvent->xclient.data.l[1] == 1);
- signalFocus( m_pWindow, &aEvent, this );
- }
- }
-
- return bContinueDispatch;
-}
-
-gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- SalMouseEvent aEvent;
- SalEvent nEventType = SalEvent::NONE;
- switch( pEvent->type )
- {
- case GDK_BUTTON_PRESS:
- nEventType = SalEvent::MouseButtonDown;
- break;
- case GDK_BUTTON_RELEASE:
- nEventType = SalEvent::MouseButtonUp;
- break;
- default:
- return false;
- }
- switch( pEvent->button )
- {
- case 1: aEvent.mnButton = MOUSE_LEFT; break;
- case 2: aEvent.mnButton = MOUSE_MIDDLE; break;
- case 3: aEvent.mnButton = MOUSE_RIGHT; break;
- default: return false;
- }
- aEvent.mnTime = pEvent->time;
- aEvent.mnX = static_cast<long>(pEvent->x_root) - pThis->maGeometry.nX;
- aEvent.mnY = static_cast<long>(pEvent->y_root) - pThis->maGeometry.nY;
- aEvent.mnCode = GetMouseModCode( pEvent->state );
-
- bool bClosePopups = false;
- if( pEvent->type == GDK_BUTTON_PRESS &&
- !(pThis->m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)
- )
- {
- if( m_nFloats > 0 )
- {
- // close popups if user clicks outside our application
- gint x, y;
- bClosePopups = (gdk_display_get_window_at_pointer( GtkSalFrame::getGdkDisplay(), &x, &y ) == nullptr);
- }
- /* #i30306# release implicit pointer grab if no popups are open; else
- * Drag cannot grab the pointer and will fail.
- */
- if( m_nFloats < 1 || bClosePopups )
- gdk_display_pointer_ungrab( GtkSalFrame::getGdkDisplay(), GDK_CURRENT_TIME );
- }
-
- if( pThis->m_bWindowIsGtkPlug &&
- pEvent->type == GDK_BUTTON_PRESS &&
- pEvent->button == 1 )
- {
- pThis->askForXEmbedFocus( pEvent->time );
- }
-
- if( AllSettings::GetLayoutRTL() )
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- vcl::DeletionListener aDel( pThis );
-
- pThis->CallCallback( nEventType, &aEvent );
-
- if( ! aDel.isDeleted() )
- {
- if( bClosePopups )
- {
- ImplSVData* pSVData = ImplGetSVData();
- if ( pSVData->maWinData.mpFirstFloat )
- {
- if (!(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoAppFocusClose))
- pSVData->maWinData.mpFirstFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
- }
- }
-
- if( ! aDel.isDeleted() )
- {
- int frame_x = static_cast<int>(pEvent->x_root - pEvent->x);
- int frame_y = static_cast<int>(pEvent->y_root - pEvent->y);
- if( frame_x != pThis->maGeometry.nX || frame_y != pThis->maGeometry.nY )
- {
- pThis->maGeometry.nX = frame_x;
- pThis->maGeometry.nY = frame_y;
- pThis->CallCallback( SalEvent::Move, nullptr );
- }
- }
- }
-
- return true;
-}
-
-gboolean GtkSalFrame::signalScroll(GtkWidget*, GdkEvent* pInEvent, gpointer frame)
-{
- GdkEventScroll& rEvent = pInEvent->scroll;
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- static sal_uLong nLines = 0;
- if( ! nLines )
- {
- char* pEnv = getenv( "SAL_WHEELLINES" );
- nLines = pEnv ? atoi( pEnv ) : 3;
- if( nLines > 10 )
- nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
- }
-
- bool bNeg = (rEvent.direction == GDK_SCROLL_DOWN || rEvent.direction == GDK_SCROLL_RIGHT );
- SalWheelMouseEvent aEvent;
- aEvent.mnTime = rEvent.time;
- aEvent.mnX = static_cast<sal_uLong>(rEvent.x);
- aEvent.mnY = static_cast<sal_uLong>(rEvent.y);
- aEvent.mnDelta = bNeg ? -120 : 120;
- aEvent.mnNotchDelta = bNeg ? -1 : 1;
- aEvent.mnScrollLines = nLines;
- aEvent.mnCode = GetMouseModCode( rEvent.state );
- aEvent.mbHorz = (rEvent.direction == GDK_SCROLL_LEFT || rEvent.direction == GDK_SCROLL_RIGHT);
-
- if( AllSettings::GetLayoutRTL() )
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- pThis->CallCallback( SalEvent::WheelMouse, &aEvent );
-
- return true;
-}
-
-gboolean GtkSalFrame::signalMotion( GtkWidget*, GdkEventMotion* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- SalMouseEvent aEvent;
- aEvent.mnTime = pEvent->time;
- aEvent.mnX = static_cast<long>(pEvent->x_root) - pThis->maGeometry.nX;
- aEvent.mnY = static_cast<long>(pEvent->y_root) - pThis->maGeometry.nY;
- aEvent.mnCode = GetMouseModCode( pEvent->state );
- aEvent.mnButton = 0;
-
- if( AllSettings::GetLayoutRTL() )
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- vcl::DeletionListener aDel( pThis );
-
- pThis->CallCallback( SalEvent::MouseMove, &aEvent );
-
- if( ! aDel.isDeleted() )
- {
- int frame_x = static_cast<int>(pEvent->x_root - pEvent->x);
- int frame_y = static_cast<int>(pEvent->y_root - pEvent->y);
- if( frame_x != pThis->maGeometry.nX || frame_y != pThis->maGeometry.nY )
- {
- pThis->maGeometry.nX = frame_x;
- pThis->maGeometry.nY = frame_y;
- pThis->CallCallback( SalEvent::Move, nullptr );
- }
-
- if( ! aDel.isDeleted() )
- {
- // ask for the next hint
- gint x, y;
- GdkModifierType mask;
- gdk_window_get_pointer( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &x, &y, &mask );
- }
- }
-
- return true;
-}
-
-gboolean GtkSalFrame::signalCrossing( GtkWidget*, GdkEventCrossing* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
- SalMouseEvent aEvent;
- aEvent.mnTime = pEvent->time;
- aEvent.mnX = static_cast<long>(pEvent->x_root) - pThis->maGeometry.nX;
- aEvent.mnY = static_cast<long>(pEvent->y_root) - pThis->maGeometry.nY;
- aEvent.mnCode = GetMouseModCode( pEvent->state );
- aEvent.mnButton = 0;
-
- if (AllSettings::GetLayoutRTL())
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- pThis->CallCallback( (pEvent->type == GDK_ENTER_NOTIFY) ? SalEvent::MouseMove : SalEvent::MouseLeave, &aEvent );
-
- return true;
-}
-
-gboolean GtkSalFrame::signalExpose( GtkWidget*, GdkEventExpose* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- struct SalPaintEvent aEvent( pEvent->area.x, pEvent->area.y, pEvent->area.width, pEvent->area.height, OpenGLHelper::isVCLOpenGLEnabled() );
-
- pThis->CallCallback( SalEvent::Paint, &aEvent );
-
- return false;
-}
-
-gboolean GtkSalFrame::signalConfigure( GtkWidget*, GdkEventConfigure* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- bool bMoved = false, bSized = false;
- int x = pEvent->x, y = pEvent->y;
-
- /* HACK: during sizing/moving a toolbar pThis->maGeometry is actually
- * already exact; even worse: due to the asynchronicity of configure
- * events the borderwindow which would evaluate this event
- * would size/move based on wrong data if we would actually evaluate
- * this event. So let's swallow it.
- */
- if( (pThis->m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) &&
- GtkSalFrame::getDisplay()->GetCaptureFrame() == pThis )
- return false;
-
- /* #i31785# claims we cannot trust the x,y members of the event;
- * they are e.g. not set correctly on maximize/demaximize;
- * yet the gdkdisplay-x11.c code handling configure_events has
- * done this XTranslateCoordinates work since the day ~zero.
- */
- if( x != pThis->maGeometry.nX || y != pThis->maGeometry.nY )
- {
- bMoved = true;
- pThis->maGeometry.nX = x;
- pThis->maGeometry.nY = y;
- }
- /* #i86302#
- * for non sizeable windows we set the min and max hint for the window manager to
- * achieve correct sizing. However this is asynchronous and e.g. on Compiz
- * it sometimes happens that the window gets resized to another size (some default)
- * if we update the size here, subsequent setMinMaxSize will use this wrong size
- * - which is not good since the window manager will now size the window back to this
- * wrong size at some point.
- */
- if( pThis->m_bFullscreen || (pThis->m_nStyle & (SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::PLUG)) == SalFrameStyleFlags::SIZEABLE )
- {
- if( pEvent->width != static_cast<int>(pThis->maGeometry.nWidth) || pEvent->height != static_cast<int>(pThis->maGeometry.nHeight) )
- {
- bSized = true;
- pThis->maGeometry.nWidth = pEvent->width;
- pThis->maGeometry.nHeight = pEvent->height;
- }
- }
-
- // update decoration hints
- if( ! (pThis->m_nStyle & SalFrameStyleFlags::PLUG) )
- {
- GdkRectangle aRect;
- gdk_window_get_frame_extents( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &aRect );
- pThis->maGeometry.nTopDecoration = y - aRect.y;
- pThis->maGeometry.nBottomDecoration = aRect.y + aRect.height - y - pEvent->height;
- pThis->maGeometry.nLeftDecoration = x - aRect.x;
- pThis->maGeometry.nRightDecoration = aRect.x + aRect.width - x - pEvent->width;
- }
- else
- {
- pThis->maGeometry.nTopDecoration =
- pThis->maGeometry.nBottomDecoration =
- pThis->maGeometry.nLeftDecoration =
- pThis->maGeometry.nRightDecoration = 0;
- }
-
- pThis->updateScreenNumber();
- if( bSized )
- pThis->AllocateFrame();
-
- if( bMoved && bSized )
- pThis->CallCallback( SalEvent::MoveResize, nullptr );
- else if( bMoved )
- pThis->CallCallback( SalEvent::Move, nullptr );
- else if( bSized )
- pThis->CallCallback( SalEvent::Resize, nullptr );
-
- if (bSized)
- pThis->TriggerPaintEvent();
- return false;
-}
-
-void GtkSalFrame::TriggerPaintEvent()
-{
-}
-
-gboolean GtkSalFrame::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- SalGenericInstance *pSalInstance =
- static_cast< SalGenericInstance* >(GetSalData()->m_pInstance);
-
- // check if printers have changed (analogous to salframe focus handler)
- pSalInstance->updatePrinterUpdate();
-
- if( !pEvent->in )
- pThis->m_nKeyModifiers = ModKeyFlags::NONE;
-
- if( pThis->m_pIMHandler )
- pThis->m_pIMHandler->focusChanged( pEvent->in != 0 );
-
- // ask for changed printers like generic implementation
- if( pEvent->in && pSalInstance->isPrinterInit() )
- pSalInstance->updatePrinterUpdate();
-
- // FIXME: find out who the hell steals the focus from our frame
- // while we have the pointer grabbed, this should not come from
- // the window manager. Is this an event that was still queued ?
- // The focus does not seem to get set inside our process
-
- // in the meantime do not propagate focus get/lose if floats are open
- if( m_nFloats == 0 )
- pThis->CallCallback( pEvent->in ? SalEvent::GetFocus : SalEvent::LoseFocus, nullptr );
-
- return false;
-}
-
-static OString getDisplayString()
-{
- int nParams = rtl_getAppCommandArgCount();
- OUString aParam;
- for( int i = 0; i < nParams; i++ )
- {
- rtl_getAppCommandArg( i, &aParam.pData );
- if( i < nParams-1 && (aParam == "-display" || aParam == "--display" ) )
- {
- rtl_getAppCommandArg( i+1, &aParam.pData );
- return OUStringToOString( aParam, osl_getThreadTextEncoding() );
- }
- }
- return OString();
-}
-
-gboolean GtkSalFrame::signalMap( GtkWidget *pWidget, GdkEvent*, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- //Spawn off a helper program that will attempt to set this fullscreen
- //window either to span all displays or the current monitor
- if (pThis->m_bFullscreen)
- {
- GdkWindow* gdkwin = widget_get_window(pThis->m_pWindow);
- if (gdkwin)
- {
- OUString sProgramURL( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/xid-fullscreen-on-all-monitors");
- rtl::Bootstrap::expandMacros(sProgramURL);
- OUString sProgram;
- if (osl::FileBase::getSystemPathFromFileURL(sProgramURL, sProgram) == osl::File::E_None)
- {
- OString sFinalProgram(OUStringToOString(sProgram, osl_getThreadTextEncoding())
- + " " + OString::number(static_cast<int>(GDK_WINDOW_XID(gdkwin)))
- + " " + OString::number(static_cast<int>(pThis->m_bSpanMonitorsWhenFullscreen)));
- OString sDisplay(getDisplayString());
- if (!sDisplay.isEmpty())
- {
- sFinalProgram += "--display " + sDisplay;
- }
- (void) system(sFinalProgram.getStr());
- }
- }
- }
-
- if ( pThis->m_nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION )
- gtk_window_set_accept_focus( GTK_WINDOW(pWidget), true );
-
- bool bSetFocus = pThis->m_bSetFocusOnMap;
- pThis->m_bSetFocusOnMap = false;
-
- if( bSetFocus )
- pThis->ToTop( SalFrameToTop::GrabFocus );
-
- pThis->CallCallback( SalEvent::Resize, nullptr );
- pThis->TriggerPaintEvent();
-
- return false;
-}
-
-gboolean GtkSalFrame::signalUnmap( GtkWidget*, GdkEvent*, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- pThis->CallCallback( SalEvent::Resize, nullptr );
-
- return false;
-}
-
-gboolean GtkSalFrame::signalKey( GtkWidget*, GdkEventKey* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- vcl::DeletionListener aDel( pThis );
-
- if( pThis->m_pIMHandler )
- {
- if( pThis->m_pIMHandler->handleKeyEvent( pEvent ) )
- return true;
- }
-
- // handle modifiers
- if( pEvent->keyval == GDK_KEY_Shift_L || pEvent->keyval == GDK_KEY_Shift_R ||
- pEvent->keyval == GDK_KEY_Control_L || pEvent->keyval == GDK_KEY_Control_R ||
- pEvent->keyval == GDK_KEY_Alt_L || pEvent->keyval == GDK_KEY_Alt_R ||
- pEvent->keyval == GDK_KEY_Meta_L || pEvent->keyval == GDK_KEY_Meta_R ||
- pEvent->keyval == GDK_KEY_Super_L || pEvent->keyval == GDK_KEY_Super_R )
- {
- sal_uInt16 nModCode = GetKeyModCode( pEvent->state );
- ModKeyFlags nExtModMask = ModKeyFlags::NONE;
- sal_uInt16 nModMask = 0;
- // pressing just the ctrl key leads to a keysym of XK_Control but
- // the event state does not contain ControlMask. In the release
- // event it's the other way round: it does contain the Control mask.
- // The modifier mode therefore has to be adapted manually.
- switch( pEvent->keyval )
- {
- case GDK_KEY_Control_L:
- nExtModMask = ModKeyFlags::LeftMod1;
- nModMask = KEY_MOD1;
- break;
- case GDK_KEY_Control_R:
- nExtModMask = ModKeyFlags::RightMod1;
- nModMask = KEY_MOD1;
- break;
- case GDK_KEY_Alt_L:
- nExtModMask = ModKeyFlags::LeftMod2;
- nModMask = KEY_MOD2;
- break;
- case GDK_KEY_Alt_R:
- nExtModMask = ModKeyFlags::RightMod2;
- nModMask = KEY_MOD2;
- break;
- case GDK_KEY_Shift_L:
- nExtModMask = ModKeyFlags::LeftShift;
- nModMask = KEY_SHIFT;
- break;
- case GDK_KEY_Shift_R:
- nExtModMask = ModKeyFlags::RightShift;
- nModMask = KEY_SHIFT;
- break;
- // Map Meta/Super to MOD3 modifier on all Unix systems
- // except macOS
- case GDK_KEY_Meta_L:
- case GDK_KEY_Super_L:
- nExtModMask = ModKeyFlags::LeftMod3;
- nModMask = KEY_MOD3;
- break;
- case GDK_KEY_Meta_R:
- case GDK_KEY_Super_R:
- nExtModMask = ModKeyFlags::RightMod3;
- nModMask = KEY_MOD3;
- break;
- }
-
- SalKeyModEvent aModEvt;
- aModEvt.mbDown = pEvent->type == GDK_KEY_PRESS;
- aModEvt.mnCode = nModCode;
-
- if( pEvent->type == GDK_KEY_RELEASE )
- {
- aModEvt.mnModKeyCode = pThis->m_nKeyModifiers;
- nModCode &= ~nModMask;
- pThis->m_nKeyModifiers &= ~nExtModMask;
- }
- else
- {
- nModCode |= nModMask;
- pThis->m_nKeyModifiers |= nExtModMask;
- aModEvt.mnModKeyCode = pThis->m_nKeyModifiers;
- }
-
- pThis->CallCallback( SalEvent::KeyModChange, &aModEvt );
- }
- else
- {
- pThis->doKeyCallback( pEvent->state,
- pEvent->keyval,
- pEvent->hardware_keycode,
- pEvent->group,
- sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )),
- (pEvent->type == GDK_KEY_PRESS),
- false );
- if( ! aDel.isDeleted() )
- pThis->m_nKeyModifiers = ModKeyFlags::NONE;
- }
-
- if( !aDel.isDeleted() && pThis->m_pIMHandler )
- pThis->m_pIMHandler->updateIMSpotLocation();
-
- return true;
-}
-
-gboolean GtkSalFrame::signalDelete( GtkWidget*, GdkEvent*, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- pThis->CallCallback( SalEvent::Close, nullptr );
-
- return true;
-}
-
-void GtkSalFrame::signalStyleSet( GtkWidget*, GtkStyle* pPrevious, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
-
- // every frame gets an initial style set on creation
- // do not post these as the whole application tends to
- // redraw itself to adjust to the new style
- // where there IS no new style resulting in tremendous unnecessary flickering
- if( pPrevious != nullptr )
- {
- // signalStyleSet does NOT usually have the gdk lock
- // so post user event to safely dispatch the SalEvent::SettingsChanged
- // note: settings changed for multiple frames is avoided in winproc.cxx ImplHandleSettings
- GtkSalFrame::getDisplay()->SendInternalEvent( pThis, nullptr, SalEvent::SettingsChanged );
-
- // fire off font-changed when the system cairo font hints change
- GtkInstance *pInstance = static_cast<GtkInstance*>(GetSalData()->m_pInstance);
- const cairo_font_options_t* pLastCairoFontOptions = pInstance->GetLastSeenCairoFontOptions();
- const cairo_font_options_t* pCurrentCairoFontOptions = gdk_screen_get_font_options(gdk_screen_get_default());
- bool bFontSettingsChanged = true;
- if (pLastCairoFontOptions && pCurrentCairoFontOptions)
- bFontSettingsChanged = !cairo_font_options_equal(pLastCairoFontOptions, pCurrentCairoFontOptions);
- else if (!pLastCairoFontOptions && !pCurrentCairoFontOptions)
- bFontSettingsChanged = false;
- if (bFontSettingsChanged)
- {
- pInstance->ResetLastSeenCairoFontOptions(pCurrentCairoFontOptions);
- GtkSalFrame::getDisplay()->SendInternalEvent( pThis, nullptr, SalEvent::FontChanged );
- }
- }
-
- /* #i64117# gtk sets a nice background pixmap
- * but we actually don't really want that, so save
- * some time on the Xserver as well as prevent
- * some paint issues
- */
- GdkWindow* pWin = widget_get_window(GTK_WIDGET(pThis->getWindow()));
- if( pWin )
- {
- ::Window aWin = GDK_WINDOW_XWINDOW(pWin);
- if( aWin != None )
- XSetWindowBackgroundPixmap( GtkSalFrame::getDisplay()->GetDisplay(),
- aWin,
- None );
- }
- if( ! pThis->m_pParent )
- {
- // signalize theme changed for NWF caches
- // FIXME: should be called only once for a style change
- GtkSalGraphics::bThemeChanged = true;
- }
-}
-
-gboolean GtkSalFrame::signalWindowState( GtkWidget*, GdkEvent* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
- if( (pThis->m_nState & GDK_WINDOW_STATE_ICONIFIED) != (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED ) )
- {
- GtkSalFrame::getDisplay()->SendInternalEvent( pThis, nullptr, SalEvent::Resize );
- pThis->TriggerPaintEvent();
- }
-
- if( (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_MAXIMIZED) &&
- ! (pThis->m_nState & GDK_WINDOW_STATE_MAXIMIZED) )
- {
- pThis->m_aRestorePosSize =
- tools::Rectangle( Point( pThis->maGeometry.nX, pThis->maGeometry.nY ),
- Size( pThis->maGeometry.nWidth, pThis->maGeometry.nHeight ) );
- }
- pThis->m_nState = pEvent->window_state.new_window_state;
-
- #if OSL_DEBUG_LEVEL > 1
- if( (pEvent->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN) )
- {
- fprintf( stderr, "window %p %s full screen state\n",
- pThis,
- (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ? "enters" : "leaves");
- }
- #endif
-
- return false;
-}
-
-gboolean GtkSalFrame::signalVisibility( GtkWidget*, GdkEventVisibility* /*pEvent*/, gpointer /*frame*/ )
-{
- return true;
-}
-
-void GtkSalFrame::signalDestroy( GtkWidget* pObj, gpointer frame )
-{
- GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
- if( pObj == pThis->m_pWindow )
- {
- pThis->m_pFixedContainer = nullptr;
- pThis->m_pEventBox = nullptr;
- pThis->m_pWindow = nullptr;
- pThis->InvalidateGraphics();
- }
-}
-
-// GtkSalFrame::IMHandler
-
-GtkSalFrame::IMHandler::IMHandler( GtkSalFrame* pFrame )
-: m_pFrame(pFrame),
- m_nPrevKeyPresses( 0 ),
- m_pIMContext( nullptr ),
- m_bFocused( true ),
- m_bPreeditJustChanged( false )
-{
- m_aInputEvent.mpTextAttr = nullptr;
- createIMContext();
-}
-
-GtkSalFrame::IMHandler::~IMHandler()
-{
- // cancel an eventual event posted to begin preedit again
- GtkSalFrame::getDisplay()->CancelInternalEvent( m_pFrame, &m_aInputEvent, SalEvent::ExtTextInput );
- deleteIMContext();
-}
-
-void GtkSalFrame::IMHandler::createIMContext()
-{
- if( m_pIMContext )
- return;
-
- m_pIMContext = gtk_im_multicontext_new ();
- g_signal_connect( m_pIMContext, "commit",
- G_CALLBACK (signalIMCommit), this );
- g_signal_connect( m_pIMContext, "preedit_changed",
- G_CALLBACK (signalIMPreeditChanged), this );
- g_signal_connect( m_pIMContext, "retrieve_surrounding",
- G_CALLBACK (signalIMRetrieveSurrounding), this );
- g_signal_connect( m_pIMContext, "delete_surrounding",
- G_CALLBACK (signalIMDeleteSurrounding), this );
- g_signal_connect( m_pIMContext, "preedit_start",
- G_CALLBACK (signalIMPreeditStart), this );
- g_signal_connect( m_pIMContext, "preedit_end",
- G_CALLBACK (signalIMPreeditEnd), this );
-
- GetGenericUnixSalData()->ErrorTrapPush();
- gtk_im_context_set_client_window( m_pIMContext, widget_get_window(GTK_WIDGET(m_pFrame->m_pWindow)) );
- gtk_im_context_focus_in( m_pIMContext );
- GetGenericUnixSalData()->ErrorTrapPop();
- m_bFocused = true;
-
-}
-
-void GtkSalFrame::IMHandler::deleteIMContext()
-{
- if( m_pIMContext )
- {
- // first give IC a chance to deinitialize
- GetGenericUnixSalData()->ErrorTrapPush();
- gtk_im_context_set_client_window( m_pIMContext, nullptr );
- GetGenericUnixSalData()->ErrorTrapPop();
- // destroy old IC
- g_object_unref( m_pIMContext );
- m_pIMContext = nullptr;
- }
-}
-
-void GtkSalFrame::IMHandler::doCallEndExtTextInput()
-{
- m_aInputEvent.mpTextAttr = nullptr;
- m_pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
-}
-
-void GtkSalFrame::IMHandler::updateIMSpotLocation()
-{
- SalExtTextInputPosEvent aPosEvent;
- m_pFrame->CallCallback( SalEvent::ExtTextInputPos, static_cast<void*>(&aPosEvent) );
- GdkRectangle aArea;
- aArea.x = aPosEvent.mnX;
- aArea.y = aPosEvent.mnY;
- aArea.width = aPosEvent.mnWidth;
- aArea.height = aPosEvent.mnHeight;
- GetGenericUnixSalData()->ErrorTrapPush();
- gtk_im_context_set_cursor_location( m_pIMContext, &aArea );
- GetGenericUnixSalData()->ErrorTrapPop();
-}
-
-void GtkSalFrame::IMHandler::sendEmptyCommit()
-{
- vcl::DeletionListener aDel( m_pFrame );
-
- SalExtTextInputEvent aEmptyEv;
- aEmptyEv.mpTextAttr = nullptr;
- aEmptyEv.maText.clear();
- aEmptyEv.mnCursorPos = 0;
- aEmptyEv.mnCursorFlags = 0;
- m_pFrame->CallCallback( SalEvent::ExtTextInput, static_cast<void*>(&aEmptyEv) );
- if( ! aDel.isDeleted() )
- m_pFrame->CallCallback( SalEvent::EndExtTextInput, nullptr );
-}
-
-void GtkSalFrame::IMHandler::endExtTextInput( EndExtTextInputFlags /*nFlags*/ )
-{
- gtk_im_context_reset ( m_pIMContext );
-
- if( m_aInputEvent.mpTextAttr )
- {
- vcl::DeletionListener aDel( m_pFrame );
- // delete preedit in sal (commit an empty string)
- sendEmptyCommit();
- if( ! aDel.isDeleted() )
- {
- // mark previous preedit state again (will e.g. be sent at focus gain)
- m_aInputEvent.mpTextAttr = m_aInputFlags.data();
- if( m_bFocused )
- {
- // begin preedit again
- GtkSalFrame::getDisplay()->SendInternalEvent( m_pFrame, &m_aInputEvent, SalEvent::ExtTextInput );
- }
- }
- }
-}
-
-void GtkSalFrame::IMHandler::focusChanged( bool bFocusIn )
-{
- m_bFocused = bFocusIn;
- if( bFocusIn )
- {
- GetGenericUnixSalData()->ErrorTrapPush();
- gtk_im_context_focus_in( m_pIMContext );
- GetGenericUnixSalData()->ErrorTrapPop();
- if( m_aInputEvent.mpTextAttr )
- {
- sendEmptyCommit();
- // begin preedit again
- GtkSalFrame::getDisplay()->SendInternalEvent( m_pFrame, &m_aInputEvent, SalEvent::ExtTextInput );
- }
- }
- else
- {
- GetGenericUnixSalData()->ErrorTrapPush();
- gtk_im_context_focus_out( m_pIMContext );
- GetGenericUnixSalData()->ErrorTrapPop();
- // cancel an eventual event posted to begin preedit again
- GtkSalFrame::getDisplay()->CancelInternalEvent( m_pFrame, &m_aInputEvent, SalEvent::ExtTextInput );
- }
-}
-
-bool GtkSalFrame::IMHandler::handleKeyEvent( GdkEventKey* pEvent )
-{
- vcl::DeletionListener aDel( m_pFrame );
-
- if( pEvent->type == GDK_KEY_PRESS )
- {
- // Add this key press event to the list of previous key presses
- // to which we compare key release events. If a later key release
- // event has a matching key press event in this list, we swallow
- // the key release because some GTK Input Methods don't swallow it
- // for us.
- m_aPrevKeyPresses.emplace_back(pEvent );
- m_nPrevKeyPresses++;
-
- // Also pop off the earliest key press event if there are more than 10
- // already.
- while (m_nPrevKeyPresses > 10)
- {
- m_aPrevKeyPresses.pop_front();
- m_nPrevKeyPresses--;
- }
-
- GObject* pRef = G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext ) ) );
-
- // #i51353# update spot location on every key input since we cannot
- // know which key may activate a preedit choice window
- updateIMSpotLocation();
- if( aDel.isDeleted() )
- return true;
-
- gboolean bResult = gtk_im_context_filter_keypress( m_pIMContext, pEvent );
- g_object_unref( pRef );
-
- if( aDel.isDeleted() )
- return true;
-
- m_bPreeditJustChanged = false;
-
- if( bResult )
- return true;
- else
- {
- SAL_WARN_IF( m_nPrevKeyPresses <= 0, "vcl.gtk", "key press has vanished !" );
- if( ! m_aPrevKeyPresses.empty() ) // sanity check
- {
- // event was not swallowed, do not filter a following
- // key release event
- // note: this relies on gtk_im_context_filter_keypress
- // returning without calling a handler (in the "not swallowed"
- // case ) which might change the previous key press list so
- // we would pop the wrong event here
- m_aPrevKeyPresses.pop_back();
- m_nPrevKeyPresses--;
- }
- }
- }
-
- // Determine if we got an earlier key press event corresponding to this key release
- if (pEvent->type == GDK_KEY_RELEASE)
- {
- GObject* pRef = G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext ) ) );
- gboolean bResult = gtk_im_context_filter_keypress( m_pIMContext, pEvent );
- g_object_unref( pRef );
-
- if( aDel.isDeleted() )
- return true;
-
- m_bPreeditJustChanged = false;
-
- auto iter = std::find(m_aPrevKeyPresses.begin(), m_aPrevKeyPresses.end(), pEvent);
- // If we found a corresponding previous key press event, swallow the release
- // and remove the earlier key press from our list
- if (iter != m_aPrevKeyPresses.end())
- {
- m_aPrevKeyPresses.erase(iter);
- m_nPrevKeyPresses--;
- return true;
- }
-
- if( bResult )
- return true;
- }
-
- return false;
-}
-
-/* FIXME:
-* #122282# still more hacking: some IMEs never start a preedit but simply commit
-* in this case we cannot commit a single character. Workaround: do not do the
-* single key hack for enter or space if the unicode committed does not match
-*/
-
-static bool checkSingleKeyCommitHack( guint keyval, sal_Unicode cCode )
-{
- bool bRet = true;
- switch( keyval )
- {
- case GDK_KEY_KP_Enter:
- case GDK_KEY_Return:
- if( cCode != '\n' && cCode != '\r' )
- bRet = false;
- break;
- case GDK_KEY_space:
- case GDK_KEY_KP_Space:
- if( cCode != ' ' )
- bRet = false;
- break;
- default:
- break;
- }
- return bRet;
-}
-
-void GtkSalFrame::IMHandler::signalIMCommit( GtkIMContext* pContext, gchar* pText, gpointer im_handler )
-{
- GtkSalFrame::IMHandler* pThis = static_cast<GtkSalFrame::IMHandler*>(im_handler);
-
- SolarMutexGuard aGuard;
- vcl::DeletionListener aDel( pThis->m_pFrame );
- {
- const bool bWasPreedit =
- (pThis->m_aInputEvent.mpTextAttr != nullptr) ||
- pThis->m_bPreeditJustChanged;
-
- pThis->m_aInputEvent.mpTextAttr = nullptr;
- pThis->m_aInputEvent.maText = OUString( pText, strlen(pText), RTL_TEXTENCODING_UTF8 );
- pThis->m_aInputEvent.mnCursorPos = pThis->m_aInputEvent.maText.getLength();
- pThis->m_aInputEvent.mnCursorFlags = 0;
-
- pThis->m_aInputFlags.clear();
-
- /* necessary HACK: all keyboard input comes in here as soon as an IMContext is set
- * which is logical and consequent. But since even simple input like
- * <space> comes through the commit signal instead of signalKey
- * and all kinds of windows only implement KeyInput (e.g. PushButtons,
- * RadioButtons and a lot of other Controls), will send a single
- * KeyInput/KeyUp sequence instead of an ExtText event if there
- * never was a preedit and the text is only one character.
- *
- * In this case there the last ExtText event must have been
- * SalEvent::EndExtTextInput, either because of a regular commit
- * or because there never was a preedit.
- */
- bool bSingleCommit = false;
- if( ! bWasPreedit
- && pThis->m_aInputEvent.maText.getLength() == 1
- && ! pThis->m_aPrevKeyPresses.empty()
- )
- {
- const PreviousKeyPress& rKP = pThis->m_aPrevKeyPresses.back();
- sal_Unicode aOrigCode = pThis->m_aInputEvent.maText[0];
-
- if( checkSingleKeyCommitHack( rKP.keyval, aOrigCode ) )
- {
- pThis->m_pFrame->doKeyCallback( rKP.state, rKP.keyval, rKP.hardware_keycode, rKP.group, aOrigCode, true, true );
- bSingleCommit = true;
- }
- }
- if( ! bSingleCommit )
- {
- pThis->m_pFrame->CallCallback( SalEvent::ExtTextInput, static_cast<void*>(&pThis->m_aInputEvent));
- if( ! aDel.isDeleted() )
- pThis->doCallEndExtTextInput();
- }
- if( ! aDel.isDeleted() )
- {
- // reset input event
- pThis->m_aInputEvent.maText.clear();
- pThis->m_aInputEvent.mnCursorPos = 0;
- pThis->updateIMSpotLocation();
- }
- }
-#ifdef __sun
- // #i51356# workaround a solaris IIIMP bug
- // in case of partial commits the preedit changed signal
- // and commit signal come in wrong order
- if( ! aDel.isDeleted() )
- signalIMPreeditChanged( pContext, im_handler );
-#else
- (void) pContext;
-#endif
-}
-
-void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_handler )
-{
- GtkSalFrame::IMHandler* pThis = static_cast<GtkSalFrame::IMHandler*>(im_handler);
-
- char* pText = nullptr;
- PangoAttrList* pAttrs = nullptr;
- gint nCursorPos = 0;
-
- gtk_im_context_get_preedit_string( pThis->m_pIMContext,
- &pText,
- &pAttrs,
- &nCursorPos );
- if( pText && ! *pText ) // empty string
- {
- // change from nothing to nothing -> do not start preedit
- // e.g. this will activate input into a calc cell without
- // user input
- if( pThis->m_aInputEvent.maText.getLength() == 0 )
- {
- g_free( pText );
- pango_attr_list_unref( pAttrs );
- return;
- }
- }
-
- pThis->m_bPreeditJustChanged = true;
-
- bool bEndPreedit = (!pText || !*pText) && pThis->m_aInputEvent.mpTextAttr != nullptr;
- pThis->m_aInputEvent.maText = pText ? OUString( pText, strlen(pText), RTL_TEXTENCODING_UTF8 ) : OUString();
- pThis->m_aInputEvent.mnCursorPos = nCursorPos;
- pThis->m_aInputEvent.mnCursorFlags = 0;
-
- pThis->m_aInputFlags = std::vector<ExtTextInputAttr>( std::max( 1, static_cast<int>(pThis->m_aInputEvent.maText.getLength()) ), ExtTextInputAttr::NONE );
-
- PangoAttrIterator *iter = pango_attr_list_get_iterator(pAttrs);
- do
- {
- GSList *attr_list = nullptr;
- GSList *tmp_list = nullptr;
- gint start, end;
- ExtTextInputAttr sal_attr = ExtTextInputAttr::NONE;
-
- pango_attr_iterator_range (iter, &start, &end);
- if (start == G_MAXINT || end == G_MAXINT)
- {
- auto len = pText ? g_utf8_strlen(pText, -1) : 0;
- if (end == G_MAXINT)
- end = len;
- if (start == G_MAXINT)
- start = len;
- }
- if (end == start)
- continue;
-
- start = g_utf8_pointer_to_offset (pText, pText + start);
- end = g_utf8_pointer_to_offset (pText, pText + end);
-
- tmp_list = attr_list = pango_attr_iterator_get_attrs (iter);
- while (tmp_list)
- {
- PangoAttribute *pango_attr = static_cast<PangoAttribute *>(tmp_list->data);
-
- switch (pango_attr->klass->type)
- {
- case PANGO_ATTR_BACKGROUND:
- sal_attr |= ExtTextInputAttr::Highlight;
- pThis->m_aInputEvent.mnCursorFlags |= EXTTEXTINPUT_CURSOR_INVISIBLE;
- break;
- case PANGO_ATTR_UNDERLINE:
- sal_attr |= ExtTextInputAttr::Underline;
- break;
- case PANGO_ATTR_STRIKETHROUGH:
- sal_attr |= ExtTextInputAttr::RedText;
- break;
- default:
- break;
- }
- pango_attribute_destroy (pango_attr);
- tmp_list = tmp_list->next;
- }
- if (sal_attr == ExtTextInputAttr::NONE)
- sal_attr |= ExtTextInputAttr::Underline;
- g_slist_free (attr_list);
-
- // Set the sal attributes on our text
- for (int i = start; i < end; ++i)
- {
- SAL_WARN_IF(i >= static_cast<int>(pThis->m_aInputFlags.size()),
- "vcl.gtk", "pango attrib out of range. Broken range: "
- << start << "," << end << " Legal range: 0,"
- << pThis->m_aInputFlags.size());
- if (i >= static_cast<int>(pThis->m_aInputFlags.size()))
- continue;
- pThis->m_aInputFlags[i] |= sal_attr;
- }
- } while (pango_attr_iterator_next (iter));
- pango_attr_iterator_destroy(iter);
-
- pThis->m_aInputEvent.mpTextAttr = pThis->m_aInputFlags.data();
-
- g_free( pText );
- pango_attr_list_unref( pAttrs );
-
- SolarMutexGuard aGuard;
- vcl::DeletionListener aDel( pThis->m_pFrame );
-
- pThis->m_pFrame->CallCallback( SalEvent::ExtTextInput, static_cast<void*>(&pThis->m_aInputEvent));
- if( bEndPreedit && ! aDel.isDeleted() )
- pThis->doCallEndExtTextInput();
- if( ! aDel.isDeleted() )
- pThis->updateIMSpotLocation();
-}
-
-void GtkSalFrame::IMHandler::signalIMPreeditStart( GtkIMContext*, gpointer /*im_handler*/ )
-{
-}
-
-void GtkSalFrame::IMHandler::signalIMPreeditEnd( GtkIMContext*, gpointer im_handler )
-{
- GtkSalFrame::IMHandler* pThis = static_cast<GtkSalFrame::IMHandler*>(im_handler);
-
- pThis->m_bPreeditJustChanged = true;
-
- SolarMutexGuard aGuard;
- vcl::DeletionListener aDel( pThis->m_pFrame );
- pThis->doCallEndExtTextInput();
- if( ! aDel.isDeleted() )
- pThis->updateIMSpotLocation();
-}
-
-static uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin)
-{
- uno::Reference<accessibility::XAccessibleEditableText> xText;
- try
- {
- uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible() );
- if (xAccessible.is())
- xText = FindFocusedEditableText(xAccessible->getAccessibleContext());
- }
- catch(const uno::Exception&)
- {
- TOOLS_WARN_EXCEPTION( "vcl.gtk", "Exception in getting input method surrounding text");
- }
- return xText;
-}
-
-gboolean GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext* pContext, gpointer /*im_handler*/ )
-{
- vcl::Window *pFocusWin = Application::GetFocusWindow();
- if (!pFocusWin)
- return true;
-
- uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(pFocusWin);
- if (xText.is())
- {
- sal_Int32 nPosition = xText->getCaretPosition();
- OUString sAllText = xText->getText();
- OString sUTF = OUStringToOString(sAllText, RTL_TEXTENCODING_UTF8);
- OUString sCursorText(sAllText.copy(0, nPosition));
- gtk_im_context_set_surrounding(pContext, sUTF.getStr(), sUTF.getLength(),
- OUStringToOString(sCursorText, RTL_TEXTENCODING_UTF8).getLength());
- return true;
- }
-
- return false;
-}
-
-gboolean GtkSalFrame::IMHandler::signalIMDeleteSurrounding( GtkIMContext*, gint offset, gint nchars,
- gpointer /*im_handler*/ )
-{
- vcl::Window *pFocusWin = Application::GetFocusWindow();
- if (!pFocusWin)
- return true;
-
- uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(pFocusWin);
- if (xText.is())
- {
- sal_Int32 nPosition = xText->getCaretPosition();
- // #i111768# range checking
- sal_Int32 nDeletePos = nPosition + offset;
- sal_Int32 nDeleteEnd = nDeletePos + nchars;
- if (nDeletePos < 0)
- nDeletePos = 0;
- if (nDeleteEnd < 0)
- nDeleteEnd = 0;
- if (nDeleteEnd > xText->getCharacterCount())
- nDeleteEnd = xText->getCharacterCount();
-
- xText->deleteText(nDeletePos, nDeleteEnd);
- //tdf91641 adjust cursor if deleted chars shift it forward (normal case)
- if (nDeletePos < nPosition)
- {
- if (nDeleteEnd <= nPosition)
- nPosition = nPosition - (nDeleteEnd - nDeletePos);
- else
- nPosition = nDeletePos;
-
- if (xText->getCharacterCount() >= nPosition)
- xText->setCaretPosition( nPosition );
- }
- return true;
- }
-
- return false;
-}
-
-Size GtkSalDisplay::GetScreenSize( int nDisplayScreen )
-{
- tools::Rectangle aRect = m_pSys->GetDisplayScreenPosSizePixel( nDisplayScreen );
- return Size( aRect.GetWidth(), aRect.GetHeight() );
-}
-
-sal_uIntPtr GtkSalFrame::GetNativeWindowHandle()
-{
- return widget_get_xid(m_pWindow);
-}
-
-GdkEvent* GtkSalFrame::makeFakeKeyPress(GtkWidget* pWidget)
-{
- GdkEvent *event = gdk_event_new(GDK_KEY_PRESS);
- event->key.window = GDK_WINDOW(g_object_ref(gtk_widget_get_window(pWidget)));
- event->key.send_event = 1 /* TRUE */;
- event->key.time = gtk_get_current_event_time();
- event->key.state = 0;
- event->key.keyval = 0;
- event->key.length = 0;
- event->key.string = nullptr;
- event->key.hardware_keycode = 0;
- event->key.group = 0;
- event->key.is_modifier = false;
- return event;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtksalmenu.cxx b/vcl/unx/gtk/gtksalmenu.cxx
deleted file mode 100644
index d0503519a084..000000000000
--- a/vcl/unx/gtk/gtksalmenu.cxx
+++ /dev/null
@@ -1,1444 +0,0 @@
-/* -*- 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/.
- */
-
-#include <unx/gtk/gtksalmenu.hxx>
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-#include <unx/gendata.hxx>
-#include <unx/saldisp.hxx>
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/glomenu.h>
-#include <unx/gtk/gloactiongroup.h>
-#include <vcl/floatwin.hxx>
-#include <vcl/menu.hxx>
-#include <vcl/pngwrite.hxx>
-#include <unx/gtk/gtkinst.hxx>
-
-#include <sal/log.hxx>
-#include <tools/stream.hxx>
-#include <window.h>
-#include <strings.hrc>
-
-static bool bUnityMode = false;
-
-/*
- * This function generates a unique command name for each menu item
- */
-static gchar* GetCommandForItem(GtkSalMenu* pParentMenu, sal_uInt16 nItemId)
-{
- OString aCommand("window-");
- aCommand = aCommand + OString::number(reinterpret_cast<unsigned long>(pParentMenu));
- aCommand = aCommand + "-" + OString::number(nItemId);
- return g_strdup(aCommand.getStr());
-}
-
-static gchar* GetCommandForItem(GtkSalMenuItem* pSalMenuItem)
-{
- return GetCommandForItem(pSalMenuItem->mpParentMenu,
- pSalMenuItem->mnId);
-}
-
-bool GtkSalMenu::PrepUpdate()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- return mpMenuModel && mpActionGroup;
-#else
- return bUnityMode && mpMenuModel && mpActionGroup;
-#endif
-}
-
-/*
- * Menu updating methods
- */
-
-static void RemoveSpareItemsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nSection, unsigned nValidItems )
-{
- sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
-
- while ( nSectionItems > static_cast<sal_Int32>(nValidItems) )
- {
- gchar* aCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, --nSectionItems );
-
- if ( aCommand != nullptr && pOldCommandList != nullptr )
- *pOldCommandList = g_list_append( *pOldCommandList, g_strdup( aCommand ) );
-
- g_free( aCommand );
-
- g_lo_menu_remove_from_section( pMenu, nSection, nSectionItems );
- }
-}
-
-typedef std::pair<GtkSalMenu*, sal_uInt16> MenuAndId;
-
-namespace
-{
- MenuAndId decode_command(const gchar *action_name)
- {
- OString sCommand(action_name);
-
- sal_Int32 nIndex = 0;
- OString sWindow = sCommand.getToken(0, '-', nIndex);
- OString sGtkSalMenu = sCommand.getToken(0, '-', nIndex);
- OString sItemId = sCommand.getToken(0, '-', nIndex);
-
- GtkSalMenu* pSalSubMenu = reinterpret_cast<GtkSalMenu*>(sGtkSalMenu.toInt64());
-
- assert(sWindow == "window" && pSalSubMenu);
- (void) sWindow;
-
- return MenuAndId(pSalSubMenu, sItemId.toInt32());
- }
-}
-
-static void RemoveDisabledItemsFromNativeMenu(GLOMenu* pMenu, GList** pOldCommandList,
- sal_Int32 nSection, GActionGroup* pActionGroup)
-{
- while (nSection >= 0)
- {
- sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
- while (nSectionItems--)
- {
- gchar* pCommand = g_lo_menu_get_command_from_item_in_section(pMenu, nSection, nSectionItems);
- // remove disabled entries
- bool bRemove = !g_action_group_get_action_enabled(pActionGroup, pCommand);
- if (!bRemove)
- {
- //also remove any empty submenus
- GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section(pMenu, nSection, nSectionItems);
- if (pSubMenuModel)
- {
- gint nSubMenuSections = g_menu_model_get_n_items(G_MENU_MODEL(pSubMenuModel));
- if (nSubMenuSections == 0)
- bRemove = true;
- else if (nSubMenuSections == 1)
- {
- gint nItems = g_lo_menu_get_n_items_from_section(pSubMenuModel, 0);
- if (nItems == 0)
- bRemove = true;
- else if (nItems == 1)
- {
- //If the only entry is the "No Selection Possible" entry, then we are allowed
- //to removed it
- gchar* pSubCommand = g_lo_menu_get_command_from_item_in_section(pSubMenuModel, 0, 0);
- MenuAndId aMenuAndId(decode_command(pSubCommand));
- bRemove = aMenuAndId.second == 0xFFFF;
- g_free(pSubCommand);
- }
- }
- }
- }
-
- if (bRemove)
- {
- //but tdf#86850 Always display clipboard functions
- bRemove = g_strcmp0(pCommand, ".uno:Cut") &&
- g_strcmp0(pCommand, ".uno:Copy") &&
- g_strcmp0(pCommand, ".uno:Paste");
- }
-
- if (bRemove)
- {
- if (pCommand != nullptr && pOldCommandList != nullptr)
- *pOldCommandList = g_list_append(*pOldCommandList, g_strdup(pCommand));
- g_lo_menu_remove_from_section(pMenu, nSection, nSectionItems);
- }
-
- g_free(pCommand);
- }
- --nSection;
- }
-}
-
-static void RemoveSpareSectionsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, sal_Int32 nLastSection )
-{
- if ( pMenu == nullptr || pOldCommandList == nullptr )
- return;
-
- sal_Int32 n = g_menu_model_get_n_items( G_MENU_MODEL( pMenu ) ) - 1;
-
- for ( ; n > nLastSection; n--)
- {
- RemoveSpareItemsFromNativeMenu( pMenu, pOldCommandList, n, 0 );
- g_lo_menu_remove( pMenu, n );
- }
-}
-
-static gint CompareStr( gpointer str1, gpointer str2 )
-{
- return g_strcmp0( static_cast<const gchar*>(str1), static_cast<const gchar*>(str2) );
-}
-
-static void RemoveUnusedCommands( GLOActionGroup* pActionGroup, GList* pOldCommandList, GList* pNewCommandList )
-{
- if ( pActionGroup == nullptr || pOldCommandList == nullptr )
- {
- g_list_free_full( pOldCommandList, g_free );
- g_list_free_full( pNewCommandList, g_free );
- return;
- }
-
- while ( pNewCommandList != nullptr )
- {
- GList* pNewCommand = g_list_first( pNewCommandList );
- pNewCommandList = g_list_remove_link( pNewCommandList, pNewCommand );
-
- gpointer aCommand = g_list_nth_data( pNewCommand, 0 );
-
- GList* pOldCommand = g_list_find_custom( pOldCommandList, aCommand, reinterpret_cast<GCompareFunc>(CompareStr) );
-
- if ( pOldCommand != nullptr )
- {
- pOldCommandList = g_list_remove_link( pOldCommandList, pOldCommand );
- g_list_free_full( pOldCommand, g_free );
- }
-
- g_list_free_full( pNewCommand, g_free );
- }
-
- while ( pOldCommandList != nullptr )
- {
- GList* pCommand = g_list_first( pOldCommandList );
- pOldCommandList = g_list_remove_link( pOldCommandList, pCommand );
-
- gchar* aCommand = static_cast<gchar*>(g_list_nth_data( pCommand, 0 ));
-
- g_lo_action_group_remove( pActionGroup, aCommand );
-
- g_list_free_full( pCommand, g_free );
- }
-}
-
-void GtkSalMenu::ImplUpdate(bool bRecurse, bool bRemoveDisabledEntries)
-{
- SolarMutexGuard aGuard;
-
- SAL_INFO("vcl.unity", "ImplUpdate pre PrepUpdate");
- if( !PrepUpdate() )
- return;
-
- if (mbNeedsUpdate)
- {
- mbNeedsUpdate = false;
- if (mbMenuBar && maUpdateMenuBarIdle.IsActive())
- {
- maUpdateMenuBarIdle.Stop();
- maUpdateMenuBarIdle.Invoke();
- return;
- }
- }
-
- Menu* pVCLMenu = mpVCLMenu;
- GLOMenu* pLOMenu = G_LO_MENU( mpMenuModel );
- GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
- SAL_INFO("vcl.unity", "Syncing vcl menu " << pVCLMenu << " to menu model " << pLOMenu << " and action group " << pActionGroup);
- GList *pOldCommandList = nullptr;
- GList *pNewCommandList = nullptr;
-
- sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
-
- if ( nLOMenuSize == 0 )
- g_lo_menu_new_section( pLOMenu, 0, nullptr );
-
- sal_Int32 nSection = 0;
- sal_Int32 nItemPos = 0;
- sal_Int32 validItems = 0;
- sal_Int32 nItem;
-
- for ( nItem = 0; nItem < static_cast<sal_Int32>(GetItemCount()); nItem++ ) {
- if ( !IsItemVisible( nItem ) )
- continue;
-
- GtkSalMenuItem *pSalMenuItem = GetItemAtPos( nItem );
- sal_uInt16 nId = pSalMenuItem->mnId;
-
- // PopupMenu::ImplExecute might add <No Selection Possible> entry to top-level
- // popup menu, but we have our own implementation below, so skip that one.
- if ( nId == 0xFFFF )
- continue;
-
- if ( pSalMenuItem->mnType == MenuItemType::SEPARATOR )
- {
- // Delete extra items from current section.
- RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
-
- nSection++;
- nItemPos = 0;
- validItems = 0;
-
- if ( nLOMenuSize <= nSection )
- {
- g_lo_menu_new_section( pLOMenu, nSection, nullptr );
- nLOMenuSize++;
- }
-
- continue;
- }
-
- if ( nItemPos >= g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
- g_lo_menu_insert_in_section( pLOMenu, nSection, nItemPos, "EMPTY STRING" );
-
- // Get internal menu item values.
- OUString aText = pVCLMenu->GetItemText( nId );
- Image aImage = pVCLMenu->GetItemImage( nId );
- bool bEnabled = pVCLMenu->IsItemEnabled( nId );
- vcl::KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
- bool bChecked = pVCLMenu->IsItemChecked( nId );
- MenuItemBits itemBits = pVCLMenu->GetItemBits( nId );
-
- // Store current item command in command list.
- gchar *aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pLOMenu, nSection, nItemPos );
-
- if ( aCurrentCommand != nullptr )
- pOldCommandList = g_list_append( pOldCommandList, aCurrentCommand );
-
- // Get the new command for the item.
- gchar* aNativeCommand = GetCommandForItem(pSalMenuItem);
-
- // Force updating of native menu labels.
- NativeSetItemText( nSection, nItemPos, aText );
- NativeSetItemIcon( nSection, nItemPos, aImage );
- NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( GetFrame()->GetWindow() ) );
-
- if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == nullptr )
- {
- NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, false );
- NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
- NativeSetEnableItem( aNativeCommand, bEnabled );
-
- pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
- }
-
- GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
-
- if ( pSubmenu && pSubmenu->GetMenu() )
- {
- bool bNonMenuChangedToMenu = NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, false, true );
- pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
-
- GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
-
- if ( pSubMenuModel == nullptr )
- {
- g_lo_menu_new_submenu_in_item_in_section( pLOMenu, nSection, nItemPos );
- pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
- }
-
- g_object_unref( pSubMenuModel );
-
- if (bRecurse || bNonMenuChangedToMenu)
- {
- SAL_INFO("vcl.unity", "preparing submenu " << pSubMenuModel << " to menu model " << G_MENU_MODEL(pSubMenuModel) << " and action group " << G_ACTION_GROUP(pActionGroup));
- pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
- pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
- pSubmenu->ImplUpdate(true, bRemoveDisabledEntries);
- }
- }
-
- g_free( aNativeCommand );
-
- ++nItemPos;
- ++validItems;
- }
-
- if (bRemoveDisabledEntries)
- {
- // Delete disabled items in last section.
- RemoveDisabledItemsFromNativeMenu(pLOMenu, &pOldCommandList, nSection, G_ACTION_GROUP(pActionGroup));
- }
-
- // Delete extra items in last section.
- RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
-
- // Delete extra sections.
- RemoveSpareSectionsFromNativeMenu( pLOMenu, &pOldCommandList, nSection );
-
- // Delete unused commands.
- RemoveUnusedCommands( pActionGroup, pOldCommandList, pNewCommandList );
-
- // Resolves: tdf#103166 if the menu is empty, add a disabled
- // <No Selection Possible> placeholder.
- sal_Int32 nSectionsCount = g_menu_model_get_n_items(G_MENU_MODEL(pLOMenu));
- gint nItemsCount = 0;
- for (nSection = 0; nSection < nSectionsCount; ++nSection)
- {
- nItemsCount += g_lo_menu_get_n_items_from_section(pLOMenu, nSection);
- if (nItemsCount)
- break;
- }
- if (!nItemsCount)
- {
- gchar* aNativeCommand = GetCommandForItem(this, 0xFFFF);
- OUString aPlaceholderText(VclResId(SV_RESID_STRING_NOSELECTIONPOSSIBLE));
- g_lo_menu_insert_in_section(pLOMenu, nSection-1, 0,
- OUStringToOString(aPlaceholderText, RTL_TEXTENCODING_UTF8).getStr());
- NativeSetItemCommand(nSection-1, 0, 0xFFFF, aNativeCommand, MenuItemBits::NONE, false, false);
- NativeSetEnableItem(aNativeCommand, false);
- g_free(aNativeCommand);
- }
-}
-
-void GtkSalMenu::Update()
-{
- //find out if top level is a menubar or not, if not, then it's a popup menu
- //hierarchy and in those we hide (most) disabled entries
- const GtkSalMenu* pMenu = this;
- while (pMenu->mpParentSalMenu)
- pMenu = pMenu->mpParentSalMenu;
- ImplUpdate(false, !pMenu->mbMenuBar);
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-static void MenuPositionFunc(GtkMenu* menu, gint* x, gint* y, gboolean* push_in, gpointer user_data)
-{
- Point *pPos = static_cast<Point*>(user_data);
- *x = pPos->X();
- if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
- {
- GtkRequisition natural_size;
- gtk_widget_get_preferred_size(GTK_WIDGET(menu), nullptr, &natural_size);
- *x -= natural_size.width;
- }
- *y = pPos->Y();
- *push_in = false;
-}
-#endif
-
-bool GtkSalMenu::ShowNativePopupMenu(FloatingWindow* pWin, const tools::Rectangle& rRect,
- FloatWinPopupFlags nFlags)
-{
-#if GTK_CHECK_VERSION(3,0,0)
- VclPtr<vcl::Window> xParent = pWin->ImplGetWindowImpl()->mpRealParent;
- mpFrame = static_cast<GtkSalFrame*>(xParent->ImplGetFrame());
-
- GLOActionGroup* pActionGroup = g_lo_action_group_new();
- mpActionGroup = G_ACTION_GROUP(pActionGroup);
- mpMenuModel = G_MENU_MODEL(g_lo_menu_new());
- // Generate the main menu structure, populates mpMenuModel
- UpdateFull();
-
- GtkWidget *pWidget = gtk_menu_new_from_model(mpMenuModel);
- gtk_menu_attach_to_widget(GTK_MENU(pWidget), mpFrame->getMouseEventWidget(), nullptr);
- gtk_widget_insert_action_group(mpFrame->getMouseEventWidget(), "win", mpActionGroup);
-
- //run in a sub main loop because we need to keep vcl PopupMenu alive to use
- //it during DispatchCommand, returning now to the outer loop causes the
- //launching PopupMenu to be destroyed, instead run the subloop here
- //until the gtk menu is destroyed
- GMainLoop* pLoop = g_main_loop_new(nullptr, true);
- g_signal_connect_swapped(G_OBJECT(pWidget), "deactivate", G_CALLBACK(g_main_loop_quit), pLoop);
-
-#if GTK_CHECK_VERSION(3,22,0)
- if (gtk_check_version(3, 22, 0) == nullptr)
- {
- GdkGravity rect_anchor = GDK_GRAVITY_SOUTH_WEST, menu_anchor = GDK_GRAVITY_NORTH_WEST;
-
- if (nFlags & FloatWinPopupFlags::Left)
- {
- rect_anchor = GDK_GRAVITY_NORTH_WEST;
- menu_anchor = GDK_GRAVITY_NORTH_EAST;
- }
- else if (nFlags & FloatWinPopupFlags::Up)
- {
- rect_anchor = GDK_GRAVITY_NORTH_WEST;
- menu_anchor = GDK_GRAVITY_SOUTH_WEST;
- }
- else if (nFlags & FloatWinPopupFlags::Right)
- {
- rect_anchor = GDK_GRAVITY_NORTH_EAST;
- }
-
- tools::Rectangle aFloatRect = FloatingWindow::ImplConvertToAbsPos(xParent, rRect);
- aFloatRect.Move(-mpFrame->maGeometry.nX, -mpFrame->maGeometry.nY);
- GdkRectangle rect {static_cast<int>(aFloatRect.Left()), static_cast<int>(aFloatRect.Top()),
- static_cast<int>(aFloatRect.GetWidth()), static_cast<int>(aFloatRect.GetHeight())};
-
- GdkWindow* gdkWindow = widget_get_window(mpFrame->getMouseEventWidget());
- gtk_menu_popup_at_rect(GTK_MENU(pWidget), gdkWindow, &rect, rect_anchor, menu_anchor, nullptr);
- }
- else
-#endif
- {
- guint nButton;
- guint32 nTime;
-
- //typically there is an event, and we can then distinguish if this was
- //launched from the keyboard (gets auto-mnemoniced) or the mouse (which
- //doesn't)
- GdkEvent *pEvent = gtk_get_current_event();
- if (pEvent)
- {
- gdk_event_get_button(pEvent, &nButton);
- nTime = gdk_event_get_time(pEvent);
- }
- else
- {
- nButton = 0;
- nTime = GtkSalFrame::GetLastInputEventTime();
- }
-
- // do the same strange semantics as vcl popup windows to arrive at a frame geometry
- // in mirrored UI case; best done by actually executing the same code
- sal_uInt16 nArrangeIndex;
- Point aPos = FloatingWindow::ImplCalcPos(pWin, rRect, nFlags, nArrangeIndex);
- aPos = FloatingWindow::ImplConvertToAbsPos(xParent, aPos);
-
- gtk_menu_popup(GTK_MENU(pWidget), nullptr, nullptr, MenuPositionFunc,
- &aPos, nButton, nTime);
- }
-
- if (g_main_loop_is_running(pLoop))
- {
- gdk_threads_leave();
- g_main_loop_run(pLoop);
- gdk_threads_enter();
- }
- g_main_loop_unref(pLoop);
-
- mpVCLMenu->Deactivate();
-
- gtk_widget_insert_action_group(mpFrame->getMouseEventWidget(), "win", nullptr);
-
- gtk_widget_destroy(pWidget);
-
- g_object_unref(mpActionGroup);
- ClearActionGroupAndMenuModel();
-
- mpFrame = nullptr;
-
- return true;
-#else
- (void)pWin;
- (void)rRect;
- (void)nFlags;
- return false;
-#endif
-}
-
-/*
- * GtkSalMenu
- */
-
-GtkSalMenu::GtkSalMenu( bool bMenuBar ) :
- mbInActivateCallback( false ),
- mbMenuBar( bMenuBar ),
- mbNeedsUpdate( false ),
- mbReturnFocusToDocument( false ),
- mbAddedGrab( false ),
- mpMenuBarContainerWidget( nullptr ),
- mpMenuAllowShrinkWidget( nullptr ),
- mpMenuBarWidget( nullptr ),
- mpMenuBarContainerProvider( nullptr ),
- mpMenuBarProvider( nullptr ),
- mpCloseButton( nullptr ),
- mpVCLMenu( nullptr ),
- mpParentSalMenu( nullptr ),
- mpFrame( nullptr ),
- mpMenuModel( nullptr ),
- mpActionGroup( nullptr )
-{
- //typically this only gets called after the menu has been customized on the
- //next idle slot, in the normal case of a new menubar SetFrame is called
- //directly long before this idle would get called.
- maUpdateMenuBarIdle.SetPriority(TaskPriority::HIGHEST);
- maUpdateMenuBarIdle.SetInvokeHandler(LINK(this, GtkSalMenu, MenuBarHierarchyChangeHandler));
- maUpdateMenuBarIdle.SetDebugName("Native Gtk Menu Update Idle");
-}
-
-IMPL_LINK_NOARG(GtkSalMenu, MenuBarHierarchyChangeHandler, Timer *, void)
-{
- SAL_WARN_IF(!mpFrame, "vcl.gtk", "MenuBar layout changed, but no frame for some reason!");
- if (!mpFrame)
- return;
- SetFrame(mpFrame);
-}
-
-void GtkSalMenu::SetNeedsUpdate()
-{
- GtkSalMenu* pMenu = this;
- // start that the menu and its parents are in need of an update
- // on the next activation
- while (pMenu && !pMenu->mbNeedsUpdate)
- {
- pMenu->mbNeedsUpdate = true;
- pMenu = pMenu->mpParentSalMenu;
- }
- // only if a menubar is directly updated do we force in a full
- // structure update
- if (mbMenuBar && !maUpdateMenuBarIdle.IsActive())
- maUpdateMenuBarIdle.Start();
-}
-
-void GtkSalMenu::SetMenuModel(GMenuModel* pMenuModel)
-{
- if (mpMenuModel)
- g_object_unref(mpMenuModel);
- mpMenuModel = pMenuModel;
- if (mpMenuModel)
- g_object_ref(mpMenuModel);
-}
-
-GtkSalMenu::~GtkSalMenu()
-{
- SolarMutexGuard aGuard;
-
- DestroyMenuBarWidget();
-
- if (mpMenuModel)
- g_object_unref(mpMenuModel);
-
- maItems.clear();
-
- if (mpFrame)
- mpFrame->SetMenu(nullptr);
-}
-
-bool GtkSalMenu::VisibleMenuBar()
-{
- return mbMenuBar && (bUnityMode || mpMenuBarContainerWidget);
-}
-
-void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
-{
- SolarMutexGuard aGuard;
- GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
-
- if ( nPos == MENU_APPEND )
- maItems.push_back( pItem );
- else
- maItems.insert( maItems.begin() + nPos, pItem );
-
- pItem->mpParentMenu = this;
-
- SetNeedsUpdate();
-}
-
-void GtkSalMenu::RemoveItem( unsigned nPos )
-{
- SolarMutexGuard aGuard;
- maItems.erase( maItems.begin() + nPos );
- SetNeedsUpdate();
-}
-
-void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned )
-{
- SolarMutexGuard aGuard;
- GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
- GtkSalMenu *pGtkSubMenu = static_cast< GtkSalMenu* >( pSubMenu );
-
- if ( pGtkSubMenu == nullptr )
- return;
-
- pGtkSubMenu->mpParentSalMenu = this;
- pItem->mpSubMenu = pGtkSubMenu;
-
- SetNeedsUpdate();
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-static void CloseMenuBar(GtkWidget *, gpointer pMenu)
-{
- Application::PostUserEvent(static_cast<MenuBar*>(pMenu)->GetCloseButtonClickHdl());
-}
-#endif
-
-void GtkSalMenu::ShowCloseButton(bool bShow)
-{
-#if GTK_CHECK_VERSION(3,0,0)
- assert(mbMenuBar);
- if (!mpMenuBarContainerWidget)
- return;
-
- if (!bShow)
- {
- if (mpCloseButton)
- gtk_widget_destroy(mpCloseButton);
- return;
- }
-
- MenuBar *pVclMenuBar = static_cast<MenuBar*>(mpVCLMenu.get());
- mpCloseButton = gtk_button_new();
- g_signal_connect(mpCloseButton, "clicked", G_CALLBACK(CloseMenuBar), pVclMenuBar);
-
- gtk_button_set_relief(GTK_BUTTON(mpCloseButton), GTK_RELIEF_NONE);
- gtk_button_set_focus_on_click(GTK_BUTTON(mpCloseButton), false);
- gtk_widget_set_can_focus(mpCloseButton, false);
-
- GtkStyleContext *pButtonContext = gtk_widget_get_style_context(GTK_WIDGET(mpCloseButton));
-
- GtkCssProvider *pProvider = gtk_css_provider_new();
- static const gchar data[] = "* { "
- "padding: 0;"
- "margin-left: 8px;"
- "margin-right: 8px;"
- "min-width: 18px;"
- "min-height: 18px;"
- "}";
- const gchar olddata[] = "* { "
- "padding: 0;"
- "margin-left: 8px;"
- "margin-right: 8px;"
- "}";
- gtk_css_provider_load_from_data(pProvider, gtk_check_version(3, 20, 0) == nullptr ? data : olddata, -1, nullptr);
- gtk_style_context_add_provider(pButtonContext,
- GTK_STYLE_PROVIDER(pProvider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
- gtk_style_context_add_class(pButtonContext, "flat");
- gtk_style_context_add_class(pButtonContext, "small-button");
-
- GIcon* icon = g_themed_icon_new_with_default_fallbacks("window-close-symbolic");
- GtkWidget* image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
- gtk_widget_show(image);
- g_object_unref(icon);
-
- OUString sToolTip(VclResId(SV_HELPTEXT_CLOSEDOCUMENT));
- gtk_widget_set_tooltip_text(mpCloseButton,
- OUStringToOString(sToolTip, RTL_TEXTENCODING_UTF8).getStr());
-
- gtk_widget_set_valign(mpCloseButton, GTK_ALIGN_CENTER);
-
- gtk_container_add(GTK_CONTAINER(mpCloseButton), image);
- gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), GTK_WIDGET(mpCloseButton), 1, 0, 1, 1);
- gtk_widget_show_all(mpCloseButton);
-#else
- (void)bShow;
- (void)mpMenuBarContainerWidget;
- (void)mpCloseButton;
-#endif
-}
-
-//Typically when the menubar is deactivated we want the focus to return
-//to where it came from. If the menubar was activated because of F6
-//moving focus into the associated VCL menubar then on pressing ESC
-//or any other normal reason for deactivation we want focus to return
-//to the document, definitely not still stuck in the associated
-//VCL menubar. But if F6 is pressed while the menubar is activated
-//we want to pass that F6 back to the VCL menubar which will move
-//focus to the next pane by itself.
-void GtkSalMenu::ReturnFocus()
-{
- if (mbAddedGrab)
- {
- gtk_grab_remove(mpMenuBarWidget);
- mbAddedGrab = false;
- }
- if (!mbReturnFocusToDocument)
- gtk_widget_grab_focus(GTK_WIDGET(mpFrame->getEventBox()));
- else
- mpFrame->GetWindow()->GrabFocusToDocument();
- mbReturnFocusToDocument = false;
-}
-
-gboolean GtkSalMenu::SignalKey(GdkEventKey const * pEvent)
-{
- if (pEvent->keyval == GDK_KEY_F6)
- {
- mbReturnFocusToDocument = false;
- gtk_menu_shell_cancel(GTK_MENU_SHELL(mpMenuBarWidget));
- //because we return false here, the keypress will continue
- //to propagate and in the case that vcl focus is in
- //the vcl menubar then that will also process F6 and move
- //to the next pane
- }
- return false;
-}
-
-//The GtkSalMenu is owner by a Vcl Menu/MenuBar. In the menubar
-//case the vcl menubar is present and "visible", but with a 0 height
-//so it not apparent. Normally it acts as though it is not there when
-//a Native menubar is active. If we return true here, then for keyboard
-//activation and traversal with F6 through panes then the vcl menubar
-//acts as though it *is* present and we translate its take focus and F6
-//traversal key events into the gtk menubar equivalents.
-bool GtkSalMenu::CanGetFocus() const
-{
- return mpMenuBarWidget != nullptr;
-}
-
-bool GtkSalMenu::TakeFocus()
-{
- if (!mpMenuBarWidget)
- return false;
-
- //Send a keyboard event to the gtk menubar to let it know it has been
- //activated via the keyboard. Doesn't do anything except cause the gtk
- //menubar "keyboard_mode" member to get set to true, so typically mnemonics
- //are shown which will serve as indication that the menubar has focus
- //(given that we want to show it with no menus popped down)
- GdkEvent *event = GtkSalFrame::makeFakeKeyPress(mpMenuBarWidget);
- gtk_widget_event(mpMenuBarWidget, event);
- gdk_event_free(event);
-
- //this pairing results in a menubar with keyboard focus with no menus
- //auto-popped down
- gtk_grab_add(mpMenuBarWidget);
- mbAddedGrab = true;
- gtk_menu_shell_select_first(GTK_MENU_SHELL(mpMenuBarWidget), false);
- gtk_menu_shell_deselect(GTK_MENU_SHELL(mpMenuBarWidget));
- mbReturnFocusToDocument = true;
- return true;
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-
-static void MenuBarReturnFocus(GtkMenuShell*, gpointer menu)
-{
- GtkSalFrame::UpdateLastInputEventTime(gtk_get_current_event_time());
- GtkSalMenu* pMenu = static_cast<GtkSalMenu*>(menu);
- pMenu->ReturnFocus();
-}
-
-static gboolean MenuBarSignalKey(GtkWidget*, GdkEventKey* pEvent, gpointer menu)
-{
- GtkSalMenu* pMenu = static_cast<GtkSalMenu*>(menu);
- return pMenu->SignalKey(pEvent);
-}
-
-#endif
-
-void GtkSalMenu::CreateMenuBarWidget()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- if (mpMenuBarContainerWidget)
- return;
-
- GtkGrid* pGrid = mpFrame->getTopLevelGridWidget();
- mpMenuBarContainerWidget = gtk_grid_new();
-
- gtk_widget_set_hexpand(GTK_WIDGET(mpMenuBarContainerWidget), true);
- gtk_grid_insert_row(pGrid, 0);
- gtk_grid_attach(pGrid, mpMenuBarContainerWidget, 0, 0, 1, 1);
-
- mpMenuAllowShrinkWidget = gtk_scrolled_window_new(nullptr, nullptr);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(mpMenuAllowShrinkWidget), GTK_SHADOW_NONE);
- // tdf#116290 external policy on scrolledwindow will not show a scrollbar,
- // but still allow scrolled window to not be sized to the child content.
- // So the menubar can be shrunk past its nominal smallest width.
- // Unlike a hack using GtkFixed/GtkLayout the correct placement of the menubar occurs under RTL
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(mpMenuAllowShrinkWidget), GTK_POLICY_EXTERNAL, GTK_POLICY_NEVER);
- gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), mpMenuAllowShrinkWidget, 0, 0, 1, 1);
-
- mpMenuBarWidget = gtk_menu_bar_new_from_model(mpMenuModel);
-
- gtk_widget_insert_action_group(mpMenuBarWidget, "win", mpActionGroup);
- gtk_widget_set_hexpand(GTK_WIDGET(mpMenuBarWidget), true);
- gtk_widget_set_hexpand(mpMenuAllowShrinkWidget, true);
- gtk_container_add(GTK_CONTAINER(mpMenuAllowShrinkWidget), mpMenuBarWidget);
-
- g_signal_connect(G_OBJECT(mpMenuBarWidget), "deactivate", G_CALLBACK(MenuBarReturnFocus), this);
- g_signal_connect(G_OBJECT(mpMenuBarWidget), "key-press-event", G_CALLBACK(MenuBarSignalKey), this);
-
- gtk_widget_show_all(mpMenuBarContainerWidget);
-
- ShowCloseButton( static_cast<MenuBar*>(mpVCLMenu.get())->HasCloseButton() );
-
- ApplyPersona();
-#else
- (void)mpMenuAllowShrinkWidget;
- (void)mpMenuBarContainerWidget;
-#endif
-}
-
-void GtkSalMenu::ApplyPersona()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- if (!mpMenuBarContainerWidget)
- return;
- assert(mbMenuBar);
- // I'm dubious about the persona theming feature, but as it exists, lets try and support
- // it, apply the image to the mpMenuBarContainerWidget
- const BitmapEx& rPersonaBitmap = Application::GetSettings().GetStyleSettings().GetPersonaHeader();
-
- GtkStyleContext *pMenuBarContainerContext = gtk_widget_get_style_context(GTK_WIDGET(mpMenuBarContainerWidget));
- if (mpMenuBarContainerProvider)
- {
- gtk_style_context_remove_provider(pMenuBarContainerContext, GTK_STYLE_PROVIDER(mpMenuBarContainerProvider));
- mpMenuBarContainerProvider = nullptr;
- }
- GtkStyleContext *pMenuBarContext = gtk_widget_get_style_context(GTK_WIDGET(mpMenuBarWidget));
- if (mpMenuBarProvider)
- {
- gtk_style_context_remove_provider(pMenuBarContext, GTK_STYLE_PROVIDER(mpMenuBarProvider));
- mpMenuBarProvider = nullptr;
- }
-
- if (!rPersonaBitmap.IsEmpty())
- {
- if (maPersonaBitmap != rPersonaBitmap)
- {
- vcl::PNGWriter aPNGWriter(rPersonaBitmap);
- mxPersonaImage.reset(new utl::TempFile);
- mxPersonaImage->EnableKillingFile(true);
- SvStream* pStream = mxPersonaImage->GetStream(StreamMode::WRITE);
- aPNGWriter.Write(*pStream);
- mxPersonaImage->CloseStream();
- }
-
- mpMenuBarContainerProvider = gtk_css_provider_new();
- OUString aBuffer = "* { background-image: url(\"" + mxPersonaImage->GetURL() + "\"); background-position: top right; }";
- OString aResult = OUStringToOString(aBuffer, RTL_TEXTENCODING_UTF8);
- gtk_css_provider_load_from_data(mpMenuBarContainerProvider, aResult.getStr(), aResult.getLength(), nullptr);
- gtk_style_context_add_provider(pMenuBarContainerContext, GTK_STYLE_PROVIDER(mpMenuBarContainerProvider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
-
- // force the menubar to be transparent when persona is active otherwise for
- // me the menubar becomes gray when its in the backdrop
- mpMenuBarProvider = gtk_css_provider_new();
- static const gchar data[] = "* { "
- "background-image: none;"
- "background-color: transparent;"
- "}";
- gtk_css_provider_load_from_data(mpMenuBarProvider, data, -1, nullptr);
- gtk_style_context_add_provider(pMenuBarContext,
- GTK_STYLE_PROVIDER(mpMenuBarProvider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
- }
- maPersonaBitmap = rPersonaBitmap;
-#else
- (void)maPersonaBitmap;
- (void)mpMenuBarContainerProvider;
- (void)mpMenuBarProvider;
-#endif
-}
-
-void GtkSalMenu::DestroyMenuBarWidget()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- if (mpMenuBarContainerWidget)
- {
- gtk_widget_destroy(mpMenuBarContainerWidget);
- mpMenuBarContainerWidget = nullptr;
- mpCloseButton = nullptr;
- }
-#else
- (void)mpMenuBarContainerWidget;
-#endif
-}
-
-void GtkSalMenu::SetFrame(const SalFrame* pFrame)
-{
- SolarMutexGuard aGuard;
- assert(mbMenuBar);
- SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
- mpFrame = const_cast<GtkSalFrame*>(static_cast<const GtkSalFrame*>(pFrame));
-
- // if we had a menu on the GtkSalMenu we have to free it as we generate a
- // full menu anyway and we might need to reuse an existing model and
- // actiongroup
- mpFrame->SetMenu( this );
- mpFrame->EnsureAppMenuWatch();
-
- // Clean menu model and action group if needed.
- GtkWidget* pWidget = mpFrame->getWindow();
- GdkWindow* gdkWindow = gtk_widget_get_window( pWidget );
-
- GLOMenu* pMenuModel = G_LO_MENU( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
- GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
- SAL_INFO("vcl.unity", "Found menu model: " << pMenuModel << " and action group: " << pActionGroup);
-
- if ( pMenuModel )
- {
- if ( g_menu_model_get_n_items( G_MENU_MODEL( pMenuModel ) ) > 0 )
- g_lo_menu_remove( pMenuModel, 0 );
-
- mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
- }
-
- if ( pActionGroup )
- {
- g_lo_action_group_clear( pActionGroup );
- mpActionGroup = G_ACTION_GROUP( pActionGroup );
- }
-
- // Generate the main menu structure.
- if ( PrepUpdate() )
- UpdateFull();
-
- g_lo_menu_insert_section( pMenuModel, 0, nullptr, mpMenuModel );
-
- if (!bUnityMode && static_cast<MenuBar*>(mpVCLMenu.get())->IsDisplayable())
- {
- DestroyMenuBarWidget();
- CreateMenuBarWidget();
- }
-}
-
-const GtkSalFrame* GtkSalMenu::GetFrame() const
-{
- SolarMutexGuard aGuard;
- const GtkSalMenu* pMenu = this;
- while( pMenu && ! pMenu->mpFrame )
- pMenu = pMenu->mpParentSalMenu;
- return pMenu ? pMenu->mpFrame : nullptr;
-}
-
-void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck )
-{
- SolarMutexGuard aGuard;
-
- if ( mpActionGroup == nullptr )
- return;
-
- gchar* aCommand = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
-
- if ( aCommand != nullptr || g_strcmp0( aCommand, "" ) != 0 )
- {
- GVariant *pCheckValue = nullptr;
- GVariant *pCurrentState = g_action_group_get_action_state( mpActionGroup, aCommand );
-
- if ( bits & MenuItemBits::RADIOCHECK )
- pCheckValue = bCheck ? g_variant_new_string( aCommand ) : g_variant_new_string( "" );
- else
- {
- // By default, all checked items are checkmark buttons.
- if (bCheck || pCurrentState != nullptr)
- pCheckValue = g_variant_new_boolean( bCheck );
- }
-
- if ( pCheckValue != nullptr )
- {
- if ( pCurrentState == nullptr || g_variant_equal( pCurrentState, pCheckValue ) == FALSE )
- {
- g_action_group_change_action_state( mpActionGroup, aCommand, pCheckValue );
- }
- else
- {
- g_variant_unref (pCheckValue);
- }
- }
-
- if ( pCurrentState != nullptr )
- g_variant_unref( pCurrentState );
- }
-
- if ( aCommand )
- g_free( aCommand );
-}
-
-void GtkSalMenu::NativeSetEnableItem( gchar const * aCommand, gboolean bEnable )
-{
- SolarMutexGuard aGuard;
- GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
-
- if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bEnable )
- g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bEnable );
-}
-
-void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const OUString& rText )
-{
- SolarMutexGuard aGuard;
- // Escape all underscores so that they don't get interpreted as hotkeys
- OUString aText = rText.replaceAll( "_", "__" );
- // Replace the LibreOffice hotkey identifier with an underscore
- aText = aText.replace( '~', '_' );
- OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
-
- // Update item text only when necessary.
- gchar* aLabel = g_lo_menu_get_label_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
-
- if ( aLabel == nullptr || g_strcmp0( aLabel, aConvertedText.getStr() ) != 0 )
- g_lo_menu_set_label_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aConvertedText.getStr() );
-
- if ( aLabel )
- g_free( aLabel );
-}
-
-namespace
-{
- void DestroyMemoryStream(gpointer data)
- {
- SvMemoryStream* pMemStm = static_cast<SvMemoryStream*>(data);
- delete pMemStm;
- }
-}
-
-void GtkSalMenu::NativeSetItemIcon( unsigned nSection, unsigned nItemPos, const Image& rImage )
-{
-#if GLIB_CHECK_VERSION(2,38,0)
- if (!rImage && mbHasNullItemIcon)
- return;
-
- SolarMutexGuard aGuard;
-
- if (!!rImage)
- {
- SvMemoryStream* pMemStm = new SvMemoryStream;
- vcl::PNGWriter aWriter(rImage.GetBitmapEx());
- aWriter.Write(*pMemStm);
-
- GBytes *pBytes = g_bytes_new_with_free_func(pMemStm->GetData(),
- pMemStm->TellEnd(),
- DestroyMemoryStream,
- pMemStm);
-
- GIcon *pIcon = g_bytes_icon_new(pBytes);
-
- g_lo_menu_set_icon_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, pIcon );
- g_object_unref(pIcon);
- g_bytes_unref(pBytes);
- mbHasNullItemIcon = false;
- }
- else
- {
- g_lo_menu_set_icon_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, nullptr );
- mbHasNullItemIcon = true;
- }
-#else
- (void)nSection;
- (void)nItemPos;
- (void)rImage;
-#endif
-}
-
-void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const vcl::KeyCode& rKeyCode, const OUString& rKeyName )
-{
- SolarMutexGuard aGuard;
-
- if ( rKeyName.isEmpty() )
- return;
-
- guint nKeyCode;
- GdkModifierType nModifiers;
- GtkSalFrame::KeyCodeToGdkKey(rKeyCode, &nKeyCode, &nModifiers);
-
- gchar* aAccelerator = gtk_accelerator_name( nKeyCode, nModifiers );
-
- gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
-
- if ( aCurrentAccel == nullptr && g_strcmp0( aCurrentAccel, aAccelerator ) != 0 )
- g_lo_menu_set_accelerator_to_item_in_section ( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aAccelerator );
-
- g_free( aAccelerator );
- g_free( aCurrentAccel );
-}
-
-bool GtkSalMenu::NativeSetItemCommand( unsigned nSection,
- unsigned nItemPos,
- sal_uInt16 nId,
- const gchar* aCommand,
- MenuItemBits nBits,
- bool bChecked,
- bool bIsSubmenu )
-{
- bool bSubMenuAddedOrRemoved = false;
-
- SolarMutexGuard aGuard;
- GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
-
- GVariant *pTarget = nullptr;
-
- if (g_action_group_has_action(mpActionGroup, aCommand))
- g_lo_action_group_remove(pActionGroup, aCommand);
-
- if ( ( nBits & MenuItemBits::CHECKABLE ) || bIsSubmenu )
- {
- // Item is a checkmark button.
- GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_BOOLEAN) );
- GVariant* pState = g_variant_new_boolean( bChecked );
-
- g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, nullptr, pStateType, nullptr, pState );
- }
- else if ( nBits & MenuItemBits::RADIOCHECK )
- {
- // Item is a radio button.
- GVariantType* pParameterType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
- GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
- GVariant* pState = g_variant_new_string( "" );
- pTarget = g_variant_new_string( aCommand );
-
- g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, nullptr, pState );
- }
- else
- {
- // Item is not special, so insert a stateless action.
- g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
- }
-
- GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
-
- // Menu item is not updated unless it's necessary.
- gchar* aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
-
- if ( aCurrentCommand == nullptr || g_strcmp0( aCurrentCommand, aCommand ) != 0 )
- {
- bool bOldHasSubmenu = g_lo_menu_get_submenu_from_item_in_section(pMenu, nSection, nItemPos) != nullptr;
- bSubMenuAddedOrRemoved = bOldHasSubmenu != bIsSubmenu;
- if (bSubMenuAddedOrRemoved)
- {
- //tdf#98636 it's not good enough to unset the "submenu-action" attribute to change something
- //from a submenu to a non-submenu item, so remove the old one entirely and re-add it to
- //support achieving that
- gchar* pLabel = g_lo_menu_get_label_from_item_in_section(pMenu, nSection, nItemPos);
- g_lo_menu_remove_from_section(pMenu, nSection, nItemPos);
- g_lo_menu_insert_in_section(pMenu, nSection, nItemPos, pLabel);
- g_free(pLabel);
- }
-
- g_lo_menu_set_command_to_item_in_section( pMenu, nSection, nItemPos, aCommand );
-
- gchar* aItemCommand = g_strconcat("win.", aCommand, nullptr );
-
- if ( bIsSubmenu )
- g_lo_menu_set_submenu_action_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand );
- else
- {
- g_lo_menu_set_action_and_target_value_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand, pTarget );
- pTarget = nullptr;
- }
-
- g_free( aItemCommand );
- }
-
- if ( aCurrentCommand )
- g_free( aCurrentCommand );
-
- if (pTarget)
- g_variant_unref(pTarget);
-
- return bSubMenuAddedOrRemoved;
-}
-
-GtkSalMenu* GtkSalMenu::GetTopLevel()
-{
- GtkSalMenu *pMenu = this;
- while (pMenu->mpParentSalMenu)
- pMenu = pMenu->mpParentSalMenu;
- return pMenu;
-}
-
-void GtkSalMenu::DispatchCommand(const gchar *pCommand)
-{
- SolarMutexGuard aGuard;
- MenuAndId aMenuAndId = decode_command(pCommand);
- GtkSalMenu* pSalSubMenu = aMenuAndId.first;
- GtkSalMenu* pTopLevel = pSalSubMenu->GetTopLevel();
- if (pTopLevel->mpMenuBarWidget)
- {
- // tdf#125803 spacebar will toggle radios and checkbuttons without automatically
- // closing the menu. To handle this properly I imagine we need to set groups for the
- // radiobuttons so the others visually untoggle when the active one is toggled and
- // we would further need to teach vcl that the state can change more than once.
- //
- // or we could unconditionally deactivate the menus if regardless of what particular
- // type of menu item got activated
- gtk_menu_shell_deactivate(GTK_MENU_SHELL(pTopLevel->mpMenuBarWidget));
- }
- pTopLevel->GetMenu()->HandleMenuCommandEvent(pSalSubMenu->GetMenu(), aMenuAndId.second);
-}
-
-void GtkSalMenu::ActivateAllSubmenus(Menu* pMenuBar)
-{
- for (GtkSalMenuItem* pSalItem : maItems)
- {
- if ( pSalItem->mpSubMenu != nullptr )
- {
- // We can re-enter this method via the new event loop that gets created
- // in GtkClipboardTransferable::getTransferDataFlavorsAsVector, so use the InActivateCallback
- // flag to detect that and skip some startup work.
- if (!pSalItem->mpSubMenu->mbInActivateCallback)
- {
- pSalItem->mpSubMenu->mbInActivateCallback = true;
- pMenuBar->HandleMenuActivateEvent(pSalItem->mpSubMenu->GetMenu());
- pSalItem->mpSubMenu->mbInActivateCallback = false;
- pSalItem->mpSubMenu->ActivateAllSubmenus(pMenuBar);
- pSalItem->mpSubMenu->Update();
- pMenuBar->HandleMenuDeActivateEvent(pSalItem->mpSubMenu->GetMenu());
- }
- }
- }
-}
-
-void GtkSalMenu::ClearActionGroupAndMenuModel()
-{
- SetMenuModel(nullptr);
- mpActionGroup = nullptr;
- for (GtkSalMenuItem* pSalItem : maItems)
- {
- if ( pSalItem->mpSubMenu != nullptr )
- {
- pSalItem->mpSubMenu->ClearActionGroupAndMenuModel();
- }
- }
-}
-
-void GtkSalMenu::Activate(const gchar* pCommand)
-{
- MenuAndId aMenuAndId = decode_command(pCommand);
- GtkSalMenu* pSalMenu = aMenuAndId.first;
- GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
- Menu* pVclMenu = pSalMenu->GetMenu();
- Menu* pVclSubMenu = pVclMenu->GetPopupMenu(aMenuAndId.second);
- GtkSalMenu* pSubMenu = pSalMenu->GetItemAtPos(pVclMenu->GetItemPos(aMenuAndId.second))->mpSubMenu;
-
- pSubMenu->mbInActivateCallback = true;
- pTopLevel->GetMenu()->HandleMenuActivateEvent(pVclSubMenu);
- pSubMenu->mbInActivateCallback = false;
- pVclSubMenu->UpdateNativeMenu();
-}
-
-void GtkSalMenu::Deactivate(const gchar* pCommand)
-{
- MenuAndId aMenuAndId = decode_command(pCommand);
- GtkSalMenu* pSalMenu = aMenuAndId.first;
- GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
- Menu* pVclMenu = pSalMenu->GetMenu();
- Menu* pVclSubMenu = pVclMenu->GetPopupMenu(aMenuAndId.second);
- pTopLevel->GetMenu()->HandleMenuDeActivateEvent(pVclSubMenu);
-}
-
-void GtkSalMenu::EnableUnity(bool bEnable)
-{
- bUnityMode = bEnable;
-
- MenuBar* pMenuBar(static_cast<MenuBar*>(mpVCLMenu.get()));
- bool bDisplayable(pMenuBar->IsDisplayable());
-
- if (bEnable)
- {
- DestroyMenuBarWidget();
- UpdateFull();
- if (!bDisplayable)
- ShowMenuBar(false);
- }
- else
- {
- Update();
- ShowMenuBar(bDisplayable);
- }
-
- pMenuBar->LayoutChanged();
-}
-
-void GtkSalMenu::ShowMenuBar( bool bVisible )
-{
- // Unity tdf#106271: Can't hide global menu, so empty it instead when user wants to hide menubar,
- if (bUnityMode)
- {
- if (bVisible)
- Update();
- else if (mpMenuModel && g_menu_model_get_n_items(G_MENU_MODEL(mpMenuModel)) > 0)
- g_lo_menu_remove(G_LO_MENU(mpMenuModel), 0);
- }
- else if (bVisible)
- CreateMenuBarWidget();
- else
- DestroyMenuBarWidget();
-}
-
-bool GtkSalMenu::IsItemVisible( unsigned nPos )
-{
- SolarMutexGuard aGuard;
- bool bVisible = false;
-
- if ( nPos < maItems.size() )
- bVisible = maItems[ nPos ]->mbVisible;
-
- return bVisible;
-}
-
-void GtkSalMenu::CheckItem( unsigned, bool )
-{
-}
-
-void GtkSalMenu::EnableItem( unsigned nPos, bool bEnable )
-{
- SolarMutexGuard aGuard;
- if ( bUnityMode && !mbInActivateCallback && !mbNeedsUpdate && GetTopLevel()->mbMenuBar && ( nPos < maItems.size() ) )
- {
- gchar* pCommand = GetCommandForItem( GetItemAtPos( nPos ) );
- NativeSetEnableItem( pCommand, bEnable );
- g_free( pCommand );
- }
-}
-
-void GtkSalMenu::ShowItem( unsigned nPos, bool bShow )
-{
- SolarMutexGuard aGuard;
- if ( nPos < maItems.size() )
- {
- maItems[ nPos ]->mbVisible = bShow;
- if ( bUnityMode && !mbInActivateCallback && !mbNeedsUpdate && GetTopLevel()->mbMenuBar )
- Update();
- }
-}
-
-void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const OUString& rText )
-{
- SolarMutexGuard aGuard;
- if ( bUnityMode && !mbInActivateCallback && !mbNeedsUpdate && GetTopLevel()->mbMenuBar && ( nPos < maItems.size() ) )
- {
- gchar* pCommand = GetCommandForItem( static_cast< GtkSalMenuItem* >( pSalMenuItem ) );
-
- gint nSectionsCount = g_menu_model_get_n_items( mpMenuModel );
- for ( gint nSection = 0; nSection < nSectionsCount; ++nSection )
- {
- gint nItemsCount = g_lo_menu_get_n_items_from_section( G_LO_MENU( mpMenuModel ), nSection );
- for ( gint nItem = 0; nItem < nItemsCount; ++nItem )
- {
- gchar* pCommandFromModel = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItem );
-
- if ( !g_strcmp0( pCommandFromModel, pCommand ) )
- {
- NativeSetItemText( nSection, nItem, rText );
- g_free( pCommandFromModel );
- g_free( pCommand );
- return;
- }
-
- g_free( pCommandFromModel );
- }
- }
-
- g_free( pCommand );
- }
-}
-
-void GtkSalMenu::SetItemImage( unsigned, SalMenuItem*, const Image& )
-{
-}
-
-void GtkSalMenu::SetAccelerator( unsigned, SalMenuItem*, const vcl::KeyCode&, const OUString& )
-{
-}
-
-void GtkSalMenu::GetSystemMenuData( SystemMenuData* )
-{
-}
-
-int GtkSalMenu::GetMenuBarHeight() const
-{
-#if GTK_CHECK_VERSION(3,0,0)
- return mpMenuBarWidget ? gtk_widget_get_allocated_height(mpMenuBarWidget) : 0;
-#else
- return 0;
-#endif
-}
-
-/*
- * GtkSalMenuItem
- */
-
-GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
- mpParentMenu( nullptr ),
- mpSubMenu( nullptr ),
- mnType( pItemData->eType ),
- mnId( pItemData->nId ),
- mbVisible( true )
-{
-}
-
-GtkSalMenuItem::~GtkSalMenuItem()
-{
-}
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/gtksys.cxx b/vcl/unx/gtk/gtksys.cxx
deleted file mode 100644
index 373459589429..000000000000
--- a/vcl/unx/gtk/gtksys.cxx
+++ /dev/null
@@ -1,296 +0,0 @@
-/* -*- 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 .
- */
-
-#include <string.h>
-#include <gmodule.h>
-#include <gtk/gtk.h>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtksys.hxx>
-#include <osl/module.h>
-
-GtkSalSystem *GtkSalSystem::GetSingleton()
-{
- static GtkSalSystem *pSingleton = new GtkSalSystem();
- return pSingleton;
-}
-
-SalSystem *GtkInstance::CreateSalSystem()
-{
- return GtkSalSystem::GetSingleton();
-}
-
-GtkSalSystem::GtkSalSystem() : SalGenericSystem()
-{
- mpDisplay = gdk_display_get_default();
- countScreenMonitors();
-#if GTK_CHECK_VERSION(3,0,0)
- // rhbz#1285356, native look will be gtk2, which crashes
- // when gtk3 is already loaded. Until there is a solution
- // java-side force look and feel to something that doesn't
- // crash when we are using gtk3
- setenv("STOC_FORCE_SYSTEM_LAF", "true", 1);
-#endif
-}
-
-GtkSalSystem::~GtkSalSystem()
-{
-}
-
-int
-GtkSalSystem::GetDisplayXScreenCount()
-{
- return gdk_display_get_n_screens (mpDisplay);
-}
-
-namespace
-{
-
-struct GdkRectangleCoincidentLess
-{
- // fdo#78799 - detect and elide overlaying monitors of different sizes
- bool operator()(GdkRectangle const& rLeft, GdkRectangle const& rRight)
- {
- return
- rLeft.x < rRight.x
- || rLeft.y < rRight.y
- ;
- }
-};
-struct GdkRectangleCoincident
-{
- // fdo#78799 - detect and elide overlaying monitors of different sizes
- bool operator()(GdkRectangle const& rLeft, GdkRectangle const& rRight)
- {
- return
- rLeft.x == rRight.x
- && rLeft.y == rRight.y
- ;
- }
-};
-
-}
-
-/**
- * GtkSalSystem::countScreenMonitors()
- *
- * This method builds the vector which allows us to map from VCL's
- * idea of linear integer ScreenNumber to gtk+'s rather more
- * complicated screen + monitor concept.
- */
-void
-GtkSalSystem::countScreenMonitors()
-{
- maScreenMonitors.clear();
- for (gint i = 0; i < gdk_display_get_n_screens(mpDisplay); i++)
- {
- GdkScreen* const pScreen(gdk_display_get_screen(mpDisplay, i));
- gint nMonitors(pScreen ? gdk_screen_get_n_monitors(pScreen) : 0);
- if (nMonitors > 1)
- {
- std::vector<GdkRectangle> aGeometries;
- aGeometries.reserve(nMonitors);
- for (gint j(0); j != nMonitors; ++j)
- {
- GdkRectangle aGeometry;
- gdk_screen_get_monitor_geometry(pScreen, j, &aGeometry);
- aGeometries.push_back(aGeometry);
- }
- std::sort(aGeometries.begin(), aGeometries.end(),
- GdkRectangleCoincidentLess());
- const std::vector<GdkRectangle>::iterator aUniqueEnd(
- std::unique(aGeometries.begin(), aGeometries.end(),
- GdkRectangleCoincident()));
- nMonitors = std::distance(aGeometries.begin(), aUniqueEnd);
- }
- maScreenMonitors.emplace_back(pScreen, nMonitors);
- }
-}
-
-// Including gdkx.h kills us with the Window / XWindow conflict
-extern "C" {
-#if GTK_CHECK_VERSION(3,0,0)
- GType gdk_x11_display_get_type();
-#endif
- int gdk_x11_screen_get_screen_number (GdkScreen *screen);
-}
-
-SalX11Screen
-GtkSalSystem::getXScreenFromDisplayScreen(unsigned int nScreen)
-{
- gint nMonitor;
-
- GdkScreen *pScreen = getScreenMonitorFromIdx (nScreen, nMonitor);
- if (!pScreen)
- return SalX11Screen (0);
-#if GTK_CHECK_VERSION(3,0,0)
- if (!G_TYPE_CHECK_INSTANCE_TYPE (mpDisplay, gdk_x11_display_get_type ()))
- return SalX11Screen (0);
-#endif
- return SalX11Screen (gdk_x11_screen_get_screen_number (pScreen));
-}
-
-GdkScreen *
-GtkSalSystem::getScreenMonitorFromIdx (int nIdx, gint &nMonitor)
-{
- GdkScreen *pScreen = nullptr;
- for (auto const& screenMonitor : maScreenMonitors)
- {
- pScreen = screenMonitor.first;
- if (!pScreen)
- break;
- if (nIdx >= screenMonitor.second)
- nIdx -= screenMonitor.second;
- else
- break;
- }
- nMonitor = nIdx;
-
- // handle invalid monitor indexes as non-existent screens
- if (nMonitor < 0 || (pScreen && nMonitor >= gdk_screen_get_n_monitors (pScreen)))
- pScreen = nullptr;
-
- return pScreen;
-}
-
-int
-GtkSalSystem::getScreenIdxFromPtr (GdkScreen *pScreen)
-{
- int nIdx = 0;
- for (auto const& screenMonitor : maScreenMonitors)
- {
- if (screenMonitor.first == pScreen)
- return nIdx;
- nIdx += screenMonitor.second;
- }
- g_warning ("failed to find screen %p", pScreen);
- return 0;
-}
-
-int GtkSalSystem::getScreenMonitorIdx (GdkScreen *pScreen,
- int nX, int nY)
-{
- // TODO: this will fail horribly for exotic combinations like two
- // monitors in mirror mode and one extra. Hopefully such
- // abominations are not used (or, even better, not possible) in
- // practice .-)
- return getScreenIdxFromPtr (pScreen) +
- gdk_screen_get_monitor_at_point (pScreen, nX, nY);
-}
-
-unsigned int GtkSalSystem::GetDisplayScreenCount()
-{
- gint nMonitor;
- (void)getScreenMonitorFromIdx (G_MAXINT, nMonitor);
- return G_MAXINT - nMonitor;
-}
-
-bool GtkSalSystem::IsUnifiedDisplay()
-{
- return gdk_display_get_n_screens (mpDisplay) == 1;
-}
-
-namespace {
-int _fallback_get_primary_monitor (GdkScreen *pScreen)
-{
- // Use monitor name as primacy heuristic
- int max = gdk_screen_get_n_monitors (pScreen);
- for (int i = 0; i < max; ++i)
- {
- char *name = gdk_screen_get_monitor_plug_name (pScreen, i);
- bool bLaptop = (name && !g_ascii_strncasecmp (name, "LVDS", 4));
- g_free (name);
- if (bLaptop)
- return i;
- }
- return 0;
-}
-
-int _get_primary_monitor (GdkScreen *pScreen)
-{
- static int (*get_fn) (GdkScreen *) = nullptr;
-#if GTK_CHECK_VERSION(3,0,0)
- get_fn = gdk_screen_get_primary_monitor;
-#endif
- // Perhaps we have a newer gtk+ with this symbol:
- if (!get_fn)
- {
- get_fn = reinterpret_cast<int(*)(GdkScreen*)>(osl_getAsciiFunctionSymbol(nullptr,
- "gdk_screen_get_primary_monitor"));
- }
- if (!get_fn)
- get_fn = _fallback_get_primary_monitor;
- if (get_fn)
- return get_fn (pScreen);
- else
- return 0;
-}
-} // end anonymous namespace
-
-unsigned int GtkSalSystem::GetDisplayBuiltInScreen()
-{
- GdkScreen *pDefault = gdk_display_get_default_screen (mpDisplay);
- int idx = getScreenIdxFromPtr (pDefault);
- return idx + _get_primary_monitor (pDefault);
-}
-
-tools::Rectangle GtkSalSystem::GetDisplayScreenPosSizePixel (unsigned int nScreen)
-{
- gint nMonitor;
- GdkScreen *pScreen;
- GdkRectangle aRect;
- pScreen = getScreenMonitorFromIdx (nScreen, nMonitor);
- if (!pScreen)
- return tools::Rectangle();
- gdk_screen_get_monitor_geometry (pScreen, nMonitor, &aRect);
- return tools::Rectangle (Point(aRect.x, aRect.y), Size(aRect.width, aRect.height));
-}
-
-// convert ~ to indicate mnemonic to '_'
-static OString MapToGtkAccelerator(const OUString &rStr)
-{
- return OUStringToOString(rStr.replaceFirst("~", "_"), RTL_TEXTENCODING_UTF8);
-}
-
-int GtkSalSystem::ShowNativeDialog (const OUString& rTitle, const OUString& rMessage,
- const std::vector< OUString >& rButtonNames)
-{
- OString aTitle (OUStringToOString (rTitle, RTL_TEXTENCODING_UTF8));
- OString aMessage (OUStringToOString (rMessage, RTL_TEXTENCODING_UTF8));
-
- GtkDialog *pDialog = GTK_DIALOG (
- g_object_new (GTK_TYPE_MESSAGE_DIALOG,
- "title", aTitle.getStr(),
- "message-type", int(GTK_MESSAGE_WARNING),
- "text", aMessage.getStr(),
- nullptr));
- int nButton = 0;
- for (auto const& buttonName : rButtonNames)
- gtk_dialog_add_button (pDialog, MapToGtkAccelerator(buttonName).getStr(), nButton++);
- gtk_dialog_set_default_response (pDialog, 0/*nDefaultButton*/);
-
- nButton = gtk_dialog_run (pDialog);
- if (nButton < 0)
- nButton = -1;
-
- gtk_widget_destroy (GTK_WIDGET (pDialog));
-
- return nButton;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/hudawareness.cxx b/vcl/unx/gtk/hudawareness.cxx
deleted file mode 100644
index b7985fdb58ab..000000000000
--- a/vcl/unx/gtk/hudawareness.cxx
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- 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/.
- */
-
-#include <string.h>
-
-#include <unx/gtk/gtksalmenu.hxx>
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-#include <unx/gtk/hudawareness.h>
-
-struct HudAwarenessHandle
-{
- GDBusConnection *connection;
- HudAwarenessCallback callback;
- gpointer user_data;
- GDestroyNotify notify;
-};
-
-static void
-hud_awareness_method_call (GDBusConnection * /* connection */,
- const gchar * /* sender */,
- const gchar * /* object_path */,
- const gchar * /* interface_name */,
- const gchar *method_name,
- GVariant *parameters,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- HudAwarenessHandle *handle = static_cast<HudAwarenessHandle*>(user_data);
-
- if (g_str_equal (method_name, "HudActiveChanged"))
- {
- gboolean active;
-
- g_variant_get (parameters, "(b)", &active);
-
- (* handle->callback) (active, handle->user_data);
- }
-
- g_dbus_method_invocation_return_value (invocation, nullptr);
-}
-
-guint
-hud_awareness_register (GDBusConnection *connection,
- const gchar *object_path,
- HudAwarenessCallback callback,
- gpointer user_data,
- GDestroyNotify notify,
- GError **error)
-{
- static GDBusInterfaceInfo *iface;
- static GDBusNodeInfo *info;
- GDBusInterfaceVTable vtable;
- HudAwarenessHandle *handle;
- guint object_id;
-
- memset (static_cast<void *>(&vtable), 0, sizeof (vtable));
- vtable.method_call = hud_awareness_method_call;
-
- if G_UNLIKELY (iface == nullptr)
- {
- GError *local_error = nullptr;
-
- info = g_dbus_node_info_new_for_xml ("<node>"
- "<interface name='com.canonical.hud.Awareness'>"
- "<method name='CheckAwareness'/>"
- "<method name='HudActiveChanged'>"
- "<arg type='b'/>"
- "</method>"
- "</interface>"
- "</node>",
- &local_error);
- g_assert_no_error (local_error);
- iface = g_dbus_node_info_lookup_interface (info, "com.canonical.hud.Awareness");
- g_assert (iface != nullptr);
- }
-
- handle = static_cast<HudAwarenessHandle*>(g_malloc (sizeof (HudAwarenessHandle)));
-
- object_id = g_dbus_connection_register_object (connection, object_path, iface, &vtable, handle, &g_free, error);
-
- if (object_id == 0)
- {
- g_free (handle);
- return 0;
- }
-
- handle->connection = static_cast<GDBusConnection*>(g_object_ref (connection));
- handle->callback = callback;
- handle->user_data = user_data;
- handle->notify = notify;
-
- return object_id;
-}
-
-void
-hud_awareness_unregister (GDBusConnection *connection,
- guint subscription_id)
-{
- g_dbus_connection_unregister_object (connection, subscription_id);
-}
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/salnativewidgets-gtk.cxx b/vcl/unx/gtk/salnativewidgets-gtk.cxx
deleted file mode 100644
index eb2f59457575..000000000000
--- a/vcl/unx/gtk/salnativewidgets-gtk.cxx
+++ /dev/null
@@ -1,4480 +0,0 @@
-/* -*- 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 .
- */
-
-#include <config_version.h>
-
-#include <vcl/svapp.hxx>
-
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkgdi.hxx>
-
-#include <unx/pixmap.hxx>
-#include <saldatabasic.hxx>
-#include <unx/saldisp.hxx>
-
-#include <cstdio>
-#include <cmath>
-#include <memory>
-#include <vector>
-#include <algorithm>
-#include <unordered_map>
-
-#include <boost/optional.hpp>
-
-#include <vcl/vclenum.hxx>
-#include <vcl/settings.hxx>
-#include <unx/fontmanager.hxx>
-#include <vcl/decoview.hxx>
-
-#include <vcl/opengl/OpenGLHelper.hxx>
-#include <ControlCacheKey.hxx>
-
-typedef struct _cairo_font_options cairo_font_options_t;
-const char* const tabPrelitDataName="libreoffice-tab-is-prelit";
-
-// initialize statics
-bool GtkSalGraphics::bThemeChanged = true;
-bool GtkSalGraphics::bNeedPixmapPaint = false;
-bool GtkSalGraphics::bNeedTwoPasses = false;
-
-enum
-{
- BG_NONE = 0,
- BG_FILL,
- BG_WHITE,
- BG_BLACK
-};
-
-GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow,
- SalX11Screen nXScreen )
- : X11SalGraphics(),
- m_pWindow( pWindow ),
- m_aClipRegion(true)
-{
- Init( pFrame, GDK_WINDOW_XID( widget_get_window( pWindow ) ), nXScreen );
-
- initWidgetDrawBackends();
-}
-
-GtkSalGraphics::~GtkSalGraphics()
-{
-}
-
-/*************************************
- * Cached native widget objects
- *************************************/
-class NWPixmapCacheList;
-class NWPixmapCache;
-struct NWFWidgetData
-{
- GtkWidget * gCacheWindow;
- GtkWidget * gDumbContainer;
-
- GtkWidget * gBtnWidget;
- GtkWidget * gRadioWidget;
- GtkWidget * gRadioWidgetSibling;
- GtkWidget * gCheckWidget;
- GtkWidget * gScrollHorizWidget;
- GtkWidget * gScrollVertWidget;
- GtkWidget * gArrowWidget;
- GtkWidget * gDropdownWidget;
- GtkWidget * gEditBoxWidget;
- GtkWidget * gSpinButtonWidget;
- GtkWidget * gNotebookWidget;
- GtkWidget * gOptionMenuWidget;
- GtkWidget * gComboWidget;
- GtkWidget * gScrolledWindowWidget;
- GtkWidget * gToolbarWidget;
- GtkWidget * gToolbarButtonWidget;
- GtkWidget * gHandleBoxWidget;
- GtkWidget * gMenubarWidget;
- GtkWidget * gMenuItemMenubarWidget;
- GtkWidget * gMenuWidget;
- GtkWidget * gMenuItemMenuWidget;
- GtkWidget * gMenuItemCheckMenuWidget;
- GtkWidget * gMenuItemRadioMenuWidget;
- GtkWidget * gMenuItemSeparatorMenuWidget;
- GtkWidget * gImageMenuItem;
- GtkWidget * gTooltipPopup;
- GtkWidget * gProgressBar;
- GtkWidget * gTreeView;
- GtkWidget * gHScale;
- GtkWidget * gVScale;
- GtkWidget * gSeparator;
- GtkWidget * gDialog;
- GtkWidget * gFrame;
-
- NWPixmapCacheList* gNWPixmapCacheList;
- NWPixmapCache* gCacheTabItems;
- NWPixmapCache* gCacheTabPages;
-
- NWFWidgetData() :
- gCacheWindow( nullptr ),
- gDumbContainer( nullptr ),
- gBtnWidget( nullptr ),
- gRadioWidget( nullptr ),
- gRadioWidgetSibling( nullptr ),
- gCheckWidget( nullptr ),
- gScrollHorizWidget( nullptr ),
- gScrollVertWidget( nullptr ),
- gArrowWidget( nullptr ),
- gDropdownWidget( nullptr ),
- gEditBoxWidget( nullptr ),
- gSpinButtonWidget( nullptr ),
- gNotebookWidget( nullptr ),
- gOptionMenuWidget( nullptr ),
- gComboWidget( nullptr ),
- gScrolledWindowWidget( nullptr ),
- gToolbarWidget( nullptr ),
- gToolbarButtonWidget( nullptr ),
- gHandleBoxWidget( nullptr ),
- gMenubarWidget( nullptr ),
- gMenuItemMenubarWidget( nullptr ),
- gMenuWidget( nullptr ),
- gMenuItemMenuWidget( nullptr ),
- gMenuItemCheckMenuWidget( nullptr ),
- gMenuItemRadioMenuWidget( nullptr ),
- gMenuItemSeparatorMenuWidget( nullptr ),
- gImageMenuItem( nullptr ),
- gTooltipPopup( nullptr ),
- gProgressBar( nullptr ),
- gTreeView( nullptr ),
- gHScale( nullptr ),
- gVScale( nullptr ),
- gSeparator( nullptr ),
- gDialog( nullptr ),
- gFrame( nullptr ),
- gNWPixmapCacheList( nullptr ),
- gCacheTabItems( nullptr ),
- gCacheTabPages( nullptr )
- {}
-};
-
-// Keep a hash table of Widgets->default flags so that we can
-// easily and quickly reset each to a default state before using
-// them
-static std::unordered_map<long, guint> gWidgetDefaultFlags;
-class WidgetDataVector
-{
-private:
- std::vector<NWFWidgetData> mData;
-
-public:
- explicit WidgetDataVector(size_t nElems = 0) : mData( nElems ) {}
- size_t size() const { return mData.size(); }
- NWFWidgetData &operator [](size_t i) { return mData.at(i); }
- NWFWidgetData &operator [](const SalX11Screen &s) { return mData.at(s.getXScreen()); }
-};
-static WidgetDataVector gWidgetData;
-
-static const GtkBorder aDefDefBorder = { 1, 1, 1, 1 };
-
-// Some GTK defaults
-#define MIN_ARROW_SIZE 11
-#define BTN_CHILD_SPACING 1
-#define MIN_SPIN_ARROW_WIDTH 6
-
-static void NWEnsureGTKRadio ( SalX11Screen nScreen );
-static void NWEnsureGTKButton ( SalX11Screen nScreen );
-static void NWEnsureGTKCheck ( SalX11Screen nScreen );
-static void NWEnsureGTKScrollbars ( SalX11Screen nScreen );
-static void NWEnsureGTKArrow ( SalX11Screen nScreen );
-static void NWEnsureGTKEditBox ( SalX11Screen nScreen );
-static void NWEnsureGTKSpinButton ( SalX11Screen nScreen );
-static void NWEnsureGTKNotebook ( SalX11Screen nScreen );
-static void NWEnsureGTKOptionMenu ( SalX11Screen nScreen );
-static void NWEnsureGTKCombo ( SalX11Screen nScreen );
-static void NWEnsureGTKScrolledWindow ( SalX11Screen nScreen );
-static void NWEnsureGTKToolbar ( SalX11Screen nScreen );
-static void NWEnsureGTKMenubar ( SalX11Screen nScreen );
-static void NWEnsureGTKMenu ( SalX11Screen nScreen );
-static void NWEnsureGTKTooltip ( SalX11Screen nScreen );
-static void NWEnsureGTKDialog ( SalX11Screen nScreen );
-static void NWEnsureGTKFrame ( SalX11Screen nScreen );
-static void NWEnsureGTKProgressBar ( SalX11Screen nScreen );
-static void NWEnsureGTKTreeView ( SalX11Screen nScreen );
-static void NWEnsureGTKSlider ( SalX11Screen nScreen );
-
-static void NWConvertVCLStateToGTKState( ControlState nVCLState, GtkStateType* nGTKState, GtkShadowType* nGTKShadow );
-static void NWAddWidgetToCacheWindow( GtkWidget* widget, SalX11Screen nScreen );
-static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState );
-
-static void NWCalcArrowRect( const tools::Rectangle& rButton, tools::Rectangle& rArrow );
-
-/*
- * Individual helper functions
- *
- */
-
-static tools::Rectangle NWGetButtonArea( SalX11Screen nScreen, tools::Rectangle aAreaRect, ControlState nState);
-
-static tools::Rectangle NWGetTabItemRect( SalX11Screen nScreen, tools::Rectangle aAreaRect );
-
-static tools::Rectangle NWGetEditBoxPixmapRect( SalX11Screen nScreen, tools::Rectangle aAreaRect );
-
-static void NWPaintOneEditBox( SalX11Screen nScreen, GdkDrawable * gdkDrawable, GdkRectangle const *gdkRect,
- ControlType nType, tools::Rectangle aEditBoxRect,
- ControlState nState );
-
-static tools::Rectangle NWGetSpinButtonRect( SalX11Screen nScreen, ControlPart nPart, tools::Rectangle aAreaRect );
-
-static void NWPaintOneSpinButton( SalX11Screen nScreen, GdkPixmap * pixmap, ControlPart nPart, tools::Rectangle aAreaRect,
- ControlState nState );
-
-static tools::Rectangle NWGetComboBoxButtonRect( SalX11Screen nScreen, ControlPart nPart, tools::Rectangle aAreaRect );
-
-static tools::Rectangle NWGetListBoxButtonRect( SalX11Screen nScreen, ControlPart nPart, tools::Rectangle aAreaRect);
-
-static tools::Rectangle NWGetListBoxIndicatorRect( SalX11Screen nScreen, tools::Rectangle aAreaRect);
-
-static tools::Rectangle NWGetToolbarRect( SalX11Screen nScreen,
- ControlPart nPart,
- tools::Rectangle aAreaRect );
-
-static int getFrameWidth(GtkWidget const * widget);
-
-static tools::Rectangle NWGetScrollButtonRect( SalX11Screen nScreen, ControlPart nPart, tools::Rectangle aAreaRect );
-
-
-/************************************************************************
- * GDK implementation of X11Pixmap
- ************************************************************************/
-
-class GdkX11Pixmap : public X11Pixmap
-{
-public:
- GdkX11Pixmap( int nWidth, int nHeight, int nDepth );
- virtual ~GdkX11Pixmap() override;
-
- virtual int GetDepth() const override;
- virtual SalX11Screen GetScreen() const override;
- virtual Pixmap GetPixmap() const override;
- GdkPixmap* GetGdkPixmap() const;
- GdkDrawable* GetGdkDrawable() const;
-
-protected:
- GdkPixmap* mpGdkPixmap;
- int mnDepth;
-};
-
-GdkX11Pixmap::GdkX11Pixmap( int nWidth, int nHeight, int nDepth )
-: X11Pixmap( nWidth, nHeight )
-{
- mpGdkPixmap = gdk_pixmap_new( nullptr, nWidth, nHeight, nDepth );
- mnDepth = gdk_drawable_get_depth( GDK_DRAWABLE( mpGdkPixmap ) );
-
- GdkScreen *pScreen = gdk_drawable_get_screen( GDK_DRAWABLE( mpGdkPixmap ) );
- gdk_drawable_set_colormap( GDK_DRAWABLE( mpGdkPixmap ), gdk_screen_get_default_colormap( pScreen ) );
-}
-
-GdkX11Pixmap::~GdkX11Pixmap()
-{
- g_object_unref( mpGdkPixmap );
-}
-
-int GdkX11Pixmap::GetDepth() const
-{
- return mnDepth;
-}
-
-SalX11Screen GdkX11Pixmap::GetScreen() const
-{
- return SalX11Screen( gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(mpGdkPixmap) ) ) );
-}
-
-Pixmap GdkX11Pixmap::GetPixmap() const
-{
- return GDK_PIXMAP_XID( mpGdkPixmap );
-}
-
-GdkPixmap* GdkX11Pixmap::GetGdkPixmap() const
-{
- return mpGdkPixmap;
-}
-
-GdkDrawable* GdkX11Pixmap::GetGdkDrawable() const
-{
- return GDK_DRAWABLE( mpGdkPixmap );
-}
-
-
-/*********************************************************
- * PixmapCache
- *********************************************************/
-
-// as some native widget drawing operations are pretty slow
-// with certain themes (eg tabpages)
-// this cache can be used to cache the corresponding pixmap
-// see NWPaintGTKTabItem
-
-class NWPixmapCacheData
-{
-public:
- ControlType m_nType;
- ControlState m_nState;
- tools::Rectangle m_pixmapRect;
- std::unique_ptr<GdkX11Pixmap> m_pixmap;
- std::unique_ptr<GdkX11Pixmap> m_mask;
-
- NWPixmapCacheData() : m_nType(ControlType::Generic), m_nState(ControlState::NONE) {}
- void SetPixmap( std::unique_ptr<GdkX11Pixmap> pPixmap, std::unique_ptr<GdkX11Pixmap> pMask );
-};
-
-class NWPixmapCache
-{
- int m_size;
- int m_idx;
- int m_screen;
- std::unique_ptr<NWPixmapCacheData[]> pData;
-public:
- explicit NWPixmapCache( SalX11Screen nScreen );
- ~NWPixmapCache();
-
- void SetSize( int n)
- { m_idx = 0; m_size = n; pData.reset(new NWPixmapCacheData[m_size]); }
- int GetSize() const { return m_size; }
-
- bool Find( ControlType aType, ControlState aState, const tools::Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask );
- void Fill( ControlType aType, ControlState aState, const tools::Rectangle& r_pixmapRect, std::unique_ptr<GdkX11Pixmap> pPixmap, std::unique_ptr<GdkX11Pixmap> pMask );
-
- void ThemeChanged();
-};
-
-class NWPixmapCacheList
-{
-public:
- ::std::vector< NWPixmapCache* > mCaches;
-
- void AddCache( NWPixmapCache *pCache );
- void RemoveCache( NWPixmapCache *pCache );
- void ThemeChanged();
-};
-
-// --- implementation ---
-
-void NWPixmapCacheData::SetPixmap( std::unique_ptr<GdkX11Pixmap> pPixmap, std::unique_ptr<GdkX11Pixmap> pMask )
-{
- m_pixmap = std::move(pPixmap);
- m_mask = std::move(pMask);
-}
-
-NWPixmapCache::NWPixmapCache( SalX11Screen nScreen )
-{
- m_idx = 0;
- m_size = 0;
- m_screen = nScreen.getXScreen();
- pData = nullptr;
- if( gWidgetData[m_screen].gNWPixmapCacheList )
- gWidgetData[m_screen].gNWPixmapCacheList->AddCache(this);
-}
-NWPixmapCache::~NWPixmapCache()
-{
- if( gWidgetData[m_screen].gNWPixmapCacheList )
- gWidgetData[m_screen].gNWPixmapCacheList->RemoveCache(this);
-}
-void NWPixmapCache::ThemeChanged()
-{
- // throw away cached pixmaps
- for(int i=0; i<m_size; i++)
- pData[i].SetPixmap( nullptr, nullptr );
-}
-
-bool NWPixmapCache::Find( ControlType aType, ControlState aState, const tools::Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask )
-{
- aState &= ~ControlState::CACHING_ALLOWED; // mask clipping flag
- int i;
- for(i=0; i<m_size; i++)
- {
- if( pData[i].m_nType == aType &&
- pData[i].m_nState == aState &&
- pData[i].m_pixmapRect.GetWidth() == r_pixmapRect.GetWidth() &&
- pData[i].m_pixmapRect.GetHeight() == r_pixmapRect.GetHeight() &&
- pData[i].m_pixmap != nullptr )
- {
- *pPixmap = pData[i].m_pixmap.get();
- *pMask = pData[i].m_mask.get();
- return true;
- }
- }
- return false;
-}
-
-void NWPixmapCache::Fill( ControlType aType, ControlState aState, const tools::Rectangle& r_pixmapRect,
- std::unique_ptr<GdkX11Pixmap> pPixmap,
- std::unique_ptr<GdkX11Pixmap> pMask )
-{
- if( !(aState & ControlState::CACHING_ALLOWED) )
- return;
-
- aState &= ~ControlState::CACHING_ALLOWED; // mask clipping flag
- m_idx = (m_idx+1) % m_size; // just wrap
- pData[m_idx].m_nType = aType;
- pData[m_idx].m_nState = aState;
- pData[m_idx].m_pixmapRect = r_pixmapRect;
- pData[m_idx].SetPixmap( std::move(pPixmap), std::move(pMask) );
-}
-
-void NWPixmapCacheList::AddCache( NWPixmapCache* pCache )
-{
- mCaches.push_back( pCache );
-}
-void NWPixmapCacheList::RemoveCache( NWPixmapCache* pCache )
-{
- auto p = ::std::find( mCaches.begin(), mCaches.end(), pCache );
- if( p != mCaches.end() )
- mCaches.erase( p );
-}
-void NWPixmapCacheList::ThemeChanged( )
-{
- for (auto const& cache : mCaches)
- cache->ThemeChanged();
-}
-
-/*********************************************************
- * Make border manipulation easier
- *********************************************************/
-static void NW_gtk_border_set_from_border( GtkBorder& aDst, const GtkBorder * pSrc )
-{
- aDst.left = pSrc->left;
- aDst.top = pSrc->top;
- aDst.right = pSrc->right;
- aDst.bottom = pSrc->bottom;
-}
-
-/*********************************************************
- * Initialize GTK and local stuff
- *********************************************************/
-void GtkSalData::initNWF()
-{
- ImplSVData* pSVData = ImplGetSVData();
-
- // draw no border for popup menus (NWF draws its own)
- pSVData->maNWFData.mbFlatMenu = true;
-
- // draw separate buttons for toolbox dropdown items
- pSVData->maNWFData.mbToolboxDropDownSeparate = true;
-
- // draw toolbars in separate lines
- pSVData->maNWFData.mbDockingAreaSeparateTB = true;
-
- // open first menu on F10
- pSVData->maNWFData.mbOpenMenuOnF10 = true;
-
- // omit GetNativeControl while painting (see brdwin.cxx)
- pSVData->maNWFData.mbCanDrawWidgetAnySize = true;
-
- pSVData->maNWFData.mbDDListBoxNoTextArea = true;
-
- // use offscreen rendering when using OpenGL backend
- if( OpenGLHelper::isVCLOpenGLEnabled() )
- {
- GtkSalGraphics::bNeedPixmapPaint = true;
- GtkSalGraphics::bNeedTwoPasses = true;
- }
-
- int nScreens = GetGtkSalData()->GetGtkDisplay()->GetXScreenCount();
- gWidgetData = WidgetDataVector( nScreens );
- for( int i = 0; i < nScreens; i++ )
- gWidgetData[i].gNWPixmapCacheList = new NWPixmapCacheList;
-
- // small extra border around menu items
- NWEnsureGTKMenu( SalX11Screen( 0 ) );
- gint horizontal_padding = 1;
- gint vertical_padding = 1;
- gint separator_padding = 1;
- gtk_widget_style_get( gWidgetData[0].gMenuWidget,
- "horizontal-padding", &horizontal_padding,
- nullptr);
- gtk_widget_style_get( gWidgetData[0].gMenuWidget,
- "vertical-padding", &vertical_padding,
- nullptr);
- gtk_widget_style_get( gWidgetData[0].gMenuItemSeparatorMenuWidget,
- "horizontal-padding", &separator_padding,
- nullptr);
- gint xthickness = gWidgetData[0].gMenuWidget->style->xthickness;
- gint ythickness = gWidgetData[0].gMenuWidget->style->ythickness;
- pSVData->maNWFData.mnMenuFormatBorderX = xthickness + horizontal_padding;
- pSVData->maNWFData.mnMenuFormatBorderY = ythickness + vertical_padding;
- pSVData->maNWFData.mnMenuSeparatorBorderX = separator_padding;
-
- static const char* pEnv = getenv( "SAL_GTK_USE_PIXMAPPAINT" );
- if( pEnv && *pEnv )
- GtkSalGraphics::bNeedPixmapPaint = true;
-
- #if OSL_DEBUG_LEVEL > 1
- std::fprintf( stderr, "GtkPlugin: using %s NWF\n",
- GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" );
- #endif
-
- GtkSettings *gtks = gtk_settings_get_default ();
- gint val;
- g_object_get (gtks, "gtk-auto-mnemonics", &val, nullptr);
- if (val) pSVData->maNWFData.mbAutoAccel = true;
- else pSVData->maNWFData.mbAutoAccel = false;
- g_object_get (gtks, "gtk-enable-mnemonics", &val, nullptr);
- if (val) pSVData->maNWFData.mbEnableAccel = true;
- else pSVData->maNWFData.mbEnableAccel = false;
-}
-
-/*********************************************************
- * Release GTK and local stuff
- *********************************************************/
-void GtkSalData::deInitNWF()
-{
- for( size_t i = 0; i < gWidgetData.size(); i++ )
- {
- // free up global widgets
- // gtk_widget_destroy will in turn destroy the child hierarchy
- // so only destroy disjunct hierarchies
- if( gWidgetData[i].gCacheWindow )
- gtk_widget_destroy( gWidgetData[i].gCacheWindow );
- if( gWidgetData[i].gMenuWidget )
- g_object_unref (gWidgetData[i].gMenuWidget);
- if( gWidgetData[i].gTooltipPopup )
- gtk_widget_destroy( gWidgetData[i].gTooltipPopup );
- if( gWidgetData[i].gDialog )
- gtk_widget_destroy( gWidgetData[i].gDialog );
- delete gWidgetData[i].gCacheTabPages;
- gWidgetData[i].gCacheTabPages = nullptr;
- delete gWidgetData[i].gCacheTabItems;
- gWidgetData[i].gCacheTabItems = nullptr;
- delete gWidgetData[i].gNWPixmapCacheList;
- gWidgetData[i].gNWPixmapCacheList = nullptr;
- }
-}
-
-/**********************************************************
- * track clip region
- **********************************************************/
-void GtkSalGraphics::ResetClipRegion()
-{
- m_aClipRegion.SetNull();
- X11SalGraphics::ResetClipRegion();
-}
-
-bool GtkSalGraphics::setClipRegion( const vcl::Region& i_rClip )
-{
- m_aClipRegion = i_rClip;
- bool bRet = X11SalGraphics::setClipRegion( m_aClipRegion );
- if( m_aClipRegion.IsEmpty() )
- m_aClipRegion.SetNull();
- return bRet;
-}
-
-void GtkSalGraphics::copyBits( const SalTwoRect& rPosAry,
- SalGraphics* pSrcGraphics )
-{
- GtkSalFrame* pFrame = GetGtkFrame();
- ::Window aWin = None;
- if( pFrame && m_pWindow )
- {
- /* #i64117# some themes set the background pixmap VERY frequently */
- GdkWindow* pWin = GTK_WIDGET(m_pWindow)->window;
- if( pWin )
- {
- aWin = GDK_WINDOW_XWINDOW(pWin);
- if( aWin != None )
- XSetWindowBackgroundPixmap( GtkSalFrame::getDisplay()->GetDisplay(),
- aWin,
- None );
- }
- }
- X11SalGraphics::copyBits( rPosAry, pSrcGraphics );
-}
-
-bool GtkSalGraphics::isNativeControlSupported( ControlType nType, ControlPart nPart )
-{
- switch(nType)
- {
- case ControlType::Pushbutton:
- case ControlType::Radiobutton:
- case ControlType::Checkbox:
- case ControlType::Tooltip:
- case ControlType::Progress:
- case ControlType::ListNode:
- case ControlType::ListNet:
- if(nPart==ControlPart::Entire)
- return true;
- break;
-
- case ControlType::Scrollbar:
- if(nPart==ControlPart::DrawBackgroundHorz || nPart==ControlPart::DrawBackgroundVert ||
- nPart==ControlPart::Entire || nPart==ControlPart::HasThreeButtons)
- return true;
- break;
-
- case ControlType::Editbox:
- case ControlType::MultilineEditbox:
- case ControlType::Combobox:
- if(nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture)
- return true;
- break;
-
- case ControlType::Spinbox:
- if(nPart==ControlPart::Entire || nPart==ControlPart::AllButtons || nPart==ControlPart::HasBackgroundTexture)
- return true;
- break;
-
- case ControlType::SpinButtons:
- if(nPart==ControlPart::Entire || nPart==ControlPart::AllButtons)
- return true;
- break;
-
- case ControlType::Frame:
- case ControlType::WindowBackground:
- return true;
-
- case ControlType::TabItem:
- case ControlType::TabPane:
- case ControlType::TabBody:
- if(nPart==ControlPart::Entire || nPart==ControlPart::TabsDrawRtl)
- return true;
- break;
-
- case ControlType::Listbox:
- if(nPart==ControlPart::Entire || nPart==ControlPart::ListboxWindow || nPart==ControlPart::HasBackgroundTexture)
- return true;
- break;
-
- case ControlType::Toolbar:
- if( nPart==ControlPart::Entire
- || nPart==ControlPart::DrawBackgroundHorz
- || nPart==ControlPart::DrawBackgroundVert
- || nPart==ControlPart::ThumbHorz
- || nPart==ControlPart::ThumbVert
- || nPart==ControlPart::Button
- || nPart==ControlPart::SeparatorHorz
- || nPart==ControlPart::SeparatorVert
- )
- return true;
- break;
-
- case ControlType::Menubar:
- if(nPart==ControlPart::Entire || nPart==ControlPart::MenuItem)
- return true;
- break;
-
- case ControlType::MenuPopup:
- if (nPart==ControlPart::Entire
- || nPart==ControlPart::MenuItem
- || nPart==ControlPart::MenuItemCheckMark
- || nPart==ControlPart::MenuItemRadioMark
- || nPart==ControlPart::Separator
- || nPart==ControlPart::SubmenuArrow
- )
- return true;
- break;
-
- case ControlType::Slider:
- if(nPart == ControlPart::TrackHorzArea || nPart == ControlPart::TrackVertArea)
- return true;
- break;
-
- case ControlType::Fixedline:
- if(nPart == ControlPart::SeparatorVert || nPart == ControlPart::SeparatorHorz)
- return true;
- break;
-
- case ControlType::ListHeader:
- if(nPart == ControlPart::Button || nPart == ControlPart::Arrow)
- return true;
- break;
- default: break;
- }
-
- return false;
-}
-
-bool GtkSalGraphics::hitTestNativeControl( ControlType nType,
- ControlPart nPart,
- const tools::Rectangle& rControlRegion,
- const Point& aPos,
- bool& rIsInside )
-{
- if ( ( nType == ControlType::Scrollbar ) &&
- ( ( nPart == ControlPart::ButtonUp ) ||
- ( nPart == ControlPart::ButtonDown ) ||
- ( nPart == ControlPart::ButtonLeft ) ||
- ( nPart == ControlPart::ButtonRight ) ) )
- {
- NWEnsureGTKScrollbars( m_nXScreen );
-
- // Grab some button style attributes
- gboolean has_forward;
- gboolean has_forward2;
- gboolean has_backward;
- gboolean has_backward2;
-
- gtk_widget_style_get( gWidgetData[m_nXScreen].gScrollHorizWidget,
- "has-forward-stepper", &has_forward,
- "has-secondary-forward-stepper", &has_forward2,
- "has-backward-stepper", &has_backward,
- "has-secondary-backward-stepper", &has_backward2,
- nullptr );
- tools::Rectangle aForward;
- tools::Rectangle aBackward;
-
- rIsInside = false;
-
- ControlPart nCounterPart = ControlPart::NONE;
- if ( nPart == ControlPart::ButtonUp )
- nCounterPart = ControlPart::ButtonDown;
- else if ( nPart == ControlPart::ButtonDown )
- nCounterPart = ControlPart::ButtonUp;
- else if ( nPart == ControlPart::ButtonLeft )
- nCounterPart = ControlPart::ButtonRight;
- else if ( nPart == ControlPart::ButtonRight )
- nCounterPart = ControlPart::ButtonLeft;
-
- aBackward = NWGetScrollButtonRect( m_nXScreen, nPart, rControlRegion );
- aForward = NWGetScrollButtonRect( m_nXScreen, nCounterPart, rControlRegion );
-
- if ( has_backward && has_forward2 )
- {
- Size aSize( aBackward.GetSize() );
- if ( ( nPart == ControlPart::ButtonUp ) || ( nPart == ControlPart::ButtonDown ) )
- aSize.setHeight( aBackward.GetHeight() / 2 );
- else
- aSize.setWidth( aBackward.GetWidth() / 2 );
- aBackward.SetSize( aSize );
-
- if ( nPart == ControlPart::ButtonDown )
- aBackward.Move( 0, aBackward.GetHeight() / 2 );
- else if ( nPart == ControlPart::ButtonRight )
- aBackward.Move( aBackward.GetWidth() / 2, 0 );
- }
-
- if ( has_backward2 && has_forward )
- {
- Size aSize( aForward.GetSize() );
- if ( ( nPart == ControlPart::ButtonUp ) || ( nPart == ControlPart::ButtonDown ) )
- aSize.setHeight( aForward.GetHeight() / 2 );
- else
- aSize.setWidth( aForward.GetWidth() / 2 );
- aForward.SetSize( aSize );
-
- if ( nPart == ControlPart::ButtonDown )
- aForward.Move( 0, aForward.GetHeight() / 2 );
- else if ( nPart == ControlPart::ButtonRight )
- aForward.Move( aForward.GetWidth() / 2, 0 );
- }
-
- if ( ( nPart == ControlPart::ButtonUp ) || ( nPart == ControlPart::ButtonLeft ) )
- {
- if ( has_backward )
- rIsInside |= aBackward.IsInside( aPos );
- if ( has_backward2 )
- rIsInside |= aForward.IsInside( aPos );
- }
- else
- {
- if ( has_forward )
- rIsInside |= aBackward.IsInside( aPos );
- if ( has_forward2 )
- rIsInside |= aForward.IsInside( aPos );
- }
- return true;
- }
-
- if( isNativeControlSupported(nType, nPart) )
- {
- rIsInside = rControlRegion.IsInside( aPos );
- return true;
- }
- else
- {
- return false;
- }
-}
-
-bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
- const tools::Rectangle& rControlRegion, ControlState nState,
- const ImplControlValue& aValue, const OUString& /*rCaption*/)
-{
- // get a GC with current clipping region set
- GetFontGC();
-
- // theme changed ?
- if( GtkSalGraphics::bThemeChanged )
- {
- // invalidate caches
- for( size_t i = 0; i < gWidgetData.size(); i++ )
- if( gWidgetData[i].gNWPixmapCacheList )
- gWidgetData[i].gNWPixmapCacheList->ThemeChanged();
- GtkSalGraphics::bThemeChanged = false;
- }
-
- tools::Rectangle aCtrlRect( rControlRegion );
- vcl::Region aClipRegion( m_aClipRegion );
- if( aClipRegion.IsNull() )
- aClipRegion = aCtrlRect;
-
- // make pixmap a little larger since some themes draw decoration
- // outside the rectangle, see e.g. checkbox
- tools::Rectangle aPixmapRect(Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
- Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
-
- ControlCacheKey aControlCacheKey(nType, nPart, nState, aPixmapRect.GetSize());
- if (aControlCacheKey.canCacheControl()
- && TryRenderCachedNativeControl(aControlCacheKey, aPixmapRect.Left(), aPixmapRect.Top()))
- {
- return true;
- }
-
- std::vector< tools::Rectangle > aClip;
- int nPasses = 0;
- GdkDrawable* gdkDrawable[2];
- std::unique_ptr<GdkX11Pixmap> xPixmap;
- std::unique_ptr<GdkX11Pixmap> xMask;
-
- if ((bNeedPixmapPaint || (nState & ControlState::DOUBLEBUFFERING))
- && nType != ControlType::Scrollbar
- && nType != ControlType::Spinbox
- && nType != ControlType::TabItem
- && nType != ControlType::TabPane
- && nType != ControlType::Progress
- && ! (nType == ControlType::Toolbar && (nPart == ControlPart::ThumbHorz || nPart == ControlPart::ThumbVert) )
- )
- {
- if( bNeedTwoPasses )
- {
- xPixmap = NWGetPixmapFromScreen( aPixmapRect, BG_WHITE );
- xMask = NWGetPixmapFromScreen( aPixmapRect, BG_BLACK );
- if( !xPixmap || !xMask )
- return false;
- nPasses = 2;
- gdkDrawable[0] = xPixmap->GetGdkDrawable();
- gdkDrawable[1] = xMask->GetGdkDrawable();
- }
- else
- {
- xPixmap = NWGetPixmapFromScreen( aPixmapRect, BG_FILL );
- if( !xPixmap )
- return false;
- nPasses = 1;
- gdkDrawable[0] = xPixmap->GetGdkDrawable();
- }
-
- aCtrlRect = tools::Rectangle( Point(1,1), aCtrlRect.GetSize() );
- aClip.push_back( aCtrlRect );
- }
- else
- {
- nPasses = 1;
- gdkDrawable[0] = GDK_DRAWABLE( GetGdkWindow() );
- RectangleVector aRectangles;
- aClipRegion.GetRegionRectangles(aRectangles);
-
- for (auto const& rectangle : aRectangles)
- {
- tools::Rectangle aPaintRect = aCtrlRect.GetIntersection(rectangle);
- if( aPaintRect.IsEmpty() )
- continue;
- aClip.push_back( aPaintRect );
- }
- }
-
- bool returnVal = false;
-
- for( int i = 0; i < nPasses; ++i )
- {
- assert(gdkDrawable[i] && "rhbz#1050162");
- if( gdkDrawable[i] == nullptr )
- return false;
-
- returnVal = DoDrawNativeControl(gdkDrawable[i], nType, nPart, aCtrlRect, aClip,
- nState, aValue, aControlCacheKey);
- if( !returnVal )
- break;
- }
-
- if( xPixmap )
- returnVal = returnVal && RenderAndCacheNativeControl(xPixmap.get(), xMask.get(),
- aPixmapRect.Left(), aPixmapRect.Top(),
- aControlCacheKey);
-
- return returnVal;
-}
-
-
-bool GtkSalGraphics::DoDrawNativeControl(
- GdkDrawable* pDrawable,
- ControlType nType,
- ControlPart nPart,
- const tools::Rectangle& aCtrlRect,
- const std::vector< tools::Rectangle >& aClip,
- ControlState nState,
- const ImplControlValue& aValue,
- ControlCacheKey& rControlCacheKey)
-{
- if ( (nType==ControlType::Pushbutton) && (nPart==ControlPart::Entire) )
- {
- return NWPaintGTKButton( pDrawable, aCtrlRect, aClip, nState );
- }
- else if ( (nType==ControlType::Radiobutton) && (nPart==ControlPart::Entire) )
- {
- return NWPaintGTKRadio( pDrawable, aCtrlRect, aClip, nState, aValue );
- }
- else if ( (nType==ControlType::Checkbox) && (nPart==ControlPart::Entire) )
- {
- return NWPaintGTKCheck( pDrawable, aCtrlRect, aClip, nState, aValue );
- }
- else if ( (nType==ControlType::Scrollbar) && ((nPart==ControlPart::DrawBackgroundHorz) || (nPart==ControlPart::DrawBackgroundVert)) )
- {
- return NWPaintGTKScrollbar( nPart, aCtrlRect, nState, aValue );
- }
- else if ( ((nType==ControlType::Editbox) && ((nPart==ControlPart::Entire) || (nPart==ControlPart::HasBackgroundTexture)) )
- || ((nType==ControlType::Spinbox) && (nPart==ControlPart::HasBackgroundTexture))
- || ((nType==ControlType::Combobox) && (nPart==ControlPart::HasBackgroundTexture))
- || ((nType==ControlType::Listbox) && (nPart==ControlPart::HasBackgroundTexture)) )
- {
- return NWPaintGTKEditBox( pDrawable, nType, aCtrlRect, aClip, nState );
- }
- else if ( (nType==ControlType::MultilineEditbox) && ((nPart==ControlPart::Entire) || (nPart==ControlPart::HasBackgroundTexture)) )
- {
- return NWPaintGTKEditBox( pDrawable, nType, aCtrlRect, aClip, nState );
- }
- else if ( ((nType==ControlType::Spinbox) || (nType==ControlType::SpinButtons))
- && ((nPart==ControlPart::Entire) || (nPart==ControlPart::AllButtons)) )
- {
- return NWPaintGTKSpinBox(nType, nPart, aCtrlRect, nState, aValue, rControlCacheKey);
- }
- else if ( (nType == ControlType::Combobox) &&
- ( (nPart==ControlPart::Entire)
- ||(nPart==ControlPart::ButtonDown)
- ) )
- {
- return NWPaintGTKComboBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState );
- }
- else if ( (nType==ControlType::TabItem) || (nType==ControlType::TabPane) || (nType==ControlType::TabBody) )
- {
- if ( nType == ControlType::TabBody )
- return true;
- else
- return NWPaintGTKTabItem( nType, aCtrlRect, nState, aValue);
- }
- else if ( (nType==ControlType::Listbox) && ((nPart==ControlPart::Entire) || (nPart==ControlPart::ListboxWindow)) )
- {
- return NWPaintGTKListBox( pDrawable, nPart, aCtrlRect, aClip, nState );
- }
- else if ( nType== ControlType::Toolbar )
- {
- return NWPaintGTKToolbar( pDrawable, nPart, aCtrlRect, aClip, nState, aValue );
- }
- else if ( nType== ControlType::Menubar )
- {
- return NWPaintGTKMenubar( pDrawable, nPart, aCtrlRect, aClip, nState );
- }
- else if( (nType == ControlType::MenuPopup)
- && ( (nPart == ControlPart::Entire)
- || (nPart == ControlPart::MenuItem)
- || (nPart == ControlPart::MenuItemCheckMark)
- || (nPart == ControlPart::MenuItemRadioMark)
- || (nPart == ControlPart::Separator)
- || (nPart == ControlPart::SubmenuArrow)
- )
- )
- {
- return NWPaintGTKPopupMenu( pDrawable, nPart, aCtrlRect, aClip, nState );
- }
- else if( (nType == ControlType::Tooltip) && (nPart == ControlPart::Entire) )
- {
- return NWPaintGTKTooltip( pDrawable, aCtrlRect, aClip );
- }
- else if( (nType == ControlType::Progress) && (nPart == ControlPart::Entire) )
- {
- return NWPaintGTKProgress( aCtrlRect, aValue );
- }
- else if( (nType == ControlType::ListNode) && (nPart == ControlPart::Entire) )
- {
- return NWPaintGTKListNode( pDrawable, aCtrlRect, nState, aValue );
- }
- else if( (nType == ControlType::ListNet) && (nPart == ControlPart::Entire) )
- {
- // don't actually draw anything; gtk treeviews do not draw lines
- return TRUE;
- }
- else if( nType == ControlType::Slider )
- {
- return NWPaintGTKSlider(pDrawable, nPart, aCtrlRect, nState, aValue);
- }
- else if( nType == ControlType::WindowBackground )
- {
- return NWPaintGTKWindowBackground( pDrawable, aCtrlRect, aClip );
- }
- else if( nType == ControlType::Fixedline )
- {
- return NWPaintGTKFixedLine( pDrawable, nPart, aCtrlRect );
- }
- else if(nType==ControlType::Frame)
- {
- return NWPaintGTKFrame( pDrawable, aCtrlRect, aClip, aValue);
- }
- else if(nType==ControlType::ListHeader)
- {
- if(nPart == ControlPart::Button)
- return NWPaintGTKListHeader( pDrawable, aCtrlRect, aClip, nState );
- else if(nPart == ControlPart::Arrow)
- return NWPaintGTKArrow( pDrawable, aCtrlRect, aClip, nState, aValue );
- }
-
- return false;
-}
-
-bool GtkSalGraphics::getNativeControlRegion( ControlType nType,
- ControlPart nPart,
- const tools::Rectangle& rControlRegion,
- ControlState nState,
- const ImplControlValue& aValue,
- const OUString& /*rCaption*/,
- tools::Rectangle &rNativeBoundingRegion,
- tools::Rectangle &rNativeContentRegion )
-{
- bool returnVal = false;
-
- if ( (nType==ControlType::Pushbutton) && (nPart==ControlPart::Entire)
- && (rControlRegion.GetWidth() > 16)
- && (rControlRegion.GetHeight() > 16) )
- {
- rNativeBoundingRegion = NWGetButtonArea( m_nXScreen, rControlRegion, nState );
- rNativeContentRegion = rControlRegion;
- returnVal = true;
- }
- if (nType == ControlType::TabItem && nPart == ControlPart::Entire)
- {
- rNativeBoundingRegion = NWGetTabItemRect(m_nXScreen, rControlRegion);
- rNativeContentRegion = rNativeBoundingRegion;
- returnVal = true;
- }
- if ( (nType==ControlType::Combobox) && ((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
- {
- rNativeBoundingRegion = NWGetComboBoxButtonRect( m_nXScreen, nPart, rControlRegion);
- rNativeContentRegion = rNativeBoundingRegion;
-
- returnVal = true;
- }
- if ( (nType==ControlType::Spinbox) && ((nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
- {
-
- rNativeBoundingRegion = NWGetSpinButtonRect( m_nXScreen, nPart, rControlRegion );
- rNativeContentRegion = rNativeBoundingRegion;
-
- returnVal = true;
- }
- if ( (nType==ControlType::Listbox) && ((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
- {
- rNativeBoundingRegion = NWGetListBoxButtonRect( m_nXScreen, nPart, rControlRegion);
- rNativeContentRegion = rNativeBoundingRegion;
-
- returnVal = true;
- }
- if ( (nType==ControlType::Toolbar) &&
- ((nPart==ControlPart::DrawBackgroundHorz) ||
- (nPart==ControlPart::DrawBackgroundVert) ||
- (nPart==ControlPart::ThumbHorz) ||
- (nPart==ControlPart::ThumbVert) ||
- (nPart==ControlPart::Button)
- ))
- {
- rNativeBoundingRegion = NWGetToolbarRect( m_nXScreen, nPart, rControlRegion );
- rNativeContentRegion = rNativeBoundingRegion;
- returnVal = true;
- }
- if ( (nType==ControlType::Scrollbar) && ((nPart==ControlPart::ButtonLeft) || (nPart==ControlPart::ButtonRight) ||
- (nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) ) )
- {
- rNativeBoundingRegion = NWGetScrollButtonRect( m_nXScreen, nPart, rControlRegion );
- rNativeContentRegion = rNativeBoundingRegion;
-
- //See fdo#33523, possibly makes sense to do this test for all return values
- if (!rNativeContentRegion.GetWidth())
- rNativeContentRegion.SetRight( rNativeContentRegion.Left() + 1 );
- if (!rNativeContentRegion.GetHeight())
- rNativeContentRegion.SetBottom( rNativeContentRegion.Top() + 1 );
- returnVal = true;
- }
- if( (nType == ControlType::Menubar) && (nPart == ControlPart::Entire) )
- {
- NWEnsureGTKMenubar( m_nXScreen );
- GtkRequisition aReq;
- gtk_widget_size_request( gWidgetData[m_nXScreen].gMenubarWidget, &aReq );
- rNativeBoundingRegion = tools::Rectangle( rControlRegion.TopLeft(),
- Size( rControlRegion.GetWidth(), aReq.height+1 ) );
- rNativeContentRegion = rNativeBoundingRegion;
- returnVal = true;
- }
- if( nType == ControlType::MenuPopup )
- {
- if( (nPart == ControlPart::MenuItemCheckMark) ||
- (nPart == ControlPart::MenuItemRadioMark) )
- {
- NWEnsureGTKMenu( m_nXScreen );
-
- gint indicator_size = 0;
- GtkWidget* pWidget = (nPart == ControlPart::MenuItemCheckMark) ?
- gWidgetData[m_nXScreen].gMenuItemCheckMenuWidget : gWidgetData[m_nXScreen].gMenuItemRadioMenuWidget;
- gtk_widget_style_get( pWidget,
- "indicator_size", &indicator_size,
- nullptr );
- rNativeBoundingRegion = rControlRegion;
- tools::Rectangle aIndicatorRect( Point( 0,
- (rControlRegion.GetHeight()-indicator_size)/2),
- Size( indicator_size, indicator_size ) );
- rNativeContentRegion = aIndicatorRect;
- returnVal = true;
- }
- else if( nPart == ControlPart::SubmenuArrow )
- {
- GtkWidget* widget = gWidgetData[m_nXScreen].gMenuItemMenuWidget;
- GtkWidget* child;
- PangoContext *context;
- PangoFontMetrics *metrics;
- gint arrow_size;
- gint arrow_extent;
- guint horizontal_padding;
- gfloat arrow_scaling = 0.4; // Default for early GTK versions
-
- gtk_widget_style_get( widget,
- "horizontal-padding", &horizontal_padding,
- nullptr );
-
- // Use arrow-scaling property if available (2.15+), avoid warning otherwise
- if ( gtk_widget_class_find_style_property( GTK_WIDGET_GET_CLASS( widget ),
- "arrow-scaling" ) )
- {
- gtk_widget_style_get( widget,
- "arrow-scaling", &arrow_scaling,
- nullptr );
- }
-
- child = GTK_BIN( widget )->child;
-
- context = gtk_widget_get_pango_context( child );
- metrics = pango_context_get_metrics( context,
- child->style->font_desc,
- pango_context_get_language( context ) );
-
- arrow_size = PANGO_PIXELS( pango_font_metrics_get_ascent( metrics ) +
- pango_font_metrics_get_descent( metrics ) );
-
- pango_font_metrics_unref( metrics );
-
- arrow_extent = static_cast<gint>(arrow_size * arrow_scaling);
-
- rNativeContentRegion = tools::Rectangle( Point( 0, 0 ),
- Size( arrow_extent, arrow_extent ));
- rNativeBoundingRegion = tools::Rectangle( Point( 0, 0 ),
- Size( arrow_extent + horizontal_padding, arrow_extent ));
- returnVal = true;
- }
- }
- if( nType == ControlType::Radiobutton || nType == ControlType::Checkbox )
- {
- NWEnsureGTKRadio( m_nXScreen );
- NWEnsureGTKCheck( m_nXScreen );
- GtkWidget* widget = (nType == ControlType::Radiobutton) ? gWidgetData[m_nXScreen].gRadioWidget : gWidgetData[m_nXScreen].gCheckWidget;
- gint indicator_size, indicator_spacing, focusPad, focusWidth;
- gtk_widget_style_get( widget,
- "indicator_size", &indicator_size,
- "indicator_spacing", &indicator_spacing,
- "focus-line-width", &focusWidth,
- "focus-padding", &focusPad,
- nullptr);
- indicator_size += 2*indicator_spacing + 2*(focusWidth + focusWidth);
- rNativeBoundingRegion = rControlRegion;
- tools::Rectangle aIndicatorRect( Point( 0,
- (rControlRegion.GetHeight()-indicator_size)/2),
- Size( indicator_size, indicator_size ) );
- rNativeContentRegion = aIndicatorRect;
- returnVal = true;
- }
- if( (nType == ControlType::Editbox || nType == ControlType::Spinbox || nType == ControlType::Combobox) && nPart == ControlPart::Entire )
- {
- NWEnsureGTKEditBox( m_nXScreen );
- GtkWidget* widget = gWidgetData[m_nXScreen].gEditBoxWidget;
- GtkRequisition aReq;
- gtk_widget_size_request( widget, &aReq );
- tools::Rectangle aEditRect = rControlRegion;
- long nHeight = std::max<long>(aEditRect.GetHeight(), aReq.height);
- aEditRect = tools::Rectangle( aEditRect.TopLeft(),
- Size( aEditRect.GetWidth(), nHeight ) );
- rNativeBoundingRegion = aEditRect;
- rNativeContentRegion = rNativeBoundingRegion;
- returnVal = true;
- }
- if( (nType == ControlType::Slider) && (nPart == ControlPart::ThumbHorz || nPart == ControlPart::ThumbVert) )
- {
- NWEnsureGTKSlider( m_nXScreen );
- GtkWidget* widget = (nPart == ControlPart::ThumbHorz) ? gWidgetData[m_nXScreen].gHScale : gWidgetData[m_nXScreen].gVScale;
- gint slider_length = 10;
- gint slider_width = 10;
- gtk_widget_style_get( widget,
- "slider-width", &slider_width,
- "slider-length", &slider_length,
- nullptr);
- tools::Rectangle aRect( rControlRegion );
- if( nPart == ControlPart::ThumbHorz )
- {
- aRect.SetRight( aRect.Left() + slider_length - 1 );
- aRect.SetBottom( aRect.Top() + slider_width - 1 );
- }
- else
- {
- aRect.SetBottom( aRect.Top() + slider_length - 1 );
- aRect.SetRight( aRect.Left() + slider_width - 1 );
- }
- rNativeBoundingRegion = rNativeContentRegion = aRect;
- returnVal = true;
- }
- if( nType == ControlType::Frame && nPart == ControlPart::Border )
- {
- int frameWidth = getFrameWidth(gWidgetData[m_nXScreen].gFrame);
- rNativeBoundingRegion = rControlRegion;
- DrawFrameFlags nStyle = static_cast<DrawFrameFlags>(aValue.getNumericVal() & 0xfff0);
- int x1=rControlRegion.Left();
- int y1=rControlRegion.Top();
- int x2=rControlRegion.Right();
- int y2=rControlRegion.Bottom();
-
- if( nStyle & DrawFrameFlags::NoDraw )
- {
- rNativeContentRegion = tools::Rectangle(x1+frameWidth,
- y1+frameWidth,
- x2-frameWidth,
- y2-frameWidth);
- }
- else
- rNativeContentRegion = rControlRegion;
- returnVal=true;
- }
-
- return returnVal;
-}
-
-/************************************************************************
- * Individual control drawing functions
- ************************************************************************/
-
-// macros to call before and after the rendering code for a widget
-// it takes care of creating the needed pixmaps
-#define BEGIN_PIXMAP_RENDER(aRect, gdkPixmap) \
- std::unique_ptr<GdkX11Pixmap> _pixmap, _mask; \
- int _nPasses = 0; \
- if( bNeedTwoPasses ) \
- { \
- _nPasses = 2; \
- _pixmap = NWGetPixmapFromScreen( aRect, BG_WHITE ); \
- _mask = NWGetPixmapFromScreen( aRect, BG_BLACK ); \
- } \
- else \
- { \
- _nPasses = 1; \
- _pixmap = NWGetPixmapFromScreen( aRect, BG_FILL ); \
- } \
- if( !_pixmap || ( bNeedTwoPasses && !_mask ) ) \
- return false; \
- for( int i = 0; i < _nPasses; ++i ) \
- { \
- GdkPixmap* gdkPixmap = (i == 0) ? _pixmap->GetGdkPixmap() \
- : _mask->GetGdkPixmap();
-
-#define END_PIXMAP_RENDER(aRect) \
- } \
- if( !NWRenderPixmapToScreen( _pixmap.get(), _mask.get(), aRect ) ) \
- return false;
-
-#define END_PIXMAP_RENDER_WITH_CONTROL_KEY(aRect, aControlKey) \
- } \
- if( !RenderAndCacheNativeControl( _pixmap.get(), _mask.get(), aRect.Left(), aRect.Top(), aControlKey ) ) \
- return false;
-
-// same as above but with pixmaps that should be kept for caching
-#define BEGIN_CACHE_PIXMAP_RENDER(aRect, pixmap, mask, gdkPixmap) \
- int _nPasses = 0; \
- if( bNeedTwoPasses ) \
- { \
- _nPasses = 2; \
- pixmap = NWGetPixmapFromScreen( aRect, BG_WHITE ).release(); \
- mask = NWGetPixmapFromScreen( aRect, BG_BLACK ).release(); \
- } \
- else \
- { \
- _nPasses = 1; \
- pixmap = NWGetPixmapFromScreen( aRect, BG_FILL ).release(); \
- mask = nullptr; \
- } \
- if( !pixmap || ( bNeedTwoPasses && !mask ) ) \
- return false; \
- for( int i = 0; i < _nPasses; ++i ) \
- { \
- GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() \
- : mask->GetGdkPixmap();
-
-#define END_CACHE_PIXMAP_RENDER(aRect, pixmap, mask) \
- } \
- if( !NWRenderPixmapToScreen( pixmap, mask, aRect ) ) \
- return false;
-
-bool GtkSalGraphics::NWPaintGTKArrow(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState, const ImplControlValue& aValue)
-{
- GtkArrowType arrowType(aValue.getNumericVal()&1?GTK_ARROW_DOWN:GTK_ARROW_UP);
- GtkStateType stateType(nState&ControlState::PRESSED?GTK_STATE_ACTIVE:GTK_STATE_NORMAL);
-
- GdkRectangle clipRect;
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- gtk_paint_arrow(m_pWindow->style,gdkDrawable,stateType,GTK_SHADOW_NONE,&clipRect,
- m_pWindow,"arrow",arrowType,true,
- rControlRectangle.Left(),
- rControlRectangle.Top(),
- rControlRectangle.GetWidth(),
- rControlRectangle.GetHeight());
- }
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKListHeader(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- NWEnsureGTKTreeView( m_nXScreen );
- GtkWidget* &treeview(gWidgetData[m_nXScreen].gTreeView);
- GtkTreeViewColumn* column=gtk_tree_view_get_column(GTK_TREE_VIEW(treeview),0);
- GtkWidget* button=gtk_tree_view_column_get_widget(column);
- while(button && !GTK_IS_BUTTON(button))
- button=gtk_widget_get_parent(button);
- if(!button)
- // Shouldn't ever happen
- return false;
- gtk_widget_realize(button);
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
- NWSetWidgetState( button, nState, stateType );
-
- GdkRectangle clipRect;
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- gtk_paint_box(button->style,gdkDrawable,stateType,shadowType,&clipRect,
- button,"button",
- rControlRectangle.Left()-1,
- rControlRectangle.Top(),
- rControlRectangle.GetWidth()+1,
- rControlRectangle.GetHeight());
- }
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKFixedLine(
- GdkDrawable* gdkDrawable,
- ControlPart nPart,
- const tools::Rectangle& rControlRectangle )
-{
- if(nPart == ControlPart::SeparatorHorz)
- gtk_paint_hline(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,nullptr,m_pWindow,"hseparator",rControlRectangle.Left(),rControlRectangle.Right(),rControlRectangle.Top());
- else
- gtk_paint_vline(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,nullptr,m_pWindow,"vseparator",rControlRectangle.Top(),rControlRectangle.Bottom(),rControlRectangle.Left());
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKFrame(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- const ImplControlValue& aValue )
-{
- GdkRectangle clipRect;
- int frameWidth=getFrameWidth(gWidgetData[m_nXScreen].gFrame);
- GtkShadowType shadowType=GTK_SHADOW_IN;
- DrawFrameStyle nStyle = static_cast<DrawFrameStyle>(aValue.getNumericVal() & 0x0f);
- if( nStyle == DrawFrameStyle::In )
- shadowType=GTK_SHADOW_OUT;
- if( nStyle == DrawFrameStyle::Out )
- shadowType=GTK_SHADOW_IN;
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- // Draw background first
-
- // Top
- gtk_paint_flat_box(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,GTK_SHADOW_OUT,&clipRect,
- m_pWindow,"base",
- rControlRectangle.Left(),
- rControlRectangle.Top(),
- rControlRectangle.GetWidth(),
- frameWidth);
- // Bottom
- gtk_paint_flat_box(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,GTK_SHADOW_OUT,&clipRect,
- m_pWindow,"base",
- rControlRectangle.Left(),
- rControlRectangle.Top()+rControlRectangle.GetHeight()-frameWidth,
- rControlRectangle.GetWidth(),
- frameWidth);
- // Left
- gtk_paint_flat_box(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,GTK_SHADOW_OUT,&clipRect,
- m_pWindow,"base",
- rControlRectangle.Left(),
- rControlRectangle.Top(),
- 2*frameWidth,
- rControlRectangle.GetHeight());
- // Right
- gtk_paint_flat_box(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,GTK_SHADOW_OUT,&clipRect,
- m_pWindow,"base",
- rControlRectangle.Left()+rControlRectangle.GetWidth()-frameWidth,
- rControlRectangle.Top(),
- 2*frameWidth,
- rControlRectangle.GetHeight());
-
- // Now render the frame
- gtk_paint_shadow(gWidgetData[m_nXScreen].gFrame->style,gdkDrawable,GTK_STATE_NORMAL,shadowType,&clipRect,
- gWidgetData[m_nXScreen].gFrame,"base",
- rControlRectangle.Left(),
- rControlRectangle.Top(),
- rControlRectangle.GetWidth(),
- rControlRectangle.GetHeight());
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKWindowBackground(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList )
-{
- GdkRectangle clipRect;
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- gtk_paint_flat_box(m_pWindow->style,gdkDrawable,GTK_STATE_NORMAL,GTK_SHADOW_NONE,&clipRect,
- m_pWindow,"base",
- rControlRectangle.Left(),
- rControlRectangle.Top(),
- rControlRectangle.GetWidth(),
- rControlRectangle.GetHeight());
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKButtonReal(
- GtkWidget* button,
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- gboolean interiorFocus;
- gint focusWidth;
- gint focusPad;
- bool bDrawFocus = true;
- gint x, y, w, h;
- GtkBorder aDefBorder;
- GtkBorder* pBorder;
- GdkRectangle clipRect;
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKToolbar( m_nXScreen );
-
- // Flat toolbutton has a bit bigger variety of states than normal buttons, so handle it differently
- if(GTK_IS_TOGGLE_BUTTON(button))
- {
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
- shadowType=GTK_SHADOW_IN;
- else
- shadowType=GTK_SHADOW_OUT;
-
- if(nState & ControlState::ROLLOVER)
- stateType=GTK_STATE_PRELIGHT;
- else
- stateType=GTK_STATE_NORMAL;
-
- if(nState & ControlState::PRESSED)
- {
- stateType=GTK_STATE_ACTIVE;
- shadowType=GTK_SHADOW_IN;
- }
- }
- else
- {
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gBtnWidget, nState, stateType );
- }
-
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- gint internal_padding = 0;
- if(GTK_IS_TOOL_ITEM(button))
- {
- gtk_widget_style_get (GTK_WIDGET (gWidgetData[m_nXScreen].gToolbarWidget),
- "internal-padding", &internal_padding,
- nullptr);
- x += internal_padding/2;
- w -= internal_padding;
- stateType = GTK_STATE_PRELIGHT;
- }
-
- // Grab some button style attributes
- gtk_widget_style_get( gWidgetData[m_nXScreen].gBtnWidget, "focus-line-width", &focusWidth,
- "focus-padding", &focusPad,
- "interior_focus", &interiorFocus,
- nullptr );
- gtk_widget_style_get( gWidgetData[m_nXScreen].gBtnWidget,
- "default_border", &pBorder,
- nullptr );
-
- // Make sure the border values exist, otherwise use some defaults
- if ( pBorder )
- {
- NW_gtk_border_set_from_border( aDefBorder, pBorder );
- gtk_border_free( pBorder );
- }
- else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder );
-
- // If the button is too small, don't ever draw focus or grab more space
- if ( (w < 16) || (h < 16) )
- bDrawFocus = false;
-
- gint xi = x, yi = y, wi = w, hi = h;
- if ( (nState & ControlState::DEFAULT) && bDrawFocus )
- {
- xi += aDefBorder.left;
- yi += aDefBorder.top;
- wi -= aDefBorder.left + aDefBorder.right;
- hi -= aDefBorder.top + aDefBorder.bottom;
- }
-
- if ( !interiorFocus && bDrawFocus )
- {
- xi += focusWidth + focusPad;
- yi += focusWidth + focusPad;
- wi -= 2 * (focusWidth + focusPad);
- hi -= 2 * (focusWidth + focusPad);
- }
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- // Buttons must paint opaque since some themes have alpha-channel enabled buttons
- if(button == gWidgetData[m_nXScreen].gToolbarButtonWidget)
- {
- gtk_paint_box( gWidgetData[m_nXScreen].gToolbarWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- &clipRect, gWidgetData[m_nXScreen].gToolbarWidget, "toolbar", x, y, w, h );
- }
- else
- {
- gtk_paint_box( m_pWindow->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- &clipRect, m_pWindow, "base", x, y, w, h );
- }
-
- if ( GTK_IS_BUTTON(button) )
- {
- if ( nState & ControlState::DEFAULT )
- gtk_paint_box( button->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
- &clipRect, button, "buttondefault", x, y, w, h );
-
- /* don't draw "button", because it can be a tool_button, and
- * it causes some weird things, so, the default button is
- * just fine */
- gtk_paint_box( button->style, gdkDrawable, stateType, shadowType,
- &clipRect, button, "button", xi, yi, wi, hi );
- }
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKButton(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState)
-{
- return NWPaintGTKButtonReal(
- gWidgetData[m_nXScreen].gBtnWidget,
- gdkDrawable,
- rControlRectangle,
- rClipList,
- nState );
-}
-
-static tools::Rectangle NWGetButtonArea( SalX11Screen nScreen,
- tools::Rectangle aAreaRect, ControlState nState )
-{
- gboolean interiorFocus;
- gint focusWidth;
- gint focusPad;
- GtkBorder aDefBorder;
- GtkBorder * pBorder;
- bool bDrawFocus = true;
- tools::Rectangle aRect;
- gint x, y, w, h;
-
- NWEnsureGTKButton( nScreen );
- gtk_widget_style_get( gWidgetData[nScreen].gBtnWidget,
- "focus-line-width", &focusWidth,
- "focus-padding", &focusPad,
- "interior_focus", &interiorFocus,
- "default_border", &pBorder,
- nullptr );
-
- // Make sure the border values exist, otherwise use some defaults
- if ( pBorder )
- {
- NW_gtk_border_set_from_border( aDefBorder, pBorder );
- gtk_border_free( pBorder );
- }
- else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder );
-
- x = aAreaRect.Left();
- y = aAreaRect.Top();
- w = aAreaRect.GetWidth();
- h = aAreaRect.GetHeight();
-
- // If the button is too small, don't ever draw focus or grab more space
- if ( (w < 16) || (h < 16) )
- bDrawFocus = false;
-
- if ( (nState & ControlState::DEFAULT) && bDrawFocus )
- {
- x -= aDefBorder.left;
- y -= aDefBorder.top;
- w += aDefBorder.left + aDefBorder.right;
- h += aDefBorder.top + aDefBorder.bottom;
- }
-
- aRect = tools::Rectangle( Point( x, y ), Size( w, h ) );
-
- return aRect;
-}
-
-static tools::Rectangle NWGetTabItemRect( SalX11Screen nScreen, tools::Rectangle aAreaRect )
-{
- NWEnsureGTKNotebook( nScreen );
-
- gint x, y, w, h;
-
- x = aAreaRect.Left();
- y = aAreaRect.Top();
- w = aAreaRect.GetWidth();
- h = aAreaRect.GetHeight();
-
- gint xthickness = gWidgetData[nScreen].gNotebookWidget->style->xthickness;
- gint ythickness = gWidgetData[nScreen].gNotebookWidget->style->ythickness;
-
- x -= xthickness;
- y -= ythickness;
- w += xthickness*2;
- h += ythickness*2;
-
- return tools::Rectangle( Point( x, y ), Size( w, h ) );
-}
-
-bool GtkSalGraphics::NWPaintGTKRadio( GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState,
- const ImplControlValue& aValue )
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- bool isChecked = (aValue.getTristateVal()==ButtonValue::On);
- gint x, y;
- GdkRectangle clipRect;
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKRadio( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- gint indicator_size;
- gtk_widget_style_get( gWidgetData[m_nXScreen].gRadioWidget, "indicator_size", &indicator_size, nullptr);
-
- x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2;
- y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2;
-
- // Set the shadow based on if checked or not so we get a freakin checkmark.
- shadowType = isChecked ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
- NWSetWidgetState( gWidgetData[m_nXScreen].gRadioWidget, nState, stateType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gRadioWidgetSibling, nState, stateType );
-
- // GTK enforces radio groups, so that if we don't have 2 buttons in the group,
- // the single button will always be active. So we have to have 2 buttons.
-
- // #i59666# set the members directly where we should use
- // gtk_toggle_button_set_active. reason: there are animated themes
- // which are in active state only after a while leading to painting
- // intermediate states between active/inactive. Let's hope that
- // GtkToggleButtone stays binary compatible.
- if (!isChecked)
- GTK_TOGGLE_BUTTON(gWidgetData[m_nXScreen].gRadioWidgetSibling)->active = true;
- GTK_TOGGLE_BUTTON(gWidgetData[m_nXScreen].gRadioWidget)->active = isChecked;
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- gtk_paint_option( gWidgetData[m_nXScreen].gRadioWidget->style, gdkDrawable, stateType, shadowType,
- &clipRect, gWidgetData[m_nXScreen].gRadioWidget, "radiobutton",
- x, y, indicator_size, indicator_size );
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKCheck( GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState,
- const ImplControlValue& aValue )
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- bool isChecked = (aValue.getTristateVal() == ButtonValue::On);
- bool isInconsistent = (aValue.getTristateVal() == ButtonValue::Mixed);
- GdkRectangle clipRect;
- gint x,y;
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKCheck( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- gint indicator_size;
- gtk_widget_style_get( gWidgetData[m_nXScreen].gCheckWidget, "indicator_size", &indicator_size, nullptr);
-
- x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2;
- y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2;
-
- // Set the shadow based on if checked or not so we get a checkmark.
- shadowType = isChecked ? GTK_SHADOW_IN : isInconsistent ? GTK_SHADOW_ETCHED_IN : GTK_SHADOW_OUT;
- NWSetWidgetState( gWidgetData[m_nXScreen].gCheckWidget, nState, stateType );
- GTK_TOGGLE_BUTTON(gWidgetData[m_nXScreen].gCheckWidget)->active = isChecked;
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- gtk_paint_check( gWidgetData[m_nXScreen].gCheckWidget->style, gdkDrawable, stateType, shadowType,
- &clipRect, gWidgetData[m_nXScreen].gCheckWidget, "checkbutton",
- x, y, indicator_size, indicator_size );
- }
-
- return true;
-}
-
-static void NWCalcArrowRect( const tools::Rectangle& rButton, tools::Rectangle& rArrow )
-{
- // Size the arrow appropriately
- Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
- rArrow.SetSize( aSize );
-
- rArrow.SetPos( Point(
- rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2,
- rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
- ) );
-}
-
-bool GtkSalGraphics::NWPaintGTKScrollbar( ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- ControlState nState,
- const ImplControlValue& aValue )
-{
- assert(aValue.getType() == ControlType::Scrollbar);
- const ScrollbarValue& rScrollbarVal = static_cast<const ScrollbarValue&>(aValue);
- std::unique_ptr<GdkX11Pixmap> pixmap;
- tools::Rectangle pixmapRect, scrollbarRect;
- GtkStateType stateType;
- GtkShadowType shadowType;
- GtkScrollbar * scrollbarWidget;
- GtkStyle * style;
- GtkAdjustment* scrollbarValues = nullptr;
- GtkOrientation scrollbarOrientation;
- tools::Rectangle thumbRect = rScrollbarVal.maThumbRect;
- tools::Rectangle button11BoundRect = rScrollbarVal.maButton1Rect; // backward
- tools::Rectangle button22BoundRect = rScrollbarVal.maButton2Rect; // forward
- tools::Rectangle button12BoundRect = rScrollbarVal.maButton1Rect; // secondary forward
- tools::Rectangle button21BoundRect = rScrollbarVal.maButton2Rect; // secondary backward
- GtkArrowType button1Type; // backward
- GtkArrowType button2Type; // forward
- gchar * scrollbarTagH = const_cast<gchar *>("hscrollbar");
- gchar * scrollbarTagV = const_cast<gchar *>("vscrollbar");
- gchar * scrollbarTag = nullptr;
- tools::Rectangle arrowRect;
- gint slider_width = 0;
- gint stepper_size = 0;
- gint stepper_spacing = 0;
- gint trough_border = 0;
- gint min_slider_length = 0;
- gint vShim = 0;
- gint hShim = 0;
- gint x,y,w,h;
-
- // make controlvalue rectangles relative to area
- thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
- button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
- button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
- button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
- button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKScrollbars( m_nXScreen );
- NWEnsureGTKArrow( m_nXScreen );
-
- // Find the overall bounding rect of the control
- pixmapRect = rControlRectangle;
- scrollbarRect = pixmapRect;
-
- if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) )
- return true;
-
- // Grab some button style attributes
- gtk_widget_style_get( gWidgetData[m_nXScreen].gScrollHorizWidget,
- "slider_width", &slider_width,
- "stepper_size", &stepper_size,
- "trough_border", &trough_border,
- "stepper_spacing", &stepper_spacing,
- "min_slider_length", &min_slider_length, nullptr );
- gboolean has_forward;
- gboolean has_forward2;
- gboolean has_backward;
- gboolean has_backward2;
-
- gtk_widget_style_get( gWidgetData[m_nXScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward,
- "has-secondary-forward-stepper", &has_forward2,
- "has-backward-stepper", &has_backward,
- "has-secondary-backward-stepper", &has_backward2, nullptr );
- gint magic = trough_border ? 1 : 0;
-
- if ( nPart == ControlPart::DrawBackgroundHorz )
- {
- unsigned int sliderHeight = slider_width + (trough_border * 2);
- vShim = (pixmapRect.GetHeight() - sliderHeight) / 2;
- bool bRTLSwap = button11BoundRect.Left() > button22BoundRect.Left();
-
- scrollbarRect.Move( 0, vShim );
- scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), sliderHeight ) );
-
- scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nXScreen].gScrollHorizWidget );
- scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
- scrollbarTag = scrollbarTagH;
- button1Type = bRTLSwap? GTK_ARROW_RIGHT: GTK_ARROW_LEFT;
- button2Type = bRTLSwap? GTK_ARROW_LEFT: GTK_ARROW_RIGHT;
-
- if ( has_backward )
- {
- button12BoundRect.Move( stepper_size - trough_border,
- (scrollbarRect.GetHeight() - slider_width) / 2 );
- }
-
- button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 );
- button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
- button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
-
- if ( has_backward2 )
- {
- button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
- button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
- }
- else
- {
- button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
- }
-
- button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
- button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
-
- thumbRect.SetBottom( thumbRect.Top() + slider_width - 1 );
- // Make sure the thumb is at least the default width (so we don't get tiny thumbs),
- // but if the VCL gives us a size smaller than the theme's default thumb size,
- // honor the VCL size
- thumbRect.AdjustRight(magic );
- // Center vertically in the track
- thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
- }
- else
- {
- unsigned int sliderWidth = slider_width + (trough_border * 2);
- hShim = (pixmapRect.GetWidth() - sliderWidth) / 2;
-
- scrollbarRect.Move( hShim, 0 );
- scrollbarRect.SetSize( Size( sliderWidth, scrollbarRect.GetHeight() ) );
-
- scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nXScreen].gScrollVertWidget );
- scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
- scrollbarTag = scrollbarTagV;
- button1Type = GTK_ARROW_UP;
- button2Type = GTK_ARROW_DOWN;
-
- if ( has_backward )
- {
- button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
- stepper_size + trough_border );
- }
- button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border );
- button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
- button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
-
- if ( has_backward2 )
- {
- button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 );
- button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
- }
- else
- {
- button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
- }
-
- button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
- button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
-
- thumbRect.SetRight( thumbRect.Left() + slider_width - 1 );
-
- thumbRect.AdjustBottom(magic );
- // Center horizontally in the track
- thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
- }
-
- bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
-
- scrollbarValues = gtk_range_get_adjustment( GTK_RANGE(scrollbarWidget) );
- if ( scrollbarValues == nullptr )
- scrollbarValues = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
- if ( nPart == ControlPart::DrawBackgroundHorz )
- {
- scrollbarValues->lower = rScrollbarVal.mnMin;
- scrollbarValues->upper = rScrollbarVal.mnMax;
- scrollbarValues->value = rScrollbarVal.mnCur;
- scrollbarValues->page_size = scrollbarRect.GetWidth() / 2;
- }
- else
- {
- scrollbarValues->lower = rScrollbarVal.mnMin;
- scrollbarValues->upper = rScrollbarVal.mnMax;
- scrollbarValues->value = rScrollbarVal.mnCur;
- scrollbarValues->page_size = scrollbarRect.GetHeight() / 2;
- }
- gtk_adjustment_changed( scrollbarValues );
-
- // as multiple paints are required for the scrollbar
- // painting them directly to the window flickers
- pixmap = NWGetPixmapFromScreen( pixmapRect );
- if( ! pixmap )
- return false;
- x = y = 0;
-
- w = pixmapRect.GetWidth();
- h = pixmapRect.GetHeight();
-
- GdkDrawable* const &gdkDrawable = pixmap->GetGdkDrawable();
- GdkRectangle* gdkRect = nullptr;
-
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
- NWSetWidgetState( GTK_WIDGET(scrollbarWidget), nState, stateType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gBtnWidget, nState, stateType );
- style = GTK_WIDGET( scrollbarWidget )->style;
-
- gtk_style_apply_default_background( m_pWindow->style, gdkDrawable, TRUE,
- GTK_STATE_NORMAL, gdkRect,
- x, y, w, h );
-
- // ----------------- TROUGH
- // Pass coordinates of draw rect: window(0,0) -> widget(bottom-right) (coords relative to widget)
- gtk_paint_flat_box(m_pWindow->style, gdkDrawable,
- GTK_STATE_NORMAL, GTK_SHADOW_NONE, gdkRect,
- m_pWindow, "base", x-pixmapRect.Left(),y-pixmapRect.Top(),x+pixmapRect.Right(),y+pixmapRect.Bottom());
-
- gtk_paint_box( style, gdkDrawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN,
- gdkRect, GTK_WIDGET(scrollbarWidget), "trough",
- x, y,
- scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
-
- if ( nState & ControlState::FOCUSED )
- {
- gtk_paint_focus( style, gdkDrawable, GTK_STATE_ACTIVE,
- gdkRect, GTK_WIDGET(scrollbarWidget), "trough",
- x, y,
- scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
- }
-
- // ----------------- THUMB
- if ( has_slider )
- {
- NWConvertVCLStateToGTKState( rScrollbarVal.mnThumbState, &stateType, &shadowType );
- gtk_paint_slider( style, gdkDrawable, stateType, GTK_SHADOW_OUT,
- gdkRect, GTK_WIDGET(scrollbarWidget), "slider",
- x+hShim+thumbRect.Left(), y+vShim+thumbRect.Top(),
- thumbRect.GetWidth(), thumbRect.GetHeight(), scrollbarOrientation );
- }
-
- // Some engines require allocation, e.g. Clearlooks uses it to identify
- // positions of the buttons, whereupon the first and the last button will
- // have rounded corners.
- GTK_WIDGET(scrollbarWidget)->allocation.x = x;
- GTK_WIDGET(scrollbarWidget)->allocation.y = y;
- GTK_WIDGET(scrollbarWidget)->allocation.width = w;
- GTK_WIDGET(scrollbarWidget)->allocation.height = h;
-
- bool backwardButtonInsensitive =
- rScrollbarVal.mnCur == rScrollbarVal.mnMin;
- bool forwardButtonInsensitive = rScrollbarVal.mnMax == 0 ||
- rScrollbarVal.mnCur + rScrollbarVal.mnVisibleSize >= rScrollbarVal.mnMax;
-
- // ----------------- BUTTON 1
- if ( has_backward )
- {
- NWConvertVCLStateToGTKState( rScrollbarVal.mnButton1State, &stateType, &shadowType );
- if ( backwardButtonInsensitive )
- stateType = GTK_STATE_INSENSITIVE;
- gtk_paint_box( style, gdkDrawable, stateType, shadowType,
- gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag,
- x+hShim+button11BoundRect.Left(), y+vShim+button11BoundRect.Top(),
- button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
- // ----------------- ARROW 1
- NWCalcArrowRect( button11BoundRect, arrowRect );
- gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
- gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, true,
- x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
- arrowRect.GetWidth(), arrowRect.GetHeight() );
- }
- if ( has_forward2 )
- {
- NWConvertVCLStateToGTKState( rScrollbarVal.mnButton2State, &stateType, &shadowType );
- if ( forwardButtonInsensitive )
- stateType = GTK_STATE_INSENSITIVE;
- gtk_paint_box( style, gdkDrawable, stateType, shadowType,
- gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag,
- x+hShim+button12BoundRect.Left(), y+vShim+button12BoundRect.Top(),
- button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
- // ----------------- ARROW 1
- NWCalcArrowRect( button12BoundRect, arrowRect );
- gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
- gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, true,
- x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
- arrowRect.GetWidth(), arrowRect.GetHeight() );
- }
- // ----------------- BUTTON 2
- if ( has_backward2 )
- {
- NWConvertVCLStateToGTKState( rScrollbarVal.mnButton1State, &stateType, &shadowType );
- if ( backwardButtonInsensitive )
- stateType = GTK_STATE_INSENSITIVE;
- gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect,
- GTK_WIDGET(scrollbarWidget), scrollbarTag,
- x+hShim+button21BoundRect.Left(), y+vShim+button21BoundRect.Top(),
- button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
- // ----------------- ARROW 2
- NWCalcArrowRect( button21BoundRect, arrowRect );
- gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
- gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, true,
- x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
- arrowRect.GetWidth(), arrowRect.GetHeight() );
- }
- if ( has_forward )
- {
- NWConvertVCLStateToGTKState( rScrollbarVal.mnButton2State, &stateType, &shadowType );
- if ( forwardButtonInsensitive )
- stateType = GTK_STATE_INSENSITIVE;
- gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect,
- GTK_WIDGET(scrollbarWidget), scrollbarTag,
- x+hShim+button22BoundRect.Left(), y+vShim+button22BoundRect.Top(),
- button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
- // ----------------- ARROW 2
- NWCalcArrowRect( button22BoundRect, arrowRect );
- gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
- gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, true,
- x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
- arrowRect.GetWidth(), arrowRect.GetHeight() );
- }
-
- bool bRet = NWRenderPixmapToScreen( pixmap.get(), nullptr, pixmapRect );
-
- return bRet;
-}
-
-static tools::Rectangle NWGetScrollButtonRect( SalX11Screen nScreen, ControlPart nPart, tools::Rectangle aAreaRect )
-{
- gint slider_width;
- gint stepper_size;
- gint stepper_spacing;
- gint trough_border;
-
- NWEnsureGTKScrollbars( nScreen );
-
- // Grab some button style attributes
- gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget,
- "slider-width", &slider_width,
- "stepper-size", &stepper_size,
- "trough-border", &trough_border,
- "stepper-spacing", &stepper_spacing, nullptr );
-
- gboolean has_forward;
- gboolean has_forward2;
- gboolean has_backward;
- gboolean has_backward2;
-
- gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget,
- "has-forward-stepper", &has_forward,
- "has-secondary-forward-stepper", &has_forward2,
- "has-backward-stepper", &has_backward,
- "has-secondary-backward-stepper", &has_backward2, nullptr );
- gint buttonWidth;
- gint buttonHeight;
- tools::Rectangle buttonRect;
-
- gint nFirst = 0;
- gint nSecond = 0;
-
- if ( has_forward ) nSecond += 1;
- if ( has_forward2 ) nFirst += 1;
- if ( has_backward ) nFirst += 1;
- if ( has_backward2 ) nSecond += 1;
-
- if ( ( nPart == ControlPart::ButtonUp ) || ( nPart == ControlPart::ButtonDown ) )
- {
- buttonWidth = slider_width + 2 * trough_border;
- buttonHeight = stepper_size + trough_border + stepper_spacing;
- }
- else
- {
- buttonWidth = stepper_size + trough_border + stepper_spacing;
- buttonHeight = slider_width + 2 * trough_border;
- }
-
- if ( nPart == ControlPart::ButtonUp )
- {
- buttonHeight *= nFirst;
- buttonHeight -= 1;
- buttonRect.setX( aAreaRect.Left() );
- buttonRect.setY( aAreaRect.Top() );
- }
- else if ( nPart == ControlPart::ButtonLeft )
- {
- buttonWidth *= nFirst;
- buttonWidth -= 1;
- buttonRect.setX( aAreaRect.Left() );
- buttonRect.setY( aAreaRect.Top() );
- }
- else if ( nPart == ControlPart::ButtonDown )
- {
- buttonHeight *= nSecond;
- buttonRect.setX( aAreaRect.Left() );
- buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight );
- }
- else if ( nPart == ControlPart::ButtonRight )
- {
- buttonWidth *= nSecond;
- buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth );
- buttonRect.setY( aAreaRect.Top() );
- }
-
- buttonRect.SetSize( Size( buttonWidth, buttonHeight ) );
-
- return buttonRect;
-}
-
-bool GtkSalGraphics::NWPaintGTKEditBox( GdkDrawable* gdkDrawable,
- ControlType nType,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- tools::Rectangle pixmapRect;
- GdkRectangle clipRect;
-
- // Find the overall bounding rect of the buttons's drawing area,
- // plus its actual draw rect excluding adornment
- pixmapRect = NWGetEditBoxPixmapRect( m_nXScreen, rControlRectangle );
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- NWPaintOneEditBox( m_nXScreen, gdkDrawable, &clipRect, nType, pixmapRect, nState );
- }
-
- return true;
-}
-
-/* Take interior/exterior focus into account and return
- * the bounding rectangle of the edit box including
- * any focus requirements.
- */
-static tools::Rectangle NWGetEditBoxPixmapRect(SalX11Screen nScreen,
- tools::Rectangle aAreaRect)
-{
- tools::Rectangle pixmapRect = aAreaRect;
- gboolean interiorFocus;
- gint focusWidth;
-
- NWEnsureGTKEditBox( nScreen );
-
- // Grab some entry style attributes
- gtk_widget_style_get( gWidgetData[nScreen].gEditBoxWidget,
- "focus-line-width", &focusWidth,
- "interior-focus", &interiorFocus, nullptr );
-
- if ( !interiorFocus )
- {
- pixmapRect.Move( -focusWidth, -focusWidth );
- pixmapRect.SetSize( Size( pixmapRect.GetWidth() + (2*focusWidth),
- pixmapRect.GetHeight() + (2*focusWidth) ) );
- }
-
- return pixmapRect;
-}
-
-/* Paint a GTK Entry widget into the specified GdkPixmap.
- * All coordinates should be local to the Pixmap, NOT
- * screen/window coordinates.
- */
-static void NWPaintOneEditBox( SalX11Screen nScreen,
- GdkDrawable * gdkDrawable,
- GdkRectangle const * gdkRect,
- ControlType nType,
- tools::Rectangle aEditBoxRect,
- ControlState nState )
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- GtkWidget *widget;
-
- NWEnsureGTKButton( nScreen );
- NWEnsureGTKEditBox( nScreen );
- NWEnsureGTKSpinButton( nScreen );
- NWEnsureGTKCombo( nScreen );
- NWEnsureGTKScrolledWindow( nScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- switch ( nType )
- {
- case ControlType::Spinbox:
- widget = gWidgetData[nScreen].gSpinButtonWidget;
- break;
-
- case ControlType::MultilineEditbox:
- widget = gWidgetData[nScreen].gScrolledWindowWidget;
- break;
- case ControlType::Combobox:
- widget = GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry;
- break;
-
- default:
- widget = gWidgetData[nScreen].gEditBoxWidget;
- break;
- }
-
- if ( stateType == GTK_STATE_PRELIGHT )
- stateType = GTK_STATE_NORMAL;
-
- NWSetWidgetState( widget, nState, stateType );
-
- gint xborder = widget->style->xthickness;
- gint yborder = widget->style->ythickness;
- gint bInteriorFocus, nFocusLineWidth;
- gtk_widget_style_get( widget,
- "interior-focus", &bInteriorFocus,
- "focus-line-width", &nFocusLineWidth,
- nullptr);
- if ( !bInteriorFocus )
- {
- xborder += nFocusLineWidth;
- yborder += nFocusLineWidth;
- }
-
- gtk_paint_flat_box( widget->style, gdkDrawable, stateType, GTK_SHADOW_NONE,
- gdkRect, widget, "entry_bg",
- aEditBoxRect.Left() + xborder, aEditBoxRect.Top() + yborder,
- aEditBoxRect.GetWidth() - 2*xborder, aEditBoxRect.GetHeight() - 2*yborder );
- gtk_paint_shadow( widget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
- gdkRect, widget, "entry",
- aEditBoxRect.Left(), aEditBoxRect.Top(),
- aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
-
-}
-
-bool GtkSalGraphics::NWPaintGTKSpinBox(ControlType nType, ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- ControlState nState,
- const ImplControlValue& aValue,
- ControlCacheKey& rControlCacheKey)
-{
- tools::Rectangle pixmapRect;
- GtkStateType stateType;
- GtkShadowType shadowType;
- const SpinbuttonValue * pSpinVal = (aValue.getType() == ControlType::SpinButtons) ? static_cast<const SpinbuttonValue *>(&aValue) : nullptr;
- tools::Rectangle upBtnRect;
- ControlPart upBtnPart = ControlPart::ButtonUp;
- ControlState upBtnState = ControlState::ENABLED;
- tools::Rectangle downBtnRect;
- ControlPart downBtnPart = ControlPart::ButtonDown;
- ControlState downBtnState = ControlState::ENABLED;
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKSpinButton( m_nXScreen );
- NWEnsureGTKArrow( m_nXScreen );
-
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- if ( pSpinVal )
- {
- upBtnPart = pSpinVal->mnUpperPart;
- upBtnState = pSpinVal->mnUpperState;
-
- downBtnPart = pSpinVal->mnLowerPart;
- downBtnState = pSpinVal->mnLowerState;
- }
-
- pixmapRect = rControlRectangle;
-
- BEGIN_PIXMAP_RENDER( pixmapRect, gdkPixmap )
- {
- // First render background
- gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,nullptr,m_pWindow,"base",
- -pixmapRect.Left(),
- -pixmapRect.Top(),
- pixmapRect.Right(),
- pixmapRect.Bottom() );
-
- upBtnRect = NWGetSpinButtonRect( m_nXScreen, upBtnPart, pixmapRect );
- downBtnRect = NWGetSpinButtonRect( m_nXScreen, downBtnPart, pixmapRect );
-
- if ( (nType==ControlType::Spinbox) && (nPart!=ControlPart::AllButtons) )
- {
- // Draw an edit field for SpinBoxes and ComboBoxes
- tools::Rectangle aEditBoxRect( pixmapRect );
- aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) );
- if( AllSettings::GetLayoutRTL() )
- aEditBoxRect.setX( upBtnRect.GetWidth() );
- else
- aEditBoxRect.setX( 0 );
- aEditBoxRect.setY( 0 );
-
- NWPaintOneEditBox( m_nXScreen, gdkPixmap, nullptr, nType, aEditBoxRect, nState );
- }
-
- NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType );
- gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, nullptr );
-
- if ( shadowType != GTK_SHADOW_NONE )
- {
- tools::Rectangle shadowRect( upBtnRect );
-
- shadowRect.Union( downBtnRect );
- gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, nullptr,
- gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton",
- (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()),
- shadowRect.GetWidth(), shadowRect.GetHeight() );
- }
-
- NWPaintOneSpinButton( m_nXScreen, gdkPixmap, upBtnPart, pixmapRect, upBtnState );
- NWPaintOneSpinButton( m_nXScreen, gdkPixmap, downBtnPart, pixmapRect, downBtnState );
- }
- END_PIXMAP_RENDER_WITH_CONTROL_KEY(pixmapRect, rControlCacheKey);
-
- return true;
-}
-
-static tools::Rectangle NWGetSpinButtonRect( SalX11Screen nScreen,
- ControlPart nPart,
- tools::Rectangle aAreaRect )
-{
- gint buttonSize;
- tools::Rectangle buttonRect;
-
- NWEnsureGTKSpinButton( nScreen );
-
- buttonSize = MAX( PANGO_PIXELS( pango_font_description_get_size(GTK_WIDGET(gWidgetData[nScreen].gSpinButtonWidget)->style->font_desc) ),
- MIN_SPIN_ARROW_WIDTH );
- buttonSize -= buttonSize % 2 - 1; /* force odd */
- buttonRect.SetSize( Size( buttonSize + 2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness,
- buttonRect.GetHeight() ) );
- if( AllSettings::GetLayoutRTL() )
- buttonRect.setX( aAreaRect.Left() );
- else
- buttonRect.setX( aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()) );
- if ( nPart == ControlPart::ButtonUp )
- {
- buttonRect.setY( aAreaRect.Top() );
- buttonRect.SetBottom( buttonRect.Top() + (aAreaRect.GetHeight() / 2) );
- }
- else if( nPart == ControlPart::ButtonDown )
- {
- buttonRect.setY( aAreaRect.Top() + (aAreaRect.GetHeight() / 2) );
- buttonRect.SetBottom( aAreaRect.Bottom() ); // cover area completely
- }
- else
- {
- if( AllSettings::GetLayoutRTL() ) {
- buttonRect.SetLeft( buttonRect.Right()+1 );
- buttonRect.SetRight( aAreaRect.Right() );
- } else {
- buttonRect.SetRight( buttonRect.Left()-1 );
- buttonRect.SetLeft( aAreaRect.Left() );
- }
- buttonRect.SetTop( aAreaRect.Top() );
- buttonRect.SetBottom( aAreaRect.Bottom() );
- }
-
- return buttonRect;
-}
-
-static void NWPaintOneSpinButton( SalX11Screen nScreen,
- GdkPixmap* pixmap,
- ControlPart nPart,
- tools::Rectangle aAreaRect,
- ControlState nState )
-{
- tools::Rectangle buttonRect;
- GtkStateType stateType;
- GtkShadowType shadowType;
- tools::Rectangle arrowRect;
- gint arrowSize;
-
- NWEnsureGTKSpinButton( nScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- buttonRect = NWGetSpinButtonRect( nScreen, nPart, aAreaRect );
-
- NWSetWidgetState( gWidgetData[nScreen].gSpinButtonWidget, nState, stateType );
- gtk_paint_box( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, shadowType, nullptr, gWidgetData[nScreen].gSpinButtonWidget,
- (nPart == ControlPart::ButtonUp) ? "spinbutton_up" : "spinbutton_down",
- (buttonRect.Left() - aAreaRect.Left()), (buttonRect.Top() - aAreaRect.Top()),
- buttonRect.GetWidth(), buttonRect.GetHeight() );
-
- arrowSize = (buttonRect.GetWidth() - (2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness)) - 4;
- arrowSize -= arrowSize % 2 - 1; /* force odd */
- arrowRect.SetSize( Size( arrowSize, arrowSize ) );
- arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
- if ( nPart == ControlPart::ButtonUp )
- arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 + 1);
- else
- arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 - 1);
-
- gtk_paint_arrow( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, GTK_SHADOW_OUT, nullptr, gWidgetData[nScreen].gSpinButtonWidget,
- "spinbutton", (nPart == ControlPart::ButtonUp) ? GTK_ARROW_UP : GTK_ARROW_DOWN, true,
- (arrowRect.Left() - aAreaRect.Left()), (arrowRect.Top() - aAreaRect.Top()),
- arrowRect.GetWidth(), arrowRect.GetHeight() );
-}
-
-bool GtkSalGraphics::NWPaintGTKComboBox( GdkDrawable* gdkDrawable,
- ControlType nType, ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- tools::Rectangle pixmapRect;
- tools::Rectangle buttonRect;
- GtkStateType stateType;
- GtkShadowType shadowType;
- tools::Rectangle arrowRect;
- gint x,y;
- GdkRectangle clipRect;
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKArrow( m_nXScreen );
- NWEnsureGTKCombo( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- // Find the overall bounding rect of the buttons's drawing area,
- // plus its actual draw rect excluding adornment
- pixmapRect = rControlRectangle;
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
-
- NWSetWidgetState( gWidgetData[m_nXScreen].gBtnWidget, nState, stateType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gComboWidget, nState, stateType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gArrowWidget, nState, stateType );
-
- buttonRect = NWGetComboBoxButtonRect( m_nXScreen, ControlPart::ButtonDown, pixmapRect );
- if( nPart == ControlPart::ButtonDown )
- buttonRect.AdjustLeft(1 );
-
- tools::Rectangle aEditBoxRect( pixmapRect );
- aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
- if( AllSettings::GetLayoutRTL() )
- aEditBoxRect.SetPos( Point( x + buttonRect.GetWidth() , y ) );
-
- #define ARROW_EXTENT 0.7
- arrowRect.SetSize( Size( gint(MIN_ARROW_SIZE * ARROW_EXTENT),
- gint(MIN_ARROW_SIZE * ARROW_EXTENT) ) );
- arrowRect.SetPos( Point( buttonRect.Left() + static_cast<gint>((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
- buttonRect.Top() + static_cast<gint>((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- if( nPart == ControlPart::Entire )
- NWPaintOneEditBox( m_nXScreen, gdkDrawable, &clipRect, nType, aEditBoxRect,
- nState );
-
- // Buttons must paint opaque since some themes have alpha-channel enabled buttons
- gtk_paint_flat_box( m_pWindow->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- &clipRect, m_pWindow, "base",
- x+(buttonRect.Left() - pixmapRect.Left()),
- y+(buttonRect.Top() - pixmapRect.Top()),
- buttonRect.GetWidth(), buttonRect.GetHeight() );
- gtk_paint_box( GTK_COMBO(gWidgetData[m_nXScreen].gComboWidget)->button->style, gdkDrawable, stateType, shadowType,
- &clipRect, GTK_COMBO(gWidgetData[m_nXScreen].gComboWidget)->button, "button",
- x+(buttonRect.Left() - pixmapRect.Left()),
- y+(buttonRect.Top() - pixmapRect.Top()),
- buttonRect.GetWidth(), buttonRect.GetHeight() );
-
- gtk_paint_arrow( gWidgetData[m_nXScreen].gArrowWidget->style, gdkDrawable, stateType, shadowType,
- &clipRect, gWidgetData[m_nXScreen].gArrowWidget, "arrow", GTK_ARROW_DOWN, true,
- x+(arrowRect.Left() - pixmapRect.Left()), y+(arrowRect.Top() - pixmapRect.Top()),
- arrowRect.GetWidth(), arrowRect.GetHeight() );
- }
-
- return true;
-}
-
-static tools::Rectangle NWGetComboBoxButtonRect( SalX11Screen nScreen,
- ControlPart nPart,
- tools::Rectangle aAreaRect )
-{
- tools::Rectangle aButtonRect;
- gint nArrowWidth;
- gint nButtonWidth;
- gint nFocusWidth;
- gint nFocusPad;
-
- NWEnsureGTKArrow( nScreen );
-
- // Grab some button style attributes
- gtk_widget_style_get( gWidgetData[nScreen].gDropdownWidget,
- "focus-line-width", &nFocusWidth,
- "focus-padding", &nFocusPad, nullptr );
-
- nArrowWidth = MIN_ARROW_SIZE + (GTK_MISC(gWidgetData[nScreen].gArrowWidget)->xpad * 2);
- nButtonWidth = nArrowWidth +
- ((BTN_CHILD_SPACING + gWidgetData[nScreen].gDropdownWidget->style->xthickness) * 2)
- + (2 * (nFocusWidth+nFocusPad));
- if( nPart == ControlPart::ButtonDown )
- {
- aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
- if( AllSettings::GetLayoutRTL() )
- aButtonRect.SetPos( Point( aAreaRect.Left(), aAreaRect.Top() ) );
- else
- aButtonRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth,
- aAreaRect.Top() ) );
- }
- else if( nPart == ControlPart::SubEdit )
- {
- NWEnsureGTKCombo( nScreen );
-
- gint adjust_x = GTK_CONTAINER(gWidgetData[nScreen].gComboWidget)->border_width +
- nFocusWidth +
- nFocusPad;
- gint adjust_y = adjust_x + gWidgetData[nScreen].gComboWidget->style->ythickness;
- adjust_x += gWidgetData[nScreen].gComboWidget->style->xthickness;
- aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - 2 * adjust_x,
- aAreaRect.GetHeight() - 2 * adjust_y ) );
- Point aEditPos = aAreaRect.TopLeft();
- aEditPos.AdjustX(adjust_x );
- aEditPos.AdjustY(adjust_y );
- if( AllSettings::GetLayoutRTL() )
- aEditPos.AdjustX(nButtonWidth );
- aButtonRect.SetPos( aEditPos );
- }
-
- return aButtonRect;
-}
-
-bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType,
- const tools::Rectangle& rControlRectangle,
- ControlState nState,
- const ImplControlValue& aValue )
-{
- OSL_ASSERT( nType != ControlType::TabItem || aValue.getType() == ControlType::TabItem );
- GdkX11Pixmap * pixmap;
- GdkX11Pixmap * mask;
- tools::Rectangle pixmapRect;
- tools::Rectangle tabRect;
- GtkStateType stateType;
- GtkShadowType shadowType;
- if( ! gWidgetData[ m_nXScreen ].gCacheTabItems )
- {
- gWidgetData[ m_nXScreen ].gCacheTabItems = new NWPixmapCache( m_nXScreen );
- gWidgetData[ m_nXScreen ].gCacheTabPages = new NWPixmapCache( m_nXScreen );
- }
- NWPixmapCache& aCacheItems = *gWidgetData[ m_nXScreen ].gCacheTabItems;
- NWPixmapCache& aCachePage = *gWidgetData[ m_nXScreen ].gCacheTabPages;
-
- if( !aCacheItems.GetSize() )
- aCacheItems.SetSize( 20 );
- if( !aCachePage.GetSize() )
- aCachePage.SetSize( 1 );
-
- if ( (nType == ControlType::TabItem) && (aValue.getType() != ControlType::TabItem) )
- {
- return false;
- }
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKNotebook( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- // Find the overall bounding rect of the buttons's drawing area,
- // plus its actual draw rect excluding adornment
- pixmapRect = rControlRectangle;
- if ( nType == ControlType::TabItem )
- {
- const TabitemValue * pTabitemValue = static_cast<const TabitemValue *>(&aValue);
- if ( !pTabitemValue->isFirst() )
- {
- // GTK+ tabs overlap on the right edge (the top tab obscures the
- // left edge of the tab right "below" it, so adjust the rectangle
- // to draw tabs slightly large so the overlap happens
- pixmapRect.Move( -2, 0 );
- pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, pixmapRect.GetHeight() ) );
- }
- if ( nState & ControlState::SELECTED )
- {
- // In GTK+, the selected tab is 2px taller than all other tabs
- pixmapRect.Move( 0, -2 );
- pixmapRect.AdjustBottom(2 );
- tabRect = pixmapRect;
- // Only draw over 1 pixel of the tab pane that this tab is drawn on top of.
- tabRect.AdjustBottom( -1 );
- }
- else
- tabRect = pixmapRect;
-
- // Allow the tab to draw a right border if needed
- tabRect.AdjustRight( -1 );
-
- // avoid degenerate cases which might lead to crashes
- if( tabRect.GetWidth() <= 1 || tabRect.GetHeight() <= 1 )
- return false;
- }
-
- if( nType == ControlType::TabItem )
- {
- if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap, &mask ) )
- return NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
- }
- else
- {
- if( aCachePage.Find( nType, nState, pixmapRect, &pixmap, &mask ) )
- return NWRenderPixmapToScreen( pixmap, mask, pixmapRect );
- }
-
- GdkRectangle paintRect;
- paintRect.x = paintRect.y = 0;
- paintRect.width = pixmapRect.GetWidth();
- paintRect.height = pixmapRect.GetHeight();
-
- BEGIN_CACHE_PIXMAP_RENDER( pixmapRect, pixmap, mask, gdkPixmap )
- {
- gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL,
- GTK_SHADOW_NONE, &paintRect, m_pWindow, "base",
- -rControlRectangle.Left(),
- -rControlRectangle.Top(),
- pixmapRect.GetWidth()+rControlRectangle.Left(),
- pixmapRect.GetHeight()+rControlRectangle.Top());
-
- NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType );
-
- switch( nType )
- {
- case ControlType::TabBody:
- break;
-
- case ControlType::TabPane:
- gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, nullptr, gWidgetData[m_nXScreen].gNotebookWidget,
- "notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 );
- break;
-
- case ControlType::TabItem:
- {
- stateType = ( nState & ControlState::SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE;
-
- // First draw the background
- gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap,
- GTK_STATE_NORMAL, GTK_SHADOW_NONE, nullptr, m_pWindow, "base",
- -rControlRectangle.Left(),
- -rControlRectangle.Top(),
- pixmapRect.GetWidth()+rControlRectangle.Left(),
- pixmapRect.GetHeight()+rControlRectangle.Top());
-
- // Now the tab itself
- if( nState & ControlState::ROLLOVER )
- g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast<gpointer>(TRUE));
-
- gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, nullptr, gWidgetData[m_nXScreen].gNotebookWidget,
- "tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()),
- tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM );
-
- g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName);
-
- if ( nState & ControlState::SELECTED )
- {
- gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, nullptr, m_pWindow,
- "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 );
- }
- break;
- }
-
- default:
- break;
- }
- }
- END_CACHE_PIXMAP_RENDER( pixmapRect, pixmap, mask )
-
- // cache data
- if( nType == ControlType::TabItem )
- aCacheItems.Fill( nType, nState, pixmapRect, std::unique_ptr<GdkX11Pixmap>(pixmap), std::unique_ptr<GdkX11Pixmap>(mask) );
- else
- aCachePage.Fill( nType, nState, pixmapRect, std::unique_ptr<GdkX11Pixmap>(pixmap), std::unique_ptr<GdkX11Pixmap>(mask) );
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKListBox( GdkDrawable* gdkDrawable,
- ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- tools::Rectangle aIndicatorRect;
- GtkStateType stateType;
- GtkShadowType shadowType;
- gint bInteriorFocus;
- gint nFocusLineWidth;
- gint nFocusPadding;
- gint x,y,w,h;
- GdkRectangle clipRect;
-
- NWEnsureGTKButton( m_nXScreen );
- NWEnsureGTKOptionMenu( m_nXScreen );
- NWEnsureGTKScrolledWindow( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- // set up references to correct drawable and cliprect
- NWSetWidgetState( gWidgetData[m_nXScreen].gBtnWidget, nState, stateType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gOptionMenuWidget, nState, stateType );
- NWSetWidgetState( gWidgetData[m_nXScreen].gScrolledWindowWidget, nState, stateType );
-
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- if ( nPart != ControlPart::ListboxWindow )
- {
- gtk_widget_style_get( gWidgetData[m_nXScreen].gOptionMenuWidget,
- "interior_focus", &bInteriorFocus,
- "focus_line_width", &nFocusLineWidth,
- "focus_padding", &nFocusPadding,
- nullptr);
- }
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- if ( nPart != ControlPart::ListboxWindow )
- {
- // Listboxes must paint opaque since some themes have alpha-channel enabled bodies
- gtk_paint_flat_box( m_pWindow->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
- &clipRect, m_pWindow, "base", x, y, w, h);
- gtk_paint_box( gWidgetData[m_nXScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect,
- gWidgetData[m_nXScreen].gOptionMenuWidget, "optionmenu",
- x, y, w, h);
- aIndicatorRect = NWGetListBoxIndicatorRect( m_nXScreen, rControlRectangle);
- gtk_paint_tab( gWidgetData[m_nXScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect,
- gWidgetData[m_nXScreen].gOptionMenuWidget, "optionmenutab",
- aIndicatorRect.Left(), aIndicatorRect.Top(),
- aIndicatorRect.GetWidth(), aIndicatorRect.GetHeight() );
- }
- else
- {
- shadowType = GTK_SHADOW_IN;
-
- gtk_paint_shadow( gWidgetData[m_nXScreen].gScrolledWindowWidget->style, gdkDrawable, GTK_STATE_NORMAL, shadowType,
- &clipRect, gWidgetData[m_nXScreen].gScrolledWindowWidget, "scrolled_window",
- x, y, w, h );
- }
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKToolbar(
- GdkDrawable* gdkDrawable,
- ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState, const ImplControlValue& aValue)
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- gint x, y, w, h;
- gint g_x=0, g_y=0, g_w=10, g_h=10;
- GtkWidget* pButtonWidget = gWidgetData[m_nXScreen].gToolbarButtonWidget;
- GdkRectangle clipRect;
-
- NWEnsureGTKToolbar( m_nXScreen );
- if( nPart == ControlPart::Button ) // toolbar buttons cannot focus in gtk
- nState &= ~ControlState::FOCUSED;
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- // handle toolbar
- if( nPart == ControlPart::DrawBackgroundHorz || nPart == ControlPart::DrawBackgroundVert )
- {
- NWSetWidgetState( gWidgetData[m_nXScreen].gToolbarWidget, nState, stateType );
-
- GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nXScreen].gToolbarWidget, GTK_SENSITIVE );
- if ( nState & ControlState::ENABLED )
- GTK_WIDGET_SET_FLAGS( gWidgetData[m_nXScreen].gToolbarWidget, GTK_SENSITIVE );
-
- if( nPart == ControlPart::DrawBackgroundHorz )
- gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nXScreen].gToolbarWidget), GTK_ORIENTATION_HORIZONTAL );
- else
- gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nXScreen].gToolbarWidget), GTK_ORIENTATION_VERTICAL );
- }
- // handle grip
- else if( nPart == ControlPart::ThumbHorz || nPart == ControlPart::ThumbVert )
- {
- NWSetWidgetState( gWidgetData[m_nXScreen].gHandleBoxWidget, nState, stateType );
-
- GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nXScreen].gHandleBoxWidget, GTK_SENSITIVE );
- if ( nState & ControlState::ENABLED )
- GTK_WIDGET_SET_FLAGS( gWidgetData[m_nXScreen].gHandleBoxWidget, GTK_SENSITIVE );
-
- gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(gWidgetData[m_nXScreen].gHandleBoxWidget), shadowType );
-
- // evaluate grip rect
- if( aValue.getType() == ControlType::Toolbar )
- {
- const ToolbarValue* pVal = static_cast<const ToolbarValue*>(&aValue);
- g_x = pVal->maGripRect.Left();
- g_y = pVal->maGripRect.Top();
- g_w = pVal->maGripRect.GetWidth();
- g_h = pVal->maGripRect.GetHeight();
- }
- }
- // handle button
- else if( nPart == ControlPart::Button )
- {
- bool bPaintButton = (nState & ControlState::PRESSED)
- || (nState & ControlState::ROLLOVER);
- if( aValue.getTristateVal() == ButtonValue::On )
- {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pButtonWidget),TRUE);
- bPaintButton = true;
- }
- else
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pButtonWidget),FALSE);
-
- NWSetWidgetState( pButtonWidget, nState, stateType );
- gtk_widget_ensure_style( pButtonWidget );
- if(bPaintButton)
- NWPaintGTKButtonReal(pButtonWidget, gdkDrawable, rControlRectangle, rClipList, nState);
- }
-
- if( nPart != ControlPart::Button )
- {
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- // draw toolbar
- if( nPart == ControlPart::DrawBackgroundHorz || nPart == ControlPart::DrawBackgroundVert )
- {
- gtk_paint_flat_box( gWidgetData[m_nXScreen].gToolbarWidget->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_NONE,
- &clipRect,
- gWidgetData[m_nXScreen].gToolbarWidget,
- "base",
- x, y, w, h );
- gtk_paint_box( gWidgetData[m_nXScreen].gToolbarWidget->style,
- gdkDrawable,
- stateType,
- shadowType,
- &clipRect,
- gWidgetData[m_nXScreen].gToolbarWidget,
- "toolbar",
- x, y, w, h );
- }
- // draw grip
- else if( nPart == ControlPart::ThumbHorz || nPart == ControlPart::ThumbVert )
- {
- gtk_paint_handle( gWidgetData[m_nXScreen].gHandleBoxWidget->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_OUT,
- &clipRect,
- gWidgetData[m_nXScreen].gHandleBoxWidget,
- "handlebox",
- g_x, g_y, g_w, g_h,
- nPart == ControlPart::ThumbHorz ?
- GTK_ORIENTATION_HORIZONTAL :
- GTK_ORIENTATION_VERTICAL
- );
- }
- else if( nPart == ControlPart::SeparatorHorz || nPart == ControlPart::SeparatorVert )
- {
- const double shim = 0.2;
-
- gint separator_height, separator_width, wide_separators = 0;
-
- gtk_widget_style_get (gWidgetData[m_nXScreen].gSeparator,
- "wide-separators", &wide_separators,
- "separator-width", &separator_width,
- "separator-height", &separator_height,
- nullptr);
-
- if (wide_separators)
- {
- if (nPart == ControlPart::SeparatorVert)
- gtk_paint_box (gWidgetData[m_nXScreen].gSeparator->style, gdkDrawable,
- GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
- &clipRect, gWidgetData[m_nXScreen].gSeparator, "vseparator",
- x + (w - separator_width) / 2, y + h * shim,
- separator_width, h * (1 - 2*shim));
- else
- gtk_paint_box (gWidgetData[m_nXScreen].gSeparator->style, gdkDrawable,
- GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
- &clipRect, gWidgetData[m_nXScreen].gSeparator, "hseparator",
- x + w * shim, y + (h - separator_width) / 2,
- w * (1 - 2*shim), separator_width);
- }
- else
- {
- if (nPart == ControlPart::SeparatorVert)
- gtk_paint_vline (gWidgetData[m_nXScreen].gSeparator->style, gdkDrawable,
- GTK_STATE_NORMAL,
- &clipRect, gWidgetData[m_nXScreen].gSeparator, "vseparator",
- y + h * shim, y + h * (1 - shim), x + w/2 - 1);
- else
- gtk_paint_hline (gWidgetData[m_nXScreen].gSeparator->style, gdkDrawable,
- GTK_STATE_NORMAL,
- &clipRect, gWidgetData[m_nXScreen].gSeparator, "hseparator",
- x + w * shim, x + w * (1 - shim), y + h/2 - 1);
- }
- }
- }
- }
-
- return true;
-}
-
-/// Converts a VCL Rectangle to a GdkRectangle.
-static void lcl_rectangleToGdkRectangle(const tools::Rectangle& rRectangle, GdkRectangle& rGdkRectangle)
-{
- rGdkRectangle.x = rRectangle.Left();
- rGdkRectangle.y = rRectangle.Top();
- rGdkRectangle.width = rRectangle.GetWidth();
- rGdkRectangle.height = rRectangle.GetHeight();
-}
-
-bool GtkSalGraphics::NWPaintGTKMenubar(
- GdkDrawable* gdkDrawable,
- ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- GtkStateType stateType;
- GtkShadowType shadowType;
- GtkShadowType selected_shadow_type = GTK_SHADOW_OUT;
- gint x, y, w, h;
- GdkRectangle clipRect;
-
- NWEnsureGTKMenubar( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- if( nPart == ControlPart::MenuItem )
- {
- if( nState & ControlState::SELECTED )
- {
- gtk_widget_style_get( gWidgetData[m_nXScreen].gMenuItemMenubarWidget,
- "selected_shadow_type", &selected_shadow_type,
- nullptr);
- }
- }
-
- for (auto const& clip : rClipList)
- {
- lcl_rectangleToGdkRectangle(clip, clipRect);
-
- // handle Menubar
- if( nPart == ControlPart::Entire )
- {
- NWSetWidgetState( gWidgetData[m_nXScreen].gMenubarWidget, nState, stateType );
-
- GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nXScreen].gMenubarWidget, GTK_SENSITIVE );
- if ( nState & ControlState::ENABLED )
- GTK_WIDGET_SET_FLAGS( gWidgetData[m_nXScreen].gMenubarWidget, GTK_SENSITIVE );
-
- // for translucent menubar styles paint background first
- gtk_paint_flat_box( gWidgetData[m_nXScreen].gMenubarWidget->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_NONE,
- &clipRect,
- GTK_WIDGET(m_pWindow),
- "base",
- x, y, w, h );
-
- // Do the conversion again, in case clipRect has been modified.
- lcl_rectangleToGdkRectangle(clip, clipRect);
-
- gtk_paint_box( gWidgetData[m_nXScreen].gMenubarWidget->style,
- gdkDrawable,
- stateType,
- shadowType,
- &clipRect,
- gWidgetData[m_nXScreen].gMenubarWidget,
- "menubar",
- x, y, w, h );
- }
-
- else if( nPart == ControlPart::MenuItem )
- {
- if( nState & ControlState::SELECTED )
- {
- gtk_paint_box( gWidgetData[m_nXScreen].gMenuItemMenubarWidget->style,
- gdkDrawable,
- GTK_STATE_PRELIGHT,
- selected_shadow_type,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuItemMenubarWidget,
- "menuitem",
- x, y, w, h);
- }
- }
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKPopupMenu(
- GdkDrawable* gdkDrawable,
- ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList,
- ControlState nState )
-{
- // #i50745# gtk does not draw disabled menu entries (and crux theme
- // even crashes) in very old (Fedora Core 4 vintage) gtk's
- if (gtk_major_version <= 2 && gtk_minor_version <= 8 &&
- nPart == ControlPart::MenuItem && ! (nState & ControlState::ENABLED) )
- return true;
-
- GtkStateType stateType;
- GtkShadowType shadowType;
- GtkShadowType selected_shadow_type = GTK_SHADOW_OUT;
- gint x, y, w, h;
- GdkRectangle clipRect;
-
- NWEnsureGTKMenu( m_nXScreen );
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- if( nPart == ControlPart::MenuItem &&
- ( nState & (ControlState::SELECTED|ControlState::ROLLOVER) ) )
- {
- gtk_widget_style_get( gWidgetData[m_nXScreen].gMenuItemMenuWidget,
- "selected_shadow_type", &selected_shadow_type,
- nullptr);
- }
-
- NWSetWidgetState( gWidgetData[m_nXScreen].gMenuWidget, nState, stateType );
-
- GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nXScreen].gMenuWidget, GTK_SENSITIVE );
- if ( nState & ControlState::ENABLED )
- GTK_WIDGET_SET_FLAGS( gWidgetData[m_nXScreen].gMenuWidget, GTK_SENSITIVE );
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- if( nPart == ControlPart::Entire )
- {
- // for translucent menubar styles paint background first
- gtk_paint_flat_box( gWidgetData[m_nXScreen].gMenuWidget->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_NONE,
- &clipRect,
- GTK_WIDGET(m_pWindow),
- "base",
- x, y, w, h );
- gtk_paint_box( gWidgetData[m_nXScreen].gMenuWidget->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_OUT,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuWidget,
- "menu",
- x, y, w, h );
- }
- else if( nPart == ControlPart::MenuItem )
- {
- if( nState & (ControlState::SELECTED|ControlState::ROLLOVER) )
- {
- if( nState & ControlState::ENABLED )
- gtk_paint_box( gWidgetData[m_nXScreen].gMenuItemMenuWidget->style,
- gdkDrawable,
- GTK_STATE_PRELIGHT,
- selected_shadow_type,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuItemMenuWidget,
- "menuitem",
- x, y, w, h);
- }
- }
- else if( nPart == ControlPart::MenuItemCheckMark || nPart == ControlPart::MenuItemRadioMark )
- {
- GtkWidget* pWidget = (nPart == ControlPart::MenuItemCheckMark) ?
- gWidgetData[m_nXScreen].gMenuItemCheckMenuWidget :
- gWidgetData[m_nXScreen].gMenuItemRadioMenuWidget;
-
- GtkStateType nStateType;
- GtkShadowType nShadowType;
- NWConvertVCLStateToGTKState( nState, &nStateType, &nShadowType );
-
- if ( (nState & ControlState::SELECTED) && (nState & ControlState::ENABLED) )
- nStateType = GTK_STATE_PRELIGHT;
-
- NWSetWidgetState( pWidget, nState, nStateType );
-
- if ( nPart == ControlPart::MenuItemCheckMark )
- {
- gtk_paint_check( pWidget->style,
- gdkDrawable,
- nStateType,
- nShadowType,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuItemMenuWidget,
- "check",
- x, y, w, h );
- }
- else
- {
- gtk_paint_option( pWidget->style,
- gdkDrawable,
- nStateType,
- nShadowType,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuItemMenuWidget,
- "option",
- x, y, w, h );
- }
- }
- else if( nPart == ControlPart::Separator )
- {
- gtk_paint_hline( gWidgetData[m_nXScreen].gMenuItemSeparatorMenuWidget->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuItemSeparatorMenuWidget,
- "menuitem",
- x, x + w, y + h / 2);
- }
- else if( nPart == ControlPart::SubmenuArrow )
- {
- GtkStateType nStateType;
- GtkShadowType nShadowType;
- NWConvertVCLStateToGTKState( nState, &nStateType, &nShadowType );
-
- if ( (nState & ControlState::SELECTED) && (nState & ControlState::ENABLED) )
- nStateType = GTK_STATE_PRELIGHT;
-
- NWSetWidgetState( gWidgetData[m_nXScreen].gMenuItemMenuWidget,
- nState, nStateType );
-
- GtkArrowType eArrow;
- if( AllSettings::GetLayoutRTL() )
- eArrow = GTK_ARROW_LEFT;
- else
- eArrow = GTK_ARROW_RIGHT;
-
- gtk_paint_arrow( gWidgetData[m_nXScreen].gMenuItemMenuWidget->style,
- gdkDrawable,
- nStateType,
- nShadowType,
- &clipRect,
- gWidgetData[m_nXScreen].gMenuItemMenuWidget,
- "menuitem",
- eArrow, TRUE,
- x, y, w, h);
- }
- }
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKTooltip(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- const std::vector< tools::Rectangle >& rClipList )
-{
- NWEnsureGTKTooltip( m_nXScreen );
-
- gint x, y, w, h;
- GdkRectangle clipRect;
-
- x = rControlRectangle.Left();
- y = rControlRectangle.Top();
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- for (auto const& clip : rClipList)
- {
- clipRect.x = clip.Left();
- clipRect.y = clip.Top();
- clipRect.width = clip.GetWidth();
- clipRect.height = clip.GetHeight();
-
- gtk_paint_flat_box( gWidgetData[m_nXScreen].gTooltipPopup->style,
- gdkDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_OUT,
- &clipRect,
- gWidgetData[m_nXScreen].gTooltipPopup,
- "tooltip",
- x, y, w, h );
- }
-
- return true;
-}
-
-namespace
-{
-void NWPaintGTKListNodeReal(SalX11Screen nXScreen, GdkDrawable* gdkDrawable, GtkStateType stateType,
- gint w, int h, GtkExpanderStyle eStyle)
-{
- gtk_paint_expander(gWidgetData[nXScreen].gTreeView->style, gdkDrawable, stateType, nullptr,
- gWidgetData[nXScreen].gTreeView, "treeview", w / 2, h / 2, eStyle);
-}
-}
-
-bool GtkSalGraphics::NWPaintGTKListNode(
- GdkDrawable* gdkDrawable,
- const tools::Rectangle& rControlRectangle,
- ControlState nState, const ImplControlValue& rValue )
-{
- NWEnsureGTKTreeView( m_nXScreen );
-
- tools::Rectangle aRect( rControlRectangle );
- aRect.AdjustLeft( -2 );
- aRect.AdjustRight(2 );
- aRect.AdjustTop( -2 );
- aRect.AdjustBottom(2 );
- gint w, h;
- w = aRect.GetWidth();
- h = aRect.GetHeight();
-
- GtkStateType stateType;
- GtkShadowType shadowType;
- NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
-
- ButtonValue aButtonValue = rValue.getTristateVal();
- GtkExpanderStyle eStyle = GTK_EXPANDER_EXPANDED;
-
- switch( aButtonValue )
- {
- case ButtonValue::On: eStyle = GTK_EXPANDER_EXPANDED;break;
- case ButtonValue::Off: eStyle = GTK_EXPANDER_COLLAPSED; break;
- default:
- break;
- }
-
- if (GtkSalGraphics::bNeedPixmapPaint)
- {
- NWPaintGTKListNodeReal(m_nXScreen, gdkDrawable, stateType, w, h, eStyle);
- return true;
- }
-
- BEGIN_PIXMAP_RENDER( aRect, pixDrawable )
- {
- NWPaintGTKListNodeReal(m_nXScreen, pixDrawable, stateType, w, h, eStyle);
- }
- END_PIXMAP_RENDER( aRect )
-
- return true;
-}
-
-bool GtkSalGraphics::NWPaintGTKProgress(
- const tools::Rectangle& rControlRectangle,
- const ImplControlValue& rValue )
-{
- NWEnsureGTKProgressBar( m_nXScreen );
-
- gint w, h;
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
- tools::Rectangle aRect( Point( 0, 0 ), Size( w, h ) );
-
- long nProgressWidth = rValue.getNumericVal();
-
- BEGIN_PIXMAP_RENDER( aRect, pixDrawable )
- {
- // paint background
- gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable,
- GTK_STATE_NORMAL, GTK_SHADOW_NONE, nullptr, m_pWindow, "base",
- -rControlRectangle.Left(),-rControlRectangle.Top(),
- rControlRectangle.Left()+w,rControlRectangle.Top()+h);
-
- gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style,
- pixDrawable,
- GTK_STATE_NORMAL,
- GTK_SHADOW_NONE,
- nullptr,
- gWidgetData[m_nXScreen].gProgressBar,
- "trough",
- 0, 0, w, h );
- if( nProgressWidth > 0 )
- {
- // paint progress
- if( AllSettings::GetLayoutRTL() )
- {
- gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style,
- pixDrawable,
- GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
- nullptr,
- gWidgetData[m_nXScreen].gProgressBar,
- "bar",
- w-nProgressWidth, 0, nProgressWidth, h
- );
- }
- else
- {
- gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style,
- pixDrawable,
- GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
- nullptr,
- gWidgetData[m_nXScreen].gProgressBar,
- "bar",
- 0, 0, nProgressWidth, h
- );
- }
- }
- }
- END_PIXMAP_RENDER( rControlRectangle )
-
- return true;
-}
-
-namespace
-{
-void NWPaintGTKSliderReal(SalX11Screen nXScreen, GdkDrawable* gdkDrawable, ControlPart nPart,
- const tools::Rectangle& rControlRectangle, ControlState nState,
- const ImplControlValue& rValue)
-{
- gint w, h;
- w = rControlRectangle.GetWidth();
- h = rControlRectangle.GetHeight();
-
- const SliderValue* pVal = static_cast<const SliderValue*>(&rValue);
-
- GtkWidget* pWidget = (nPart == ControlPart::TrackHorzArea)
- ? GTK_WIDGET(gWidgetData[nXScreen].gHScale)
- : GTK_WIDGET(gWidgetData[nXScreen].gVScale);
- const gchar* pDetail = (nPart == ControlPart::TrackHorzArea) ? "hscale" : "vscale";
- GtkOrientation eOri = (nPart == ControlPart::TrackHorzArea) ? GTK_ORIENTATION_HORIZONTAL
- : GTK_ORIENTATION_VERTICAL;
- gint slider_width = 10;
- gint slider_length = 10;
- gint trough_border = 0;
- gtk_widget_style_get(pWidget, "slider-width", &slider_width, "slider-length", &slider_length,
- "trough-border", &trough_border, nullptr);
-
- GtkStateType eState
- = (nState & ControlState::ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
- if (nPart == ControlPart::TrackHorzArea)
- {
- gtk_paint_box(pWidget->style, gdkDrawable, eState, GTK_SHADOW_IN, nullptr, pWidget,
- "trough", 0, (h - slider_width - 2 * trough_border) / 2, w,
- slider_width + 2 * trough_border);
- gint x
- = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
- gtk_paint_slider(pWidget->style, gdkDrawable, eState, GTK_SHADOW_OUT, nullptr, pWidget,
- pDetail, x, (h - slider_width) / 2, slider_length, slider_width, eOri);
- }
- else
- {
- gtk_paint_box(pWidget->style, gdkDrawable, eState, GTK_SHADOW_IN, nullptr, pWidget,
- "trough", (w - slider_width - 2 * trough_border) / 2, 0,
- slider_width + 2 * trough_border, h);
- gint y
- = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
- gtk_paint_slider(pWidget->style, gdkDrawable, eState, GTK_SHADOW_OUT, nullptr, pWidget,
- pDetail, (w - slider_width) / 2, y, slider_width, slider_length, eOri);
- }
-}
-}
-
-bool GtkSalGraphics::NWPaintGTKSlider(
- GdkDrawable* gdkDrawable,
- ControlPart nPart,
- const tools::Rectangle& rControlRectangle,
- ControlState nState, const ImplControlValue& rValue )
-{
- OSL_ASSERT( rValue.getType() == ControlType::Slider );
- NWEnsureGTKSlider( m_nXScreen );
-
- if (GtkSalGraphics::bNeedPixmapPaint)
- {
- NWPaintGTKSliderReal(m_nXScreen, gdkDrawable, nPart, rControlRectangle, nState, rValue);
- return true;
- }
-
- BEGIN_PIXMAP_RENDER( rControlRectangle, pixDrawable )
- {
- NWPaintGTKSliderReal(m_nXScreen, pixDrawable, nPart, rControlRectangle, nState, rValue);
- }
- END_PIXMAP_RENDER( rControlRectangle )
-
- return true;
-}
-
-static int getFrameWidth(GtkWidget const * widget)
-{
- return widget->style->xthickness;
-}
-
-static tools::Rectangle NWGetListBoxButtonRect( SalX11Screen nScreen,
- ControlPart nPart,
- tools::Rectangle aAreaRect )
-{
- tools::Rectangle aPartRect;
- GtkRequisition *pIndicatorSize = nullptr;
- GtkBorder *pIndicatorSpacing = nullptr;
- gint width = 13; // GTK+ default
- gint right = 5; // GTK+ default
- gint nButtonAreaWidth = 0;
- gint xthickness = 0;
-
- NWEnsureGTKOptionMenu( nScreen );
-
- gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget,
- "indicator_size", &pIndicatorSize,
- "indicator_spacing",&pIndicatorSpacing, nullptr);
-
- if ( pIndicatorSize )
- width = pIndicatorSize->width;
-
- if ( pIndicatorSpacing )
- right = pIndicatorSpacing->right;
-
- Size aPartSize( 0, aAreaRect.GetHeight() );
- Point aPartPos ( 0, aAreaRect.Top() );
-
- xthickness = gWidgetData[nScreen].gOptionMenuWidget->style->xthickness;
- nButtonAreaWidth = width + right + (xthickness * 2);
- switch( nPart )
- {
- case ControlPart::ButtonDown:
- aPartSize.setWidth( nButtonAreaWidth );
- aPartPos.setX( aAreaRect.Left() + aAreaRect.GetWidth() - aPartSize.Width() );
- break;
-
- case ControlPart::SubEdit:
- aPartSize.setWidth( aAreaRect.GetWidth() - nButtonAreaWidth - xthickness );
- if( AllSettings::GetLayoutRTL() )
- aPartPos.setX( aAreaRect.Left() + nButtonAreaWidth );
- else
- aPartPos.setX( aAreaRect.Left() + xthickness );
- break;
-
- default:
- aPartSize.setWidth( aAreaRect.GetWidth() );
- aPartPos.setX( aAreaRect.Left() );
- break;
- }
- aPartRect = tools::Rectangle( aPartPos, aPartSize );
-
- if ( pIndicatorSize )
- gtk_requisition_free( pIndicatorSize );
- if ( pIndicatorSpacing )
- gtk_border_free( pIndicatorSpacing );
-
- return aPartRect;
-}
-
-static tools::Rectangle NWGetListBoxIndicatorRect( SalX11Screen nScreen,
- tools::Rectangle aAreaRect )
-{
- tools::Rectangle aIndicatorRect;
- GtkRequisition *pIndicatorSize = nullptr;
- GtkBorder *pIndicatorSpacing = nullptr;
- gint width = 13; // GTK+ default
- gint height = 13; // GTK+ default
- gint right = 5; // GTK+ default
- gint x;
-
- NWEnsureGTKOptionMenu( nScreen );
-
- gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget,
- "indicator_size", &pIndicatorSize,
- "indicator_spacing",&pIndicatorSpacing, nullptr);
-
- if ( pIndicatorSize )
- {
- width = pIndicatorSize->width;
- height = pIndicatorSize->height;
- }
-
- if ( pIndicatorSpacing )
- right = pIndicatorSpacing->right;
-
- aIndicatorRect.SetSize( Size( width, height ) );
- if( AllSettings::GetLayoutRTL() )
- x = aAreaRect.Left() + right;
- else
- x = aAreaRect.Left() + aAreaRect.GetWidth() - width - right - gWidgetData[nScreen].gOptionMenuWidget->style->xthickness;
- aIndicatorRect.SetPos( Point( x, aAreaRect.Top() + ((aAreaRect.GetHeight() - height) / 2) ) );
-
- // If height is odd, move the indicator down 1 pixel
- if ( aIndicatorRect.GetHeight() % 2 )
- aIndicatorRect.Move( 0, 1 );
-
- if ( pIndicatorSize )
- gtk_requisition_free( pIndicatorSize );
- if ( pIndicatorSpacing )
- gtk_border_free( pIndicatorSpacing );
-
- return aIndicatorRect;
-}
-
-static tools::Rectangle NWGetToolbarRect( SalX11Screen nScreen,
- ControlPart nPart,
- tools::Rectangle aAreaRect )
-{
- tools::Rectangle aRet;
-
- if( nPart == ControlPart::DrawBackgroundHorz ||
- nPart == ControlPart::DrawBackgroundVert )
- aRet = aAreaRect;
- else if( nPart == ControlPart::ThumbHorz )
- aRet = tools::Rectangle( Point( 0, 0 ), Size( aAreaRect.GetWidth(), 10 ) );
- else if( nPart == ControlPart::ThumbVert )
- aRet = tools::Rectangle( Point( 0, 0 ), Size( 10, aAreaRect.GetHeight() ) );
- else if( nPart == ControlPart::Button )
- {
- aRet = aAreaRect;
-
- NWEnsureGTKToolbar( nScreen );
-
- gint nMinWidth =
- 2*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness
- + 1 // CHILD_SPACING constant, found in gtk_button.c
- + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness; // Murphy factor
- gint nMinHeight =
- 2*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness
- + 1 // CHILD_SPACING constant, found in gtk_button.c
- + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness; // Murphy factor
-
- gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarButtonWidget );
- if( aAreaRect.GetWidth() < nMinWidth )
- aRet.SetRight( aRet.Left() + nMinWidth );
- if( aAreaRect.GetHeight() < nMinHeight )
- aRet.SetBottom( aRet.Top() + nMinHeight );
- }
-
- return aRet;
-}
-
-/************************************************************************
- * helper for GtkSalFrame
- ************************************************************************/
-static Color getColor( const GdkColor& rCol )
-{
- return Color( rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
-}
-
-#if OSL_DEBUG_LEVEL > 1
-
-void printColor( const char* name, const GdkColor& rCol )
-{
- std::fprintf( stderr, " %s = 0x%2x 0x%2x 0x%2x\n",
- name,
- rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
-}
-
-void printStyleColors( GtkStyle* pStyle )
-{
- static const char* pStates[] = { "NORMAL", "ACTIVE", "PRELIGHT", "SELECTED", "INSENSITIVE" };
-
- for( int i = 0; i < 5; i++ )
- {
- std::fprintf( stderr, "state %s colors:\n", pStates[i] );
- printColor( "bg ", pStyle->bg[i] );
- printColor( "fg ", pStyle->fg[i] );
- printColor( "light ", pStyle->light[i] );
- printColor( "dark ", pStyle->dark[i] );
- printColor( "mid ", pStyle->mid[i] );
- printColor( "text ", pStyle->text[i] );
- printColor( "base ", pStyle->base[i] );
- printColor( "text_aa", pStyle->text_aa[i] );
- }
-}
-#endif
-
-void GtkSalGraphics::signalSettingsNotify( GObject *pSettings, GParamSpec *pSpec, gpointer )
-{
- g_return_if_fail( pSpec != nullptr );
-
- if( !strcmp( pSpec->name, "gtk-fontconfig-timestamp" ) )
- GtkSalGraphics::refreshFontconfig( GTK_SETTINGS( pSettings ) );
-}
-
-void GtkSalGraphics::refreshFontconfig( GtkSettings *pSettings )
-{
- guint latest_fontconfig_timestamp = 0;
- static guint our_fontconfig_timestamp = 0;
- g_object_get( pSettings, "gtk-fontconfig-timestamp", &latest_fontconfig_timestamp, nullptr );
- if (latest_fontconfig_timestamp != our_fontconfig_timestamp)
- {
- bool bFirstTime = our_fontconfig_timestamp == 0;
- our_fontconfig_timestamp = latest_fontconfig_timestamp;
- if (!bFirstTime)
- {
- psp::PrintFontManager::get().initialize();
- }
- }
-}
-
-bool GtkSalGraphics::updateSettings( AllSettings& rSettings )
-{
- gtk_widget_ensure_style( m_pWindow );
- GtkStyle* pStyle = gtk_widget_get_style( m_pWindow );
- GtkSettings* pSettings = gtk_widget_get_settings( m_pWindow );
- StyleSettings aStyleSet = rSettings.GetStyleSettings();
-
- // Listen for font changes
- if( !g_object_get_data( G_OBJECT( pSettings ), "libo:listening" ) )
- {
- g_object_set_data( G_OBJECT( pSettings ), "libo:listening",
- GUINT_TO_POINTER( 1 ) );
- g_signal_connect_data( G_OBJECT( pSettings ), "notify",
- G_CALLBACK( signalSettingsNotify ),
- nullptr, nullptr, G_CONNECT_AFTER );
- }
-
- refreshFontconfig( pSettings );
-
- // get the widgets in place
- NWEnsureGTKMenu( m_nXScreen );
- NWEnsureGTKMenubar( m_nXScreen );
- NWEnsureGTKToolbar( m_nXScreen );
- NWEnsureGTKScrollbars( m_nXScreen );
- NWEnsureGTKEditBox( m_nXScreen );
- NWEnsureGTKTooltip( m_nXScreen );
- NWEnsureGTKDialog( m_nXScreen );
- NWEnsureGTKFrame( m_nXScreen );
-
-#if OSL_DEBUG_LEVEL > 2
- printStyleColors( pStyle );
-#endif
-
- // text colors
- Color aTextColor = getColor( pStyle->text[GTK_STATE_NORMAL] );
- aStyleSet.SetDialogTextColor( aTextColor );
- aStyleSet.SetWindowTextColor( aTextColor );
- aStyleSet.SetFieldTextColor( aTextColor );
- aTextColor = getColor( pStyle->fg[GTK_STATE_NORMAL] );
- aStyleSet.SetButtonTextColor( aTextColor );
- aStyleSet.SetRadioCheckTextColor( aTextColor );
- aStyleSet.SetGroupTextColor( aTextColor );
- aStyleSet.SetLabelTextColor( aTextColor );
- aStyleSet.SetTabTextColor( aTextColor );
- aStyleSet.SetTabRolloverTextColor( aTextColor );
- aStyleSet.SetTabHighlightTextColor( aTextColor );
-
- // Tooltip colors
- GtkStyle* pTooltipStyle = gtk_widget_get_style( gWidgetData[m_nXScreen].gTooltipPopup );
- aTextColor = getColor( pTooltipStyle->fg[ GTK_STATE_NORMAL ] );
- aStyleSet.SetHelpTextColor( aTextColor );
-
- DialogStyle aDialogStyle(aStyleSet.GetDialogStyle());
- gtk_widget_style_get (gWidgetData[m_nXScreen].gDialog,
- "content-area-border", &aDialogStyle.content_area_border,
- "content-area-spacing", &aDialogStyle.content_area_spacing,
- "button-spacing", &aDialogStyle.button_spacing,
- "action-area-border", &aDialogStyle.action_area_border,
- nullptr);
- aStyleSet.SetDialogStyle(aDialogStyle);
-
- FrameStyle aFrameStyle(aStyleSet.GetFrameStyle());
- aFrameStyle.left = aFrameStyle.right =
- gWidgetData[m_nXScreen].gFrame->style->xthickness;
- aFrameStyle.top = aFrameStyle.bottom =
- gWidgetData[m_nXScreen].gFrame->style->ythickness;
- aStyleSet.SetFrameStyle(aFrameStyle);
-
- // mouse over text colors
- aTextColor = getColor( pStyle->fg[ GTK_STATE_PRELIGHT ] );
- aStyleSet.SetButtonRolloverTextColor( aTextColor );
- aStyleSet.SetButtonPressedRolloverTextColor( aTextColor );
- aStyleSet.SetFieldRolloverTextColor( aTextColor );
-
- // background colors
- Color aBackColor = getColor( pStyle->bg[GTK_STATE_NORMAL] );
- Color aBackFieldColor = getColor( pStyle->base[GTK_STATE_NORMAL] );
- aStyleSet.BatchSetBackgrounds( aBackColor );
-
- aStyleSet.SetFieldColor( aBackFieldColor );
- aStyleSet.SetWindowColor( aBackFieldColor );
-
- // Dark shadow color
- Color aDarkShadowColor = getColor( pStyle->fg[GTK_STATE_INSENSITIVE] );
- aStyleSet.SetDarkShadowColor( aDarkShadowColor );
-
- ::Color aShadowColor(aBackColor);
- if (aDarkShadowColor.GetLuminance() > aBackColor.GetLuminance())
- aShadowColor.IncreaseLuminance(64);
- else
- aShadowColor.DecreaseLuminance(64);
- aStyleSet.SetShadowColor(aShadowColor);
-
- // highlighting colors
- Color aHighlightColor = getColor( pStyle->base[GTK_STATE_SELECTED] );
- Color aHighlightTextColor = getColor( pStyle->text[GTK_STATE_SELECTED] );
- aStyleSet.SetHighlightColor( aHighlightColor );
- aStyleSet.SetHighlightTextColor( aHighlightTextColor );
-
- // hyperlink colors
- GdkColor *link_color = nullptr;
- gtk_widget_style_get (m_pWindow, "link-color", &link_color, nullptr);
- if (link_color)
- {
- aStyleSet.SetLinkColor(getColor(*link_color));
- gdk_color_free (link_color);
- link_color = nullptr;
- }
- gtk_widget_style_get (m_pWindow, "visited-link-color", &link_color, nullptr);
- if (link_color)
- {
- aStyleSet.SetVisitedLinkColor(getColor(*link_color));
- gdk_color_free (link_color);
- }
-
- // Tab colors
- aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color.
- Color aSelectedBackColor = getColor( pStyle->bg[GTK_STATE_ACTIVE] );
- aStyleSet.SetInactiveTabColor( aSelectedBackColor );
-
- // menu disabled entries handling
- aStyleSet.SetSkipDisabledInMenus( true );
- aStyleSet.SetPreferredContextMenuShortcuts( false );
- // menu colors
- GtkStyle* pMenuStyle = gtk_widget_get_style( gWidgetData[m_nXScreen].gMenuWidget );
- GtkStyle* pMenuItemStyle = gtk_rc_get_style( gWidgetData[m_nXScreen].gMenuItemMenuWidget );
- GtkStyle* pMenubarStyle = gtk_rc_get_style( gWidgetData[m_nXScreen].gMenubarWidget );
- GtkStyle* pMenuTextStyle = gtk_rc_get_style( gtk_bin_get_child( GTK_BIN(gWidgetData[m_nXScreen].gMenuItemMenuWidget) ) );
- aBackColor = getColor( pMenubarStyle->bg[GTK_STATE_NORMAL] );
- aStyleSet.SetMenuBarColor( aBackColor );
- aStyleSet.SetMenuBarRolloverColor( aBackColor );
- aBackColor = getColor( pMenuStyle->bg[GTK_STATE_NORMAL] );
- aTextColor = getColor( pMenuTextStyle->fg[GTK_STATE_NORMAL] );
- aStyleSet.SetMenuColor( aBackColor );
- aStyleSet.SetMenuTextColor( aTextColor );
-
- aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( pMenubarStyle->fg[GTK_STATE_NORMAL] ) );
- aStyleSet.SetMenuBarTextColor( aTextColor );
- aStyleSet.SetMenuBarRolloverTextColor(getColor(pMenubarStyle->fg[GTK_STATE_PRELIGHT]));
- aStyleSet.SetMenuBarHighlightTextColor(getColor(pMenubarStyle->fg[GTK_STATE_SELECTED]));
-
- // toolbar colors
- GtkStyle* pToolbarButtonStyle = gtk_rc_get_style( gWidgetData[m_nXScreen].gToolbarButtonWidget );
- aStyleSet.SetToolTextColor(getColor(pToolbarButtonStyle->fg[GTK_STATE_NORMAL]));
-
-#if OSL_DEBUG_LEVEL > 1
- std::fprintf( stderr, "==\n" );
- std::fprintf( stderr, "MenuColor = %x (%d)\n", (int)aStyleSet.GetMenuColor(), aStyleSet.GetMenuColor().GetLuminance() );
- std::fprintf( stderr, "MenuTextColor = %x (%d)\n", (int)aStyleSet.GetMenuTextColor(), aStyleSet.GetMenuTextColor().GetLuminance() );
- std::fprintf( stderr, "MenuBarColor = %x (%d)\n", (int)aStyleSet.GetMenuBarColor(), aStyleSet.GetMenuBarColor().GetLuminance() );
- std::fprintf( stderr, "MenuBarRolloverColor = %x (%d)\n", (int)aStyleSet.GetMenuBarRolloverColor(), aStyleSet.GetMenuBarRolloverColor().GetLuminance() );
- std::fprintf( stderr, "MenuBarTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarTextColor(), aStyleSet.GetMenuBarTextColor().GetLuminance() );
- std::fprintf( stderr, "MenuBarRolloverTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarRolloverTextColor(), aStyleSet.GetMenuBarRolloverTextColor().GetLuminance() );
- std::fprintf( stderr, "LightColor = %x (%d)\n", (int)aStyleSet.GetLightColor(), aStyleSet.GetLightColor().GetLuminance() );
- std::fprintf( stderr, "ShadowColor = %x (%d)\n", (int)aStyleSet.GetShadowColor(), aStyleSet.GetShadowColor().GetLuminance() );
- std::fprintf( stderr, "DarkShadowColor = %x (%d)\n", (int)aStyleSet.GetDarkShadowColor(), aStyleSet.GetDarkShadowColor().GetLuminance() );
-#endif
-
- aHighlightColor = getColor( pMenuItemStyle->bg[ GTK_STATE_SELECTED ] );
- aHighlightTextColor = getColor( pMenuItemStyle->fg[ GTK_STATE_SELECTED ] );
- aStyleSet.SetMenuHighlightColor( aHighlightColor );
- aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
-
- // UI font
- OString aFamily = pango_font_description_get_family( pStyle->font_desc );
- int nPangoHeight = pango_font_description_get_size( pStyle->font_desc );
- PangoStyle eStyle = pango_font_description_get_style( pStyle->font_desc );
- PangoWeight eWeight = pango_font_description_get_weight( pStyle->font_desc );
- PangoStretch eStretch = pango_font_description_get_stretch( pStyle->font_desc );
-
- psp::FastPrintFontInfo aInfo;
- // set family name
- aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
- // set italic
- switch( eStyle )
- {
- case PANGO_STYLE_NORMAL: aInfo.m_eItalic = ITALIC_NONE;break;
- case PANGO_STYLE_ITALIC: aInfo.m_eItalic = ITALIC_NORMAL;break;
- case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = ITALIC_OBLIQUE;break;
- }
- // set weight
- if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
- aInfo.m_eWeight = WEIGHT_ULTRALIGHT;
- else if( eWeight <= PANGO_WEIGHT_LIGHT )
- aInfo.m_eWeight = WEIGHT_LIGHT;
- else if( eWeight <= PANGO_WEIGHT_NORMAL )
- aInfo.m_eWeight = WEIGHT_NORMAL;
- else if( eWeight <= PANGO_WEIGHT_BOLD )
- aInfo.m_eWeight = WEIGHT_BOLD;
- else
- aInfo.m_eWeight = WEIGHT_ULTRABOLD;
- // set width
- switch( eStretch )
- {
- case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = WIDTH_ULTRA_CONDENSED;break;
- case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = WIDTH_EXTRA_CONDENSED;break;
- case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = WIDTH_CONDENSED;break;
- case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = WIDTH_SEMI_CONDENSED;break;
- case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = WIDTH_NORMAL;break;
- case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = WIDTH_SEMI_EXPANDED;break;
- case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = WIDTH_EXPANDED;break;
- case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = WIDTH_EXTRA_EXPANDED;break;
- case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = WIDTH_ULTRA_EXPANDED;break;
- }
-
-#if OSL_DEBUG_LEVEL > 1
- std::fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() );
-#endif
-
- // match font to e.g. resolve "Sans"
- psp::PrintFontManager::get().matchFont( aInfo, rSettings.GetUILanguageTag().getLocale() );
-
-#if OSL_DEBUG_LEVEL > 1
- std::fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
- aInfo.m_nID != 0 ? "succeeded" : "failed",
- OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
-#endif
-
- sal_Int32 nDispDPIY = GetDisplay()->GetResolution().B();
- int nPointHeight;
- if (pango_font_description_get_size_is_absolute(pStyle->font_desc))
- nPointHeight = (nPangoHeight * 72 + nDispDPIY*PANGO_SCALE/2) / (nDispDPIY * PANGO_SCALE);
- else
- nPointHeight = nPangoHeight/PANGO_SCALE;
-
- vcl::Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
- if( aInfo.m_eWeight != WEIGHT_DONTKNOW )
- aFont.SetWeight( aInfo.m_eWeight );
- if( aInfo.m_eWidth != WIDTH_DONTKNOW )
- aFont.SetWidthType( aInfo.m_eWidth );
- if( aInfo.m_eItalic != ITALIC_DONTKNOW )
- aFont.SetItalic( aInfo.m_eItalic );
- if( aInfo.m_ePitch != PITCH_DONTKNOW )
- aFont.SetPitch( aInfo.m_ePitch );
-
- aStyleSet.BatchSetFonts( aFont, aFont );
-
- aFont.SetWeight( WEIGHT_BOLD );
- aStyleSet.SetTitleFont( aFont );
- aStyleSet.SetFloatTitleFont( aFont );
-
- // Cursor width
- gfloat caretAspectRatio = 0.04f;
- gtk_widget_style_get( gWidgetData[m_nXScreen].gEditBoxWidget, "cursor-aspect-ratio", &caretAspectRatio, nullptr );
- // Assume 20px tall for the ratio computation, which should give reasonable results
- aStyleSet.SetCursorSize( 20 * caretAspectRatio + 1 );
-
- // get cursor blink time
- gboolean blink = false;
-
- g_object_get( pSettings, "gtk-cursor-blink", &blink, nullptr );
- if( blink )
- {
- gint blink_time = static_cast<gint>(STYLE_CURSOR_NOBLINKTIME);
- g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, nullptr );
- // set the blink_time if there is a setting and it is reasonable
- // else leave the default value
- if( blink_time > 100 )
- aStyleSet.SetCursorBlinkTime( blink_time/2 );
- }
- else
- aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
-
- MouseSettings aMouseSettings = rSettings.GetMouseSettings();
- int iDoubleClickTime, iDoubleClickDistance, iDragThreshold, iMenuPopupDelay;
- g_object_get( pSettings,
- "gtk-double-click-time", &iDoubleClickTime,
- "gtk-double-click-distance", &iDoubleClickDistance,
- "gtk-dnd-drag-threshold", &iDragThreshold,
- "gtk-menu-popup-delay", &iMenuPopupDelay,
- nullptr );
- aMouseSettings.SetDoubleClickTime( iDoubleClickTime );
- aMouseSettings.SetDoubleClickWidth( iDoubleClickDistance );
- aMouseSettings.SetDoubleClickHeight( iDoubleClickDistance );
- aMouseSettings.SetStartDragWidth( iDragThreshold );
- aMouseSettings.SetStartDragHeight( iDragThreshold );
- aMouseSettings.SetMenuDelay( iMenuPopupDelay );
- rSettings.SetMouseSettings( aMouseSettings );
-
- gboolean showmenuicons = true, primarybuttonwarps = false;
- g_object_get( pSettings,
- "gtk-menu-images", &showmenuicons,
- nullptr );
- if( g_object_class_find_property(
- G_OBJECT_GET_CLASS(pSettings), "gtk-primary-button-warps-slider") )
- {
- g_object_get( pSettings,
- "gtk-primary-button-warps-slider", &primarybuttonwarps,
- nullptr );
- }
- aStyleSet.SetPreferredUseImagesInMenus(showmenuicons);
- aStyleSet.SetPrimaryButtonWarpsSlider(primarybuttonwarps);
-
- // set scrollbar settings
- gint slider_width = 14;
- gint trough_border = 1;
- gint min_slider_length = 21;
-
- // Grab some button style attributes
- gtk_widget_style_get( gWidgetData[m_nXScreen].gScrollHorizWidget,
- "slider-width", &slider_width,
- "trough-border", &trough_border,
- "min-slider-length", &min_slider_length,
- nullptr );
- gint magic = trough_border ? 1 : 0;
- aStyleSet.SetScrollBarSize( slider_width + 2*trough_border );
- aStyleSet.SetMinThumbSize( min_slider_length - magic );
-
- // preferred icon style
- gchar* pIconThemeName = nullptr;
- g_object_get( pSettings, "gtk-icon-theme-name", &pIconThemeName, nullptr );
- aStyleSet.SetPreferredIconTheme( OUString::createFromAscii( pIconThemeName ) );
- g_free( pIconThemeName );
-
- aStyleSet.SetToolbarIconSize( ToolbarIconSize::Large );
-
- // finally update the collected settings
- rSettings.SetStyleSettings( aStyleSet );
-
- return true;
-}
-
-/************************************************************************
- * Create a GdkPixmap filled with the contents of an area of an Xlib window
- ************************************************************************/
-
-std::unique_ptr<GdkX11Pixmap> GtkSalGraphics::NWGetPixmapFromScreen( tools::Rectangle srcRect, int nBgColor )
-{
- int nDepth = vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetVisual( m_nXScreen ).GetDepth();
-
- std::unique_ptr<GdkX11Pixmap> pPixmap(new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), nDepth ));
-
- if( nBgColor == BG_FILL )
- {
- FillPixmapFromScreen( pPixmap.get(), srcRect.Left(), srcRect.Top() );
- }
- else if( nBgColor != BG_NONE )
- {
- cairo_t *cr = gdk_cairo_create( pPixmap->GetGdkDrawable() );
- if( nBgColor == BG_BLACK)
- cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
- else
- cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_paint (cr);
- cairo_destroy(cr);
- }
-
- return pPixmap;
-}
-
-/************************************************************************
- * Copy an alpha pixmap to screen using a gc with clipping
- ************************************************************************/
-
-bool GtkSalGraphics::NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask, tools::Rectangle dstRect )
-{
- return RenderPixmapToScreen( pPixmap, pMask, dstRect.Left(), dstRect.Top() );
-}
-
-/************************************************************************
- * State conversion
- ************************************************************************/
-static void NWConvertVCLStateToGTKState( ControlState nVCLState,
- GtkStateType* nGTKState, GtkShadowType* nGTKShadow )
-{
- *nGTKShadow = GTK_SHADOW_OUT;
- *nGTKState = GTK_STATE_INSENSITIVE;
-
- if ( nVCLState & ControlState::ENABLED )
- {
- if ( nVCLState & ControlState::PRESSED )
- {
- *nGTKState = GTK_STATE_ACTIVE;
- *nGTKShadow = GTK_SHADOW_IN;
- }
- else if ( nVCLState & ControlState::ROLLOVER )
- {
- *nGTKState = GTK_STATE_PRELIGHT;
- *nGTKShadow = GTK_SHADOW_OUT;
- }
- else
- {
- *nGTKState = GTK_STATE_NORMAL;
- *nGTKShadow = GTK_SHADOW_OUT;
- }
- }
-}
-
-/************************************************************************
- * Set widget flags
- ************************************************************************/
-static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState )
-{
- // Set to default state, then build up from there
- GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_DEFAULT );
- GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_FOCUS );
- GTK_WIDGET_UNSET_FLAGS( widget, GTK_SENSITIVE );
- GTK_WIDGET_SET_FLAGS( widget, gWidgetDefaultFlags[reinterpret_cast<long>(widget)] );
-
- if ( nState & ControlState::DEFAULT )
- GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_DEFAULT );
- if ( !GTK_IS_TOGGLE_BUTTON(widget) && (nState & ControlState::FOCUSED) )
- GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_FOCUS );
- if ( nState & ControlState::ENABLED )
- GTK_WIDGET_SET_FLAGS( widget, GTK_SENSITIVE );
- gtk_widget_set_state( widget, nGtkState );
-}
-
-/************************************************************************
- * Widget ensure functions - make sure cached objects are valid
- ************************************************************************/
-
-static void NWAddWidgetToCacheWindow( GtkWidget* widget, SalX11Screen nScreen )
-{
- NWFWidgetData& rData = gWidgetData[nScreen];
- if ( !rData.gCacheWindow || !rData.gDumbContainer )
- {
- if ( !rData.gCacheWindow )
- {
- rData.gCacheWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
- g_object_set_data( G_OBJECT( rData.gCacheWindow ), "libo-version",
- const_cast<char *>(LIBO_VERSION_DOTTED) );
-
- GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(),
- nScreen.getXScreen() );
- if( pScreen )
- gtk_window_set_screen( GTK_WINDOW(rData.gCacheWindow), pScreen );
- }
- if ( !rData.gDumbContainer )
- rData.gDumbContainer = gtk_fixed_new();
- gtk_container_add( GTK_CONTAINER(rData.gCacheWindow), rData.gDumbContainer );
- gtk_widget_realize( rData.gDumbContainer );
- gtk_widget_realize( rData.gCacheWindow );
- }
-
- gtk_container_add( GTK_CONTAINER(rData.gDumbContainer), widget );
- gtk_widget_realize( widget );
- gtk_widget_ensure_style( widget );
-
- // Store widget's default flags
- gWidgetDefaultFlags[ reinterpret_cast<long>(widget) ] = GTK_WIDGET_FLAGS( widget );
-}
-
-static void NWEnsureGTKButton( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gBtnWidget )
- {
- gWidgetData[nScreen].gBtnWidget = gtk_button_new_with_label( "" );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gBtnWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKRadio( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gRadioWidget || !gWidgetData[nScreen].gRadioWidgetSibling )
- {
- gWidgetData[nScreen].gRadioWidget = gtk_radio_button_new( nullptr );
- gWidgetData[nScreen].gRadioWidgetSibling = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(gWidgetData[nScreen].gRadioWidget) );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidget, nScreen );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidgetSibling, nScreen );
- }
-}
-
-static void NWEnsureGTKCheck( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gCheckWidget )
- {
- gWidgetData[nScreen].gCheckWidget = gtk_check_button_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gCheckWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKScrollbars( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gScrollHorizWidget )
- {
- gWidgetData[nScreen].gScrollHorizWidget = gtk_hscrollbar_new( nullptr );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollHorizWidget, nScreen );
- }
-
- if ( !gWidgetData[nScreen].gScrollVertWidget )
- {
- gWidgetData[nScreen].gScrollVertWidget = gtk_vscrollbar_new( nullptr );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollVertWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKArrow( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gArrowWidget || !gWidgetData[nScreen].gDropdownWidget )
- {
- gWidgetData[nScreen].gDropdownWidget = gtk_toggle_button_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gDropdownWidget, nScreen );
- gWidgetData[nScreen].gArrowWidget = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
- gtk_container_add( GTK_CONTAINER(gWidgetData[nScreen].gDropdownWidget), gWidgetData[nScreen].gArrowWidget );
- gtk_widget_set_rc_style( gWidgetData[nScreen].gArrowWidget );
- gtk_widget_realize( gWidgetData[nScreen].gArrowWidget );
- }
-}
-
-static void NWEnsureGTKEditBox( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gEditBoxWidget )
- {
- gWidgetData[nScreen].gEditBoxWidget = gtk_entry_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gEditBoxWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKSpinButton( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gSpinButtonWidget )
- {
- GtkAdjustment *adj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 1, 1, 1, 0) );
- gWidgetData[nScreen].gSpinButtonWidget = gtk_spin_button_new( adj, 1, 2 );
-
- //Setting non-editable means it doesn't blink, so there's no timeouts
- //running around to nobble us
- gtk_editable_set_editable(GTK_EDITABLE(gWidgetData[nScreen].gSpinButtonWidget), false);
-
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gSpinButtonWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKNotebook( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gNotebookWidget )
- {
- gWidgetData[nScreen].gNotebookWidget = gtk_notebook_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gNotebookWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKOptionMenu( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gOptionMenuWidget )
- {
- gWidgetData[nScreen].gOptionMenuWidget = gtk_option_menu_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gOptionMenuWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKCombo( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gComboWidget )
- {
- gWidgetData[nScreen].gComboWidget = gtk_combo_new();
-
- // #i59129# Setting non-editable means it doesn't blink, so
- // there are no timeouts running around to nobble us
- gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry), false);
-
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gComboWidget, nScreen );
- // Must realize the ComboBox's children, since GTK
- // does not do this for us in GtkCombo::gtk_widget_realize()
- gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->button );
- gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry );
- }
-}
-
-static void NWEnsureGTKScrolledWindow( SalX11Screen nScreen )
-{
- if ( !gWidgetData[nScreen].gScrolledWindowWidget )
- {
- GtkAdjustment *hadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
- GtkAdjustment *vadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
-
- gWidgetData[nScreen].gScrolledWindowWidget = gtk_scrolled_window_new( hadj, vadj );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrolledWindowWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKToolbar( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gToolbarWidget )
- {
- gWidgetData[nScreen].gToolbarWidget = gtk_toolbar_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarWidget, nScreen );
- gWidgetData[nScreen].gToolbarButtonWidget = GTK_WIDGET(gtk_toggle_button_new());
- gWidgetData[nScreen].gSeparator = GTK_WIDGET(gtk_separator_tool_item_new());
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gSeparator, nScreen );
-
- GtkReliefStyle aRelief = GTK_RELIEF_NORMAL;
- gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarWidget );
- gtk_widget_style_get( gWidgetData[nScreen].gToolbarWidget,
- "button_relief", &aRelief,
- nullptr);
-
- gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarButtonWidget), aRelief );
- GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_FOCUS );
- GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_DEFAULT );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarButtonWidget, nScreen );
-
- }
- if( ! gWidgetData[nScreen].gHandleBoxWidget )
- {
- gWidgetData[nScreen].gHandleBoxWidget = gtk_handle_box_new();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHandleBoxWidget, nScreen );
- }
-}
-
-static void NWEnsureGTKMenubar( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gMenubarWidget )
- {
- gWidgetData[nScreen].gMenubarWidget = gtk_menu_bar_new();
- gWidgetData[nScreen].gMenuItemMenubarWidget = gtk_menu_item_new_with_label( "b" );
- gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenubarWidget ), gWidgetData[nScreen].gMenuItemMenubarWidget );
- gtk_widget_show( gWidgetData[nScreen].gMenuItemMenubarWidget );
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gMenubarWidget, nScreen );
- gtk_widget_show( gWidgetData[nScreen].gMenubarWidget );
-
- // do what NWAddWidgetToCacheWindow does except adding to def container
- gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenubarWidget );
- gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenubarWidget );
-
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gMenuItemMenubarWidget) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenubarWidget );
- }
-}
-
-static void NWEnsureGTKMenu( SalX11Screen nScreen )
-{
- if( gWidgetData[nScreen].gMenuWidget )
- return;
-
- gWidgetData[nScreen].gMenuWidget = gtk_menu_new();
- gWidgetData[nScreen].gMenuItemMenuWidget = gtk_menu_item_new_with_label( "b" );
- gWidgetData[nScreen].gMenuItemCheckMenuWidget = gtk_check_menu_item_new_with_label( "b" );
- gWidgetData[nScreen].gMenuItemRadioMenuWidget = gtk_radio_menu_item_new_with_label( nullptr, "b" );
- gWidgetData[nScreen].gMenuItemSeparatorMenuWidget = gtk_separator_menu_item_new();
- gWidgetData[nScreen].gImageMenuItem = gtk_image_menu_item_new();
-
- g_object_ref_sink (gWidgetData[nScreen].gMenuWidget);
-
- gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemMenuWidget );
- gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemCheckMenuWidget );
- gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemRadioMenuWidget );
- gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemSeparatorMenuWidget );
- gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gImageMenuItem );
-
- // do what NWAddWidgetToCacheWindow does except adding to def container
- gtk_widget_realize( gWidgetData[nScreen].gMenuWidget );
- gtk_widget_ensure_style( gWidgetData[nScreen].gMenuWidget );
-
- gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenuWidget );
- gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenuWidget );
-
- gtk_widget_realize( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
- gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
-
- gtk_widget_realize( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
- gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
-
- gtk_widget_realize( gWidgetData[nScreen].gMenuItemSeparatorMenuWidget );
- gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemSeparatorMenuWidget );
-
- gtk_widget_realize( gWidgetData[nScreen].gImageMenuItem );
- gtk_widget_ensure_style( gWidgetData[nScreen].gImageMenuItem );
-
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gMenuWidget) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuWidget );
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gMenuItemMenuWidget) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenuWidget );
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gMenuItemCheckMenuWidget) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gMenuItemRadioMenuWidget) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gMenuItemSeparatorMenuWidget) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemSeparatorMenuWidget );
- gWidgetDefaultFlags[ reinterpret_cast<long>(gWidgetData[nScreen].gImageMenuItem) ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gImageMenuItem );
-
-}
-
-static void NWEnsureGTKTooltip( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gTooltipPopup )
- {
- gWidgetData[nScreen].gTooltipPopup = gtk_window_new (GTK_WINDOW_POPUP);
- GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(),
- nScreen.getXScreen() );
- if( pScreen )
- gtk_window_set_screen( GTK_WINDOW(gWidgetData[nScreen].gTooltipPopup), pScreen );
- gtk_widget_set_name( gWidgetData[nScreen].gTooltipPopup, "gtk-tooltips");
- gtk_widget_realize( gWidgetData[nScreen].gTooltipPopup );
- gtk_widget_ensure_style( gWidgetData[nScreen].gTooltipPopup );
- }
-}
-
-static void NWEnsureGTKDialog( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gDialog )
- {
- gWidgetData[nScreen].gDialog = gtk_dialog_new();
- GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(),
- nScreen.getXScreen() );
- if( pScreen )
- gtk_window_set_screen( GTK_WINDOW(gWidgetData[nScreen].gDialog), pScreen );
- gtk_widget_realize(gWidgetData[nScreen].gDialog);
- gtk_widget_ensure_style(gWidgetData[nScreen].gDialog);
- }
-}
-
-static void NWEnsureGTKFrame( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gFrame )
- {
- gWidgetData[nScreen].gFrame = gtk_frame_new(nullptr);
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gFrame, nScreen );
- }
-}
-
-static void NWEnsureGTKProgressBar( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gProgressBar )
- {
- gWidgetData[nScreen].gProgressBar = gtk_progress_bar_new ();
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gProgressBar, nScreen );
- }
-}
-
-static void NWEnsureGTKTreeView( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gTreeView )
- {
- gWidgetData[nScreen].gTreeView = gtk_tree_view_new ();
-
- // Columns will be used for tree header rendering
- GtkCellRenderer* renderer=gtk_cell_renderer_text_new();
- GtkTreeViewColumn* column=gtk_tree_view_column_new_with_attributes("",renderer,"text",0,nullptr);
- gtk_tree_view_column_set_widget(column,gtk_label_new(""));
- gtk_tree_view_append_column(GTK_TREE_VIEW(gWidgetData[nScreen].gTreeView), column);
-
- // Add one more column so that some engines like clearlooks did render separators between columns
- column=gtk_tree_view_column_new_with_attributes("",renderer,"text",0,nullptr);
- gtk_tree_view_append_column(GTK_TREE_VIEW(gWidgetData[nScreen].gTreeView), column);
-
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gTreeView, nScreen );
- }
-}
-
-static void NWEnsureGTKSlider( SalX11Screen nScreen )
-{
- if( !gWidgetData[nScreen].gHScale )
- {
- gWidgetData[nScreen].gHScale = gtk_hscale_new_with_range(0, 10, 1);
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHScale, nScreen );
- }
- if( !gWidgetData[nScreen].gVScale )
- {
- gWidgetData[nScreen].gVScale = gtk_vscale_new_with_range(0, 10, 1);
- NWAddWidgetToCacheWindow( gWidgetData[nScreen].gVScale, nScreen );
- }
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/salprn-gtk.cxx b/vcl/unx/gtk/salprn-gtk.cxx
deleted file mode 100644
index e5e17a5ec9e1..000000000000
--- a/vcl/unx/gtk/salprn-gtk.cxx
+++ /dev/null
@@ -1,970 +0,0 @@
-/* -*- 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/.
- */
-
-#include <unx/gtk/gtkprintwrapper.hxx>
-
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkprn.hxx>
-
-#include <vcl/configsettings.hxx>
-#include <vcl/help.hxx>
-#include <vcl/print.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/window.hxx>
-
-#include <gtk/gtk.h>
-
-#include <com/sun/star/beans/PropertyValue.hpp>
-#include <com/sun/star/container/XNamed.hpp>
-#include <com/sun/star/document/XExporter.hpp>
-#include <com/sun/star/document/XFilter.hpp>
-#include <com/sun/star/frame/XFrame.hpp>
-#include <com/sun/star/io/XOutputStream.hpp>
-#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
-#include <com/sun/star/sheet/XSpreadsheet.hpp>
-#include <com/sun/star/sheet/XSpreadsheetView.hpp>
-#include <com/sun/star/view/PrintableState.hpp>
-#include <com/sun/star/view/XSelectionSupplier.hpp>
-
-#include <officecfg/Office/Common.hxx>
-
-#include <rtl/ustring.hxx>
-#include <sal/log.hxx>
-
-#include <unotools/streamwrap.hxx>
-
-#include <cstring>
-#include <map>
-
-namespace beans = com::sun::star::beans;
-namespace uno = com::sun::star::uno;
-namespace view = com::sun::star::view;
-
-using vcl::unx::GtkPrintWrapper;
-
-using uno::UNO_QUERY;
-
-class GtkPrintDialog
-{
-public:
- explicit GtkPrintDialog(vcl::PrinterController& io_rController);
- bool run();
- GtkPrinter* getPrinter() const
- {
- return m_xWrapper->print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(m_pDialog));
- }
- GtkPrintSettings* getSettings() const
- {
- return m_xWrapper->print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog));
- }
- void updateControllerPrintRange();
-
- ~GtkPrintDialog();
-
- static void UIOption_CheckHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis)
- {
- io_pThis->impl_UIOption_CheckHdl(i_pWidget);
- }
- static void UIOption_RadioHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis)
- {
- io_pThis->impl_UIOption_RadioHdl(i_pWidget);
- }
- static void UIOption_SelectHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis)
- {
- io_pThis->impl_UIOption_SelectHdl(i_pWidget);
- }
-
-private:
- beans::PropertyValue* impl_queryPropertyValue(GtkWidget* i_pWidget) const;
- void impl_checkOptionalControlDependencies();
-
- void impl_UIOption_CheckHdl(GtkWidget* i_pWidget);
- void impl_UIOption_RadioHdl(GtkWidget* i_pWidget);
- void impl_UIOption_SelectHdl(GtkWidget* i_pWidget);
-
- void impl_initDialog();
- void impl_initCustomTab();
- void impl_initPrintContent(uno::Sequence<sal_Bool> const& i_rDisabled);
-
- void impl_readFromSettings();
- void impl_storeToSettings() const;
-
-private:
- GtkWidget* m_pDialog;
- vcl::PrinterController& m_rController;
- std::map<GtkWidget*, OUString> m_aControlToPropertyMap;
- std::map<GtkWidget*, sal_Int32> m_aControlToNumValMap;
- std::shared_ptr<GtkPrintWrapper> m_xWrapper;
-};
-
-struct GtkSalPrinter_Impl
-{
- OString m_sSpoolFile;
- OUString m_sJobName;
- GtkPrinter* m_pPrinter;
- GtkPrintSettings* m_pSettings;
-
- GtkSalPrinter_Impl();
- ~GtkSalPrinter_Impl();
-};
-
-GtkSalPrinter_Impl::GtkSalPrinter_Impl()
- : m_pPrinter(nullptr)
- , m_pSettings(nullptr)
-{
-}
-
-GtkSalPrinter_Impl::~GtkSalPrinter_Impl()
-{
- if (m_pPrinter)
- {
- g_object_unref(G_OBJECT(m_pPrinter));
- m_pPrinter = nullptr;
- }
- if (m_pSettings)
- {
- g_object_unref(G_OBJECT(m_pSettings));
- m_pSettings = nullptr;
- }
-}
-
-namespace
-{
-
-GtkInstance const&
-lcl_getGtkSalInstance()
-{
- // we _know_ this is GtkInstance
- return *static_cast<GtkInstance*>(GetGtkSalData()->m_pInstance);
-}
-
-bool
-lcl_useSystemPrintDialog()
-{
- return officecfg::Office::Common::Misc::UseSystemPrintDialog::get()
- && officecfg::Office::Common::Misc::ExperimentalMode::get()
- && lcl_getGtkSalInstance().getPrintWrapper()->supportsPrinting();
-}
-
-}
-
-GtkSalPrinter::GtkSalPrinter(SalInfoPrinter* const i_pInfoPrinter)
- : PspSalPrinter(i_pInfoPrinter)
-{
-}
-
-GtkSalPrinter::~GtkSalPrinter() = default;
-
-bool
-GtkSalPrinter::impl_doJob(
- const OUString* const i_pFileName,
- const OUString& i_rJobName,
- const OUString& i_rAppName,
- ImplJobSetup* const io_pSetupData,
- const bool i_bCollate,
- vcl::PrinterController& io_rController)
-{
- io_rController.setJobState(view::PrintableState_JOB_STARTED);
- io_rController.jobStarted();
- const bool bJobStarted(
- PspSalPrinter::StartJob(i_pFileName, i_rJobName, i_rAppName,
- 1/*i_nCopies*/, i_bCollate, true, io_pSetupData))
- ;
-
- if (bJobStarted)
- {
- io_rController.createProgressDialog();
- const int nPages(io_rController.getFilteredPageCount());
- for (int nPage(0); nPage != nPages; ++nPage)
- {
- if (nPage == nPages - 1)
- io_rController.setLastPage(true);
- io_rController.printFilteredPage(nPage);
- }
- io_rController.setJobState(view::PrintableState_JOB_COMPLETED);
- }
-
- return bJobStarted;
-}
-
-bool
-GtkSalPrinter::StartJob(
- const OUString* const i_pFileName,
- const OUString& i_rJobName,
- const OUString& i_rAppName,
- ImplJobSetup* io_pSetupData,
- vcl::PrinterController& io_rController)
-{
- if (!lcl_useSystemPrintDialog())
- return PspSalPrinter::StartJob(i_pFileName, i_rJobName, i_rAppName, io_pSetupData, io_rController);
-
- assert(!m_xImpl);
-
- m_xImpl.reset(new GtkSalPrinter_Impl());
- m_xImpl->m_sJobName = i_rJobName;
-
- OString sFileName;
- if (i_pFileName)
- sFileName = OUStringToOString(*i_pFileName, osl_getThreadTextEncoding());
-
- GtkPrintDialog aDialog(io_rController);
- if (!aDialog.run())
- {
- io_rController.abortJob();
- return false;
- }
- aDialog.updateControllerPrintRange();
- m_xImpl->m_pPrinter = aDialog.getPrinter();
- m_xImpl->m_pSettings = aDialog.getSettings();
-
- //To-Do proper name, watch for encodings
- sFileName = OString("/tmp/hacking.ps");
- m_xImpl->m_sSpoolFile = sFileName;
-
- OUString aFileName = OStringToOUString(sFileName, osl_getThreadTextEncoding());
-
- //To-Do, swap ps/pdf for gtk_printer_accepts_ps()/gtk_printer_accepts_pdf() ?
-
- return impl_doJob(&aFileName, i_rJobName, i_rAppName, io_pSetupData, /*bCollate*/false, io_rController);
-}
-
-bool
-GtkSalPrinter::EndJob()
-{
- bool bRet = PspSalPrinter::EndJob();
-
- if (!lcl_useSystemPrintDialog())
- return bRet;
-
- assert(m_xImpl);
-
- if (!bRet || m_xImpl->m_sSpoolFile.isEmpty())
- return bRet;
-
- std::shared_ptr<GtkPrintWrapper> const xWrapper(lcl_getGtkSalInstance().getPrintWrapper());
-
- GtkPageSetup* pPageSetup = xWrapper->page_setup_new();
-
- GtkPrintJob* const pJob = xWrapper->print_job_new(
- OUStringToOString(m_xImpl->m_sJobName, RTL_TEXTENCODING_UTF8).getStr(),
- m_xImpl->m_pPrinter, m_xImpl->m_pSettings, pPageSetup);
-
- GError* error = nullptr;
- bRet = xWrapper->print_job_set_source_file(pJob, m_xImpl->m_sSpoolFile.getStr(), &error);
- if (bRet)
- xWrapper->print_job_send(pJob, nullptr, nullptr, nullptr);
- else
- {
- //To-Do, do something with this
- fprintf(stderr, "error was %s\n", error->message);
- g_error_free(error);
- }
-
- g_object_unref(pPageSetup);
- m_xImpl.reset();
-
- //To-Do, remove temp spool file
-
- return bRet;
-}
-
-namespace
-{
-
-void
-lcl_setHelpText(
- GtkWidget* const io_pWidget,
- const uno::Sequence<OUString>& i_rHelpTexts,
- const sal_Int32 i_nIndex)
-{
- if (i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength())
- gtk_widget_set_tooltip_text(io_pWidget,
- OUStringToOString(i_rHelpTexts.getConstArray()[i_nIndex], RTL_TEXTENCODING_UTF8).getStr());
-}
-
-GtkWidget*
-lcl_makeFrame(
- GtkWidget* const i_pChild,
- const OUString &i_rText,
- const uno::Sequence<OUString> &i_rHelpTexts,
- sal_Int32* const io_pCurHelpText)
-{
- GtkWidget* const pLabel = gtk_label_new(nullptr);
- lcl_setHelpText(pLabel, i_rHelpTexts, !io_pCurHelpText ? 0 : (*io_pCurHelpText)++);
- gtk_misc_set_alignment(GTK_MISC(pLabel), 0.0, 0.5);
-
- {
- gchar* const pText = g_markup_printf_escaped("<b>%s</b>",
- OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr());
- gtk_label_set_markup_with_mnemonic(GTK_LABEL(pLabel), pText);
- g_free(pText);
- }
-
- GtkWidget* const pFrame = gtk_vbox_new(FALSE, 6);
- gtk_box_pack_start(GTK_BOX(pFrame), pLabel, FALSE, FALSE, 0);
-
- GtkWidget* const pAlignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(pAlignment), 0, 0, 12, 0);
- gtk_box_pack_start(GTK_BOX(pFrame), pAlignment, FALSE, FALSE, 0);
-
- gtk_container_add(GTK_CONTAINER(pAlignment), i_pChild);
- return pFrame;
-}
-
-void
-lcl_extractHelpTextsOrIds(
- const beans::PropertyValue& rEntry,
- uno::Sequence<OUString>& rHelpStrings)
-{
- if (!(rEntry.Value >>= rHelpStrings))
- {
- OUString aHelpString;
- if (rEntry.Value >>= aHelpString)
- {
- rHelpStrings.realloc(1);
- *rHelpStrings.getArray() = aHelpString;
- }
- }
-}
-
-GtkWidget*
-lcl_combo_box_text_new()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- return gtk_combo_box_text_new();
-#else
- return gtk_combo_box_new_text();
-#endif
-}
-
-void
-lcl_combo_box_text_append(GtkWidget* const pWidget, gchar const* const pText)
-{
-#if GTK_CHECK_VERSION(3,0,0)
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pWidget), pText);
-#else
- gtk_combo_box_append_text(GTK_COMBO_BOX(pWidget), pText);
-#endif
-}
-
-}
-
-GtkPrintDialog::GtkPrintDialog(vcl::PrinterController& io_rController)
- : m_rController(io_rController)
- , m_xWrapper(lcl_getGtkSalInstance().getPrintWrapper())
-{
- assert(m_xWrapper->supportsPrinting());
- impl_initDialog();
- impl_initCustomTab();
- impl_readFromSettings();
-}
-
-void
-GtkPrintDialog::impl_initDialog()
-{
- //To-Do, like fpicker, set UI language
- m_pDialog = m_xWrapper->print_unix_dialog_new();
-
- vcl::Window* const pTopWindow(Application::GetActiveTopWindow());
- if (pTopWindow)
- {
- GtkSalFrame* const pFrame(dynamic_cast<GtkSalFrame*>(pTopWindow->ImplGetFrame()));
- if (pFrame)
- {
- GtkWindow* const pParent(GTK_WINDOW(pFrame->getWindow()));
- if (pParent)
- gtk_window_set_transient_for(GTK_WINDOW(m_pDialog), pParent);
- }
- }
-
- m_xWrapper->print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(m_pDialog),
- GtkPrintCapabilities(GTK_PRINT_CAPABILITY_COPIES
- | GTK_PRINT_CAPABILITY_COLLATE
- | GTK_PRINT_CAPABILITY_REVERSE
- | GTK_PRINT_CAPABILITY_GENERATE_PS
- | GTK_PRINT_CAPABILITY_NUMBER_UP
- | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT
- ));
-}
-
-void
-GtkPrintDialog::impl_initCustomTab()
-{
- typedef std::vector<std::pair<GtkWidget*, OUString> > CustomTabs_t;
-
- const uno::Sequence<beans::PropertyValue>& rOptions(m_rController.getUIOptions());
- std::map<OUString, GtkWidget*> aPropertyToDependencyRowMap;
- CustomTabs_t aCustomTabs;
- GtkWidget* pCurParent = nullptr;
- GtkWidget* pCurTabPage = nullptr;
- GtkWidget* pCurSubGroup = nullptr;
- bool bIgnoreSubgroup = false;
- for (const auto& rOption : rOptions)
- {
- uno::Sequence<beans::PropertyValue> aOptProp;
- rOption.Value >>= aOptProp;
-
- OUString aCtrlType;
- OUString aText;
- OUString aPropertyName;
- uno::Sequence<OUString> aChoices;
- uno::Sequence<sal_Bool> aChoicesDisabled;
- uno::Sequence<OUString> aHelpTexts;
- sal_Int64 nMinValue = 0, nMaxValue = 0;
- sal_Int32 nCurHelpText = 0;
- OUString aDependsOnName;
- sal_Int32 nDependsOnValue = 0;
- bool bUseDependencyRow = false;
- bool bIgnore = false;
- GtkWidget* pGroup = nullptr;
- bool bGtkInternal = false;
-
- //Fix fdo#69381
- //Next options if this one is empty
- if (!aOptProp.hasElements())
- continue;
-
- for (const beans::PropertyValue& rEntry : std::as_const(aOptProp))
- {
- if ( rEntry.Name == "Text" )
- {
- OUString aValue;
- rEntry.Value >>= aValue;
- aText = aValue.replace('~', '_');
- }
- else if ( rEntry.Name == "ControlType" )
- rEntry.Value >>= aCtrlType;
- else if ( rEntry.Name == "Choices" )
- rEntry.Value >>= aChoices;
- else if ( rEntry.Name == "ChoicesDisabled" )
- rEntry.Value >>= aChoicesDisabled;
- else if ( rEntry.Name == "Property" )
- {
- beans::PropertyValue aVal;
- rEntry.Value >>= aVal;
- aPropertyName = aVal.Name;
- }
- else if ( rEntry.Name == "DependsOnName" )
- rEntry.Value >>= aDependsOnName;
- else if ( rEntry.Name == "DependsOnEntry" )
- rEntry.Value >>= nDependsOnValue;
- else if ( rEntry.Name == "AttachToDependency" )
- rEntry.Value >>= bUseDependencyRow;
- else if ( rEntry.Name == "MinValue" )
- rEntry.Value >>= nMinValue;
- else if ( rEntry.Name == "MaxValue" )
- rEntry.Value >>= nMaxValue;
- else if ( rEntry.Name == "HelpId" )
- {
- uno::Sequence<OUString> aHelpIds;
- lcl_extractHelpTextsOrIds(rEntry, aHelpIds);
- Help* const pHelp = Application::GetHelp();
- if (pHelp)
- {
- const int nLen = aHelpIds.getLength();
- aHelpTexts.realloc(nLen);
- std::transform(aHelpIds.begin(), aHelpIds.end(), aHelpTexts.begin(),
- [&pHelp](const OUString& rHelpId) { return pHelp->GetHelpText(rHelpId, static_cast<weld::Widget*>(nullptr)); });
- }
- else // fallback
- aHelpTexts = aHelpIds;
- }
- else if ( rEntry.Name == "HelpText" )
- lcl_extractHelpTextsOrIds(rEntry, aHelpTexts);
- else if ( rEntry.Name == "InternalUIOnly" )
- rEntry.Value >>= bIgnore;
- else if ( rEntry.Name == "Enabled" )
- {
- // Ignore this. We use UIControlOptions::isUIOptionEnabled
- // to check whether a control should be enabled.
- }
- else if ( rEntry.Name == "GroupingHint" )
- {
- // Ignore this. We cannot add/modify controls to/on existing
- // tabs of the Gtk print dialog.
- }
- else
- {
- SAL_INFO("vcl.gtk", "unhandled UI option entry: " << rEntry.Name);
- }
- }
-
- if ( aPropertyName == "PrintContent" )
- bGtkInternal = true;
-
- if (aCtrlType == "Group" || !pCurParent)
- {
- pCurTabPage = gtk_vbox_new(FALSE, 12);
- gtk_container_set_border_width(GTK_CONTAINER(pCurTabPage), 6);
- lcl_setHelpText(pCurTabPage, aHelpTexts, 0);
-
- pCurParent = pCurTabPage;
- aCustomTabs.emplace_back(pCurTabPage, aText);
- }
- else if (aCtrlType == "Subgroup")
- {
- bIgnoreSubgroup = bIgnore;
- if (bIgnore)
- continue;
- pCurParent = gtk_vbox_new(FALSE, 12);
- gtk_container_set_border_width(GTK_CONTAINER(pCurParent), 0);
-
- pCurSubGroup = lcl_makeFrame(pCurParent, aText, aHelpTexts, nullptr);
- gtk_box_pack_start(GTK_BOX(pCurTabPage), pCurSubGroup, FALSE, FALSE, 0);
- }
- // special case: we need to map these to controls of the gtk print dialog
- else if (bGtkInternal)
- {
- if ( aPropertyName == "PrintContent" )
- {
- // What to print? And, more importantly, is there a selection?
- impl_initPrintContent(aChoicesDisabled);
- }
- }
- else if (bIgnoreSubgroup || bIgnore)
- continue;
- else
- {
- // change handlers for all the controls set up in this block
- // should be set _after_ the control has been made (in)active,
- // because:
- // 1. value of the property is _known_--we are using it to
- // _set_ the control, right?--no need to change it back .-)
- // 2. it may cause warning because the widget may not
- // have been placed in m_aControlToPropertyMap yet
-
- GtkWidget* pWidget = nullptr;
- beans::PropertyValue* pVal = nullptr;
- if (aCtrlType == "Bool" && pCurParent)
- {
- pWidget = gtk_check_button_new_with_mnemonic(
- OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr());
- lcl_setHelpText(pWidget, aHelpTexts, 0);
- m_aControlToPropertyMap[pWidget] = aPropertyName;
-
- bool bVal = false;
- pVal = m_rController.getValue(aPropertyName);
- if (pVal)
- pVal->Value >>= bVal;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget), bVal);
- gtk_widget_set_sensitive(pWidget,
- m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr);
- g_signal_connect(pWidget, "toggled", G_CALLBACK(GtkPrintDialog::UIOption_CheckHdl), this);
- }
- else if (aCtrlType == "Radio" && pCurParent)
- {
- GtkWidget* const pVbox = gtk_vbox_new(FALSE, 12);
- gtk_container_set_border_width(GTK_CONTAINER(pVbox), 0);
-
- if (!aText.isEmpty())
- pGroup = lcl_makeFrame(pVbox, aText, aHelpTexts, &nCurHelpText);
-
- sal_Int32 nSelectVal = 0;
- pVal = m_rController.getValue(aPropertyName);
- if (pVal && pVal->Value.hasValue())
- pVal->Value >>= nSelectVal;
-
- for (sal_Int32 m = 0; m != aChoices.getLength(); m++)
- {
- pWidget = gtk_radio_button_new_with_mnemonic_from_widget(
- GTK_RADIO_BUTTON(m == 0 ? nullptr : pWidget),
- OUStringToOString(aChoices[m].replace('~', '_'), RTL_TEXTENCODING_UTF8).getStr());
- lcl_setHelpText(pWidget, aHelpTexts, nCurHelpText++);
- m_aControlToPropertyMap[pWidget] = aPropertyName;
- m_aControlToNumValMap[pWidget] = m;
- GtkWidget* const pRow = gtk_hbox_new(FALSE, 12);
- gtk_box_pack_start(GTK_BOX(pVbox), pRow, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(pRow), pWidget, FALSE, FALSE, 0);
- aPropertyToDependencyRowMap[aPropertyName + OUString::number(m)] = pRow;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget), m == nSelectVal);
- gtk_widget_set_sensitive(pWidget,
- m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr);
- g_signal_connect(pWidget, "toggled",
- G_CALLBACK(GtkPrintDialog::UIOption_RadioHdl), this);
- }
-
- if (pGroup)
- pWidget = pGroup;
- else
- pWidget = pVbox;
- }
- else if ((aCtrlType == "List" ||
- aCtrlType == "Range" ||
- aCtrlType == "Edit"
- ) && pCurParent)
- {
- GtkWidget* const pHbox = gtk_hbox_new(FALSE, 12);
- gtk_container_set_border_width(GTK_CONTAINER(pHbox), 0);
-
- if ( aCtrlType == "List" )
- {
- pWidget = lcl_combo_box_text_new();
-
- for (const auto& rChoice : std::as_const(aChoices))
- {
- lcl_combo_box_text_append(pWidget,
- OUStringToOString(rChoice, RTL_TEXTENCODING_UTF8).getStr());
- }
-
- sal_Int32 nSelectVal = 0;
- pVal = m_rController.getValue(aPropertyName);
- if (pVal && pVal->Value.hasValue())
- pVal->Value >>= nSelectVal;
- gtk_combo_box_set_active(GTK_COMBO_BOX(pWidget), nSelectVal);
- g_signal_connect(pWidget, "changed", G_CALLBACK(GtkPrintDialog::UIOption_SelectHdl), this);
- }
- else if (aCtrlType == "Edit" && pCurParent)
- {
- pWidget = gtk_entry_new();
-
- OUString aCurVal;
- pVal = m_rController.getValue(aPropertyName);
- if (pVal && pVal->Value.hasValue())
- pVal->Value >>= aCurVal;
- gtk_entry_set_text(GTK_ENTRY(pWidget),
- OUStringToOString(aCurVal, RTL_TEXTENCODING_UTF8).getStr());
- }
- else if (aCtrlType == "Range" && pCurParent)
- {
- pWidget = gtk_spin_button_new_with_range(nMinValue, nMaxValue, 1.0);
-
- sal_Int64 nCurVal = 0;
- pVal = m_rController.getValue(aPropertyName);
- if (pVal && pVal->Value.hasValue())
- pVal->Value >>= nCurVal;
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(pWidget), nCurVal);
- }
-
- lcl_setHelpText(pWidget, aHelpTexts, 0);
- m_aControlToPropertyMap[pWidget] = aPropertyName;
-
- gtk_widget_set_sensitive(pWidget,
- m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr);
-
- if (!aText.isEmpty())
- {
- GtkWidget* const pLabel = gtk_label_new_with_mnemonic(
- OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr());
- gtk_label_set_mnemonic_widget(GTK_LABEL(pLabel), pWidget);
- gtk_box_pack_start(GTK_BOX(pHbox), pLabel, FALSE, FALSE, 0);
- }
-
- gtk_box_pack_start(GTK_BOX(pHbox), pWidget, FALSE, FALSE, 0);
-
- pWidget = pHbox;
-
- }
- else
- SAL_INFO("vcl.gtk", "unhandled option type: " << aCtrlType);
-
- GtkWidget* pRow = nullptr;
- if (pWidget)
- {
- if (bUseDependencyRow && !aDependsOnName.isEmpty())
- {
- pRow = aPropertyToDependencyRowMap[aDependsOnName + OUString::number(nDependsOnValue)];
- if (!pRow)
- {
- gtk_widget_destroy(pWidget);
- pWidget = nullptr;
- }
- }
- }
- if (pWidget)
- {
- if (!pRow)
- {
- pRow = gtk_hbox_new(FALSE, 12);
- gtk_box_pack_start(GTK_BOX(pCurParent), pRow, FALSE, FALSE, 0);
- }
- if (!pGroup)
- aPropertyToDependencyRowMap[aPropertyName + OUString::number(0)] = pRow;
- gtk_box_pack_start(GTK_BOX(pRow), pWidget, FALSE, FALSE, 0);
- }
- }
- }
-
- CustomTabs_t::const_reverse_iterator aEnd = aCustomTabs.rend();
- for (CustomTabs_t::const_reverse_iterator aI = aCustomTabs.rbegin(); aI != aEnd; ++aI)
- {
- gtk_widget_show_all(aI->first);
- m_xWrapper->print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(m_pDialog), aI->first,
- gtk_label_new(OUStringToOString(aI->second, RTL_TEXTENCODING_UTF8).getStr()));
- }
-}
-
-void
-GtkPrintDialog::impl_initPrintContent(uno::Sequence<sal_Bool> const& i_rDisabled)
-{
- SAL_WARN_IF(i_rDisabled.getLength() != 3, "vcl.gtk", "there is more choices than we expected");
- if (i_rDisabled.getLength() != 3)
- return;
-
- GtkPrintUnixDialog* const pDialog(GTK_PRINT_UNIX_DIALOG(m_pDialog));
-
- // XXX: This is a hack that depends on the number and the ordering of
- // the controls in the rDisabled sequence (cf. the initialization of
- // the "PrintContent" UI option in SwPrintUIOptions::SwPrintUIOptions,
- // sw/source/core/view/printdata.cxx)
- if (m_xWrapper->supportsPrintSelection() && !i_rDisabled[2])
- {
- m_xWrapper->print_unix_dialog_set_support_selection(pDialog, TRUE);
- m_xWrapper->print_unix_dialog_set_has_selection(pDialog, TRUE);
- }
-
- beans::PropertyValue* const pPrintContent(
- m_rController.getValue(OUString("PrintContent")));
-
- if (pPrintContent)
- {
- sal_Int32 nSelectionType(0);
- pPrintContent->Value >>= nSelectionType;
- GtkPrintSettings* const pSettings(getSettings());
- GtkPrintPages ePrintPages(GTK_PRINT_PAGES_ALL);
- switch (nSelectionType)
- {
- case 0:
- ePrintPages = GTK_PRINT_PAGES_ALL;
- break;
- case 1:
- ePrintPages = GTK_PRINT_PAGES_RANGES;
- break;
- case 2:
- if (m_xWrapper->supportsPrintSelection())
- ePrintPages = GTK_PRINT_PAGES_SELECTION;
- else
- SAL_INFO("vcl.gtk", "the application wants to print a selection, but the present gtk version does not support it");
- break;
- default:
- SAL_WARN("vcl.gtk", "unexpected selection type: " << nSelectionType);
- }
- m_xWrapper->print_settings_set_print_pages(pSettings, ePrintPages);
- m_xWrapper->print_unix_dialog_set_settings(pDialog, pSettings);
- g_object_unref(G_OBJECT(pSettings));
- }
-}
-
-void
-GtkPrintDialog::impl_checkOptionalControlDependencies()
-{
- for (auto& rEntry : m_aControlToPropertyMap)
- {
- gtk_widget_set_sensitive(rEntry.first, m_rController.isUIOptionEnabled(rEntry.second));
- }
-}
-
-beans::PropertyValue*
-GtkPrintDialog::impl_queryPropertyValue(GtkWidget* const i_pWidget) const
-{
- beans::PropertyValue* pVal(nullptr);
- std::map<GtkWidget*, OUString>::const_iterator aIt(m_aControlToPropertyMap.find(i_pWidget));
- if (aIt != m_aControlToPropertyMap.end())
- {
- pVal = m_rController.getValue(aIt->second);
- SAL_WARN_IF(!pVal, "vcl.gtk", "property value not found");
- }
- else
- {
- SAL_WARN("vcl.gtk", "changed control not in property map");
- }
- return pVal;
-}
-
-void
-GtkPrintDialog::impl_UIOption_CheckHdl(GtkWidget* const i_pWidget)
-{
- beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
- if (pVal)
- {
- const bool bVal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget));
- pVal->Value <<= bVal;
-
- impl_checkOptionalControlDependencies();
- }
-}
-
-void
-GtkPrintDialog::impl_UIOption_RadioHdl(GtkWidget* const i_pWidget)
-{
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget)))
- {
- beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
- std::map<GtkWidget*, sal_Int32>::const_iterator it = m_aControlToNumValMap.find(i_pWidget);
- if (pVal && it != m_aControlToNumValMap.end())
- {
-
- const sal_Int32 nVal = it->second;
- pVal->Value <<= nVal;
-
- impl_checkOptionalControlDependencies();
- }
- }
-}
-
-void
-GtkPrintDialog::impl_UIOption_SelectHdl(GtkWidget* const i_pWidget)
-{
- beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
- if (pVal)
- {
- const sal_Int32 nVal(gtk_combo_box_get_active(GTK_COMBO_BOX(i_pWidget)));
- pVal->Value <<= nVal;
-
- impl_checkOptionalControlDependencies();
- }
-}
-
-bool
-GtkPrintDialog::run()
-{
- bool bDoJob = false;
- bool bContinue = true;
- while (bContinue)
- {
- bContinue = false;
- const gint nStatus = gtk_dialog_run(GTK_DIALOG(m_pDialog));
- switch (nStatus)
- {
- case GTK_RESPONSE_HELP:
- fprintf(stderr, "To-Do: Help ?\n");
- bContinue = true;
- break;
- case GTK_RESPONSE_OK:
- bDoJob = true;
- break;
- default:
- break;
- }
- }
- gtk_widget_hide(m_pDialog);
- impl_storeToSettings();
- return bDoJob;
-}
-
-void
-GtkPrintDialog::updateControllerPrintRange()
-{
- GtkPrintSettings* const pSettings(getSettings());
- // TODO: use get_print_pages
- if (const gchar* const pStr = m_xWrapper->print_settings_get(pSettings, GTK_PRINT_SETTINGS_PRINT_PAGES))
- {
- beans::PropertyValue* pVal = m_rController.getValue(OUString("PrintRange"));
- if (!pVal)
- pVal = m_rController.getValue(OUString("PrintContent"));
- SAL_WARN_IF(!pVal, "vcl.gtk", "Nothing to map standard print options to!");
- if (pVal)
- {
- sal_Int32 nVal = 0;
- if (!strcmp(pStr, "all"))
- nVal = 0;
- else if (!strcmp(pStr, "ranges"))
- nVal = 1;
- else if (!strcmp(pStr, "selection"))
- nVal = 2;
- pVal->Value <<= nVal;
-
- if (nVal == 1)
- {
- pVal = m_rController.getValue(OUString("PageRange"));
- SAL_WARN_IF(!pVal, "vcl.gtk", "PageRange doesn't exist!");
- if (pVal)
- {
- OUStringBuffer sBuf;
- gint num_ranges;
- const GtkPageRange* const pRanges = m_xWrapper->print_settings_get_page_ranges(pSettings, &num_ranges);
- for (gint i = 0; i != num_ranges && pRanges; ++i)
- {
- sBuf.append(sal_Int32(pRanges[i].start+1));
- if (pRanges[i].start != pRanges[i].end)
- {
- sBuf.append('-');
- sBuf.append(sal_Int32(pRanges[i].end+1));
- }
-
- if (i != num_ranges-1)
- sBuf.append(',');
- }
- pVal->Value <<= sBuf.makeStringAndClear();
- }
- }
- }
- }
- g_object_unref(G_OBJECT(pSettings));
-}
-
-GtkPrintDialog::~GtkPrintDialog()
-{
- gtk_widget_destroy(m_pDialog);
-}
-
-void
-GtkPrintDialog::impl_readFromSettings()
-{
- vcl::SettingsConfigItem* const pItem(vcl::SettingsConfigItem::get());
- GtkPrintSettings* const pSettings(getSettings());
-
- const OUString aPrintDialogStr("PrintDialog");
- const OUString aCopyCount(pItem->getValue(aPrintDialogStr,
- "CopyCount"));
- const OUString aCollate(pItem->getValue(aPrintDialogStr,
- "Collate"));
-
- const gint nOldCopyCount(m_xWrapper->print_settings_get_n_copies(pSettings));
- const sal_Int32 nCopyCount(aCopyCount.toInt32());
- if (nCopyCount > 0 && nOldCopyCount != nCopyCount)
- {
- m_xWrapper->print_settings_set_n_copies(pSettings, sal::static_int_cast<gint>(nCopyCount));
- }
-
- const bool bOldCollate(m_xWrapper->print_settings_get_collate(pSettings));
- const bool bCollate(aCollate.equalsIgnoreAsciiCase("true"));
- if (bOldCollate != bCollate)
- {
- m_xWrapper->print_settings_set_collate(pSettings, bCollate);
- }
-
- m_xWrapper->print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog), pSettings);
- g_object_unref(G_OBJECT(pSettings));
-}
-
-void
-GtkPrintDialog::impl_storeToSettings()
-const
-{
- vcl::SettingsConfigItem* const pItem(vcl::SettingsConfigItem::get());
- GtkPrintSettings* const pSettings(getSettings());
-
- const OUString aPrintDialogStr("PrintDialog");
- pItem->setValue(aPrintDialogStr,
- "CopyCount",
- OUString::number(m_xWrapper->print_settings_get_n_copies(pSettings)));
- pItem->setValue(aPrintDialogStr,
- "Collate",
- m_xWrapper->print_settings_get_collate(pSettings)
- ? OUString("true")
- : OUString("false"))
- ;
- // pItem->setValue(aPrintDialog, OUString("ToFile"), );
- g_object_unref(G_OBJECT(pSettings));
- pItem->Commit();
-}
-
-sal_uInt32
-GtkSalInfoPrinter::GetCapabilities(
- const ImplJobSetup* const i_pSetupData,
- const PrinterCapType i_nType)
-{
- if (i_nType == PrinterCapType::ExternalDialog && lcl_useSystemPrintDialog())
- return 1;
- return PspSalInfoPrinter::GetCapabilities(i_pSetupData, i_nType);
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/xid_fullscreen_on_all_monitors.c b/vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
deleted file mode 100644
index 558ede597a48..000000000000
--- a/vcl/unx/gtk/xid_fullscreen_on_all_monitors.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- 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/.
- */
-
-#include <dlfcn.h>
-#include <stdlib.h>
-
-typedef int Window;
-typedef union _GdkEvent GdkEvent;
-typedef struct _GdkWindow GdkWindow;
-typedef struct _GdkDisplay GdkDisplay;
-typedef struct _GdkScreen GdkScreen;
-
-typedef enum
-{
- GDK_FULLSCREEN_ON_CURRENT_MONITOR,
- GDK_FULLSCREEN_ON_ALL_MONITORS
-} GdkFullscreenMode;
-
-int main(int argc, char *argv[])
-{
- void *handle;
- void (*gtk_init)(int*, char***);
- GdkWindow* (*gdk_x11_window_foreign_new_for_display)(GdkDisplay*, Window);
- GdkDisplay* (*gdk_display_get_default)(void);
- GdkEvent* (*gdk_event_get)(void);
- void (*gtk_main_do_event)(GdkEvent*);
- void (*gdk_event_free)(GdkEvent*);
- void (*gdk_window_fullscreen)(GdkWindow *);
- void (*gdk_window_set_fullscreen_mode)(GdkWindow *, GdkFullscreenMode);
-
- GdkEvent *event;
- GdkWindow *window;
- int windowid;
- int spanmonitors;
-
- handle = dlopen("libgtk-3.so.0", RTLD_LAZY);
- if( NULL == handle )
- return -1;
-
- gtk_init = (void (*) (int*, char***))
- dlsym(handle, "gtk_init");
- gdk_x11_window_foreign_new_for_display = (GdkWindow* (*)(GdkDisplay*, Window))
- dlsym(handle, "gdk_x11_window_foreign_new_for_display");
- gdk_display_get_default = (GdkDisplay* (*)(void))
- dlsym(handle, "gdk_display_get_default");
- gdk_event_get = (GdkEvent* (*)(void))
- dlsym(handle, "gdk_event_get");
- gtk_main_do_event = (void (*)(GdkEvent*))
- dlsym(handle, "gtk_main_do_event");
- gdk_event_free = (void (*)(GdkEvent*))
- dlsym(handle, "gdk_event_free");
- gdk_window_fullscreen = (void (*)(GdkWindow *))
- dlsym(handle, "gdk_window_fullscreen");
- gdk_window_set_fullscreen_mode = (void (*)(GdkWindow *, GdkFullscreenMode))
- dlsym(handle, "gdk_window_set_fullscreen_mode");
-
- if (!gtk_init ||
- !gdk_x11_window_foreign_new_for_display ||
- !gdk_display_get_default ||
- !gdk_event_get ||
- !gtk_main_do_event ||
- !gdk_event_free ||
- !gdk_window_fullscreen ||
- !gdk_window_set_fullscreen_mode)
- {
- dlclose(handle);
- return -1;
- }
-
- gtk_init(&argc, &argv);
-
- windowid = atoi(argv[1]);
- spanmonitors = atoi(argv[2]);
-
- window = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), windowid);
- if (!window)
- {
- dlclose(handle);
- return -1;
- }
-
- gdk_window_set_fullscreen_mode(window, spanmonitors ? GDK_FULLSCREEN_ON_ALL_MONITORS : GDK_FULLSCREEN_ON_CURRENT_MONITOR);
- gdk_window_fullscreen(window);
-
- while ((event = gdk_event_get()) != NULL)
- {
- gtk_main_do_event(event);
- gdk_event_free(event);
- }
-
- dlclose(handle);
- return 0;
-}
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
-
diff --git a/vcl/unx/gtk/a11y/TODO b/vcl/unx/gtk3/a11y/TODO
index 1048bd96ef75..1048bd96ef75 100644
--- a/vcl/unx/gtk/a11y/TODO
+++ b/vcl/unx/gtk3/a11y/TODO
diff --git a/vcl/unx/gtk/a11y/atkfactory.hxx b/vcl/unx/gtk3/a11y/atkfactory.hxx
index ac72b5897813..ac72b5897813 100644
--- a/vcl/unx/gtk/a11y/atkfactory.hxx
+++ b/vcl/unx/gtk3/a11y/atkfactory.hxx
diff --git a/vcl/unx/gtk/a11y/atklistener.hxx b/vcl/unx/gtk3/a11y/atklistener.hxx
index 58798d4439fb..58798d4439fb 100644
--- a/vcl/unx/gtk/a11y/atklistener.hxx
+++ b/vcl/unx/gtk3/a11y/atklistener.hxx
diff --git a/vcl/unx/gtk/a11y/atkregistry.hxx b/vcl/unx/gtk3/a11y/atkregistry.hxx
index b692290847d8..b692290847d8 100644
--- a/vcl/unx/gtk/a11y/atkregistry.hxx
+++ b/vcl/unx/gtk3/a11y/atkregistry.hxx
diff --git a/vcl/unx/gtk/a11y/atktextattributes.hxx b/vcl/unx/gtk3/a11y/atktextattributes.hxx
index f86c82f4fe09..f86c82f4fe09 100644
--- a/vcl/unx/gtk/a11y/atktextattributes.hxx
+++ b/vcl/unx/gtk3/a11y/atktextattributes.hxx
diff --git a/vcl/unx/gtk/a11y/atkutil.hxx b/vcl/unx/gtk3/a11y/atkutil.hxx
index cb4a005157a0..cb4a005157a0 100644
--- a/vcl/unx/gtk/a11y/atkutil.hxx
+++ b/vcl/unx/gtk3/a11y/atkutil.hxx
diff --git a/vcl/unx/gtk/a11y/atkwindow.hxx b/vcl/unx/gtk3/a11y/atkwindow.hxx
index 35a4bcedf486..35a4bcedf486 100644
--- a/vcl/unx/gtk/a11y/atkwindow.hxx
+++ b/vcl/unx/gtk3/a11y/atkwindow.hxx
diff --git a/vcl/unx/gtk/a11y/atkwrapper.hxx b/vcl/unx/gtk3/a11y/atkwrapper.hxx
index 8725e54ccf5b..7ae0379de9c3 100644
--- a/vcl/unx/gtk/a11y/atkwrapper.hxx
+++ b/vcl/unx/gtk3/a11y/atkwrapper.hxx
@@ -22,9 +22,7 @@
#include <atk/atk.h>
#include <gtk/gtk.h>
-#if GTK_CHECK_VERSION(3,0,0)
#include <gtk/gtk-a11y.h>
-#endif
#include <com/sun/star/accessibility/XAccessible.hpp>
extern "C" {
@@ -74,11 +72,7 @@ struct AtkObjectWrapper
struct AtkObjectWrapperClass
{
-#if GTK_CHECK_VERSION(3,0,0)
GtkWidgetAccessibleClass aParentClass;
-#else
- AtkObjectClass const aParentClass;
-#endif
};
GType atk_object_wrapper_get_type() G_GNUC_CONST;
diff --git a/vcl/unx/gtk3/a11y/gtk3atkaction.cxx b/vcl/unx/gtk3/a11y/gtk3atkaction.cxx
index a3fa632d08a1..81e743238d84 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkaction.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkaction.cxx
@@ -5,8 +5,271 @@
* 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 .
*/
-#include "../../gtk/a11y/atkaction.cxx"
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleAction.hpp>
+#include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
+
+#include <com/sun/star/awt/Key.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+
+#include <rtl/strbuf.hxx>
+#include <algorithm>
+#include <map>
+
+using namespace ::com::sun::star;
+
+// FIXME
+static G_CONST_RETURN gchar *
+getAsConst( const OString& rString )
+{
+ static const int nMax = 10;
+ static OString aUgly[nMax];
+ static int nIdx = 0;
+ nIdx = (nIdx + 1) % nMax;
+ aUgly[nIdx] = rString;
+ return aUgly[ nIdx ].getStr();
+}
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleAction>
+ getAction( AtkAction *action )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( action );
+
+ if( pWrap )
+ {
+ if( !pWrap->mpAction.is() )
+ {
+ pWrap->mpAction.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpAction;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleAction>();
+}
+
+extern "C" {
+
+static gboolean
+action_wrapper_do_action (AtkAction *action,
+ gint i)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleAction> pAction
+ = getAction( action );
+ if( pAction.is() )
+ return pAction->doAccessibleAction( i );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in doAccessibleAction()" );
+ }
+
+ return FALSE;
+}
+
+static gint
+action_wrapper_get_n_actions (AtkAction *action)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleAction> pAction
+ = getAction( action );
+ if( pAction.is() )
+ return pAction->getAccessibleActionCount();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleActionCount()" );
+ }
+
+ return 0;
+}
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_description (AtkAction *, gint)
+{
+ // GAIL implement this only for cells
+ g_warning( "Not implemented: get_description()" );
+ return "";
+}
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_localized_name (AtkAction *, gint)
+{
+ // GAIL doesn't implement this as well
+ g_warning( "Not implemented: get_localized_name()" );
+ return "";
+}
+
+#define ACTION_NAME_PAIR( OOoName, AtkName ) \
+ std::pair< const OUString, const gchar * > ( OUString( OOoName ), AtkName )
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_name (AtkAction *action,
+ gint i)
+{
+ static std::map< OUString, const gchar * > aNameMap;
+
+ if( aNameMap.empty() )
+ {
+ aNameMap.insert( ACTION_NAME_PAIR( "click", "click" ) );
+ aNameMap.insert( ACTION_NAME_PAIR( "select", "click" ) );
+ aNameMap.insert( ACTION_NAME_PAIR( "togglePopup", "push" ) );
+ }
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleAction> pAction
+ = getAction( action );
+ if( pAction.is() )
+ {
+ std::map< OUString, const gchar * >::iterator iter;
+
+ OUString aDesc( pAction->getAccessibleActionDescription( i ) );
+
+ iter = aNameMap.find( aDesc );
+ if( iter != aNameMap.end() )
+ return iter->second;
+
+ std::pair< const OUString, const gchar * > aNewVal( aDesc,
+ g_strdup( OUStringToConstGChar(aDesc) ) );
+
+ if( aNameMap.insert( aNewVal ).second )
+ return aNewVal.second;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleActionDescription()" );
+ }
+
+ return "";
+}
+
+/*
+* GNOME Expects a string in the format:
+*
+* <mnemonic>;<full-path>;<accelerator>
+*
+* The keybindings in <full-path> should be separated by ":"
+*/
+
+static void
+appendKeyStrokes(OStringBuffer& rBuffer, const uno::Sequence< awt::KeyStroke >& rKeyStrokes)
+{
+ for( const auto& rKeyStroke : rKeyStrokes )
+ {
+ if( rKeyStroke.Modifiers & awt::KeyModifier::SHIFT )
+ rBuffer.append("<Shift>");
+ if( rKeyStroke.Modifiers & awt::KeyModifier::MOD1 )
+ rBuffer.append("<Control>");
+ if( rKeyStroke.Modifiers & awt::KeyModifier::MOD2 )
+ rBuffer.append("<Alt>");
+
+ if( ( rKeyStroke.KeyCode >= awt::Key::A ) && ( rKeyStroke.KeyCode <= awt::Key::Z ) )
+ rBuffer.append( static_cast<sal_Char>( 'a' + ( rKeyStroke.KeyCode - awt::Key::A ) ) );
+ else
+ {
+ sal_Char c = '\0';
+
+ switch( rKeyStroke.KeyCode )
+ {
+ case awt::Key::TAB: c = '\t'; break;
+ case awt::Key::SPACE: c = ' '; break;
+ case awt::Key::ADD: c = '+'; break;
+ case awt::Key::SUBTRACT: c = '-'; break;
+ case awt::Key::MULTIPLY: c = '*'; break;
+ case awt::Key::DIVIDE: c = '/'; break;
+ case awt::Key::POINT: c = '.'; break;
+ case awt::Key::COMMA: c = ','; break;
+ case awt::Key::LESS: c = '<'; break;
+ case awt::Key::GREATER: c = '>'; break;
+ case awt::Key::EQUAL: c = '='; break;
+ case 0:
+ break;
+ default:
+ g_warning( "Unmapped KeyCode: %d", rKeyStroke.KeyCode );
+ break;
+ }
+
+ if( c != '\0' )
+ rBuffer.append( c );
+ else
+ {
+ // The KeyCode approach did not work, probably a non ascii character
+ // let's hope that there is a character given in KeyChar.
+ rBuffer.append( OUStringToGChar( OUString( rKeyStroke.KeyChar ) ) );
+ }
+ }
+ }
+}
+
+static G_CONST_RETURN gchar *
+action_wrapper_get_keybinding (AtkAction *action,
+ gint i)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleAction> pAction
+ = getAction( action );
+ if( pAction.is() )
+ {
+ uno::Reference< accessibility::XAccessibleKeyBinding > xBinding( pAction->getAccessibleActionKeyBinding( i ));
+
+ if( xBinding.is() )
+ {
+ OStringBuffer aRet;
+
+ sal_Int32 nmax = std::min( xBinding->getAccessibleKeyBindingCount(), sal_Int32(3) );
+ for( sal_Int32 n = 0; n < nmax; n++ )
+ {
+ appendKeyStrokes( aRet, xBinding->getAccessibleKeyBinding( n ) );
+
+ if( n < 2 )
+ aRet.append( ';' );
+ }
+
+ // !! FIXME !! remember keystroke in wrapper object ?
+ return getAsConst( aRet.makeStringAndClear() );
+ }
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in get_keybinding()" );
+ }
+
+ return "";
+}
+
+static gboolean
+action_wrapper_set_description (AtkAction *, gint, const gchar *)
+{
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+actionIfaceInit (AtkActionIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->do_action = action_wrapper_do_action;
+ iface->get_n_actions = action_wrapper_get_n_actions;
+ iface->get_description = action_wrapper_get_description;
+ iface->get_keybinding = action_wrapper_get_keybinding;
+ iface->get_name = action_wrapper_get_name;
+ iface->get_localized_name = action_wrapper_get_localized_name;
+ iface->set_description = action_wrapper_set_description;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkbridge.cxx b/vcl/unx/gtk3/a11y/gtk3atkbridge.cxx
index d8e087956067..0e2781cf8fd5 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkbridge.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkbridge.cxx
@@ -5,8 +5,33 @@
* 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 .
*/
-#include "../../gtk/a11y/atkbridge.cxx"
+#include <unx/gtk/atkbridge.hxx>
+#include <unx/gtk/gtkframe.hxx>
+
+#include "atkfactory.hxx"
+#include "atkutil.hxx"
+#include "atkwindow.hxx"
+
+bool InitAtkBridge()
+{
+ ooo_atk_util_ensure_event_listener();
+ return true;
+}
+
+void DeInitAtkBridge()
+{
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkcomponent.cxx b/vcl/unx/gtk3/a11y/gtk3atkcomponent.cxx
index e4eabec20fb8..e904b12ac610 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkcomponent.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkcomponent.cxx
@@ -5,8 +5,379 @@
* 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 .
*/
-#include "../../gtk/a11y/atkcomponent.cxx"
+#include "atkwrapper.hxx"
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <gtk/gtk.h>
+
+using namespace ::com::sun::star;
+
+static AtkObjectWrapper* getObjectWrapper(AtkComponent *pComponent)
+{
+ AtkObjectWrapper *pWrap = nullptr;
+ if (ATK_IS_OBJECT_WRAPPER(pComponent))
+ pWrap = ATK_OBJECT_WRAPPER(pComponent);
+ else if (GTK_IS_DRAWING_AREA(pComponent)) //when using a GtkDrawingArea as a custom widget in welded gtk3
+ {
+ GtkWidget* pDrawingArea = GTK_WIDGET(pComponent);
+ AtkObject* pAtkObject = gtk_widget_get_accessible(pDrawingArea);
+ pWrap = ATK_IS_OBJECT_WRAPPER(pAtkObject) ? ATK_OBJECT_WRAPPER(pAtkObject) : nullptr;
+ }
+ return pWrap;
+}
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleComponent>
+ getComponent(AtkObjectWrapper *pWrap)
+{
+ if (pWrap)
+ {
+ if (!pWrap->mpComponent.is())
+ pWrap->mpComponent.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ return pWrap->mpComponent;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleComponent>();
+}
+
+/*****************************************************************************/
+
+static awt::Point
+translatePoint( css::uno::Reference<accessibility::XAccessibleComponent> const & pComponent,
+ gint x, gint y, AtkCoordType t)
+{
+ awt::Point aOrigin( 0, 0 );
+ if( t == ATK_XY_SCREEN )
+ aOrigin = pComponent->getLocationOnScreen();
+ return awt::Point( x - aOrigin.X, y - aOrigin.Y );
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gboolean
+component_wrapper_grab_focus (AtkComponent *component)
+{
+ AtkObjectWrapper* obj = getObjectWrapper(component);
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
+ if (obj && obj->mpOrig)
+ return atk_component_grab_focus(ATK_COMPONENT(obj->mpOrig));
+
+ try
+ {
+ css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
+ = getComponent(obj);
+ if( pComponent.is() )
+ {
+ pComponent->grabFocus();
+ return TRUE;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ g_warning( "Exception in grabFocus()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_contains (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ AtkObjectWrapper* obj = getObjectWrapper(component);
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
+ if (obj && obj->mpOrig)
+ return atk_component_contains(ATK_COMPONENT(obj->mpOrig), x, y, coord_type);
+
+ try
+ {
+ css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
+ = getComponent(obj);
+ if( pComponent.is() )
+ return pComponent->containsPoint( translatePoint( pComponent, x, y, coord_type ) );
+ }
+ catch( const uno::Exception & )
+ {
+ g_warning( "Exception in containsPoint()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+component_wrapper_ref_accessible_at_point (AtkComponent *component,
+ gint x,
+ gint y,
+ AtkCoordType coord_type)
+{
+ AtkObjectWrapper* obj = getObjectWrapper(component);
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
+ if (obj && obj->mpOrig)
+ return atk_component_ref_accessible_at_point(ATK_COMPONENT(obj->mpOrig), x, y, coord_type);
+
+ try
+ {
+ css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
+ = getComponent(obj);
+
+ if( pComponent.is() )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible = pComponent->getAccessibleAtPoint(
+ translatePoint( pComponent, x, y, coord_type ) );
+ return atk_object_wrapper_ref( xAccessible );
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ g_warning( "Exception in getAccessibleAtPoint()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_get_position (AtkComponent *component,
+ gint *x,
+ gint *y,
+ AtkCoordType coord_type)
+{
+ AtkObjectWrapper* obj = getObjectWrapper(component);
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
+ if (obj && obj->mpOrig)
+ {
+ atk_component_get_extents(ATK_COMPONENT(obj->mpOrig), x, y, nullptr, nullptr, coord_type);
+ return;
+ }
+
+ try
+ {
+ css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
+ = getComponent(obj);
+ if( pComponent.is() )
+ {
+ awt::Point aPos;
+
+ if( coord_type == ATK_XY_SCREEN )
+ aPos = pComponent->getLocationOnScreen();
+ else
+ aPos = pComponent->getLocation();
+
+ *x = aPos.X;
+ *y = aPos.Y;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ g_warning( "Exception in getLocation[OnScreen]()" );
+ }
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_get_size (AtkComponent *component,
+ gint *width,
+ gint *height)
+{
+ AtkObjectWrapper* obj = getObjectWrapper(component);
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
+ if (obj && obj->mpOrig)
+ {
+ atk_component_get_extents(ATK_COMPONENT(obj->mpOrig), nullptr, nullptr, width, height, ATK_XY_WINDOW);
+ return;
+ }
+
+ try
+ {
+ css::uno::Reference<css::accessibility::XAccessibleComponent> pComponent
+ = getComponent(obj);
+ if( pComponent.is() )
+ {
+ awt::Size aSize = pComponent->getSize();
+ *width = aSize.Width;
+ *height = aSize.Height;
+ }
+ }
+ catch( const uno::Exception & )
+ {
+ g_warning( "Exception in getSize()" );
+ }
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_get_extents (AtkComponent *component,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coord_type)
+{
+ component_wrapper_get_position( component, x, y, coord_type );
+ component_wrapper_get_size( component, width, height );
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_set_extents (AtkComponent *, gint, gint, gint, gint, AtkCoordType)
+{
+ g_warning( "AtkComponent::set_extents unimplementable" );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_set_position (AtkComponent *, gint, gint, AtkCoordType)
+{
+ g_warning( "AtkComponent::set_position unimplementable" );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+component_wrapper_set_size (AtkComponent *, gint, gint)
+{
+ g_warning( "AtkComponent::set_size unimplementable" );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static AtkLayer
+component_wrapper_get_layer (AtkComponent *component)
+{
+ AtkRole role = atk_object_get_role( ATK_OBJECT( component ) );
+ AtkLayer layer = ATK_LAYER_WIDGET;
+
+ switch (role)
+ {
+ case ATK_ROLE_POPUP_MENU:
+ case ATK_ROLE_MENU_ITEM:
+ case ATK_ROLE_CHECK_MENU_ITEM:
+ case ATK_ROLE_SEPARATOR:
+ case ATK_ROLE_LIST_ITEM:
+ layer = ATK_LAYER_POPUP;
+ break;
+ case ATK_ROLE_MENU:
+ {
+ AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
+ if( atk_object_get_role( parent ) != ATK_ROLE_MENU_BAR )
+ layer = ATK_LAYER_POPUP;
+ }
+ break;
+
+ case ATK_ROLE_LIST:
+ {
+ AtkObject * parent = atk_object_get_parent( ATK_OBJECT( component ) );
+ if( atk_object_get_role( parent ) == ATK_ROLE_COMBO_BOX )
+ layer = ATK_LAYER_POPUP;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return layer;
+}
+
+/*****************************************************************************/
+
+static gint
+component_wrapper_get_mdi_zorder (AtkComponent *)
+{
+ // only needed for ATK_LAYER_MDI (not used) or ATK_LAYER_WINDOW (inherited from GAIL)
+ return G_MININT;
+}
+
+/*****************************************************************************/
+
+// This code is mostly stolen from libgail ..
+
+static guint
+component_wrapper_add_focus_handler (AtkComponent *component,
+ AtkFocusHandler handler)
+{
+ GSignalMatchType match_type;
+ gulong ret;
+ guint signal_id;
+
+ match_type = GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC);
+ signal_id = g_signal_lookup( "focus-event", ATK_TYPE_OBJECT );
+
+ ret = g_signal_handler_find( component, match_type, signal_id, 0, nullptr,
+ static_cast<gpointer>(&handler), nullptr);
+ if (!ret)
+ {
+ return g_signal_connect_closure_by_id (component,
+ signal_id, 0,
+ g_cclosure_new (
+ G_CALLBACK (handler), nullptr,
+ nullptr),
+ FALSE);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*****************************************************************************/
+
+static void
+component_wrapper_remove_focus_handler (AtkComponent *component,
+ guint handler_id)
+{
+ g_signal_handler_disconnect (component, handler_id);
+}
+
+/*****************************************************************************/
+
+} // extern "C"
+
+void
+componentIfaceInit (AtkComponentIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->add_focus_handler = component_wrapper_add_focus_handler;
+ iface->contains = component_wrapper_contains;
+ iface->get_extents = component_wrapper_get_extents;
+ iface->get_layer = component_wrapper_get_layer;
+ iface->get_mdi_zorder = component_wrapper_get_mdi_zorder;
+ iface->get_position = component_wrapper_get_position;
+ iface->get_size = component_wrapper_get_size;
+ iface->grab_focus = component_wrapper_grab_focus;
+ iface->ref_accessible_at_point = component_wrapper_ref_accessible_at_point;
+ iface->remove_focus_handler = component_wrapper_remove_focus_handler;
+ iface->set_extents = component_wrapper_set_extents;
+ iface->set_position = component_wrapper_set_position;
+ iface->set_size = component_wrapper_set_size;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkeditabletext.cxx b/vcl/unx/gtk3/a11y/gtk3atkeditabletext.cxx
index ea3f0895fb8e..49d3eb9ccfc9 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkeditabletext.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkeditabletext.cxx
@@ -5,8 +5,190 @@
* 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 .
*/
-#include "../../gtk/a11y/atkeditabletext.cxx"
+#include "atkwrapper.hxx"
+#include "atktextattributes.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ getEditableText( AtkEditableText *pEditableText )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pEditableText );
+ if( pWrap )
+ {
+ if( !pWrap->mpEditableText.is() )
+ {
+ pWrap->mpEditableText.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpEditableText;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleEditableText>();
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gboolean
+editable_text_wrapper_set_run_attributes( AtkEditableText *text,
+ AtkAttributeSet *attribute_set,
+ gint nStartOffset,
+ gint nEndOffset)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ {
+ uno::Sequence< beans::PropertyValue > aAttributeList;
+
+ if( attribute_set_map_to_property_values( attribute_set, aAttributeList ) )
+ return pEditableText->setAttributes(nStartOffset, nEndOffset, aAttributeList);
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in setAttributes()" );
+ }
+
+ return FALSE;
+}
+
+static void
+editable_text_wrapper_set_text_contents( AtkEditableText *text,
+ const gchar *string )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ {
+ OUString aString ( string, strlen(string), RTL_TEXTENCODING_UTF8 );
+ pEditableText->setText( aString );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in setText()" );
+ }
+}
+
+static void
+editable_text_wrapper_insert_text( AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *pos )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ {
+ OUString aString ( string, length, RTL_TEXTENCODING_UTF8 );
+ if( pEditableText->insertText( aString, *pos ) )
+ *pos += length;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in insertText()" );
+ }
+}
+
+static void
+editable_text_wrapper_cut_text( AtkEditableText *text,
+ gint start,
+ gint end )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ pEditableText->cutText( start, end );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in cutText()" );
+ }
+}
+
+static void
+editable_text_wrapper_delete_text( AtkEditableText *text,
+ gint start,
+ gint end )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ pEditableText->deleteText( start, end );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in deleteText()" );
+ }
+}
+
+static void
+editable_text_wrapper_paste_text( AtkEditableText *text,
+ gint pos )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ pEditableText->pasteText( pos );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in pasteText()" );
+ }
+}
+
+static void
+editable_text_wrapper_copy_text( AtkEditableText *text,
+ gint start,
+ gint end )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleEditableText>
+ pEditableText = getEditableText( text );
+ if( pEditableText.is() )
+ pEditableText->copyText( start, end );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in copyText()" );
+ }
+}
+
+} // extern "C"
+
+void
+editableTextIfaceInit (AtkEditableTextIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->set_text_contents = editable_text_wrapper_set_text_contents;
+ iface->insert_text = editable_text_wrapper_insert_text;
+ iface->copy_text = editable_text_wrapper_copy_text;
+ iface->cut_text = editable_text_wrapper_cut_text;
+ iface->delete_text = editable_text_wrapper_delete_text;
+ iface->paste_text = editable_text_wrapper_paste_text;
+ iface->set_run_attributes = editable_text_wrapper_set_run_attributes;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkfactory.cxx b/vcl/unx/gtk3/a11y/gtk3atkfactory.cxx
index c60db2fcc074..d7c8bf9f6289 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkfactory.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkfactory.cxx
@@ -5,8 +5,182 @@
* 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 .
+ */
+
+#include <unx/gtk/gtkframe.hxx>
+#include <vcl/window.hxx>
+#include "atkwrapper.hxx"
+#include "atkfactory.hxx"
+#include "atkregistry.hxx"
+
+using namespace ::com::sun::star;
+
+extern "C" {
+
+/*
+ * Instances of this dummy object class are returned whenever we have to
+ * create an AtkObject, but can't touch the OOo object anymore since it
+ * is already disposed.
+ */
+
+static AtkStateSet *
+noop_wrapper_ref_state_set( AtkObject * )
+{
+ AtkStateSet *state_set = atk_state_set_new();
+ atk_state_set_add_state( state_set, ATK_STATE_DEFUNCT );
+ return state_set;
+}
+
+static void
+atk_noop_object_wrapper_class_init(AtkNoOpObjectClass *klass)
+{
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
+ atk_class->ref_state_set = noop_wrapper_ref_state_set;
+}
+
+static GType
+atk_noop_object_wrapper_get_type()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo typeInfo =
+ {
+ sizeof (AtkNoOpObjectClass),
+ nullptr,
+ nullptr,
+ reinterpret_cast<GClassInitFunc>(atk_noop_object_wrapper_class_init),
+ nullptr,
+ nullptr,
+ sizeof (AtkObjectWrapper),
+ 0,
+ nullptr,
+ nullptr
+ } ;
+
+ type = g_type_register_static (ATK_TYPE_OBJECT, "OOoAtkNoOpObj", &typeInfo, GTypeFlags(0)) ;
+ }
+ return type;
+}
+
+static AtkObject*
+atk_noop_object_wrapper_new()
+{
+ AtkObject *accessible;
+
+ accessible = static_cast<AtkObject *>(g_object_new (atk_noop_object_wrapper_get_type(), nullptr));
+ g_return_val_if_fail (accessible != nullptr, nullptr);
+
+ accessible->role = ATK_ROLE_INVALID;
+ accessible->layer = ATK_LAYER_INVALID;
+
+ return accessible;
+}
+
+/*
+ * The wrapper factory
*/
-#include "../../gtk/a11y/atkfactory.cxx"
+static GType
+wrapper_factory_get_accessible_type()
+{
+ return atk_object_wrapper_get_type();
+}
+
+static AtkObject*
+wrapper_factory_create_accessible( GObject *obj )
+{
+ GtkWidget* pEventBox = gtk_widget_get_parent(GTK_WIDGET(obj));
+
+ // gail_container_real_remove_gtk tries to re-instantiate an accessible
+ // for a widget that is about to vanish ..
+ if (!pEventBox)
+ return atk_noop_object_wrapper_new();
+
+ GtkWidget* pTopLevelGrid = gtk_widget_get_parent(pEventBox);
+ if (!pTopLevelGrid)
+ return atk_noop_object_wrapper_new();
+
+ GtkWidget* pTopLevel = gtk_widget_get_parent(pTopLevelGrid);
+ if (!pTopLevel)
+ return atk_noop_object_wrapper_new();
+
+ GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(GTK_WINDOW(pTopLevel));
+ g_return_val_if_fail( pFrame != nullptr, nullptr );
+
+ vcl::Window* pFrameWindow = pFrame->GetWindow();
+ if( pFrameWindow )
+ {
+ vcl::Window* pWindow = pFrameWindow;
+
+ // skip accessible objects already exposed by the frame objects
+ if( WindowType::BORDERWINDOW == pWindow->GetType() )
+ pWindow = pFrameWindow->GetAccessibleChildWindow(0);
+
+ if( pWindow )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible = pWindow->GetAccessible();
+ if( xAccessible.is() )
+ {
+ AtkObject *accessible = ooo_wrapper_registry_get( xAccessible );
+
+ if( accessible )
+ g_object_ref( G_OBJECT(accessible) );
+ else
+ accessible = atk_object_wrapper_new( xAccessible, gtk_widget_get_accessible(pTopLevel) );
+
+ return accessible;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+AtkObject* ooo_fixed_get_accessible(GtkWidget *obj)
+{
+ return wrapper_factory_create_accessible(G_OBJECT(obj));
+}
+
+static void
+wrapper_factory_class_init( AtkObjectFactoryClass *klass )
+{
+ klass->create_accessible = wrapper_factory_create_accessible;
+ klass->get_accessible_type = wrapper_factory_get_accessible_type;
+}
+
+GType
+wrapper_factory_get_type()
+{
+ static GType t = 0;
+
+ if (!t) {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (AtkObjectFactoryClass),
+ nullptr, nullptr, reinterpret_cast<GClassInitFunc>(wrapper_factory_class_init),
+ nullptr, nullptr, sizeof (AtkObjectFactory), 0, nullptr, nullptr
+ };
+
+ t = g_type_register_static (
+ ATK_TYPE_OBJECT_FACTORY, "OOoAtkObjectWrapperFactory",
+ &tinfo, GTypeFlags(0));
+ }
+
+ return t;
+}
+
+} // extern C
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkhypertext.cxx b/vcl/unx/gtk3/a11y/gtk3atkhypertext.cxx
index bb9749c36af3..ab94126dfc51 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkhypertext.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkhypertext.cxx
@@ -5,8 +5,269 @@
* 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 .
*/
-#include "../../gtk/a11y/atkhypertext.cxx"
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
+
+using namespace ::com::sun::star;
+
+// ---------------------- AtkHyperlink ----------------------
+
+struct HyperLink {
+ AtkHyperlink const atk_hyper_link;
+
+ uno::Reference< accessibility::XAccessibleHyperlink > xLink;
+};
+
+static uno::Reference< accessibility::XAccessibleHyperlink > const &
+ getHyperlink( AtkHyperlink *pHyperlink )
+{
+ HyperLink *pLink = reinterpret_cast<HyperLink *>(pHyperlink);
+ return pLink->xLink;
+}
+
+static GObjectClass *hyper_parent_class = nullptr;
+
+extern "C" {
+
+static void
+hyper_link_finalize (GObject *obj)
+{
+ HyperLink *hl = reinterpret_cast<HyperLink *>(obj);
+ hl->xLink.clear();
+ hyper_parent_class->finalize (obj);
+}
+
+static gchar *
+hyper_link_get_uri( AtkHyperlink *pLink,
+ gint i )
+{
+ try {
+ uno::Any aAny = getHyperlink( pLink )->getAccessibleActionObject( i );
+ OUString aUri = aAny.get< OUString > ();
+ return OUStringToGChar(aUri);
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in hyper_link_get_uri" );
+ }
+ return nullptr;
+}
+
+static AtkObject *
+hyper_link_get_object( AtkHyperlink *,
+ gint )
+{
+ g_warning( "FIXME: hyper_link_get_object unimplemented" );
+ return nullptr;
+}
+static gint
+hyper_link_get_end_index( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->getEndIndex();
+ }
+ catch(const uno::Exception&) {
+ }
+ return -1;
+}
+static gint
+hyper_link_get_start_index( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->getStartIndex();
+ }
+ catch(const uno::Exception&) {
+ }
+ return -1;
+}
+static gboolean
+hyper_link_is_valid( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->isValid();
+ }
+ catch(const uno::Exception&) {
+ }
+ return FALSE;
+}
+static gint
+hyper_link_get_n_anchors( AtkHyperlink *pLink )
+{
+ try {
+ return getHyperlink( pLink )->getAccessibleActionCount();
+ }
+ catch(const uno::Exception&) {
+ }
+ return 0;
+}
+
+static guint
+hyper_link_link_state( AtkHyperlink * )
+{
+ g_warning( "FIXME: hyper_link_link_state unimplemented" );
+ return 0;
+}
+static gboolean
+hyper_link_is_selected_link( AtkHyperlink * )
+{
+ g_warning( "FIXME: hyper_link_is_selected_link unimplemented" );
+ return FALSE;
+}
+
+static void
+hyper_link_class_init (AtkHyperlinkClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = hyper_link_finalize;
+
+ hyper_parent_class = static_cast<GObjectClass *>(g_type_class_peek_parent (klass));
+
+ klass->get_uri = hyper_link_get_uri;
+ klass->get_object = hyper_link_get_object;
+ klass->get_end_index = hyper_link_get_end_index;
+ klass->get_start_index = hyper_link_get_start_index;
+ klass->is_valid = hyper_link_is_valid;
+ klass->get_n_anchors = hyper_link_get_n_anchors;
+ klass->link_state = hyper_link_link_state;
+ klass->is_selected_link = hyper_link_is_selected_link;
+}
+
+static GType
+hyper_link_get_type()
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo tinfo = {
+ sizeof (AtkHyperlinkClass),
+ nullptr, /* base init */
+ nullptr, /* base finalize */
+ reinterpret_cast<GClassInitFunc>(hyper_link_class_init),
+ nullptr, /* class finalize */
+ nullptr, /* class data */
+ sizeof (HyperLink), /* instance size */
+ 0, /* nb preallocs */
+ nullptr, /* instance init */
+ nullptr /* value table */
+ };
+
+ static const GInterfaceInfo atk_action_info = {
+ reinterpret_cast<GInterfaceInitFunc>(actionIfaceInit),
+ nullptr,
+ nullptr
+ };
+
+ type = g_type_register_static (ATK_TYPE_HYPERLINK,
+ "OOoAtkObjHyperLink", &tinfo,
+ GTypeFlags(0));
+ g_type_add_interface_static (type, ATK_TYPE_ACTION,
+ &atk_action_info);
+ }
+
+ return type;
+}
+
+// ---------------------- AtkHyperText ----------------------
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleHypertext>
+ getHypertext( AtkHypertext *pHypertext )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pHypertext );
+ if( pWrap )
+ {
+ if( !pWrap->mpHypertext.is() )
+ {
+ pWrap->mpHypertext.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpHypertext;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleHypertext>();
+}
+
+static AtkHyperlink *
+hypertext_get_link( AtkHypertext *hypertext,
+ gint link_index)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleHypertext> pHypertext
+ = getHypertext( hypertext );
+ if( pHypertext.is() )
+ {
+ HyperLink *pLink = static_cast<HyperLink *>(g_object_new( hyper_link_get_type(), nullptr ));
+ pLink->xLink = pHypertext->getHyperLink( link_index );
+ if( !pLink->xLink.is() ) {
+ g_object_unref( G_OBJECT( pLink ) );
+ pLink = nullptr;
+ }
+ return ATK_HYPERLINK( pLink );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getHyperLink()" );
+ }
+
+ return nullptr;
+}
+
+static gint
+hypertext_get_n_links( AtkHypertext *hypertext )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleHypertext> pHypertext
+ = getHypertext( hypertext );
+ if( pHypertext.is() )
+ return pHypertext->getHyperLinkCount();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getHyperLinkCount()" );
+ }
+
+ return 0;
+}
+
+static gint
+hypertext_get_link_index( AtkHypertext *hypertext,
+ gint index)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleHypertext> pHypertext
+ = getHypertext( hypertext );
+ if( pHypertext.is() )
+ return pHypertext->getHyperLinkIndex( index );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getHyperLinkIndex()" );
+ }
+
+ return 0;
+}
+
+} // extern "C"
+
+void
+hypertextIfaceInit (AtkHypertextIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->get_link = hypertext_get_link;
+ iface->get_n_links = hypertext_get_n_links;
+ iface->get_link_index = hypertext_get_link_index;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkimage.cxx b/vcl/unx/gtk3/a11y/gtk3atkimage.cxx
index 4e2c77e9f2b1..1c9bc2c640f9 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkimage.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkimage.cxx
@@ -5,8 +5,128 @@
* 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 .
*/
-#include "../../gtk/a11y/atkimage.cxx"
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+
+using namespace ::com::sun::star;
+
+// FIXME
+static G_CONST_RETURN gchar *
+getAsConst( const OUString& rString )
+{
+ static const int nMax = 10;
+ static OString aUgly[nMax];
+ static int nIdx = 0;
+ nIdx = (nIdx + 1) % nMax;
+ aUgly[nIdx] = OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
+ return aUgly[ nIdx ].getStr();
+}
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleImage>
+ getImage( AtkImage *pImage )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pImage );
+ if( pWrap )
+ {
+ if( !pWrap->mpImage.is() )
+ {
+ pWrap->mpImage.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpImage;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleImage>();
+}
+
+extern "C" {
+
+static G_CONST_RETURN gchar *
+image_get_image_description( AtkImage *image )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleImage> pImage
+ = getImage( image );
+ if( pImage.is() )
+ return getAsConst( pImage->getAccessibleImageDescription() );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleImageDescription()" );
+ }
+
+ return nullptr;
+}
+
+static void
+image_get_image_position( AtkImage *image,
+ gint *x,
+ gint *y,
+ AtkCoordType coord_type )
+{
+ *x = *y = 0;
+ if( ATK_IS_COMPONENT( image ) )
+ {
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ atk_component_get_position( ATK_COMPONENT( image ), x, y, coord_type );
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ }
+ else
+ g_warning( "FIXME: no image position information" );
+}
+
+static void
+image_get_image_size( AtkImage *image,
+ gint *width,
+ gint *height )
+{
+ *width = 0;
+ *height = 0;
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleImage> pImage
+ = getImage( image );
+ if( pImage.is() )
+ {
+ *width = pImage->getAccessibleImageWidth();
+ *height = pImage->getAccessibleImageHeight();
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleImageHeight() or Width" );
+ }
+}
+
+static gboolean
+image_set_image_description( AtkImage *, const gchar * )
+{
+ g_warning ("FIXME: no set image description");
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+imageIfaceInit (AtkImageIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->set_image_description = image_set_image_description;
+ iface->get_image_description = image_get_image_description;
+ iface->get_image_position = image_get_image_position;
+ iface->get_image_size = image_get_image_size;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atklistener.cxx b/vcl/unx/gtk3/a11y/gtk3atklistener.cxx
index eca1cd7ec1d0..c30bc638bced 100644
--- a/vcl/unx/gtk3/a11y/gtk3atklistener.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atklistener.cxx
@@ -5,8 +5,735 @@
* 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 .
*/
-#include "../../gtk/a11y/atklistener.cxx"
+#ifdef AIX
+#define _LINUX_SOURCE_COMPAT
+#include <sys/timer.h>
+#undef _LINUX_SOURCE_COMPAT
+#endif
+
+#include <com/sun/star/accessibility/TextSegment.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include "atklistener.hxx"
+#include "atkwrapper.hxx"
+#include <vcl/svapp.hxx>
+
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+
+#define DEBUG_ATK_LISTENER 0
+
+#if DEBUG_ATK_LISTENER
+#include <iostream>
+#include <sstream>
+#endif
+
+using namespace com::sun::star;
+
+AtkListener::AtkListener( AtkObjectWrapper* pWrapper ) : mpWrapper( pWrapper )
+{
+ if( mpWrapper )
+ {
+ g_object_ref( mpWrapper );
+ updateChildList( mpWrapper->mpContext );
+ }
+}
+
+AtkListener::~AtkListener()
+{
+ if( mpWrapper )
+ g_object_unref( mpWrapper );
+}
+
+/*****************************************************************************/
+
+static AtkStateType mapState( const uno::Any &rAny )
+{
+ sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
+ rAny >>= nState;
+ return mapAtkState( nState );
+}
+
+/*****************************************************************************/
+
+extern "C" {
+ // rhbz#1001768 - down to horrific problems releasing the solar mutex
+ // while destroying a Window - which occurs inside these notifications.
+ static gboolean
+ idle_defunc_state_change( AtkObject *atk_obj )
+ {
+ SolarMutexGuard aGuard;
+
+ // This is an equivalent to a state change to DEFUNC(T).
+ atk_object_notify_state_change( atk_obj, ATK_STATE_DEFUNCT, TRUE );
+ if( atk_get_focus_object() == atk_obj )
+ {
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ atk_focus_tracker_notify( nullptr );
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ }
+ g_object_unref( G_OBJECT( atk_obj ) );
+ return false;
+ }
+}
+
+// XEventListener implementation
+void AtkListener::disposing( const lang::EventObject& )
+{
+ if( mpWrapper )
+ {
+ AtkObject *atk_obj = ATK_OBJECT( mpWrapper );
+
+ // Release all interface references to avoid shutdown problems with
+ // global mutex
+ atk_object_wrapper_dispose( mpWrapper );
+
+ g_idle_add( reinterpret_cast<GSourceFunc>(idle_defunc_state_change),
+ g_object_ref( G_OBJECT( atk_obj ) ) );
+
+ // Release the wrapper object so that it can vanish ..
+ g_object_unref( mpWrapper );
+ mpWrapper = nullptr;
+ }
+}
+
+/*****************************************************************************/
+
+static AtkObject *getObjFromAny( const uno::Any &rAny )
+{
+ uno::Reference< accessibility::XAccessible > xAccessible;
+ rAny >>= xAccessible;
+ return xAccessible.is() ? atk_object_wrapper_ref( xAccessible ) : nullptr;
+}
+
+/*****************************************************************************/
+
+// Updates the child list held to provide the old IndexInParent on children_changed::remove
+void AtkListener::updateChildList(
+ css::uno::Reference<css::accessibility::XAccessibleContext> const &
+ pContext)
+{
+ m_aChildList.clear();
+
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet = pContext->getAccessibleStateSet();
+ if( xStateSet.is()
+ && !xStateSet->contains(accessibility::AccessibleStateType::DEFUNC)
+ && !xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS) )
+ {
+ sal_Int32 nChildren = pContext->getAccessibleChildCount();
+ m_aChildList.resize(nChildren);
+ for(sal_Int32 n = 0; n < nChildren; n++)
+ {
+ try
+ {
+ m_aChildList[n] = pContext->getAccessibleChild(n);
+ }
+ catch (lang::IndexOutOfBoundsException const&)
+ {
+ sal_Int32 nChildren2 = pContext->getAccessibleChildCount();
+ assert(nChildren2 <= n && "consistency?");
+ m_aChildList.resize(std::min(nChildren2, n));
+ break;
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void AtkListener::handleChildAdded(
+ const uno::Reference< accessibility::XAccessibleContext >& rxParent,
+ const uno::Reference< accessibility::XAccessible>& rxAccessible)
+{
+ AtkObject * pChild = rxAccessible.is() ? atk_object_wrapper_ref( rxAccessible ) : nullptr;
+
+ if( pChild )
+ {
+ updateChildList(rxParent);
+
+ atk_object_wrapper_add_child( mpWrapper, pChild,
+ atk_object_get_index_in_parent( pChild ));
+
+ g_object_unref( pChild );
+ }
+}
+
+/*****************************************************************************/
+
+void AtkListener::handleChildRemoved(
+ const uno::Reference< accessibility::XAccessibleContext >& rxParent,
+ const uno::Reference< accessibility::XAccessible>& rxChild)
+{
+ sal_Int32 nIndex = -1;
+
+ // Locate the child in the children list
+ size_t n, nmax = m_aChildList.size();
+ for( n = 0; n < nmax; ++n )
+ {
+ if( rxChild == m_aChildList[n] )
+ {
+ nIndex = n;
+ break;
+ }
+ }
+
+ // FIXME: two problems here:
+ // a) we get child-removed events for objects that are no real children
+ // in the accessibility hierarchy or have been removed before due to
+ // some child removing batch.
+ // b) spi_atk_bridge_signal_listener ignores the given parameters
+ // for children_changed events and always asks the parent for the
+ // 0. child, which breaks somehow on vanishing list boxes.
+ // Ignoring "remove" events for objects not in the m_aChildList
+ // for now.
+ if( nIndex >= 0 )
+ {
+ uno::Reference<accessibility::XAccessibleEventBroadcaster> xBroadcaster(
+ rxChild->getAccessibleContext(), uno::UNO_QUERY);
+
+ if (xBroadcaster.is())
+ {
+ uno::Reference<accessibility::XAccessibleEventListener> xListener(this);
+ xBroadcaster->removeAccessibleEventListener(xListener);
+ }
+
+ updateChildList(rxParent);
+
+ AtkObject * pChild = atk_object_wrapper_ref( rxChild, false );
+ if( pChild )
+ {
+ atk_object_wrapper_remove_child( mpWrapper, pChild, nIndex );
+ g_object_unref( pChild );
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void AtkListener::handleInvalidateChildren(
+ const uno::Reference< accessibility::XAccessibleContext >& rxParent)
+{
+ // Send notifications for all previous children
+ size_t n = m_aChildList.size();
+ while( n-- > 0 )
+ {
+ if( m_aChildList[n].is() )
+ {
+ AtkObject * pChild = atk_object_wrapper_ref( m_aChildList[n], false );
+ if( pChild )
+ {
+ atk_object_wrapper_remove_child( mpWrapper, pChild, n );
+ g_object_unref( pChild );
+ }
+ }
+ }
+
+ updateChildList(rxParent);
+
+ // Send notifications for all new children
+ size_t nmax = m_aChildList.size();
+ for( n = 0; n < nmax; ++n )
+ {
+ if( m_aChildList[n].is() )
+ {
+ AtkObject * pChild = atk_object_wrapper_ref( m_aChildList[n] );
+
+ if( pChild )
+ {
+ atk_object_wrapper_add_child( mpWrapper, pChild, n );
+ g_object_unref( pChild );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static uno::Reference< accessibility::XAccessibleContext >
+getAccessibleContextFromSource( const uno::Reference< uno::XInterface >& rxSource )
+{
+ uno::Reference< accessibility::XAccessibleContext > xContext(rxSource, uno::UNO_QUERY);
+ if( ! xContext.is() )
+ {
+ g_warning( "ERROR: Event source does not implement XAccessibleContext" );
+
+ // Second try - query for XAccessible, which should give us access to
+ // XAccessibleContext.
+ uno::Reference< accessibility::XAccessible > xAccessible(rxSource, uno::UNO_QUERY);
+ if( xAccessible.is() )
+ xContext = xAccessible->getAccessibleContext();
+ }
+
+ return xContext;
+}
+
+#if DEBUG_ATK_LISTENER
+
+namespace {
+
+void printNotifyEvent( const accessibility::AccessibleEventObject& rEvent )
+{
+ static std::vector<const char*> aLabels = {
+ 0,
+ "NAME_CHANGED", // 01
+ "DESCRIPTION_CHANGED", // 02
+ "ACTION_CHANGED", // 03
+ "STATE_CHANGED", // 04
+ "ACTIVE_DESCENDANT_CHANGED", // 05
+ "BOUNDRECT_CHANGED", // 06
+ "CHILD", // 07
+ "INVALIDATE_ALL_CHILDREN", // 08
+ "SELECTION_CHANGED", // 09
+ "VISIBLE_DATA_CHANGED", // 10
+ "VALUE_CHANGED", // 11
+ "CONTENT_FLOWS_FROM_RELATION_CHANGED", // 12
+ "CONTENT_FLOWS_TO_RELATION_CHANGED", // 13
+ "CONTROLLED_BY_RELATION_CHANGED", // 14
+ "CONTROLLER_FOR_RELATION_CHANGED", // 15
+ "LABEL_FOR_RELATION_CHANGED", // 16
+ "LABELED_BY_RELATION_CHANGED", // 17
+ "MEMBER_OF_RELATION_CHANGED", // 18
+ "SUB_WINDOW_OF_RELATION_CHANGED", // 19
+ "CARET_CHANGED", // 20
+ "TEXT_SELECTION_CHANGED", // 21
+ "TEXT_CHANGED", // 22
+ "TEXT_ATTRIBUTE_CHANGED", // 23
+ "HYPERTEXT_CHANGED", // 24
+ "TABLE_CAPTION_CHANGED", // 25
+ "TABLE_COLUMN_DESCRIPTION_CHANGED", // 26
+ "TABLE_COLUMN_HEADER_CHANGED", // 27
+ "TABLE_MODEL_CHANGED", // 28
+ "TABLE_ROW_DESCRIPTION_CHANGED", // 29
+ "TABLE_ROW_HEADER_CHANGED", // 30
+ "TABLE_SUMMARY_CHANGED", // 31
+ "LISTBOX_ENTRY_EXPANDED", // 32
+ "LISTBOX_ENTRY_COLLAPSED", // 33
+ "ACTIVE_DESCENDANT_CHANGED_NOFOCUS", // 34
+ "SELECTION_CHANGED_ADD", // 35
+ "SELECTION_CHANGED_REMOVE", // 36
+ "SELECTION_CHANGED_WITHIN", // 37
+ "PAGE_CHANGED", // 38
+ "SECTION_CHANGED", // 39
+ "COLUMN_CHANGED", // 40
+ "ROLE_CHANGED", // 41
+ };
+
+ static std::vector<const char*> aStates = {
+ "INVALID", // 00
+ "ACTIVE", // 01
+ "ARMED", // 02
+ "BUSY", // 03
+ "CHECKED", // 04
+ "DEFUNC", // 05
+ "EDITABLE", // 06
+ "ENABLED", // 07
+ "EXPANDABLE", // 08
+ "EXPANDED", // 09
+ "FOCUSABLE", // 10
+ "FOCUSED", // 11
+ "HORIZONTAL", // 12
+ "ICONIFIED", // 13
+ "INDETERMINATE", // 14
+ "MANAGES_DESCENDANTS", // 15
+ "MODAL", // 16
+ "MULTI_LINE", // 17
+ "MULTI_SELECTABLE", // 18
+ "OPAQUE", // 19
+ "PRESSED", // 20
+ "RESIZABLE", // 21
+ "SELECTABLE", // 22
+ "SELECTED", // 23
+ "SENSITIVE", // 24
+ "SHOWING", // 25
+ "SINGLE_LINE", // 26
+ "STALE", // 27
+ "TRANSIENT", // 28
+ "VERTICAL", // 29
+ "VISIBLE", // 30
+ "MOVEABLE", // 31
+ "DEFAULT", // 32
+ "OFFSCREEN", // 33
+ "COLLAPSE", // 34
+ };
+
+ auto getOrUnknown = [](const std::vector<const char*>& rCont, size_t nIndex) -> std::string
+ {
+ return (nIndex < rCont.size()) ? rCont[nIndex] : "<unknown>";
+ };
+
+ std::ostringstream os;
+ os << "--" << std::endl;
+ os << "* event = " << getOrUnknown(aLabels, rEvent.EventId) << std::endl;
+
+ switch (rEvent.EventId)
+ {
+ case accessibility::AccessibleEventId::STATE_CHANGED:
+ {
+ sal_Int16 nState;
+ if (rEvent.OldValue >>= nState)
+ os << " * old state = " << getOrUnknown(aStates, nState);
+ if (rEvent.NewValue >>= nState)
+ os << " * new state = " << getOrUnknown(aStates, nState);
+
+ os << std::endl;
+ break;
+ }
+ default:
+ ;
+ }
+
+ std::cout << os.str();
+}
+
+}
+
+#endif
+
+void AtkListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
+{
+ if( !mpWrapper )
+ return;
+
+ AtkObject *atk_obj = ATK_OBJECT( mpWrapper );
+
+ switch( aEvent.EventId )
+ {
+ // AtkObject signals:
+ // Hierarchy signals
+ case accessibility::AccessibleEventId::CHILD:
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParent;
+ uno::Reference< accessibility::XAccessible > xChild;
+
+ xParent = getAccessibleContextFromSource(aEvent.Source);
+ g_return_if_fail( xParent.is() );
+
+ if( aEvent.OldValue >>= xChild )
+ handleChildRemoved(xParent, xChild);
+
+ if( aEvent.NewValue >>= xChild )
+ handleChildAdded(xParent, xChild);
+ break;
+ }
+
+ case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParent = getAccessibleContextFromSource(aEvent.Source);
+ g_return_if_fail( xParent.is() );
+
+ handleInvalidateChildren(xParent);
+ break;
+ }
+
+ case accessibility::AccessibleEventId::NAME_CHANGED:
+ {
+ OUString aName;
+ if( aEvent.NewValue >>= aName )
+ {
+ atk_object_set_name(atk_obj,
+ OUStringToOString(aName, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ break;
+ }
+
+ case accessibility::AccessibleEventId::DESCRIPTION_CHANGED:
+ {
+ OUString aDescription;
+ if( aEvent.NewValue >>= aDescription )
+ {
+ atk_object_set_description(atk_obj,
+ OUStringToOString(aDescription, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ break;
+ }
+
+ case accessibility::AccessibleEventId::STATE_CHANGED:
+ {
+ AtkStateType eOldState = mapState( aEvent.OldValue );
+ AtkStateType eNewState = mapState( aEvent.NewValue );
+
+ gboolean bState = eNewState != ATK_STATE_INVALID;
+ AtkStateType eRealState = bState ? eNewState : eOldState;
+
+ atk_object_notify_state_change( atk_obj, eRealState, bState );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::BOUNDRECT_CHANGED:
+
+#ifdef HAS_ATKRECTANGLE
+ if( ATK_IS_COMPONENT( atk_obj ) )
+ {
+ AtkRectangle rect;
+
+ atk_component_get_extents( ATK_COMPONENT( atk_obj ),
+ &rect.x,
+ &rect.y,
+ &rect.width,
+ &rect.height,
+ ATK_XY_SCREEN );
+
+ g_signal_emit_by_name( atk_obj, "bounds_changed", &rect );
+ }
+ else
+ g_warning( "bounds_changed event for object not implementing AtkComponent\n");
+#endif
+
+ break;
+
+ case accessibility::AccessibleEventId::VISIBLE_DATA_CHANGED:
+ g_signal_emit_by_name( atk_obj, "visible-data-changed" );
+ break;
+
+ case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
+ {
+ AtkObject *pChild = getObjFromAny( aEvent.NewValue );
+ if( pChild )
+ {
+ g_signal_emit_by_name( atk_obj, "active-descendant-changed", pChild );
+ g_object_unref( pChild );
+ }
+ break;
+ }
+
+ //ACTIVE_DESCENDANT_CHANGED_NOFOCUS (sic) appears to have been added
+ //as a workaround or an aid for the ia2 winaccessibility implementation
+ //so ignore it silently without warning here
+ case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS:
+ break;
+
+ // #i92103#
+ case accessibility::AccessibleEventId::LISTBOX_ENTRY_EXPANDED:
+ {
+ AtkObject *pChild = getObjFromAny( aEvent.NewValue );
+ if( pChild )
+ {
+ atk_object_notify_state_change( pChild, ATK_STATE_EXPANDED, true );
+ g_object_unref( pChild );
+ }
+ break;
+ }
+
+ case accessibility::AccessibleEventId::LISTBOX_ENTRY_COLLAPSED:
+ {
+ AtkObject *pChild = getObjFromAny( aEvent.NewValue );
+ if( pChild )
+ {
+ atk_object_notify_state_change( pChild, ATK_STATE_EXPANDED, false );
+ g_object_unref( pChild );
+ }
+ break;
+ }
+
+ // AtkAction signals ...
+ case accessibility::AccessibleEventId::ACTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-actions");
+ break;
+
+ // AtkText
+ case accessibility::AccessibleEventId::CARET_CHANGED:
+ {
+ sal_Int32 nPos=0;
+ aEvent.NewValue >>= nPos;
+ g_signal_emit_by_name( atk_obj, "text_caret_moved", nPos );
+ break;
+ }
+ case accessibility::AccessibleEventId::TEXT_CHANGED:
+ {
+ // TESTME: and remove this comment:
+ // cf. comphelper/source/misc/accessibletexthelper.cxx (implInitTextChangedEvent)
+ accessibility::TextSegment aDeletedText;
+ accessibility::TextSegment aInsertedText;
+
+ // TODO: when GNOME starts to send "update" kind of events, change
+ // we need to re-think this implementation as well
+ if( aEvent.OldValue >>= aDeletedText )
+ {
+ /* Remember the text segment here to be able to return removed text in get_text().
+ * This is clearly a hack to be used until appropriate API exists in atk to pass
+ * the string value directly or we find a compelling reason to start caching the
+ * UTF-8 converted strings in the atk wrapper object.
+ */
+
+ g_object_set_data( G_OBJECT(atk_obj), "ooo::text_changed::delete", &aDeletedText);
+
+ g_signal_emit_by_name( atk_obj, "text_changed::delete",
+ static_cast<gint>(aDeletedText.SegmentStart),
+ static_cast<gint>( aDeletedText.SegmentEnd - aDeletedText.SegmentStart ) );
+
+ g_object_steal_data( G_OBJECT(atk_obj), "ooo::text_changed::delete" );
+ }
+
+ if( aEvent.NewValue >>= aInsertedText )
+ g_signal_emit_by_name( atk_obj, "text_changed::insert",
+ static_cast<gint>(aInsertedText.SegmentStart),
+ static_cast<gint>( aInsertedText.SegmentEnd - aInsertedText.SegmentStart ) );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED:
+ {
+ g_signal_emit_by_name( atk_obj, "text-selection-changed" );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TEXT_ATTRIBUTE_CHANGED:
+ g_signal_emit_by_name( atk_obj, "text-attributes-changed" );
+ break;
+
+ // AtkValue
+ case accessibility::AccessibleEventId::VALUE_CHANGED:
+ g_object_notify( G_OBJECT( atk_obj ), "accessible-value" );
+ break;
+
+ case accessibility::AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::LABELED_BY_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
+ case accessibility::AccessibleEventId::SUB_WINDOW_OF_RELATION_CHANGED:
+ // FIXME: ask Bill how Atk copes with this little lot ...
+ break;
+
+ // AtkTable
+ case accessibility::AccessibleEventId::TABLE_MODEL_CHANGED:
+ {
+ accessibility::AccessibleTableModelChange aChange;
+ aEvent.NewValue >>= aChange;
+
+ sal_Int32 nRowsChanged = aChange.LastRow - aChange.FirstRow + 1;
+ sal_Int32 nColumnsChanged = aChange.LastColumn - aChange.FirstColumn + 1;
+
+ static const struct {
+ const char *row;
+ const char *col;
+ } aSignalNames[] =
+ {
+ { nullptr, nullptr }, // dummy
+ { "row_inserted", "column_inserted" }, // INSERT = 1
+ { "row_deleted", "column_deleted" } // DELETE = 2
+ };
+ switch( aChange.Type )
+ {
+ case accessibility::AccessibleTableModelChangeType::INSERT:
+ case accessibility::AccessibleTableModelChangeType::DELETE:
+ if( nRowsChanged > 0 )
+ g_signal_emit_by_name( G_OBJECT( atk_obj ),
+ aSignalNames[aChange.Type].row,
+ aChange.FirstRow, nRowsChanged );
+ if( nColumnsChanged > 0 )
+ g_signal_emit_by_name( G_OBJECT( atk_obj ),
+ aSignalNames[aChange.Type].col,
+ aChange.FirstColumn, nColumnsChanged );
+ break;
+
+ case accessibility::AccessibleTableModelChangeType::UPDATE:
+ // This is not really a model change, is it ?
+ break;
+ default:
+ g_warning( "TESTME: unusual table model change %d\n", aChange.Type );
+ break;
+ }
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "model-changed" );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
+ {
+ accessibility::AccessibleTableModelChange aChange;
+ aEvent.NewValue >>= aChange;
+
+ AtkPropertyValues values;
+ memset(&values, 0, sizeof(AtkPropertyValues));
+ g_value_init (&values.new_value, G_TYPE_INT);
+ values.property_name = "accessible-table-column-header";
+
+ for (sal_Int32 nChangedColumn = aChange.FirstColumn; nChangedColumn <= aChange.LastColumn; ++nChangedColumn)
+ {
+ g_value_set_int (&values.new_value, nChangedColumn);
+ g_signal_emit_by_name(G_OBJECT(atk_obj), "property_change::accessible-table-column-header", &values, nullptr);
+ }
+ break;
+ }
+
+ case accessibility::AccessibleEventId::TABLE_CAPTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-caption");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-column-description");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-row-description");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-row-header");
+ break;
+
+ case accessibility::AccessibleEventId::TABLE_SUMMARY_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-table-summary");
+ break;
+
+ case accessibility::AccessibleEventId::SELECTION_CHANGED:
+ case accessibility::AccessibleEventId::SELECTION_CHANGED_ADD:
+ case accessibility::AccessibleEventId::SELECTION_CHANGED_REMOVE:
+ case accessibility::AccessibleEventId::SELECTION_CHANGED_WITHIN:
+ if (ATK_IS_SELECTION(atk_obj))
+ g_signal_emit_by_name(G_OBJECT(atk_obj), "selection_changed");
+ else
+ {
+ // e.g. tdf#122353, when such dialogs become native the problem will go away anyway
+ SAL_INFO("vcl.gtk", "selection change from obj which doesn't support XAccessibleSelection");
+ }
+ break;
+
+ case accessibility::AccessibleEventId::HYPERTEXT_CHANGED:
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "property_change::accessible-hypertext-offset");
+ break;
+
+ case accessibility::AccessibleEventId::ROLE_CHANGED:
+ {
+ uno::Reference< accessibility::XAccessibleContext > xContext = getAccessibleContextFromSource( aEvent.Source );
+ atk_object_wrapper_set_role( mpWrapper, xContext->getAccessibleRole() );
+ break;
+ }
+
+ case accessibility::AccessibleEventId::PAGE_CHANGED:
+ {
+ /* // If we implemented AtkDocument then I imagine this is what this
+ // handler should look like
+ sal_Int32 nPos=0;
+ aEvent.NewValue >>= nPos;
+ g_signal_emit_by_name( G_OBJECT( atk_obj ), "page_changed", nPos );
+ */
+ break;
+ }
+
+ default:
+ SAL_WARN("vcl.gtk", "Unknown event notification: " << aEvent.EventId);
+ break;
+ }
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkregistry.cxx b/vcl/unx/gtk3/a11y/gtk3atkregistry.cxx
index 126e97a808ae..ff96378c41dc 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkregistry.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkregistry.cxx
@@ -5,8 +5,62 @@
* 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 .
*/
-#include "../../gtk/a11y/atkregistry.cxx"
+#include "atkregistry.hxx"
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+
+static GHashTable *uno_to_gobject = nullptr;
+
+/*****************************************************************************/
+
+AtkObject *
+ooo_wrapper_registry_get(const Reference< XAccessible >& rxAccessible)
+{
+ if( uno_to_gobject )
+ {
+ gpointer cached =
+ g_hash_table_lookup(uno_to_gobject, static_cast<gpointer>(rxAccessible.get()));
+
+ if( cached )
+ return ATK_OBJECT( cached );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+void
+ooo_wrapper_registry_add(const Reference< XAccessible >& rxAccessible, AtkObject *obj)
+{
+ if( !uno_to_gobject )
+ uno_to_gobject = g_hash_table_new (nullptr, nullptr);
+
+ g_hash_table_insert( uno_to_gobject, static_cast<gpointer>(rxAccessible.get()), obj );
+}
+
+/*****************************************************************************/
+
+void
+ooo_wrapper_registry_remove(
+ css::uno::Reference<css::accessibility::XAccessible> const & pAccessible)
+{
+ if( uno_to_gobject )
+ g_hash_table_remove(
+ uno_to_gobject, static_cast<gpointer>(pAccessible.get()) );
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkselection.cxx b/vcl/unx/gtk3/a11y/gtk3atkselection.cxx
index f67b665304d7..1d9772bc1587 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkselection.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkselection.cxx
@@ -5,8 +5,186 @@
* 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 .
*/
-#include "../../gtk/a11y/atkselection.cxx"
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+using namespace ::com::sun::star;
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleSelection>
+ getSelection( AtkSelection *pSelection )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pSelection );
+ if( pWrap )
+ {
+ if( !pWrap->mpSelection.is() )
+ {
+ pWrap->mpSelection.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpSelection;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleSelection>();
+}
+
+extern "C" {
+
+static gboolean
+selection_add_selection( AtkSelection *selection,
+ gint i )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ {
+ pSelection->selectAccessibleChild( i );
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in selectAccessibleChild()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+selection_clear_selection( AtkSelection *selection )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ {
+ pSelection->clearAccessibleSelection();
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in selectAccessibleChild()" );
+ }
+
+ return FALSE;
+}
+
+static AtkObject*
+selection_ref_selection( AtkSelection *selection,
+ gint i )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ return atk_object_wrapper_ref( pSelection->getSelectedAccessibleChild( i ) );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleChild()" );
+ }
+
+ return nullptr;
+}
+
+static gint
+selection_get_selection_count( AtkSelection *selection)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ return pSelection->getSelectedAccessibleChildCount();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return -1;
+}
+
+static gboolean
+selection_is_child_selected( AtkSelection *selection,
+ gint i)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ return pSelection->isAccessibleChildSelected( i );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+selection_remove_selection( AtkSelection *selection,
+ gint i )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ {
+ pSelection->deselectAccessibleChild( i );
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+selection_select_all_selection( AtkSelection *selection)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleSelection> pSelection
+ = getSelection( selection );
+ if( pSelection.is() )
+ {
+ pSelection->selectAllAccessibleChildren();
+ return TRUE;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleChildCount()" );
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+selectionIfaceInit( AtkSelectionIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->add_selection = selection_add_selection;
+ iface->clear_selection = selection_clear_selection;
+ iface->ref_selection = selection_ref_selection;
+ iface->get_selection_count = selection_get_selection_count;
+ iface->is_child_selected = selection_is_child_selected;
+ iface->remove_selection = selection_remove_selection;
+ iface->select_all_selection = selection_select_all_selection;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atktable.cxx b/vcl/unx/gtk3/a11y/gtk3atktable.cxx
index d886ac07296a..29ffa48d5b9d 100644
--- a/vcl/unx/gtk3/a11y/gtk3atktable.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atktable.cxx
@@ -5,8 +5,576 @@
* 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 .
*/
-#include "../../gtk/a11y/atktable.cxx"
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+#include <comphelper/sequence.hxx>
+
+using namespace ::com::sun::star;
+
+static AtkObject *
+atk_object_wrapper_conditional_ref( const uno::Reference< accessibility::XAccessible >& rxAccessible )
+{
+ if( rxAccessible.is() )
+ return atk_object_wrapper_ref( rxAccessible );
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+// FIXME
+static G_CONST_RETURN gchar *
+getAsConst( const OUString& rString )
+{
+ static const int nMax = 10;
+ static OString aUgly[nMax];
+ static int nIdx = 0;
+ nIdx = (nIdx + 1) % nMax;
+ aUgly[nIdx] = OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
+ return aUgly[ nIdx ].getStr();
+}
+
+/*****************************************************************************/
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleTable>
+ getTable( AtkTable *pTable )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pTable );
+ if( pWrap )
+ {
+ if( !pWrap->mpTable.is() )
+ {
+ pWrap->mpTable.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpTable;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleTable>();
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static AtkObject*
+table_wrapper_ref_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable = getTable( table );
+ if( pTable.is() )
+ return atk_object_wrapper_conditional_ref( pTable->getAccessibleCellAt( row, column ) );
+ }
+
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleCellAt()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_index_at (AtkTable *table,
+ gint row,
+ gint column)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleIndex( row, column );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleIndex()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_column_at_index (AtkTable *table,
+ gint nIndex)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleColumn( nIndex );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleColumn()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_row_at_index( AtkTable *table,
+ gint nIndex )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleRow( nIndex );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleRow()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_n_columns( AtkTable *table )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleColumnCount();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleColumnCount()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_n_rows( AtkTable *table )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleRowCount();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleRowCount()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_column_extent_at( AtkTable *table,
+ gint row,
+ gint column )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleColumnExtentAt( row, column );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleColumnExtentAt()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_row_extent_at( AtkTable *table,
+ gint row,
+ gint column )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->getAccessibleRowExtentAt( row, column );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleRowExtentAt()" );
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_caption( AtkTable *table )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return atk_object_wrapper_conditional_ref( pTable->getAccessibleCaption() );
+ }
+
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleCaption()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar *
+table_wrapper_get_row_description( AtkTable *table,
+ gint row )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return getAsConst( pTable->getAccessibleRowDescription( row ) );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleRowDescription()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar *
+table_wrapper_get_column_description( AtkTable *table,
+ gint column )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return getAsConst( pTable->getAccessibleColumnDescription( column ) );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleColumnDescription()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_row_header( AtkTable *table,
+ gint row )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ {
+ uno::Reference< accessibility::XAccessibleTable > xRowHeaders( pTable->getAccessibleRowHeaders() );
+ if( xRowHeaders.is() )
+ return atk_object_wrapper_conditional_ref( xRowHeaders->getAccessibleCellAt( row, 0 ) );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleRowHeaders()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_column_header( AtkTable *table,
+ gint column )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ {
+ uno::Reference< accessibility::XAccessibleTable > xColumnHeaders( pTable->getAccessibleColumnHeaders() );
+ if( xColumnHeaders.is() )
+ return atk_object_wrapper_conditional_ref( xColumnHeaders->getAccessibleCellAt( 0, column ) );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleColumnHeaders()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+table_wrapper_get_summary( AtkTable *table )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ {
+ return atk_object_wrapper_conditional_ref( pTable->getAccessibleSummary() );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleSummary()" );
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+static gint
+convertToGIntArray( const uno::Sequence< ::sal_Int32 >& aSequence, gint **pSelected )
+{
+ if( aSequence.hasElements() )
+ {
+ *pSelected = g_new( gint, aSequence.getLength() );
+
+ *pSelected = comphelper::sequenceToArray(*pSelected, aSequence);
+ }
+
+ return aSequence.getLength();
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_selected_columns( AtkTable *table,
+ gint **pSelected )
+{
+ *pSelected = nullptr;
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return convertToGIntArray( pTable->getSelectedAccessibleColumns(), pSelected );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleColumns()" );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gint
+table_wrapper_get_selected_rows( AtkTable *table,
+ gint **pSelected )
+{
+ *pSelected = nullptr;
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return convertToGIntArray( pTable->getSelectedAccessibleRows(), pSelected );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectedAccessibleRows()" );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_is_column_selected( AtkTable *table,
+ gint column )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->isAccessibleColumnSelected( column );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in isAccessibleColumnSelected()" );
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_is_row_selected( AtkTable *table,
+ gint row )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->isAccessibleRowSelected( row );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in isAccessibleRowSelected()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_is_selected( AtkTable *table,
+ gint row,
+ gint column )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTable> pTable
+ = getTable( table );
+ if( pTable.is() )
+ return pTable->isAccessibleSelected( row, column );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in isAccessibleSelected()" );
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_add_row_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for add_row_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_remove_row_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for remove_row_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_add_column_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for add_column_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static gboolean
+table_wrapper_remove_column_selection( AtkTable *, gint )
+{
+ g_warning( "FIXME: no simple analogue for remove_column_selection" );
+ return 0;
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_caption( AtkTable *, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_column_description( AtkTable *, gint, const gchar * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_column_header( AtkTable *, gint, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_row_description( AtkTable *, gint, const gchar * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_row_header( AtkTable *, gint, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+static void
+table_wrapper_set_summary( AtkTable *, AtkObject * )
+{ // meaningless helper
+}
+
+/*****************************************************************************/
+
+} // extern "C"
+
+void
+tableIfaceInit (AtkTableIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->ref_at = table_wrapper_ref_at;
+ iface->get_n_rows = table_wrapper_get_n_rows;
+ iface->get_n_columns = table_wrapper_get_n_columns;
+ iface->get_index_at = table_wrapper_get_index_at;
+ iface->get_column_at_index = table_wrapper_get_column_at_index;
+ iface->get_row_at_index = table_wrapper_get_row_at_index;
+ iface->is_row_selected = table_wrapper_is_row_selected;
+ iface->is_selected = table_wrapper_is_selected;
+ iface->get_selected_rows = table_wrapper_get_selected_rows;
+ iface->add_row_selection = table_wrapper_add_row_selection;
+ iface->remove_row_selection = table_wrapper_remove_row_selection;
+ iface->add_column_selection = table_wrapper_add_column_selection;
+ iface->remove_column_selection = table_wrapper_remove_column_selection;
+ iface->get_selected_columns = table_wrapper_get_selected_columns;
+ iface->is_column_selected = table_wrapper_is_column_selected;
+ iface->get_column_extent_at = table_wrapper_get_column_extent_at;
+ iface->get_row_extent_at = table_wrapper_get_row_extent_at;
+ iface->get_row_header = table_wrapper_get_row_header;
+ iface->set_row_header = table_wrapper_set_row_header;
+ iface->get_column_header = table_wrapper_get_column_header;
+ iface->set_column_header = table_wrapper_set_column_header;
+ iface->get_caption = table_wrapper_get_caption;
+ iface->set_caption = table_wrapper_set_caption;
+ iface->get_summary = table_wrapper_get_summary;
+ iface->set_summary = table_wrapper_set_summary;
+ iface->get_row_description = table_wrapper_get_row_description;
+ iface->set_row_description = table_wrapper_set_row_description;
+ iface->get_column_description = table_wrapper_get_column_description;
+ iface->set_column_description = table_wrapper_set_column_description;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atktext.cxx b/vcl/unx/gtk3/a11y/gtk3atktext.cxx
index e4bbd5a38980..532b55013ddd 100644
--- a/vcl/unx/gtk3/a11y/gtk3atktext.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atktext.cxx
@@ -5,8 +5,833 @@
* 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 .
*/
-#include "../../gtk/a11y/atktext.cxx"
+#include "atkwrapper.hxx"
+#include "atktextattributes.hxx"
+#include <algorithm>
+
+#include <osl/diagnose.h>
+
+#include <com/sun/star/accessibility/AccessibleTextType.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/text/TextMarkupType.hpp>
+
+using namespace ::com::sun::star;
+
+static sal_Int16
+text_type_from_boundary(AtkTextBoundary boundary_type)
+{
+ switch(boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ return accessibility::AccessibleTextType::CHARACTER;
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ return accessibility::AccessibleTextType::WORD;
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ return accessibility::AccessibleTextType::SENTENCE;
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ return accessibility::AccessibleTextType::LINE;
+ default:
+ return -1;
+ }
+}
+
+/*****************************************************************************/
+
+static gchar *
+adjust_boundaries( css::uno::Reference<css::accessibility::XAccessibleText> const & pText,
+ accessibility::TextSegment const & rTextSegment,
+ AtkTextBoundary boundary_type,
+ gint * start_offset, gint * end_offset )
+{
+ accessibility::TextSegment aTextSegment;
+ OUString aString;
+ gint start = 0, end = 0;
+
+ if( !rTextSegment.SegmentText.isEmpty() )
+ {
+ switch(boundary_type)
+ {
+ case ATK_TEXT_BOUNDARY_CHAR:
+ case ATK_TEXT_BOUNDARY_LINE_START:
+ case ATK_TEXT_BOUNDARY_LINE_END:
+ case ATK_TEXT_BOUNDARY_SENTENCE_START:
+ start = rTextSegment.SegmentStart;
+ end = rTextSegment.SegmentEnd;
+ aString = rTextSegment.SegmentText;
+ break;
+
+ // the OOo break iterator behaves as SENTENCE_START
+ case ATK_TEXT_BOUNDARY_SENTENCE_END:
+ start = rTextSegment.SegmentStart;
+ end = rTextSegment.SegmentEnd;
+
+ if( start > 0 )
+ --start;
+ if( end > 0 && end < pText->getCharacterCount() - 1 )
+ --end;
+
+ aString = pText->getTextRange(start, end);
+ break;
+
+ case ATK_TEXT_BOUNDARY_WORD_START:
+ start = rTextSegment.SegmentStart;
+
+ // Determine the start index of the next segment
+ aTextSegment = pText->getTextBehindIndex(rTextSegment.SegmentEnd,
+ text_type_from_boundary(boundary_type));
+ if( !aTextSegment.SegmentText.isEmpty() )
+ end = aTextSegment.SegmentStart;
+ else
+ end = pText->getCharacterCount();
+
+ aString = pText->getTextRange(start, end);
+ break;
+
+ case ATK_TEXT_BOUNDARY_WORD_END:
+ end = rTextSegment.SegmentEnd;
+
+ // Determine the end index of the previous segment
+ aTextSegment = pText->getTextBeforeIndex(rTextSegment.SegmentStart,
+ text_type_from_boundary(boundary_type));
+ if( !aTextSegment.SegmentText.isEmpty() )
+ start = aTextSegment.SegmentEnd;
+ else
+ start = 0;
+
+ aString = pText->getTextRange(start, end);
+ break;
+
+ default:
+ return nullptr;
+ }
+ }
+
+ *start_offset = start;
+ *end_offset = end;
+
+ return OUStringToGChar(aString);
+}
+
+/*****************************************************************************/
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleText>
+ getText( AtkText *pText )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpText.is() )
+ {
+ pWrap->mpText.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpText;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleText>();
+}
+
+/*****************************************************************************/
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
+ getTextMarkup( AtkText *pText )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpTextMarkup.is() )
+ {
+ pWrap->mpTextMarkup.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpTextMarkup;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleTextMarkup>();
+}
+
+/*****************************************************************************/
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
+ getTextAttributes( AtkText *pText )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpTextAttributes.is() )
+ {
+ pWrap->mpTextAttributes.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpTextAttributes;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleTextAttributes>();
+}
+
+/*****************************************************************************/
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleMultiLineText>
+ getMultiLineText( AtkText *pText )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpMultiLineText.is() )
+ {
+ pWrap->mpMultiLineText.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpMultiLineText;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleMultiLineText>();
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gchar *
+text_wrapper_get_text (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ gchar * ret = nullptr;
+
+ g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), nullptr );
+
+ /* at-spi expects the delete event to be send before the deletion happened
+ * so we save the deleted string object in the UNO event notification and
+ * fool libatk-bridge.so here ..
+ */
+ void * pData = g_object_get_data( G_OBJECT(text), "ooo::text_changed::delete" );
+ if( pData != nullptr )
+ {
+ accessibility::TextSegment * pTextSegment =
+ static_cast <accessibility::TextSegment *> (pData);
+
+ if( pTextSegment->SegmentStart == start_offset &&
+ pTextSegment->SegmentEnd == end_offset )
+ {
+ OString aUtf8 = OUStringToOString( pTextSegment->SegmentText, RTL_TEXTENCODING_UTF8 );
+ return g_strdup( aUtf8.getStr() );
+ }
+ }
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ OUString aText;
+ sal_Int32 n = pText->getCharacterCount();
+
+ if( -1 == end_offset )
+ aText = pText->getText();
+ else if( start_offset < n )
+ aText = pText->getTextRange(start_offset, end_offset);
+
+ ret = g_strdup( OUStringToOString(aText, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getText()" );
+ }
+
+ return ret;
+}
+
+static gchar *
+text_wrapper_get_text_after_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ accessibility::TextSegment aTextSegment = pText->getTextBehindIndex(offset, text_type_from_boundary(boundary_type));
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in get_text_after_offset()" );
+ }
+
+ return nullptr;
+}
+
+static gchar *
+text_wrapper_get_text_at_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ /* If the user presses the 'End' key, the caret will be placed behind the last character,
+ * which is the same index as the first character of the next line. In atk the magic offset
+ * '-2' is used to cover this special case.
+ */
+ if (
+ -2 == offset &&
+ (ATK_TEXT_BOUNDARY_LINE_START == boundary_type ||
+ ATK_TEXT_BOUNDARY_LINE_END == boundary_type)
+ )
+ {
+ css::uno::Reference<
+ css::accessibility::XAccessibleMultiLineText> pMultiLineText
+ = getMultiLineText( text );
+ if( pMultiLineText.is() )
+ {
+ accessibility::TextSegment aTextSegment = pMultiLineText->getTextAtLineWithCaret();
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+
+ accessibility::TextSegment aTextSegment = pText->getTextAtIndex(offset, text_type_from_boundary(boundary_type));
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in get_text_at_offset()" );
+ }
+
+ return nullptr;
+}
+
+static gunichar
+text_wrapper_get_character_at_offset (AtkText *text,
+ gint offset)
+{
+ gint start, end;
+ gunichar uc = 0;
+
+ gchar * char_as_string =
+ text_wrapper_get_text_at_offset(text, offset, ATK_TEXT_BOUNDARY_CHAR,
+ &start, &end);
+ if( char_as_string )
+ {
+ uc = g_utf8_get_char( char_as_string );
+ g_free( char_as_string );
+ }
+
+ return uc;
+}
+
+static gchar *
+text_wrapper_get_text_before_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ accessibility::TextSegment aTextSegment = pText->getTextBeforeIndex(offset, text_type_from_boundary(boundary_type));
+ return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in text_before_offset()" );
+ }
+
+ return nullptr;
+}
+
+static gint
+text_wrapper_get_caret_offset (AtkText *text)
+{
+ gint offset = -1;
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ offset = pText->getCaretPosition();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCaretPosition()" );
+ }
+
+ return offset;
+}
+
+static gboolean
+text_wrapper_set_caret_offset (AtkText *text,
+ gint offset)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ return pText->setCaretPosition( offset );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in setCaretPosition()" );
+ }
+
+ return FALSE;
+}
+
+// #i92232#
+static AtkAttributeSet*
+handle_text_markup_as_run_attribute( css::uno::Reference<css::accessibility::XAccessibleTextMarkup> const & pTextMarkup,
+ const gint nTextMarkupType,
+ const gint offset,
+ AtkAttributeSet* pSet,
+ gint *start_offset,
+ gint *end_offset )
+{
+ const gint nTextMarkupCount( pTextMarkup->getTextMarkupCount( nTextMarkupType ) );
+ if ( nTextMarkupCount > 0 )
+ {
+ for ( gint nTextMarkupIndex = 0;
+ nTextMarkupIndex < nTextMarkupCount;
+ ++nTextMarkupIndex )
+ {
+ accessibility::TextSegment aTextSegment =
+ pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
+ const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
+ const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
+ if ( nStartOffsetTextMarkup <= offset )
+ {
+ if ( offset < nEndOffsetTextMarkup )
+ {
+ // text markup at <offset>
+ *start_offset = ::std::max( *start_offset,
+ nStartOffsetTextMarkup );
+ *end_offset = ::std::min( *end_offset,
+ nEndOffsetTextMarkup );
+ switch ( nTextMarkupType )
+ {
+ case css::text::TextMarkupType::SPELLCHECK:
+ {
+ pSet = attribute_set_prepend_misspelled( pSet );
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ {
+ pSet = attribute_set_prepend_tracked_change_insertion( pSet );
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
+ {
+ pSet = attribute_set_prepend_tracked_change_deletion( pSet );
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
+ }
+ break;
+ default:
+ {
+ OSL_ASSERT( false );
+ }
+ }
+ break; // no further iteration needed.
+ }
+ else
+ {
+ *start_offset = ::std::max( *start_offset,
+ nEndOffsetTextMarkup );
+ // continue iteration.
+ }
+ }
+ else
+ {
+ *end_offset = ::std::min( *end_offset,
+ nStartOffsetTextMarkup );
+ break; // no further iteration.
+ }
+ } // eof iteration over text markups
+ }
+
+ return pSet;
+}
+
+static AtkAttributeSet *
+text_wrapper_get_run_attributes( AtkText *text,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset)
+{
+ AtkAttributeSet *pSet = nullptr;
+
+ try {
+ bool bOffsetsAreValid = false;
+
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is())
+ {
+ uno::Sequence< beans::PropertyValue > aAttributeList;
+
+ css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
+ pTextAttributes = getTextAttributes( text );
+ if(pTextAttributes.is()) // Text attributes are available for paragraphs only
+ {
+ aAttributeList = pTextAttributes->getRunAttributes( offset, uno::Sequence< OUString > () );
+ }
+ else // For other text objects use character attributes
+ {
+ aAttributeList = pText->getCharacterAttributes( offset, uno::Sequence< OUString > () );
+ }
+
+ pSet = attribute_set_new_from_property_values( aAttributeList, true, text );
+ // #i100938#
+ // - always provide start_offset and end_offset
+ {
+ accessibility::TextSegment aTextSegment =
+ pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
+
+ *start_offset = aTextSegment.SegmentStart;
+ // #i100938#
+ // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
+ *end_offset = aTextSegment.SegmentEnd;
+ bOffsetsAreValid = true;
+ }
+ }
+
+ // Special handling for misspelled text
+ // #i92232#
+ // - add special handling for tracked changes and refactor the
+ // corresponding code for handling misspelled text.
+ css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
+ pTextMarkup = getTextMarkup( text );
+ if( pTextMarkup.is() )
+ {
+ // Get attribute run here if it hasn't been done before
+ if (!bOffsetsAreValid && pText.is())
+ {
+ accessibility::TextSegment aAttributeTextSegment =
+ pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
+ *start_offset = aAttributeTextSegment.SegmentStart;
+ *end_offset = aAttributeTextSegment.SegmentEnd;
+ }
+ // handle misspelled text
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ css::text::TextMarkupType::SPELLCHECK,
+ offset, pSet, start_offset, end_offset );
+ // handle tracked changes
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ css::text::TextMarkupType::TRACK_CHANGE_INSERTION,
+ offset, pSet, start_offset, end_offset );
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ css::text::TextMarkupType::TRACK_CHANGE_DELETION,
+ offset, pSet, start_offset, end_offset );
+ pSet = handle_text_markup_as_run_attribute(
+ pTextMarkup,
+ css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
+ offset, pSet, start_offset, end_offset );
+ }
+ }
+ catch(const uno::Exception&){
+
+ g_warning( "Exception in get_run_attributes()" );
+
+ if( pSet )
+ {
+ atk_attribute_set_free( pSet );
+ pSet = nullptr;
+ }
+ }
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+static AtkAttributeSet *
+text_wrapper_get_default_attributes( AtkText *text )
+{
+ AtkAttributeSet *pSet = nullptr;
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
+ pTextAttributes = getTextAttributes( text );
+ if( pTextAttributes.is() )
+ {
+ uno::Sequence< beans::PropertyValue > aAttributeList =
+ pTextAttributes->getDefaultAttributes( uno::Sequence< OUString > () );
+
+ pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
+ }
+ }
+ catch(const uno::Exception&) {
+
+ g_warning( "Exception in get_default_attributes()" );
+
+ if( pSet )
+ {
+ atk_attribute_set_free( pSet );
+ pSet = nullptr;
+ }
+ }
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+static void
+text_wrapper_get_character_extents( AtkText *text,
+ gint offset,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coords )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ *x = *y = *width = *height = 0;
+ awt::Rectangle aRect = pText->getCharacterBounds( offset );
+
+ gint origin_x = 0;
+ gint origin_y = 0;
+
+ if( coords == ATK_XY_SCREEN )
+ {
+ g_return_if_fail( ATK_IS_COMPONENT( text ) );
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ }
+
+ *x = aRect.X + origin_x;
+ *y = aRect.Y + origin_y;
+ *width = aRect.Width;
+ *height = aRect.Height;
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCharacterBounds" );
+ }
+}
+
+static gint
+text_wrapper_get_character_count (AtkText *text)
+{
+ gint rv = 0;
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ rv = pText->getCharacterCount();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCharacterCount" );
+ }
+
+ return rv;
+}
+
+static gint
+text_wrapper_get_offset_at_point (AtkText *text,
+ gint x,
+ gint y,
+ AtkCoordType coords)
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ gint origin_x = 0;
+ gint origin_y = 0;
+
+ if( coords == ATK_XY_SCREEN )
+ {
+ g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ atk_component_get_position( ATK_COMPONENT( text ), &origin_x, &origin_y, coords);
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ }
+
+ return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getIndexAtPoint" );
+ }
+
+ return -1;
+}
+
+// FIXME: the whole series of selections API is problematic ...
+
+static gint
+text_wrapper_get_n_selections (AtkText *text)
+{
+ gint rv = 0;
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
+ }
+
+ return rv;
+}
+
+static gchar *
+text_wrapper_get_selection (AtkText *text,
+ gint selection_num,
+ gint *start_offset,
+ gint *end_offset)
+{
+ g_return_val_if_fail( selection_num == 0, FALSE );
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ {
+ *start_offset = pText->getSelectionStart();
+ *end_offset = pText->getSelectionEnd();
+
+ return OUStringToGChar( pText->getSelectedText() );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
+ }
+
+ return nullptr;
+}
+
+static gboolean
+text_wrapper_add_selection (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ // FIXME: can we try to be more compatible by expanding an
+ // existing adjacent selection ?
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ return pText->setSelection( start_offset, end_offset ); // ?
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in setSelection()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+text_wrapper_remove_selection (AtkText *text,
+ gint selection_num)
+{
+ g_return_val_if_fail( selection_num == 0, FALSE );
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ return pText->setSelection( 0, 0 ); // ?
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in setSelection()" );
+ }
+
+ return FALSE;
+}
+
+static gboolean
+text_wrapper_set_selection (AtkText *text,
+ gint selection_num,
+ gint start_offset,
+ gint end_offset)
+{
+ g_return_val_if_fail( selection_num == 0, FALSE );
+
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleText> pText
+ = getText( text );
+ if( pText.is() )
+ return pText->setSelection( start_offset, end_offset );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in setSelection()" );
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+textIfaceInit (AtkTextIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->get_text = text_wrapper_get_text;
+ iface->get_character_at_offset = text_wrapper_get_character_at_offset;
+ iface->get_text_before_offset = text_wrapper_get_text_before_offset;
+ iface->get_text_at_offset = text_wrapper_get_text_at_offset;
+ iface->get_text_after_offset = text_wrapper_get_text_after_offset;
+ iface->get_caret_offset = text_wrapper_get_caret_offset;
+ iface->set_caret_offset = text_wrapper_set_caret_offset;
+ iface->get_character_count = text_wrapper_get_character_count;
+ iface->get_n_selections = text_wrapper_get_n_selections;
+ iface->get_selection = text_wrapper_get_selection;
+ iface->add_selection = text_wrapper_add_selection;
+ iface->remove_selection = text_wrapper_remove_selection;
+ iface->set_selection = text_wrapper_set_selection;
+ iface->get_run_attributes = text_wrapper_get_run_attributes;
+ iface->get_default_attributes = text_wrapper_get_default_attributes;
+ iface->get_character_extents = text_wrapper_get_character_extents;
+ iface->get_offset_at_point = text_wrapper_get_offset_at_point;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx b/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx
index b0edad06a65c..0ba7fd561862 100644
--- a/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atktextattributes.cxx
@@ -5,8 +5,1379 @@
* 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 .
*/
-#include "../../gtk/a11y/atktextattributes.cxx"
+#include "atktextattributes.hxx"
+
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontStrikeout.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+
+#include <com/sun/star/style/CaseMap.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/LineSpacingMode.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/style/TabAlign.hpp>
+#include <com/sun/star/style/TabStop.hpp>
+
+#include <com/sun/star/text/WritingMode2.hpp>
+
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+
+#include <i18nlangtag/languagetag.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+
+#include <stdio.h>
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
+typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
+
+#define STRNCMP_PARAM( s ) s,sizeof( s )-1
+
+/*****************************************************************************/
+
+static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
+static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
+// #i92232#
+static AtkTextAttribute atk_text_attribute_tracked_change = ATK_TEXT_ATTR_INVALID;
+// #i92233#
+static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio = ATK_TEXT_ATTR_INVALID;
+
+/*****************************************************************************/
+
+/**
+ * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
+ * and re-arrange the enum values accordingly.
+ */
+
+enum ExportedAttribute
+{
+ TEXT_ATTRIBUTE_BACKGROUND_COLOR = 0,
+ TEXT_ATTRIBUTE_CASEMAP,
+ TEXT_ATTRIBUTE_FOREGROUND_COLOR,
+ TEXT_ATTRIBUTE_CONTOURED,
+ TEXT_ATTRIBUTE_CHAR_ESCAPEMENT,
+ TEXT_ATTRIBUTE_BLINKING,
+ TEXT_ATTRIBUTE_FONT_NAME,
+ TEXT_ATTRIBUTE_HEIGHT,
+ TEXT_ATTRIBUTE_HIDDEN,
+ TEXT_ATTRIBUTE_KERNING,
+ TEXT_ATTRIBUTE_LOCALE,
+ TEXT_ATTRIBUTE_POSTURE,
+ TEXT_ATTRIBUTE_RELIEF,
+ TEXT_ATTRIBUTE_ROTATION,
+ TEXT_ATTRIBUTE_SCALE,
+ TEXT_ATTRIBUTE_SHADOWED,
+ TEXT_ATTRIBUTE_STRIKETHROUGH,
+ TEXT_ATTRIBUTE_UNDERLINE,
+ TEXT_ATTRIBUTE_WEIGHT,
+ // #i92233#
+ TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO,
+ TEXT_ATTRIBUTE_JUSTIFICATION,
+ TEXT_ATTRIBUTE_BOTTOM_MARGIN,
+ TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
+ TEXT_ATTRIBUTE_LEFT_MARGIN,
+ TEXT_ATTRIBUTE_LINE_SPACING,
+ TEXT_ATTRIBUTE_RIGHT_MARGIN,
+ TEXT_ATTRIBUTE_STYLE_NAME,
+ TEXT_ATTRIBUTE_TAB_STOPS,
+ TEXT_ATTRIBUTE_TOP_MARGIN,
+ TEXT_ATTRIBUTE_WRITING_MODE,
+ TEXT_ATTRIBUTE_LAST
+};
+
+static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
+{
+ "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
+ "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
+ "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
+ "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
+ "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
+ "CharFlash", // TEXT_ATTRIBUTE_BLINKING
+ "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
+ "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
+ "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
+ "CharKerning", // TEXT_ATTRIBUTE_KERNING
+ "CharLocale", // TEXT_ATTRIBUTE_LOCALE
+ "CharPosture", // TEXT_ATTRIBUTE_POSTURE
+ "CharRelief", // TEXT_ATTRIBUTE_RELIEF
+ "CharRotation", // TEXT_ATTRIBUTE_ROTATION
+ "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
+ "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
+ "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
+ "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
+ "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
+ // #i92233#
+ "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
+ "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
+ "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
+ "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
+ "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
+ "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
+ "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
+ "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
+ "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
+ "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
+ "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
+};
+
+/*****************************************************************************/
+
+static gchar*
+get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ sal_Int32 nIndex, AtkTextAttrFunc func )
+{
+ if( nIndex != -1 )
+ return func(rAttributeList[nIndex].Value);
+
+ return nullptr;
+}
+
+#define get_bool_value( list, index ) get_value( list, index, Bool2String )
+#define get_height_value( list, index ) get_value( list, index, Float2String )
+#define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
+#define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
+#define get_scale_width( list, index ) get_value( list, index, Scale2String )
+#define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
+#define get_string_value( list, index ) get_value( list, index, GetString )
+#define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
+#define get_underline_value( list, index ) get_value( list, index, Underline2String )
+#define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
+#define get_weight_value( list, index ) get_value( list, index, Weight2String )
+#define get_language_string( list, index ) get_value( list, index, Locale2String )
+
+static double toPoint(sal_Int16 n)
+{
+ // 100th mm -> pt
+ return static_cast<double>(n * 72) / 2540;
+}
+
+/*****************************************************************************/
+
+static bool
+InvalidValue( uno::Any&, const gchar * )
+{
+ return false;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Float2String(const uno::Any& rAny)
+{
+ return g_strdup_printf( "%g", rAny.get<float>() );
+}
+
+static bool
+String2Float( uno::Any& rAny, const gchar * value )
+{
+ float fval;
+
+ if( 1 != sscanf( value, "%g", &fval ) )
+ return false;
+
+ rAny <<= fval;
+ return true;
+}
+
+/*****************************************************************************/
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleComponent>
+ getComponent( AtkText *pText )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
+ if( pWrap )
+ {
+ if( !pWrap->mpComponent.is() )
+ {
+ pWrap->mpComponent.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpComponent;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleComponent>();
+}
+
+static gchar*
+get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ const sal_Int32 * pIndexArray,
+ ExportedAttribute attr,
+ AtkText * text)
+{
+ sal_Int32 nColor = -1; // AUTOMATIC
+ sal_Int32 nIndex = pIndexArray[attr];
+
+ if( nIndex != -1 )
+ nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
+
+ /*
+ * Check for color value for 100% alpha white, which means
+ * "automatic". Grab the RGB value from XAccessibleComponent
+ * in this case.
+ */
+
+ if( (nColor == -1) && text )
+ {
+ try
+ {
+ css::uno::Reference<css::accessibility::XAccessibleComponent>
+ pComponent = getComponent( text );
+ if( pComponent.is() )
+ {
+ switch( attr )
+ {
+ case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
+ nColor = pComponent->getBackground();
+ break;
+ case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
+ nColor = pComponent->getForeground();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ catch(const uno::Exception&) {
+ g_warning( "Exception in get[Fore|Back]groundColor()" );
+ }
+ }
+
+ if( nColor != -1 )
+ {
+ sal_uInt8 blue = nColor & 0xFF;
+ sal_uInt8 green = (nColor >> 8) & 0xFF;
+ sal_uInt8 red = (nColor >> 16) & 0xFF;
+
+ return g_strdup_printf( "%u,%u,%u", red, green, blue );
+ }
+
+ return nullptr;
+}
+
+static bool
+String2Color( uno::Any& rAny, const gchar * value )
+{
+ int red, green, blue;
+
+ if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
+ return false;
+
+ sal_Int32 nColor = static_cast<sal_Int32>(blue) | ( static_cast<sal_Int32>(green) << 8 ) | ( static_cast<sal_Int32>(red) << 16 );
+ rAny <<= nColor;
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+FontSlant2Style(const uno::Any& rAny)
+{
+ const gchar * value = nullptr;
+
+ awt::FontSlant aFontSlant;
+ if(!(rAny >>= aFontSlant))
+ return nullptr;
+
+ switch( aFontSlant )
+ {
+ case awt::FontSlant_NONE:
+ value = "normal";
+ break;
+
+ case awt::FontSlant_OBLIQUE:
+ value = "oblique";
+ break;
+
+ case awt::FontSlant_ITALIC:
+ value = "italic";
+ break;
+
+ case awt::FontSlant_REVERSE_OBLIQUE:
+ value = "reverse oblique";
+ break;
+
+ case awt::FontSlant_REVERSE_ITALIC:
+ value = "reverse italic";
+ break;
+
+ default:
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return nullptr;
+}
+
+static bool
+Style2FontSlant( uno::Any& rAny, const gchar * value )
+{
+ awt::FontSlant aFontSlant;
+
+ if( strncmp( value, STRNCMP_PARAM( "normal" ) ) == 0 )
+ aFontSlant = awt::FontSlant_NONE;
+ else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) == 0 )
+ aFontSlant = awt::FontSlant_OBLIQUE;
+ else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) == 0 )
+ aFontSlant = awt::FontSlant_ITALIC;
+ else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) == 0 )
+ aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
+ else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) == 0 )
+ aFontSlant = awt::FontSlant_REVERSE_ITALIC;
+ else
+ return false;
+
+ rAny <<= aFontSlant;
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Weight2String(const uno::Any& rAny)
+{
+ return g_strdup_printf( "%g", rAny.get<float>() * 4 );
+}
+
+static bool
+String2Weight( uno::Any& rAny, const gchar * value )
+{
+ float weight;
+
+ if( 1 != sscanf( value, "%g", &weight ) )
+ return false;
+
+ rAny <<= weight / 4;
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Adjust2Justification(const uno::Any& rAny)
+{
+ const gchar * value = nullptr;
+
+ switch( static_cast<style::ParagraphAdjust>(rAny.get<short>()) )
+ {
+ case style::ParagraphAdjust_LEFT:
+ value = "left";
+ break;
+
+ case style::ParagraphAdjust_RIGHT:
+ value = "right";
+ break;
+
+ case style::ParagraphAdjust_BLOCK:
+ case style::ParagraphAdjust_STRETCH:
+ value = "fill";
+ break;
+
+ case style::ParagraphAdjust_CENTER:
+ value = "center";
+ break;
+
+ default:
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return nullptr;
+}
+
+static bool
+Justification2Adjust( uno::Any& rAny, const gchar * value )
+{
+ style::ParagraphAdjust nParagraphAdjust;
+
+ if( strncmp( value, STRNCMP_PARAM( "left" ) ) == 0 )
+ nParagraphAdjust = style::ParagraphAdjust_LEFT;
+ else if( strncmp( value, STRNCMP_PARAM( "right" ) ) == 0 )
+ nParagraphAdjust = style::ParagraphAdjust_RIGHT;
+ else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) == 0 )
+ nParagraphAdjust = style::ParagraphAdjust_BLOCK;
+ else if( strncmp( value, STRNCMP_PARAM( "center" ) ) == 0 )
+ nParagraphAdjust = style::ParagraphAdjust_CENTER;
+ else
+ return false;
+
+ rAny <<= static_cast<short>(nParagraphAdjust);
+ return true;
+}
+
+/*****************************************************************************/
+
+const gchar * const font_strikethrough[] = {
+ "none", // FontStrikeout::NONE
+ "single", // FontStrikeout::SINGLE
+ "double", // FontStrikeout::DOUBLE
+ nullptr, // FontStrikeout::DONTKNOW
+ "bold", // FontStrikeout::BOLD
+ "with /", // FontStrikeout::SLASH
+ "with X" // FontStrikeout::X
+};
+
+static gchar*
+Strikeout2String(const uno::Any& rAny)
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+
+ if( n >= 0 && n < sal_Int16(SAL_N_ELEMENTS(font_strikethrough)) )
+ return g_strdup( font_strikethrough[n] );
+
+ return nullptr;
+}
+
+static bool
+String2Strikeout( uno::Any& rAny, const gchar * value )
+{
+ for( sal_Int16 n=0; n < sal_Int16(SAL_N_ELEMENTS(font_strikethrough)); ++n )
+ {
+ if( ( nullptr != font_strikethrough[n] ) &&
+ 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
+ {
+ rAny <<= n;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Underline2String(const uno::Any& rAny)
+{
+ const gchar * value = nullptr;
+
+ switch( rAny.get<sal_Int16>() )
+ {
+ case awt::FontUnderline::NONE:
+ value = "none";
+ break;
+
+ case awt::FontUnderline::SINGLE:
+ value = "single";
+ break;
+
+ case awt::FontUnderline::DOUBLE:
+ value = "double";
+ break;
+
+ default:
+ break;
+ }
+
+ if( value )
+ return g_strdup( value );
+
+ return nullptr;
+}
+
+static bool
+String2Underline( uno::Any& rAny, const gchar * value )
+{
+ short nUnderline;
+
+ if( strncmp( value, STRNCMP_PARAM( "none" ) ) == 0 )
+ nUnderline = awt::FontUnderline::NONE;
+ else if( strncmp( value, STRNCMP_PARAM( "single" ) ) == 0 )
+ nUnderline = awt::FontUnderline::SINGLE;
+ else if( strncmp( value, STRNCMP_PARAM( "double" ) ) == 0 )
+ nUnderline = awt::FontUnderline::DOUBLE;
+ else
+ return false;
+
+ rAny <<= nUnderline;
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+GetString(const uno::Any& rAny)
+{
+ OString aFontName = OUStringToOString( rAny.get< OUString > (), RTL_TEXTENCODING_UTF8 );
+
+ if( !aFontName.isEmpty() )
+ return g_strdup( aFontName.getStr() );
+
+ return nullptr;
+}
+
+static bool
+SetString( uno::Any& rAny, const gchar * value )
+{
+ OString aFontName( value );
+
+ if( !aFontName.isEmpty() )
+ {
+ rAny <<= OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 );
+ return true;
+ }
+
+ return false;
+}
+
+/*****************************************************************************/
+
+// @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
+
+// CMM = 100th of mm
+static gchar*
+CMM2UnitString(const uno::Any& rAny)
+{
+ double fValue = rAny.get<sal_Int32>();
+ fValue = fValue * 0.01;
+
+ return g_strdup_printf( "%gmm", fValue );
+}
+
+static bool
+UnitString2CMM( uno::Any& rAny, const gchar * value )
+{
+ float fValue = 0.0; // pb: don't use double here because of warning on linux
+
+ if( 1 != sscanf( value, "%gmm", &fValue ) )
+ return false;
+
+ fValue = fValue * 100;
+
+ rAny <<= static_cast<sal_Int32>(fValue);
+ return true;
+}
+
+/*****************************************************************************/
+
+static const gchar * bool_values[] = { "true", "false" };
+
+static gchar *
+Bool2String( const uno::Any& rAny )
+{
+ int n = 1;
+
+ if( rAny.get<bool>() )
+ n = 0;
+
+ return g_strdup( bool_values[n] );
+}
+
+static bool
+String2Bool( uno::Any& rAny, const gchar * value )
+{
+ bool bValue;
+
+ if( strncmp( value, STRNCMP_PARAM( "true" ) ) == 0 )
+ bValue = true;
+ else if( strncmp( value, STRNCMP_PARAM( "false" ) ) == 0 )
+ bValue = false;
+ else
+ return false;
+
+ rAny <<= bValue;
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar*
+Scale2String( const uno::Any& rAny )
+{
+ return g_strdup_printf( "%g", static_cast<double>(rAny.get< sal_Int16 > ()) / 100 );
+}
+
+static bool
+String2Scale( uno::Any& rAny, const gchar * value )
+{
+ double dval;
+
+ if( 1 != sscanf( value, "%lg", &dval ) )
+ return false;
+
+ rAny <<= static_cast<sal_Int16>(dval * 100);
+ return true;
+}
+
+/*****************************************************************************/
+
+static gchar *
+CaseMap2String( const uno::Any& rAny )
+{
+ const gchar * value;
+
+ switch( rAny.get<short>() )
+ {
+ case style::CaseMap::SMALLCAPS:
+ value = "small_caps";
+ break;
+
+ default:
+ value = "normal";
+ break;
+ }
+
+ return g_strdup(value);
+}
+
+static bool
+String2CaseMap( uno::Any& rAny, const gchar * value )
+{
+ short nCaseMap;
+
+ if( strncmp( value, STRNCMP_PARAM( "normal" ) ) == 0 )
+ nCaseMap = style::CaseMap::NONE;
+ else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) == 0 )
+ nCaseMap = style::CaseMap::SMALLCAPS;
+ else
+ return false;
+
+ rAny <<= nCaseMap;
+ return true;
+}
+
+/*****************************************************************************/
+
+const gchar * const font_stretch[] = {
+ "ultra_condensed",
+ "extra_condensed",
+ "condensed",
+ "semi_condensed",
+ "normal",
+ "semi_expanded",
+ "expanded",
+ "extra_expanded",
+ "ultra_expanded"
+};
+
+static gchar*
+Kerning2Stretch(const uno::Any& rAny)
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+ int i = 4;
+
+ // No good idea for a mapping - just return the basic info
+ if( n < 0 )
+ i=2;
+ else if( n > 0 )
+ i=6;
+
+ return g_strdup(font_stretch[i]);
+}
+
+/*****************************************************************************/
+
+static gchar*
+Locale2String(const uno::Any& rAny)
+{
+ /* FIXME-BCP47: support language tags? And why is country lowercase? */
+ lang::Locale aLocale = rAny.get<lang::Locale> ();
+ LanguageTag aLanguageTag( aLocale);
+ return g_strdup_printf( "%s-%s",
+ OUStringToOString( aLanguageTag.getLanguage(), RTL_TEXTENCODING_ASCII_US).getStr(),
+ OUStringToOString( aLanguageTag.getCountry(), RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
+}
+
+static bool
+String2Locale( uno::Any& rAny, const gchar * value )
+{
+ /* FIXME-BCP47: support language tags? */
+ bool ret = false;
+
+ gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
+ if( str_array[0] != nullptr )
+ {
+ ret = true;
+
+ lang::Locale aLocale;
+
+ aLocale.Language = OUString::createFromAscii(str_array[0]);
+ if( str_array[1] != nullptr )
+ {
+ gchar * country = g_ascii_strup(str_array[1], -1);
+ aLocale.Country = OUString::createFromAscii(country);
+ g_free(country);
+ }
+
+ rAny <<= aLocale;
+ }
+
+ g_strfreev(str_array);
+ return ret;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
+static const gchar * relief[] = { "none", "emboss", "engrave" };
+static const gchar * const outline = "outline";
+
+static gchar *
+get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
+{
+ if( nContourIndex != -1 )
+ {
+ if( rAttributeList[nContourIndex].Value.get<bool>() )
+ return g_strdup(outline);
+ }
+
+ if( nReliefIndex != -1 )
+ {
+ sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
+ if( n < 3)
+ return g_strdup(relief[n]);
+ }
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
+
+enum
+{
+ DECORATION_NONE = 0,
+ DECORATION_BLINK,
+ DECORATION_UNDERLINE,
+ DECORATION_LINE_THROUGH
+};
+
+static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
+
+static gchar *
+get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
+ sal_Int16 nStrikeoutIndex)
+{
+ gchar * value_list[4] = { nullptr, nullptr, nullptr, nullptr };
+ gint count = 0;
+
+ // no property value found
+ if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
+ return nullptr;
+
+ if( nBlinkIndex != -1 )
+ {
+ if( rAttributeList[nBlinkIndex].Value.get<bool>() )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
+ }
+ if( nUnderlineIndex != -1 )
+ {
+ sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
+ if( n != awt::FontUnderline::NONE )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
+ }
+ if( nStrikeoutIndex != -1 )
+ {
+ sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
+ if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
+ }
+
+ if( count == 0 )
+ value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
+
+ return g_strjoinv(" ", value_list);
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
+
+static const gchar * shadow_values[] = { "none", "black" };
+
+static gchar *
+Bool2Shadow( const uno::Any& rAny )
+{
+ int n = 0;
+
+ if( rAny.get<bool>() )
+ n = 1;
+
+ return g_strdup( shadow_values[n] );
+}
+
+/*****************************************************************************/
+
+static gchar *
+Short2Degree( const uno::Any& rAny )
+{
+ float f = rAny.get<sal_Int16>() / 10.0;
+ return g_strdup_printf( "%g", f );
+}
+
+/*****************************************************************************/
+
+const gchar * const directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
+
+static gchar *
+WritingMode2Direction( const uno::Any& rAny )
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+
+ if( 0 <= n && n <= text::WritingMode2::PAGE )
+ return g_strdup(directions[n]);
+
+ return nullptr;
+}
+
+// @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
+
+const gchar * const writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
+static gchar *
+WritingMode2String( const uno::Any& rAny )
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+
+ if( 0 <= n && n <= text::WritingMode2::PAGE )
+ return g_strdup(writing_modes[n]);
+
+ return nullptr;
+}
+
+/*****************************************************************************/
+
+const char * const baseline_values[] = { "baseline", "sub", "super" };
+
+// @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
+static gchar *
+Escapement2VerticalAlign( const uno::Any& rAny )
+{
+ sal_Int16 n = rAny.get<sal_Int16>();
+ gchar * ret = nullptr;
+
+ // Values are in %, 101% means "automatic"
+ if( n == 0 )
+ ret = g_strdup(baseline_values[0]);
+ else if( n == 101 )
+ ret = g_strdup(baseline_values[2]);
+ else if( n == -101 )
+ ret = g_strdup(baseline_values[1]);
+ else
+ ret = g_strdup_printf( "%d%%", n );
+
+ return ret;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
+static gchar *
+LineSpacing2LineHeight( const uno::Any& rAny )
+{
+ style::LineSpacing ls;
+ gchar * ret = nullptr;
+
+ if( rAny >>= ls )
+ {
+ if( ls.Mode == style::LineSpacingMode::PROP )
+ ret = g_strdup_printf( "%d%%", ls.Height );
+ else if( ls.Mode == style::LineSpacingMode::FIX )
+ ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+
+// @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
+static gchar *
+TabStopList2String( const uno::Any& rAny, bool default_tabs )
+{
+ uno::Sequence< style::TabStop > theTabStops;
+ gchar * ret = nullptr;
+
+ if( rAny >>= theTabStops)
+ {
+ sal_Unicode lastFillChar = ' ';
+
+ for( const auto& rTabStop : std::as_const(theTabStops) )
+ {
+ bool is_default_tab = (style::TabAlign_DEFAULT == rTabStop.Alignment);
+
+ if( is_default_tab != default_tabs )
+ continue;
+
+ double fValue = rTabStop.Position;
+ fValue = fValue * 0.01;
+
+ const gchar * tab_align = "";
+ switch( rTabStop.Alignment )
+ {
+ case style::TabAlign_LEFT :
+ tab_align = "left ";
+ break;
+ case style::TabAlign_CENTER :
+ tab_align = "center ";
+ break;
+ case style::TabAlign_RIGHT :
+ tab_align = "right ";
+ break;
+ case style::TabAlign_DECIMAL :
+ tab_align = "decimal ";
+ break;
+ default:
+ break;
+ }
+
+ const gchar * lead_char = "";
+
+ if( rTabStop.FillChar != lastFillChar )
+ {
+ lastFillChar = rTabStop.FillChar;
+ switch (lastFillChar)
+ {
+ case ' ':
+ lead_char = "blank ";
+ break;
+
+ case '.':
+ lead_char = "dotted ";
+ break;
+
+ case '-':
+ lead_char = "dashed ";
+ break;
+
+ case '_':
+ lead_char = "lined ";
+ break;
+
+ default:
+ lead_char = "custom ";
+ break;
+ }
+ }
+
+ gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
+
+ if( ret )
+ {
+ gchar * old_tab_str = ret;
+ ret = g_strconcat(old_tab_str, " ", tab_str, nullptr);
+ g_free( old_tab_str );
+ }
+ else
+ ret = tab_str;
+ }
+ }
+
+ return ret;
+}
+
+static gchar *
+TabStops2String( const uno::Any& rAny )
+{
+ return TabStopList2String(rAny, false);
+}
+
+static gchar *
+DefaultTabStops2String( const uno::Any& rAny )
+{
+ return TabStopList2String(rAny, true);
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+static int
+attr_compare(const void *p1,const void *p2)
+{
+ const rtl_uString * pustr = static_cast<const rtl_uString *>(p1);
+ const char * pc = *static_cast<const char * const *>(p2);
+
+ return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
+}
+
+}
+
+static void
+find_exported_attributes( sal_Int32 *pArray,
+ const css::uno::Sequence< css::beans::PropertyValue >& rAttributeList )
+{
+ for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
+ {
+ const char ** pAttr = static_cast<const char **>(bsearch(rAttributeList[i].Name.pData,
+ ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
+ attr_compare));
+
+ if( pAttr )
+ {
+ sal_Int32 nIndex = pAttr - ExportedTextAttributes;
+ pArray[nIndex] = i;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static AtkAttributeSet*
+attribute_set_prepend( AtkAttributeSet* attribute_set,
+ AtkTextAttribute attribute,
+ gchar * value )
+{
+ if( value )
+ {
+ AtkAttribute *at = static_cast<AtkAttribute *>(g_malloc( sizeof (AtkAttribute) ));
+ at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
+ at->value = value;
+
+ return g_slist_prepend(attribute_set, at);
+ }
+
+ return attribute_set;
+}
+
+/*****************************************************************************/
+
+AtkAttributeSet*
+attribute_set_new_from_property_values(
+ const uno::Sequence< beans::PropertyValue >& rAttributeList,
+ bool run_attributes_only,
+ AtkText *text)
+{
+ AtkAttributeSet* attribute_set = nullptr;
+
+ sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
+
+ // Initialize index array with -1
+ for(sal_Int32 & rn : aIndexList)
+ rn = -1;
+
+ find_exported_attributes(aIndexList, rAttributeList);
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
+ get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? nullptr : text ) );
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
+ get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? nullptr : text) );
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
+ get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
+ get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
+ get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
+ get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
+ get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
+ get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
+ get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
+ get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
+ get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
+ get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
+ atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
+ get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
+ atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
+ get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
+ aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
+ atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
+ atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
+ atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
+ atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
+
+ if( run_attributes_only )
+ return attribute_set;
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
+ get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
+
+ attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
+ get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
+ atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
+ get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
+ atk_text_attribute_line_height = atk_text_attribute_register("line-height");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
+ atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
+
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
+ atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
+
+ attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
+
+ // #i92233#
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_mm_to_pixel_ratio )
+ atk_text_attribute_mm_to_pixel_ratio = atk_text_attribute_register("mm-to-pixel-ratio");
+
+ attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_mm_to_pixel_ratio,
+ get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO], Float2String));
+
+ return attribute_set;
+}
+
+AtkAttributeSet*
+attribute_set_new_from_extended_attributes(
+ const css::uno::Reference< css::accessibility::XAccessibleExtendedAttributes >& rExtendedAttributes )
+{
+ AtkAttributeSet *pSet = nullptr;
+
+ // extended attributes is a string of colon-separated pairs of property and value,
+ // with pairs separated by semicolons. Example: "heading-level:2;weight:bold;"
+ uno::Any anyVal = rExtendedAttributes->getExtendedAttributes();
+ OUString sExtendedAttrs;
+ anyVal >>= sExtendedAttrs;
+ sal_Int32 nIndex = 0;
+ do
+ {
+ OUString sProperty = sExtendedAttrs.getToken( 0, ';', nIndex );
+
+ sal_Int32 nColonPos = 0;
+ OString sPropertyName = OUStringToOString( sProperty.getToken( 0, ':', nColonPos ),
+ RTL_TEXTENCODING_UTF8 );
+ OString sPropertyValue = OUStringToOString( sProperty.getToken( 0, ':', nColonPos ),
+ RTL_TEXTENCODING_UTF8 );
+
+ pSet = attribute_set_prepend( pSet,
+ atk_text_attribute_register( sPropertyName.getStr() ),
+ g_strdup_printf( "%s", sPropertyValue.getStr() ) );
+ }
+ while ( nIndex >= 0 && nIndex < sExtendedAttrs.getLength() );
+
+ return pSet;
+}
+
+AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
+{
+ if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
+ atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
+
+ attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
+ g_strdup_printf( "misspelled" ) );
+
+ return attribute_set;
+}
+
+// #i92232#
+AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set )
+{
+ if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
+ {
+ atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
+ }
+
+ attribute_set = attribute_set_prepend( attribute_set,
+ atk_text_attribute_tracked_change,
+ g_strdup_printf( "insertion" ) );
+
+ return attribute_set;
+}
+
+AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set )
+{
+ if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
+ {
+ atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
+ }
+
+ attribute_set = attribute_set_prepend( attribute_set,
+ atk_text_attribute_tracked_change,
+ g_strdup_printf( "deletion" ) );
+
+ return attribute_set;
+}
+
+AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set )
+{
+ if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
+ {
+ atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
+ }
+
+ attribute_set = attribute_set_prepend( attribute_set,
+ atk_text_attribute_tracked_change,
+ g_strdup_printf( "attribute-change" ) );
+
+ return attribute_set;
+}
+
+/*****************************************************************************/
+
+struct AtkTextAttrMapping
+{
+ const char * name;
+ TextPropertyValueFunc const toPropertyValue;
+};
+
+const AtkTextAttrMapping g_TextAttrMap[] =
+{
+ { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
+ { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
+ { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
+ { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
+ { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
+ { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
+ { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
+ { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
+ { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
+ { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
+ { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
+ { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
+ { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
+ { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
+ { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
+ { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
+ { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
+ { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
+ { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
+ { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
+ { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
+ { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
+ { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
+ { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
+ { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
+};
+
+/*****************************************************************************/
+
+bool
+attribute_set_map_to_property_values(
+ AtkAttributeSet* attribute_set,
+ uno::Sequence< beans::PropertyValue >& rValueList )
+{
+ // Ensure enough space ..
+ uno::Sequence< beans::PropertyValue > aAttributeList (SAL_N_ELEMENTS(g_TextAttrMap));
+
+ sal_Int32 nIndex = 0;
+ for( GSList * item = attribute_set; item != nullptr; item = g_slist_next( item ) )
+ {
+ AtkAttribute* attribute = reinterpret_cast<AtkAttribute *>(item);
+
+ AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
+ if( text_attr < SAL_N_ELEMENTS(g_TextAttrMap) )
+ {
+ if( g_TextAttrMap[text_attr].name[0] != '\0' )
+ {
+ if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
+ return false;
+
+ aAttributeList[nIndex].Name = OUString::createFromAscii( g_TextAttrMap[text_attr].name );
+ aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
+ ++nIndex;
+ }
+ }
+ else
+ {
+ // Unsupported text attribute
+ return false;
+ }
+ }
+
+ aAttributeList.realloc( nIndex );
+ rValueList = aAttributeList;
+ return true;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkutil.cxx b/vcl/unx/gtk3/a11y/gtk3atkutil.cxx
index 8c1eeaf9882b..cac3ac6e4805 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkutil.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkutil.cxx
@@ -5,8 +5,785 @@
* 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 .
*/
-#include "../../gtk/a11y/atkutil.cxx"
+#ifdef AIX
+#define _LINUX_SOURCE_COMPAT
+#include <sys/timer.h>
+#undef _LINUX_SOURCE_COMPAT
+#endif
+
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/toolbox.hxx>
+
+#include <unx/gtk/gtkdata.hxx>
+#include "atkwrapper.hxx"
+#include "atkutil.hxx"
+
+#include <gtk/gtk.h>
+#include <config_version.h>
+
+#include <cassert>
+#include <set>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+ struct theNextFocusObject :
+ public rtl::Static< uno::WeakReference< accessibility::XAccessible >, theNextFocusObject>
+ {
+ };
+}
+
+static guint focus_notify_handler = 0;
+
+/*****************************************************************************/
+
+extern "C" {
+
+static gboolean
+atk_wrapper_focus_idle_handler (gpointer data)
+{
+ SolarMutexGuard aGuard;
+
+ focus_notify_handler = 0;
+
+ uno::Reference< accessibility::XAccessible > xAccessible = theNextFocusObject::get();
+ if( xAccessible.get() == static_cast < accessibility::XAccessible * > (data) )
+ {
+ AtkObject *atk_obj = xAccessible.is() ? atk_object_wrapper_ref( xAccessible ) : nullptr;
+ // Gail does not notify focus changes to NULL, so do we ..
+ if( atk_obj )
+ {
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ atk_focus_tracker_notify(atk_obj);
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ // #i93269#
+ // emit text_caret_moved event for <XAccessibleText> object,
+ // if cursor is inside the <XAccessibleText> object.
+ // also emit state-changed:focused event under the same condition.
+ {
+ AtkObjectWrapper* wrapper_obj = ATK_OBJECT_WRAPPER (atk_obj);
+ if( wrapper_obj && !wrapper_obj->mpText.is() )
+ {
+ wrapper_obj->mpText.set(wrapper_obj->mpContext, css::uno::UNO_QUERY);
+ if ( wrapper_obj->mpText.is() )
+ {
+ gint caretPos = -1;
+
+ try {
+ caretPos = wrapper_obj->mpText->getCaretPosition();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCaretPosition()" );
+ }
+
+ if ( caretPos != -1 )
+ {
+ atk_object_notify_state_change( atk_obj, ATK_STATE_FOCUSED, TRUE );
+ g_signal_emit_by_name( atk_obj, "text_caret_moved", caretPos );
+ }
+ }
+ }
+ }
+ g_object_unref(atk_obj);
+ }
+ }
+
+ return false;
+}
+
+} // extern "C"
+
+/*****************************************************************************/
+
+static void
+atk_wrapper_focus_tracker_notify_when_idle( const uno::Reference< accessibility::XAccessible > &xAccessible )
+{
+ if( focus_notify_handler )
+ g_source_remove(focus_notify_handler);
+
+ theNextFocusObject::get() = xAccessible;
+
+ focus_notify_handler = g_idle_add (atk_wrapper_focus_idle_handler, xAccessible.get());
+}
+
+/*****************************************************************************/
+
+class DocumentFocusListener :
+ public ::cppu::WeakImplHelper< accessibility::XAccessibleEventListener >
+{
+
+ std::set< uno::Reference< uno::XInterface > > m_aRefList;
+
+public:
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void detachRecursive(
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ void detachRecursive(
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+ );
+
+ /// @throws lang::IndexOutOfBoundsException
+ /// @throws uno::RuntimeException
+ static uno::Reference< accessibility::XAccessible > getAccessible(const lang::EventObject& aEvent );
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
+
+ // XAccessibleEventListener
+ virtual void SAL_CALL notifyEvent( const accessibility::AccessibleEventObject& aEvent ) override;
+};
+
+/*****************************************************************************/
+
+void DocumentFocusListener::disposing( const lang::EventObject& aEvent )
+{
+
+ // Unref the object here, but do not remove as listener since the object
+ // might no longer be in a state that safely allows this.
+ if( aEvent.Source.is() )
+ m_aRefList.erase(aEvent.Source);
+
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
+{
+ try {
+ switch( aEvent.EventId )
+ {
+ case accessibility::AccessibleEventId::STATE_CHANGED:
+ {
+ sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
+ aEvent.NewValue >>= nState;
+
+ if( accessibility::AccessibleStateType::FOCUSED == nState )
+ atk_wrapper_focus_tracker_notify_when_idle( getAccessible(aEvent) );
+
+ break;
+ }
+
+ case accessibility::AccessibleEventId::CHILD:
+ {
+ uno::Reference< accessibility::XAccessible > xChild;
+ if( (aEvent.OldValue >>= xChild) && xChild.is() )
+ detachRecursive(xChild);
+
+ if( (aEvent.NewValue >>= xChild) && xChild.is() )
+ attachRecursive(xChild);
+
+ break;
+ }
+
+ case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
+ SAL_INFO("vcl.a11y", "Invalidate all children called");
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch( const lang::IndexOutOfBoundsException& e )
+ {
+ g_warning("Focused object has invalid index in parent");
+ }
+}
+
+/*****************************************************************************/
+
+uno::Reference< accessibility::XAccessible > DocumentFocusListener::getAccessible(const lang::EventObject& aEvent )
+{
+ uno::Reference< accessibility::XAccessible > xAccessible(aEvent.Source, uno::UNO_QUERY);
+
+ if( xAccessible.is() )
+ return xAccessible;
+
+ uno::Reference< accessibility::XAccessibleContext > xContext(aEvent.Source, uno::UNO_QUERY);
+
+ if( xContext.is() )
+ {
+ uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
+ if( xParent.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if( xParentContext.is() )
+ {
+ return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() );
+ }
+ }
+ }
+
+ return uno::Reference< accessibility::XAccessible >();
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+)
+{
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( xContext.is() )
+ attachRecursive(xAccessible, xContext);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+)
+{
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
+ xContext->getAccessibleStateSet();
+
+ if( xStateSet.is() )
+ attachRecursive(xAccessible, xContext, xStateSet);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::attachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible,
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+)
+{
+ if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED ) )
+ atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
+
+ uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
+
+ if (!xBroadcaster.is())
+ return;
+
+ // If not already done, add the broadcaster to the list and attach as listener.
+ const uno::Reference< uno::XInterface >& xInterface = xBroadcaster;
+ if( m_aRefList.insert(xInterface).second )
+ {
+ xBroadcaster->addAccessibleEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
+
+ if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
+ {
+ sal_Int32 n, nmax = xContext->getAccessibleChildCount();
+ for( n = 0; n < nmax; n++ )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
+
+ if( xChild.is() )
+ attachRecursive(xChild);
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::detachRecursive(
+ const uno::Reference< accessibility::XAccessible >& xAccessible
+)
+{
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( xContext.is() )
+ detachRecursive(xContext);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::detachRecursive(
+ const uno::Reference< accessibility::XAccessibleContext >& xContext
+)
+{
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
+ xContext->getAccessibleStateSet();
+
+ if( xStateSet.is() )
+ detachRecursive(xContext, xStateSet);
+}
+
+/*****************************************************************************/
+
+void DocumentFocusListener::detachRecursive(
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
+)
+{
+ uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
+
+ if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) )
+ {
+ xBroadcaster->removeAccessibleEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
+
+ if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
+ {
+ sal_Int32 n, nmax = xContext->getAccessibleChildCount();
+ for( n = 0; n < nmax; n++ )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
+
+ if( xChild.is() )
+ detachRecursive(xChild);
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/*
+ * page tabs in gtk are widgets, so we need to simulate focus events for those
+ */
+
+static void handle_tabpage_activated(vcl::Window *pWindow)
+{
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ pWindow->GetAccessible();
+
+ if( ! xAccessible.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleSelection > xSelection(
+ xAccessible->getAccessibleContext(), uno::UNO_QUERY);
+
+ if( xSelection.is() )
+ atk_wrapper_focus_tracker_notify_when_idle( xSelection->getSelectedAccessibleChild(0) );
+}
+
+/*****************************************************************************/
+
+/*
+ * toolbar items in gtk are widgets, so we need to simulate focus events for those
+ */
+
+static void notify_toolbox_item_focus(ToolBox *pToolBox)
+{
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ pToolBox->GetAccessible();
+
+ if( ! xAccessible.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( ! xContext.is() )
+ return;
+
+ ToolBox::ImplToolItems::size_type nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
+ if( nPos != ToolBox::ITEM_NOTFOUND )
+ atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32
+}
+
+static void handle_toolbox_highlight(vcl::Window *pWindow)
+{
+ ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
+
+ // Make sure either the toolbox or its parent toolbox has the focus
+ if ( ! pToolBox->HasFocus() )
+ {
+ ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
+ if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
+ return;
+ }
+
+ notify_toolbox_item_focus(pToolBox);
+}
+
+static void handle_toolbox_highlightoff(vcl::Window const *pWindow)
+{
+ ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pWindow->GetParent() );
+
+ // Notify when leaving sub toolboxes
+ if( pToolBoxParent && pToolBoxParent->HasFocus() )
+ notify_toolbox_item_focus( pToolBoxParent );
+}
+
+/*****************************************************************************/
+
+static void create_wrapper_for_child(
+ const uno::Reference< accessibility::XAccessibleContext >& xContext,
+ sal_Int32 index)
+{
+ if( xContext.is() )
+ {
+ uno::Reference< accessibility::XAccessible > xChild(xContext->getAccessibleChild(index));
+ if( xChild.is() )
+ {
+ // create the wrapper object - it will survive the unref unless it is a transient object
+ g_object_unref( atk_object_wrapper_ref( xChild ) );
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static void handle_toolbox_buttonchange(VclWindowEvent const *pEvent)
+{
+ vcl::Window* pWindow = pEvent->GetWindow();
+ sal_Int32 index = static_cast<sal_Int32>(reinterpret_cast<sal_IntPtr>(pEvent->GetData()));
+
+ if( pWindow && pWindow->IsReallyVisible() )
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
+ if( xAccessible.is() )
+ {
+ create_wrapper_for_child(xAccessible->getAccessibleContext(), index);
+ }
+ }
+}
+
+/*****************************************************************************/
+
+namespace {
+
+struct WindowList {
+ ~WindowList() { assert(list.empty()); };
+ // needs to be empty already on DeInitVCL, but at least check it's empty
+ // on exit
+
+ std::set< VclPtr<vcl::Window> > list;
+};
+
+WindowList g_aWindowList;
+
+}
+
+DocumentFocusListener & GtkSalData::GetDocumentFocusListener()
+{
+ if (!m_pDocumentFocusListener)
+ {
+ m_pDocumentFocusListener = new DocumentFocusListener;
+ m_xDocumentFocusListener.set(m_pDocumentFocusListener);
+ }
+ return *m_pDocumentFocusListener;
+}
+
+static void handle_get_focus(::VclWindowEvent const * pEvent)
+{
+ GtkSalData *const pSalData(GetGtkSalData());
+ assert(pSalData);
+
+ DocumentFocusListener & rDocumentFocusListener(pSalData->GetDocumentFocusListener());
+
+ vcl::Window *pWindow = pEvent->GetWindow();
+
+ // The menu bar is handled through VclEventId::MenuHighlightED
+ if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WindowType::MENUBARWINDOW )
+ return;
+
+ // ToolBoxes are handled through VclEventId::ToolboxHighlight
+ if( pWindow->GetType() == WindowType::TOOLBOX )
+ return;
+
+ if( pWindow->GetType() == WindowType::TABCONTROL )
+ {
+ handle_tabpage_activated( pWindow );
+ return;
+ }
+
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ pWindow->GetAccessible();
+
+ if( ! xAccessible.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleContext > xContext =
+ xAccessible->getAccessibleContext();
+
+ if( ! xContext.is() )
+ return;
+
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
+ xContext->getAccessibleStateSet();
+
+ if( ! xStateSet.is() )
+ return;
+
+/* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
+ * need to add listeners to the children instead of re-using the tabpage stuff
+ */
+ if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED) &&
+ ( pWindow->GetType() != WindowType::TREELISTBOX ) )
+ {
+ atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
+ }
+ else
+ {
+ if( g_aWindowList.list.insert(pWindow).second )
+ {
+ try
+ {
+ rDocumentFocusListener.attachRecursive(xAccessible, xContext, xStateSet);
+ }
+ catch (const uno::Exception&)
+ {
+ g_warning( "Exception caught processing focus events" );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static void handle_menu_highlighted(::VclMenuEvent const * pEvent)
+{
+ try
+ {
+ Menu* pMenu = pEvent->GetMenu();
+ sal_uInt16 nPos = pEvent->GetItemPos();
+
+ if( pMenu && nPos != 0xFFFF)
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible ( pMenu->GetAccessible() );
+
+ if( xAccessible.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xContext ( xAccessible->getAccessibleContext() );
+
+ if( xContext.is() )
+ atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ g_warning( "Exception caught processing menu highlight events" );
+ }
+}
+
+/*****************************************************************************/
+
+static void WindowEventHandler(void *, VclSimpleEvent& rEvent)
+{
+ try
+ {
+ switch (rEvent.GetId())
+ {
+ case VclEventId::WindowShow:
+ break;
+ case VclEventId::WindowHide:
+ break;
+ case VclEventId::WindowClose:
+ break;
+ case VclEventId::WindowGetFocus:
+ handle_get_focus(static_cast< ::VclWindowEvent const * >(&rEvent));
+ break;
+ case VclEventId::WindowLoseFocus:
+ break;
+ case VclEventId::WindowMinimize:
+ break;
+ case VclEventId::WindowNormalize:
+ break;
+ case VclEventId::WindowKeyInput:
+ case VclEventId::WindowKeyUp:
+ case VclEventId::WindowCommand:
+ case VclEventId::WindowMouseMove:
+ break;
+
+ case VclEventId::MenuHighlight:
+ if (const VclMenuEvent* pMenuEvent = dynamic_cast<const VclMenuEvent*>(&rEvent))
+ {
+ handle_menu_highlighted(pMenuEvent);
+ }
+ else if (const VclAccessibleEvent* pAccEvent = dynamic_cast<const VclAccessibleEvent*>(&rEvent))
+ {
+ const uno::Reference< accessibility::XAccessible >& xAccessible = pAccEvent->GetAccessible();
+ if (xAccessible.is())
+ atk_wrapper_focus_tracker_notify_when_idle(xAccessible);
+ }
+ break;
+
+ case VclEventId::ToolboxHighlight:
+ handle_toolbox_highlight(static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow());
+ break;
+
+ case VclEventId::ToolboxButtonStateChanged:
+ handle_toolbox_buttonchange(static_cast< ::VclWindowEvent const * >(&rEvent));
+ break;
+
+ case VclEventId::ObjectDying:
+ g_aWindowList.list.erase( static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow() );
+ [[fallthrough]];
+ case VclEventId::ToolboxHighlightOff:
+ handle_toolbox_highlightoff(static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow());
+ break;
+
+ case VclEventId::TabpageActivate:
+ handle_tabpage_activated(static_cast< ::VclWindowEvent const * >(&rEvent)->GetWindow());
+ break;
+
+ case VclEventId::ComboboxSetText:
+ // This looks quite strange to me. Stumbled over this when fixing #i104290#.
+ // This kicked in when leaving the combobox in the toolbar, after that the events worked.
+ // I guess this was a try to work around missing combobox events, which didn't do the full job, and shouldn't be necessary anymore.
+ // Fix for #i104290# was done in toolkit/source/awt/vclxaccessiblecomponent, FOCUSED state for compound controls in general.
+ // create_wrapper_for_children(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch (const lang::IndexOutOfBoundsException&)
+ {
+ g_warning("Focused object has invalid index in parent");
+ }
+}
+
+static Link<VclSimpleEvent&,void> g_aEventListenerLink( nullptr, WindowEventHandler );
+
+/*****************************************************************************/
+
+extern "C" {
+
+static G_CONST_RETURN gchar *
+ooo_atk_util_get_toolkit_name()
+{
+ return "VCL";
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar *
+ooo_atk_util_get_toolkit_version()
+{
+ return LIBO_VERSION_DOTTED;
+}
+
+/*****************************************************************************/
+
+/*
+ * GObject inheritance
+ */
+
+static void
+ooo_atk_util_class_init (AtkUtilClass *)
+{
+ AtkUtilClass *atk_class;
+ gpointer data;
+
+ data = g_type_class_peek (ATK_TYPE_UTIL);
+ atk_class = ATK_UTIL_CLASS (data);
+
+ atk_class->get_toolkit_name = ooo_atk_util_get_toolkit_name;
+ atk_class->get_toolkit_version = ooo_atk_util_get_toolkit_version;
+
+ ooo_atk_util_ensure_event_listener();
+}
+
+} // extern "C"
+
+void ooo_atk_util_ensure_event_listener()
+{
+ static bool bInited;
+ if (!bInited)
+ {
+ Application::AddEventListener( g_aEventListenerLink );
+ bInited = true;
+ }
+}
+
+GType
+ooo_atk_util_get_type()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ GType parent_type = g_type_from_name( "GailUtil" );
+
+ if( ! parent_type )
+ {
+ g_warning( "Unknown type: GailUtil" );
+ parent_type = ATK_TYPE_UTIL;
+ }
+
+ GTypeQuery type_query;
+ g_type_query( parent_type, &type_query );
+
+ static const GTypeInfo typeInfo =
+ {
+ static_cast<guint16>(type_query.class_size),
+ nullptr,
+ nullptr,
+ reinterpret_cast<GClassInitFunc>(ooo_atk_util_class_init),
+ nullptr,
+ nullptr,
+ static_cast<guint16>(type_query.instance_size),
+ 0,
+ nullptr,
+ nullptr
+ } ;
+
+ type = g_type_register_static (parent_type, "OOoUtil", &typeInfo, GTypeFlags(0)) ;
+ }
+
+ return type;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkvalue.cxx b/vcl/unx/gtk3/a11y/gtk3atkvalue.cxx
index 30057943bc44..f5e45d3b2556 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkvalue.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkvalue.cxx
@@ -5,8 +5,134 @@
* 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 .
*/
-#include "../../gtk/a11y/atkvalue.cxx"
+#include "atkwrapper.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+
+#include <string.h>
+
+using namespace ::com::sun::star;
+
+/// @throws uno::RuntimeException
+static css::uno::Reference<css::accessibility::XAccessibleValue>
+ getValue( AtkValue *pValue )
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pValue );
+ if( pWrap )
+ {
+ if( !pWrap->mpValue.is() )
+ {
+ pWrap->mpValue.set(pWrap->mpContext, css::uno::UNO_QUERY);
+ }
+
+ return pWrap->mpValue;
+ }
+
+ return css::uno::Reference<css::accessibility::XAccessibleValue>();
+}
+
+static void anyToGValue( const uno::Any& aAny, GValue *pValue )
+{
+ // FIXME: expand to lots of types etc.
+ double aDouble=0;
+ aAny >>= aDouble;
+
+ memset( pValue, 0, sizeof( GValue ) );
+ g_value_init( pValue, G_TYPE_DOUBLE );
+ g_value_set_double( pValue, aDouble );
+}
+
+extern "C" {
+
+static void
+value_wrapper_get_current_value( AtkValue *value,
+ GValue *gval )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleValue> pValue
+ = getValue( value );
+ if( pValue.is() )
+ anyToGValue( pValue->getCurrentValue(), gval );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+}
+
+static void
+value_wrapper_get_maximum_value( AtkValue *value,
+ GValue *gval )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleValue> pValue
+ = getValue( value );
+ if( pValue.is() )
+ anyToGValue( pValue->getMaximumValue(), gval );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+}
+
+static void
+value_wrapper_get_minimum_value( AtkValue *value,
+ GValue *gval )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleValue> pValue
+ = getValue( value );
+ if( pValue.is() )
+ anyToGValue( pValue->getMinimumValue(), gval );
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+}
+
+static gboolean
+value_wrapper_set_current_value( AtkValue *value,
+ const GValue *gval )
+{
+ try {
+ css::uno::Reference<css::accessibility::XAccessibleValue> pValue
+ = getValue( value );
+ if( pValue.is() )
+ {
+ // FIXME - this needs expanding
+ double aDouble = g_value_get_double( gval );
+ return pValue->setCurrentValue( uno::Any(aDouble) );
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getCurrentValue()" );
+ }
+
+ return FALSE;
+}
+
+} // extern "C"
+
+void
+valueIfaceInit (AtkValueIface *iface)
+{
+ g_return_if_fail (iface != nullptr);
+
+ iface->get_current_value = value_wrapper_get_current_value;
+ iface->get_maximum_value = value_wrapper_get_maximum_value;
+ iface->get_minimum_value = value_wrapper_get_minimum_value;
+ iface->set_current_value = value_wrapper_set_current_value;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkwindow.cxx b/vcl/unx/gtk3/a11y/gtk3atkwindow.cxx
index cd8479cd4df7..eb72edf4908c 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkwindow.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkwindow.cxx
@@ -5,8 +5,326 @@
* 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 .
*/
-#include "../../gtk/a11y/atkwindow.cxx"
+#include <unx/gtk/gtkframe.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/popupmenuwindow.hxx>
+#include <sal/log.hxx>
+
+#include "atkwindow.hxx"
+#include "atkwrapper.hxx"
+#include "atkregistry.hxx"
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+
+extern "C" {
+
+static void (* window_real_initialize) (AtkObject *obj, gpointer data) = nullptr;
+static void (* window_real_finalize) (GObject *obj) = nullptr;
+
+static void
+init_from_window( AtkObject *accessible, vcl::Window const *pWindow )
+{
+ static AtkRole aDefaultRole = ATK_ROLE_INVALID;
+
+ // Special role for sub-menu and combo-box popups that are exposed directly
+ // by their parents already.
+ if( aDefaultRole == ATK_ROLE_INVALID )
+ {
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ aDefaultRole = atk_role_register( "redundant object" );
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ }
+
+ AtkRole role = aDefaultRole;
+
+ // Determine the appropriate role for the GtkWindow
+ switch( pWindow->GetAccessibleRole() )
+ {
+ case AccessibleRole::ALERT:
+ role = ATK_ROLE_ALERT;
+ break;
+
+ case AccessibleRole::DIALOG:
+ role = ATK_ROLE_DIALOG;
+ break;
+
+ case AccessibleRole::FRAME:
+ role = ATK_ROLE_FRAME;
+ break;
+
+ /* Ignore window objects for sub-menus, combo- and list boxes,
+ * which are exposed as children of their parents.
+ */
+ case AccessibleRole::WINDOW:
+ {
+ WindowType type = WindowType::WINDOW;
+ bool parentIsMenuFloatingWindow = false;
+
+ vcl::Window *pParent = pWindow->GetParent();
+ if( pParent ) {
+ type = pParent->GetType();
+ parentIsMenuFloatingWindow = pParent->IsMenuFloatingWindow();
+ }
+
+ if( (WindowType::LISTBOX != type) && (WindowType::COMBOBOX != type) &&
+ (WindowType::MENUBARWINDOW != type) && ! parentIsMenuFloatingWindow )
+ {
+ role = ATK_ROLE_WINDOW;
+ }
+ }
+ break;
+
+ default:
+ {
+ vcl::Window *pChild = pWindow->GetWindow(GetWindowType::FirstChild);
+ if( pChild )
+ {
+ if( WindowType::HELPTEXTWINDOW == pChild->GetType() )
+ {
+ role = ATK_ROLE_TOOL_TIP;
+ pChild->SetAccessibleRole( AccessibleRole::LABEL );
+ accessible->name = g_strdup( OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ else if ( pWindow->GetType() == WindowType::BORDERWINDOW && pChild->GetType() == WindowType::FLOATINGWINDOW )
+ {
+ PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
+ if (p && p->IsPopupMenu() && p->GetMenuStackLevel() == 0)
+ {
+ // This is a top-level menu popup. Register it.
+ role = ATK_ROLE_POPUP_MENU;
+ pChild->SetAccessibleRole( AccessibleRole::POPUP_MENU );
+ accessible->name = g_strdup( OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ accessible->role = role;
+}
+
+/*****************************************************************************/
+
+static gboolean
+ooo_window_wrapper_clear_focus(gpointer)
+{
+ SolarMutexGuard aGuard;
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ atk_focus_tracker_notify( nullptr );
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ return false;
+}
+
+/*****************************************************************************/
+
+static gboolean
+ooo_window_wrapper_real_focus_gtk (GtkWidget *, GdkEventFocus *)
+{
+ g_idle_add( ooo_window_wrapper_clear_focus, nullptr );
+ return false;
+}
+
+static gboolean ooo_tooltip_map( GtkWidget* pToolTip, gpointer )
+{
+ AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
+ if( pAccessible )
+ atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, TRUE );
+ return FALSE;
+}
+
+static gboolean ooo_tooltip_unmap( GtkWidget* pToolTip, gpointer )
+{
+ AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
+ if( pAccessible )
+ atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, FALSE );
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+static bool
+isChildPopupMenu(vcl::Window* pWindow)
+{
+ vcl::Window* pChild = pWindow->GetAccessibleChildWindow(0);
+ if (!pChild)
+ return false;
+
+ if (WindowType::FLOATINGWINDOW != pChild->GetType())
+ return false;
+
+ PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
+ if (!p)
+ return false;
+
+ return p->IsPopupMenu();
+}
+
+static void
+ooo_window_wrapper_real_initialize(AtkObject *obj, gpointer data)
+{
+ window_real_initialize(obj, data);
+
+ GtkSalFrame *pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( data ) );
+ if( pFrame )
+ {
+ vcl::Window *pWindow = pFrame->GetWindow();
+ if( pWindow )
+ {
+ init_from_window( obj, pWindow );
+
+ Reference< XAccessible > xAccessible( pWindow->GetAccessible() );
+
+ /* We need the wrapper object for the top-level XAccessible to be
+ * in the wrapper registry when atk traverses the hierarchy up on
+ * focus events
+ */
+ if( WindowType::BORDERWINDOW == pWindow->GetType() )
+ {
+ if ( isChildPopupMenu(pWindow) )
+ {
+ AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
+ ooo_wrapper_registry_add( xAccessible, child );
+ }
+ else
+ {
+ ooo_wrapper_registry_add( xAccessible, obj );
+ g_object_set_data( G_OBJECT(obj), "ooo:atk-wrapper-key", xAccessible.get() );
+ }
+ }
+ else
+ {
+ AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
+ child->role = ATK_ROLE_FILLER;
+ if( (ATK_ROLE_DIALOG == obj->role) || (ATK_ROLE_ALERT == obj->role) )
+ child->role = ATK_ROLE_OPTION_PANE;
+ ooo_wrapper_registry_add( xAccessible, child );
+ }
+ }
+ }
+
+ g_signal_connect_after( GTK_WIDGET( data ), "focus-out-event",
+ G_CALLBACK (ooo_window_wrapper_real_focus_gtk),
+ nullptr);
+
+ if( obj->role == ATK_ROLE_TOOL_TIP )
+ {
+ g_signal_connect_after( GTK_WIDGET( data ), "map-event",
+ G_CALLBACK (ooo_tooltip_map),
+ nullptr);
+ g_signal_connect_after( GTK_WIDGET( data ), "unmap-event",
+ G_CALLBACK (ooo_tooltip_unmap),
+ nullptr);
+ }
+}
+
+/*****************************************************************************/
+
+static void
+ooo_window_wrapper_real_finalize (GObject *obj)
+{
+ ooo_wrapper_registry_remove( static_cast<XAccessible *>(g_object_get_data( obj, "ooo:atk-wrapper-key" )));
+ window_real_finalize( obj );
+}
+
+/*****************************************************************************/
+
+static void
+ooo_window_wrapper_class_init (AtkObjectClass *klass, gpointer)
+{
+ AtkObjectClass *atk_class;
+ GObjectClass *gobject_class;
+ gpointer data;
+
+ /*
+ * Patch the gobject vtable of GailWindow to refer to our instance of
+ * "initialize".
+ */
+
+ data = g_type_class_peek_parent( klass );
+ atk_class = ATK_OBJECT_CLASS (data);
+
+ window_real_initialize = atk_class->initialize;
+ atk_class->initialize = ooo_window_wrapper_real_initialize;
+
+ gobject_class = G_OBJECT_CLASS (data);
+
+ window_real_finalize = gobject_class->finalize;
+ gobject_class->finalize = ooo_window_wrapper_real_finalize;
+}
+
+} // extern "C"
+
+/*****************************************************************************/
+
+GType
+ooo_window_wrapper_get_type()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ GType parent_type = g_type_from_name( "GailWindow" );
+
+ if( ! parent_type )
+ {
+ SAL_INFO("vcl.a11y", "Unknown type: GailWindow");
+ parent_type = ATK_TYPE_OBJECT;
+ }
+
+ GTypeQuery type_query;
+ g_type_query( parent_type, &type_query );
+
+ static const GTypeInfo typeInfo =
+ {
+ static_cast<guint16>(type_query.class_size),
+ nullptr,
+ nullptr,
+ reinterpret_cast<GClassInitFunc>(ooo_window_wrapper_class_init),
+ nullptr,
+ nullptr,
+ static_cast<guint16>(type_query.instance_size),
+ 0,
+ nullptr,
+ nullptr
+ } ;
+
+ type = g_type_register_static (parent_type, "OOoWindowAtkObject", &typeInfo, GTypeFlags(0)) ;
+ }
+
+ return type;
+}
+
+void restore_gail_window_vtable()
+{
+ AtkObjectClass *atk_class;
+ gpointer data;
+
+ GType type = g_type_from_name( "GailWindow" );
+
+ if( type == G_TYPE_INVALID )
+ return;
+
+ data = g_type_class_peek( type );
+ atk_class = ATK_OBJECT_CLASS (data);
+
+ atk_class->initialize = window_real_initialize;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/a11y/gtk3atkwrapper.cxx b/vcl/unx/gtk3/a11y/gtk3atkwrapper.cxx
index 3b07e9536d77..0998553bd927 100644
--- a/vcl/unx/gtk3/a11y/gtk3atkwrapper.cxx
+++ b/vcl/unx/gtk3/a11y/gtk3atkwrapper.cxx
@@ -5,8 +5,955 @@
* 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 .
*/
-#include "../../gtk/a11y/atkwrapper.cxx"
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleRelation.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+#include <com/sun/star/accessibility/XAccessibleAction.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext2.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
+#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+#include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
+#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/awt/XExtendedToolkit.hpp>
+#include <com/sun/star/awt/XTopWindow.hpp>
+#include <com/sun/star/awt/XTopWindowListener.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/beans/Property.hpp>
+
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.hxx>
+#include <osl/diagnose.h>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include "atkwrapper.hxx"
+#include "atkregistry.hxx"
+#include "atklistener.hxx"
+#include "atktextattributes.hxx"
+
+#include <string.h>
+#include <vector>
+
+using namespace ::com::sun::star;
+
+static GObjectClass *parent_class = nullptr;
+
+static AtkRelationType mapRelationType( sal_Int16 nRelation )
+{
+ AtkRelationType type = ATK_RELATION_NULL;
+
+ switch( nRelation )
+ {
+ case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
+ type = ATK_RELATION_FLOWS_FROM;
+ break;
+
+ case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
+ type = ATK_RELATION_FLOWS_TO;
+ break;
+
+ case accessibility::AccessibleRelationType::CONTROLLED_BY:
+ type = ATK_RELATION_CONTROLLED_BY;
+ break;
+
+ case accessibility::AccessibleRelationType::CONTROLLER_FOR:
+ type = ATK_RELATION_CONTROLLER_FOR;
+ break;
+
+ case accessibility::AccessibleRelationType::LABEL_FOR:
+ type = ATK_RELATION_LABEL_FOR;
+ break;
+
+ case accessibility::AccessibleRelationType::LABELED_BY:
+ type = ATK_RELATION_LABELLED_BY;
+ break;
+
+ case accessibility::AccessibleRelationType::MEMBER_OF:
+ type = ATK_RELATION_MEMBER_OF;
+ break;
+
+ case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
+ type = ATK_RELATION_SUBWINDOW_OF;
+ break;
+
+ case accessibility::AccessibleRelationType::NODE_CHILD_OF:
+ type = ATK_RELATION_NODE_CHILD_OF;
+ break;
+
+ default:
+ break;
+ }
+
+ return type;
+}
+
+AtkStateType mapAtkState( sal_Int16 nState )
+{
+ AtkStateType type = ATK_STATE_INVALID;
+
+ // A perfect / complete mapping ...
+ switch( nState )
+ {
+#define MAP_DIRECT( a ) \
+ case accessibility::AccessibleStateType::a: \
+ type = ATK_STATE_##a; break
+
+ MAP_DIRECT( INVALID );
+ MAP_DIRECT( ACTIVE );
+ MAP_DIRECT( ARMED );
+ MAP_DIRECT( BUSY );
+ MAP_DIRECT( CHECKED );
+ MAP_DIRECT( EDITABLE );
+ MAP_DIRECT( ENABLED );
+ MAP_DIRECT( EXPANDABLE );
+ MAP_DIRECT( EXPANDED );
+ MAP_DIRECT( FOCUSABLE );
+ MAP_DIRECT( FOCUSED );
+ MAP_DIRECT( HORIZONTAL );
+ MAP_DIRECT( ICONIFIED );
+ MAP_DIRECT( INDETERMINATE );
+ MAP_DIRECT( MANAGES_DESCENDANTS );
+ MAP_DIRECT( MODAL );
+ MAP_DIRECT( MULTI_LINE );
+ MAP_DIRECT( OPAQUE );
+ MAP_DIRECT( PRESSED );
+ MAP_DIRECT( RESIZABLE );
+ MAP_DIRECT( SELECTABLE );
+ MAP_DIRECT( SELECTED );
+ MAP_DIRECT( SENSITIVE );
+ MAP_DIRECT( SHOWING );
+ MAP_DIRECT( SINGLE_LINE );
+ MAP_DIRECT( STALE );
+ MAP_DIRECT( TRANSIENT );
+ MAP_DIRECT( VERTICAL );
+ MAP_DIRECT( VISIBLE );
+ MAP_DIRECT( DEFAULT );
+ // a spelling error ...
+ case accessibility::AccessibleStateType::DEFUNC:
+ type = ATK_STATE_DEFUNCT; break;
+ case accessibility::AccessibleStateType::MULTI_SELECTABLE:
+ type = ATK_STATE_MULTISELECTABLE; break;
+ default:
+ //Mis-use ATK_STATE_LAST_DEFINED to check if a state is unmapped
+ //NOTE! Do not report it
+ type = ATK_STATE_LAST_DEFINED;
+ break;
+ }
+
+ return type;
+}
+
+static AtkRole getRoleForName( const gchar * name )
+{
+ AtkRole ret = atk_role_for_name( name );
+ if( ATK_ROLE_INVALID == ret )
+ {
+ // this should only happen in old ATK versions
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ ret = atk_role_register( name );
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+ }
+
+ return ret;
+}
+
+static AtkRole mapToAtkRole( sal_Int16 nRole )
+{
+ AtkRole role = ATK_ROLE_UNKNOWN;
+
+ static AtkRole roleMap[] = {
+ ATK_ROLE_UNKNOWN,
+ ATK_ROLE_ALERT,
+ ATK_ROLE_COLUMN_HEADER,
+ ATK_ROLE_CANVAS,
+ ATK_ROLE_CHECK_BOX,
+ ATK_ROLE_CHECK_MENU_ITEM,
+ ATK_ROLE_COLOR_CHOOSER,
+ ATK_ROLE_COMBO_BOX,
+ ATK_ROLE_DATE_EDITOR,
+ ATK_ROLE_DESKTOP_ICON,
+ ATK_ROLE_DESKTOP_FRAME, // ? pane
+ ATK_ROLE_DIRECTORY_PANE,
+ ATK_ROLE_DIALOG,
+ ATK_ROLE_UNKNOWN, // DOCUMENT - registered below
+ ATK_ROLE_UNKNOWN, // EMBEDDED_OBJECT - registered below
+ ATK_ROLE_UNKNOWN, // END_NOTE - registered below
+ ATK_ROLE_FILE_CHOOSER,
+ ATK_ROLE_FILLER,
+ ATK_ROLE_FONT_CHOOSER,
+ ATK_ROLE_FOOTER,
+ ATK_ROLE_UNKNOWN, // FOOTNOTE - registered below
+ ATK_ROLE_FRAME,
+ ATK_ROLE_GLASS_PANE,
+ ATK_ROLE_IMAGE, // GRAPHIC
+ ATK_ROLE_UNKNOWN, // GROUP_BOX - registered below
+ ATK_ROLE_HEADER,
+ ATK_ROLE_HEADING,
+ ATK_ROLE_TEXT, // HYPER_LINK - registered below
+ ATK_ROLE_ICON,
+ ATK_ROLE_INTERNAL_FRAME,
+ ATK_ROLE_LABEL,
+ ATK_ROLE_LAYERED_PANE,
+ ATK_ROLE_LIST,
+ ATK_ROLE_LIST_ITEM,
+ ATK_ROLE_MENU,
+ ATK_ROLE_MENU_BAR,
+ ATK_ROLE_MENU_ITEM,
+ ATK_ROLE_OPTION_PANE,
+ ATK_ROLE_PAGE_TAB,
+ ATK_ROLE_PAGE_TAB_LIST,
+ ATK_ROLE_PANEL,
+ ATK_ROLE_PARAGRAPH,
+ ATK_ROLE_PASSWORD_TEXT,
+ ATK_ROLE_POPUP_MENU,
+ ATK_ROLE_PUSH_BUTTON,
+ ATK_ROLE_PROGRESS_BAR,
+ ATK_ROLE_RADIO_BUTTON,
+ ATK_ROLE_RADIO_MENU_ITEM,
+ ATK_ROLE_ROW_HEADER,
+ ATK_ROLE_ROOT_PANE,
+ ATK_ROLE_SCROLL_BAR,
+ ATK_ROLE_SCROLL_PANE,
+ ATK_ROLE_PANEL, // SHAPE
+ ATK_ROLE_SEPARATOR,
+ ATK_ROLE_SLIDER,
+ ATK_ROLE_SPIN_BUTTON, // SPIN_BOX ?
+ ATK_ROLE_SPLIT_PANE,
+ ATK_ROLE_STATUSBAR,
+ ATK_ROLE_TABLE,
+ ATK_ROLE_TABLE_CELL,
+ ATK_ROLE_TEXT,
+ ATK_ROLE_PANEL, // TEXT_FRAME
+ ATK_ROLE_TOGGLE_BUTTON,
+ ATK_ROLE_TOOL_BAR,
+ ATK_ROLE_TOOL_TIP,
+ ATK_ROLE_TREE,
+ ATK_ROLE_VIEWPORT,
+ ATK_ROLE_WINDOW,
+ ATK_ROLE_PUSH_BUTTON, // BUTTON_DROPDOWN
+ ATK_ROLE_PUSH_BUTTON, // BUTTON_MENU
+ ATK_ROLE_UNKNOWN, // CAPTION - registered below
+ ATK_ROLE_UNKNOWN, // CHART - registered below
+ ATK_ROLE_UNKNOWN, // EDIT_BAR - registered below
+ ATK_ROLE_UNKNOWN, // FORM - registered below
+ ATK_ROLE_UNKNOWN, // IMAGE_MAP - registered below
+ ATK_ROLE_UNKNOWN, // NOTE - registered below
+ ATK_ROLE_UNKNOWN, // PAGE - registered below
+ ATK_ROLE_RULER,
+ ATK_ROLE_UNKNOWN, // SECTION - registered below
+ ATK_ROLE_UNKNOWN, // TREE_ITEM - registered below
+ ATK_ROLE_TREE_TABLE,
+ ATK_ROLE_SCROLL_PANE, // COMMENT - mapped to atk_role_scroll_pane
+ ATK_ROLE_UNKNOWN // COMMENT_END - mapped to atk_role_unknown
+#if defined(ATK_CHECK_VERSION)
+ //older ver that doesn't define ATK_CHECK_VERSION doesn't have the following
+ , ATK_ROLE_DOCUMENT_PRESENTATION
+ , ATK_ROLE_DOCUMENT_SPREADSHEET
+ , ATK_ROLE_DOCUMENT_TEXT
+#if ATK_CHECK_VERSION(2,15,2)
+ , ATK_ROLE_STATIC
+#else
+ , ATK_ROLE_LABEL
+#endif
+#else
+ //older version should fallback to DOCUMENT_FRAME role
+ , ATK_ROLE_DOCUMENT_FRAME
+ , ATK_ROLE_DOCUMENT_FRAME
+ , ATK_ROLE_DOCUMENT_FRAME
+ , ATK_ROLE_LABEL
+#endif
+ };
+
+ static bool initialized = false;
+
+ if( ! initialized )
+ {
+ // the accessible roles below were added to ATK in later versions,
+ // with role_for_name we will know if they exist in runtime.
+ roleMap[accessibility::AccessibleRole::EDIT_BAR] = getRoleForName("edit bar");
+ roleMap[accessibility::AccessibleRole::EMBEDDED_OBJECT] = getRoleForName("embedded");
+ roleMap[accessibility::AccessibleRole::CHART] = getRoleForName("chart");
+ roleMap[accessibility::AccessibleRole::CAPTION] = getRoleForName("caption");
+ roleMap[accessibility::AccessibleRole::DOCUMENT] = getRoleForName("document frame");
+ roleMap[accessibility::AccessibleRole::PAGE] = getRoleForName("page");
+ roleMap[accessibility::AccessibleRole::SECTION] = getRoleForName("section");
+ roleMap[accessibility::AccessibleRole::FORM] = getRoleForName("form");
+ roleMap[accessibility::AccessibleRole::GROUP_BOX] = getRoleForName("grouping");
+ roleMap[accessibility::AccessibleRole::COMMENT] = getRoleForName("comment");
+ roleMap[accessibility::AccessibleRole::IMAGE_MAP] = getRoleForName("image map");
+ roleMap[accessibility::AccessibleRole::TREE_ITEM] = getRoleForName("tree item");
+ roleMap[accessibility::AccessibleRole::HYPER_LINK] = getRoleForName("link");
+ roleMap[accessibility::AccessibleRole::END_NOTE] = getRoleForName("footnote");
+ roleMap[accessibility::AccessibleRole::FOOTNOTE] = getRoleForName("footnote");
+ roleMap[accessibility::AccessibleRole::NOTE] = getRoleForName("comment");
+
+ initialized = true;
+ }
+
+ static const sal_Int32 nMapSize = SAL_N_ELEMENTS(roleMap);
+ if( 0 <= nRole && nMapSize > nRole )
+ role = roleMap[nRole];
+
+ return role;
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar*
+wrapper_get_name( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ OString aName =
+ OUStringToOString(
+ obj->mpContext->getAccessibleName(),
+ RTL_TEXTENCODING_UTF8);
+
+ int nCmp = atk_obj->name ? rtl_str_compare( atk_obj->name, aName.getStr() ) : -1;
+ if( nCmp != 0 )
+ {
+ if( atk_obj->name )
+ g_free(atk_obj->name);
+ atk_obj->name = g_strdup(aName.getStr());
+ }
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleName()" );
+ }
+ }
+
+ return ATK_OBJECT_CLASS (parent_class)->get_name(atk_obj);
+}
+
+/*****************************************************************************/
+
+static G_CONST_RETURN gchar*
+wrapper_get_description( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ OString aDescription =
+ OUStringToOString(
+ obj->mpContext->getAccessibleDescription(),
+ RTL_TEXTENCODING_UTF8);
+
+ g_free(atk_obj->description);
+ atk_obj->description = g_strdup(aDescription.getStr());
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleDescription()" );
+ }
+ }
+
+ return ATK_OBJECT_CLASS (parent_class)->get_description(atk_obj);
+
+}
+
+/*****************************************************************************/
+
+static AtkAttributeSet *
+wrapper_get_attributes( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER( atk_obj );
+ AtkAttributeSet *pSet = nullptr;
+
+ try
+ {
+ uno::Reference< accessibility::XAccessibleExtendedAttributes >
+ xExtendedAttrs( obj->mpContext, uno::UNO_QUERY );
+ if( xExtendedAttrs.is() )
+ pSet = attribute_set_new_from_extended_attributes( xExtendedAttrs );
+ }
+ catch(const uno::Exception&)
+ {
+ g_warning( "Exception in getAccessibleAttributes()" );
+ }
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+static gint
+wrapper_get_n_children( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ gint n = 0;
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ n = obj->mpContext->getAccessibleChildCount();
+ }
+ catch(const uno::Exception&) {
+ OSL_FAIL("Exception in getAccessibleChildCount()" );
+ }
+ }
+
+ return n;
+}
+
+/*****************************************************************************/
+
+static AtkObject *
+wrapper_ref_child( AtkObject *atk_obj,
+ gint i )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ AtkObject* child = nullptr;
+
+ // see comments above atk_object_wrapper_remove_child
+ if( -1 < i && obj->index_of_child_about_to_be_removed == i )
+ {
+ g_object_ref( obj->child_about_to_be_removed );
+ return obj->child_about_to_be_removed;
+ }
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ uno::Reference< accessibility::XAccessible > xAccessible =
+ obj->mpContext->getAccessibleChild( i );
+
+ child = atk_object_wrapper_ref( xAccessible );
+ }
+ catch(const uno::Exception&) {
+ OSL_FAIL("Exception in getAccessibleChild");
+ }
+ }
+
+ return child;
+}
+
+/*****************************************************************************/
+
+static gint
+wrapper_get_index_in_parent( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit a11y
+ if (obj->mpOrig)
+ return atk_object_get_index_in_parent(obj->mpOrig);
+
+ gint i = -1;
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ i = obj->mpContext->getAccessibleIndexInParent();
+ }
+ catch(const uno::Exception&) {
+ g_warning( "Exception in getAccessibleIndexInParent()" );
+ }
+ }
+ return i;
+}
+
+/*****************************************************************************/
+
+AtkRelation*
+atk_object_wrapper_relation_new(const accessibility::AccessibleRelation& rRelation)
+{
+ sal_uInt32 nTargetCount = rRelation.TargetSet.getLength();
+
+ std::vector<AtkObject*> aTargets;
+
+ for (const auto& rTarget : rRelation.TargetSet)
+ {
+ uno::Reference< accessibility::XAccessible > xAccessible( rTarget, uno::UNO_QUERY );
+ aTargets.push_back(atk_object_wrapper_ref(xAccessible));
+ }
+
+ AtkRelation *pRel =
+ atk_relation_new(
+ aTargets.data(), nTargetCount,
+ mapRelationType( rRelation.RelationType )
+ );
+
+ return pRel;
+}
+
+static AtkRelationSet *
+wrapper_ref_relation_set( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+
+ //if we're a native GtkDrawingArea with custom a11y, use the default toolkit relation set impl
+ if (obj->mpOrig)
+ return atk_object_ref_relation_set(obj->mpOrig);
+
+ AtkRelationSet *pSet = atk_relation_set_new();
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ uno::Reference< accessibility::XAccessibleRelationSet > xRelationSet(
+ obj->mpContext->getAccessibleRelationSet()
+ );
+
+ sal_Int32 nRelations = xRelationSet.is() ? xRelationSet->getRelationCount() : 0;
+ for( sal_Int32 n = 0; n < nRelations; n++ )
+ {
+ AtkRelation *pRel = atk_object_wrapper_relation_new(xRelationSet->getRelation(n));
+ atk_relation_set_add(pSet, pRel);
+ g_object_unref(pRel);
+ }
+ }
+ catch(const uno::Exception &) {
+ g_object_unref( G_OBJECT( pSet ) );
+ pSet = nullptr;
+ }
+ }
+
+ return pSet;
+}
+
+static AtkStateSet *
+wrapper_ref_state_set( AtkObject *atk_obj )
+{
+ AtkObjectWrapper *obj = ATK_OBJECT_WRAPPER (atk_obj);
+ AtkStateSet *pSet = atk_state_set_new();
+
+ if( obj->mpContext.is() )
+ {
+ try {
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet(
+ obj->mpContext->getAccessibleStateSet());
+
+ if( xStateSet.is() )
+ {
+ uno::Sequence< sal_Int16 > aStates = xStateSet->getStates();
+
+ for( const auto nState : aStates )
+ {
+ // ATK_STATE_LAST_DEFINED is used to check if the state
+ // is unmapped, do not report it to Atk
+ if ( mapAtkState( nState ) != ATK_STATE_LAST_DEFINED )
+ atk_state_set_add_state( pSet, mapAtkState( nState ) );
+ }
+
+ // We need to emulate FOCUS state for menus, menu-items etc.
+ if( atk_obj == atk_get_focus_object() )
+ atk_state_set_add_state( pSet, ATK_STATE_FOCUSED );
+/* FIXME - should we do this ?
+ else
+ atk_state_set_remove_state( pSet, ATK_STATE_FOCUSED );
+*/
+ }
+ }
+
+ catch(const uno::Exception &) {
+ g_warning( "Exception in wrapper_ref_state_set" );
+ atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
+ }
+ }
+ else
+ atk_state_set_add_state( pSet, ATK_STATE_DEFUNCT );
+
+ return pSet;
+}
+
+/*****************************************************************************/
+
+static void
+atk_object_wrapper_finalize (GObject *obj)
+{
+ AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER (obj);
+
+ if( pWrap->mpAccessible.is() )
+ {
+ ooo_wrapper_registry_remove( pWrap->mpAccessible );
+ pWrap->mpAccessible.clear();
+ }
+
+ atk_object_wrapper_dispose( pWrap );
+
+ parent_class->finalize( obj );
+}
+
+static void
+atk_object_wrapper_class_init (AtkObjectWrapperClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS( klass );
+
+ parent_class = static_cast<GObjectClass *>(g_type_class_peek_parent (klass));
+
+ // GObject methods
+ gobject_class->finalize = atk_object_wrapper_finalize;
+
+ // AtkObject methods
+ atk_class->get_name = wrapper_get_name;
+ atk_class->get_description = wrapper_get_description;
+ atk_class->get_attributes = wrapper_get_attributes;
+ atk_class->get_n_children = wrapper_get_n_children;
+ atk_class->ref_child = wrapper_ref_child;
+ atk_class->get_index_in_parent = wrapper_get_index_in_parent;
+ atk_class->ref_relation_set = wrapper_ref_relation_set;
+ atk_class->ref_state_set = wrapper_ref_state_set;
+}
+
+static void
+atk_object_wrapper_init (AtkObjectWrapper *wrapper,
+ AtkObjectWrapperClass*)
+{
+ wrapper->mpAction = nullptr;
+ wrapper->mpComponent = nullptr;
+ wrapper->mpEditableText = nullptr;
+ wrapper->mpHypertext = nullptr;
+ wrapper->mpImage = nullptr;
+ wrapper->mpSelection = nullptr;
+ wrapper->mpTable = nullptr;
+ wrapper->mpText = nullptr;
+ wrapper->mpValue = nullptr;
+}
+
+} // extern "C"
+
+GType
+atk_object_wrapper_get_type()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo typeInfo =
+ {
+ sizeof (AtkObjectWrapperClass),
+ nullptr,
+ nullptr,
+ reinterpret_cast<GClassInitFunc>(atk_object_wrapper_class_init),
+ nullptr,
+ nullptr,
+ sizeof (AtkObjectWrapper),
+ 0,
+ reinterpret_cast<GInstanceInitFunc>(atk_object_wrapper_init),
+ nullptr
+ } ;
+ type = g_type_register_static (ATK_TYPE_OBJECT,
+ "OOoAtkObj",
+ &typeInfo, GTypeFlags(0)) ;
+ }
+ return type;
+}
+
+static bool
+isOfType( uno::XInterface *pInterface, const uno::Type & rType )
+{
+ g_return_val_if_fail( pInterface != nullptr, false );
+
+ bool bIs = false;
+ try {
+ uno::Any aRet = pInterface->queryInterface( rType );
+
+ bIs = ( ( typelib_TypeClass_INTERFACE == aRet.pType->eTypeClass ) &&
+ ( aRet.pReserved != nullptr ) );
+ } catch( const uno::Exception &) { }
+
+ return bIs;
+}
+
+extern "C" {
+typedef GType (* GetGIfaceType ) ();
+}
+const struct {
+ const char *name;
+ GInterfaceInitFunc const aInit;
+ GetGIfaceType const aGetGIfaceType;
+ const uno::Type & (*aGetUnoType) ();
+} aTypeTable[] = {
+// re-location heaven:
+ {
+ "Comp", reinterpret_cast<GInterfaceInitFunc>(componentIfaceInit),
+ atk_component_get_type,
+ cppu::UnoType<accessibility::XAccessibleComponent>::get
+ },
+ {
+ "Act", reinterpret_cast<GInterfaceInitFunc>(actionIfaceInit),
+ atk_action_get_type,
+ cppu::UnoType<accessibility::XAccessibleAction>::get
+ },
+ {
+ "Txt", reinterpret_cast<GInterfaceInitFunc>(textIfaceInit),
+ atk_text_get_type,
+ cppu::UnoType<accessibility::XAccessibleText>::get
+ },
+ {
+ "Val", reinterpret_cast<GInterfaceInitFunc>(valueIfaceInit),
+ atk_value_get_type,
+ cppu::UnoType<accessibility::XAccessibleValue>::get
+ },
+ {
+ "Tab", reinterpret_cast<GInterfaceInitFunc>(tableIfaceInit),
+ atk_table_get_type,
+ cppu::UnoType<accessibility::XAccessibleTable>::get
+ },
+ {
+ "Edt", reinterpret_cast<GInterfaceInitFunc>(editableTextIfaceInit),
+ atk_editable_text_get_type,
+ cppu::UnoType<accessibility::XAccessibleEditableText>::get
+ },
+ {
+ "Img", reinterpret_cast<GInterfaceInitFunc>(imageIfaceInit),
+ atk_image_get_type,
+ cppu::UnoType<accessibility::XAccessibleImage>::get
+ },
+ {
+ "Hyp", reinterpret_cast<GInterfaceInitFunc>(hypertextIfaceInit),
+ atk_hypertext_get_type,
+ cppu::UnoType<accessibility::XAccessibleHypertext>::get
+ },
+ {
+ "Sel", reinterpret_cast<GInterfaceInitFunc>(selectionIfaceInit),
+ atk_selection_get_type,
+ cppu::UnoType<accessibility::XAccessibleSelection>::get
+ }
+ // AtkDocument is a nastily broken interface (so far)
+ // we could impl. get_document_type perhaps though.
+};
+
+const int aTypeTableSize = G_N_ELEMENTS( aTypeTable );
+
+static GType
+ensureTypeFor( uno::XInterface *pAccessible )
+{
+ int i;
+ bool bTypes[ aTypeTableSize ] = { false, };
+ OStringBuffer aTypeNameBuf( "OOoAtkObj" );
+
+ for( i = 0; i < aTypeTableSize; i++ )
+ {
+ if( isOfType( pAccessible, aTypeTable[i].aGetUnoType() ) )
+ {
+ aTypeNameBuf.append(aTypeTable[i].name);
+ bTypes[i] = true;
+ }
+ }
+
+ OString aTypeName = aTypeNameBuf.makeStringAndClear();
+ GType nType = g_type_from_name( aTypeName.getStr() );
+ if( nType == G_TYPE_INVALID )
+ {
+ GTypeInfo aTypeInfo = {
+ sizeof( AtkObjectWrapperClass ),
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ sizeof( AtkObjectWrapper ),
+ 0, nullptr, nullptr
+ } ;
+ nType = g_type_register_static( ATK_TYPE_OBJECT_WRAPPER,
+ aTypeName.getStr(), &aTypeInfo,
+ GTypeFlags(0) ) ;
+
+ for( int j = 0; j < aTypeTableSize; j++ )
+ if( bTypes[j] )
+ {
+ GInterfaceInfo aIfaceInfo = { nullptr, nullptr, nullptr };
+ aIfaceInfo.interface_init = aTypeTable[j].aInit;
+ g_type_add_interface_static (nType, aTypeTable[j].aGetGIfaceType(),
+ &aIfaceInfo);
+ }
+ }
+ return nType;
+}
+
+AtkObject *
+atk_object_wrapper_ref( const uno::Reference< accessibility::XAccessible > &rxAccessible, bool create )
+{
+ g_return_val_if_fail( rxAccessible.get() != nullptr, nullptr );
+
+ AtkObject *obj = ooo_wrapper_registry_get(rxAccessible);
+ if( obj )
+ {
+ g_object_ref( obj );
+ return obj;
+ }
+
+ if( create )
+ return atk_object_wrapper_new( rxAccessible );
+
+ return nullptr;
+}
+
+AtkObject *
+atk_object_wrapper_new( const css::uno::Reference< css::accessibility::XAccessible >& rxAccessible,
+ AtkObject* parent, AtkObject* orig )
+{
+ g_return_val_if_fail( rxAccessible.get() != nullptr, nullptr );
+
+ AtkObjectWrapper *pWrap = nullptr;
+
+ try {
+ uno::Reference< accessibility::XAccessibleContext > xContext(rxAccessible->getAccessibleContext());
+
+ g_return_val_if_fail( xContext.get() != nullptr, nullptr );
+
+ GType nType = ensureTypeFor( xContext.get() );
+ gpointer obj = g_object_new( nType, nullptr);
+
+ pWrap = ATK_OBJECT_WRAPPER( obj );
+ pWrap->mpAccessible = rxAccessible;
+
+ pWrap->index_of_child_about_to_be_removed = -1;
+ pWrap->child_about_to_be_removed = nullptr;
+
+ pWrap->mpContext = xContext;
+ pWrap->mpOrig = orig;
+
+ AtkObject* atk_obj = ATK_OBJECT(pWrap);
+ atk_obj->role = mapToAtkRole( xContext->getAccessibleRole() );
+ atk_obj->accessible_parent = parent;
+
+ ooo_wrapper_registry_add( rxAccessible, atk_obj );
+
+ if( parent )
+ g_object_ref( atk_obj->accessible_parent );
+ else
+ {
+ /* gail_focus_tracker remembers the focused object at the first
+ * parent in the hierarchy that is a Gtk+ widget, but at the time the
+ * event gets processed (at idle), it may be too late to create the
+ * hierarchy, so doing it now ..
+ */
+ uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
+
+ if( xParent.is() )
+ atk_obj->accessible_parent = atk_object_wrapper_ref( xParent );
+ }
+
+ // Attach a listener to the UNO object if it's not TRANSIENT
+ uno::Reference< accessibility::XAccessibleStateSet > xStateSet( xContext->getAccessibleStateSet() );
+ if( xStateSet.is() && ! xStateSet->contains( accessibility::AccessibleStateType::TRANSIENT ) )
+ {
+ uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
+ if( xBroadcaster.is() )
+ {
+ uno::Reference<accessibility::XAccessibleEventListener> xListener(new AtkListener(pWrap));
+ xBroadcaster->addAccessibleEventListener(xListener);
+ }
+ else
+ OSL_ASSERT( false );
+ }
+
+#if ATK_CHECK_VERSION(2,33,1)
+ {
+ css::uno::Reference<css::accessibility::XAccessibleContext2> xContext2(xContext, css::uno::UNO_QUERY);
+ if( xContext2.is() )
+ {
+ OString aId = OUStringToOString( xContext2->getAccessibleId(), RTL_TEXTENCODING_UTF8);
+ atk_object_set_accessible_id(atk_obj, aId.getStr());
+ }
+ }
+#endif
+
+ return ATK_OBJECT( pWrap );
+ }
+ catch (const uno::Exception &)
+ {
+ if( pWrap )
+ g_object_unref( pWrap );
+
+ return nullptr;
+ }
+}
+
+/*****************************************************************************/
+
+void atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
+{
+ AtkObject *atk_obj = ATK_OBJECT( wrapper );
+
+ atk_object_set_parent( child, atk_obj );
+ g_signal_emit_by_name( atk_obj, "children_changed::add", index, child, nullptr );
+}
+
+/*****************************************************************************/
+
+void atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index)
+{
+ /*
+ * the atk-bridge GTK+ module gets back to the event source to ref the child just
+ * vanishing, so we keep this reference because the semantic on OOo side is different.
+ */
+ wrapper->child_about_to_be_removed = child;
+ wrapper->index_of_child_about_to_be_removed = index;
+
+ g_signal_emit_by_name( ATK_OBJECT( wrapper ), "children_changed::remove", index, child, nullptr );
+
+ wrapper->index_of_child_about_to_be_removed = -1;
+ wrapper->child_about_to_be_removed = nullptr;
+}
+
+/*****************************************************************************/
+
+void atk_object_wrapper_set_role(AtkObjectWrapper* wrapper, sal_Int16 role)
+{
+ AtkObject *atk_obj = ATK_OBJECT( wrapper );
+ atk_object_set_role( atk_obj, mapToAtkRole( role ) );
+}
+
+/*****************************************************************************/
+
+void atk_object_wrapper_dispose(AtkObjectWrapper* wrapper)
+{
+ wrapper->mpContext.clear();
+ wrapper->mpAction.clear();
+ wrapper->mpComponent.clear();
+ wrapper->mpEditableText.clear();
+ wrapper->mpHypertext.clear();
+ wrapper->mpImage.clear();
+ wrapper->mpSelection.clear();
+ wrapper->mpMultiLineText.clear();
+ wrapper->mpTable.clear();
+ wrapper->mpText.clear();
+ wrapper->mpTextMarkup.clear();
+ wrapper->mpTextAttributes.clear();
+ wrapper->mpValue.clear();
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx
index c106aa0ce4c4..2552bb16b253 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx
+++ b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.cxx
@@ -53,7 +53,7 @@
#include <set>
#include <string.h>
-#include <gtk/fpicker/SalGtkFilePicker.hxx>
+#include "SalGtkFilePicker.hxx"
using namespace ::com::sun::star;
using namespace ::com::sun::star::ui::dialogs;
@@ -437,15 +437,11 @@ dialog_remove_buttons( GtkDialog *pDialog )
{
g_return_if_fail( GTK_IS_DIALOG( pDialog ) );
-#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *pHeaderBar = gtk_dialog_get_header_bar(pDialog);
if( pHeaderBar != nullptr )
dialog_remove_buttons( pHeaderBar );
else
dialog_remove_buttons(gtk_dialog_get_action_area(pDialog));
-#else
- dialog_remove_buttons(pDialog->action_area);
-#endif
}
namespace {
@@ -798,14 +794,10 @@ uno::Sequence<OUString> SAL_CALL SalGtkFilePicker::getSelectedFiles()
}
if( bChangeFilter && bExtensionTypedIn )
{
-#if GTK_CHECK_VERSION(3,0,0)
gchar* pCurrentName = gtk_file_chooser_get_current_name(GTK_FILE_CHOOSER(m_pDialog));
setCurrentFilter( aNewFilter );
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_pDialog), pCurrentName);
g_free(pCurrentName);
-#else
- setCurrentFilter( aNewFilter );
-#endif
}
}
}
@@ -1009,12 +1001,7 @@ sal_Int16 SAL_CALL SalGtkFilePicker::execute()
gtk_window_set_title( GTK_WINDOW( dlg ),
OUStringToOString(getResString(FILE_PICKER_TITLE_SAVE ),
RTL_TEXTENCODING_UTF8 ).getStr() );
-#if GTK_CHECK_VERSION(3,0,0)
gtk_window_set_transient_for(GTK_WINDOW(dlg), GTK_WINDOW(m_pDialog));
-#else
- if (pParent)
- gtk_window_set_transient_for(GTK_WINDOW(dlg), pParent);
-#endif
RunDialog* pAnotherDialog = new RunDialog(dlg, xToolkit, xDesktop);
uno::Reference < awt::XTopWindowListener > xAnotherLifeCycle(pAnotherDialog);
btn = pAnotherDialog->run();
diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx
index ae3e1baa8275..db471d5e5c6c 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx
+++ b/vcl/unx/gtk3/fpicker/SalGtkFilePicker.hxx
@@ -32,7 +32,7 @@
#include <memory>
#include <rtl/ustring.hxx>
-#include <gtk/fpicker/SalGtkPicker.hxx>
+#include "SalGtkPicker.hxx"
// Implementation class for the XFilePicker Interface
diff --git a/vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx b/vcl/unx/gtk3/fpicker/SalGtkFolderPicker.cxx
index ade5ff504539..13df53994dee 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx
+++ b/vcl/unx/gtk3/fpicker/SalGtkFolderPicker.cxx
@@ -34,7 +34,7 @@
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <vcl/svapp.hxx>
#include <unx/gtk/gtkinst.hxx>
-#include <gtk/fpicker/SalGtkFolderPicker.hxx>
+#include "SalGtkFolderPicker.hxx"
#include <sal/log.hxx>
#include <string.h>
diff --git a/vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx b/vcl/unx/gtk3/fpicker/SalGtkFolderPicker.hxx
index 46cf107a04ae..229bbe8b8749 100644
--- a/vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx
+++ b/vcl/unx/gtk3/fpicker/SalGtkFolderPicker.hxx
@@ -25,7 +25,7 @@
#include <rtl/ustring.hxx>
#include <cppuhelper/implbase.hxx>
-#include <gtk/fpicker/SalGtkPicker.hxx>
+#include "SalGtkPicker.hxx"
class SalGtkFolderPicker :
public SalGtkPicker,
diff --git a/vcl/unx/gtk/fpicker/SalGtkPicker.cxx b/vcl/unx/gtk3/fpicker/SalGtkPicker.cxx
index 3e443ea04692..7db114069651 100644
--- a/vcl/unx/gtk/fpicker/SalGtkPicker.cxx
+++ b/vcl/unx/gtk3/fpicker/SalGtkPicker.cxx
@@ -36,7 +36,7 @@
#include <vcl/window.hxx>
#include <unx/gtk/gtkframe.hxx>
-#include <gtk/fpicker/SalGtkPicker.hxx>
+#include "SalGtkPicker.hxx"
using namespace ::rtl;
using namespace ::com::sun::star;
diff --git a/vcl/unx/gtk/fpicker/SalGtkPicker.hxx b/vcl/unx/gtk3/fpicker/SalGtkPicker.hxx
index 0eb8720f771a..0eb8720f771a 100644
--- a/vcl/unx/gtk/fpicker/SalGtkPicker.hxx
+++ b/vcl/unx/gtk3/fpicker/SalGtkPicker.hxx
diff --git a/vcl/unx/gtk/fpicker/eventnotification.hxx b/vcl/unx/gtk3/fpicker/eventnotification.hxx
index 88a472e0e8ce..88a472e0e8ce 100644
--- a/vcl/unx/gtk/fpicker/eventnotification.hxx
+++ b/vcl/unx/gtk3/fpicker/eventnotification.hxx
diff --git a/vcl/unx/gtk/fpicker/resourceprovider.cxx b/vcl/unx/gtk3/fpicker/resourceprovider.cxx
index 745521ac596a..818018b4a7e5 100644
--- a/vcl/unx/gtk/fpicker/resourceprovider.cxx
+++ b/vcl/unx/gtk3/fpicker/resourceprovider.cxx
@@ -24,7 +24,7 @@
#include <strings.hrc>
#include <svdata.hxx>
-#include <gtk/fpicker/SalGtkPicker.hxx>
+#include "SalGtkPicker.hxx"
using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
diff --git a/vcl/unx/gtk3/gtk3fpicker.cxx b/vcl/unx/gtk3/gtk3fpicker.cxx
deleted file mode 100644
index 9b83c57daed8..000000000000
--- a/vcl/unx/gtk3/gtk3fpicker.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -*- 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/.
- */
-
-#include "../gtk/fpicker/resourceprovider.cxx"
-#include "../gtk/fpicker/SalGtkPicker.cxx"
-#include "../gtk/fpicker/SalGtkFilePicker.cxx"
-#include "../gtk/fpicker/SalGtkFolderPicker.cxx"
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3gloactiongroup.cxx b/vcl/unx/gtk3/gtk3gloactiongroup.cxx
index 749f5434a456..19b412faec38 100644
--- a/vcl/unx/gtk3/gtk3gloactiongroup.cxx
+++ b/vcl/unx/gtk3/gtk3gloactiongroup.cxx
@@ -1,5 +1,403 @@
/* -*- 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/.
+ */
-#include "../gtk/gloactiongroup.cxx"
+#include <unx/gtk/gtksalmenu.hxx>
+
+#include <unx/gtk/gloactiongroup.h>
+#include <unx/gtk/gtkinst.hxx>
+#include <unx/gtk/gtkframe.hxx>
+
+#include <sal/log.hxx>
+
+/*
+ * GLOAction
+ */
+
+#define G_TYPE_LO_ACTION (g_lo_action_get_type ())
+#define G_LO_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
+ G_TYPE_LO_ACTION, GLOAction))
+
+struct GLOAction
+{
+ GObject parent_instance;
+
+ gint item_id; // Menu item ID.
+ gboolean submenu; // TRUE if action is a submenu action.
+ gboolean enabled; // TRUE if action is enabled.
+ GVariantType* parameter_type; // A GVariantType with the action parameter type.
+ GVariantType* state_type; // A GVariantType with item state type
+ GVariant* state_hint; // A GVariant with state hints.
+ GVariant* state; // A GVariant with current item state
+};
+
+typedef GObjectClass GLOActionClass;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+G_DEFINE_TYPE (GLOAction, g_lo_action, G_TYPE_OBJECT);
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+static GLOAction*
+g_lo_action_new()
+{
+ return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION, nullptr));
+}
+
+static void
+g_lo_action_init (GLOAction *action)
+{
+ action->item_id = -1;
+ action->submenu = FALSE;
+ action->enabled = TRUE;
+ action->parameter_type = nullptr;
+ action->state_type = nullptr;
+ action->state_hint = nullptr;
+ action->state = nullptr;
+}
+
+static void
+g_lo_action_finalize (GObject *object)
+{
+ GLOAction* action = G_LO_ACTION(object);
+
+ if (action->parameter_type)
+ g_variant_type_free (action->parameter_type);
+
+ if (action->state_type)
+ g_variant_type_free (action->state_type);
+
+ if (action->state_hint)
+ g_variant_unref (action->state_hint);
+
+ if (action->state)
+ g_variant_unref (action->state);
+
+ G_OBJECT_CLASS (g_lo_action_parent_class)->finalize (object);
+}
+
+static void
+g_lo_action_class_init (GLOActionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->finalize = g_lo_action_finalize;
+}
+
+/*
+ * GLOActionGroup
+ */
+
+struct GLOActionGroupPrivate
+{
+ GHashTable *table; /* string -> GLOAction */
+};
+
+static void g_lo_action_group_iface_init (GActionGroupInterface *);
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+G_DEFINE_TYPE_WITH_CODE (GLOActionGroup,
+ g_lo_action_group, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
+ g_lo_action_group_iface_init));
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+static gchar **
+g_lo_action_group_list_actions (GActionGroup *group)
+{
+ GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
+ GHashTableIter iter;
+ gint n, i = 0;
+ gchar **keys;
+ gpointer key;
+
+ n = g_hash_table_size (loGroup->priv->table);
+ keys = g_new (gchar *, n + 1);
+
+ g_hash_table_iter_init (&iter, loGroup->priv->table);
+ while (g_hash_table_iter_next (&iter, &key, nullptr))
+ keys[i++] = g_strdup (static_cast<gchar*>(key));
+ g_assert_cmpint (i, ==, n);
+ keys[n] = nullptr;
+
+ return keys;
+}
+
+static gboolean
+g_lo_action_group_query_action (GActionGroup *group,
+ const gchar *action_name,
+ gboolean *enabled,
+ const GVariantType **parameter_type,
+ const GVariantType **state_type,
+ GVariant **state_hint,
+ GVariant **state)
+{
+ //SAL_INFO("vcl.unity", "g_lo_action_group_query_action on " << group);
+ GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
+ GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
+
+ if (action == nullptr)
+ return FALSE;
+
+ if (enabled)
+ {
+ *enabled = action->enabled;
+ }
+
+ if (parameter_type)
+ *parameter_type = action->parameter_type;
+
+ if (state_type)
+ *state_type = action->state_type;
+
+ if (state_hint)
+ *state_hint = (action->state_hint) ? g_variant_ref (action->state_hint) : nullptr;
+
+ if (state)
+ *state = (action->state) ? g_variant_ref (action->state) : nullptr;
+
+ return TRUE;
+}
+
+static void
+g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
+ const gchar *action_name,
+ GVariant *state)
+{
+ gboolean bState = g_variant_get_boolean (state);
+ SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " to " << bState);
+
+ if (bState)
+ GtkSalMenu::Activate(action_name);
+ else
+ GtkSalMenu::Deactivate(action_name);
+}
+
+static void
+g_lo_action_group_change_state (GActionGroup *group,
+ const gchar *action_name,
+ GVariant *value)
+{
+ SAL_INFO("vcl.unity", "g_lo_action_group_change_state on " << group );
+ g_return_if_fail (value != nullptr);
+
+ g_variant_ref_sink (value);
+
+ if (action_name != nullptr)
+ {
+ GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
+ GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
+
+ if (action != nullptr)
+ {
+ if (action->submenu)
+ g_lo_action_group_perform_submenu_action (lo_group, action_name, value);
+ else
+ {
+ gboolean is_new = FALSE;
+
+ /* If action already exists but has no state, it should be removed and added again. */
+ if (action->state_type == nullptr)
+ {
+ g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
+ action->state_type = g_variant_type_copy (g_variant_get_type(value));
+ is_new = TRUE;
+ }
+
+ if (g_variant_is_of_type (value, action->state_type))
+ {
+ if (action->state)
+ g_variant_unref(action->state);
+
+ action->state = g_variant_ref (value);
+
+ if (is_new)
+ g_action_group_action_added (G_ACTION_GROUP (group), action_name);
+ else
+ g_action_group_action_state_changed (group, action_name, value);
+ }
+ }
+ }
+ }
+
+ g_variant_unref (value);
+}
+
+static void
+g_lo_action_group_activate (GActionGroup *group,
+ const gchar *action_name,
+ GVariant *parameter)
+{
+ if (parameter != nullptr)
+ g_action_group_change_action_state(group, action_name, parameter);
+ GtkSalMenu::DispatchCommand(action_name);
+}
+
+void
+g_lo_action_group_insert (GLOActionGroup *group,
+ const gchar *action_name,
+ gint item_id,
+ gboolean submenu)
+{
+ g_lo_action_group_insert_stateful (group, action_name, item_id, submenu, nullptr, nullptr, nullptr, nullptr);
+}
+
+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)
+{
+ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
+
+ GLOAction* old_action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
+
+ if (old_action == nullptr || old_action->item_id != item_id)
+ {
+ if (old_action != nullptr)
+ g_lo_action_group_remove (group, action_name);
+
+ GLOAction* action = g_lo_action_new();
+
+ g_hash_table_insert (group->priv->table, g_strdup (action_name), action);
+
+ action->item_id = item_id;
+ action->submenu = submenu;
+
+ if (parameter_type)
+ action->parameter_type = const_cast<GVariantType*>(parameter_type);
+
+ if (state_type)
+ action->state_type = const_cast<GVariantType*>(state_type);
+
+ if (state_hint)
+ action->state_hint = g_variant_ref_sink (state_hint);
+
+ if (state)
+ action->state = g_variant_ref_sink (state);
+
+ g_action_group_action_added (G_ACTION_GROUP (group), action_name);
+ }
+}
+
+static void
+g_lo_action_group_finalize (GObject *object)
+{
+ GLOActionGroup *lo_group = G_LO_ACTION_GROUP (object);
+
+ g_hash_table_unref (lo_group->priv->table);
+
+ G_OBJECT_CLASS (g_lo_action_group_parent_class)->finalize (object);
+}
+
+static void
+g_lo_action_group_init (GLOActionGroup *group)
+{
+ SAL_INFO("vcl.unity", "g_lo_action_group_init on " << group);
+ group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
+ G_TYPE_LO_ACTION_GROUP,
+ GLOActionGroupPrivate);
+ group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+}
+
+static void
+g_lo_action_group_class_init (GLOActionGroupClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = g_lo_action_group_finalize;
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+ g_type_class_add_private (klass, sizeof (GLOActionGroupPrivate));
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+}
+
+static void
+g_lo_action_group_iface_init (GActionGroupInterface *iface)
+{
+ iface->list_actions = g_lo_action_group_list_actions;
+ iface->query_action = g_lo_action_group_query_action;
+ iface->change_action_state = g_lo_action_group_change_state;
+ iface->activate_action = g_lo_action_group_activate;
+}
+
+GLOActionGroup *
+g_lo_action_group_new()
+{
+ GLOActionGroup* group = G_LO_ACTION_GROUP (g_object_new (G_TYPE_LO_ACTION_GROUP, nullptr));
+ return group;
+}
+
+void
+g_lo_action_group_set_action_enabled (GLOActionGroup *group,
+ const gchar *action_name,
+ gboolean enabled)
+{
+ SAL_INFO("vcl.unity", "g_lo_action_group_set_action_enabled on " << group);
+ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
+ g_return_if_fail (action_name != nullptr);
+
+ GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
+
+ if (action == nullptr)
+ return;
+
+ action->enabled = enabled;
+
+ g_action_group_action_enabled_changed (G_ACTION_GROUP (group), action_name, enabled);
+}
+
+void
+g_lo_action_group_remove (GLOActionGroup *group,
+ const gchar *action_name)
+{
+ SAL_INFO("vcl.unity", "g_lo_action_group_remove on " << group);
+ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
+
+ if (action_name != nullptr)
+ {
+ g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
+ g_hash_table_remove (group->priv->table, action_name);
+ }
+}
+
+void
+g_lo_action_group_clear (GLOActionGroup *group)
+{
+ SAL_INFO("vcl.unity", "g_lo_action_group_clear on " << group);
+ g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
+
+ GList* keys = g_hash_table_get_keys (group->priv->table);
+
+ for (GList* element = g_list_first (keys); element != nullptr; element = g_list_next (element))
+ {
+ g_lo_action_group_remove (group, static_cast<gchar*>(element->data));
+ }
+
+ g_list_free (keys);
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3glomenu.cxx b/vcl/unx/gtk3/gtk3glomenu.cxx
index e894b09320fd..f20903d0bd5a 100644
--- a/vcl/unx/gtk3/gtk3glomenu.cxx
+++ b/vcl/unx/gtk3/gtk3glomenu.cxx
@@ -1,5 +1,686 @@
/* -*- 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/.
+ */
-#include "../gtk/glomenu.cxx"
+#include <string.h>
+
+#include <unx/gtk/gtksalmenu.hxx>
+#include <unx/gtk/glomenu.h>
+
+struct GLOMenu
+{
+ GMenuModel const parent_instance;
+
+ GArray *items;
+};
+
+typedef GMenuModelClass GLOMenuClass;
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+G_DEFINE_TYPE (GLOMenu, g_lo_menu, G_TYPE_MENU_MODEL);
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+struct item
+{
+ GHashTable* attributes; // Item attributes.
+ GHashTable* links; // Item links.
+};
+
+static void
+g_lo_menu_struct_item_init (struct item *menu_item)
+{
+ menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, reinterpret_cast<GDestroyNotify>(g_variant_unref));
+ menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+}
+
+/* We treat attribute names the same as GSettings keys:
+ * - only lowercase ascii, digits and '-'
+ * - must start with lowercase
+ * - must not end with '-'
+ * - no consecutive '-'
+ * - not longer than 1024 chars
+ */
+static gboolean
+valid_attribute_name (const gchar *name)
+{
+ gint i;
+
+ if (!g_ascii_islower (name[0]))
+ return FALSE;
+
+ for (i = 1; name[i]; i++)
+ {
+ if (name[i] != '-' &&
+ !g_ascii_islower (name[i]) &&
+ !g_ascii_isdigit (name[i]))
+ return FALSE;
+
+ if (name[i] == '-' && name[i + 1] == '-')
+ return FALSE;
+ }
+
+ if (name[i - 1] == '-')
+ return FALSE;
+
+ if (i > 1024)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * GLOMenu
+ */
+
+static gboolean
+g_lo_menu_is_mutable (GMenuModel*)
+{
+ // Menu is always mutable.
+ return TRUE;
+}
+
+static gint
+g_lo_menu_get_n_items (GMenuModel *model)
+{
+ g_return_val_if_fail (model != nullptr, 0);
+ GLOMenu *menu = G_LO_MENU (model);
+ g_return_val_if_fail (menu->items != nullptr, 0);
+
+ return menu->items->len;
+}
+
+gint
+g_lo_menu_get_n_items_from_section (GLOMenu *menu,
+ gint section)
+{
+ g_return_val_if_fail (0 <= section && section < static_cast<gint>(menu->items->len), 0);
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_val_if_fail (model != nullptr, 0);
+
+ gint length = model->items->len;
+
+ g_object_unref (model);
+
+ return length;
+}
+
+static void
+g_lo_menu_get_item_attributes (GMenuModel *model,
+ gint position,
+ GHashTable **table)
+{
+ GLOMenu *menu = G_LO_MENU (model);
+ *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes);
+}
+
+static void
+g_lo_menu_get_item_links (GMenuModel *model,
+ gint position,
+ GHashTable **table)
+{
+ GLOMenu *menu = G_LO_MENU (model);
+ *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links);
+}
+
+void
+g_lo_menu_insert (GLOMenu *menu,
+ gint position,
+ const gchar *label)
+{
+ g_lo_menu_insert_section (menu, position, label, nullptr);
+}
+
+void
+g_lo_menu_insert_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *label)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+ g_return_if_fail (0 <= section && section < static_cast<gint>(menu->items->len));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ g_lo_menu_insert (model, position, label);
+
+ g_object_unref (model);
+}
+
+GLOMenu *
+g_lo_menu_new()
+{
+ return G_LO_MENU( g_object_new (G_TYPE_LO_MENU, nullptr) );
+}
+
+static void
+g_lo_menu_set_attribute_value (GLOMenu *menu,
+ gint position,
+ const gchar *attribute,
+ GVariant *value)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+ g_return_if_fail (attribute != nullptr);
+ g_return_if_fail (valid_attribute_name (attribute));
+
+ if (position >= static_cast<gint>(menu->items->len))
+ return;
+
+ struct item menu_item = g_array_index (menu->items, struct item, position);
+
+ if (value != nullptr)
+ g_hash_table_insert (menu_item.attributes, g_strdup (attribute), g_variant_ref_sink (value));
+ else
+ g_hash_table_remove (menu_item.attributes, attribute);
+}
+
+static GVariant*
+g_lo_menu_get_attribute_value_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *attribute,
+ const GVariantType *type)
+{
+ GMenuModel *model = G_MENU_MODEL (g_lo_menu_get_section (menu, section));
+
+ g_return_val_if_fail (model != nullptr, nullptr);
+
+ GVariant *value = g_menu_model_get_item_attribute_value (model,
+ position,
+ attribute,
+ type);
+
+ g_object_unref (model);
+
+ return value;
+}
+
+void
+g_lo_menu_set_label (GLOMenu *menu,
+ gint position,
+ const gchar *label)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GVariant *value;
+
+ if (label != nullptr)
+ value = g_variant_new_string (label);
+ else
+ value = nullptr;
+
+ g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_LABEL, value);
+}
+
+void
+g_lo_menu_set_icon (GLOMenu *menu,
+ gint position,
+ const GIcon *icon)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GVariant *value;
+
+ if (icon != nullptr)
+ {
+#if GLIB_CHECK_VERSION(2,38,0)
+ value = g_icon_serialize (const_cast<GIcon*>(icon));
+#else
+ value = nullptr;
+#endif
+ }
+ else
+ value = nullptr;
+
+#ifndef G_MENU_ATTRIBUTE_ICON
+# define G_MENU_ATTRIBUTE_ICON "icon"
+#endif
+
+ g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_ICON, value);
+ if (value)
+ g_variant_unref (value);
+}
+
+void
+g_lo_menu_set_label_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *label)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ g_lo_menu_set_label (model, position, label);
+
+ // Notify the update.
+ g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
+
+ g_object_unref (model);
+}
+
+void
+g_lo_menu_set_icon_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const GIcon *icon)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ g_lo_menu_set_icon (model, position, icon);
+
+ // Notify the update.
+ g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
+
+ g_object_unref (model);
+}
+
+gchar *
+g_lo_menu_get_label_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position)
+{
+ g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
+
+ GVariant *label_value = g_lo_menu_get_attribute_value_from_item_in_section (menu,
+ section,
+ position,
+ G_MENU_ATTRIBUTE_LABEL,
+ G_VARIANT_TYPE_STRING);
+
+ gchar *label = nullptr;
+
+ if (label_value)
+ {
+ label = g_variant_dup_string (label_value, nullptr);
+ g_variant_unref (label_value);
+ }
+
+ return label;
+}
+
+void
+g_lo_menu_set_action_and_target_value (GLOMenu *menu,
+ gint position,
+ const gchar *action,
+ GVariant *target_value)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GVariant *action_value;
+
+ if (action != nullptr)
+ {
+ action_value = g_variant_new_string (action);
+ }
+ else
+ {
+ action_value = nullptr;
+ target_value = nullptr;
+ }
+
+ g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_ACTION, action_value);
+ g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_TARGET, target_value);
+ g_lo_menu_set_attribute_value (menu, position, G_LO_MENU_ATTRIBUTE_SUBMENU_ACTION, nullptr);
+
+ g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 1);
+}
+
+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)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ g_lo_menu_set_action_and_target_value (model, position, command, target_value);
+
+ g_object_unref (model);
+}
+
+void
+g_lo_menu_set_accelerator_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *accelerator)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ GVariant *value;
+
+ if (accelerator != nullptr)
+ value = g_variant_new_string (accelerator);
+ else
+ value = nullptr;
+
+ g_lo_menu_set_attribute_value (model, position, G_LO_MENU_ATTRIBUTE_ACCELERATOR, value);
+
+ // Notify the update.
+ g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
+
+ g_object_unref (model);
+}
+
+gchar *
+g_lo_menu_get_accelerator_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position)
+{
+ g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
+
+ GVariant *accel_value = g_lo_menu_get_attribute_value_from_item_in_section (menu,
+ section,
+ position,
+ G_LO_MENU_ATTRIBUTE_ACCELERATOR,
+ G_VARIANT_TYPE_STRING);
+
+ gchar *accel = nullptr;
+
+ if (accel_value != nullptr)
+ {
+ accel = g_variant_dup_string (accel_value, nullptr);
+ g_variant_unref (accel_value);
+ }
+
+ return accel;
+}
+
+void
+g_lo_menu_set_command_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *command)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ GVariant *value;
+
+ if (command != nullptr)
+ value = g_variant_new_string (command);
+ else
+ value = nullptr;
+
+ g_lo_menu_set_attribute_value (model, position, G_LO_MENU_ATTRIBUTE_COMMAND, value);
+
+ // Notify the update.
+ g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
+
+ g_object_unref (model);
+}
+
+gchar *
+g_lo_menu_get_command_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position)
+{
+ g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
+
+ GVariant *command_value = g_lo_menu_get_attribute_value_from_item_in_section (menu,
+ section,
+ position,
+ G_LO_MENU_ATTRIBUTE_COMMAND,
+ G_VARIANT_TYPE_STRING);
+
+ gchar *command = nullptr;
+
+ if (command_value != nullptr)
+ {
+ command = g_variant_dup_string (command_value, nullptr);
+ g_variant_unref (command_value);
+ }
+
+ return command;
+}
+
+static void
+g_lo_menu_set_link (GLOMenu *menu,
+ gint position,
+ const gchar *link,
+ GMenuModel *model)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+ g_return_if_fail (link != nullptr);
+ g_return_if_fail (valid_attribute_name (link));
+
+ if (position < 0 || position >= static_cast<gint>(menu->items->len))
+ position = menu->items->len - 1;
+
+ struct item menu_item = g_array_index (menu->items, struct item, position);
+
+ if (model != nullptr)
+ g_hash_table_insert (menu_item.links, g_strdup (link), g_object_ref (model));
+ else
+ g_hash_table_remove (menu_item.links, link);
+}
+
+void
+g_lo_menu_insert_section (GLOMenu *menu,
+ gint position,
+ const gchar *label,
+ GMenuModel *section)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ if (position < 0 || position > static_cast<gint>(menu->items->len))
+ position = menu->items->len;
+
+ struct item menu_item;
+
+ g_lo_menu_struct_item_init(&menu_item);
+
+ g_array_insert_val (menu->items, position, menu_item);
+
+ g_lo_menu_set_label (menu, position, label);
+ g_lo_menu_set_link (menu, position, G_MENU_LINK_SECTION, section);
+
+ g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
+}
+
+void
+g_lo_menu_new_section (GLOMenu *menu,
+ gint position,
+ const gchar *label)
+{
+ GMenuModel *section = G_MENU_MODEL (g_lo_menu_new());
+
+ g_lo_menu_insert_section (menu, position, label, section);
+
+ g_object_unref (section);
+}
+
+GLOMenu *
+g_lo_menu_get_section (GLOMenu *menu,
+ gint section)
+{
+ g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
+
+ return G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
+ ->get_item_link (G_MENU_MODEL (menu), section, G_MENU_LINK_SECTION));
+}
+
+void
+g_lo_menu_new_submenu_in_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+ g_return_if_fail (0 <= section && section < static_cast<gint>(menu->items->len));
+
+ GLOMenu* model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ if (0 <= position && position < static_cast<gint>(model->items->len)) {
+ GMenuModel* submenu = G_MENU_MODEL (g_lo_menu_new());
+
+ g_lo_menu_set_link (model, position, G_MENU_LINK_SUBMENU, submenu);
+
+ g_object_unref (submenu);
+
+ g_menu_model_items_changed (G_MENU_MODEL (model), position, 1, 1);
+
+ g_object_unref (model);
+ }
+}
+
+GLOMenu *
+g_lo_menu_get_submenu_from_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position)
+{
+ g_return_val_if_fail (G_IS_LO_MENU (menu), nullptr);
+ g_return_val_if_fail (0 <= section && section < static_cast<gint>(menu->items->len), nullptr);
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_val_if_fail (model != nullptr, nullptr);
+
+ GLOMenu *submenu = nullptr;
+
+ if (0 <= position && position < static_cast<gint>(model->items->len))
+ submenu = G_LO_MENU (G_MENU_MODEL_CLASS (g_lo_menu_parent_class)
+ ->get_item_link (G_MENU_MODEL (model), position, G_MENU_LINK_SUBMENU));
+ //submenu = g_menu_model_get_item_link (G_MENU_MODEL (model), position, G_MENU_LINK_SUBMENU);
+
+ g_object_unref (model);
+
+ return submenu;
+}
+
+void
+g_lo_menu_set_submenu_action_to_item_in_section (GLOMenu *menu,
+ gint section,
+ gint position,
+ const gchar *action)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+
+ GMenuModel *model = G_MENU_MODEL (g_lo_menu_get_section (menu, section));
+
+ g_return_if_fail (model != nullptr);
+
+ GVariant *value;
+
+ if (action != nullptr)
+ value = g_variant_new_string (action);
+ else
+ value = nullptr;
+
+ g_lo_menu_set_attribute_value (G_LO_MENU (model), position, G_LO_MENU_ATTRIBUTE_SUBMENU_ACTION, value);
+
+ // Notify the update.
+ g_menu_model_items_changed (model, position, 1, 1);
+
+ g_object_unref (model);
+}
+
+static void
+g_lo_menu_clear_item (struct item *menu_item)
+{
+ if (menu_item->attributes != nullptr)
+ g_hash_table_unref (menu_item->attributes);
+ if (menu_item->links != nullptr)
+ g_hash_table_unref (menu_item->links);
+}
+
+void
+g_lo_menu_remove (GLOMenu *menu,
+ gint position)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+ g_return_if_fail (0 <= position && position < static_cast<gint>(menu->items->len));
+
+ g_lo_menu_clear_item (&g_array_index (menu->items, struct item, position));
+ g_array_remove_index (menu->items, position);
+ g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
+}
+
+void
+g_lo_menu_remove_from_section (GLOMenu *menu,
+ gint section,
+ gint position)
+{
+ g_return_if_fail (G_IS_LO_MENU (menu));
+ g_return_if_fail (0 <= section && section < static_cast<gint>(menu->items->len));
+
+ GLOMenu *model = g_lo_menu_get_section (menu, section);
+
+ g_return_if_fail (model != nullptr);
+
+ g_lo_menu_remove (model, position);
+
+ g_object_unref (model);
+}
+
+static void
+g_lo_menu_finalize (GObject *object)
+{
+ GLOMenu *menu = G_LO_MENU (object);
+ struct item *items;
+ gint n_items;
+ gint i;
+
+ n_items = menu->items->len;
+ items = reinterpret_cast<struct item *>(g_array_free (menu->items, FALSE));
+ for (i = 0; i < n_items; i++)
+ g_lo_menu_clear_item (&items[i]);
+ g_free (items);
+
+ G_OBJECT_CLASS (g_lo_menu_parent_class)
+ ->finalize (object);
+}
+
+static void
+g_lo_menu_init (GLOMenu *menu)
+{
+ menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
+}
+
+static void
+g_lo_menu_class_init (GLOMenuClass *klass)
+{
+ GMenuModelClass *model_class = G_MENU_MODEL_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = g_lo_menu_finalize;
+
+ model_class->is_mutable = g_lo_menu_is_mutable;
+ model_class->get_n_items = g_lo_menu_get_n_items;
+ model_class->get_item_attributes = g_lo_menu_get_item_attributes;
+ model_class->get_item_links = g_lo_menu_get_item_links;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 333db6693d13..f5e26be83b59 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -7,8 +7,35 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../gtk/gtkinst.cxx"
-#include "../gtk/a11y/atkwrapper.hxx"
+#include <stack>
+#include <string.h>
+#include <osl/process.h>
+#include <unx/gtk/gtkdata.hxx>
+#include <unx/gtk/gtkinst.hxx>
+#include <unx/salobj.h>
+#include <unx/gtk/gtkgdi.hxx>
+#include <unx/gtk/gtkframe.hxx>
+#include <unx/gtk/gtkobject.hxx>
+#include <unx/gtk/atkbridge.hxx>
+#include <unx/gtk/gtkprn.hxx>
+#include <unx/gtk/gtksalmenu.hxx>
+#include <headless/svpvd.hxx>
+#include <headless/svpbmp.hxx>
+#include <vcl/inputtypes.hxx>
+#include <unx/genpspgraphics.h>
+#include <rtl/strbuf.hxx>
+#include <sal/log.hxx>
+#include <rtl/uri.hxx>
+
+#include <vcl/settings.hxx>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <unx/gtk/gtkprintwrapper.hxx>
+
+#include "a11y/atkwrapper.hxx"
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
@@ -56,6 +83,376 @@ using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
+extern "C"
+{
+ #define GET_YIELD_MUTEX() static_cast<GtkYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())
+ static void GdkThreadsEnter()
+ {
+ GtkYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
+ pYieldMutex->ThreadsEnter();
+ }
+ static void GdkThreadsLeave()
+ {
+ GtkYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
+ pYieldMutex->ThreadsLeave();
+ }
+
+ VCLPLUG_GTK_PUBLIC SalInstance* create_SalInstance()
+ {
+ SAL_INFO(
+ "vcl.gtk",
+ "create vcl plugin instance with gtk version " << gtk_major_version
+ << " " << gtk_minor_version << " " << gtk_micro_version);
+
+ if (gtk_major_version == 3 && gtk_minor_version < 18)
+ {
+ g_warning("require gtk >= 3.18 for theme expectations");
+ return nullptr;
+ }
+
+ // for gtk2 it is always built with X support, so this is always called
+ // for gtk3 it is normally built with X and Wayland support, if
+ // X is supported GDK_WINDOWING_X11 is defined and this is always
+ // called, regardless of if we're running under X or Wayland.
+ // We can't use (DLSYM_GDK_IS_X11_DISPLAY(pDisplay)) to only do it under
+ // X, because we need to do it earlier than we have a display
+#if defined(GDK_WINDOWING_X11)
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+#endif
+
+ // init gdk thread protection
+ bool const sup = g_thread_supported();
+ // extracted from the 'if' to avoid Clang -Wunreachable-code
+ if ( !sup )
+ g_thread_init( nullptr );
+
+ gdk_threads_set_lock_functions (GdkThreadsEnter, GdkThreadsLeave);
+ SAL_INFO("vcl.gtk", "Hooked gdk threads locks");
+
+ auto pYieldMutex = std::make_unique<GtkYieldMutex>();
+
+ gdk_threads_init();
+
+ GtkInstance* pInstance = new GtkInstance( std::move(pYieldMutex) );
+ SAL_INFO("vcl.gtk", "creating GtkInstance " << pInstance);
+
+ // Create SalData, this does not leak
+ new GtkSalData( pInstance );
+
+ return pInstance;
+ }
+}
+
+static VclInputFlags categorizeEvent(const GdkEvent *pEvent)
+{
+ VclInputFlags nType = VclInputFlags::NONE;
+ switch( pEvent->type )
+ {
+ case GDK_MOTION_NOTIFY:
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ case GDK_SCROLL:
+ nType = VclInputFlags::MOUSE;
+ break;
+ case GDK_KEY_PRESS:
+ // case GDK_KEY_RELEASE: //similar to the X11SalInstance one
+ nType = VclInputFlags::KEYBOARD;
+ break;
+ case GDK_EXPOSE:
+ nType = VclInputFlags::PAINT;
+ break;
+ default:
+ nType = VclInputFlags::OTHER;
+ break;
+ }
+ return nType;
+}
+
+GtkInstance::GtkInstance( std::unique_ptr<SalYieldMutex> pMutex )
+ : SvpSalInstance( std::move(pMutex) )
+ , m_pTimer(nullptr)
+ , bNeedsInit(true)
+ , m_pLastCairoFontOptions(nullptr)
+{
+}
+
+//We want to defer initializing gtk until we are after uno has been
+//bootstrapped so we can ask the config what the UI language is so that we can
+//force that in as $LANGUAGE to get gtk to render widgets RTL if we have a RTL
+//UI in a LTR locale
+void GtkInstance::AfterAppInit()
+{
+ EnsureInit();
+}
+
+void GtkInstance::EnsureInit()
+{
+ if (!bNeedsInit)
+ return;
+ // initialize SalData
+ GtkSalData *pSalData = GetGtkSalData();
+ pSalData->Init();
+ GtkSalData::initNWF();
+
+ InitAtkBridge();
+
+ ImplSVData* pSVData = ImplGetSVData();
+#ifdef GTK_TOOLKIT_NAME
+ pSVData->maAppData.mxToolkitName = OUString(GTK_TOOLKIT_NAME);
+#else
+ pSVData->maAppData.mxToolkitName = OUString("gtk3");
+#endif
+
+ bNeedsInit = false;
+}
+
+GtkInstance::~GtkInstance()
+{
+ assert( nullptr == m_pTimer );
+ DeInitAtkBridge();
+ ResetLastSeenCairoFontOptions(nullptr);
+}
+
+SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle )
+{
+ EnsureInit();
+ return new GtkSalFrame( pParent, nStyle );
+}
+
+SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, SalFrameStyleFlags )
+{
+ EnsureInit();
+ return new GtkSalFrame( pParentData );
+}
+
+SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* /*pWindowData*/, bool bShow )
+{
+ EnsureInit();
+ //FIXME: Missing CreateObject functionality ...
+ return new GtkSalObject( static_cast<GtkSalFrame*>(pParent), bShow );
+}
+
+extern "C"
+{
+ typedef void*(* getDefaultFnc)();
+ typedef void(* addItemFnc)(void *, const char *);
+}
+
+void GtkInstance::AddToRecentDocumentList(const OUString& rFileUrl, const OUString&, const OUString&)
+{
+ EnsureInit();
+ OString sGtkURL;
+ rtl_TextEncoding aSystemEnc = osl_getThreadTextEncoding();
+ if ((aSystemEnc == RTL_TEXTENCODING_UTF8) || !rFileUrl.startsWith( "file://" ))
+ sGtkURL = OUStringToOString(rFileUrl, RTL_TEXTENCODING_UTF8);
+ else
+ {
+ //Non-utf8 locales are a bad idea if trying to work with non-ascii filenames
+ //Decode %XX components
+ OUString sDecodedUri = rtl::Uri::decode(rFileUrl.copy(7), rtl_UriDecodeToIuri, RTL_TEXTENCODING_UTF8);
+ //Convert back to system locale encoding
+ OString sSystemUrl = OUStringToOString(sDecodedUri, aSystemEnc);
+ //Encode to an escaped ASCII-encoded URI
+ gchar *g_uri = g_filename_to_uri(sSystemUrl.getStr(), nullptr, nullptr);
+ sGtkURL = OString(g_uri);
+ g_free(g_uri);
+ }
+ GtkRecentManager *manager = gtk_recent_manager_get_default ();
+ gtk_recent_manager_add_item (manager, sGtkURL.getStr());
+}
+
+SalInfoPrinter* GtkInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
+ ImplJobSetup* pSetupData )
+{
+ EnsureInit();
+ mbPrinterInit = true;
+ // create and initialize SalInfoPrinter
+ PspSalInfoPrinter* pPrinter = new GtkSalInfoPrinter;
+ configurePspInfoPrinter(pPrinter, pQueueInfo, pSetupData);
+ return pPrinter;
+}
+
+std::unique_ptr<SalPrinter> GtkInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
+{
+ EnsureInit();
+ mbPrinterInit = true;
+ return std::unique_ptr<SalPrinter>(new GtkSalPrinter( pInfoPrinter ));
+}
+
+/*
+ * These methods always occur in pairs
+ * A ThreadsEnter is followed by a ThreadsLeave
+ * We need to queue up the recursive lock count
+ * for each pair, so we can accurately restore
+ * it later.
+ */
+thread_local std::stack<sal_uInt32> GtkYieldMutex::yieldCounts;
+
+void GtkYieldMutex::ThreadsEnter()
+{
+ acquire();
+ if (!yieldCounts.empty()) {
+ auto n = yieldCounts.top();
+ yieldCounts.pop();
+ assert(n > 0);
+ n--;
+ if (n > 0)
+ acquire(n);
+ }
+}
+
+void GtkYieldMutex::ThreadsLeave()
+{
+ assert(m_nCount != 0);
+ yieldCounts.push(m_nCount);
+ release(true);
+}
+
+std::unique_ptr<SalVirtualDevice> GtkInstance::CreateVirtualDevice( SalGraphics *pG,
+ long &nDX, long &nDY,
+ DeviceFormat eFormat,
+ const SystemGraphicsData* /*pGd*/ )
+{
+ EnsureInit();
+ SvpSalGraphics *pSvpSalGraphics = dynamic_cast<SvpSalGraphics*>(pG);
+ assert(pSvpSalGraphics);
+ std::unique_ptr<SalVirtualDevice> pNew(new SvpSalVirtualDevice(eFormat, pSvpSalGraphics->getSurface()));
+ pNew->SetSize( nDX, nDY );
+ return pNew;
+}
+
+std::shared_ptr<SalBitmap> GtkInstance::CreateSalBitmap()
+{
+ EnsureInit();
+ return SvpSalInstance::CreateSalBitmap();
+}
+
+std::unique_ptr<SalMenu> GtkInstance::CreateMenu( bool bMenuBar, Menu* pVCLMenu )
+{
+ EnsureInit();
+ GtkSalMenu* pSalMenu = new GtkSalMenu( bMenuBar );
+ pSalMenu->SetMenu( pVCLMenu );
+ return std::unique_ptr<SalMenu>(pSalMenu);
+}
+
+std::unique_ptr<SalMenuItem> GtkInstance::CreateMenuItem( const SalItemParams & rItemData )
+{
+ EnsureInit();
+ return std::unique_ptr<SalMenuItem>(new GtkSalMenuItem( &rItemData ));
+}
+
+SalTimer* GtkInstance::CreateSalTimer()
+{
+ EnsureInit();
+ assert( nullptr == m_pTimer );
+ if ( nullptr == m_pTimer )
+ m_pTimer = new GtkSalTimer();
+ return m_pTimer;
+}
+
+void GtkInstance::RemoveTimer ()
+{
+ EnsureInit();
+ m_pTimer = nullptr;
+}
+
+bool GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
+{
+ EnsureInit();
+ return GetGtkSalData()->Yield( bWait, bHandleAllCurrentEvents );
+}
+
+bool GtkInstance::IsTimerExpired()
+{
+ EnsureInit();
+ return (m_pTimer && m_pTimer->Expired());
+}
+
+bool GtkInstance::AnyInput( VclInputFlags nType )
+{
+ EnsureInit();
+ if( (nType & VclInputFlags::TIMER) && IsTimerExpired() )
+ return true;
+ if (!gdk_events_pending())
+ return false;
+
+ if (nType == VCL_INPUT_ANY)
+ return true;
+
+ bool bRet = false;
+ std::stack<GdkEvent*> aEvents;
+ GdkEvent *pEvent = nullptr;
+ while ((pEvent = gdk_event_get()))
+ {
+ aEvents.push(pEvent);
+ VclInputFlags nEventType = categorizeEvent(pEvent);
+ if ( (nEventType & nType) || ( nEventType == VclInputFlags::NONE && (nType & VclInputFlags::OTHER) ) )
+ {
+ bRet = true;
+ break;
+ }
+ }
+
+ while (!aEvents.empty())
+ {
+ pEvent = aEvents.top();
+ gdk_event_put(pEvent);
+ gdk_event_free(pEvent);
+ aEvents.pop();
+ }
+ return bRet;
+}
+
+std::unique_ptr<GenPspGraphics> GtkInstance::CreatePrintGraphics()
+{
+ EnsureInit();
+ return std::make_unique<GenPspGraphics>();
+}
+
+std::shared_ptr<vcl::unx::GtkPrintWrapper> const &
+GtkInstance::getPrintWrapper() const
+{
+ if (!m_xPrintWrapper)
+ m_xPrintWrapper.reset(new vcl::unx::GtkPrintWrapper);
+ return m_xPrintWrapper;
+}
+
+const cairo_font_options_t* GtkInstance::GetCairoFontOptions()
+{
+ const cairo_font_options_t* pCairoFontOptions = gdk_screen_get_font_options(gdk_screen_get_default());
+ if (!m_pLastCairoFontOptions && pCairoFontOptions)
+ m_pLastCairoFontOptions = cairo_font_options_copy(pCairoFontOptions);
+ return pCairoFontOptions;
+}
+
+const cairo_font_options_t* GtkInstance::GetLastSeenCairoFontOptions() const
+{
+ return m_pLastCairoFontOptions;
+}
+
+void GtkInstance::ResetLastSeenCairoFontOptions(const cairo_font_options_t* pCairoFontOptions)
+{
+ if (m_pLastCairoFontOptions)
+ cairo_font_options_destroy(m_pLastCairoFontOptions);
+ if (pCairoFontOptions)
+ m_pLastCairoFontOptions = cairo_font_options_copy(pCairoFontOptions);
+ else
+ m_pLastCairoFontOptions = nullptr;
+}
+
+
namespace
{
struct TypeEntry
diff --git a/vcl/unx/gtk3/gtk3gtkprintwrapper.cxx b/vcl/unx/gtk3/gtk3gtkprintwrapper.cxx
index edefca9626ad..b1a8b9c66d13 100644
--- a/vcl/unx/gtk3/gtk3gtkprintwrapper.cxx
+++ b/vcl/unx/gtk3/gtk3gtkprintwrapper.cxx
@@ -7,6 +7,154 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../gtk/gtkprintwrapper.cxx"
+#include <cassert>
+
+#include <rtl/ustring.hxx>
+
+#include <unx/gtk/gtkprintwrapper.hxx>
+
+namespace vcl
+{
+namespace unx
+{
+
+GtkPrintWrapper::GtkPrintWrapper()
+{
+}
+
+GtkPrintWrapper::~GtkPrintWrapper()
+{
+}
+
+bool GtkPrintWrapper::supportsPrinting() const
+{
+ (void) this; // loplugin:staticmethods
+ return true;
+}
+
+bool GtkPrintWrapper::supportsPrintSelection() const
+{
+ (void) this; // loplugin:staticmethods
+ return true;
+}
+
+GtkPageSetup* GtkPrintWrapper::page_setup_new() const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_page_setup_new();
+}
+
+GtkPrintJob* GtkPrintWrapper::print_job_new(const gchar* title, GtkPrinter* printer, GtkPrintSettings* settings, GtkPageSetup* page_setup) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_job_new(title, printer, settings, page_setup);
+}
+
+void GtkPrintWrapper::print_job_send(GtkPrintJob* job, GtkPrintJobCompleteFunc callback, gpointer user_data, GDestroyNotify dnotify) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_job_send(job, callback, user_data, dnotify);
+}
+
+gboolean GtkPrintWrapper::print_job_set_source_file(GtkPrintJob* job, const gchar* filename, GError** error) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_job_set_source_file(job, filename, error);
+}
+
+const gchar* GtkPrintWrapper::print_settings_get(GtkPrintSettings* settings, const gchar* key) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_settings_get(settings, key);
+}
+
+gboolean GtkPrintWrapper::print_settings_get_collate(GtkPrintSettings* settings) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_settings_get_collate(settings);
+}
+
+void GtkPrintWrapper::print_settings_set_collate(GtkPrintSettings* settings, gboolean collate) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_settings_set_collate(settings, collate);
+}
+
+gint GtkPrintWrapper::print_settings_get_n_copies(GtkPrintSettings* settings) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_settings_get_n_copies(settings);
+}
+
+void GtkPrintWrapper::print_settings_set_n_copies(GtkPrintSettings* settings, gint num_copies) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_settings_set_n_copies(settings, num_copies);
+}
+
+GtkPageRange* GtkPrintWrapper::print_settings_get_page_ranges(GtkPrintSettings* settings, gint* num_ranges) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_settings_get_page_ranges(settings, num_ranges);
+}
+
+void GtkPrintWrapper::print_settings_set_print_pages(GtkPrintSettings* settings, GtkPrintPages pages) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_settings_set_print_pages(settings, pages);
+}
+
+GtkWidget* GtkPrintWrapper::print_unix_dialog_new() const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_unix_dialog_new(nullptr, nullptr);
+}
+
+void GtkPrintWrapper::print_unix_dialog_add_custom_tab(GtkPrintUnixDialog* dialog, GtkWidget* child, GtkWidget* tab_label) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_unix_dialog_add_custom_tab(dialog, child, tab_label);
+}
+
+GtkPrinter* GtkPrintWrapper::print_unix_dialog_get_selected_printer(GtkPrintUnixDialog* dialog) const
+{
+ (void) this; // loplugin:staticmethods
+ GtkPrinter* pRet = gtk_print_unix_dialog_get_selected_printer(dialog);
+ g_object_ref(G_OBJECT(pRet));
+ return pRet;
+}
+
+void GtkPrintWrapper::print_unix_dialog_set_manual_capabilities(GtkPrintUnixDialog* dialog, GtkPrintCapabilities capabilities) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_unix_dialog_set_manual_capabilities(dialog, capabilities);
+}
+
+GtkPrintSettings* GtkPrintWrapper::print_unix_dialog_get_settings(GtkPrintUnixDialog* dialog) const
+{
+ (void) this; // loplugin:staticmethods
+ return gtk_print_unix_dialog_get_settings(dialog);
+}
+
+void GtkPrintWrapper::print_unix_dialog_set_settings(GtkPrintUnixDialog* dialog, GtkPrintSettings* settings) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_unix_dialog_set_settings(dialog, settings);
+}
+
+void GtkPrintWrapper::print_unix_dialog_set_support_selection(GtkPrintUnixDialog* dialog, gboolean support_selection) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_unix_dialog_set_support_selection(dialog, support_selection);
+}
+
+void GtkPrintWrapper::print_unix_dialog_set_has_selection(GtkPrintUnixDialog* dialog, gboolean has_selection) const
+{
+ (void) this; // loplugin:staticmethods
+ gtk_print_unix_dialog_set_has_selection(dialog, has_selection);
+}
+
+}
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3gtksalmenu.cxx b/vcl/unx/gtk3/gtk3gtksalmenu.cxx
index d465594fc9bc..81d5d650dd26 100644
--- a/vcl/unx/gtk3/gtk3gtksalmenu.cxx
+++ b/vcl/unx/gtk3/gtk3gtksalmenu.cxx
@@ -1,5 +1,1396 @@
/* -*- 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/.
+ */
-#include "../gtk/gtksalmenu.cxx"
+#include <unx/gtk/gtksalmenu.hxx>
+
+#include <unx/gendata.hxx>
+#include <unx/saldisp.hxx>
+#include <unx/gtk/gtkdata.hxx>
+#include <unx/gtk/glomenu.h>
+#include <unx/gtk/gloactiongroup.h>
+#include <vcl/floatwin.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/pngwrite.hxx>
+#include <unx/gtk/gtkinst.hxx>
+
+#include <sal/log.hxx>
+#include <tools/stream.hxx>
+#include <window.h>
+#include <strings.hrc>
+
+static bool bUnityMode = false;
+
+/*
+ * This function generates a unique command name for each menu item
+ */
+static gchar* GetCommandForItem(GtkSalMenu* pParentMenu, sal_uInt16 nItemId)
+{
+ OString aCommand("window-");
+ aCommand = aCommand + OString::number(reinterpret_cast<unsigned long>(pParentMenu));
+ aCommand = aCommand + "-" + OString::number(nItemId);
+ return g_strdup(aCommand.getStr());
+}
+
+static gchar* GetCommandForItem(GtkSalMenuItem* pSalMenuItem)
+{
+ return GetCommandForItem(pSalMenuItem->mpParentMenu,
+ pSalMenuItem->mnId);
+}
+
+bool GtkSalMenu::PrepUpdate()
+{
+ return mpMenuModel && mpActionGroup;
+}
+
+/*
+ * Menu updating methods
+ */
+
+static void RemoveSpareItemsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nSection, unsigned nValidItems )
+{
+ sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
+
+ while ( nSectionItems > static_cast<sal_Int32>(nValidItems) )
+ {
+ gchar* aCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, --nSectionItems );
+
+ if ( aCommand != nullptr && pOldCommandList != nullptr )
+ *pOldCommandList = g_list_append( *pOldCommandList, g_strdup( aCommand ) );
+
+ g_free( aCommand );
+
+ g_lo_menu_remove_from_section( pMenu, nSection, nSectionItems );
+ }
+}
+
+typedef std::pair<GtkSalMenu*, sal_uInt16> MenuAndId;
+
+namespace
+{
+ MenuAndId decode_command(const gchar *action_name)
+ {
+ OString sCommand(action_name);
+
+ sal_Int32 nIndex = 0;
+ OString sWindow = sCommand.getToken(0, '-', nIndex);
+ OString sGtkSalMenu = sCommand.getToken(0, '-', nIndex);
+ OString sItemId = sCommand.getToken(0, '-', nIndex);
+
+ GtkSalMenu* pSalSubMenu = reinterpret_cast<GtkSalMenu*>(sGtkSalMenu.toInt64());
+
+ assert(sWindow == "window" && pSalSubMenu);
+ (void) sWindow;
+
+ return MenuAndId(pSalSubMenu, sItemId.toInt32());
+ }
+}
+
+static void RemoveDisabledItemsFromNativeMenu(GLOMenu* pMenu, GList** pOldCommandList,
+ sal_Int32 nSection, GActionGroup* pActionGroup)
+{
+ while (nSection >= 0)
+ {
+ sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
+ while (nSectionItems--)
+ {
+ gchar* pCommand = g_lo_menu_get_command_from_item_in_section(pMenu, nSection, nSectionItems);
+ // remove disabled entries
+ bool bRemove = !g_action_group_get_action_enabled(pActionGroup, pCommand);
+ if (!bRemove)
+ {
+ //also remove any empty submenus
+ GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section(pMenu, nSection, nSectionItems);
+ if (pSubMenuModel)
+ {
+ gint nSubMenuSections = g_menu_model_get_n_items(G_MENU_MODEL(pSubMenuModel));
+ if (nSubMenuSections == 0)
+ bRemove = true;
+ else if (nSubMenuSections == 1)
+ {
+ gint nItems = g_lo_menu_get_n_items_from_section(pSubMenuModel, 0);
+ if (nItems == 0)
+ bRemove = true;
+ else if (nItems == 1)
+ {
+ //If the only entry is the "No Selection Possible" entry, then we are allowed
+ //to removed it
+ gchar* pSubCommand = g_lo_menu_get_command_from_item_in_section(pSubMenuModel, 0, 0);
+ MenuAndId aMenuAndId(decode_command(pSubCommand));
+ bRemove = aMenuAndId.second == 0xFFFF;
+ g_free(pSubCommand);
+ }
+ }
+ }
+ }
+
+ if (bRemove)
+ {
+ //but tdf#86850 Always display clipboard functions
+ bRemove = g_strcmp0(pCommand, ".uno:Cut") &&
+ g_strcmp0(pCommand, ".uno:Copy") &&
+ g_strcmp0(pCommand, ".uno:Paste");
+ }
+
+ if (bRemove)
+ {
+ if (pCommand != nullptr && pOldCommandList != nullptr)
+ *pOldCommandList = g_list_append(*pOldCommandList, g_strdup(pCommand));
+ g_lo_menu_remove_from_section(pMenu, nSection, nSectionItems);
+ }
+
+ g_free(pCommand);
+ }
+ --nSection;
+ }
+}
+
+static void RemoveSpareSectionsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, sal_Int32 nLastSection )
+{
+ if ( pMenu == nullptr || pOldCommandList == nullptr )
+ return;
+
+ sal_Int32 n = g_menu_model_get_n_items( G_MENU_MODEL( pMenu ) ) - 1;
+
+ for ( ; n > nLastSection; n--)
+ {
+ RemoveSpareItemsFromNativeMenu( pMenu, pOldCommandList, n, 0 );
+ g_lo_menu_remove( pMenu, n );
+ }
+}
+
+static gint CompareStr( gpointer str1, gpointer str2 )
+{
+ return g_strcmp0( static_cast<const gchar*>(str1), static_cast<const gchar*>(str2) );
+}
+
+static void RemoveUnusedCommands( GLOActionGroup* pActionGroup, GList* pOldCommandList, GList* pNewCommandList )
+{
+ if ( pActionGroup == nullptr || pOldCommandList == nullptr )
+ {
+ g_list_free_full( pOldCommandList, g_free );
+ g_list_free_full( pNewCommandList, g_free );
+ return;
+ }
+
+ while ( pNewCommandList != nullptr )
+ {
+ GList* pNewCommand = g_list_first( pNewCommandList );
+ pNewCommandList = g_list_remove_link( pNewCommandList, pNewCommand );
+
+ gpointer aCommand = g_list_nth_data( pNewCommand, 0 );
+
+ GList* pOldCommand = g_list_find_custom( pOldCommandList, aCommand, reinterpret_cast<GCompareFunc>(CompareStr) );
+
+ if ( pOldCommand != nullptr )
+ {
+ pOldCommandList = g_list_remove_link( pOldCommandList, pOldCommand );
+ g_list_free_full( pOldCommand, g_free );
+ }
+
+ g_list_free_full( pNewCommand, g_free );
+ }
+
+ while ( pOldCommandList != nullptr )
+ {
+ GList* pCommand = g_list_first( pOldCommandList );
+ pOldCommandList = g_list_remove_link( pOldCommandList, pCommand );
+
+ gchar* aCommand = static_cast<gchar*>(g_list_nth_data( pCommand, 0 ));
+
+ g_lo_action_group_remove( pActionGroup, aCommand );
+
+ g_list_free_full( pCommand, g_free );
+ }
+}
+
+void GtkSalMenu::ImplUpdate(bool bRecurse, bool bRemoveDisabledEntries)
+{
+ SolarMutexGuard aGuard;
+
+ SAL_INFO("vcl.unity", "ImplUpdate pre PrepUpdate");
+ if( !PrepUpdate() )
+ return;
+
+ if (mbNeedsUpdate)
+ {
+ mbNeedsUpdate = false;
+ if (mbMenuBar && maUpdateMenuBarIdle.IsActive())
+ {
+ maUpdateMenuBarIdle.Stop();
+ maUpdateMenuBarIdle.Invoke();
+ return;
+ }
+ }
+
+ Menu* pVCLMenu = mpVCLMenu;
+ GLOMenu* pLOMenu = G_LO_MENU( mpMenuModel );
+ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
+ SAL_INFO("vcl.unity", "Syncing vcl menu " << pVCLMenu << " to menu model " << pLOMenu << " and action group " << pActionGroup);
+ GList *pOldCommandList = nullptr;
+ GList *pNewCommandList = nullptr;
+
+ sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
+
+ if ( nLOMenuSize == 0 )
+ g_lo_menu_new_section( pLOMenu, 0, nullptr );
+
+ sal_Int32 nSection = 0;
+ sal_Int32 nItemPos = 0;
+ sal_Int32 validItems = 0;
+ sal_Int32 nItem;
+
+ for ( nItem = 0; nItem < static_cast<sal_Int32>(GetItemCount()); nItem++ ) {
+ if ( !IsItemVisible( nItem ) )
+ continue;
+
+ GtkSalMenuItem *pSalMenuItem = GetItemAtPos( nItem );
+ sal_uInt16 nId = pSalMenuItem->mnId;
+
+ // PopupMenu::ImplExecute might add <No Selection Possible> entry to top-level
+ // popup menu, but we have our own implementation below, so skip that one.
+ if ( nId == 0xFFFF )
+ continue;
+
+ if ( pSalMenuItem->mnType == MenuItemType::SEPARATOR )
+ {
+ // Delete extra items from current section.
+ RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
+
+ nSection++;
+ nItemPos = 0;
+ validItems = 0;
+
+ if ( nLOMenuSize <= nSection )
+ {
+ g_lo_menu_new_section( pLOMenu, nSection, nullptr );
+ nLOMenuSize++;
+ }
+
+ continue;
+ }
+
+ if ( nItemPos >= g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
+ g_lo_menu_insert_in_section( pLOMenu, nSection, nItemPos, "EMPTY STRING" );
+
+ // Get internal menu item values.
+ OUString aText = pVCLMenu->GetItemText( nId );
+ Image aImage = pVCLMenu->GetItemImage( nId );
+ bool bEnabled = pVCLMenu->IsItemEnabled( nId );
+ vcl::KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
+ bool bChecked = pVCLMenu->IsItemChecked( nId );
+ MenuItemBits itemBits = pVCLMenu->GetItemBits( nId );
+
+ // Store current item command in command list.
+ gchar *aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pLOMenu, nSection, nItemPos );
+
+ if ( aCurrentCommand != nullptr )
+ pOldCommandList = g_list_append( pOldCommandList, aCurrentCommand );
+
+ // Get the new command for the item.
+ gchar* aNativeCommand = GetCommandForItem(pSalMenuItem);
+
+ // Force updating of native menu labels.
+ NativeSetItemText( nSection, nItemPos, aText );
+ NativeSetItemIcon( nSection, nItemPos, aImage );
+ NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( GetFrame()->GetWindow() ) );
+
+ if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == nullptr )
+ {
+ NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, false );
+ NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
+ NativeSetEnableItem( aNativeCommand, bEnabled );
+
+ pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
+ }
+
+ GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
+
+ if ( pSubmenu && pSubmenu->GetMenu() )
+ {
+ bool bNonMenuChangedToMenu = NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, false, true );
+ pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
+
+ GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+
+ if ( pSubMenuModel == nullptr )
+ {
+ g_lo_menu_new_submenu_in_item_in_section( pLOMenu, nSection, nItemPos );
+ pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+ }
+
+ g_object_unref( pSubMenuModel );
+
+ if (bRecurse || bNonMenuChangedToMenu)
+ {
+ SAL_INFO("vcl.unity", "preparing submenu " << pSubMenuModel << " to menu model " << G_MENU_MODEL(pSubMenuModel) << " and action group " << G_ACTION_GROUP(pActionGroup));
+ pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
+ pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
+ pSubmenu->ImplUpdate(true, bRemoveDisabledEntries);
+ }
+ }
+
+ g_free( aNativeCommand );
+
+ ++nItemPos;
+ ++validItems;
+ }
+
+ if (bRemoveDisabledEntries)
+ {
+ // Delete disabled items in last section.
+ RemoveDisabledItemsFromNativeMenu(pLOMenu, &pOldCommandList, nSection, G_ACTION_GROUP(pActionGroup));
+ }
+
+ // Delete extra items in last section.
+ RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
+
+ // Delete extra sections.
+ RemoveSpareSectionsFromNativeMenu( pLOMenu, &pOldCommandList, nSection );
+
+ // Delete unused commands.
+ RemoveUnusedCommands( pActionGroup, pOldCommandList, pNewCommandList );
+
+ // Resolves: tdf#103166 if the menu is empty, add a disabled
+ // <No Selection Possible> placeholder.
+ sal_Int32 nSectionsCount = g_menu_model_get_n_items(G_MENU_MODEL(pLOMenu));
+ gint nItemsCount = 0;
+ for (nSection = 0; nSection < nSectionsCount; ++nSection)
+ {
+ nItemsCount += g_lo_menu_get_n_items_from_section(pLOMenu, nSection);
+ if (nItemsCount)
+ break;
+ }
+ if (!nItemsCount)
+ {
+ gchar* aNativeCommand = GetCommandForItem(this, 0xFFFF);
+ OUString aPlaceholderText(VclResId(SV_RESID_STRING_NOSELECTIONPOSSIBLE));
+ g_lo_menu_insert_in_section(pLOMenu, nSection-1, 0,
+ OUStringToOString(aPlaceholderText, RTL_TEXTENCODING_UTF8).getStr());
+ NativeSetItemCommand(nSection-1, 0, 0xFFFF, aNativeCommand, MenuItemBits::NONE, false, false);
+ NativeSetEnableItem(aNativeCommand, false);
+ g_free(aNativeCommand);
+ }
+}
+
+void GtkSalMenu::Update()
+{
+ //find out if top level is a menubar or not, if not, then it's a popup menu
+ //hierarchy and in those we hide (most) disabled entries
+ const GtkSalMenu* pMenu = this;
+ while (pMenu->mpParentSalMenu)
+ pMenu = pMenu->mpParentSalMenu;
+ ImplUpdate(false, !pMenu->mbMenuBar);
+}
+
+static void MenuPositionFunc(GtkMenu* menu, gint* x, gint* y, gboolean* push_in, gpointer user_data)
+{
+ Point *pPos = static_cast<Point*>(user_data);
+ *x = pPos->X();
+ if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
+ {
+ GtkRequisition natural_size;
+ gtk_widget_get_preferred_size(GTK_WIDGET(menu), nullptr, &natural_size);
+ *x -= natural_size.width;
+ }
+ *y = pPos->Y();
+ *push_in = false;
+}
+
+bool GtkSalMenu::ShowNativePopupMenu(FloatingWindow* pWin, const tools::Rectangle& rRect,
+ FloatWinPopupFlags nFlags)
+{
+ VclPtr<vcl::Window> xParent = pWin->ImplGetWindowImpl()->mpRealParent;
+ mpFrame = static_cast<GtkSalFrame*>(xParent->ImplGetFrame());
+
+ GLOActionGroup* pActionGroup = g_lo_action_group_new();
+ mpActionGroup = G_ACTION_GROUP(pActionGroup);
+ mpMenuModel = G_MENU_MODEL(g_lo_menu_new());
+ // Generate the main menu structure, populates mpMenuModel
+ UpdateFull();
+
+ GtkWidget *pWidget = gtk_menu_new_from_model(mpMenuModel);
+ gtk_menu_attach_to_widget(GTK_MENU(pWidget), mpFrame->getMouseEventWidget(), nullptr);
+ gtk_widget_insert_action_group(mpFrame->getMouseEventWidget(), "win", mpActionGroup);
+
+ //run in a sub main loop because we need to keep vcl PopupMenu alive to use
+ //it during DispatchCommand, returning now to the outer loop causes the
+ //launching PopupMenu to be destroyed, instead run the subloop here
+ //until the gtk menu is destroyed
+ GMainLoop* pLoop = g_main_loop_new(nullptr, true);
+ g_signal_connect_swapped(G_OBJECT(pWidget), "deactivate", G_CALLBACK(g_main_loop_quit), pLoop);
+
+#if GTK_CHECK_VERSION(3,22,0)
+ if (gtk_check_version(3, 22, 0) == nullptr)
+ {
+ GdkGravity rect_anchor = GDK_GRAVITY_SOUTH_WEST, menu_anchor = GDK_GRAVITY_NORTH_WEST;
+
+ if (nFlags & FloatWinPopupFlags::Left)
+ {
+ rect_anchor = GDK_GRAVITY_NORTH_WEST;
+ menu_anchor = GDK_GRAVITY_NORTH_EAST;
+ }
+ else if (nFlags & FloatWinPopupFlags::Up)
+ {
+ rect_anchor = GDK_GRAVITY_NORTH_WEST;
+ menu_anchor = GDK_GRAVITY_SOUTH_WEST;
+ }
+ else if (nFlags & FloatWinPopupFlags::Right)
+ {
+ rect_anchor = GDK_GRAVITY_NORTH_EAST;
+ }
+
+ tools::Rectangle aFloatRect = FloatingWindow::ImplConvertToAbsPos(xParent, rRect);
+ aFloatRect.Move(-mpFrame->maGeometry.nX, -mpFrame->maGeometry.nY);
+ GdkRectangle rect {static_cast<int>(aFloatRect.Left()), static_cast<int>(aFloatRect.Top()),
+ static_cast<int>(aFloatRect.GetWidth()), static_cast<int>(aFloatRect.GetHeight())};
+
+ GdkWindow* gdkWindow = widget_get_window(mpFrame->getMouseEventWidget());
+ gtk_menu_popup_at_rect(GTK_MENU(pWidget), gdkWindow, &rect, rect_anchor, menu_anchor, nullptr);
+ }
+ else
+#endif
+ {
+ guint nButton;
+ guint32 nTime;
+
+ //typically there is an event, and we can then distinguish if this was
+ //launched from the keyboard (gets auto-mnemoniced) or the mouse (which
+ //doesn't)
+ GdkEvent *pEvent = gtk_get_current_event();
+ if (pEvent)
+ {
+ gdk_event_get_button(pEvent, &nButton);
+ nTime = gdk_event_get_time(pEvent);
+ }
+ else
+ {
+ nButton = 0;
+ nTime = GtkSalFrame::GetLastInputEventTime();
+ }
+
+ // do the same strange semantics as vcl popup windows to arrive at a frame geometry
+ // in mirrored UI case; best done by actually executing the same code
+ sal_uInt16 nArrangeIndex;
+ Point aPos = FloatingWindow::ImplCalcPos(pWin, rRect, nFlags, nArrangeIndex);
+ aPos = FloatingWindow::ImplConvertToAbsPos(xParent, aPos);
+
+ gtk_menu_popup(GTK_MENU(pWidget), nullptr, nullptr, MenuPositionFunc,
+ &aPos, nButton, nTime);
+ }
+
+ if (g_main_loop_is_running(pLoop))
+ {
+ gdk_threads_leave();
+ g_main_loop_run(pLoop);
+ gdk_threads_enter();
+ }
+ g_main_loop_unref(pLoop);
+
+ mpVCLMenu->Deactivate();
+
+ gtk_widget_insert_action_group(mpFrame->getMouseEventWidget(), "win", nullptr);
+
+ gtk_widget_destroy(pWidget);
+
+ g_object_unref(mpActionGroup);
+ ClearActionGroupAndMenuModel();
+
+ mpFrame = nullptr;
+
+ return true;
+}
+
+/*
+ * GtkSalMenu
+ */
+
+GtkSalMenu::GtkSalMenu( bool bMenuBar ) :
+ mbInActivateCallback( false ),
+ mbMenuBar( bMenuBar ),
+ mbNeedsUpdate( false ),
+ mbReturnFocusToDocument( false ),
+ mbAddedGrab( false ),
+ mpMenuBarContainerWidget( nullptr ),
+ mpMenuAllowShrinkWidget( nullptr ),
+ mpMenuBarWidget( nullptr ),
+ mpMenuBarContainerProvider( nullptr ),
+ mpMenuBarProvider( nullptr ),
+ mpCloseButton( nullptr ),
+ mpVCLMenu( nullptr ),
+ mpParentSalMenu( nullptr ),
+ mpFrame( nullptr ),
+ mpMenuModel( nullptr ),
+ mpActionGroup( nullptr )
+{
+ //typically this only gets called after the menu has been customized on the
+ //next idle slot, in the normal case of a new menubar SetFrame is called
+ //directly long before this idle would get called.
+ maUpdateMenuBarIdle.SetPriority(TaskPriority::HIGHEST);
+ maUpdateMenuBarIdle.SetInvokeHandler(LINK(this, GtkSalMenu, MenuBarHierarchyChangeHandler));
+ maUpdateMenuBarIdle.SetDebugName("Native Gtk Menu Update Idle");
+}
+
+IMPL_LINK_NOARG(GtkSalMenu, MenuBarHierarchyChangeHandler, Timer *, void)
+{
+ SAL_WARN_IF(!mpFrame, "vcl.gtk", "MenuBar layout changed, but no frame for some reason!");
+ if (!mpFrame)
+ return;
+ SetFrame(mpFrame);
+}
+
+void GtkSalMenu::SetNeedsUpdate()
+{
+ GtkSalMenu* pMenu = this;
+ // start that the menu and its parents are in need of an update
+ // on the next activation
+ while (pMenu && !pMenu->mbNeedsUpdate)
+ {
+ pMenu->mbNeedsUpdate = true;
+ pMenu = pMenu->mpParentSalMenu;
+ }
+ // only if a menubar is directly updated do we force in a full
+ // structure update
+ if (mbMenuBar && !maUpdateMenuBarIdle.IsActive())
+ maUpdateMenuBarIdle.Start();
+}
+
+void GtkSalMenu::SetMenuModel(GMenuModel* pMenuModel)
+{
+ if (mpMenuModel)
+ g_object_unref(mpMenuModel);
+ mpMenuModel = pMenuModel;
+ if (mpMenuModel)
+ g_object_ref(mpMenuModel);
+}
+
+GtkSalMenu::~GtkSalMenu()
+{
+ SolarMutexGuard aGuard;
+
+ DestroyMenuBarWidget();
+
+ if (mpMenuModel)
+ g_object_unref(mpMenuModel);
+
+ maItems.clear();
+
+ if (mpFrame)
+ mpFrame->SetMenu(nullptr);
+}
+
+bool GtkSalMenu::VisibleMenuBar()
+{
+ return mbMenuBar && (bUnityMode || mpMenuBarContainerWidget);
+}
+
+void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
+{
+ SolarMutexGuard aGuard;
+ GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
+
+ if ( nPos == MENU_APPEND )
+ maItems.push_back( pItem );
+ else
+ maItems.insert( maItems.begin() + nPos, pItem );
+
+ pItem->mpParentMenu = this;
+
+ SetNeedsUpdate();
+}
+
+void GtkSalMenu::RemoveItem( unsigned nPos )
+{
+ SolarMutexGuard aGuard;
+ maItems.erase( maItems.begin() + nPos );
+ SetNeedsUpdate();
+}
+
+void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned )
+{
+ SolarMutexGuard aGuard;
+ GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
+ GtkSalMenu *pGtkSubMenu = static_cast< GtkSalMenu* >( pSubMenu );
+
+ if ( pGtkSubMenu == nullptr )
+ return;
+
+ pGtkSubMenu->mpParentSalMenu = this;
+ pItem->mpSubMenu = pGtkSubMenu;
+
+ SetNeedsUpdate();
+}
+
+static void CloseMenuBar(GtkWidget *, gpointer pMenu)
+{
+ Application::PostUserEvent(static_cast<MenuBar*>(pMenu)->GetCloseButtonClickHdl());
+}
+
+void GtkSalMenu::ShowCloseButton(bool bShow)
+{
+ assert(mbMenuBar);
+ if (!mpMenuBarContainerWidget)
+ return;
+
+ if (!bShow)
+ {
+ if (mpCloseButton)
+ gtk_widget_destroy(mpCloseButton);
+ return;
+ }
+
+ MenuBar *pVclMenuBar = static_cast<MenuBar*>(mpVCLMenu.get());
+ mpCloseButton = gtk_button_new();
+ g_signal_connect(mpCloseButton, "clicked", G_CALLBACK(CloseMenuBar), pVclMenuBar);
+
+ gtk_button_set_relief(GTK_BUTTON(mpCloseButton), GTK_RELIEF_NONE);
+ gtk_button_set_focus_on_click(GTK_BUTTON(mpCloseButton), false);
+ gtk_widget_set_can_focus(mpCloseButton, false);
+
+ GtkStyleContext *pButtonContext = gtk_widget_get_style_context(GTK_WIDGET(mpCloseButton));
+
+ GtkCssProvider *pProvider = gtk_css_provider_new();
+ static const gchar data[] = "* { "
+ "padding: 0;"
+ "margin-left: 8px;"
+ "margin-right: 8px;"
+ "min-width: 18px;"
+ "min-height: 18px;"
+ "}";
+ const gchar olddata[] = "* { "
+ "padding: 0;"
+ "margin-left: 8px;"
+ "margin-right: 8px;"
+ "}";
+ gtk_css_provider_load_from_data(pProvider, gtk_check_version(3, 20, 0) == nullptr ? data : olddata, -1, nullptr);
+ gtk_style_context_add_provider(pButtonContext,
+ GTK_STYLE_PROVIDER(pProvider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ gtk_style_context_add_class(pButtonContext, "flat");
+ gtk_style_context_add_class(pButtonContext, "small-button");
+
+ GIcon* icon = g_themed_icon_new_with_default_fallbacks("window-close-symbolic");
+ GtkWidget* image = gtk_image_new_from_gicon(icon, GTK_ICON_SIZE_MENU);
+ gtk_widget_show(image);
+ g_object_unref(icon);
+
+ OUString sToolTip(VclResId(SV_HELPTEXT_CLOSEDOCUMENT));
+ gtk_widget_set_tooltip_text(mpCloseButton,
+ OUStringToOString(sToolTip, RTL_TEXTENCODING_UTF8).getStr());
+
+ gtk_widget_set_valign(mpCloseButton, GTK_ALIGN_CENTER);
+
+ gtk_container_add(GTK_CONTAINER(mpCloseButton), image);
+ gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), GTK_WIDGET(mpCloseButton), 1, 0, 1, 1);
+ gtk_widget_show_all(mpCloseButton);
+}
+
+//Typically when the menubar is deactivated we want the focus to return
+//to where it came from. If the menubar was activated because of F6
+//moving focus into the associated VCL menubar then on pressing ESC
+//or any other normal reason for deactivation we want focus to return
+//to the document, definitely not still stuck in the associated
+//VCL menubar. But if F6 is pressed while the menubar is activated
+//we want to pass that F6 back to the VCL menubar which will move
+//focus to the next pane by itself.
+void GtkSalMenu::ReturnFocus()
+{
+ if (mbAddedGrab)
+ {
+ gtk_grab_remove(mpMenuBarWidget);
+ mbAddedGrab = false;
+ }
+ if (!mbReturnFocusToDocument)
+ gtk_widget_grab_focus(GTK_WIDGET(mpFrame->getEventBox()));
+ else
+ mpFrame->GetWindow()->GrabFocusToDocument();
+ mbReturnFocusToDocument = false;
+}
+
+gboolean GtkSalMenu::SignalKey(GdkEventKey const * pEvent)
+{
+ if (pEvent->keyval == GDK_KEY_F6)
+ {
+ mbReturnFocusToDocument = false;
+ gtk_menu_shell_cancel(GTK_MENU_SHELL(mpMenuBarWidget));
+ //because we return false here, the keypress will continue
+ //to propagate and in the case that vcl focus is in
+ //the vcl menubar then that will also process F6 and move
+ //to the next pane
+ }
+ return false;
+}
+
+//The GtkSalMenu is owner by a Vcl Menu/MenuBar. In the menubar
+//case the vcl menubar is present and "visible", but with a 0 height
+//so it not apparent. Normally it acts as though it is not there when
+//a Native menubar is active. If we return true here, then for keyboard
+//activation and traversal with F6 through panes then the vcl menubar
+//acts as though it *is* present and we translate its take focus and F6
+//traversal key events into the gtk menubar equivalents.
+bool GtkSalMenu::CanGetFocus() const
+{
+ return mpMenuBarWidget != nullptr;
+}
+
+bool GtkSalMenu::TakeFocus()
+{
+ if (!mpMenuBarWidget)
+ return false;
+
+ //Send a keyboard event to the gtk menubar to let it know it has been
+ //activated via the keyboard. Doesn't do anything except cause the gtk
+ //menubar "keyboard_mode" member to get set to true, so typically mnemonics
+ //are shown which will serve as indication that the menubar has focus
+ //(given that we want to show it with no menus popped down)
+ GdkEvent *event = GtkSalFrame::makeFakeKeyPress(mpMenuBarWidget);
+ gtk_widget_event(mpMenuBarWidget, event);
+ gdk_event_free(event);
+
+ //this pairing results in a menubar with keyboard focus with no menus
+ //auto-popped down
+ gtk_grab_add(mpMenuBarWidget);
+ mbAddedGrab = true;
+ gtk_menu_shell_select_first(GTK_MENU_SHELL(mpMenuBarWidget), false);
+ gtk_menu_shell_deselect(GTK_MENU_SHELL(mpMenuBarWidget));
+ mbReturnFocusToDocument = true;
+ return true;
+}
+
+static void MenuBarReturnFocus(GtkMenuShell*, gpointer menu)
+{
+ GtkSalFrame::UpdateLastInputEventTime(gtk_get_current_event_time());
+ GtkSalMenu* pMenu = static_cast<GtkSalMenu*>(menu);
+ pMenu->ReturnFocus();
+}
+
+static gboolean MenuBarSignalKey(GtkWidget*, GdkEventKey* pEvent, gpointer menu)
+{
+ GtkSalMenu* pMenu = static_cast<GtkSalMenu*>(menu);
+ return pMenu->SignalKey(pEvent);
+}
+
+void GtkSalMenu::CreateMenuBarWidget()
+{
+ if (mpMenuBarContainerWidget)
+ return;
+
+ GtkGrid* pGrid = mpFrame->getTopLevelGridWidget();
+ mpMenuBarContainerWidget = gtk_grid_new();
+
+ gtk_widget_set_hexpand(GTK_WIDGET(mpMenuBarContainerWidget), true);
+ gtk_grid_insert_row(pGrid, 0);
+ gtk_grid_attach(pGrid, mpMenuBarContainerWidget, 0, 0, 1, 1);
+
+ mpMenuAllowShrinkWidget = gtk_scrolled_window_new(nullptr, nullptr);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(mpMenuAllowShrinkWidget), GTK_SHADOW_NONE);
+ // tdf#116290 external policy on scrolledwindow will not show a scrollbar,
+ // but still allow scrolled window to not be sized to the child content.
+ // So the menubar can be shrunk past its nominal smallest width.
+ // Unlike a hack using GtkFixed/GtkLayout the correct placement of the menubar occurs under RTL
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(mpMenuAllowShrinkWidget), GTK_POLICY_EXTERNAL, GTK_POLICY_NEVER);
+ gtk_grid_attach(GTK_GRID(mpMenuBarContainerWidget), mpMenuAllowShrinkWidget, 0, 0, 1, 1);
+
+ mpMenuBarWidget = gtk_menu_bar_new_from_model(mpMenuModel);
+
+ gtk_widget_insert_action_group(mpMenuBarWidget, "win", mpActionGroup);
+ gtk_widget_set_hexpand(GTK_WIDGET(mpMenuBarWidget), true);
+ gtk_widget_set_hexpand(mpMenuAllowShrinkWidget, true);
+ gtk_container_add(GTK_CONTAINER(mpMenuAllowShrinkWidget), mpMenuBarWidget);
+
+ g_signal_connect(G_OBJECT(mpMenuBarWidget), "deactivate", G_CALLBACK(MenuBarReturnFocus), this);
+ g_signal_connect(G_OBJECT(mpMenuBarWidget), "key-press-event", G_CALLBACK(MenuBarSignalKey), this);
+
+ gtk_widget_show_all(mpMenuBarContainerWidget);
+
+ ShowCloseButton( static_cast<MenuBar*>(mpVCLMenu.get())->HasCloseButton() );
+
+ ApplyPersona();
+}
+
+void GtkSalMenu::ApplyPersona()
+{
+ if (!mpMenuBarContainerWidget)
+ return;
+ assert(mbMenuBar);
+ // I'm dubious about the persona theming feature, but as it exists, lets try and support
+ // it, apply the image to the mpMenuBarContainerWidget
+ const BitmapEx& rPersonaBitmap = Application::GetSettings().GetStyleSettings().GetPersonaHeader();
+
+ GtkStyleContext *pMenuBarContainerContext = gtk_widget_get_style_context(GTK_WIDGET(mpMenuBarContainerWidget));
+ if (mpMenuBarContainerProvider)
+ {
+ gtk_style_context_remove_provider(pMenuBarContainerContext, GTK_STYLE_PROVIDER(mpMenuBarContainerProvider));
+ mpMenuBarContainerProvider = nullptr;
+ }
+ GtkStyleContext *pMenuBarContext = gtk_widget_get_style_context(GTK_WIDGET(mpMenuBarWidget));
+ if (mpMenuBarProvider)
+ {
+ gtk_style_context_remove_provider(pMenuBarContext, GTK_STYLE_PROVIDER(mpMenuBarProvider));
+ mpMenuBarProvider = nullptr;
+ }
+
+ if (!rPersonaBitmap.IsEmpty())
+ {
+ if (maPersonaBitmap != rPersonaBitmap)
+ {
+ vcl::PNGWriter aPNGWriter(rPersonaBitmap);
+ mxPersonaImage.reset(new utl::TempFile);
+ mxPersonaImage->EnableKillingFile(true);
+ SvStream* pStream = mxPersonaImage->GetStream(StreamMode::WRITE);
+ aPNGWriter.Write(*pStream);
+ mxPersonaImage->CloseStream();
+ }
+
+ mpMenuBarContainerProvider = gtk_css_provider_new();
+ OUString aBuffer = "* { background-image: url(\"" + mxPersonaImage->GetURL() + "\"); background-position: top right; }";
+ OString aResult = OUStringToOString(aBuffer, RTL_TEXTENCODING_UTF8);
+ gtk_css_provider_load_from_data(mpMenuBarContainerProvider, aResult.getStr(), aResult.getLength(), nullptr);
+ gtk_style_context_add_provider(pMenuBarContainerContext, GTK_STYLE_PROVIDER(mpMenuBarContainerProvider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+
+ // force the menubar to be transparent when persona is active otherwise for
+ // me the menubar becomes gray when its in the backdrop
+ mpMenuBarProvider = gtk_css_provider_new();
+ static const gchar data[] = "* { "
+ "background-image: none;"
+ "background-color: transparent;"
+ "}";
+ gtk_css_provider_load_from_data(mpMenuBarProvider, data, -1, nullptr);
+ gtk_style_context_add_provider(pMenuBarContext,
+ GTK_STYLE_PROVIDER(mpMenuBarProvider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ }
+ maPersonaBitmap = rPersonaBitmap;
+}
+
+void GtkSalMenu::DestroyMenuBarWidget()
+{
+ if (mpMenuBarContainerWidget)
+ {
+ gtk_widget_destroy(mpMenuBarContainerWidget);
+ mpMenuBarContainerWidget = nullptr;
+ mpCloseButton = nullptr;
+ }
+}
+
+void GtkSalMenu::SetFrame(const SalFrame* pFrame)
+{
+ SolarMutexGuard aGuard;
+ assert(mbMenuBar);
+ SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
+ mpFrame = const_cast<GtkSalFrame*>(static_cast<const GtkSalFrame*>(pFrame));
+
+ // if we had a menu on the GtkSalMenu we have to free it as we generate a
+ // full menu anyway and we might need to reuse an existing model and
+ // actiongroup
+ mpFrame->SetMenu( this );
+ mpFrame->EnsureAppMenuWatch();
+
+ // Clean menu model and action group if needed.
+ GtkWidget* pWidget = mpFrame->getWindow();
+ GdkWindow* gdkWindow = gtk_widget_get_window( pWidget );
+
+ GLOMenu* pMenuModel = G_LO_MENU( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
+ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
+ SAL_INFO("vcl.unity", "Found menu model: " << pMenuModel << " and action group: " << pActionGroup);
+
+ if ( pMenuModel )
+ {
+ if ( g_menu_model_get_n_items( G_MENU_MODEL( pMenuModel ) ) > 0 )
+ g_lo_menu_remove( pMenuModel, 0 );
+
+ mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
+ }
+
+ if ( pActionGroup )
+ {
+ g_lo_action_group_clear( pActionGroup );
+ mpActionGroup = G_ACTION_GROUP( pActionGroup );
+ }
+
+ // Generate the main menu structure.
+ if ( PrepUpdate() )
+ UpdateFull();
+
+ g_lo_menu_insert_section( pMenuModel, 0, nullptr, mpMenuModel );
+
+ if (!bUnityMode && static_cast<MenuBar*>(mpVCLMenu.get())->IsDisplayable())
+ {
+ DestroyMenuBarWidget();
+ CreateMenuBarWidget();
+ }
+}
+
+const GtkSalFrame* GtkSalMenu::GetFrame() const
+{
+ SolarMutexGuard aGuard;
+ const GtkSalMenu* pMenu = this;
+ while( pMenu && ! pMenu->mpFrame )
+ pMenu = pMenu->mpParentSalMenu;
+ return pMenu ? pMenu->mpFrame : nullptr;
+}
+
+void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck )
+{
+ SolarMutexGuard aGuard;
+
+ if ( mpActionGroup == nullptr )
+ return;
+
+ gchar* aCommand = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
+
+ if ( aCommand != nullptr || g_strcmp0( aCommand, "" ) != 0 )
+ {
+ GVariant *pCheckValue = nullptr;
+ GVariant *pCurrentState = g_action_group_get_action_state( mpActionGroup, aCommand );
+
+ if ( bits & MenuItemBits::RADIOCHECK )
+ pCheckValue = bCheck ? g_variant_new_string( aCommand ) : g_variant_new_string( "" );
+ else
+ {
+ // By default, all checked items are checkmark buttons.
+ if (bCheck || pCurrentState != nullptr)
+ pCheckValue = g_variant_new_boolean( bCheck );
+ }
+
+ if ( pCheckValue != nullptr )
+ {
+ if ( pCurrentState == nullptr || g_variant_equal( pCurrentState, pCheckValue ) == FALSE )
+ {
+ g_action_group_change_action_state( mpActionGroup, aCommand, pCheckValue );
+ }
+ else
+ {
+ g_variant_unref (pCheckValue);
+ }
+ }
+
+ if ( pCurrentState != nullptr )
+ g_variant_unref( pCurrentState );
+ }
+
+ if ( aCommand )
+ g_free( aCommand );
+}
+
+void GtkSalMenu::NativeSetEnableItem( gchar const * aCommand, gboolean bEnable )
+{
+ SolarMutexGuard aGuard;
+ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
+
+ if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bEnable )
+ g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bEnable );
+}
+
+void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const OUString& rText )
+{
+ SolarMutexGuard aGuard;
+ // Escape all underscores so that they don't get interpreted as hotkeys
+ OUString aText = rText.replaceAll( "_", "__" );
+ // Replace the LibreOffice hotkey identifier with an underscore
+ aText = aText.replace( '~', '_' );
+ OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
+
+ // Update item text only when necessary.
+ gchar* aLabel = g_lo_menu_get_label_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
+
+ if ( aLabel == nullptr || g_strcmp0( aLabel, aConvertedText.getStr() ) != 0 )
+ g_lo_menu_set_label_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aConvertedText.getStr() );
+
+ if ( aLabel )
+ g_free( aLabel );
+}
+
+namespace
+{
+ void DestroyMemoryStream(gpointer data)
+ {
+ SvMemoryStream* pMemStm = static_cast<SvMemoryStream*>(data);
+ delete pMemStm;
+ }
+}
+
+void GtkSalMenu::NativeSetItemIcon( unsigned nSection, unsigned nItemPos, const Image& rImage )
+{
+#if GLIB_CHECK_VERSION(2,38,0)
+ if (!!rImage && mbHasNullItemIcon)
+ return;
+
+ SolarMutexGuard aGuard;
+
+ if (!!rImage)
+ {
+ SvMemoryStream* pMemStm = new SvMemoryStream;
+ vcl::PNGWriter aWriter(rImage.GetBitmapEx());
+ aWriter.Write(*pMemStm);
+
+ GBytes *pBytes = g_bytes_new_with_free_func(pMemStm->GetData(),
+ pMemStm->TellEnd(),
+ DestroyMemoryStream,
+ pMemStm);
+
+ GIcon *pIcon = g_bytes_icon_new(pBytes);
+
+ g_lo_menu_set_icon_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, pIcon );
+ g_object_unref(pIcon);
+ g_bytes_unref(pBytes);
+ mbHasNullItemIcon = false;
+ }
+ else
+ {
+ g_lo_menu_set_icon_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, nullptr );
+ mbHasNullItemIcon = true;
+ }
+#else
+ (void)nSection;
+ (void)nItemPos;
+ (void)rImage;
+#endif
+}
+
+void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const vcl::KeyCode& rKeyCode, const OUString& rKeyName )
+{
+ SolarMutexGuard aGuard;
+
+ if ( rKeyName.isEmpty() )
+ return;
+
+ guint nKeyCode;
+ GdkModifierType nModifiers;
+ GtkSalFrame::KeyCodeToGdkKey(rKeyCode, &nKeyCode, &nModifiers);
+
+ gchar* aAccelerator = gtk_accelerator_name( nKeyCode, nModifiers );
+
+ gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
+
+ if ( aCurrentAccel == nullptr && g_strcmp0( aCurrentAccel, aAccelerator ) != 0 )
+ g_lo_menu_set_accelerator_to_item_in_section ( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aAccelerator );
+
+ g_free( aAccelerator );
+ g_free( aCurrentAccel );
+}
+
+bool GtkSalMenu::NativeSetItemCommand( unsigned nSection,
+ unsigned nItemPos,
+ sal_uInt16 nId,
+ const gchar* aCommand,
+ MenuItemBits nBits,
+ bool bChecked,
+ bool bIsSubmenu )
+{
+ bool bSubMenuAddedOrRemoved = false;
+
+ SolarMutexGuard aGuard;
+ GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
+
+ GVariant *pTarget = nullptr;
+
+ if (g_action_group_has_action(mpActionGroup, aCommand))
+ g_lo_action_group_remove(pActionGroup, aCommand);
+
+ if ( ( nBits & MenuItemBits::CHECKABLE ) || bIsSubmenu )
+ {
+ // Item is a checkmark button.
+ GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_BOOLEAN) );
+ GVariant* pState = g_variant_new_boolean( bChecked );
+
+ g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, nullptr, pStateType, nullptr, pState );
+ }
+ else if ( nBits & MenuItemBits::RADIOCHECK )
+ {
+ // Item is a radio button.
+ GVariantType* pParameterType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
+ GVariantType* pStateType = g_variant_type_new( reinterpret_cast<gchar const *>(G_VARIANT_TYPE_STRING) );
+ GVariant* pState = g_variant_new_string( "" );
+ pTarget = g_variant_new_string( aCommand );
+
+ g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, nullptr, pState );
+ }
+ else
+ {
+ // Item is not special, so insert a stateless action.
+ g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
+ }
+
+ GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
+
+ // Menu item is not updated unless it's necessary.
+ gchar* aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
+
+ if ( aCurrentCommand == nullptr || g_strcmp0( aCurrentCommand, aCommand ) != 0 )
+ {
+ bool bOldHasSubmenu = g_lo_menu_get_submenu_from_item_in_section(pMenu, nSection, nItemPos) != nullptr;
+ bSubMenuAddedOrRemoved = bOldHasSubmenu != bIsSubmenu;
+ if (bSubMenuAddedOrRemoved)
+ {
+ //tdf#98636 it's not good enough to unset the "submenu-action" attribute to change something
+ //from a submenu to a non-submenu item, so remove the old one entirely and re-add it to
+ //support achieving that
+ gchar* pLabel = g_lo_menu_get_label_from_item_in_section(pMenu, nSection, nItemPos);
+ g_lo_menu_remove_from_section(pMenu, nSection, nItemPos);
+ g_lo_menu_insert_in_section(pMenu, nSection, nItemPos, pLabel);
+ g_free(pLabel);
+ }
+
+ g_lo_menu_set_command_to_item_in_section( pMenu, nSection, nItemPos, aCommand );
+
+ gchar* aItemCommand = g_strconcat("win.", aCommand, nullptr );
+
+ if ( bIsSubmenu )
+ g_lo_menu_set_submenu_action_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand );
+ else
+ {
+ g_lo_menu_set_action_and_target_value_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand, pTarget );
+ pTarget = nullptr;
+ }
+
+ g_free( aItemCommand );
+ }
+
+ if ( aCurrentCommand )
+ g_free( aCurrentCommand );
+
+ if (pTarget)
+ g_variant_unref(pTarget);
+
+ return bSubMenuAddedOrRemoved;
+}
+
+GtkSalMenu* GtkSalMenu::GetTopLevel()
+{
+ GtkSalMenu *pMenu = this;
+ while (pMenu->mpParentSalMenu)
+ pMenu = pMenu->mpParentSalMenu;
+ return pMenu;
+}
+
+void GtkSalMenu::DispatchCommand(const gchar *pCommand)
+{
+ SolarMutexGuard aGuard;
+ MenuAndId aMenuAndId = decode_command(pCommand);
+ GtkSalMenu* pSalSubMenu = aMenuAndId.first;
+ GtkSalMenu* pTopLevel = pSalSubMenu->GetTopLevel();
+ if (pTopLevel->mpMenuBarWidget)
+ {
+ // tdf#125803 spacebar will toggle radios and checkbuttons without automatically
+ // closing the menu. To handle this properly I imagine we need to set groups for the
+ // radiobuttons so the others visually untoggle when the active one is toggled and
+ // we would further need to teach vcl that the state can change more than once.
+ //
+ // or we could unconditionally deactivate the menus if regardless of what particular
+ // type of menu item got activated
+ gtk_menu_shell_deactivate(GTK_MENU_SHELL(pTopLevel->mpMenuBarWidget));
+ }
+ pTopLevel->GetMenu()->HandleMenuCommandEvent(pSalSubMenu->GetMenu(), aMenuAndId.second);
+}
+
+void GtkSalMenu::ActivateAllSubmenus(Menu* pMenuBar)
+{
+ for (GtkSalMenuItem* pSalItem : maItems)
+ {
+ if ( pSalItem->mpSubMenu != nullptr )
+ {
+ // We can re-enter this method via the new event loop that gets created
+ // in GtkClipboardTransferable::getTransferDataFlavorsAsVector, so use the InActivateCallback
+ // flag to detect that and skip some startup work.
+ if (!pSalItem->mpSubMenu->mbInActivateCallback)
+ {
+ pSalItem->mpSubMenu->mbInActivateCallback = true;
+ pMenuBar->HandleMenuActivateEvent(pSalItem->mpSubMenu->GetMenu());
+ pSalItem->mpSubMenu->mbInActivateCallback = false;
+ pSalItem->mpSubMenu->ActivateAllSubmenus(pMenuBar);
+ pSalItem->mpSubMenu->Update();
+ pMenuBar->HandleMenuDeActivateEvent(pSalItem->mpSubMenu->GetMenu());
+ }
+ }
+ }
+}
+
+void GtkSalMenu::ClearActionGroupAndMenuModel()
+{
+ SetMenuModel(nullptr);
+ mpActionGroup = nullptr;
+ for (GtkSalMenuItem* pSalItem : maItems)
+ {
+ if ( pSalItem->mpSubMenu != nullptr )
+ {
+ pSalItem->mpSubMenu->ClearActionGroupAndMenuModel();
+ }
+ }
+}
+
+void GtkSalMenu::Activate(const gchar* pCommand)
+{
+ MenuAndId aMenuAndId = decode_command(pCommand);
+ GtkSalMenu* pSalMenu = aMenuAndId.first;
+ GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
+ Menu* pVclMenu = pSalMenu->GetMenu();
+ Menu* pVclSubMenu = pVclMenu->GetPopupMenu(aMenuAndId.second);
+ GtkSalMenu* pSubMenu = pSalMenu->GetItemAtPos(pVclMenu->GetItemPos(aMenuAndId.second))->mpSubMenu;
+
+ pSubMenu->mbInActivateCallback = true;
+ pTopLevel->GetMenu()->HandleMenuActivateEvent(pVclSubMenu);
+ pSubMenu->mbInActivateCallback = false;
+ pVclSubMenu->UpdateNativeMenu();
+}
+
+void GtkSalMenu::Deactivate(const gchar* pCommand)
+{
+ MenuAndId aMenuAndId = decode_command(pCommand);
+ GtkSalMenu* pSalMenu = aMenuAndId.first;
+ GtkSalMenu* pTopLevel = pSalMenu->GetTopLevel();
+ Menu* pVclMenu = pSalMenu->GetMenu();
+ Menu* pVclSubMenu = pVclMenu->GetPopupMenu(aMenuAndId.second);
+ pTopLevel->GetMenu()->HandleMenuDeActivateEvent(pVclSubMenu);
+}
+
+void GtkSalMenu::EnableUnity(bool bEnable)
+{
+ bUnityMode = bEnable;
+
+ MenuBar* pMenuBar(static_cast<MenuBar*>(mpVCLMenu.get()));
+ bool bDisplayable(pMenuBar->IsDisplayable());
+
+ if (bEnable)
+ {
+ DestroyMenuBarWidget();
+ UpdateFull();
+ if (!bDisplayable)
+ ShowMenuBar(false);
+ }
+ else
+ {
+ Update();
+ ShowMenuBar(bDisplayable);
+ }
+
+ pMenuBar->LayoutChanged();
+}
+
+void GtkSalMenu::ShowMenuBar( bool bVisible )
+{
+ // Unity tdf#106271: Can't hide global menu, so empty it instead when user wants to hide menubar,
+ if (bUnityMode)
+ {
+ if (bVisible)
+ Update();
+ else if (mpMenuModel && g_menu_model_get_n_items(G_MENU_MODEL(mpMenuModel)) > 0)
+ g_lo_menu_remove(G_LO_MENU(mpMenuModel), 0);
+ }
+ else if (bVisible)
+ CreateMenuBarWidget();
+ else
+ DestroyMenuBarWidget();
+}
+
+bool GtkSalMenu::IsItemVisible( unsigned nPos )
+{
+ SolarMutexGuard aGuard;
+ bool bVisible = false;
+
+ if ( nPos < maItems.size() )
+ bVisible = maItems[ nPos ]->mbVisible;
+
+ return bVisible;
+}
+
+void GtkSalMenu::CheckItem( unsigned, bool )
+{
+}
+
+void GtkSalMenu::EnableItem( unsigned nPos, bool bEnable )
+{
+ SolarMutexGuard aGuard;
+ if ( bUnityMode && !mbInActivateCallback && !mbNeedsUpdate && GetTopLevel()->mbMenuBar && ( nPos < maItems.size() ) )
+ {
+ gchar* pCommand = GetCommandForItem( GetItemAtPos( nPos ) );
+ NativeSetEnableItem( pCommand, bEnable );
+ g_free( pCommand );
+ }
+}
+
+void GtkSalMenu::ShowItem( unsigned nPos, bool bShow )
+{
+ SolarMutexGuard aGuard;
+ if ( nPos < maItems.size() )
+ {
+ maItems[ nPos ]->mbVisible = bShow;
+ if ( bUnityMode && !mbInActivateCallback && !mbNeedsUpdate && GetTopLevel()->mbMenuBar )
+ Update();
+ }
+}
+
+void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const OUString& rText )
+{
+ SolarMutexGuard aGuard;
+ if ( bUnityMode && !mbInActivateCallback && !mbNeedsUpdate && GetTopLevel()->mbMenuBar && ( nPos < maItems.size() ) )
+ {
+ gchar* pCommand = GetCommandForItem( static_cast< GtkSalMenuItem* >( pSalMenuItem ) );
+
+ gint nSectionsCount = g_menu_model_get_n_items( mpMenuModel );
+ for ( gint nSection = 0; nSection < nSectionsCount; ++nSection )
+ {
+ gint nItemsCount = g_lo_menu_get_n_items_from_section( G_LO_MENU( mpMenuModel ), nSection );
+ for ( gint nItem = 0; nItem < nItemsCount; ++nItem )
+ {
+ gchar* pCommandFromModel = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItem );
+
+ if ( !g_strcmp0( pCommandFromModel, pCommand ) )
+ {
+ NativeSetItemText( nSection, nItem, rText );
+ g_free( pCommandFromModel );
+ g_free( pCommand );
+ return;
+ }
+
+ g_free( pCommandFromModel );
+ }
+ }
+
+ g_free( pCommand );
+ }
+}
+
+void GtkSalMenu::SetItemImage( unsigned, SalMenuItem*, const Image& )
+{
+}
+
+void GtkSalMenu::SetAccelerator( unsigned, SalMenuItem*, const vcl::KeyCode&, const OUString& )
+{
+}
+
+void GtkSalMenu::GetSystemMenuData( SystemMenuData* )
+{
+}
+
+int GtkSalMenu::GetMenuBarHeight() const
+{
+ return mpMenuBarWidget ? gtk_widget_get_allocated_height(mpMenuBarWidget) : 0;
+}
+
+/*
+ * GtkSalMenuItem
+ */
+
+GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
+ mpParentMenu( nullptr ),
+ mpSubMenu( nullptr ),
+ mnType( pItemData->eType ),
+ mnId( pItemData->nId ),
+ mbVisible( true )
+{
+}
+
+GtkSalMenuItem::~GtkSalMenuItem()
+{
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3gtksys.cxx b/vcl/unx/gtk3/gtk3gtksys.cxx
index 2406e0aa3118..229a718c75a7 100644
--- a/vcl/unx/gtk3/gtk3gtksys.cxx
+++ b/vcl/unx/gtk3/gtk3gtksys.cxx
@@ -5,8 +5,279 @@
* 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 .
+ */
+
+#include <string.h>
+#include <gmodule.h>
+#include <gtk/gtk.h>
+#include <unx/gtk/gtkinst.hxx>
+#include <unx/gtk/gtksys.hxx>
+#include <unx/gtk/gtkbackend.hxx>
+#include <osl/module.h>
+
+GtkSalSystem *GtkSalSystem::GetSingleton()
+{
+ static GtkSalSystem *pSingleton = new GtkSalSystem();
+ return pSingleton;
+}
+
+SalSystem *GtkInstance::CreateSalSystem()
+{
+ return GtkSalSystem::GetSingleton();
+}
+
+GtkSalSystem::GtkSalSystem() : SalGenericSystem()
+{
+ mpDisplay = gdk_display_get_default();
+ countScreenMonitors();
+ // rhbz#1285356, native look will be gtk2, which crashes
+ // when gtk3 is already loaded. Until there is a solution
+ // java-side force look and feel to something that doesn't
+ // crash when we are using gtk3
+ setenv("STOC_FORCE_SYSTEM_LAF", "true", 1);
+}
+
+GtkSalSystem::~GtkSalSystem()
+{
+}
+
+int
+GtkSalSystem::GetDisplayXScreenCount()
+{
+ return gdk_display_get_n_screens (mpDisplay);
+}
+
+namespace
+{
+
+struct GdkRectangleCoincidentLess
+{
+ // fdo#78799 - detect and elide overlaying monitors of different sizes
+ bool operator()(GdkRectangle const& rLeft, GdkRectangle const& rRight)
+ {
+ return
+ rLeft.x < rRight.x
+ || rLeft.y < rRight.y
+ ;
+ }
+};
+struct GdkRectangleCoincident
+{
+ // fdo#78799 - detect and elide overlaying monitors of different sizes
+ bool operator()(GdkRectangle const& rLeft, GdkRectangle const& rRight)
+ {
+ return
+ rLeft.x == rRight.x
+ && rLeft.y == rRight.y
+ ;
+ }
+};
+
+}
+
+/**
+ * GtkSalSystem::countScreenMonitors()
+ *
+ * This method builds the vector which allows us to map from VCL's
+ * idea of linear integer ScreenNumber to gtk+'s rather more
+ * complicated screen + monitor concept.
*/
+void
+GtkSalSystem::countScreenMonitors()
+{
+ maScreenMonitors.clear();
+ for (gint i = 0; i < gdk_display_get_n_screens(mpDisplay); i++)
+ {
+ GdkScreen* const pScreen(gdk_display_get_screen(mpDisplay, i));
+ gint nMonitors(pScreen ? gdk_screen_get_n_monitors(pScreen) : 0);
+ if (nMonitors > 1)
+ {
+ std::vector<GdkRectangle> aGeometries;
+ aGeometries.reserve(nMonitors);
+ for (gint j(0); j != nMonitors; ++j)
+ {
+ GdkRectangle aGeometry;
+ gdk_screen_get_monitor_geometry(pScreen, j, &aGeometry);
+ aGeometries.push_back(aGeometry);
+ }
+ std::sort(aGeometries.begin(), aGeometries.end(),
+ GdkRectangleCoincidentLess());
+ const std::vector<GdkRectangle>::iterator aUniqueEnd(
+ std::unique(aGeometries.begin(), aGeometries.end(),
+ GdkRectangleCoincident()));
+ nMonitors = std::distance(aGeometries.begin(), aUniqueEnd);
+ }
+ maScreenMonitors.emplace_back(pScreen, nMonitors);
+ }
+}
+
+SalX11Screen
+GtkSalSystem::getXScreenFromDisplayScreen(unsigned int nScreen)
+{
+ gint nMonitor;
+
+ GdkScreen *pScreen = getScreenMonitorFromIdx (nScreen, nMonitor);
+ if (!pScreen)
+ return SalX11Screen (0);
+ if (!DLSYM_GDK_IS_X11_DISPLAY(mpDisplay))
+ return SalX11Screen (0);
+ return SalX11Screen (gdk_x11_screen_get_screen_number (pScreen));
+}
+
+GdkScreen *
+GtkSalSystem::getScreenMonitorFromIdx (int nIdx, gint &nMonitor)
+{
+ GdkScreen *pScreen = nullptr;
+ for (auto const& screenMonitor : maScreenMonitors)
+ {
+ pScreen = screenMonitor.first;
+ if (!pScreen)
+ break;
+ if (nIdx >= screenMonitor.second)
+ nIdx -= screenMonitor.second;
+ else
+ break;
+ }
+ nMonitor = nIdx;
+
+ // handle invalid monitor indexes as non-existent screens
+ if (nMonitor < 0 || (pScreen && nMonitor >= gdk_screen_get_n_monitors (pScreen)))
+ pScreen = nullptr;
+
+ return pScreen;
+}
+
+int
+GtkSalSystem::getScreenIdxFromPtr (GdkScreen *pScreen)
+{
+ int nIdx = 0;
+ for (auto const& screenMonitor : maScreenMonitors)
+ {
+ if (screenMonitor.first == pScreen)
+ return nIdx;
+ nIdx += screenMonitor.second;
+ }
+ g_warning ("failed to find screen %p", pScreen);
+ return 0;
+}
+
+int GtkSalSystem::getScreenMonitorIdx (GdkScreen *pScreen,
+ int nX, int nY)
+{
+ // TODO: this will fail horribly for exotic combinations like two
+ // monitors in mirror mode and one extra. Hopefully such
+ // abominations are not used (or, even better, not possible) in
+ // practice .-)
+ return getScreenIdxFromPtr (pScreen) +
+ gdk_screen_get_monitor_at_point (pScreen, nX, nY);
+}
+
+unsigned int GtkSalSystem::GetDisplayScreenCount()
+{
+ gint nMonitor;
+ (void)getScreenMonitorFromIdx (G_MAXINT, nMonitor);
+ return G_MAXINT - nMonitor;
+}
+
+bool GtkSalSystem::IsUnifiedDisplay()
+{
+ return gdk_display_get_n_screens (mpDisplay) == 1;
+}
+
+namespace {
+int _fallback_get_primary_monitor (GdkScreen *pScreen)
+{
+ // Use monitor name as primacy heuristic
+ int max = gdk_screen_get_n_monitors (pScreen);
+ for (int i = 0; i < max; ++i)
+ {
+ char *name = gdk_screen_get_monitor_plug_name (pScreen, i);
+ bool bLaptop = (name && !g_ascii_strncasecmp (name, "LVDS", 4));
+ g_free (name);
+ if (bLaptop)
+ return i;
+ }
+ return 0;
+}
+
+int _get_primary_monitor (GdkScreen *pScreen)
+{
+ static int (*get_fn) (GdkScreen *) = nullptr;
+ get_fn = gdk_screen_get_primary_monitor;
+ // Perhaps we have a newer gtk+ with this symbol:
+ if (!get_fn)
+ {
+ get_fn = reinterpret_cast<int(*)(GdkScreen*)>(osl_getAsciiFunctionSymbol(nullptr,
+ "gdk_screen_get_primary_monitor"));
+ }
+ if (!get_fn)
+ get_fn = _fallback_get_primary_monitor;
+ if (get_fn)
+ return get_fn (pScreen);
+ else
+ return 0;
+}
+} // end anonymous namespace
+
+unsigned int GtkSalSystem::GetDisplayBuiltInScreen()
+{
+ GdkScreen *pDefault = gdk_display_get_default_screen (mpDisplay);
+ int idx = getScreenIdxFromPtr (pDefault);
+ return idx + _get_primary_monitor (pDefault);
+}
+
+tools::Rectangle GtkSalSystem::GetDisplayScreenPosSizePixel (unsigned int nScreen)
+{
+ gint nMonitor;
+ GdkScreen *pScreen;
+ GdkRectangle aRect;
+ pScreen = getScreenMonitorFromIdx (nScreen, nMonitor);
+ if (!pScreen)
+ return tools::Rectangle();
+ gdk_screen_get_monitor_geometry (pScreen, nMonitor, &aRect);
+ return tools::Rectangle (Point(aRect.x, aRect.y), Size(aRect.width, aRect.height));
+}
+
+// convert ~ to indicate mnemonic to '_'
+static OString MapToGtkAccelerator(const OUString &rStr)
+{
+ return OUStringToOString(rStr.replaceFirst("~", "_"), RTL_TEXTENCODING_UTF8);
+}
+
+int GtkSalSystem::ShowNativeDialog (const OUString& rTitle, const OUString& rMessage,
+ const std::vector< OUString >& rButtonNames)
+{
+ OString aTitle (OUStringToOString (rTitle, RTL_TEXTENCODING_UTF8));
+ OString aMessage (OUStringToOString (rMessage, RTL_TEXTENCODING_UTF8));
+
+ GtkDialog *pDialog = GTK_DIALOG (
+ g_object_new (GTK_TYPE_MESSAGE_DIALOG,
+ "title", aTitle.getStr(),
+ "message-type", int(GTK_MESSAGE_WARNING),
+ "text", aMessage.getStr(),
+ nullptr));
+ int nButton = 0;
+ for (auto const& buttonName : rButtonNames)
+ gtk_dialog_add_button (pDialog, MapToGtkAccelerator(buttonName).getStr(), nButton++);
+ gtk_dialog_set_default_response (pDialog, 0/*nDefaultButton*/);
+
+ nButton = gtk_dialog_run (pDialog);
+ if (nButton < 0)
+ nButton = -1;
+
+ gtk_widget_destroy (GTK_WIDGET (pDialog));
-#include "../gtk/gtksys.cxx"
+ return nButton;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3hudawareness.cxx b/vcl/unx/gtk3/gtk3hudawareness.cxx
index 3d928f0fd0b1..0aa5878a1afe 100644
--- a/vcl/unx/gtk3/gtk3hudawareness.cxx
+++ b/vcl/unx/gtk3/gtk3hudawareness.cxx
@@ -1,4 +1,107 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-#include "../gtk/hudawareness.cxx"
+/*
+ * 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/.
+ */
+
+#include <string.h>
+
+#include <unx/gtk/gtksalmenu.hxx>
+#include <unx/gtk/hudawareness.h>
+
+struct HudAwarenessHandle
+{
+ GDBusConnection *connection;
+ HudAwarenessCallback callback;
+ gpointer user_data;
+ GDestroyNotify notify;
+};
+
+static void
+hud_awareness_method_call (GDBusConnection * /* connection */,
+ const gchar * /* sender */,
+ const gchar * /* object_path */,
+ const gchar * /* interface_name */,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ HudAwarenessHandle *handle = static_cast<HudAwarenessHandle*>(user_data);
+
+ if (g_str_equal (method_name, "HudActiveChanged"))
+ {
+ gboolean active;
+
+ g_variant_get (parameters, "(b)", &active);
+
+ (* handle->callback) (active, handle->user_data);
+ }
+
+ g_dbus_method_invocation_return_value (invocation, nullptr);
+}
+
+guint
+hud_awareness_register (GDBusConnection *connection,
+ const gchar *object_path,
+ HudAwarenessCallback callback,
+ gpointer user_data,
+ GDestroyNotify notify,
+ GError **error)
+{
+ static GDBusInterfaceInfo *iface;
+ static GDBusNodeInfo *info;
+ GDBusInterfaceVTable vtable;
+ HudAwarenessHandle *handle;
+ guint object_id;
+
+ memset (static_cast<void *>(&vtable), 0, sizeof (vtable));
+ vtable.method_call = hud_awareness_method_call;
+
+ if G_UNLIKELY (iface == nullptr)
+ {
+ GError *local_error = nullptr;
+
+ info = g_dbus_node_info_new_for_xml ("<node>"
+ "<interface name='com.canonical.hud.Awareness'>"
+ "<method name='CheckAwareness'/>"
+ "<method name='HudActiveChanged'>"
+ "<arg type='b'/>"
+ "</method>"
+ "</interface>"
+ "</node>",
+ &local_error);
+ g_assert_no_error (local_error);
+ iface = g_dbus_node_info_lookup_interface (info, "com.canonical.hud.Awareness");
+ g_assert (iface != nullptr);
+ }
+
+ handle = static_cast<HudAwarenessHandle*>(g_malloc (sizeof (HudAwarenessHandle)));
+
+ object_id = g_dbus_connection_register_object (connection, object_path, iface, &vtable, handle, &g_free, error);
+
+ if (object_id == 0)
+ {
+ g_free (handle);
+ return 0;
+ }
+
+ handle->connection = static_cast<GDBusConnection*>(g_object_ref (connection));
+ handle->callback = callback;
+ handle->user_data = user_data;
+ handle->notify = notify;
+
+ return object_id;
+}
+
+void
+hud_awareness_unregister (GDBusConnection *connection,
+ guint subscription_id)
+{
+ g_dbus_connection_unregister_object (connection, subscription_id);
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gtk3salprn-gtk.cxx b/vcl/unx/gtk3/gtk3salprn-gtk.cxx
index 16bf17c8562a..aeb9b1de246c 100644
--- a/vcl/unx/gtk3/gtk3salprn-gtk.cxx
+++ b/vcl/unx/gtk3/gtk3salprn-gtk.cxx
@@ -7,6 +7,956 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../gtk/salprn-gtk.cxx"
+#include <unx/gtk/gtkprintwrapper.hxx>
+
+#include <unx/gtk/gtkdata.hxx>
+#include <unx/gtk/gtkframe.hxx>
+#include <unx/gtk/gtkinst.hxx>
+#include <unx/gtk/gtkprn.hxx>
+
+#include <vcl/configsettings.hxx>
+#include <vcl/help.hxx>
+#include <vcl/print.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+
+#include <gtk/gtk.h>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <com/sun/star/sheet/XSpreadsheetView.hpp>
+#include <com/sun/star/view/PrintableState.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <officecfg/Office/Common.hxx>
+
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+#include <unotools/streamwrap.hxx>
+
+#include <cstring>
+#include <map>
+
+namespace beans = com::sun::star::beans;
+namespace uno = com::sun::star::uno;
+namespace view = com::sun::star::view;
+
+using vcl::unx::GtkPrintWrapper;
+
+using uno::UNO_QUERY;
+
+class GtkPrintDialog
+{
+public:
+ explicit GtkPrintDialog(vcl::PrinterController& io_rController);
+ bool run();
+ GtkPrinter* getPrinter() const
+ {
+ return m_xWrapper->print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(m_pDialog));
+ }
+ GtkPrintSettings* getSettings() const
+ {
+ return m_xWrapper->print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog));
+ }
+ void updateControllerPrintRange();
+
+ ~GtkPrintDialog();
+
+ static void UIOption_CheckHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis)
+ {
+ io_pThis->impl_UIOption_CheckHdl(i_pWidget);
+ }
+ static void UIOption_RadioHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis)
+ {
+ io_pThis->impl_UIOption_RadioHdl(i_pWidget);
+ }
+ static void UIOption_SelectHdl(GtkWidget* i_pWidget, GtkPrintDialog* io_pThis)
+ {
+ io_pThis->impl_UIOption_SelectHdl(i_pWidget);
+ }
+
+private:
+ beans::PropertyValue* impl_queryPropertyValue(GtkWidget* i_pWidget) const;
+ void impl_checkOptionalControlDependencies();
+
+ void impl_UIOption_CheckHdl(GtkWidget* i_pWidget);
+ void impl_UIOption_RadioHdl(GtkWidget* i_pWidget);
+ void impl_UIOption_SelectHdl(GtkWidget* i_pWidget);
+
+ void impl_initDialog();
+ void impl_initCustomTab();
+ void impl_initPrintContent(uno::Sequence<sal_Bool> const& i_rDisabled);
+
+ void impl_readFromSettings();
+ void impl_storeToSettings() const;
+
+private:
+ GtkWidget* m_pDialog;
+ vcl::PrinterController& m_rController;
+ std::map<GtkWidget*, OUString> m_aControlToPropertyMap;
+ std::map<GtkWidget*, sal_Int32> m_aControlToNumValMap;
+ std::shared_ptr<GtkPrintWrapper> m_xWrapper;
+};
+
+struct GtkSalPrinter_Impl
+{
+ OString m_sSpoolFile;
+ OUString m_sJobName;
+ GtkPrinter* m_pPrinter;
+ GtkPrintSettings* m_pSettings;
+
+ GtkSalPrinter_Impl();
+ ~GtkSalPrinter_Impl();
+};
+
+GtkSalPrinter_Impl::GtkSalPrinter_Impl()
+ : m_pPrinter(nullptr)
+ , m_pSettings(nullptr)
+{
+}
+
+GtkSalPrinter_Impl::~GtkSalPrinter_Impl()
+{
+ if (m_pPrinter)
+ {
+ g_object_unref(G_OBJECT(m_pPrinter));
+ m_pPrinter = nullptr;
+ }
+ if (m_pSettings)
+ {
+ g_object_unref(G_OBJECT(m_pSettings));
+ m_pSettings = nullptr;
+ }
+}
+
+namespace
+{
+
+GtkInstance const&
+lcl_getGtkSalInstance()
+{
+ // we _know_ this is GtkInstance
+ return *static_cast<GtkInstance*>(GetGtkSalData()->m_pInstance);
+}
+
+bool
+lcl_useSystemPrintDialog()
+{
+ return officecfg::Office::Common::Misc::UseSystemPrintDialog::get()
+ && officecfg::Office::Common::Misc::ExperimentalMode::get()
+ && lcl_getGtkSalInstance().getPrintWrapper()->supportsPrinting();
+}
+
+}
+
+GtkSalPrinter::GtkSalPrinter(SalInfoPrinter* const i_pInfoPrinter)
+ : PspSalPrinter(i_pInfoPrinter)
+{
+}
+
+GtkSalPrinter::~GtkSalPrinter() = default;
+
+bool
+GtkSalPrinter::impl_doJob(
+ const OUString* const i_pFileName,
+ const OUString& i_rJobName,
+ const OUString& i_rAppName,
+ ImplJobSetup* const io_pSetupData,
+ const bool i_bCollate,
+ vcl::PrinterController& io_rController)
+{
+ io_rController.setJobState(view::PrintableState_JOB_STARTED);
+ io_rController.jobStarted();
+ const bool bJobStarted(
+ PspSalPrinter::StartJob(i_pFileName, i_rJobName, i_rAppName,
+ 1/*i_nCopies*/, i_bCollate, true, io_pSetupData))
+ ;
+
+ if (bJobStarted)
+ {
+ io_rController.createProgressDialog();
+ const int nPages(io_rController.getFilteredPageCount());
+ for (int nPage(0); nPage != nPages; ++nPage)
+ {
+ if (nPage == nPages - 1)
+ io_rController.setLastPage(true);
+ io_rController.printFilteredPage(nPage);
+ }
+ io_rController.setJobState(view::PrintableState_JOB_COMPLETED);
+ }
+
+ return bJobStarted;
+}
+
+bool
+GtkSalPrinter::StartJob(
+ const OUString* const i_pFileName,
+ const OUString& i_rJobName,
+ const OUString& i_rAppName,
+ ImplJobSetup* io_pSetupData,
+ vcl::PrinterController& io_rController)
+{
+ if (!lcl_useSystemPrintDialog())
+ return PspSalPrinter::StartJob(i_pFileName, i_rJobName, i_rAppName, io_pSetupData, io_rController);
+
+ assert(!m_xImpl);
+
+ m_xImpl.reset(new GtkSalPrinter_Impl());
+ m_xImpl->m_sJobName = i_rJobName;
+
+ OString sFileName;
+ if (i_pFileName)
+ sFileName = OUStringToOString(*i_pFileName, osl_getThreadTextEncoding());
+
+ GtkPrintDialog aDialog(io_rController);
+ if (!aDialog.run())
+ {
+ io_rController.abortJob();
+ return false;
+ }
+ aDialog.updateControllerPrintRange();
+ m_xImpl->m_pPrinter = aDialog.getPrinter();
+ m_xImpl->m_pSettings = aDialog.getSettings();
+
+ //To-Do proper name, watch for encodings
+ sFileName = OString("/tmp/hacking.ps");
+ m_xImpl->m_sSpoolFile = sFileName;
+
+ OUString aFileName = OStringToOUString(sFileName, osl_getThreadTextEncoding());
+
+ //To-Do, swap ps/pdf for gtk_printer_accepts_ps()/gtk_printer_accepts_pdf() ?
+
+ return impl_doJob(&aFileName, i_rJobName, i_rAppName, io_pSetupData, /*bCollate*/false, io_rController);
+}
+
+bool
+GtkSalPrinter::EndJob()
+{
+ bool bRet = PspSalPrinter::EndJob();
+
+ if (!lcl_useSystemPrintDialog())
+ return bRet;
+
+ assert(m_xImpl);
+
+ if (!bRet || m_xImpl->m_sSpoolFile.isEmpty())
+ return bRet;
+
+ std::shared_ptr<GtkPrintWrapper> const xWrapper(lcl_getGtkSalInstance().getPrintWrapper());
+
+ GtkPageSetup* pPageSetup = xWrapper->page_setup_new();
+
+ GtkPrintJob* const pJob = xWrapper->print_job_new(
+ OUStringToOString(m_xImpl->m_sJobName, RTL_TEXTENCODING_UTF8).getStr(),
+ m_xImpl->m_pPrinter, m_xImpl->m_pSettings, pPageSetup);
+
+ GError* error = nullptr;
+ bRet = xWrapper->print_job_set_source_file(pJob, m_xImpl->m_sSpoolFile.getStr(), &error);
+ if (bRet)
+ xWrapper->print_job_send(pJob, nullptr, nullptr, nullptr);
+ else
+ {
+ //To-Do, do something with this
+ fprintf(stderr, "error was %s\n", error->message);
+ g_error_free(error);
+ }
+
+ g_object_unref(pPageSetup);
+ m_xImpl.reset();
+
+ //To-Do, remove temp spool file
+
+ return bRet;
+}
+
+namespace
+{
+
+void
+lcl_setHelpText(
+ GtkWidget* const io_pWidget,
+ const uno::Sequence<OUString>& i_rHelpTexts,
+ const sal_Int32 i_nIndex)
+{
+ if (i_nIndex >= 0 && i_nIndex < i_rHelpTexts.getLength())
+ gtk_widget_set_tooltip_text(io_pWidget,
+ OUStringToOString(i_rHelpTexts.getConstArray()[i_nIndex], RTL_TEXTENCODING_UTF8).getStr());
+}
+
+GtkWidget*
+lcl_makeFrame(
+ GtkWidget* const i_pChild,
+ const OUString &i_rText,
+ const uno::Sequence<OUString> &i_rHelpTexts,
+ sal_Int32* const io_pCurHelpText)
+{
+ GtkWidget* const pLabel = gtk_label_new(nullptr);
+ lcl_setHelpText(pLabel, i_rHelpTexts, !io_pCurHelpText ? 0 : (*io_pCurHelpText)++);
+ gtk_misc_set_alignment(GTK_MISC(pLabel), 0.0, 0.5);
+
+ {
+ gchar* const pText = g_markup_printf_escaped("<b>%s</b>",
+ OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr());
+ gtk_label_set_markup_with_mnemonic(GTK_LABEL(pLabel), pText);
+ g_free(pText);
+ }
+
+ GtkWidget* const pFrame = gtk_vbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(pFrame), pLabel, FALSE, FALSE, 0);
+
+ GtkWidget* const pAlignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(pAlignment), 0, 0, 12, 0);
+ gtk_box_pack_start(GTK_BOX(pFrame), pAlignment, FALSE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(pAlignment), i_pChild);
+ return pFrame;
+}
+
+void
+lcl_extractHelpTextsOrIds(
+ const beans::PropertyValue& rEntry,
+ uno::Sequence<OUString>& rHelpStrings)
+{
+ if (!(rEntry.Value >>= rHelpStrings))
+ {
+ OUString aHelpString;
+ if (rEntry.Value >>= aHelpString)
+ {
+ rHelpStrings.realloc(1);
+ *rHelpStrings.getArray() = aHelpString;
+ }
+ }
+}
+
+GtkWidget*
+lcl_combo_box_text_new()
+{
+ return gtk_combo_box_text_new();
+}
+
+void
+lcl_combo_box_text_append(GtkWidget* const pWidget, gchar const* const pText)
+{
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pWidget), pText);
+}
+
+}
+
+GtkPrintDialog::GtkPrintDialog(vcl::PrinterController& io_rController)
+ : m_rController(io_rController)
+ , m_xWrapper(lcl_getGtkSalInstance().getPrintWrapper())
+{
+ assert(m_xWrapper->supportsPrinting());
+ impl_initDialog();
+ impl_initCustomTab();
+ impl_readFromSettings();
+}
+
+void
+GtkPrintDialog::impl_initDialog()
+{
+ //To-Do, like fpicker, set UI language
+ m_pDialog = m_xWrapper->print_unix_dialog_new();
+
+ vcl::Window* const pTopWindow(Application::GetActiveTopWindow());
+ if (pTopWindow)
+ {
+ GtkSalFrame* const pFrame(dynamic_cast<GtkSalFrame*>(pTopWindow->ImplGetFrame()));
+ if (pFrame)
+ {
+ GtkWindow* const pParent(GTK_WINDOW(pFrame->getWindow()));
+ if (pParent)
+ gtk_window_set_transient_for(GTK_WINDOW(m_pDialog), pParent);
+ }
+ }
+
+ m_xWrapper->print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(m_pDialog),
+ GtkPrintCapabilities(GTK_PRINT_CAPABILITY_COPIES
+ | GTK_PRINT_CAPABILITY_COLLATE
+ | GTK_PRINT_CAPABILITY_REVERSE
+ | GTK_PRINT_CAPABILITY_GENERATE_PS
+ | GTK_PRINT_CAPABILITY_NUMBER_UP
+ | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT
+ ));
+}
+
+void
+GtkPrintDialog::impl_initCustomTab()
+{
+ typedef std::vector<std::pair<GtkWidget*, OUString> > CustomTabs_t;
+
+ const uno::Sequence<beans::PropertyValue>& rOptions(m_rController.getUIOptions());
+ std::map<OUString, GtkWidget*> aPropertyToDependencyRowMap;
+ CustomTabs_t aCustomTabs;
+ GtkWidget* pCurParent = nullptr;
+ GtkWidget* pCurTabPage = nullptr;
+ GtkWidget* pCurSubGroup = nullptr;
+ bool bIgnoreSubgroup = false;
+ for (const auto& rOption : rOptions)
+ {
+ uno::Sequence<beans::PropertyValue> aOptProp;
+ rOption.Value >>= aOptProp;
+
+ OUString aCtrlType;
+ OUString aText;
+ OUString aPropertyName;
+ uno::Sequence<OUString> aChoices;
+ uno::Sequence<sal_Bool> aChoicesDisabled;
+ uno::Sequence<OUString> aHelpTexts;
+ sal_Int64 nMinValue = 0, nMaxValue = 0;
+ sal_Int32 nCurHelpText = 0;
+ OUString aDependsOnName;
+ sal_Int32 nDependsOnValue = 0;
+ bool bUseDependencyRow = false;
+ bool bIgnore = false;
+ GtkWidget* pGroup = nullptr;
+ bool bGtkInternal = false;
+
+ //Fix fdo#69381
+ //Next options if this one is empty
+ if (!aOptProp.hasElements())
+ continue;
+
+ for (const beans::PropertyValue& rEntry : std::as_const(aOptProp))
+ {
+ if ( rEntry.Name == "Text" )
+ {
+ OUString aValue;
+ rEntry.Value >>= aValue;
+ aText = aValue.replace('~', '_');
+ }
+ else if ( rEntry.Name == "ControlType" )
+ rEntry.Value >>= aCtrlType;
+ else if ( rEntry.Name == "Choices" )
+ rEntry.Value >>= aChoices;
+ else if ( rEntry.Name == "ChoicesDisabled" )
+ rEntry.Value >>= aChoicesDisabled;
+ else if ( rEntry.Name == "Property" )
+ {
+ beans::PropertyValue aVal;
+ rEntry.Value >>= aVal;
+ aPropertyName = aVal.Name;
+ }
+ else if ( rEntry.Name == "DependsOnName" )
+ rEntry.Value >>= aDependsOnName;
+ else if ( rEntry.Name == "DependsOnEntry" )
+ rEntry.Value >>= nDependsOnValue;
+ else if ( rEntry.Name == "AttachToDependency" )
+ rEntry.Value >>= bUseDependencyRow;
+ else if ( rEntry.Name == "MinValue" )
+ rEntry.Value >>= nMinValue;
+ else if ( rEntry.Name == "MaxValue" )
+ rEntry.Value >>= nMaxValue;
+ else if ( rEntry.Name == "HelpId" )
+ {
+ uno::Sequence<OUString> aHelpIds;
+ lcl_extractHelpTextsOrIds(rEntry, aHelpIds);
+ Help* const pHelp = Application::GetHelp();
+ if (pHelp)
+ {
+ const int nLen = aHelpIds.getLength();
+ aHelpTexts.realloc(nLen);
+ std::transform(aHelpIds.begin(), aHelpIds.end(), aHelpTexts.begin(),
+ [&pHelp](const OUString& rHelpId) { return pHelp->GetHelpText(rHelpId, static_cast<weld::Widget*>(nullptr)); });
+ }
+ else // fallback
+ aHelpTexts = aHelpIds;
+ }
+ else if ( rEntry.Name == "HelpText" )
+ lcl_extractHelpTextsOrIds(rEntry, aHelpTexts);
+ else if ( rEntry.Name == "InternalUIOnly" )
+ rEntry.Value >>= bIgnore;
+ else if ( rEntry.Name == "Enabled" )
+ {
+ // Ignore this. We use UIControlOptions::isUIOptionEnabled
+ // to check whether a control should be enabled.
+ }
+ else if ( rEntry.Name == "GroupingHint" )
+ {
+ // Ignore this. We cannot add/modify controls to/on existing
+ // tabs of the Gtk print dialog.
+ }
+ else
+ {
+ SAL_INFO("vcl.gtk", "unhandled UI option entry: " << rEntry.Name);
+ }
+ }
+
+ if ( aPropertyName == "PrintContent" )
+ bGtkInternal = true;
+
+ if (aCtrlType == "Group" || !pCurParent)
+ {
+ pCurTabPage = gtk_vbox_new(FALSE, 12);
+ gtk_container_set_border_width(GTK_CONTAINER(pCurTabPage), 6);
+ lcl_setHelpText(pCurTabPage, aHelpTexts, 0);
+
+ pCurParent = pCurTabPage;
+ aCustomTabs.emplace_back(pCurTabPage, aText);
+ }
+ else if (aCtrlType == "Subgroup")
+ {
+ bIgnoreSubgroup = bIgnore;
+ if (bIgnore)
+ continue;
+ pCurParent = gtk_vbox_new(FALSE, 12);
+ gtk_container_set_border_width(GTK_CONTAINER(pCurParent), 0);
+
+ pCurSubGroup = lcl_makeFrame(pCurParent, aText, aHelpTexts, nullptr);
+ gtk_box_pack_start(GTK_BOX(pCurTabPage), pCurSubGroup, FALSE, FALSE, 0);
+ }
+ // special case: we need to map these to controls of the gtk print dialog
+ else if (bGtkInternal)
+ {
+ if ( aPropertyName == "PrintContent" )
+ {
+ // What to print? And, more importantly, is there a selection?
+ impl_initPrintContent(aChoicesDisabled);
+ }
+ }
+ else if (bIgnoreSubgroup || bIgnore)
+ continue;
+ else
+ {
+ // change handlers for all the controls set up in this block
+ // should be set _after_ the control has been made (in)active,
+ // because:
+ // 1. value of the property is _known_--we are using it to
+ // _set_ the control, right?--no need to change it back .-)
+ // 2. it may cause warning because the widget may not
+ // have been placed in m_aControlToPropertyMap yet
+
+ GtkWidget* pWidget = nullptr;
+ beans::PropertyValue* pVal = nullptr;
+ if (aCtrlType == "Bool" && pCurParent)
+ {
+ pWidget = gtk_check_button_new_with_mnemonic(
+ OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr());
+ lcl_setHelpText(pWidget, aHelpTexts, 0);
+ m_aControlToPropertyMap[pWidget] = aPropertyName;
+
+ bool bVal = false;
+ pVal = m_rController.getValue(aPropertyName);
+ if (pVal)
+ pVal->Value >>= bVal;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget), bVal);
+ gtk_widget_set_sensitive(pWidget,
+ m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr);
+ g_signal_connect(pWidget, "toggled", G_CALLBACK(GtkPrintDialog::UIOption_CheckHdl), this);
+ }
+ else if (aCtrlType == "Radio" && pCurParent)
+ {
+ GtkWidget* const pVbox = gtk_vbox_new(FALSE, 12);
+ gtk_container_set_border_width(GTK_CONTAINER(pVbox), 0);
+
+ if (!aText.isEmpty())
+ pGroup = lcl_makeFrame(pVbox, aText, aHelpTexts, &nCurHelpText);
+
+ sal_Int32 nSelectVal = 0;
+ pVal = m_rController.getValue(aPropertyName);
+ if (pVal && pVal->Value.hasValue())
+ pVal->Value >>= nSelectVal;
+
+ for (sal_Int32 m = 0; m != aChoices.getLength(); m++)
+ {
+ pWidget = gtk_radio_button_new_with_mnemonic_from_widget(
+ GTK_RADIO_BUTTON(m == 0 ? nullptr : pWidget),
+ OUStringToOString(aChoices[m].replace('~', '_'), RTL_TEXTENCODING_UTF8).getStr());
+ lcl_setHelpText(pWidget, aHelpTexts, nCurHelpText++);
+ m_aControlToPropertyMap[pWidget] = aPropertyName;
+ m_aControlToNumValMap[pWidget] = m;
+ GtkWidget* const pRow = gtk_hbox_new(FALSE, 12);
+ gtk_box_pack_start(GTK_BOX(pVbox), pRow, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(pRow), pWidget, FALSE, FALSE, 0);
+ aPropertyToDependencyRowMap[aPropertyName + OUString::number(m)] = pRow;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pWidget), m == nSelectVal);
+ gtk_widget_set_sensitive(pWidget,
+ m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr);
+ g_signal_connect(pWidget, "toggled",
+ G_CALLBACK(GtkPrintDialog::UIOption_RadioHdl), this);
+ }
+
+ if (pGroup)
+ pWidget = pGroup;
+ else
+ pWidget = pVbox;
+ }
+ else if ((aCtrlType == "List" ||
+ aCtrlType == "Range" ||
+ aCtrlType == "Edit"
+ ) && pCurParent)
+ {
+ GtkWidget* const pHbox = gtk_hbox_new(FALSE, 12);
+ gtk_container_set_border_width(GTK_CONTAINER(pHbox), 0);
+
+ if ( aCtrlType == "List" )
+ {
+ pWidget = lcl_combo_box_text_new();
+
+ for (const auto& rChoice : std::as_const(aChoices))
+ {
+ lcl_combo_box_text_append(pWidget,
+ OUStringToOString(rChoice, RTL_TEXTENCODING_UTF8).getStr());
+ }
+
+ sal_Int32 nSelectVal = 0;
+ pVal = m_rController.getValue(aPropertyName);
+ if (pVal && pVal->Value.hasValue())
+ pVal->Value >>= nSelectVal;
+ gtk_combo_box_set_active(GTK_COMBO_BOX(pWidget), nSelectVal);
+ g_signal_connect(pWidget, "changed", G_CALLBACK(GtkPrintDialog::UIOption_SelectHdl), this);
+ }
+ else if (aCtrlType == "Edit" && pCurParent)
+ {
+ pWidget = gtk_entry_new();
+
+ OUString aCurVal;
+ pVal = m_rController.getValue(aPropertyName);
+ if (pVal && pVal->Value.hasValue())
+ pVal->Value >>= aCurVal;
+ gtk_entry_set_text(GTK_ENTRY(pWidget),
+ OUStringToOString(aCurVal, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ else if (aCtrlType == "Range" && pCurParent)
+ {
+ pWidget = gtk_spin_button_new_with_range(nMinValue, nMaxValue, 1.0);
+
+ sal_Int64 nCurVal = 0;
+ pVal = m_rController.getValue(aPropertyName);
+ if (pVal && pVal->Value.hasValue())
+ pVal->Value >>= nCurVal;
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(pWidget), nCurVal);
+ }
+
+ lcl_setHelpText(pWidget, aHelpTexts, 0);
+ m_aControlToPropertyMap[pWidget] = aPropertyName;
+
+ gtk_widget_set_sensitive(pWidget,
+ m_rController.isUIOptionEnabled(aPropertyName) && pVal != nullptr);
+
+ if (!aText.isEmpty())
+ {
+ GtkWidget* const pLabel = gtk_label_new_with_mnemonic(
+ OUStringToOString(aText, RTL_TEXTENCODING_UTF8).getStr());
+ gtk_label_set_mnemonic_widget(GTK_LABEL(pLabel), pWidget);
+ gtk_box_pack_start(GTK_BOX(pHbox), pLabel, FALSE, FALSE, 0);
+ }
+
+ gtk_box_pack_start(GTK_BOX(pHbox), pWidget, FALSE, FALSE, 0);
+
+ pWidget = pHbox;
+
+ }
+ else
+ SAL_INFO("vcl.gtk", "unhandled option type: " << aCtrlType);
+
+ GtkWidget* pRow = nullptr;
+ if (pWidget)
+ {
+ if (bUseDependencyRow && !aDependsOnName.isEmpty())
+ {
+ pRow = aPropertyToDependencyRowMap[aDependsOnName + OUString::number(nDependsOnValue)];
+ if (!pRow)
+ {
+ gtk_widget_destroy(pWidget);
+ pWidget = nullptr;
+ }
+ }
+ }
+ if (pWidget)
+ {
+ if (!pRow)
+ {
+ pRow = gtk_hbox_new(FALSE, 12);
+ gtk_box_pack_start(GTK_BOX(pCurParent), pRow, FALSE, FALSE, 0);
+ }
+ if (!pGroup)
+ aPropertyToDependencyRowMap[aPropertyName + OUString::number(0)] = pRow;
+ gtk_box_pack_start(GTK_BOX(pRow), pWidget, FALSE, FALSE, 0);
+ }
+ }
+ }
+
+ CustomTabs_t::const_reverse_iterator aEnd = aCustomTabs.rend();
+ for (CustomTabs_t::const_reverse_iterator aI = aCustomTabs.rbegin(); aI != aEnd; ++aI)
+ {
+ gtk_widget_show_all(aI->first);
+ m_xWrapper->print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(m_pDialog), aI->first,
+ gtk_label_new(OUStringToOString(aI->second, RTL_TEXTENCODING_UTF8).getStr()));
+ }
+}
+
+void
+GtkPrintDialog::impl_initPrintContent(uno::Sequence<sal_Bool> const& i_rDisabled)
+{
+ SAL_WARN_IF(i_rDisabled.getLength() != 3, "vcl.gtk", "there is more choices than we expected");
+ if (i_rDisabled.getLength() != 3)
+ return;
+
+ GtkPrintUnixDialog* const pDialog(GTK_PRINT_UNIX_DIALOG(m_pDialog));
+
+ // XXX: This is a hack that depends on the number and the ordering of
+ // the controls in the rDisabled sequence (cf. the initialization of
+ // the "PrintContent" UI option in SwPrintUIOptions::SwPrintUIOptions,
+ // sw/source/core/view/printdata.cxx)
+ if (m_xWrapper->supportsPrintSelection() && !i_rDisabled[2])
+ {
+ m_xWrapper->print_unix_dialog_set_support_selection(pDialog, TRUE);
+ m_xWrapper->print_unix_dialog_set_has_selection(pDialog, TRUE);
+ }
+
+ beans::PropertyValue* const pPrintContent(
+ m_rController.getValue(OUString("PrintContent")));
+
+ if (pPrintContent)
+ {
+ sal_Int32 nSelectionType(0);
+ pPrintContent->Value >>= nSelectionType;
+ GtkPrintSettings* const pSettings(getSettings());
+ GtkPrintPages ePrintPages(GTK_PRINT_PAGES_ALL);
+ switch (nSelectionType)
+ {
+ case 0:
+ ePrintPages = GTK_PRINT_PAGES_ALL;
+ break;
+ case 1:
+ ePrintPages = GTK_PRINT_PAGES_RANGES;
+ break;
+ case 2:
+ if (m_xWrapper->supportsPrintSelection())
+ ePrintPages = GTK_PRINT_PAGES_SELECTION;
+ else
+ SAL_INFO("vcl.gtk", "the application wants to print a selection, but the present gtk version does not support it");
+ break;
+ default:
+ SAL_WARN("vcl.gtk", "unexpected selection type: " << nSelectionType);
+ }
+ m_xWrapper->print_settings_set_print_pages(pSettings, ePrintPages);
+ m_xWrapper->print_unix_dialog_set_settings(pDialog, pSettings);
+ g_object_unref(G_OBJECT(pSettings));
+ }
+}
+
+void
+GtkPrintDialog::impl_checkOptionalControlDependencies()
+{
+ for (auto& rEntry : m_aControlToPropertyMap)
+ {
+ gtk_widget_set_sensitive(rEntry.first, m_rController.isUIOptionEnabled(rEntry.second));
+ }
+}
+
+beans::PropertyValue*
+GtkPrintDialog::impl_queryPropertyValue(GtkWidget* const i_pWidget) const
+{
+ beans::PropertyValue* pVal(nullptr);
+ std::map<GtkWidget*, OUString>::const_iterator aIt(m_aControlToPropertyMap.find(i_pWidget));
+ if (aIt != m_aControlToPropertyMap.end())
+ {
+ pVal = m_rController.getValue(aIt->second);
+ SAL_WARN_IF(!pVal, "vcl.gtk", "property value not found");
+ }
+ else
+ {
+ SAL_WARN("vcl.gtk", "changed control not in property map");
+ }
+ return pVal;
+}
+
+void
+GtkPrintDialog::impl_UIOption_CheckHdl(GtkWidget* const i_pWidget)
+{
+ beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
+ if (pVal)
+ {
+ const bool bVal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget));
+ pVal->Value <<= bVal;
+
+ impl_checkOptionalControlDependencies();
+ }
+}
+
+void
+GtkPrintDialog::impl_UIOption_RadioHdl(GtkWidget* const i_pWidget)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(i_pWidget)))
+ {
+ beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
+ std::map<GtkWidget*, sal_Int32>::const_iterator it = m_aControlToNumValMap.find(i_pWidget);
+ if (pVal && it != m_aControlToNumValMap.end())
+ {
+
+ const sal_Int32 nVal = it->second;
+ pVal->Value <<= nVal;
+
+ impl_checkOptionalControlDependencies();
+ }
+ }
+}
+
+void
+GtkPrintDialog::impl_UIOption_SelectHdl(GtkWidget* const i_pWidget)
+{
+ beans::PropertyValue* const pVal = impl_queryPropertyValue(i_pWidget);
+ if (pVal)
+ {
+ const sal_Int32 nVal(gtk_combo_box_get_active(GTK_COMBO_BOX(i_pWidget)));
+ pVal->Value <<= nVal;
+
+ impl_checkOptionalControlDependencies();
+ }
+}
+
+bool
+GtkPrintDialog::run()
+{
+ bool bDoJob = false;
+ bool bContinue = true;
+ while (bContinue)
+ {
+ bContinue = false;
+ const gint nStatus = gtk_dialog_run(GTK_DIALOG(m_pDialog));
+ switch (nStatus)
+ {
+ case GTK_RESPONSE_HELP:
+ fprintf(stderr, "To-Do: Help ?\n");
+ bContinue = true;
+ break;
+ case GTK_RESPONSE_OK:
+ bDoJob = true;
+ break;
+ default:
+ break;
+ }
+ }
+ gtk_widget_hide(m_pDialog);
+ impl_storeToSettings();
+ return bDoJob;
+}
+
+void
+GtkPrintDialog::updateControllerPrintRange()
+{
+ GtkPrintSettings* const pSettings(getSettings());
+ // TODO: use get_print_pages
+ if (const gchar* const pStr = m_xWrapper->print_settings_get(pSettings, GTK_PRINT_SETTINGS_PRINT_PAGES))
+ {
+ beans::PropertyValue* pVal = m_rController.getValue(OUString("PrintRange"));
+ if (!pVal)
+ pVal = m_rController.getValue(OUString("PrintContent"));
+ SAL_WARN_IF(!pVal, "vcl.gtk", "Nothing to map standard print options to!");
+ if (pVal)
+ {
+ sal_Int32 nVal = 0;
+ if (!strcmp(pStr, "all"))
+ nVal = 0;
+ else if (!strcmp(pStr, "ranges"))
+ nVal = 1;
+ else if (!strcmp(pStr, "selection"))
+ nVal = 2;
+ pVal->Value <<= nVal;
+
+ if (nVal == 1)
+ {
+ pVal = m_rController.getValue(OUString("PageRange"));
+ SAL_WARN_IF(!pVal, "vcl.gtk", "PageRange doesn't exist!");
+ if (pVal)
+ {
+ OUStringBuffer sBuf;
+ gint num_ranges;
+ const GtkPageRange* const pRanges = m_xWrapper->print_settings_get_page_ranges(pSettings, &num_ranges);
+ for (gint i = 0; i != num_ranges && pRanges; ++i)
+ {
+ sBuf.append(sal_Int32(pRanges[i].start+1));
+ if (pRanges[i].start != pRanges[i].end)
+ {
+ sBuf.append('-');
+ sBuf.append(sal_Int32(pRanges[i].end+1));
+ }
+
+ if (i != num_ranges-1)
+ sBuf.append(',');
+ }
+ pVal->Value <<= sBuf.makeStringAndClear();
+ }
+ }
+ }
+ }
+ g_object_unref(G_OBJECT(pSettings));
+}
+
+GtkPrintDialog::~GtkPrintDialog()
+{
+ gtk_widget_destroy(m_pDialog);
+}
+
+void
+GtkPrintDialog::impl_readFromSettings()
+{
+ vcl::SettingsConfigItem* const pItem(vcl::SettingsConfigItem::get());
+ GtkPrintSettings* const pSettings(getSettings());
+
+ const OUString aPrintDialogStr("PrintDialog");
+ const OUString aCopyCount(pItem->getValue(aPrintDialogStr,
+ "CopyCount"));
+ const OUString aCollate(pItem->getValue(aPrintDialogStr,
+ "Collate"));
+
+ const gint nOldCopyCount(m_xWrapper->print_settings_get_n_copies(pSettings));
+ const sal_Int32 nCopyCount(aCopyCount.toInt32());
+ if (nCopyCount > 0 && nOldCopyCount != nCopyCount)
+ {
+ m_xWrapper->print_settings_set_n_copies(pSettings, sal::static_int_cast<gint>(nCopyCount));
+ }
+
+ const bool bOldCollate(m_xWrapper->print_settings_get_collate(pSettings));
+ const bool bCollate(aCollate.equalsIgnoreAsciiCase("true"));
+ if (bOldCollate != bCollate)
+ {
+ m_xWrapper->print_settings_set_collate(pSettings, bCollate);
+ }
+
+ m_xWrapper->print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(m_pDialog), pSettings);
+ g_object_unref(G_OBJECT(pSettings));
+}
+
+void
+GtkPrintDialog::impl_storeToSettings()
+const
+{
+ vcl::SettingsConfigItem* const pItem(vcl::SettingsConfigItem::get());
+ GtkPrintSettings* const pSettings(getSettings());
+
+ const OUString aPrintDialogStr("PrintDialog");
+ pItem->setValue(aPrintDialogStr,
+ "CopyCount",
+ OUString::number(m_xWrapper->print_settings_get_n_copies(pSettings)));
+ pItem->setValue(aPrintDialogStr,
+ "Collate",
+ m_xWrapper->print_settings_get_collate(pSettings)
+ ? OUString("true")
+ : OUString("false"))
+ ;
+ // pItem->setValue(aPrintDialog, OUString("ToFile"), );
+ g_object_unref(G_OBJECT(pSettings));
+ pItem->Commit();
+}
+
+sal_uInt32
+GtkSalInfoPrinter::GetCapabilities(
+ const ImplJobSetup* const i_pSetupData,
+ const PrinterCapType i_nType)
+{
+ if (i_nType == PrinterCapType::ExternalDialog && lcl_useSystemPrintDialog())
+ return 1;
+ return PspSalInfoPrinter::GetCapabilities(i_pSetupData, i_nType);
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkaction.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkaction.cxx
index a3fa632d08a1..b05929b90571 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkaction.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkaction.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkaction.cxx"
+#include "../../gtk3/a11y/gtk3atkaction.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkbridge.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkbridge.cxx
index d8e087956067..d31e5e429597 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkbridge.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkbridge.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkbridge.cxx"
+#include "../../gtk3/a11y/gtk3atkbridge.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkcomponent.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkcomponent.cxx
index e4eabec20fb8..63f44a3a14e9 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkcomponent.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkcomponent.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkcomponent.cxx"
+#include "../../gtk3/a11y/gtk3atkcomponent.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkeditabletext.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkeditabletext.cxx
index ea3f0895fb8e..064e72d98612 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkeditabletext.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkeditabletext.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkeditabletext.cxx"
+#include "../../gtk3/a11y/gtk3atkeditabletext.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkfactory.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkfactory.cxx
index c60db2fcc074..86d9ac43adb5 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkfactory.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkfactory.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkfactory.cxx"
+#include "../../gtk3/a11y/gtk3atkfactory.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkhypertext.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkhypertext.cxx
index bb9749c36af3..d2ce059aad62 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkhypertext.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkhypertext.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkhypertext.cxx"
+#include "../../gtk3/a11y/gtk3atkhypertext.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkimage.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkimage.cxx
index 4e2c77e9f2b1..3a1234e07462 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkimage.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkimage.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkimage.cxx"
+#include "../../gtk3/a11y/gtk3atkimage.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atklistener.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atklistener.cxx
index eca1cd7ec1d0..51d53bf9163b 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atklistener.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atklistener.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atklistener.cxx"
+#include "../../gtk3/a11y/gtk3atklistener.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkregistry.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkregistry.cxx
index 126e97a808ae..f5e79172084a 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkregistry.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkregistry.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkregistry.cxx"
+#include "../../gtk3/a11y/gtk3atkregistry.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkselection.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkselection.cxx
index f67b665304d7..ab39c0e132f0 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkselection.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkselection.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkselection.cxx"
+#include "../../gtk3/a11y/gtk3atkselection.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktable.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktable.cxx
index d886ac07296a..194791b68c10 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktable.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktable.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atktable.cxx"
+#include "../../gtk3/a11y/gtk3atktable.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktext.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktext.cxx
index e4bbd5a38980..8d668e6e69d0 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktext.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktext.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atktext.cxx"
+#include "../../gtk3/a11y/gtk3atktext.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktextattributes.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktextattributes.cxx
index b0edad06a65c..c767a95d0448 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktextattributes.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atktextattributes.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atktextattributes.cxx"
+#include "../../gtk3/a11y/gtk3atktextattributes.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkutil.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkutil.cxx
index 8c1eeaf9882b..39eb5aeebd60 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkutil.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkutil.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkutil.cxx"
+#include "../../gtk3/a11y/gtk3atkutil.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkvalue.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkvalue.cxx
index 30057943bc44..5a526e1cf909 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkvalue.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkvalue.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkvalue.cxx"
+#include "../../gtk3/a11y/gtk3atkvalue.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwindow.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwindow.cxx
index cd8479cd4df7..194e10999657 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwindow.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwindow.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkwindow.cxx"
+#include "../../gtk3/a11y/gtk3atkwindow.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwrapper.cxx b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwrapper.cxx
index 3b07e9536d77..b0029f273ee2 100644
--- a/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwrapper.cxx
+++ b/vcl/unx/gtk3_kde5/a11y/gtk3_kde5_atkwrapper.cxx
@@ -7,6 +7,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-#include "../../gtk/a11y/atkwrapper.cxx"
+#include "../../gtk3/a11y/gtk3atkwrapper.cxx"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */