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
28 #if GTK_CHECK_VERSION(3,0,0)
29 # include <gtk/gtkx.h>
31 #include <gdk/gdkkeysyms.h>
34 #include <salframe.hxx>
35 #include <vcl/sysdata.hxx>
36 #include <unx/x11windowprovider.hxx>
37 #include <unx/saltype.h>
39 #include "tools/link.hxx"
41 #include <basebmp/bitmapdevice.hxx>
42 #include <basebmp/scanlineformats.hxx>
43 #include <com/sun/star/awt/XTopWindow.hpp>
51 #if GTK_CHECK_VERSION(3,0,0)
52 typedef ::Window GdkNativeWindow
;
53 #define GDK_WINDOW_XWINDOW(o) GDK_WINDOW_XID(o)
54 #define gdk_set_sm_client_id(i) gdk_x11_set_sm_client_id(i)
55 #define gdk_window_foreign_new_for_display(a,b) gdk_x11_window_foreign_new_for_display(a,b)
58 #if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 26)
59 typedef void GDBusConnection
;
62 class GtkSalFrame
: public SalFrame
, public X11WindowProvider
64 static const int nMaxGraphics
= 2;
68 GtkSalGraphics
* pGraphics
;
80 // Not all GTK Input Methods swallow key release
81 // events. Since they swallow the key press events and we
82 // are left with the key release events, we need to
83 // manually swallow those. To do this, we keep a list of
84 // the previous 10 key press events in each GtkSalFrame
85 // and when we get a key release that matches one of the
86 // key press events in our list, we swallow it.
87 struct PreviousKeyPress
94 guint16 hardware_keycode
;
97 PreviousKeyPress (GdkEventKey
*event
)
103 hardware_keycode (0),
108 window
= event
->window
;
109 send_event
= event
->send_event
;
111 state
= event
->state
;
112 keyval
= event
->keyval
;
113 hardware_keycode
= event
->hardware_keycode
;
114 group
= event
->group
;
118 PreviousKeyPress( const PreviousKeyPress
& rPrev
)
119 : window( rPrev
.window
),
120 send_event( rPrev
.send_event
),
122 state( rPrev
.state
),
123 keyval( rPrev
.keyval
),
124 hardware_keycode( rPrev
.hardware_keycode
),
128 bool operator== (GdkEventKey
*event
) const
130 return (event
!= NULL
)
131 && (event
->window
== window
)
132 && (event
->send_event
== send_event
)
133 // ignore non-Gdk state bits, e.g., these used by IBus
134 && ((event
->state
& GDK_MODIFIER_MASK
) == (state
& GDK_MODIFIER_MASK
))
135 && (event
->keyval
== keyval
)
136 && (event
->hardware_keycode
== hardware_keycode
)
137 && (event
->group
== group
)
138 && (event
->time
- time
< 300)
143 GtkSalFrame
* m_pFrame
;
144 std::list
< PreviousKeyPress
> m_aPrevKeyPresses
;
145 int m_nPrevKeyPresses
; // avoid using size()
146 GtkIMContext
* m_pIMContext
;
148 bool m_bPreeditJustChanged
;
149 SalExtTextInputEvent m_aInputEvent
;
150 std::vector
< sal_uInt16
> m_aInputFlags
;
152 IMHandler( GtkSalFrame
* );
155 void createIMContext();
156 void deleteIMContext();
157 void updateIMSpotLocation();
158 void endExtTextInput( sal_uInt16 nFlags
);
159 bool handleKeyEvent( GdkEventKey
* pEvent
);
160 void focusChanged( bool bFocusIn
);
162 void doCallEndExtTextInput();
163 void sendEmptyCommit();
165 static void signalIMCommit( GtkIMContext
*, gchar
*, gpointer
);
166 static gboolean
signalIMDeleteSurrounding( GtkIMContext
*, gint
, gint
, gpointer
);
167 static void signalIMPreeditChanged( GtkIMContext
*, gpointer
);
168 static void signalIMPreeditEnd( GtkIMContext
*, gpointer
);
169 static void signalIMPreeditStart( GtkIMContext
*, gpointer
);
170 static gboolean
signalIMRetrieveSurrounding( GtkIMContext
*, gpointer
);
172 friend struct IMHandler
;
174 SalX11Screen m_nXScreen
;
175 GtkWidget
* m_pWindow
;
176 GdkWindow
* m_pForeignParent
;
177 GdkNativeWindow m_aForeignParentWindow
;
178 GdkWindow
* m_pForeignTopLevel
;
179 GdkNativeWindow m_aForeignTopLevelWindow
;
180 Pixmap m_hBackgroundPixmap
;
182 SalExtStyle m_nExtStyle
;
183 GtkFixed
* m_pFixedContainer
;
184 GtkSalFrame
* m_pParent
;
185 std::list
< GtkSalFrame
* > m_aChildren
;
186 GdkWindowState m_nState
;
187 SystemEnvData m_aSystemData
;
188 GraphicsHolder m_aGraphics
[ nMaxGraphics
];
189 sal_uInt16 m_nKeyModifiers
;
190 GdkCursor
*m_pCurrentCursor
;
191 GdkVisibilityState m_nVisibility
;
192 PointerStyle m_ePointerStyle
;
193 int m_nSavedScreenSaverTimeout
;
197 bool m_bSpanMonitorsWhenFullscreen
;
200 bool m_bSendModChangeOnRelease
;
201 bool m_bWindowIsGtkPlug
;
202 bool m_bSetFocusOnMap
;
206 IMHandler
* m_pIMHandler
;
210 Rectangle m_aRestorePosSize
;
212 #if GTK_CHECK_VERSION(3,0,0)
213 cairo_region_t
* m_pRegion
;
215 GdkRegion
* m_pRegion
;
220 #if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
222 void EnsureDbusMenuSynced();
224 SalMenu
* m_pLastSyncedDbusMenu
;
225 friend void ensure_dbus_setup(GdkWindow
* gdkWindow
, GtkSalFrame
* pSalFrame
);
226 friend void on_registrar_available (GDBusConnection
*, const gchar
*, const gchar
*, gpointer
);
227 friend void on_registrar_unavailable (GDBusConnection
*, const gchar
*, gpointer
);
231 void Init( SalFrame
* pParent
, sal_uLong nStyle
);
232 void Init( SystemParentData
* pSysData
);
234 void InvalidateGraphics();
237 static gboolean
signalButton( GtkWidget
*, GdkEventButton
*, gpointer
);
238 static void signalStyleSet( GtkWidget
*, GtkStyle
* pPrevious
, gpointer
);
239 #if GTK_CHECK_VERSION(3,0,0)
240 static gboolean
signalDraw( GtkWidget
*, cairo_t
*cr
, gpointer
);
241 static void signalFlagsChanged( GtkWidget
*, GtkStateFlags
, gpointer
);
242 static void sizeAllocated(GtkWidget
*, GdkRectangle
*pAllocation
, gpointer frame
);
243 #if GTK_CHECK_VERSION(3,14,0)
244 static void gestureSwipe(GtkGestureSwipe
* gesture
, gdouble velocity_x
, gdouble velocity_y
, gpointer frame
);
245 static void gestureLongPress(GtkGestureLongPress
* gesture
, gpointer frame
);
248 static gboolean
signalExpose( GtkWidget
*, GdkEventExpose
*, gpointer
);
250 static gboolean
signalFocus( GtkWidget
*, GdkEventFocus
*, gpointer
);
251 static gboolean
signalMap( GtkWidget
*, GdkEvent
*, gpointer
);
252 static gboolean
signalUnmap( GtkWidget
*, GdkEvent
*, gpointer
);
253 static gboolean
signalConfigure( GtkWidget
*, GdkEventConfigure
*, gpointer
);
254 static gboolean
signalMotion( GtkWidget
*, GdkEventMotion
*, gpointer
);
255 static gboolean
signalKey( GtkWidget
*, GdkEventKey
*, gpointer
);
256 static gboolean
signalDelete( GtkWidget
*, GdkEvent
*, gpointer
);
257 static gboolean
signalWindowState( GtkWidget
*, GdkEvent
*, gpointer
);
258 static gboolean
signalScroll( GtkWidget
*, GdkEvent
*, gpointer
);
259 static gboolean
signalCrossing( GtkWidget
*, GdkEventCrossing
*, gpointer
);
260 static gboolean
signalVisibility( GtkWidget
*, GdkEventVisibility
*, gpointer
);
261 static void signalDestroy( GtkWidget
*, gpointer
);
264 void SetDefaultSize();
265 void setAutoLock( bool bLock
);
266 void setScreenSaverTimeout( int nTimeout
);
268 void doKeyCallback( guint state
,
270 guint16 hardware_keycode
,
273 sal_Unicode aOrigCode
,
278 static GdkNativeWindow
findTopLevelSystemWindow( GdkNativeWindow aWindow
);
280 static int m_nFloats
;
282 bool isFloatGrabWindow() const
285 (m_nStyle
& SAL_FRAME_STYLE_FLOAT
) && // only a float can be floatgrab
286 !(m_nStyle
& SAL_FRAME_STYLE_TOOLTIP
) && // tool tips are not
287 !(m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) && // toolbars are also not
288 !(m_nStyle
& SAL_FRAME_STYLE_FLOAT_FOCUSABLE
); // focusable floats are not
291 bool isChild( bool bPlug
= true, bool bSysChild
= true )
295 nMask
|= SAL_FRAME_STYLE_PLUG
;
297 nMask
|= SAL_FRAME_STYLE_SYSTEMCHILD
;
298 return (m_nStyle
& nMask
) != 0;
301 //call gtk_window_resize if the current size differs and
302 //block Paints until Configure is received and the size
304 void window_resize(long nWidth
, long nHeight
);
305 //call gtk_widget_set_size_request if the current size request differs and
306 //block Paints until Configure is received and the size
308 void widget_set_size_request(long nWidth
, long nHeight
);
310 void resizeWindow( long nWidth
, long nHeight
);
311 void moveWindow( long nX
, long nY
);
313 Size
calcDefaultSize();
315 void setMinMaxSize();
316 void createNewWindow( ::Window aParent
, bool bXEmbed
, SalX11Screen nXScreen
);
317 void askForXEmbedFocus( sal_Int32 nTimecode
);
319 void AllocateFrame();
320 void TriggerPaintEvent();
322 void updateWMClass();
323 void SetScreen( unsigned int nNewScreen
, int eType
, Rectangle
*pSize
= NULL
);
325 DECL_LINK( ImplDelayedFullScreenHdl
, void* );
327 #if GTK_CHECK_VERSION(3,0,0)
328 basebmp::BitmapDeviceSharedPtr m_aFrame
;
330 GtkSalFrame( SalFrame
* pParent
, sal_uLong nStyle
);
331 GtkSalFrame( SystemParentData
* pSysData
);
333 guint m_nMenuExportId
;
334 guint m_nAppMenuExportId
;
335 guint m_nActionGroupExportId
;
336 guint m_nAppActionGroupExportId
;
337 guint m_nHudAwarenessId
;
339 // dispatches an event, returns true if dispatched
340 // and false else; if true was returned the event should
342 bool Dispatch( const XEvent
* pEvent
);
343 void grabPointer(bool bGrab
, bool bOwnerEvents
= false);
344 void grabKeyboard(bool bGrab
);
346 static GtkSalDisplay
* getDisplay();
347 static GdkDisplay
* getGdkDisplay();
348 GtkWidget
* getWindow() const { return m_pWindow
; }
349 GtkFixed
* getFixedContainer() const { return m_pFixedContainer
; }
350 GdkWindow
* getForeignParent() const { return m_pForeignParent
; }
351 GdkNativeWindow
getForeignParentWindow() const { return m_aForeignParentWindow
; }
352 GdkWindow
* getForeignTopLevel() const { return m_pForeignTopLevel
; }
353 GdkNativeWindow
getForeignTopLevelWindow() const { return m_aForeignTopLevelWindow
; }
354 GdkVisibilityState
getVisibilityState() const
355 { return m_nVisibility
; }
356 Pixmap
getBackgroundPixmap() const { return m_hBackgroundPixmap
; }
357 SalX11Screen
getXScreenNumber() const { return m_nXScreen
; }
358 int GetDisplayScreen() const { return maGeometry
.nDisplayScreenNumber
; }
359 void updateScreenNumber();
361 #if GTK_CHECK_VERSION(3,0,0)
363 cairo_t
* getCairoContext() const;
364 void damaged (const basegfx::B2IBox
& rDamageRect
);
366 virtual ~GtkSalFrame();
368 // SalGraphics or NULL, but two Graphics for all SalFrames
370 virtual SalGraphics
* AcquireGraphics() SAL_OVERRIDE
;
371 virtual void ReleaseGraphics( SalGraphics
* pGraphics
) SAL_OVERRIDE
;
373 // Event must be destroyed, when Frame is destroyed
374 // When Event is called, SalInstance::Yield() must be returned
375 virtual bool PostEvent( void* pData
) SAL_OVERRIDE
;
377 virtual void SetTitle( const OUString
& rTitle
) SAL_OVERRIDE
;
378 virtual void SetIcon( sal_uInt16 nIcon
) SAL_OVERRIDE
;
379 virtual void SetMenu( SalMenu
*pSalMenu
) SAL_OVERRIDE
;
381 virtual void DrawMenuBar() SAL_OVERRIDE
;
382 void EnsureAppMenuWatch();
384 virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle
) SAL_OVERRIDE
;
385 // Before the window is visible, a resize event
386 // must be sent with the correct size
387 virtual void Show( bool bVisible
, bool bNoActivate
= false ) SAL_OVERRIDE
;
388 // Set ClientSize and Center the Window to the desktop
389 // and send/post a resize message
390 virtual void SetMinClientSize( long nWidth
, long nHeight
) SAL_OVERRIDE
;
391 virtual void SetMaxClientSize( long nWidth
, long nHeight
) SAL_OVERRIDE
;
392 virtual void SetPosSize( long nX
, long nY
, long nWidth
, long nHeight
, sal_uInt16 nFlags
) SAL_OVERRIDE
;
393 virtual void GetClientSize( long& rWidth
, long& rHeight
) SAL_OVERRIDE
;
394 virtual void GetWorkArea( Rectangle
& rRect
) SAL_OVERRIDE
;
395 virtual SalFrame
* GetParent() const SAL_OVERRIDE
;
396 virtual void SetWindowState( const SalFrameState
* pState
) SAL_OVERRIDE
;
397 virtual bool GetWindowState( SalFrameState
* pState
) SAL_OVERRIDE
;
398 virtual void ShowFullScreen( bool bFullScreen
, sal_Int32 nDisplay
) SAL_OVERRIDE
;
399 // Enable/Disable ScreenSaver, SystemAgents, ...
400 virtual void StartPresentation( bool bStart
) SAL_OVERRIDE
;
401 // Show Window over all other Windows
402 virtual void SetAlwaysOnTop( bool bOnTop
) SAL_OVERRIDE
;
404 // Window to top and grab focus
405 virtual void ToTop( sal_uInt16 nFlags
) SAL_OVERRIDE
;
407 // this function can call with the same
409 virtual void SetPointer( PointerStyle ePointerStyle
) SAL_OVERRIDE
;
410 virtual void CaptureMouse( bool bMouse
) SAL_OVERRIDE
;
411 virtual void SetPointerPos( long nX
, long nY
) SAL_OVERRIDE
;
413 // flush output buffer
414 using SalFrame::Flush
;
415 virtual void Flush() SAL_OVERRIDE
;
416 // flush output buffer, wait till outstanding operations are done
417 virtual void Sync() SAL_OVERRIDE
;
419 virtual void SetInputContext( SalInputContext
* pContext
) SAL_OVERRIDE
;
420 virtual void EndExtTextInput( sal_uInt16 nFlags
) SAL_OVERRIDE
;
422 virtual OUString
GetKeyName( sal_uInt16 nKeyCode
) SAL_OVERRIDE
;
423 virtual bool MapUnicodeToKeyCode( sal_Unicode aUnicode
, LanguageType aLangType
, vcl::KeyCode
& rKeyCode
) SAL_OVERRIDE
;
425 // returns the input language used for the last key stroke
426 // may be LANGUAGE_DONTKNOW if not supported by the OS
427 virtual LanguageType
GetInputLanguage() SAL_OVERRIDE
;
429 virtual void UpdateSettings( AllSettings
& rSettings
) SAL_OVERRIDE
;
431 virtual void Beep() SAL_OVERRIDE
;
433 // returns system data (most prominent: window handle)
434 virtual const SystemEnvData
* GetSystemData() const SAL_OVERRIDE
;
436 // get current modifier and button mask
437 virtual SalPointerState
GetPointerState() SAL_OVERRIDE
;
439 virtual KeyIndicatorState
GetIndicatorState() SAL_OVERRIDE
;
441 virtual void SimulateKeyPress( sal_uInt16 nKeyCode
) SAL_OVERRIDE
;
443 // set new parent window
444 virtual void SetParent( SalFrame
* pNewParent
) SAL_OVERRIDE
;
445 // reparent window to act as a plugin; implementation
446 // may choose to use a new system window internally
447 // return false to indicate failure
448 virtual bool SetPluginParent( SystemParentData
* pNewParent
) SAL_OVERRIDE
;
450 virtual void SetScreenNumber( unsigned int ) SAL_OVERRIDE
;
451 virtual void SetApplicationID( const OUString
&rWMClass
) SAL_OVERRIDE
;
453 // shaped system windows
454 // set clip region to none (-> rectangular windows, normal state)
455 virtual void ResetClipRegion() SAL_OVERRIDE
;
456 // start setting the clipregion consisting of nRects rectangles
457 virtual void BeginSetClipRegion( sal_uLong nRects
) SAL_OVERRIDE
;
458 // add a rectangle to the clip region
459 virtual void UnionClipRegion( long nX
, long nY
, long nWidth
, long nHeight
) SAL_OVERRIDE
;
460 // done setting up the clipregion
461 virtual void EndSetClipRegion() SAL_OVERRIDE
;
463 static GtkSalFrame
*getFromWindow( GtkWindow
*pWindow
);
465 virtual Window
GetX11Window() SAL_OVERRIDE
;
467 static void KeyCodeToGdkKey(const vcl::KeyCode
& rKeyCode
,
468 guint
* pGdkKeyCode
, GdkModifierType
*pGdkModifiers
);
471 #define OOO_TYPE_FIXED ooo_fixed_get_type()
475 GType
ooo_fixed_get_type();
476 AtkObject
* ooo_fixed_get_accessible(GtkWidget
*obj
);
480 #endif // INCLUDED_VCL_INC_UNX_GTK_GTKFRAME_HXX
482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */