1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_VCL_INC_UNX_GTK_GTKDATA_HXX
21 #define INCLUDED_VCL_INC_UNX_GTK_GTKDATA_HXX
22 
23 #define GLIB_DISABLE_DEPRECATION_WARNINGS
24 #include <gtk/gtk.h>
25 #include <gdk/gdk.h>
26 #if GTK_CHECK_VERSION(4,0,0)
27 #include <gdk/x11/gdkx.h>
28 #else
29 #include <gdk/gdkx.h>
30 #endif
31 
32 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
33 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
34 #include <unx/gendata.hxx>
35 #include <unx/saldisp.hxx>
36 #include <unx/gtk/gtksys.hxx>
37 #include <vcl/ptrstyle.hxx>
38 #include <osl/conditn.hxx>
39 #include <saltimer.hxx>
40 #include <o3tl/enumarray.hxx>
41 
42 #include <vector>
43 
44 namespace com::sun::star::accessibility { class XAccessibleEventListener; }
45 
46 class GtkSalDisplay;
47 class DocumentFocusListener;
48 
49 #if !GTK_CHECK_VERSION(4,0,0)
50 typedef GdkWindow GdkSurface;
51 typedef GdkWindowState GdkToplevelState;
52 #endif
53 
main_loop_run(GMainLoop * pLoop)54 inline void main_loop_run(GMainLoop* pLoop)
55 {
56 #if !GTK_CHECK_VERSION(4, 0, 0)
57     gdk_threads_leave();
58 #endif
59     g_main_loop_run(pLoop);
60 #if !GTK_CHECK_VERSION(4, 0, 0)
61     gdk_threads_enter();
62 #endif
63 }
64 
css_provider_load_from_data(GtkCssProvider * css_provider,const gchar * data,gssize length)65 inline void css_provider_load_from_data(GtkCssProvider *css_provider,
66                                         const gchar *data,
67                                         gssize length)
68 {
69 #if GTK_CHECK_VERSION(4, 0, 0)
70     gtk_css_provider_load_from_data(css_provider, data, length);
71 #else
72     gtk_css_provider_load_from_data(css_provider, data, length, nullptr);
73 #endif
74 }
75 
widget_get_toplevel(GtkWidget * pWidget)76 inline GtkWidget* widget_get_toplevel(GtkWidget* pWidget)
77 {
78 #if GTK_CHECK_VERSION(4, 0, 0)
79     GtkRoot* pRoot = gtk_widget_get_root(pWidget);
80     return pRoot ? GTK_WIDGET(pRoot) : pWidget;
81 #else
82     return gtk_widget_get_toplevel(pWidget);
83 #endif
84 }
85 
image_get_icon_name(GtkImage * pImage)86 inline const char* image_get_icon_name(GtkImage *pImage)
87 {
88 #if GTK_CHECK_VERSION(4, 0, 0)
89     return gtk_image_get_icon_name(pImage);
90 #else
91     const gchar* icon_name;
92     gtk_image_get_icon_name(pImage, &icon_name, nullptr);
93     return icon_name;
94 #endif
95 }
96 
widget_get_first_child(GtkWidget * pWidget)97 inline GtkWidget* widget_get_first_child(GtkWidget *pWidget)
98 {
99 #if GTK_CHECK_VERSION(4, 0, 0)
100     return gtk_widget_get_first_child(pWidget);
101 #else
102     GList* pChildren = gtk_container_get_children(GTK_CONTAINER(pWidget));
103     GList* pChild = g_list_first(pChildren);
104     GtkWidget* pRet = pChild ? static_cast<GtkWidget*>(pChild->data) : nullptr;
105     g_list_free(pChildren);
106     return pRet;
107 #endif
108 }
109 
style_context_get_color(GtkStyleContext * pStyle,GdkRGBA * pColor)110 inline void style_context_get_color(GtkStyleContext *pStyle, GdkRGBA *pColor)
111 {
112 #if GTK_CHECK_VERSION(4, 0, 0)
113     return gtk_style_context_get_color(pStyle, pColor);
114 #else
115     return gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), pColor);
116 #endif
117 }
118 
widget_get_surface(GtkWidget * pWidget)119 inline GdkSurface* widget_get_surface(GtkWidget* pWidget)
120 {
121 #if GTK_CHECK_VERSION(4,0,0)
122     return gtk_native_get_surface(gtk_widget_get_native(pWidget));
123 #else
124     return gtk_widget_get_window(pWidget);
125 #endif
126 }
127 
widget_set_cursor(GtkWidget * pWidget,GdkCursor * pCursor)128 inline void widget_set_cursor(GtkWidget *pWidget, GdkCursor *pCursor)
129 {
130 #if GTK_CHECK_VERSION(4, 0, 0)
131     gtk_widget_set_cursor(pWidget, pCursor);
132 #else
133     gdk_window_set_cursor(gtk_widget_get_window(pWidget), pCursor);
134 #endif
135 }
136 
surface_create_similar_surface(GdkSurface * pSurface,cairo_content_t eContent,int nWidth,int nHeight)137 inline cairo_surface_t * surface_create_similar_surface(GdkSurface *pSurface,
138                                                         cairo_content_t eContent,
139                                                         int nWidth,
140                                                         int nHeight)
141 {
142 #if GTK_CHECK_VERSION(4, 0, 0)
143     return gdk_surface_create_similar_surface(pSurface, eContent, nWidth, nHeight);
144 #else
145     return gdk_window_create_similar_surface(pSurface, eContent, nWidth, nHeight);
146 #endif
147 }
148 
im_context_set_client_widget(GtkIMContext * pIMContext,GtkWidget * pWidget)149 inline void im_context_set_client_widget(GtkIMContext *pIMContext, GtkWidget *pWidget)
150 {
151 #if GTK_CHECK_VERSION(4, 0, 0)
152     gtk_im_context_set_client_widget(pIMContext, pWidget);
153 #else
154     gtk_im_context_set_client_window(pIMContext, pWidget ? gtk_widget_get_window(pWidget) : nullptr);
155 #endif
156 }
157 
158 #if GTK_CHECK_VERSION(4, 0, 0)
159 typedef double gtk_coord;
160 #else
161 typedef int gtk_coord;
162 #endif
163 
surface_get_device_position(GdkSurface * pSurface,GdkDevice * pDevice,double & x,double & y,GdkModifierType * pMask)164 inline bool surface_get_device_position(GdkSurface* pSurface,
165                                         GdkDevice* pDevice,
166                                         double& x,
167                                         double& y,
168                                         GdkModifierType* pMask)
169 {
170 #if GTK_CHECK_VERSION(4, 0, 0)
171     return gdk_surface_get_device_position(pSurface, pDevice,
172                                            &x, &y,
173                                            pMask);
174 #else
175     int nX(x), nY(y);
176     bool bRet = gdk_window_get_device_position(pSurface, pDevice,
177                                                &nX, &nY,
178                                                pMask);
179     x = nX;
180     y = nY;
181     return bRet;
182 #endif
183 }
184 
surface_create_gl_context(GdkSurface * pSurface)185 inline GdkGLContext* surface_create_gl_context(GdkSurface* pSurface)
186 {
187 #if GTK_CHECK_VERSION(4, 0, 0)
188     return gdk_surface_create_gl_context(pSurface, nullptr);
189 #else
190     return gdk_window_create_gl_context(pSurface, nullptr);
191 #endif
192 }
193 
194 #if !GTK_CHECK_VERSION(4, 0, 0)
195 typedef GtkClipboard GdkClipboard;
196 #endif
197 
198 int getButtonPriority(const OString &rType);
199 
200 class GtkSalTimer final : public SalTimer
201 {
202     struct SalGtkTimeoutSource *m_pTimeout;
203 public:
204     GtkSalTimer();
205     virtual ~GtkSalTimer() override;
206     virtual void Start( sal_uInt64 nMS ) override;
207     virtual void Stop() override;
208     bool         Expired();
209 
210     sal_uLong    m_nTimeoutMS;
211 };
212 
213 class DocumentFocusListener :
214     public ::cppu::WeakImplHelper< css::accessibility::XAccessibleEventListener >
215 {
216 
217     o3tl::sorted_vector< css::uno::Reference< css::uno::XInterface > > m_aRefList;
218 
219 public:
220     /// @throws lang::IndexOutOfBoundsException
221     /// @throws uno::RuntimeException
222     void attachRecursive(
223         const css::uno::Reference< css::accessibility::XAccessible >& xAccessible
224     );
225 
226     /// @throws lang::IndexOutOfBoundsException
227     /// @throws uno::RuntimeException
228     void attachRecursive(
229         const css::uno::Reference< css::accessibility::XAccessible >& xAccessible,
230         const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext
231     );
232 
233     /// @throws lang::IndexOutOfBoundsException
234     /// @throws uno::RuntimeException
235     void attachRecursive(
236         const css::uno::Reference< css::accessibility::XAccessible >& xAccessible,
237         const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext,
238         const css::uno::Reference< css::accessibility::XAccessibleStateSet >& xStateSet
239     );
240 
241     /// @throws lang::IndexOutOfBoundsException
242     /// @throws uno::RuntimeException
243     void detachRecursive(
244         const css::uno::Reference< css::accessibility::XAccessible >& xAccessible
245     );
246 
247     /// @throws lang::IndexOutOfBoundsException
248     /// @throws uno::RuntimeException
249     void detachRecursive(
250         const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext
251     );
252 
253     /// @throws lang::IndexOutOfBoundsException
254     /// @throws uno::RuntimeException
255     void detachRecursive(
256         const css::uno::Reference< css::accessibility::XAccessibleContext >& xContext,
257         const css::uno::Reference< css::accessibility::XAccessibleStateSet >& xStateSet
258     );
259 
260     /// @throws lang::IndexOutOfBoundsException
261     /// @throws uno::RuntimeException
262     static css::uno::Reference< css::accessibility::XAccessible > getAccessible(const css::lang::EventObject& aEvent );
263 
264     // XEventListener
265     virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
266 
267     // XAccessibleEventListener
268     virtual void SAL_CALL notifyEvent( const css::accessibility::AccessibleEventObject& aEvent ) override;
269 };
270 
271 class GtkSalData final : public GenericUnixSalData
272 {
273     GSource*        m_pUserEvent;
274     osl::Mutex      m_aDispatchMutex;
275     osl::Condition  m_aDispatchCondition;
276     std::exception_ptr m_aException;
277 
278     rtl::Reference<DocumentFocusListener> m_xDocumentFocusListener;
279 
280 public:
281     GtkSalData( SalInstance *pInstance );
282     virtual ~GtkSalData() override;
283 
284     DocumentFocusListener & GetDocumentFocusListener();
285 
286     void Init();
287     virtual void Dispose() override;
288 
289     static void initNWF();
290     static void deInitNWF();
291 
292     void TriggerUserEventProcessing();
293     void TriggerAllUserEventsProcessed();
294 
295     bool Yield( bool bWait, bool bHandleAllCurrentEvents );
296     inline GdkDisplay *GetGdkDisplay();
297 
298     virtual void ErrorTrapPush() override;
299     virtual bool ErrorTrapPop( bool bIgnoreError = true ) override;
300 
301     inline GtkSalDisplay *GetGtkDisplay() const;
setException(const std::exception_ptr & exception)302     void setException(const std::exception_ptr& exception) { m_aException = exception; }
303 };
304 
305 class GtkSalFrame;
306 
307 class GtkSalDisplay : public SalGenericDisplay
308 {
309     GtkSalSystem*                   m_pSys;
310     GdkDisplay*                     m_pGdkDisplay;
311     o3tl::enumarray<PointerStyle, GdkCursor*> m_aCursors;
312     bool                            m_bStartupCompleted;
313 
314     GdkCursor* getFromSvg( OUString const & name, int nXHot, int nYHot );
315 
316 public:
317              GtkSalDisplay( GdkDisplay* pDisplay );
318     virtual ~GtkSalDisplay() override;
319 
GetGdkDisplay() const320     GdkDisplay* GetGdkDisplay() const { return m_pGdkDisplay; }
321 
getSystem() const322     GtkSalSystem* getSystem() const { return m_pSys; }
323 
324     GtkWidget* findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) const;
325 
326     virtual void deregisterFrame( SalFrame* pFrame ) override;
327     GdkCursor *getCursor( PointerStyle ePointerStyle );
328     virtual int CaptureMouse( SalFrame* pFrame );
329 
GetDefaultXScreen()330     SalX11Screen GetDefaultXScreen() { return m_pSys->GetDisplayDefaultXScreen(); }
331     Size         GetScreenSize( int nDisplayScreen );
332 
startupNotificationCompleted()333     void startupNotificationCompleted() { m_bStartupCompleted = true; }
334 
335 #if !GTK_CHECK_VERSION(4,0,0)
336     void screenSizeChanged( GdkScreen const * );
337     void monitorsChanged( GdkScreen const * );
338 #endif
339 
340     virtual void TriggerUserEventProcessing() override;
341     virtual void TriggerAllUserEventsProcessed() override;
342 };
343 
GetGtkSalData()344 inline GtkSalData* GetGtkSalData()
345 {
346     return static_cast<GtkSalData*>(ImplGetSVData()->mpSalData);
347 }
GetGdkDisplay()348 inline GdkDisplay *GtkSalData::GetGdkDisplay()
349 {
350     return GetGtkDisplay()->GetGdkDisplay();
351 }
352 
GetGtkDisplay() const353 GtkSalDisplay *GtkSalData::GetGtkDisplay() const
354 {
355     return static_cast<GtkSalDisplay *>(GetDisplay());
356 }
357 
358 #endif // INCLUDED_VCL_INC_UNX_GTK_GTKDATA_HXX
359 
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
361