1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_VCL_INC_UNX_GTK_GTKFRAME_HXX
21 #define INCLUDED_VCL_INC_UNX_GTK_GTKFRAME_HXX
27 #if GTK_CHECK_VERSION(3,0,0)
28 # include <gtk/gtkx.h>
30 #include <gdk/gdkkeysyms.h>
32 #include <salframe.hxx>
33 #include <vcl/idle.hxx>
34 #include <vcl/sysdata.hxx>
35 #include <unx/nativewindowhandleprovider.hxx>
36 #include <unx/saltype.h>
37 #include <unx/screensaverinhibitor.hxx>
39 #include "tools/link.hxx"
41 #include <com/sun/star/awt/XTopWindow.hpp>
42 #include <com/sun/star/datatransfer/DataFlavor.hpp>
43 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
44 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
49 #include <config_dbus.h>
50 #include <config_gio.h>
52 #include "headless/svpgdi.hxx"
57 #if GTK_CHECK_VERSION(3,0,0)
58 typedef ::Window GdkNativeWindow
;
59 #define GDK_WINDOW_XWINDOW(o) GDK_WINDOW_XID(o)
60 #define gdk_set_sm_client_id(i) gdk_x11_set_sm_client_id(i)
61 #define gdk_window_foreign_new_for_display(a,b) gdk_x11_window_foreign_new_for_display(a,b)
64 class GtkDnDTransferable
;
67 #if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 26)
68 typedef void GDBusConnection
;
71 class GtkSalFrame
: public SalFrame
72 , public NativeWindowHandleProvider
77 // Not all GTK Input Methods swallow key release
78 // events. Since they swallow the key press events and we
79 // are left with the key release events, we need to
80 // manually swallow those. To do this, we keep a list of
81 // the previous 10 key press events in each GtkSalFrame
82 // and when we get a key release that matches one of the
83 // key press events in our list, we swallow it.
84 struct PreviousKeyPress
91 guint16 hardware_keycode
;
94 PreviousKeyPress (GdkEventKey
*event
)
100 hardware_keycode (0),
105 window
= event
->window
;
106 send_event
= event
->send_event
;
108 state
= event
->state
;
109 keyval
= event
->keyval
;
110 hardware_keycode
= event
->hardware_keycode
;
111 group
= event
->group
;
115 PreviousKeyPress( const PreviousKeyPress
& rPrev
)
116 : window( rPrev
.window
),
117 send_event( rPrev
.send_event
),
119 state( rPrev
.state
),
120 keyval( rPrev
.keyval
),
121 hardware_keycode( rPrev
.hardware_keycode
),
125 bool operator== (GdkEventKey
*event
) const
127 return (event
!= nullptr)
128 && (event
->window
== window
)
129 && (event
->send_event
== send_event
)
130 // ignore non-Gdk state bits, e.g., these used by IBus
131 && ((event
->state
& GDK_MODIFIER_MASK
) == (state
& GDK_MODIFIER_MASK
))
132 && (event
->keyval
== keyval
)
133 && (event
->hardware_keycode
== hardware_keycode
)
134 && (event
->group
== group
)
135 && (event
->time
- time
< 300)
140 GtkSalFrame
* m_pFrame
;
141 std::list
< PreviousKeyPress
> m_aPrevKeyPresses
;
142 int m_nPrevKeyPresses
; // avoid using size()
143 GtkIMContext
* m_pIMContext
;
145 bool m_bPreeditJustChanged
;
146 SalExtTextInputEvent m_aInputEvent
;
147 std::vector
< ExtTextInputAttr
> m_aInputFlags
;
149 IMHandler( GtkSalFrame
* );
152 void createIMContext();
153 void deleteIMContext();
154 void updateIMSpotLocation();
155 void endExtTextInput( EndExtTextInputFlags nFlags
);
156 bool handleKeyEvent( GdkEventKey
* pEvent
);
157 void focusChanged( bool bFocusIn
);
159 void doCallEndExtTextInput();
160 void sendEmptyCommit();
162 static void signalIMCommit( GtkIMContext
*, gchar
*, gpointer
);
163 static gboolean
signalIMDeleteSurrounding( GtkIMContext
*, gint
, gint
, gpointer
);
164 static void signalIMPreeditChanged( GtkIMContext
*, gpointer
);
165 static void signalIMPreeditEnd( GtkIMContext
*, gpointer
);
166 static void signalIMPreeditStart( GtkIMContext
*, gpointer
);
167 static gboolean
signalIMRetrieveSurrounding( GtkIMContext
*, gpointer
);
169 friend struct IMHandler
;
171 SalX11Screen m_nXScreen
;
172 GtkWidget
* m_pWindow
;
173 #if GTK_CHECK_VERSION(3,0,0)
174 GtkGrid
* m_pTopLevelGrid
;
176 GtkEventBox
* m_pEventBox
;
177 GtkFixed
* m_pFixedContainer
;
178 GdkWindow
* m_pForeignParent
;
179 GdkNativeWindow m_aForeignParentWindow
;
180 GdkWindow
* m_pForeignTopLevel
;
181 GdkNativeWindow m_aForeignTopLevelWindow
;
182 SalFrameStyleFlags m_nStyle
;
183 GtkSalFrame
* m_pParent
;
184 std::list
< GtkSalFrame
* > m_aChildren
;
185 GdkWindowState m_nState
;
186 SystemEnvData m_aSystemData
;
187 GtkSalGraphics
*m_pGraphics
;
189 ModKeyFlags m_nKeyModifiers
;
190 GdkCursor
*m_pCurrentCursor
;
191 GdkVisibilityState m_nVisibility
;
192 PointerStyle m_ePointerStyle
;
193 ScreenSaverInhibitor m_ScreenSaverInhibitor
;
196 bool m_bSpanMonitorsWhenFullscreen
;
199 bool m_bWindowIsGtkPlug
;
203 IMHandler
* m_pIMHandler
;
207 tools::Rectangle m_aRestorePosSize
;
209 #if GTK_CHECK_VERSION(3,0,0)
211 tools::Rectangle m_aHelpArea
;
212 long m_nWidthRequest
;
213 long m_nHeightRequest
;
214 cairo_region_t
* m_pRegion
;
215 GtkDropTarget
* m_pDropTarget
;
216 GtkDragSource
* m_pDragSource
;
218 GtkDnDTransferable
* m_pFormatConversionRequest
;
220 GdkRegion
* m_pRegion
;
221 bool m_bSetFocusOnMap
;
226 #if ENABLE_DBUS && ENABLE_GIO
228 friend void ensure_dbus_setup(GdkWindow
* gdkWindow
, GtkSalFrame
* pSalFrame
);
229 friend void on_registrar_available (GDBusConnection
*, const gchar
*, const gchar
*, gpointer
);
230 friend void on_registrar_unavailable (GDBusConnection
*, const gchar
*, gpointer
);
234 void Init( SalFrame
* pParent
, SalFrameStyleFlags nStyle
);
235 void Init( SystemParentData
* pSysData
);
237 void InvalidateGraphics();
240 static gboolean
signalButton( GtkWidget
*, GdkEventButton
*, gpointer
);
241 #if GTK_CHECK_VERSION(3,0,0)
242 static void signalStyleUpdated(GtkWidget
*, gpointer
);
244 static void signalStyleSet(GtkWidget
*, GtkStyle
* pPrevious
, gpointer
);
246 #if GTK_CHECK_VERSION(3,0,0)
247 static gboolean
signalDraw( GtkWidget
*, cairo_t
*cr
, gpointer
);
248 static void signalRealize(GtkWidget
*, gpointer frame
);
249 static void sizeAllocated(GtkWidget
*, GdkRectangle
*pAllocation
, gpointer frame
);
250 static gboolean
signalTooltipQuery(GtkWidget
*, gint x
, gint y
,
251 gboolean keyboard_mode
, GtkTooltip
*tooltip
,
253 static gboolean
signalDragMotion(GtkWidget
*widget
, GdkDragContext
*context
, gint x
, gint y
,
254 guint time
, gpointer frame
);
255 static gboolean
signalDragDrop(GtkWidget
* widget
, GdkDragContext
*context
, gint x
, gint y
,
256 guint time
, gpointer frame
);
257 static void signalDragDropReceived(GtkWidget
*widget
, GdkDragContext
*context
, gint x
, gint y
,
258 GtkSelectionData
*data
, guint ttype
, guint time
, gpointer frame
);
259 static void signalDragLeave(GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer frame
);
261 static gboolean
signalDragFailed(GtkWidget
*widget
, GdkDragContext
*context
, GtkDragResult result
, gpointer frame
);
262 static void signalDragDelete(GtkWidget
*widget
, GdkDragContext
*context
, gpointer frame
);
263 static void signalDragEnd(GtkWidget
*widget
, GdkDragContext
*context
, gpointer frame
);
264 static void signalDragDataGet(GtkWidget
* widget
, GdkDragContext
* context
, GtkSelectionData
*data
, guint info
,
265 guint time
, gpointer frame
);
267 #if GTK_CHECK_VERSION(3,14,0)
268 static void gestureSwipe(GtkGestureSwipe
* gesture
, gdouble velocity_x
, gdouble velocity_y
, gpointer frame
);
269 static void gestureLongPress(GtkGestureLongPress
* gesture
, gpointer frame
);
272 static gboolean
signalExpose( GtkWidget
*, GdkEventExpose
*, gpointer
);
273 void askForXEmbedFocus( sal_Int32 nTimecode
);
274 void grabKeyboard(bool bGrab
);
276 static gboolean
signalFocus( GtkWidget
*, GdkEventFocus
*, gpointer
);
277 static gboolean
signalMap( GtkWidget
*, GdkEvent
*, gpointer
);
278 static gboolean
signalUnmap( GtkWidget
*, GdkEvent
*, gpointer
);
279 static gboolean
signalConfigure( GtkWidget
*, GdkEventConfigure
*, gpointer
);
280 static gboolean
signalMotion( GtkWidget
*, GdkEventMotion
*, gpointer
);
281 static gboolean
signalKey( GtkWidget
*, GdkEventKey
*, gpointer
);
282 static gboolean
signalDelete( GtkWidget
*, GdkEvent
*, gpointer
);
283 static gboolean
signalWindowState( GtkWidget
*, GdkEvent
*, gpointer
);
284 static gboolean
signalScroll( GtkWidget
*, GdkEvent
*, gpointer
);
285 static gboolean
signalCrossing( GtkWidget
*, GdkEventCrossing
*, gpointer
);
286 static gboolean
signalVisibility( GtkWidget
*, GdkEventVisibility
*, gpointer
);
287 static void signalDestroy( GtkWidget
*, gpointer
);
290 void SetDefaultSize();
292 bool doKeyCallback( guint state
,
294 guint16 hardware_keycode
,
297 sal_Unicode aOrigCode
,
302 static GdkNativeWindow
findTopLevelSystemWindow( GdkNativeWindow aWindow
);
304 static int m_nFloats
;
306 bool isFloatGrabWindow() const
309 (m_nStyle
& SalFrameStyleFlags::FLOAT
) && // only a float can be floatgrab
310 !(m_nStyle
& SalFrameStyleFlags::TOOLTIP
) && // tool tips are not
311 !(m_nStyle
& SalFrameStyleFlags::OWNERDRAWDECORATION
); // toolbars are also not
314 bool isChild( bool bPlug
= true, bool bSysChild
= true )
316 SalFrameStyleFlags nMask
= SalFrameStyleFlags::NONE
;
318 nMask
|= SalFrameStyleFlags::PLUG
;
320 nMask
|= SalFrameStyleFlags::SYSTEMCHILD
;
321 return bool(m_nStyle
& nMask
);
324 //call gtk_window_resize
325 void window_resize(long nWidth
, long nHeight
);
326 //call gtk_widget_set_size_request
327 void widget_set_size_request(long nWidth
, long nHeight
);
329 void resizeWindow( long nWidth
, long nHeight
);
330 void moveWindow( long nX
, long nY
);
332 Size
calcDefaultSize();
334 void setMinMaxSize();
335 void createNewWindow( ::Window aParent
, bool bXEmbed
, SalX11Screen nXScreen
);
337 void AllocateFrame();
338 void TriggerPaintEvent();
340 void updateWMClass();
342 enum class SetType
{ RetainSize
, Fullscreen
, UnFullscreen
};
344 void SetScreen( unsigned int nNewScreen
, SetType eType
, tools::Rectangle
*pSize
= nullptr );
347 #if GTK_CHECK_VERSION(3,0,0)
348 cairo_surface_t
* m_pSurface
;
349 basegfx::B2IVector m_aFrameSize
;
350 DamageHandler m_aDamageHandler
;
351 std::vector
<GdkEvent
*> m_aPendingScrollEvents
;
352 Idle m_aSmoothScrollIdle
;
354 bool m_bSalObjectSetPosSize
;
356 GtkSalFrame( SalFrame
* pParent
, SalFrameStyleFlags nStyle
);
357 GtkSalFrame( SystemParentData
* pSysData
);
359 guint m_nMenuExportId
;
360 guint m_nAppMenuExportId
;
361 guint m_nActionGroupExportId
;
362 guint m_nAppActionGroupExportId
;
363 guint m_nHudAwarenessId
;
364 std::vector
<gulong
> m_aMouseSignalIds
;
366 // dispatches an event, returns true if dispatched
367 // and false else; if true was returned the event should
369 bool Dispatch( const XEvent
* pEvent
);
370 void grabPointer(bool bGrab
, bool bOwnerEvents
= false);
372 static GtkSalDisplay
* getDisplay();
373 static GdkDisplay
* getGdkDisplay();
374 GtkWidget
* getWindow() const { return m_pWindow
; }
375 GtkFixed
* getFixedContainer() const { return m_pFixedContainer
; }
376 GtkEventBox
* getEventBox() const { return m_pEventBox
; }
377 GtkWidget
* getMouseEventWidget() const;
378 #if GTK_CHECK_VERSION(3,0,0)
379 GtkGrid
* getTopLevelGridWidget() const { return m_pTopLevelGrid
; }
381 GdkWindow
* getForeignParent() const { return m_pForeignParent
; }
382 GdkNativeWindow
getForeignParentWindow() const { return m_aForeignParentWindow
; }
383 GdkWindow
* getForeignTopLevel() const { return m_pForeignTopLevel
; }
384 GdkNativeWindow
getForeignTopLevelWindow() const { return m_aForeignTopLevelWindow
; }
385 const SalX11Screen
& getXScreenNumber() const { return m_nXScreen
; }
386 int GetDisplayScreen() const { return maGeometry
.nDisplayScreenNumber
; }
387 void updateScreenNumber();
389 #if GTK_CHECK_VERSION(3,0,0)
391 cairo_t
* getCairoContext() const;
392 void damaged(sal_Int32 nExtentsLeft
, sal_Int32 nExtentsTop
,
393 sal_Int32 nExtentsRight
, sal_Int32 nExtentsBottom
) const;
395 void registerDropTarget(GtkDropTarget
* pDropTarget
)
397 assert(!m_pDropTarget
);
398 m_pDropTarget
= pDropTarget
;
401 void deregisterDropTarget(GtkDropTarget
* pDropTarget
)
403 assert(m_pDropTarget
== pDropTarget
); (void)pDropTarget
;
404 m_pDropTarget
= nullptr;
407 void registerDragSource(GtkDragSource
* pDragSource
)
409 assert(!m_pDragSource
);
410 m_pDragSource
= pDragSource
;
413 void deregisterDragSource(GtkDragSource
* pDragSource
)
415 assert(m_pDragSource
== pDragSource
); (void)pDragSource
;
416 m_pDragSource
= nullptr;
419 void SetFormatConversionRequest(GtkDnDTransferable
*pRequest
)
421 m_pFormatConversionRequest
= pRequest
;
424 void startDrag(gint nButton
, gint nDragOriginX
, gint nDragOriginY
,
425 GdkDragAction sourceActions
, GtkTargetList
* pTargetList
);
430 void removeGrabLevel();
432 void nopaint_container_resize_children(GtkContainer
*);
434 void LaunchAsyncScroll(GdkEvent
* pEvent
);
435 DECL_LINK(AsyncScroll
, Timer
*, void);
438 virtual ~GtkSalFrame() override
;
440 // SalGraphics or NULL, but two Graphics for all SalFrames
442 virtual SalGraphics
* AcquireGraphics() override
;
443 virtual void ReleaseGraphics( SalGraphics
* pGraphics
) override
;
445 // Event must be destroyed, when Frame is destroyed
446 // When Event is called, SalInstance::Yield() must be returned
447 virtual bool PostEvent(ImplSVEvent
* pData
) override
;
449 virtual void SetTitle( const OUString
& rTitle
) override
;
450 virtual void SetIcon( sal_uInt16 nIcon
) override
;
451 virtual void SetMenu( SalMenu
*pSalMenu
) override
;
453 virtual void DrawMenuBar() override
;
454 void EnsureAppMenuWatch();
456 virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle
) override
;
457 // Before the window is visible, a resize event
458 // must be sent with the correct size
459 virtual void Show( bool bVisible
, bool bNoActivate
= false ) override
;
460 // Set ClientSize and Center the Window to the desktop
461 // and send/post a resize message
462 virtual void SetMinClientSize( long nWidth
, long nHeight
) override
;
463 virtual void SetMaxClientSize( long nWidth
, long nHeight
) override
;
464 virtual void SetPosSize( long nX
, long nY
, long nWidth
, long nHeight
, sal_uInt16 nFlags
) override
;
465 virtual void GetClientSize( long& rWidth
, long& rHeight
) override
;
466 virtual void GetWorkArea( tools::Rectangle
& rRect
) override
;
467 virtual SalFrame
* GetParent() const override
;
468 virtual void SetWindowState( const SalFrameState
* pState
) override
;
469 virtual bool GetWindowState( SalFrameState
* pState
) override
;
470 virtual void ShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
) override
;
471 // Enable/Disable ScreenSaver, SystemAgents, ...
472 virtual void StartPresentation( bool bStart
) override
;
473 // Show Window over all other Windows
474 virtual void SetAlwaysOnTop( bool bOnTop
) override
;
476 // Window to top and grab focus
477 virtual void ToTop( SalFrameToTop nFlags
) override
;
479 // this function can call with the same
481 virtual void SetPointer( PointerStyle ePointerStyle
) override
;
482 virtual void CaptureMouse( bool bMouse
) override
;
483 virtual void SetPointerPos( long nX
, long nY
) override
;
485 // flush output buffer
486 using SalFrame::Flush
;
487 virtual void Flush() override
;
488 // flush output buffer, wait till outstanding operations are done
490 virtual void SetInputContext( SalInputContext
* pContext
) override
;
491 virtual void EndExtTextInput( EndExtTextInputFlags nFlags
) override
;
493 virtual OUString
GetKeyName( sal_uInt16 nKeyCode
) override
;
494 virtual bool MapUnicodeToKeyCode( sal_Unicode aUnicode
, LanguageType aLangType
, vcl::KeyCode
& rKeyCode
) override
;
496 // returns the input language used for the last key stroke
497 // may be LANGUAGE_DONTKNOW if not supported by the OS
498 virtual LanguageType
GetInputLanguage() override
;
500 virtual void UpdateSettings( AllSettings
& rSettings
) override
;
502 virtual void Beep() override
;
504 // returns system data (most prominent: window handle)
505 virtual const SystemEnvData
* GetSystemData() const override
;
507 // get current modifier and button mask
508 virtual SalPointerState
GetPointerState() override
;
510 virtual KeyIndicatorState
GetIndicatorState() override
;
512 virtual void SimulateKeyPress( sal_uInt16 nKeyCode
) override
;
514 // set new parent window
515 virtual void SetParent( SalFrame
* pNewParent
) override
;
516 // reparent window to act as a plugin; implementation
517 // may choose to use a new system window internally
518 // return false to indicate failure
519 virtual bool SetPluginParent( SystemParentData
* pNewParent
) override
;
521 virtual void SetScreenNumber( unsigned int ) override
;
522 virtual void SetApplicationID( const OUString
&rWMClass
) override
;
524 // shaped system windows
525 // set clip region to none (-> rectangular windows, normal state)
526 virtual void ResetClipRegion() override
;
527 // start setting the clipregion consisting of nRects rectangles
528 virtual void BeginSetClipRegion( sal_uLong nRects
) override
;
529 // add a rectangle to the clip region
530 virtual void UnionClipRegion( long nX
, long nY
, long nWidth
, long nHeight
) override
;
531 // done setting up the clipregion
532 virtual void EndSetClipRegion() override
;
534 #if GTK_CHECK_VERSION(3,0,0)
535 virtual void SetModal(bool bModal
) override
;
536 virtual bool ShowTooltip(const OUString
& rHelpText
, const tools::Rectangle
& rHelpArea
) override
;
537 virtual sal_uIntPtr
ShowPopover(const OUString
& rHelpText
, const tools::Rectangle
& rHelpArea
, QuickHelpFlags nFlags
) override
;
538 virtual bool UpdatePopover(sal_uIntPtr nId
, const OUString
& rHelpText
, const tools::Rectangle
& rHelpArea
) override
;
539 virtual bool HidePopover(sal_uIntPtr nId
) override
;
542 static GtkSalFrame
*getFromWindow( GtkWindow
*pWindow
);
544 sal_uIntPtr
GetNativeWindowHandle(GtkWidget
*pWidget
);
545 virtual sal_uIntPtr
GetNativeWindowHandle() override
;
547 //Call the usual SalFrame Callback, but catch uno exceptions and delegate
548 //to GtkData to rethrow them after the gsignal is processed when its safe
549 //to do so again in our own code after the g_main_context_iteration call
550 //which triggers the gsignals.
551 long CallCallbackExc(SalEvent nEvent
, const void* pEvent
) const;
554 static void KeyCodeToGdkKey(const vcl::KeyCode
& rKeyCode
,
555 guint
* pGdkKeyCode
, GdkModifierType
*pGdkModifiers
);
557 static guint32
GetLastInputEventTime();
558 static void UpdateLastInputEventTime(guint32 nUserInputTime
);
561 #define OOO_TYPE_FIXED ooo_fixed_get_type()
565 GType
ooo_fixed_get_type();
566 AtkObject
* ooo_fixed_get_accessible(GtkWidget
*obj
);
570 #endif // INCLUDED_VCL_INC_UNX_GTK_GTKFRAME_HXX
572 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */