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