Line data Source code
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_GTKFRAME_HXX
21 : #define INCLUDED_VCL_INC_UNX_GTK_GTKFRAME_HXX
22 :
23 : #include <prex.h>
24 : #include <cairo.h>
25 : #include <gdk/gdk.h>
26 : #include <gdk/gdkx.h>
27 : #include <gtk/gtk.h>
28 : #if GTK_CHECK_VERSION(3,0,0)
29 : # include <gtk/gtkx.h>
30 : #endif
31 : #include <gdk/gdkkeysyms.h>
32 : #include <postx.h>
33 :
34 : #include <salframe.hxx>
35 : #include <vcl/sysdata.hxx>
36 : #include <unx/x11windowprovider.hxx>
37 : #include <unx/saltype.h>
38 :
39 : #include "tools/link.hxx"
40 :
41 : #include <basebmp/bitmapdevice.hxx>
42 : #include <basebmp/scanlineformats.hxx>
43 : #include <com/sun/star/awt/XTopWindow.hpp>
44 :
45 : #include <list>
46 : #include <vector>
47 :
48 : class GtkSalGraphics;
49 : class GtkSalDisplay;
50 :
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)
56 : #endif
57 :
58 : #if !(GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 26)
59 : typedef void GDBusConnection;
60 : #endif
61 :
62 : class GtkSalFrame : public SalFrame, public X11WindowProvider
63 : {
64 : static const int nMaxGraphics = 2;
65 :
66 : struct GraphicsHolder
67 : {
68 : GtkSalGraphics* pGraphics;
69 : bool bInUse;
70 32 : GraphicsHolder()
71 : : pGraphics( NULL ),
72 32 : bInUse( false )
73 32 : {}
74 : ~GraphicsHolder();
75 : };
76 :
77 : struct IMHandler
78 : {
79 :
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
88 : {
89 : GdkWindow *window;
90 : gint8 send_event;
91 : guint32 time;
92 : guint state;
93 : guint keyval;
94 : guint16 hardware_keycode;
95 : guint8 group;
96 :
97 0 : PreviousKeyPress (GdkEventKey *event)
98 : : window (NULL),
99 : send_event (0),
100 : time (0),
101 : state (0),
102 : keyval (0),
103 : hardware_keycode (0),
104 0 : group (0)
105 : {
106 0 : if (event)
107 : {
108 0 : window = event->window;
109 0 : send_event = event->send_event;
110 0 : time = event->time;
111 0 : state = event->state;
112 0 : keyval = event->keyval;
113 0 : hardware_keycode = event->hardware_keycode;
114 0 : group = event->group;
115 : }
116 0 : }
117 :
118 0 : PreviousKeyPress( const PreviousKeyPress& rPrev )
119 : : window( rPrev.window ),
120 : send_event( rPrev.send_event ),
121 : time( rPrev.time ),
122 : state( rPrev.state ),
123 : keyval( rPrev.keyval ),
124 : hardware_keycode( rPrev.hardware_keycode ),
125 0 : group( rPrev.group )
126 0 : {}
127 :
128 0 : bool operator== (GdkEventKey *event) const
129 : {
130 : return (event != NULL)
131 0 : && (event->window == window)
132 0 : && (event->send_event == send_event)
133 : // ignore non-Gdk state bits, e.g., these used by IBus
134 0 : && ((event->state & GDK_MODIFIER_MASK) == (state & GDK_MODIFIER_MASK))
135 0 : && (event->keyval == keyval)
136 0 : && (event->hardware_keycode == hardware_keycode)
137 0 : && (event->group == group)
138 0 : && (event->time - time < 300)
139 : ;
140 : }
141 : };
142 :
143 : GtkSalFrame* m_pFrame;
144 : std::list< PreviousKeyPress > m_aPrevKeyPresses;
145 : int m_nPrevKeyPresses; // avoid using size()
146 : GtkIMContext* m_pIMContext;
147 : bool m_bFocused;
148 : bool m_bPreeditJustChanged;
149 : SalExtTextInputEvent m_aInputEvent;
150 : std::vector< sal_uInt16 > m_aInputFlags;
151 :
152 : IMHandler( GtkSalFrame* );
153 : ~IMHandler();
154 :
155 : void createIMContext();
156 : void deleteIMContext();
157 : void updateIMSpotLocation();
158 : void endExtTextInput( EndExtTextInputFlags nFlags );
159 : bool handleKeyEvent( GdkEventKey* pEvent );
160 : void focusChanged( bool bFocusIn );
161 :
162 : void doCallEndExtTextInput();
163 : void sendEmptyCommit();
164 :
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 );
171 : };
172 : friend struct IMHandler;
173 :
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;
181 : sal_uLong m_nStyle;
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;
194 : guint m_nGSMCookie;
195 : int m_nWorkArea;
196 : bool m_bFullscreen;
197 : bool m_bSpanMonitorsWhenFullscreen;
198 : bool m_bDefaultPos;
199 : bool m_bDefaultSize;
200 : bool m_bSendModChangeOnRelease;
201 : bool m_bWindowIsGtkPlug;
202 : bool m_bSetFocusOnMap;
203 : OUString m_aTitle;
204 : OUString m_sWMClass;
205 :
206 : IMHandler* m_pIMHandler;
207 :
208 : Size m_aMaxSize;
209 : Size m_aMinSize;
210 : Rectangle m_aRestorePosSize;
211 :
212 : #if GTK_CHECK_VERSION(3,0,0)
213 : cairo_region_t* m_pRegion;
214 : #else
215 : GdkRegion* m_pRegion;
216 : #endif
217 :
218 : SalMenu* m_pSalMenu;
219 :
220 : #if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
221 : public:
222 : void EnsureDbusMenuSynced();
223 : private:
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);
228 : #endif
229 : guint m_nWatcherId;
230 :
231 : void Init( SalFrame* pParent, sal_uLong nStyle );
232 : void Init( SystemParentData* pSysData );
233 : void InitCommon();
234 :
235 : // signals
236 : static gboolean signalButton( GtkWidget*, GdkEventButton*, gpointer );
237 : static void signalStyleSet( GtkWidget*, GtkStyle* pPrevious, gpointer );
238 : #if GTK_CHECK_VERSION(3,0,0)
239 : static gboolean signalDraw( GtkWidget*, cairo_t *cr, gpointer );
240 : #if GTK_CHECK_VERSION(3,14,0)
241 : static void gestureSwipe(GtkGestureSwipe* gesture, gdouble velocity_x, gdouble velocity_y, gpointer frame);
242 : static void gestureLongPress(GtkGestureLongPress* gesture, gpointer frame);
243 : #endif
244 : #else
245 : static gboolean signalExpose( GtkWidget*, GdkEventExpose*, gpointer );
246 : #endif
247 : static gboolean signalFocus( GtkWidget*, GdkEventFocus*, gpointer );
248 : static gboolean signalMap( GtkWidget*, GdkEvent*, gpointer );
249 : static gboolean signalUnmap( GtkWidget*, GdkEvent*, gpointer );
250 : static gboolean signalConfigure( GtkWidget*, GdkEventConfigure*, gpointer );
251 : static gboolean signalMotion( GtkWidget*, GdkEventMotion*, gpointer );
252 : static gboolean signalKey( GtkWidget*, GdkEventKey*, gpointer );
253 : static gboolean signalDelete( GtkWidget*, GdkEvent*, gpointer );
254 : static gboolean signalState( GtkWidget*, GdkEvent*, gpointer );
255 : static gboolean signalScroll( GtkWidget*, GdkEvent*, gpointer );
256 : static gboolean signalCrossing( GtkWidget*, GdkEventCrossing*, gpointer );
257 : static gboolean signalVisibility( GtkWidget*, GdkEventVisibility*, gpointer );
258 : static void signalDestroy( GtkWidget*, gpointer );
259 :
260 : void Center();
261 : void SetDefaultSize();
262 : void setAutoLock( bool bLock );
263 : void setScreenSaverTimeout( int nTimeout );
264 :
265 : void doKeyCallback( guint state,
266 : guint keyval,
267 : guint16 hardware_keycode,
268 : guint8 group,
269 : guint32 time,
270 : sal_Unicode aOrigCode,
271 : bool bDown,
272 : bool bSendRelease
273 : );
274 :
275 : static GdkNativeWindow findTopLevelSystemWindow( GdkNativeWindow aWindow );
276 :
277 : static int m_nFloats;
278 :
279 1 : bool isFloatGrabWindow() const
280 : {
281 : return
282 1 : (m_nStyle & SAL_FRAME_STYLE_FLOAT) && // only a float can be floatgrab
283 0 : !(m_nStyle & SAL_FRAME_STYLE_TOOLTIP) && // tool tips are not
284 1 : !(m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) && // toolbars are also not
285 1 : !(m_nStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE); // focusable floats are not
286 : }
287 :
288 161 : bool isChild( bool bPlug = true, bool bSysChild = true )
289 : {
290 161 : sal_uLong nMask = 0;
291 161 : if( bPlug )
292 140 : nMask |= SAL_FRAME_STYLE_PLUG;
293 161 : if( bSysChild )
294 141 : nMask |= SAL_FRAME_STYLE_SYSTEMCHILD;
295 161 : return (m_nStyle & nMask) != 0;
296 : }
297 :
298 : void resizeWindow( long nWidth, long nHeight );
299 : void moveWindow( long nX, long nY );
300 :
301 : Size calcDefaultSize();
302 :
303 : void setMinMaxSize();
304 : void createNewWindow( ::Window aParent, bool bXEmbed, SalX11Screen nXScreen );
305 : void askForXEmbedFocus( sal_Int32 nTimecode );
306 :
307 : void AllocateFrame();
308 : void TriggerPaintEvent();
309 :
310 : void updateWMClass();
311 : void SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSize = NULL );
312 :
313 : DECL_LINK( ImplDelayedFullScreenHdl, void* );
314 : public:
315 : #if GTK_CHECK_VERSION(3,0,0)
316 : basebmp::BitmapDeviceSharedPtr m_aFrame;
317 : #endif
318 : GtkSalFrame( SalFrame* pParent, sal_uLong nStyle );
319 : GtkSalFrame( SystemParentData* pSysData );
320 :
321 : guint m_nMenuExportId;
322 : guint m_nAppMenuExportId;
323 : guint m_nActionGroupExportId;
324 : guint m_nAppActionGroupExportId;
325 : guint m_nHudAwarenessId;
326 :
327 : // dispatches an event, returns true if dispatched
328 : // and false else; if true was returned the event should
329 : // be swallowed
330 : bool Dispatch( const XEvent* pEvent );
331 : void grabPointer(bool bGrab, bool bOwnerEvents = false);
332 : void grabKeyboard(bool bGrab);
333 :
334 : static GtkSalDisplay* getDisplay();
335 : static GdkDisplay* getGdkDisplay();
336 34 : GtkWidget* getWindow() const { return m_pWindow; }
337 0 : GtkFixed* getFixedContainer() const { return m_pFixedContainer; }
338 0 : GdkWindow* getForeignParent() const { return m_pForeignParent; }
339 0 : GdkNativeWindow getForeignParentWindow() const { return m_aForeignParentWindow; }
340 0 : GdkWindow* getForeignTopLevel() const { return m_pForeignTopLevel; }
341 0 : GdkNativeWindow getForeignTopLevelWindow() const { return m_aForeignTopLevelWindow; }
342 : GdkVisibilityState getVisibilityState() const
343 : { return m_nVisibility; }
344 0 : Pixmap getBackgroundPixmap() const { return m_hBackgroundPixmap; }
345 0 : SalX11Screen getXScreenNumber() const { return m_nXScreen; }
346 16 : int GetDisplayScreen() const { return maGeometry.nDisplayScreenNumber; }
347 : void updateScreenNumber();
348 :
349 : #if GTK_CHECK_VERSION(3,0,0)
350 : // only for gtk3 ...
351 : cairo_t* getCairoContext() const;
352 : void damaged (const basegfx::B2IBox& rDamageRect);
353 : #endif
354 : virtual ~GtkSalFrame();
355 :
356 : // SalGraphics or NULL, but two Graphics for all SalFrames
357 : // must be returned
358 : virtual SalGraphics* AcquireGraphics() SAL_OVERRIDE;
359 : virtual void ReleaseGraphics( SalGraphics* pGraphics ) SAL_OVERRIDE;
360 :
361 : // Event must be destroyed, when Frame is destroyed
362 : // When Event is called, SalInstance::Yield() must be returned
363 : virtual bool PostEvent( void* pData ) SAL_OVERRIDE;
364 :
365 : virtual void SetTitle( const OUString& rTitle ) SAL_OVERRIDE;
366 : virtual void SetIcon( sal_uInt16 nIcon ) SAL_OVERRIDE;
367 : virtual void SetMenu( SalMenu *pSalMenu ) SAL_OVERRIDE;
368 : SalMenu* GetMenu();
369 : virtual void DrawMenuBar() SAL_OVERRIDE;
370 : void EnsureAppMenuWatch();
371 :
372 : virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle ) SAL_OVERRIDE;
373 : // Before the window is visible, a resize event
374 : // must be sent with the correct size
375 : virtual void Show( bool bVisible, bool bNoActivate = false ) SAL_OVERRIDE;
376 : // Set ClientSize and Center the Window to the desktop
377 : // and send/post a resize message
378 : virtual void SetMinClientSize( long nWidth, long nHeight ) SAL_OVERRIDE;
379 : virtual void SetMaxClientSize( long nWidth, long nHeight ) SAL_OVERRIDE;
380 : virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) SAL_OVERRIDE;
381 : virtual void GetClientSize( long& rWidth, long& rHeight ) SAL_OVERRIDE;
382 : virtual void GetWorkArea( Rectangle& rRect ) SAL_OVERRIDE;
383 : virtual SalFrame* GetParent() const SAL_OVERRIDE;
384 : virtual void SetWindowState( const SalFrameState* pState ) SAL_OVERRIDE;
385 : virtual bool GetWindowState( SalFrameState* pState ) SAL_OVERRIDE;
386 : virtual void ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay ) SAL_OVERRIDE;
387 : // Enable/Disable ScreenSaver, SystemAgents, ...
388 : virtual void StartPresentation( bool bStart ) SAL_OVERRIDE;
389 : // Show Window over all other Windows
390 : virtual void SetAlwaysOnTop( bool bOnTop ) SAL_OVERRIDE;
391 :
392 : // Window to top and grab focus
393 : virtual void ToTop( sal_uInt16 nFlags ) SAL_OVERRIDE;
394 :
395 : // this function can call with the same
396 : // pointer style
397 : virtual void SetPointer( PointerStyle ePointerStyle ) SAL_OVERRIDE;
398 : virtual void CaptureMouse( bool bMouse ) SAL_OVERRIDE;
399 : virtual void SetPointerPos( long nX, long nY ) SAL_OVERRIDE;
400 :
401 : // flush output buffer
402 : using SalFrame::Flush;
403 : virtual void Flush() SAL_OVERRIDE;
404 : // flush output buffer, wait till outstanding operations are done
405 : virtual void Sync() SAL_OVERRIDE;
406 :
407 : virtual void SetInputContext( SalInputContext* pContext ) SAL_OVERRIDE;
408 : virtual void EndExtTextInput( EndExtTextInputFlags nFlags ) SAL_OVERRIDE;
409 :
410 : virtual OUString GetKeyName( sal_uInt16 nKeyCode ) SAL_OVERRIDE;
411 : virtual bool MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, vcl::KeyCode& rKeyCode ) SAL_OVERRIDE;
412 :
413 : // returns the input language used for the last key stroke
414 : // may be LANGUAGE_DONTKNOW if not supported by the OS
415 : virtual LanguageType GetInputLanguage() SAL_OVERRIDE;
416 :
417 : virtual void UpdateSettings( AllSettings& rSettings ) SAL_OVERRIDE;
418 :
419 : virtual void Beep() SAL_OVERRIDE;
420 :
421 : // returns system data (most prominent: window handle)
422 : virtual const SystemEnvData* GetSystemData() const SAL_OVERRIDE;
423 :
424 : // get current modifier and button mask
425 : virtual SalPointerState GetPointerState() SAL_OVERRIDE;
426 :
427 : virtual KeyIndicatorState GetIndicatorState() SAL_OVERRIDE;
428 :
429 : virtual void SimulateKeyPress( sal_uInt16 nKeyCode ) SAL_OVERRIDE;
430 :
431 : // set new parent window
432 : virtual void SetParent( SalFrame* pNewParent ) SAL_OVERRIDE;
433 : // reparent window to act as a plugin; implementation
434 : // may choose to use a new system window internally
435 : // return false to indicate failure
436 : virtual bool SetPluginParent( SystemParentData* pNewParent ) SAL_OVERRIDE;
437 :
438 : virtual void SetScreenNumber( unsigned int ) SAL_OVERRIDE;
439 : virtual void SetApplicationID( const OUString &rWMClass ) SAL_OVERRIDE;
440 :
441 : // shaped system windows
442 : // set clip region to none (-> rectangular windows, normal state)
443 : virtual void ResetClipRegion() SAL_OVERRIDE;
444 : // start setting the clipregion consisting of nRects rectangles
445 : virtual void BeginSetClipRegion( sal_uLong nRects ) SAL_OVERRIDE;
446 : // add a rectangle to the clip region
447 : virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE;
448 : // done setting up the clipregion
449 : virtual void EndSetClipRegion() SAL_OVERRIDE;
450 :
451 : static GtkSalFrame *getFromWindow( GtkWindow *pWindow );
452 :
453 : virtual Window GetX11Window() SAL_OVERRIDE;
454 : };
455 :
456 : #define OOO_TYPE_FIXED ooo_fixed_get_type()
457 :
458 : extern "C" {
459 :
460 : GType ooo_fixed_get_type();
461 :
462 : } // extern "C"
463 :
464 : #endif // INCLUDED_VCL_INC_UNX_GTK_GTKFRAME_HXX
465 :
466 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|