1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gtkframe.cxx,v $
10 * $Revision: 1.84.36.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <plugins/gtk/gtkframe.hxx>
35 #include <plugins/gtk/gtkdata.hxx>
36 #include <plugins/gtk/gtkinst.hxx>
37 #include <plugins/gtk/gtkgdi.hxx>
38 #include <vcl/keycodes.hxx>
39 #include <wmadaptor.hxx>
43 #include <vcl/floatwin.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/window.hxx>
48 #include <tools/prex.h>
49 #include <X11/Xatom.h>
50 #include <tools/postx.h>
53 #include <vcl/salbtype.hxx>
54 #include <vcl/bitmapex.hxx>
55 #include <vcl/impbmp.hxx>
56 #include <vcl/svids.hrc>
60 #if OSL_DEBUG_LEVEL > 1
64 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
65 #include <com/sun/star/accessibility/AccessibleRole.hpp>
66 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
67 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
68 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
71 #include <dbus/dbus-glib.h>
73 #define GSS_DBUS_SERVICE "org.gnome.ScreenSaver"
74 #define GSS_DBUS_PATH "/org/gnome/ScreenSaver"
75 #define GSS_DBUS_INTERFACE "org.gnome.ScreenSaver"
78 // make compile on gtk older than 2.10
79 #if GTK_MINOR_VERSION < 10
80 #define GDK_SUPER_MASK (1 << 26)
81 #define GDK_HYPER_MASK (1 << 27)
82 #define GDK_META_MASK (1 << 28)
85 using namespace com::sun::star
;
87 int GtkSalFrame::m_nFloats
= 0;
89 static USHORT
GetKeyModCode( guint state
)
92 if( (state
& GDK_SHIFT_MASK
) )
94 if( (state
& GDK_CONTROL_MASK
) )
96 if( (state
& GDK_MOD1_MASK
) )
99 // Map Meta/Super keys to MOD3 modifier on all Unix systems
101 if ( (state
& GDK_META_MASK
) || ( state
& GDK_SUPER_MASK
) )
106 static USHORT
GetMouseModCode( guint state
)
108 USHORT nCode
= GetKeyModCode( state
);
109 if( (state
& GDK_BUTTON1_MASK
) )
111 if( (state
& GDK_BUTTON2_MASK
) )
112 nCode
|= MOUSE_MIDDLE
;
113 if( (state
& GDK_BUTTON3_MASK
) )
114 nCode
|= MOUSE_RIGHT
;
119 static USHORT
GetKeyCode( guint keyval
)
122 if( keyval
>= GDK_0
&& keyval
<= GDK_9
)
123 nCode
= KEY_0
+ (keyval
-GDK_0
);
124 else if( keyval
>= GDK_KP_0
&& keyval
<= GDK_KP_9
)
125 nCode
= KEY_0
+ (keyval
-GDK_KP_0
);
126 else if( keyval
>= GDK_A
&& keyval
<= GDK_Z
)
127 nCode
= KEY_A
+ (keyval
-GDK_A
);
128 else if( keyval
>= GDK_a
&& keyval
<= GDK_z
)
129 nCode
= KEY_A
+ (keyval
-GDK_a
);
130 else if( keyval
>= GDK_F1
&& keyval
<= GDK_F26
)
132 if( GetX11SalData()->GetDisplay()->IsNumLockFromXS() )
134 nCode
= KEY_F1
+ (keyval
-GDK_F1
);
140 // - - - - - Sun keyboard, see vcl/unx/source/app/saldisp.cxx
142 if( GetX11SalData()->GetDisplay()->GetServerVendor() == vendor_sun
)
147 case GDK_L3
: nCode
= KEY_PROPERTIES
; break;
148 case GDK_L4
: nCode
= KEY_UNDO
; break;
149 case GDK_L6
: nCode
= KEY_COPY
; break; // KEY_F16
150 case GDK_L8
: nCode
= KEY_PASTE
; break; // KEY_F18
151 case GDK_L10
: nCode
= KEY_CUT
; break; // KEY_F20
153 nCode
= KEY_F1
+ (keyval
-GDK_F1
); break;
162 case GDK_Down
: nCode
= KEY_DOWN
; break;
164 case GDK_Up
: nCode
= KEY_UP
; break;
166 case GDK_Left
: nCode
= KEY_LEFT
; break;
168 case GDK_Right
: nCode
= KEY_RIGHT
; break;
172 case GDK_Home
: nCode
= KEY_HOME
; break;
174 case GDK_End
: nCode
= KEY_END
; break;
176 case GDK_Page_Up
: nCode
= KEY_PAGEUP
; break;
177 case GDK_KP_Page_Down
:
178 case GDK_Page_Down
: nCode
= KEY_PAGEDOWN
; break;
180 case GDK_Return
: nCode
= KEY_RETURN
; break;
181 case GDK_Escape
: nCode
= KEY_ESCAPE
; break;
182 case GDK_ISO_Left_Tab
:
184 case GDK_Tab
: nCode
= KEY_TAB
; break;
185 case GDK_BackSpace
: nCode
= KEY_BACKSPACE
; break;
187 case GDK_space
: nCode
= KEY_SPACE
; break;
189 case GDK_Insert
: nCode
= KEY_INSERT
; break;
191 case GDK_Delete
: nCode
= KEY_DELETE
; break;
193 case GDK_KP_Add
: nCode
= KEY_ADD
; break;
195 case GDK_KP_Subtract
: nCode
= KEY_SUBTRACT
; break;
197 case GDK_KP_Multiply
: nCode
= KEY_MULTIPLY
; break;
199 case GDK_KP_Divide
: nCode
= KEY_DIVIDE
; break;
201 case GDK_decimalpoint
: nCode
= KEY_POINT
; break;
202 case GDK_comma
: nCode
= KEY_COMMA
; break;
203 case GDK_less
: nCode
= KEY_LESS
; break;
204 case GDK_greater
: nCode
= KEY_GREATER
; break;
206 case GDK_equal
: nCode
= KEY_EQUAL
; break;
207 case GDK_Find
: nCode
= KEY_FIND
; break;
208 case GDK_Menu
: nCode
= KEY_CONTEXTMENU
;break;
209 case GDK_Help
: nCode
= KEY_HELP
; break;
210 case GDK_Undo
: nCode
= KEY_UNDO
; break;
211 case GDK_Redo
: nCode
= KEY_REPEAT
; break;
213 case GDK_KP_Separator
: nCode
= KEY_DECIMAL
; break;
214 case GDK_asciitilde
: nCode
= KEY_TILDE
; break;
215 case GDK_leftsinglequotemark
:
216 case GDK_quoteleft
: nCode
= KEY_QUOTELEFT
; break;
217 case GDK_bracketleft
: nCode
= KEY_BRACKETLEFT
; break;
218 case GDK_bracketright
: nCode
= KEY_BRACKETRIGHT
; break;
219 // some special cases, also see saldisp.cxx
220 // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
221 case 0x1000FF02: // apXK_Copy
224 case 0x1000FF03: // apXK_Cut
227 case 0x1000FF04: // apXK_Paste
230 case 0x1000FF14: // apXK_Repeat
234 // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
238 // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
239 case 0x1000FF73: // hpXK_DeleteChar
242 case 0x1000FF74: // hpXK_BackTab
243 case 0x1000FF75: // hpXK_KP_BackTab
246 // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
247 // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
248 case 0x1004FF02: // osfXK_Copy
251 case 0x1004FF03: // osfXK_Cut
254 case 0x1004FF04: // osfXK_Paste
257 case 0x1004FF07: // osfXK_BackTab
260 case 0x1004FF08: // osfXK_BackSpace
261 nCode
= KEY_BACKSPACE
;
263 case 0x1004FF1B: // osfXK_Escape
266 // Up, Down, Left, Right, PageUp, PageDown
267 // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
268 // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
269 // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
270 // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
271 case 0x1005FF10: // SunXK_F36
274 case 0x1005FF11: // SunXK_F37
277 case 0x1005FF70: // SunXK_Props
278 nCode
= KEY_PROPERTIES
;
280 case 0x1005FF71: // SunXK_Front
283 case 0x1005FF72: // SunXK_Copy
286 case 0x1005FF73: // SunXK_Open
289 case 0x1005FF74: // SunXK_Paste
292 case 0x1005FF75: // SunXK_Cut
301 // F10 means either KEY_F10 or KEY_MENU, which has to be decided
302 // in the independent part.
306 sal_Unicode nCharCode
;
307 KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
308 KeyAlternate( USHORT nKey
, sal_Unicode nChar
= 0 ) : nKeyCode( nKey
), nCharCode( nChar
) {}
312 GetAlternateKeyCode( const USHORT nKeyCode
)
314 KeyAlternate aAlternate
;
318 case KEY_F10
: aAlternate
= KeyAlternate( KEY_MENU
);break;
319 case KEY_F24
: aAlternate
= KeyAlternate( KEY_SUBTRACT
, '-' );break;
325 void GtkSalFrame::doKeyCallback( guint state
,
327 guint16 hardware_keycode
,
330 sal_Unicode aOrigCode
,
337 aEvent
.mnTime
= time
;
338 aEvent
.mnCharCode
= aOrigCode
;
341 vcl::DeletionListener
aDel( this );
342 /* #i42122# translate all keys with Ctrl and/or Alt to group 0
343 * else shortcuts (e.g. Ctrl-o) will not work but be inserted by
346 /* #i52338# do this for all keys that the independent part has no key code for
348 aEvent
.mnCode
= GetKeyCode( keyval
);
349 if( aEvent
.mnCode
== 0 )
351 // check other mapping
352 gint eff_group
, level
;
353 GdkModifierType consumed
;
354 guint updated_keyval
= 0;
355 // use gdk_keymap_get_default instead of NULL;
356 // workaround a crahs fixed in gtk 2.4
357 if( gdk_keymap_translate_keyboard_state( gdk_keymap_get_default(),
366 aEvent
.mnCode
= GetKeyCode( updated_keyval
);
369 aEvent
.mnCode
|= GetKeyModCode( state
);
373 bool bHandled
= CallCallback( SALEVENT_KEYINPUT
, &aEvent
);
374 // #i46889# copy AlternatKeyCode handling from generic plugin
377 KeyAlternate aAlternate
= GetAlternateKeyCode( aEvent
.mnCode
);
378 if( aAlternate
.nKeyCode
)
380 aEvent
.mnCode
= aAlternate
.nKeyCode
;
381 if( aAlternate
.nCharCode
)
382 aEvent
.mnCharCode
= aAlternate
.nCharCode
;
383 bHandled
= CallCallback( SALEVENT_KEYINPUT
, &aEvent
);
386 if( bSendRelease
&& ! aDel
.isDeleted() )
388 CallCallback( SALEVENT_KEYUP
, &aEvent
);
392 CallCallback( SALEVENT_KEYUP
, &aEvent
);
395 GtkSalFrame::GraphicsHolder::~GraphicsHolder()
400 GtkSalFrame::GtkSalFrame( SalFrame
* pParent
, ULONG nStyle
)
402 m_nScreen
= getDisplay()->GetDefaultScreenNumber();
403 getDisplay()->registerFrame( this );
404 m_bDefaultPos
= true;
405 m_bDefaultSize
= ( (nStyle
& SAL_FRAME_STYLE_SIZEABLE
) && ! pParent
);
406 m_bWindowIsGtkPlug
= false;
407 Init( pParent
, nStyle
);
410 GtkSalFrame::GtkSalFrame( SystemParentData
* pSysData
)
412 m_nScreen
= getDisplay()->GetDefaultScreenNumber();
413 getDisplay()->registerFrame( this );
414 getDisplay()->setHaveSystemChildFrame();
415 m_bDefaultPos
= true;
416 m_bDefaultSize
= true;
420 GtkSalFrame::~GtkSalFrame()
422 for( unsigned int i
= 0; i
< sizeof(m_aGraphics
)/sizeof(m_aGraphics
[0]); ++i
)
424 if( !m_aGraphics
[i
].pGraphics
)
426 m_aGraphics
[i
].pGraphics
->SetDrawable( None
, m_nScreen
);
427 m_aGraphics
[i
].bInUse
= false;
431 m_pParent
->m_aChildren
.remove( this );
433 getDisplay()->deregisterFrame( this );
436 gdk_region_destroy( m_pRegion
);
438 if( m_hBackgroundPixmap
)
440 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
441 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
443 XFreePixmap( getDisplay()->GetDisplay(), m_hBackgroundPixmap
);
449 if( m_pFixedContainer
)
450 gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer
) );
453 g_object_set_data( G_OBJECT( m_pWindow
), "SalFrame", NULL
);
454 gtk_widget_destroy( m_pWindow
);
456 if( m_pForeignParent
)
457 g_object_unref( G_OBJECT(m_pForeignParent
) );
458 if( m_pForeignTopLevel
)
459 g_object_unref(G_OBJECT( m_pForeignTopLevel
) );
462 void GtkSalFrame::moveWindow( long nX
, long nY
)
464 if( isChild( false, true ) )
467 gtk_fixed_move( m_pParent
->getFixedContainer(),
469 nX
- m_pParent
->maGeometry
.nX
, nY
- m_pParent
->maGeometry
.nY
);
472 gtk_window_move( GTK_WINDOW(m_pWindow
), nX
, nY
);
475 void GtkSalFrame::resizeWindow( long nWidth
, long nHeight
)
477 if( isChild( false, true ) )
478 gtk_widget_set_size_request( m_pWindow
, nWidth
, nHeight
);
479 else if( ! isChild( true, false ) )
480 gtk_window_resize( GTK_WINDOW(m_pWindow
), nWidth
, nHeight
);
484 * Always use a sub-class of GtkFixed we can tag for a11y. This allows us to
485 * utilize GAIL for the toplevel window and toolkit implementation incl.
486 * key event listener support ..
492 static GType type
= 0;
495 static const GTypeInfo tinfo
=
497 sizeof (GtkFixedClass
),
498 (GBaseInitFunc
) NULL
, /* base init */
499 (GBaseFinalizeFunc
) NULL
, /* base finalize */
500 (GClassInitFunc
) NULL
, /* class init */
501 (GClassFinalizeFunc
) NULL
, /* class finalize */
502 NULL
, /* class data */
503 sizeof (GtkFixed
), /* instance size */
504 0, /* nb preallocs */
505 (GInstanceInitFunc
) NULL
, /* instance init */
506 NULL
/* value table */
509 type
= g_type_register_static( GTK_TYPE_FIXED
, "OOoFixed",
510 &tinfo
, (GTypeFlags
) 0);
516 void GtkSalFrame::updateScreenNumber()
518 if( getDisplay()->IsXinerama() && getDisplay()->GetXineramaScreens().size() > 1 )
520 Point
aPoint( maGeometry
.nX
, maGeometry
.nY
);
521 const std::vector
<Rectangle
>& rScreenRects( getDisplay()->GetXineramaScreens() );
522 size_t nScreens
= rScreenRects
.size();
523 for( size_t i
= 0; i
< nScreens
; i
++ )
525 if( rScreenRects
[i
].IsInside( aPoint
) )
527 maGeometry
.nScreenNumber
= static_cast<unsigned int>(i
);
533 maGeometry
.nScreenNumber
= static_cast<unsigned int>(m_nScreen
);
536 void GtkSalFrame::InitCommon()
539 g_signal_connect( G_OBJECT(m_pWindow
), "style-set", G_CALLBACK(signalStyleSet
), this );
540 g_signal_connect( G_OBJECT(m_pWindow
), "button-press-event", G_CALLBACK(signalButton
), this );
541 g_signal_connect( G_OBJECT(m_pWindow
), "button-release-event", G_CALLBACK(signalButton
), this );
542 g_signal_connect( G_OBJECT(m_pWindow
), "expose-event", G_CALLBACK(signalExpose
), this );
543 g_signal_connect( G_OBJECT(m_pWindow
), "focus-in-event", G_CALLBACK(signalFocus
), this );
544 g_signal_connect( G_OBJECT(m_pWindow
), "focus-out-event", G_CALLBACK(signalFocus
), this );
545 g_signal_connect( G_OBJECT(m_pWindow
), "map-event", G_CALLBACK(signalMap
), this );
546 g_signal_connect( G_OBJECT(m_pWindow
), "unmap-event", G_CALLBACK(signalUnmap
), this );
547 g_signal_connect( G_OBJECT(m_pWindow
), "configure-event", G_CALLBACK(signalConfigure
), this );
548 g_signal_connect( G_OBJECT(m_pWindow
), "motion-notify-event", G_CALLBACK(signalMotion
), this );
549 g_signal_connect( G_OBJECT(m_pWindow
), "key-press-event", G_CALLBACK(signalKey
), this );
550 g_signal_connect( G_OBJECT(m_pWindow
), "key-release-event", G_CALLBACK(signalKey
), this );
551 g_signal_connect( G_OBJECT(m_pWindow
), "delete-event", G_CALLBACK(signalDelete
), this );
552 g_signal_connect( G_OBJECT(m_pWindow
), "window-state-event", G_CALLBACK(signalState
), this );
553 g_signal_connect( G_OBJECT(m_pWindow
), "scroll-event", G_CALLBACK(signalScroll
), this );
554 g_signal_connect( G_OBJECT(m_pWindow
), "leave-notify-event", G_CALLBACK(signalCrossing
), this );
555 g_signal_connect( G_OBJECT(m_pWindow
), "enter-notify-event", G_CALLBACK(signalCrossing
), this );
556 g_signal_connect( G_OBJECT(m_pWindow
), "visibility-notify-event", G_CALLBACK(signalVisibility
), this );
557 g_signal_connect( G_OBJECT(m_pWindow
), "destroy", G_CALLBACK(signalDestroy
), this );
560 m_pCurrentCursor
= NULL
;
562 m_bSingleAltPress
= false;
563 m_bFullscreen
= false;
564 m_nState
= GDK_WINDOW_STATE_WITHDRAWN
;
565 m_nVisibility
= GDK_VISIBILITY_FULLY_OBSCURED
;
566 m_bSendModChangeOnRelease
= false;
568 m_hBackgroundPixmap
= None
;
569 m_nSavedScreenSaverTimeout
= 0;
573 m_ePointerStyle
= 0xffff;
575 gtk_widget_set_app_paintable( m_pWindow
, TRUE
);
576 gtk_widget_set_double_buffered( m_pWindow
, FALSE
);
577 gtk_widget_set_redraw_on_allocate( m_pWindow
, FALSE
);
578 gtk_widget_add_events( m_pWindow
,
579 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
|
580 GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK
|
581 GDK_VISIBILITY_NOTIFY_MASK
584 // add the fixed container child,
585 // fixed is needed since we have to position plugin windows
586 m_pFixedContainer
= GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL
));
587 gtk_container_add( GTK_CONTAINER(m_pWindow
), GTK_WIDGET(m_pFixedContainer
) );
590 gtk_widget_show( GTK_WIDGET(m_pFixedContainer
) );
592 // realize the window, we need an XWindow id
593 gtk_widget_realize( m_pWindow
);
596 SalDisplay
* pDisp
= GetX11SalData()->GetDisplay();
597 m_aSystemData
.nSize
= sizeof( SystemChildData
);
598 m_aSystemData
.pDisplay
= pDisp
->GetDisplay();
599 m_aSystemData
.aWindow
= GDK_WINDOW_XWINDOW(m_pWindow
->window
);
600 m_aSystemData
.pSalFrame
= this;
601 m_aSystemData
.pWidget
= m_pWindow
;
602 m_aSystemData
.pVisual
= pDisp
->GetVisual( m_nScreen
).GetVisual();
603 m_aSystemData
.nScreen
= m_nScreen
;
604 m_aSystemData
.nDepth
= pDisp
->GetVisual( m_nScreen
).GetDepth();
605 m_aSystemData
.aColormap
= pDisp
->GetColormap( m_nScreen
).GetXColormap();
606 m_aSystemData
.pAppContext
= NULL
;
607 m_aSystemData
.aShellWindow
= m_aSystemData
.aWindow
;
608 m_aSystemData
.pShellWidget
= m_aSystemData
.pWidget
;
611 // fake an initial geometry, gets updated via configure event or SetPosSize
612 if( m_bDefaultPos
|| m_bDefaultSize
)
614 Size aDefSize
= calcDefaultSize();
617 maGeometry
.nWidth
= aDefSize
.Width();
618 maGeometry
.nHeight
= aDefSize
.Height();
622 maGeometry
.nTopDecoration
= m_pParent
->maGeometry
.nTopDecoration
;
623 maGeometry
.nBottomDecoration
= m_pParent
->maGeometry
.nBottomDecoration
;
624 maGeometry
.nLeftDecoration
= m_pParent
->maGeometry
.nLeftDecoration
;
625 maGeometry
.nRightDecoration
= m_pParent
->maGeometry
.nRightDecoration
;
629 maGeometry
.nTopDecoration
= 0;
630 maGeometry
.nBottomDecoration
= 0;
631 maGeometry
.nLeftDecoration
= 0;
632 maGeometry
.nRightDecoration
= 0;
637 resizeWindow( maGeometry
.nWidth
, maGeometry
.nHeight
);
638 moveWindow( maGeometry
.nX
, maGeometry
.nY
);
640 updateScreenNumber();
643 m_nWorkArea
= pDisp
->getWMAdaptor()->getCurrentWorkArea();
645 /* #i64117# gtk sets a nice background pixmap
646 * but we actually don't really want that, so save
647 * some time on the Xserver as well as prevent
650 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
651 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
652 m_hBackgroundPixmap
);
655 /* Sadly gtk_window_set_accept_focus exists only since gtk 2.4
656 * for achieving the same effect we will remove the WM_TAKE_FOCUS
657 * protocol from the window and set the input hint to false.
658 * But gtk_window_set_accept_focus needs to be called before
659 * window realization whereas the removal obviously can only happen
664 typedef void(*setAcceptFn
)( GtkWindow
*, gboolean
);
665 static setAcceptFn p_gtk_window_set_accept_focus
= NULL
;
666 static bool bGetAcceptFocusFn
= true;
668 typedef void(*setUserTimeFn
)( GdkWindow
*, guint32
);
669 static setUserTimeFn p_gdk_x11_window_set_user_time
= NULL
;
670 static bool bGetSetUserTimeFn
= true;
673 static void lcl_set_accept_focus( GtkWindow
* pWindow
, gboolean bAccept
, bool bBeforeRealize
)
675 if( bGetAcceptFocusFn
)
677 bGetAcceptFocusFn
= false;
678 p_gtk_window_set_accept_focus
= (setAcceptFn
)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin
, "gtk_window_set_accept_focus" );
680 if( p_gtk_window_set_accept_focus
&& bBeforeRealize
)
681 p_gtk_window_set_accept_focus( pWindow
, bAccept
);
682 else if( ! bBeforeRealize
)
684 Display
* pDisplay
= GetX11SalData()->GetDisplay()->GetDisplay();
685 XLIB_Window aWindow
= GDK_WINDOW_XWINDOW( GTK_WIDGET(pWindow
)->window
);
686 XWMHints
* pHints
= XGetWMHints( pDisplay
, aWindow
);
689 pHints
= XAllocWMHints();
692 pHints
->flags
|= InputHint
;
693 pHints
->input
= bAccept
? True
: False
;
694 XSetWMHints( pDisplay
, aWindow
, pHints
);
697 if (GetX11SalData()->GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz"))
700 /* remove WM_TAKE_FOCUS protocol; this would usually be the
701 * right thing, but gtk handles it internally whereas we
702 * want to handle it ourselves (as to sometimes not get
705 Atom
* pProtocols
= NULL
;
707 XGetWMProtocols( pDisplay
,
709 &pProtocols
, &nProtocols
);
713 Atom nTakeFocus
= XInternAtom( pDisplay
, "WM_TAKE_FOCUS", True
);
716 for( int i
= 0; i
< nProtocols
; i
++ )
718 if( pProtocols
[i
] == nTakeFocus
)
720 for( int n
= i
; n
< nProtocols
-1; n
++ )
721 pProtocols
[n
] = pProtocols
[n
+1];
729 XSetWMProtocols( pDisplay
, aWindow
, pProtocols
, nProtocols
);
734 static void lcl_set_user_time( GdkWindow
* i_pWindow
, guint32 i_nTime
)
736 if( bGetSetUserTimeFn
)
738 bGetSetUserTimeFn
= false;
739 p_gdk_x11_window_set_user_time
= (setUserTimeFn
)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin
, "gdk_x11_window_set_user_time" );
741 if( p_gdk_x11_window_set_user_time
)
742 p_gdk_x11_window_set_user_time( i_pWindow
, i_nTime
);
745 Display
* pDisplay
= GetX11SalData()->GetDisplay()->GetDisplay();
746 XLIB_Window aWindow
= GDK_WINDOW_XWINDOW( i_pWindow
);
747 Atom nUserTime
= XInternAtom( pDisplay
, "_NET_WM_USER_TIME", True
);
750 XChangeProperty( pDisplay
, aWindow
,
751 nUserTime
, XA_CARDINAL
, 32,
752 PropModeReplace
, (unsigned char*)&i_nTime
, 1 );
757 GtkSalFrame
*GtkSalFrame::getFromWindow( GtkWindow
*pWindow
)
759 return (GtkSalFrame
*) g_object_get_data( G_OBJECT( pWindow
), "SalFrame" );
762 void GtkSalFrame::Init( SalFrame
* pParent
, ULONG nStyle
)
764 if( nStyle
& SAL_FRAME_STYLE_DEFAULT
) // ensure default style
766 nStyle
|= SAL_FRAME_STYLE_MOVEABLE
| SAL_FRAME_STYLE_SIZEABLE
| SAL_FRAME_STYLE_CLOSEABLE
;
767 nStyle
&= ~SAL_FRAME_STYLE_FLOAT
;
770 m_pParent
= static_cast<GtkSalFrame
*>(pParent
);
771 m_pForeignParent
= NULL
;
772 m_aForeignParentWindow
= None
;
773 m_pForeignTopLevel
= NULL
;
774 m_aForeignTopLevelWindow
= None
;
777 GtkWindowType eWinType
= ((nStyle
& SAL_FRAME_STYLE_FLOAT
) && ! (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
))
778 ? GTK_WINDOW_POPUP
: GTK_WINDOW_TOPLEVEL
;
780 if( nStyle
& SAL_FRAME_STYLE_SYSTEMCHILD
)
782 m_pWindow
= gtk_event_box_new();
785 // insert into container
786 gtk_fixed_put( m_pParent
->getFixedContainer(),
792 m_pWindow
= gtk_widget_new( GTK_TYPE_WINDOW
, "type", eWinType
, "visible", FALSE
, NULL
);
793 g_object_set_data( G_OBJECT( m_pWindow
), "SalFrame", this );
795 // force wm class hint
797 SetExtendedFrameStyle( 0 );
799 if( m_pParent
&& m_pParent
->m_pWindow
&& ! isChild() )
800 gtk_window_set_screen( GTK_WINDOW(m_pWindow
), gtk_window_get_screen( GTK_WINDOW(m_pParent
->m_pWindow
) ) );
805 ( ! (nStyle
& SAL_FRAME_STYLE_FLOAT
) ||
806 (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) );
808 /* #i100116# metacity has a peculiar behavior regarding WM_HINT accept focus and _NET_WM_USER_TIME
809 at some point that may be fixed in metacity and we will have to revisit this
811 bool bMetaCityToolWindowHack
= getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") &&
812 (nStyle
& SAL_FRAME_STYLE_TOOLWINDOW
);
815 bool bNoDecor
= ! (nStyle
& (SAL_FRAME_STYLE_MOVEABLE
| SAL_FRAME_STYLE_SIZEABLE
| SAL_FRAME_STYLE_CLOSEABLE
) );
816 GdkWindowTypeHint eType
= GDK_WINDOW_TYPE_HINT_NORMAL
;
817 if( (nStyle
& SAL_FRAME_STYLE_DIALOG
) && m_pParent
!= 0 )
818 eType
= GDK_WINDOW_TYPE_HINT_DIALOG
;
819 if( (nStyle
& SAL_FRAME_STYLE_INTRO
) )
821 gtk_window_set_role( GTK_WINDOW(m_pWindow
), "splashscreen" );
822 eType
= GDK_WINDOW_TYPE_HINT_SPLASHSCREEN
;
824 else if( (nStyle
& SAL_FRAME_STYLE_TOOLWINDOW
) )
826 eType
= GDK_WINDOW_TYPE_HINT_UTILITY
;
827 gtk_window_set_skip_taskbar_hint( GTK_WINDOW(m_pWindow
), true );
828 if( bMetaCityToolWindowHack
)
829 lcl_set_accept_focus( GTK_WINDOW(m_pWindow
), FALSE
, true );
831 else if( (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) )
833 eType
= GDK_WINDOW_TYPE_HINT_TOOLBAR
;
834 lcl_set_accept_focus( GTK_WINDOW(m_pWindow
), FALSE
, true );
837 if( (nStyle
& SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
) )
839 eType
= GDK_WINDOW_TYPE_HINT_TOOLBAR
;
840 gtk_window_set_keep_above( GTK_WINDOW(m_pWindow
), true );
843 gtk_window_set_type_hint( GTK_WINDOW(m_pWindow
), eType
);
845 gtk_window_set_decorated( GTK_WINDOW(m_pWindow
), FALSE
);
846 gtk_window_set_gravity( GTK_WINDOW(m_pWindow
), GDK_GRAVITY_STATIC
);
847 if( m_pParent
&& ! (m_pParent
->m_nStyle
& SAL_FRAME_STYLE_PLUG
) )
848 gtk_window_set_transient_for( GTK_WINDOW(m_pWindow
), GTK_WINDOW(m_pParent
->m_pWindow
) );
850 else if( (nStyle
& SAL_FRAME_STYLE_FLOAT
) )
852 gtk_window_set_type_hint( GTK_WINDOW(m_pWindow
), GDK_WINDOW_TYPE_HINT_UTILITY
);
855 m_pParent
->m_aChildren
.push_back( this );
859 if( eWinType
== GTK_WINDOW_TOPLEVEL
)
861 guint32 nUserTime
= 0;
862 if( (nStyle
& (SAL_FRAME_STYLE_OWNERDRAWDECORATION
|SAL_FRAME_STYLE_TOOLWINDOW
)) == 0 )
864 /* #i99360# ugly workaround an X11 library bug */
865 nUserTime
= getDisplay()->GetLastUserEventTime( true );
866 // nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
868 lcl_set_user_time(GTK_WIDGET(m_pWindow
)->window
, nUserTime
);
873 gtk_window_set_resizable( GTK_WINDOW(m_pWindow
), (nStyle
& SAL_FRAME_STYLE_SIZEABLE
) ? TRUE
: FALSE
);
874 if( ( (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) ) || bMetaCityToolWindowHack
)
875 lcl_set_accept_focus( GTK_WINDOW(m_pWindow
), FALSE
, false );
880 GdkNativeWindow
GtkSalFrame::findTopLevelSystemWindow( GdkNativeWindow aWindow
)
882 XLIB_Window aRoot
, aParent
;
883 XLIB_Window
* pChildren
;
884 unsigned int nChildren
;
890 aParent
= aRoot
= None
;
891 XQueryTree( getDisplay()->GetDisplay(), aWindow
,
892 &aRoot
, &aParent
, &pChildren
, &nChildren
);
894 if( aParent
!= aRoot
)
897 Atom
* pProps
= XListProperties( getDisplay()->GetDisplay(),
900 for( int i
= 0; i
< nCount
&& ! bBreak
; ++i
)
901 bBreak
= (pProps
[i
] == XA_WM_HINTS
);
904 } while( aParent
!= aRoot
&& ! bBreak
);
909 void GtkSalFrame::Init( SystemParentData
* pSysData
)
912 m_aForeignParentWindow
= (GdkNativeWindow
)pSysData
->aWindow
;
913 m_pForeignParent
= NULL
;
914 m_aForeignTopLevelWindow
= findTopLevelSystemWindow( (GdkNativeWindow
)pSysData
->aWindow
);
915 m_pForeignTopLevel
= gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignTopLevelWindow
);
916 gdk_window_set_events( m_pForeignTopLevel
, GDK_STRUCTURE_MASK
);
918 if( pSysData
->nSize
> sizeof(pSysData
->nSize
)+sizeof(pSysData
->aWindow
) && pSysData
->bXEmbedSupport
)
920 m_pWindow
= gtk_plug_new( pSysData
->aWindow
);
921 m_bWindowIsGtkPlug
= true;
922 GTK_WIDGET_SET_FLAGS( m_pWindow
, GTK_CAN_FOCUS
| GTK_SENSITIVE
| GTK_CAN_DEFAULT
);
923 gtk_widget_set_sensitive( m_pWindow
, true );
927 m_pWindow
= gtk_window_new( GTK_WINDOW_POPUP
);
928 m_bWindowIsGtkPlug
= false;
930 m_nStyle
= SAL_FRAME_STYLE_PLUG
;
933 m_pForeignParent
= gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignParentWindow
);
934 gdk_window_set_events( m_pForeignParent
, GDK_STRUCTURE_MASK
);
936 unsigned int w
, h
, bw
, d
;
938 XGetGeometry( getDisplay()->GetDisplay(), pSysData
->aWindow
,
939 &aRoot
, &x_ret
, &y_ret
, &w
, &h
, &bw
, &d
);
940 maGeometry
.nWidth
= w
;
941 maGeometry
.nHeight
= h
;
942 gtk_window_resize( GTK_WINDOW(m_pWindow
), w
, h
);
943 gtk_window_move( GTK_WINDOW(m_pWindow
), 0, 0 );
944 if( ! m_bWindowIsGtkPlug
)
946 XReparentWindow( getDisplay()->GetDisplay(),
947 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
948 (XLIB_Window
)pSysData
->aWindow
,
953 void GtkSalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode
)
957 rtl_zeroMemory( &aEvent
, sizeof(aEvent
) );
958 aEvent
.xclient
.window
= m_aForeignParentWindow
;
959 aEvent
.xclient
.type
= ClientMessage
;
960 aEvent
.xclient
.message_type
= getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED
);
961 aEvent
.xclient
.format
= 32;
962 aEvent
.xclient
.data
.l
[0] = i_nTimeCode
? i_nTimeCode
: CurrentTime
;
963 aEvent
.xclient
.data
.l
[1] = 3; // XEMBED_REQUEST_FOCUS
964 aEvent
.xclient
.data
.l
[2] = 0;
965 aEvent
.xclient
.data
.l
[3] = 0;
966 aEvent
.xclient
.data
.l
[4] = 0;
968 getDisplay()->GetXLib()->PushXErrorLevel( true );
969 XSendEvent( getDisplay()->GetDisplay(),
970 m_aForeignParentWindow
,
971 False
, NoEventMask
, &aEvent
);
972 XSync( getDisplay()->GetDisplay(), False
);
973 getDisplay()->GetXLib()->PopXErrorLevel();
976 void GtkSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle
)
978 if( nStyle
!= m_nExtStyle
&& ! isChild() )
980 m_nExtStyle
= nStyle
;
981 if( GTK_WIDGET_REALIZED( m_pWindow
) )
983 XClassHint
* pClass
= XAllocClassHint();
984 rtl::OString aResHint
= X11SalData::getFrameResName( m_nExtStyle
);
985 pClass
->res_name
= const_cast<char*>(aResHint
.getStr());
986 pClass
->res_class
= const_cast<char*>(X11SalData::getFrameClassName());
987 XSetClassHint( getDisplay()->GetDisplay(),
988 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
993 gtk_window_set_wmclass( GTK_WINDOW(m_pWindow
),
994 X11SalData::getFrameResName( m_nExtStyle
),
995 X11SalData::getFrameClassName() );
1000 SalGraphics
* GtkSalFrame::GetGraphics()
1004 for( int i
= 0; i
< nMaxGraphics
; i
++ )
1006 if( ! m_aGraphics
[i
].bInUse
)
1008 m_aGraphics
[i
].bInUse
= true;
1009 if( ! m_aGraphics
[i
].pGraphics
)
1011 m_aGraphics
[i
].pGraphics
= new GtkSalGraphics( m_pWindow
);
1012 m_aGraphics
[i
].pGraphics
->Init( this, GDK_WINDOW_XWINDOW(m_pWindow
->window
), m_nScreen
);
1014 return m_aGraphics
[i
].pGraphics
;
1022 void GtkSalFrame::ReleaseGraphics( SalGraphics
* pGraphics
)
1024 for( int i
= 0; i
< nMaxGraphics
; i
++ )
1026 if( m_aGraphics
[i
].pGraphics
== pGraphics
)
1028 m_aGraphics
[i
].bInUse
= false;
1034 BOOL
GtkSalFrame::PostEvent( void* pData
)
1036 getDisplay()->SendInternalEvent( this, pData
);
1040 void GtkSalFrame::SetTitle( const String
& rTitle
)
1043 if( m_pWindow
&& ! isChild() )
1044 gtk_window_set_title( GTK_WINDOW(m_pWindow
), rtl::OUStringToOString( rTitle
, RTL_TEXTENCODING_UTF8
).getStr() );
1047 static inline BYTE
*
1048 getRow( BitmapBuffer
*pBuffer
, ULONG nRow
)
1050 if( BMP_SCANLINE_ADJUSTMENT( pBuffer
->mnFormat
) == BMP_FORMAT_TOP_DOWN
)
1051 return pBuffer
->mpBits
+ nRow
* pBuffer
->mnScanlineSize
;
1053 return pBuffer
->mpBits
+ ( pBuffer
->mnHeight
- nRow
- 1 ) * pBuffer
->mnScanlineSize
;
1057 bitmapToPixbuf( SalBitmap
*pSalBitmap
, SalBitmap
*pSalAlpha
)
1059 g_return_val_if_fail( pSalBitmap
!= NULL
, NULL
);
1060 g_return_val_if_fail( pSalAlpha
!= NULL
, NULL
);
1062 BitmapBuffer
*pBitmap
= pSalBitmap
->AcquireBuffer( TRUE
);
1063 g_return_val_if_fail( pBitmap
!= NULL
, NULL
);
1064 g_return_val_if_fail( pBitmap
->mnBitCount
== 24, NULL
);
1066 BitmapBuffer
*pAlpha
= pSalAlpha
->AcquireBuffer( TRUE
);
1067 g_return_val_if_fail( pAlpha
!= NULL
, NULL
);
1068 g_return_val_if_fail( pAlpha
->mnBitCount
== 8, NULL
);
1070 Size aSize
= pSalBitmap
->GetSize();
1071 g_return_val_if_fail( pSalAlpha
->GetSize() == aSize
, NULL
);
1074 guchar
*pPixbufData
= (guchar
*)g_malloc (4 * aSize
.Width() * aSize
.Height() );
1075 guchar
*pDestData
= pPixbufData
;
1077 for( nY
= 0; nY
< pBitmap
->mnHeight
; nY
++ )
1079 BYTE
*pData
= getRow( pBitmap
, nY
);
1080 BYTE
*pAlphaData
= getRow( pAlpha
, nY
);
1082 for( nX
= 0; nX
< pBitmap
->mnWidth
; nX
++ )
1084 if( pBitmap
->mnFormat
== BMP_FORMAT_24BIT_TC_BGR
)
1086 pDestData
[2] = *pData
++;
1087 pDestData
[1] = *pData
++;
1088 pDestData
[0] = *pData
++;
1090 else // BMP_FORMAT_24BIT_TC_RGB
1092 pDestData
[0] = *pData
++;
1093 pDestData
[1] = *pData
++;
1094 pDestData
[2] = *pData
++;
1097 *pDestData
++ = 255 - *pAlphaData
++;
1101 pSalBitmap
->ReleaseBuffer( pBitmap
, TRUE
);
1102 pSalAlpha
->ReleaseBuffer( pAlpha
, TRUE
);
1104 return gdk_pixbuf_new_from_data( pPixbufData
,
1105 GDK_COLORSPACE_RGB
, TRUE
, 8,
1106 aSize
.Width(), aSize
.Height(),
1108 (GdkPixbufDestroyNotify
) g_free
,
1112 void GtkSalFrame::SetIcon( USHORT nIcon
)
1114 if( (m_nStyle
& (SAL_FRAME_STYLE_PLUG
|SAL_FRAME_STYLE_SYSTEMCHILD
|SAL_FRAME_STYLE_FLOAT
|SAL_FRAME_STYLE_INTRO
|SAL_FRAME_STYLE_OWNERDRAWDECORATION
))
1118 if( !ImplGetResMgr() )
1122 GList
*pIcons
= NULL
;
1124 USHORT nOffsets
[2] = { SV_ICON_SMALL_START
, SV_ICON_LARGE_START
};
1127 // Use high contrast icons where appropriate
1128 if( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1130 nOffsets
[0] = SV_ICON_LARGE_HC_START
;
1131 nOffsets
[1] = SV_ICON_SMALL_HC_START
;
1134 for( nIndex
= 0; nIndex
< sizeof(nOffsets
)/ sizeof(USHORT
); nIndex
++ )
1136 // #i44723# workaround gcc temporary problem
1137 ResId
aResId( nOffsets
[nIndex
] + nIcon
, *ImplGetResMgr() );
1140 aIcon
= BitmapEx( aResId
);
1141 } catch (com::sun::star::uno::RuntimeException
&) {
1142 // UCB not initialized for splash screen creation; very exceptional.
1146 // #i81083# convert to 24bit/8bit alpha bitmap
1147 Bitmap aBmp
= aIcon
.GetBitmap();
1148 if( aBmp
.GetBitCount() != 24 || ! aIcon
.IsAlpha() )
1150 if( aBmp
.GetBitCount() != 24 )
1151 aBmp
.Convert( BMP_CONVERSION_24BIT
);
1153 if( ! aIcon
.IsAlpha() )
1155 switch( aIcon
.GetTransparentType() )
1157 case TRANSPARENT_NONE
:
1160 aMask
= AlphaMask( aBmp
.GetSizePixel(), &nTrans
);
1163 case TRANSPARENT_COLOR
:
1164 aMask
= AlphaMask( aBmp
.CreateMask( aIcon
.GetTransparentColor() ) );
1166 case TRANSPARENT_BITMAP
:
1167 aMask
= AlphaMask( aIcon
.GetMask() );
1170 DBG_ERROR( "unhandled transparent type" );
1175 aMask
= aIcon
.GetAlpha();
1176 aIcon
= BitmapEx( aBmp
, aMask
);
1179 ImpBitmap
*pIconImpBitmap
= aIcon
.ImplGetBitmapImpBitmap();
1180 ImpBitmap
*pIconImpMask
= aIcon
.ImplGetMaskImpBitmap();
1183 if( pIconImpBitmap
&& pIconImpMask
)
1185 SalBitmap
*pIconBitmap
=
1186 pIconImpBitmap
->ImplGetSalBitmap();
1187 SalBitmap
*pIconMask
=
1188 pIconImpMask
->ImplGetSalBitmap();
1190 if( ( pBuf
= bitmapToPixbuf( pIconBitmap
, pIconMask
) ) )
1191 pIcons
= g_list_prepend( pIcons
, pBuf
);
1195 gtk_window_set_icon_list( GTK_WINDOW(m_pWindow
), pIcons
);
1197 g_list_foreach( pIcons
, (GFunc
) g_object_unref
, NULL
);
1198 g_list_free( pIcons
);
1201 void GtkSalFrame::SetMenu( SalMenu
* )
1205 void GtkSalFrame::DrawMenuBar()
1209 void GtkSalFrame::Center()
1215 nX
= ((long)m_pParent
->maGeometry
.nWidth
- (long)maGeometry
.nWidth
)/2;
1216 nY
= ((long)m_pParent
->maGeometry
.nHeight
- (long)maGeometry
.nHeight
)/2;
1221 long nScreenWidth
, nScreenHeight
;
1222 long nScreenX
= 0, nScreenY
= 0;
1224 Size aScreenSize
= GetX11SalData()->GetDisplay()->GetScreenSize( m_nScreen
);
1225 nScreenWidth
= aScreenSize
.Width();
1226 nScreenHeight
= aScreenSize
.Height();
1227 if( GetX11SalData()->GetDisplay()->IsXinerama() )
1229 // get xinerama screen we are on
1230 // if there is a parent, use its center for screen determination
1231 // else use the pointer
1234 GdkModifierType aMask
;
1235 gdk_display_get_pointer( getGdkDisplay(), &pScreen
, &x
, &y
, &aMask
);
1237 const std::vector
< Rectangle
>& rScreens
= GetX11SalData()->GetDisplay()->GetXineramaScreens();
1238 for( unsigned int i
= 0; i
< rScreens
.size(); i
++ )
1239 if( rScreens
[i
].IsInside( Point( x
, y
) ) )
1241 nScreenX
= rScreens
[i
].Left();
1242 nScreenY
= rScreens
[i
].Top();
1243 nScreenWidth
= rScreens
[i
].GetWidth();
1244 nScreenHeight
= rScreens
[i
].GetHeight();
1248 nX
= nScreenX
+ (nScreenWidth
- (long)maGeometry
.nWidth
)/2;
1249 nY
= nScreenY
+ (nScreenHeight
- (long)maGeometry
.nHeight
)/2;
1251 SetPosSize( nX
, nY
, 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
1254 Size
GtkSalFrame::calcDefaultSize()
1256 Size aScreenSize
= GetX11SalData()->GetDisplay()->GetScreenSize( m_nScreen
);
1257 long w
= aScreenSize
.Width();
1258 long h
= aScreenSize
.Height();
1260 // fill in holy default values brought to us by product management
1261 if( aScreenSize
.Width() >= 800 )
1263 if( aScreenSize
.Width() >= 1024 )
1266 if( aScreenSize
.Height() >= 600 )
1268 if( aScreenSize
.Height() >= 768 )
1270 if( aScreenSize
.Height() >= 1024 )
1273 return Size( w
, h
);
1276 void GtkSalFrame::SetDefaultSize()
1278 Size aDefSize
= calcDefaultSize();
1280 SetPosSize( 0, 0, aDefSize
.Width(), aDefSize
.Height(),
1281 SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
1283 if( (m_nStyle
& SAL_FRAME_STYLE_DEFAULT
) && m_pWindow
)
1284 gtk_window_maximize( GTK_WINDOW(m_pWindow
) );
1287 static void initClientId()
1289 static bool bOnce
= false;
1293 const ByteString
& rID
= SessionManagerClient::getSessionID();
1295 gdk_set_sm_client_id(rID
.GetBuffer());
1299 void GtkSalFrame::Show( BOOL bVisible
, BOOL bNoActivate
)
1303 if( m_pParent
&& (m_pParent
->m_nStyle
& SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
) )
1304 gtk_window_set_keep_above( GTK_WINDOW(m_pWindow
), bVisible
);
1307 SessionManagerClient::open(); // will simply return after the first time
1309 getDisplay()->startupNotificationCompleted();
1313 if( m_bDefaultSize
)
1317 // #i45160# switch to desktop where a dialog with parent will appear
1318 if( m_pParent
&& m_pParent
->m_nWorkArea
!= m_nWorkArea
)
1319 getDisplay()->getWMAdaptor()->switchToWorkArea( m_pParent
->m_nWorkArea
);
1321 if( isFloatGrabWindow() &&
1324 ! getDisplay()->GetCaptureFrame() )
1327 * outsmart Metacity's "focus:mouse" mode
1328 * which insists on taking the focus from the document
1329 * to the new float. Grab focus to parent frame BEFORE
1330 * showing the float (cannot grab it to the float
1333 m_pParent
->grabPointer( TRUE
, TRUE
);
1336 guint32 nUserTime
= 0;
1337 if( ! bNoActivate
&& (m_nStyle
& (SAL_FRAME_STYLE_OWNERDRAWDECORATION
|SAL_FRAME_STYLE_TOOLWINDOW
)) == 0 )
1338 /* #i99360# ugly workaround an X11 library bug */
1339 nUserTime
= getDisplay()->GetLastUserEventTime( true );
1340 //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
1342 //For these floating windows we don't want the main window to lose focus, and metacity has...
1343 // metacity-2.24.0/src/core/window.c
1345 // if ((focus_window != NULL) && XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time))
1346 // "compare" window focus prevented by other activity
1348 // where "compare" is this window
1350 // which leads to...
1352 // /* This happens for error dialogs or alerts; these need to remain on
1353 // * top, but it would be confusing to have its ancestor remain
1356 // if (meta_window_is_ancestor_of_transient (focus_window, window))
1357 // "The focus window %s is an ancestor of the newly mapped "
1358 // "window %s which isn't being focused. Unfocusing the "
1361 // i.e. having a time < that of the toplevel frame means that the toplevel frame gets unfocused.
1363 if( nUserTime
== 0 &&
1365 getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") ||
1367 getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz") &&
1368 (m_nStyle
& (SAL_FRAME_STYLE_OWNERDRAWDECORATION
))
1373 /* #i99360# ugly workaround an X11 library bug */
1374 nUserTime
= getDisplay()->GetLastUserEventTime( true );
1375 //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
1378 lcl_set_user_time( GTK_WIDGET(m_pWindow
)->window
, nUserTime
);
1380 gtk_widget_show( m_pWindow
);
1382 if( isFloatGrabWindow() )
1385 if( ! getDisplay()->GetCaptureFrame() && m_nFloats
== 1 )
1386 grabPointer( TRUE
, TRUE
);
1387 // #i44068# reset parent's IM context
1389 m_pParent
->EndExtTextInput(0);
1391 if( m_bWindowIsGtkPlug
)
1392 askForXEmbedFocus( 0 );
1396 if( isFloatGrabWindow() )
1399 if( ! getDisplay()->GetCaptureFrame() && m_nFloats
== 0)
1400 grabPointer( FALSE
);
1402 gtk_widget_hide( m_pWindow
);
1404 m_pIMHandler
->focusChanged( false );
1405 // flush here; there may be a very seldom race between
1406 // the display connection used for clipboard and our connection
1409 CallCallback( SALEVENT_RESIZE
, NULL
);
1413 void GtkSalFrame::Enable( BOOL
/*bEnable*/ )
1415 // Not implemented by X11SalFrame either
1418 void GtkSalFrame::setMinMaxSize()
1420 /* FIXME: for yet unknown reasons the reported size is a little smaller
1421 * than the max size hint; one would guess that this was due to the border
1422 * sizes of the widgets involved (GtkWindow and GtkFixed), but setting the
1423 * their border to 0 (which is the default anyway) does not change the
1424 * behaviour. Until the reason is known we'll add some pixels here.
1426 #define CONTAINER_ADJUSTMENT 6
1428 /* #i34504# metacity (and possibly others) do not treat
1429 * _NET_WM_STATE_FULLSCREEN and max_width/heigth independently;
1430 * whether they should is undefined. So don't set the max size hint
1431 * for a full screen window.
1433 if( m_pWindow
&& ! isChild() )
1437 if( m_nStyle
& SAL_FRAME_STYLE_SIZEABLE
)
1439 if( m_aMinSize
.Width() && m_aMinSize
.Height() )
1441 aGeo
.min_width
= m_aMinSize
.Width()+CONTAINER_ADJUSTMENT
;
1442 aGeo
.min_height
= m_aMinSize
.Height()+CONTAINER_ADJUSTMENT
;
1443 aHints
|= GDK_HINT_MIN_SIZE
;
1445 if( m_aMaxSize
.Width() && m_aMaxSize
.Height() && ! m_bFullscreen
)
1447 aGeo
.max_width
= m_aMaxSize
.Width()+CONTAINER_ADJUSTMENT
;
1448 aGeo
.max_height
= m_aMaxSize
.Height()+CONTAINER_ADJUSTMENT
;
1449 aHints
|= GDK_HINT_MAX_SIZE
;
1454 aGeo
.min_width
= maGeometry
.nWidth
;
1455 aGeo
.min_height
= maGeometry
.nHeight
;
1456 aHints
|= GDK_HINT_MIN_SIZE
;
1457 if( ! m_bFullscreen
)
1459 aGeo
.max_width
= maGeometry
.nWidth
;
1460 aGeo
.max_height
= maGeometry
.nHeight
;
1461 aHints
|= GDK_HINT_MAX_SIZE
;
1465 gtk_window_set_geometry_hints( GTK_WINDOW(m_pWindow
),
1468 GdkWindowHints( aHints
) );
1472 void GtkSalFrame::SetMaxClientSize( long nWidth
, long nHeight
)
1476 m_aMaxSize
= Size( nWidth
, nHeight
);
1477 // Show does a setMinMaxSize
1478 if( GTK_WIDGET_MAPPED( m_pWindow
) )
1482 void GtkSalFrame::SetMinClientSize( long nWidth
, long nHeight
)
1486 m_aMinSize
= Size( nWidth
, nHeight
);
1489 gtk_widget_set_size_request( m_pWindow
, nWidth
, nHeight
);
1490 // Show does a setMinMaxSize
1491 if( GTK_WIDGET_MAPPED( m_pWindow
) )
1497 void GtkSalFrame::SetPosSize( long nX
, long nY
, long nWidth
, long nHeight
, USHORT nFlags
)
1499 if( !m_pWindow
|| isChild( true, false ) )
1502 bool bSized
= false, bMoved
= false;
1504 if( (nFlags
& ( SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
)) &&
1505 (nWidth
> 0 && nHeight
> 0 ) // sometimes stupid things happen
1508 m_bDefaultSize
= false;
1510 if( (unsigned long)nWidth
!= maGeometry
.nWidth
|| (unsigned long)nHeight
!= maGeometry
.nHeight
)
1512 maGeometry
.nWidth
= nWidth
;
1513 maGeometry
.nHeight
= nHeight
;
1515 if( isChild( false, true ) )
1516 gtk_widget_set_size_request( m_pWindow
, nWidth
, nHeight
);
1517 else if( ! ( m_nState
& GDK_WINDOW_STATE_MAXIMIZED
) )
1518 gtk_window_resize( GTK_WINDOW(m_pWindow
), nWidth
, nHeight
);
1521 else if( m_bDefaultSize
)
1524 m_bDefaultSize
= false;
1526 if( nFlags
& ( SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
) )
1530 if( Application::GetSettings().GetLayoutRTL() )
1531 nX
= m_pParent
->maGeometry
.nWidth
-maGeometry
.nWidth
-1-nX
;
1532 nX
+= m_pParent
->maGeometry
.nX
;
1533 nY
+= m_pParent
->maGeometry
.nY
;
1536 // adjust position to avoid off screen windows
1537 // but allow toolbars to be positioned partly off screen by the user
1538 Size aScreenSize
= GetX11SalData()->GetDisplay()->GetScreenSize( m_nScreen
);
1539 if( ! (m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) )
1541 if( nX
< (long)maGeometry
.nLeftDecoration
)
1542 nX
= maGeometry
.nLeftDecoration
;
1543 if( nY
< (long)maGeometry
.nTopDecoration
)
1544 nY
= maGeometry
.nTopDecoration
;
1545 if( (nX
+ (long)maGeometry
.nWidth
+ (long)maGeometry
.nRightDecoration
) > (long)aScreenSize
.Width() )
1546 nX
= aScreenSize
.Width() - maGeometry
.nWidth
- maGeometry
.nRightDecoration
;
1547 if( (nY
+ (long)maGeometry
.nHeight
+ (long)maGeometry
.nBottomDecoration
) > (long)aScreenSize
.Height() )
1548 nY
= aScreenSize
.Height() - maGeometry
.nHeight
- maGeometry
.nBottomDecoration
;
1552 if( nX
+ (long)maGeometry
.nWidth
< 10 )
1553 nX
= 10 - (long)maGeometry
.nWidth
;
1554 if( nY
+ (long)maGeometry
.nHeight
< 10 )
1555 nY
= 10 - (long)maGeometry
.nHeight
;
1556 if( nX
> (long)aScreenSize
.Width() - 10 )
1557 nX
= (long)aScreenSize
.Width() - 10;
1558 if( nY
> (long)aScreenSize
.Height() - 10 )
1559 nY
= (long)aScreenSize
.Height() - 10;
1562 if( nX
!= maGeometry
.nX
|| nY
!= maGeometry
.nY
)
1567 m_bDefaultPos
= false;
1569 moveWindow( maGeometry
.nX
, maGeometry
.nY
);
1571 updateScreenNumber();
1573 else if( m_bDefaultPos
)
1576 m_bDefaultPos
= false;
1578 if( bSized
&& ! bMoved
)
1579 CallCallback( SALEVENT_RESIZE
, NULL
);
1580 else if( bMoved
&& ! bSized
)
1581 CallCallback( SALEVENT_MOVE
, NULL
);
1582 else if( bMoved
&& bSized
)
1583 CallCallback( SALEVENT_MOVERESIZE
, NULL
);
1586 void GtkSalFrame::GetClientSize( long& rWidth
, long& rHeight
)
1588 if( m_pWindow
&& !(m_nState
& GDK_WINDOW_STATE_ICONIFIED
) )
1590 rWidth
= maGeometry
.nWidth
;
1591 rHeight
= maGeometry
.nHeight
;
1594 rWidth
= rHeight
= 0;
1597 void GtkSalFrame::GetWorkArea( Rectangle
& rRect
)
1599 rRect
= GetX11SalData()->GetDisplay()->getWMAdaptor()->getWorkArea( 0 );
1602 SalFrame
* GtkSalFrame::GetParent() const
1607 void GtkSalFrame::SetWindowState( const SalFrameState
* pState
)
1609 if( ! m_pWindow
|| ! pState
|| isChild( true, false ) )
1612 const ULONG nMaxGeometryMask
=
1613 SAL_FRAMESTATE_MASK_X
| SAL_FRAMESTATE_MASK_Y
|
1614 SAL_FRAMESTATE_MASK_WIDTH
| SAL_FRAMESTATE_MASK_HEIGHT
|
1615 SAL_FRAMESTATE_MASK_MAXIMIZED_X
| SAL_FRAMESTATE_MASK_MAXIMIZED_Y
|
1616 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH
| SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT
;
1618 if( (pState
->mnMask
& SAL_FRAMESTATE_MASK_STATE
) &&
1619 ! ( m_nState
& GDK_WINDOW_STATE_MAXIMIZED
) &&
1620 (pState
->mnState
& SAL_FRAMESTATE_MAXIMIZED
) &&
1621 (pState
->mnMask
& nMaxGeometryMask
) == nMaxGeometryMask
)
1623 resizeWindow( pState
->mnWidth
, pState
->mnHeight
);
1624 moveWindow( pState
->mnX
, pState
->mnY
);
1625 m_bDefaultPos
= m_bDefaultSize
= false;
1627 maGeometry
.nX
= pState
->mnMaximizedX
;
1628 maGeometry
.nY
= pState
->mnMaximizedY
;
1629 maGeometry
.nWidth
= pState
->mnMaximizedWidth
;
1630 maGeometry
.nHeight
= pState
->mnMaximizedHeight
;
1631 updateScreenNumber();
1633 m_nState
= GdkWindowState( m_nState
| GDK_WINDOW_STATE_MAXIMIZED
);
1634 m_aRestorePosSize
= Rectangle( Point( pState
->mnX
, pState
->mnY
),
1635 Size( pState
->mnWidth
, pState
->mnHeight
) );
1637 else if( pState
->mnMask
& (SAL_FRAMESTATE_MASK_X
| SAL_FRAMESTATE_MASK_Y
|
1638 SAL_FRAMESTATE_MASK_WIDTH
| SAL_FRAMESTATE_MASK_HEIGHT
) )
1640 USHORT nPosSizeFlags
= 0;
1641 long nX
= pState
->mnX
- (m_pParent
? m_pParent
->maGeometry
.nX
: 0);
1642 long nY
= pState
->mnY
- (m_pParent
? m_pParent
->maGeometry
.nY
: 0);
1643 long nWidth
= pState
->mnWidth
;
1644 long nHeight
= pState
->mnHeight
;
1645 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_X
)
1646 nPosSizeFlags
|= SAL_FRAME_POSSIZE_X
;
1648 nX
= maGeometry
.nX
- (m_pParent
? m_pParent
->maGeometry
.nX
: 0);
1649 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_Y
)
1650 nPosSizeFlags
|= SAL_FRAME_POSSIZE_Y
;
1652 nY
= maGeometry
.nY
- (m_pParent
? m_pParent
->maGeometry
.nY
: 0);
1653 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_WIDTH
)
1654 nPosSizeFlags
|= SAL_FRAME_POSSIZE_WIDTH
;
1656 nWidth
= maGeometry
.nWidth
;
1657 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_HEIGHT
)
1658 nPosSizeFlags
|= SAL_FRAME_POSSIZE_HEIGHT
;
1660 nHeight
= maGeometry
.nHeight
;
1661 SetPosSize( nX
, nY
, pState
->mnWidth
, pState
->mnHeight
, nPosSizeFlags
);
1663 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_STATE
&& ! isChild() )
1665 if( pState
->mnState
& SAL_FRAMESTATE_MAXIMIZED
)
1666 gtk_window_maximize( GTK_WINDOW(m_pWindow
) );
1668 gtk_window_unmaximize( GTK_WINDOW(m_pWindow
) );
1669 /* #i42379# there is no rollup state in GDK; and rolled up windows are
1670 * (probably depending on the WM) reported as iconified. If we iconify a
1671 * window here that was e.g. a dialog, then it will be unmapped but still
1672 * not be displayed in the task list, so it's an iconified window that
1673 * the user cannot get out of this state. So do not set the iconified state
1674 * on windows with a parent (that is transient frames) since these tend
1675 * to not be represented in an icon task list.
1677 if( (pState
->mnState
& SAL_FRAMESTATE_MINIMIZED
)
1679 gtk_window_iconify( GTK_WINDOW(m_pWindow
) );
1681 gtk_window_deiconify( GTK_WINDOW(m_pWindow
) );
1685 BOOL
GtkSalFrame::GetWindowState( SalFrameState
* pState
)
1687 pState
->mnState
= SAL_FRAMESTATE_NORMAL
;
1688 pState
->mnMask
= SAL_FRAMESTATE_MASK_STATE
;
1689 // rollup ? gtk 2.2 does not seem to support the shaded state
1690 if( (m_nState
& GDK_WINDOW_STATE_ICONIFIED
) )
1691 pState
->mnState
|= SAL_FRAMESTATE_MINIMIZED
;
1692 if( m_nState
& GDK_WINDOW_STATE_MAXIMIZED
)
1694 pState
->mnState
|= SAL_FRAMESTATE_MAXIMIZED
;
1695 pState
->mnX
= m_aRestorePosSize
.Left();
1696 pState
->mnY
= m_aRestorePosSize
.Top();
1697 pState
->mnWidth
= m_aRestorePosSize
.GetWidth();
1698 pState
->mnHeight
= m_aRestorePosSize
.GetHeight();
1699 pState
->mnMaximizedX
= maGeometry
.nX
;
1700 pState
->mnMaximizedY
= maGeometry
.nY
;
1701 pState
->mnMaximizedWidth
= maGeometry
.nWidth
;
1702 pState
->mnMaximizedHeight
= maGeometry
.nHeight
;
1703 pState
->mnMask
|= SAL_FRAMESTATE_MASK_MAXIMIZED_X
|
1704 SAL_FRAMESTATE_MASK_MAXIMIZED_Y
|
1705 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH
|
1706 SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT
;
1711 pState
->mnX
= maGeometry
.nX
;
1712 pState
->mnY
= maGeometry
.nY
;
1713 pState
->mnWidth
= maGeometry
.nWidth
;
1714 pState
->mnHeight
= maGeometry
.nHeight
;
1716 pState
->mnMask
|= SAL_FRAMESTATE_MASK_X
|
1717 SAL_FRAMESTATE_MASK_Y
|
1718 SAL_FRAMESTATE_MASK_WIDTH
|
1719 SAL_FRAMESTATE_MASK_HEIGHT
;
1724 void GtkSalFrame::moveToScreen( int nScreen
)
1729 if( nScreen
< 0 || nScreen
>= gdk_display_get_n_screens( getGdkDisplay() ) )
1730 nScreen
= m_nScreen
;
1731 if( nScreen
== m_nScreen
)
1734 GdkScreen
* pScreen
= gdk_display_get_screen( getGdkDisplay(), nScreen
);
1737 m_nScreen
= nScreen
;
1738 gtk_window_set_screen( GTK_WINDOW(m_pWindow
), pScreen
);
1739 // realize the window, we need an XWindow id
1740 gtk_widget_realize( m_pWindow
);
1741 // update system data
1742 GtkSalDisplay
* pDisp
= getDisplay();
1743 m_aSystemData
.aWindow
= GDK_WINDOW_XWINDOW(m_pWindow
->window
);
1744 m_aSystemData
.pVisual
= pDisp
->GetVisual( m_nScreen
).GetVisual();
1745 m_aSystemData
.nScreen
= nScreen
;
1746 m_aSystemData
.nDepth
= pDisp
->GetVisual( m_nScreen
).GetDepth();
1747 m_aSystemData
.aColormap
= pDisp
->GetColormap( m_nScreen
).GetXColormap();
1748 m_aSystemData
.pAppContext
= NULL
;
1749 m_aSystemData
.aShellWindow
= m_aSystemData
.aWindow
;
1750 // update graphics if necessary
1751 for( unsigned int i
= 0; i
< sizeof(m_aGraphics
)/sizeof(m_aGraphics
[0]); i
++ )
1753 if( m_aGraphics
[i
].bInUse
)
1754 m_aGraphics
[i
].pGraphics
->SetDrawable( GDK_WINDOW_XWINDOW(m_pWindow
->window
), m_nScreen
);
1756 updateScreenNumber();
1759 if( m_pParent
&& m_pParent
->m_nScreen
!= m_nScreen
)
1761 std::list
< GtkSalFrame
* > aChildren
= m_aChildren
;
1762 for( std::list
< GtkSalFrame
* >::iterator it
= aChildren
.begin(); it
!= aChildren
.end(); ++it
)
1763 (*it
)->moveToScreen( m_nScreen
);
1765 // FIXME: SalObjects
1768 void GtkSalFrame::SetScreenNumber( unsigned int nNewScreen
)
1770 if( nNewScreen
== maGeometry
.nScreenNumber
)
1773 if( m_pWindow
&& ! isChild() )
1775 GtkSalDisplay
* pDisp
= getDisplay();
1776 if( pDisp
->IsXinerama() && pDisp
->GetXineramaScreens().size() > 1 )
1778 if( nNewScreen
>= pDisp
->GetXineramaScreens().size() )
1781 Rectangle
aOldScreenRect( pDisp
->GetXineramaScreens()[maGeometry
.nScreenNumber
] );
1782 Rectangle
aNewScreenRect( pDisp
->GetXineramaScreens()[nNewScreen
] );
1783 bool bVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
1786 maGeometry
.nX
= aNewScreenRect
.Left() + (maGeometry
.nX
- aOldScreenRect
.Left());
1787 maGeometry
.nY
= aNewScreenRect
.Top() + (maGeometry
.nY
- aOldScreenRect
.Top());
1788 createNewWindow( None
, false, m_nScreen
);
1789 gtk_window_move( GTK_WINDOW(m_pWindow
), maGeometry
.nX
, maGeometry
.nY
);
1792 maGeometry
.nScreenNumber
= nNewScreen
;
1794 else if( sal_Int32(nNewScreen
) < pDisp
->GetScreenCount() )
1796 moveToScreen( (int)nNewScreen
);
1797 maGeometry
.nScreenNumber
= nNewScreen
;
1798 gtk_window_move( GTK_WINDOW(m_pWindow
), maGeometry
.nX
, maGeometry
.nY
);
1803 void GtkSalFrame::ShowFullScreen( BOOL bFullScreen
, sal_Int32 nScreen
)
1805 if( m_pWindow
&& ! isChild() )
1807 GtkSalDisplay
* pDisp
= getDisplay();
1809 if( pDisp
->IsXinerama() && pDisp
->GetXineramaScreens().size() > 1 )
1813 m_aRestorePosSize
= Rectangle( Point( maGeometry
.nX
, maGeometry
.nY
),
1814 Size( maGeometry
.nWidth
, maGeometry
.nHeight
) );
1815 // workaround different window managers have different opinions about
1816 // _NET_WM_STATE_FULLSCREEN (Metacity <-> KWin)
1817 bool bVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
1820 m_nStyle
|= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
;
1821 createNewWindow( None
, false, m_nScreen
);
1822 Rectangle aNewPosSize
;
1823 if( nScreen
< 0 || nScreen
>= static_cast<int>(pDisp
->GetXineramaScreens().size()) )
1824 aNewPosSize
= Rectangle( Point( 0, 0 ), pDisp
->GetScreenSize(m_nScreen
) );
1826 aNewPosSize
= pDisp
->GetXineramaScreens()[ nScreen
];
1827 gtk_window_resize( GTK_WINDOW(m_pWindow
),
1828 maGeometry
.nWidth
= aNewPosSize
.GetWidth(),
1829 maGeometry
.nHeight
= aNewPosSize
.GetHeight() );
1830 gtk_window_move( GTK_WINDOW(m_pWindow
),
1831 maGeometry
.nX
= aNewPosSize
.Left(),
1832 maGeometry
.nY
= aNewPosSize
.Top() );
1838 bool bVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
1841 m_nStyle
&= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
;
1842 createNewWindow( None
, false, m_nScreen
);
1843 if( ! m_aRestorePosSize
.IsEmpty() )
1845 gtk_window_resize( GTK_WINDOW(m_pWindow
),
1846 maGeometry
.nWidth
= m_aRestorePosSize
.GetWidth(),
1847 maGeometry
.nHeight
= m_aRestorePosSize
.GetHeight() );
1848 gtk_window_move( GTK_WINDOW(m_pWindow
),
1849 maGeometry
.nX
= m_aRestorePosSize
.Left(),
1850 maGeometry
.nY
= m_aRestorePosSize
.Top() );
1851 m_aRestorePosSize
= Rectangle();
1861 if( !(m_nStyle
& SAL_FRAME_STYLE_SIZEABLE
) )
1862 gtk_window_set_resizable( GTK_WINDOW(m_pWindow
), TRUE
);
1863 gtk_window_fullscreen( GTK_WINDOW(m_pWindow
) );
1864 moveToScreen( nScreen
);
1865 Size aScreenSize
= pDisp
->GetScreenSize( m_nScreen
);
1868 maGeometry
.nWidth
= aScreenSize
.Width();
1869 maGeometry
.nHeight
= aScreenSize
.Height();
1873 gtk_window_unfullscreen( GTK_WINDOW(m_pWindow
) );
1874 if( !(m_nStyle
& SAL_FRAME_STYLE_SIZEABLE
) )
1875 gtk_window_set_resizable( GTK_WINDOW(m_pWindow
), FALSE
);
1876 moveToScreen( nScreen
);
1879 m_bDefaultPos
= m_bDefaultSize
= false;
1880 updateScreenNumber();
1881 CallCallback( SALEVENT_MOVERESIZE
, NULL
);
1883 m_bFullscreen
= bFullScreen
;
1886 /* definitions from xautolock.c (pl15) */
1887 #define XAUTOLOCK_DISABLE 1
1888 #define XAUTOLOCK_ENABLE 2
1890 void GtkSalFrame::setAutoLock( bool bLock
)
1895 GdkScreen
*pScreen
= gtk_window_get_screen( GTK_WINDOW(m_pWindow
) );
1896 GdkDisplay
*pDisplay
= gdk_screen_get_display( pScreen
);
1897 GdkWindow
*pRootWin
= gdk_screen_get_root_window( pScreen
);
1899 Atom nAtom
= XInternAtom( GDK_DISPLAY_XDISPLAY( pDisplay
),
1900 "XAUTOLOCK_MESSAGE", False
);
1902 int nMessage
= bLock
? XAUTOLOCK_ENABLE
: XAUTOLOCK_DISABLE
;
1904 XChangeProperty( GDK_DISPLAY_XDISPLAY( pDisplay
),
1905 GDK_WINDOW_XID( pRootWin
),
1908 (unsigned char*)&nMessage
,
1909 sizeof( nMessage
) );
1913 /** cookie is returned as an unsigned integer */
1915 dbus_inhibit_gss (const gchar
*appname
,
1916 const gchar
*reason
)
1920 GError
*error
= NULL
;
1921 DBusGProxy
*proxy
= NULL
;
1922 DBusGConnection
*session_connection
= NULL
;
1924 /* get the DBUS session connection */
1925 session_connection
= dbus_g_bus_get (DBUS_BUS_SESSION
, &error
);
1926 if (error
!= NULL
) {
1927 g_warning ("DBUS cannot connect : %s", error
->message
);
1928 g_error_free (error
);
1932 /* get the proxy with gnome-screensaver */
1933 proxy
= dbus_g_proxy_new_for_name (session_connection
,
1936 GSS_DBUS_INTERFACE
);
1937 if (proxy
== NULL
) {
1938 g_warning ("Could not get DBUS proxy: %s", GSS_DBUS_SERVICE
);
1942 res
= dbus_g_proxy_call (proxy
,
1944 G_TYPE_STRING
, appname
,
1945 G_TYPE_STRING
, reason
,
1947 G_TYPE_UINT
, &cookie
,
1950 /* check the return value */
1953 g_warning ("Inhibit method failed");
1956 /* check the error value */
1957 if (error
!= NULL
) {
1958 g_warning ("Inhibit problem : %s", error
->message
);
1959 g_error_free (error
);
1963 g_object_unref (G_OBJECT (proxy
));
1968 dbus_uninhibit_gss (guint cookie
)
1971 GError
*error
= NULL
;
1972 DBusGProxy
*proxy
= NULL
;
1973 DBusGConnection
*session_connection
= NULL
;
1975 /* cookies have to be positive as unsigned */
1977 g_warning ("Invalid cookie");
1981 /* get the DBUS session connection */
1982 session_connection
= dbus_g_bus_get (DBUS_BUS_SESSION
, &error
);
1984 g_warning ("DBUS cannot connect : %s", error
->message
);
1985 g_error_free (error
);
1989 /* get the proxy with gnome-screensaver */
1990 proxy
= dbus_g_proxy_new_for_name (session_connection
,
1993 GSS_DBUS_INTERFACE
);
1994 if (proxy
== NULL
) {
1995 g_warning ("Could not get DBUS proxy: %s", GSS_DBUS_SERVICE
);
1999 res
= dbus_g_proxy_call (proxy
,
2002 G_TYPE_UINT
, cookie
,
2006 /* check the return value */
2008 g_warning ("UnInhibit method failed");
2011 /* check the error value */
2012 if (error
!= NULL
) {
2013 g_warning ("Inhibit problem : %s", error
->message
);
2014 g_error_free (error
);
2017 g_object_unref (G_OBJECT (proxy
));
2021 void GtkSalFrame::StartPresentation( BOOL bStart
)
2023 Display
*pDisplay
= GDK_DISPLAY_XDISPLAY( getGdkDisplay() );
2025 setAutoLock( !bStart
);
2027 int nTimeout
, nInterval
, bPreferBlanking
, bAllowExposures
;
2029 XGetScreenSaver( pDisplay
, &nTimeout
, &nInterval
,
2030 &bPreferBlanking
, &bAllowExposures
);
2035 m_nSavedScreenSaverTimeout
= nTimeout
;
2036 XResetScreenSaver( pDisplay
);
2037 XSetScreenSaver( pDisplay
, 0, nInterval
,
2038 bPreferBlanking
, bAllowExposures
);
2041 m_nGSSCookie
= dbus_inhibit_gss(g_get_application_name(), "presentation");
2046 if( m_nSavedScreenSaverTimeout
)
2047 XSetScreenSaver( pDisplay
, m_nSavedScreenSaverTimeout
,
2048 nInterval
, bPreferBlanking
,
2050 m_nSavedScreenSaverTimeout
= 0;
2052 dbus_uninhibit_gss(m_nGSSCookie
);
2057 void GtkSalFrame::SetAlwaysOnTop( BOOL
/*bOnTop*/ )
2061 void GtkSalFrame::ToTop( USHORT nFlags
)
2065 if( isChild( false, true ) )
2066 gtk_widget_grab_focus( m_pWindow
);
2067 else if( GTK_WIDGET_MAPPED( m_pWindow
) )
2069 if( ! (nFlags
& SAL_FRAME_TOTOP_GRABFOCUS_ONLY
) )
2070 gtk_window_present( GTK_WINDOW(m_pWindow
) );
2073 // gdk_window_focus( m_pWindow->window, gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window) );
2074 /* #i99360# ugly workaround an X11 library bug */
2075 guint32 nUserTime
= getDisplay()->GetLastUserEventTime( true );
2076 gdk_window_focus( m_pWindow
->window
, nUserTime
);
2078 /* need to do an XSetInputFocus here because
2079 * gdk_window_focus will ask a EWMH compliant WM to put the focus
2080 * to our window - which it of course won't since our input hint
2083 if( (m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) )
2084 XSetInputFocus( getDisplay()->GetDisplay(), GDK_WINDOW_XWINDOW( m_pWindow
->window
), RevertToParent
, CurrentTime
);
2088 if( nFlags
& SAL_FRAME_TOTOP_RESTOREWHENMIN
)
2089 gtk_window_present( GTK_WINDOW(m_pWindow
) );
2094 void GtkSalFrame::SetPointer( PointerStyle ePointerStyle
)
2096 if( m_pWindow
&& ePointerStyle
!= m_ePointerStyle
)
2098 m_ePointerStyle
= ePointerStyle
;
2099 GdkCursor
*pCursor
= getDisplay()->getCursor( ePointerStyle
);
2100 gdk_window_set_cursor( m_pWindow
->window
, pCursor
);
2101 m_pCurrentCursor
= pCursor
;
2103 // #i80791# use grabPointer the same way as CaptureMouse, respective float grab
2104 if( getDisplay()->MouseCaptured( this ) )
2105 grabPointer( TRUE
, FALSE
);
2106 else if( m_nFloats
> 0 )
2107 grabPointer( TRUE
, TRUE
);
2111 void GtkSalFrame::grabPointer( BOOL bGrab
, BOOL bOwnerEvents
)
2117 bool bUseGdkGrab
= true;
2118 if( getDisplay()->getHaveSystemChildFrame() )
2120 const std::list
< SalFrame
* >& rFrames
= getDisplay()->getFrames();
2121 for( std::list
< SalFrame
* >::const_iterator it
= rFrames
.begin(); it
!= rFrames
.end(); ++it
)
2123 const GtkSalFrame
* pFrame
= static_cast< const GtkSalFrame
* >(*it
);
2124 if( pFrame
->m_bWindowIsGtkPlug
)
2126 bUseGdkGrab
= false;
2133 const int nMask
= ( GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK
);
2135 gdk_pointer_grab( m_pWindow
->window
, bOwnerEvents
,
2136 (GdkEventMask
) nMask
, NULL
, m_pCurrentCursor
,
2141 // FIXME: for some unknown reason gdk_pointer_grab does not
2142 // really produce owner events for GtkPlug windows
2143 // the cause is yet unknown
2145 // this is of course a bad hack, especially as we cannot
2146 // set the right cursor this way
2147 XGrabPointer( getDisplay()->GetDisplay(),
2148 GDK_WINDOW_XWINDOW( m_pWindow
->window
),
2150 PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
,
2162 // Two GdkDisplays may be open
2163 gdk_display_pointer_ungrab( getGdkDisplay(), GDK_CURRENT_TIME
);
2168 void GtkSalFrame::CaptureMouse( BOOL bCapture
)
2170 getDisplay()->CaptureMouse( bCapture
? this : NULL
);
2173 void GtkSalFrame::SetPointerPos( long nX
, long nY
)
2175 GtkSalFrame
* pFrame
= this;
2176 while( pFrame
&& pFrame
->isChild( false, true ) )
2177 pFrame
= pFrame
->m_pParent
;
2181 GdkScreen
*pScreen
= gtk_window_get_screen( GTK_WINDOW(pFrame
->m_pWindow
) );
2182 GdkDisplay
*pDisplay
= gdk_screen_get_display( pScreen
);
2184 /* #87921# when the application tries to center the mouse in the dialog the
2185 * window isn't mapped already. So use coordinates relative to the root window.
2187 unsigned int nWindowLeft
= maGeometry
.nX
+ nX
;
2188 unsigned int nWindowTop
= maGeometry
.nY
+ nY
;
2190 XWarpPointer( GDK_DISPLAY_XDISPLAY (pDisplay
), None
,
2191 GDK_WINDOW_XID (gdk_screen_get_root_window( pScreen
) ),
2192 0, 0, 0, 0, nWindowLeft
, nWindowTop
);
2193 // #i38648# ask for the next motion hint
2195 GdkModifierType mask
;
2196 gdk_window_get_pointer( pFrame
->m_pWindow
->window
, &x
, &y
, &mask
);
2199 void GtkSalFrame::Flush()
2201 #ifdef HAVE_A_RECENT_GTK
2202 gdk_display_flush( getGdkDisplay() );
2204 XFlush (GDK_DISPLAY_XDISPLAY (getGdkDisplay()));
2208 void GtkSalFrame::Sync()
2210 gdk_display_sync( getGdkDisplay() );
2213 String
GtkSalFrame::GetSymbolKeyName( const String
&, USHORT nKeyCode
)
2215 return getDisplay()->GetKeyName( nKeyCode
);
2218 String
GtkSalFrame::GetKeyName( USHORT nKeyCode
)
2220 return getDisplay()->GetKeyName( nKeyCode
);
2223 GdkDisplay
*GtkSalFrame::getGdkDisplay()
2225 return static_cast<GtkSalDisplay
*>(GetX11SalData()->GetDisplay())->GetGdkDisplay();
2228 GtkSalDisplay
*GtkSalFrame::getDisplay()
2230 return static_cast<GtkSalDisplay
*>(GetX11SalData()->GetDisplay());
2233 SalFrame::SalPointerState
GtkSalFrame::GetPointerState()
2235 SalPointerState aState
;
2238 GdkModifierType aMask
;
2239 gdk_display_get_pointer( getGdkDisplay(), &pScreen
, &x
, &y
, &aMask
);
2240 aState
.maPos
= Point( x
- maGeometry
.nX
, y
- maGeometry
.nY
);
2241 aState
.mnState
= GetMouseModCode( aMask
);
2245 SalFrame::SalIndicatorState
GtkSalFrame::GetIndicatorState()
2247 SalIndicatorState aState
;
2248 aState
.mnState
= GetX11SalData()->GetDisplay()->GetIndicatorState();
2252 void GtkSalFrame::SimulateKeyPress( USHORT nKeyCode
)
2254 GetX11SalData()->GetDisplay()->SimulateKeyPress(nKeyCode
);
2257 void GtkSalFrame::SetInputContext( SalInputContext
* pContext
)
2262 if( ! (pContext
->mnOptions
& SAL_INPUTCONTEXT_TEXT
) )
2265 // create a new im context
2266 if( ! m_pIMHandler
)
2267 m_pIMHandler
= new IMHandler( this );
2268 m_pIMHandler
->setInputContext( pContext
);
2271 void GtkSalFrame::EndExtTextInput( USHORT nFlags
)
2274 m_pIMHandler
->endExtTextInput( nFlags
);
2277 BOOL
GtkSalFrame::MapUnicodeToKeyCode( sal_Unicode
, LanguageType
, KeyCode
& )
2279 // not supported yet
2283 LanguageType
GtkSalFrame::GetInputLanguage()
2285 return LANGUAGE_DONTKNOW
;
2288 SalBitmap
* GtkSalFrame::SnapShot()
2293 X11SalBitmap
*pBmp
= new X11SalBitmap
;
2294 GdkWindow
*pWin
= m_pWindow
->window
;
2295 if( pBmp
->SnapShot( GDK_DISPLAY_XDISPLAY( getGdkDisplay() ),
2296 GDK_WINDOW_XID( pWin
) ) )
2304 void GtkSalFrame::UpdateSettings( AllSettings
& rSettings
)
2309 GtkSalGraphics
* pGraphics
= static_cast<GtkSalGraphics
*>(m_aGraphics
[0].pGraphics
);
2310 bool bFreeGraphics
= false;
2313 pGraphics
= static_cast<GtkSalGraphics
*>(GetGraphics());
2314 bFreeGraphics
= true;
2317 pGraphics
->updateSettings( rSettings
);
2320 ReleaseGraphics( pGraphics
);
2323 void GtkSalFrame::Beep( SoundType eType
)
2329 gdk_display_beep( getGdkDisplay() );
2336 const SystemEnvData
* GtkSalFrame::GetSystemData() const
2338 return &m_aSystemData
;
2341 void GtkSalFrame::SetParent( SalFrame
* pNewParent
)
2344 m_pParent
->m_aChildren
.remove( this );
2345 m_pParent
= static_cast<GtkSalFrame
*>(pNewParent
);
2347 m_pParent
->m_aChildren
.push_back( this );
2349 gtk_window_set_transient_for( GTK_WINDOW(m_pWindow
),
2350 (m_pParent
&& ! m_pParent
->isChild(true,false)) ? GTK_WINDOW(m_pParent
->m_pWindow
) : NULL
2354 void GtkSalFrame::createNewWindow( XLIB_Window aNewParent
, bool bXEmbed
, int nScreen
)
2356 bool bWasVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
2360 if( nScreen
< 0 || nScreen
>= getDisplay()->GetScreenCount() )
2361 nScreen
= m_nScreen
;
2363 SystemParentData aParentData
;
2364 aParentData
.aWindow
= aNewParent
;
2365 aParentData
.bXEmbedSupport
= bXEmbed
;
2366 if( aNewParent
== None
)
2368 aNewParent
= getDisplay()->GetRootWindow(nScreen
);
2369 aParentData
.aWindow
= None
;
2370 aParentData
.bXEmbedSupport
= false;
2374 // is new parent a root window ?
2375 Display
* pDisp
= getDisplay()->GetDisplay();
2376 int nScreens
= getDisplay()->GetScreenCount();
2377 for( int i
= 0; i
< nScreens
; i
++ )
2379 if( aNewParent
== RootWindow( pDisp
, i
) )
2382 aParentData
.aWindow
= None
;
2383 aParentData
.bXEmbedSupport
= false;
2389 // first deinit frame
2392 delete m_pIMHandler
;
2393 m_pIMHandler
= NULL
;
2396 gdk_region_destroy( m_pRegion
);
2397 if( m_pFixedContainer
)
2398 gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer
) );
2400 gtk_widget_destroy( m_pWindow
);
2401 if( m_pForeignParent
)
2402 g_object_unref( G_OBJECT(m_pForeignParent
) );
2403 if( m_pForeignTopLevel
)
2404 g_object_unref( G_OBJECT(m_pForeignTopLevel
) );
2407 m_bDefaultPos
= m_bDefaultSize
= false;
2408 if( aParentData
.aWindow
!= None
)
2410 m_nStyle
|= SAL_FRAME_STYLE_PLUG
;
2411 Init( &aParentData
);
2415 m_nStyle
&= ~SAL_FRAME_STYLE_PLUG
;
2416 Init( (m_pParent
&& m_pParent
->m_nScreen
== m_nScreen
) ? m_pParent
: NULL
, m_nStyle
);
2420 for( unsigned int i
= 0; i
< sizeof(m_aGraphics
)/sizeof(m_aGraphics
[0]); i
++ )
2422 if( m_aGraphics
[i
].bInUse
)
2424 m_aGraphics
[i
].pGraphics
->SetDrawable( GDK_WINDOW_XWINDOW(m_pWindow
->window
), m_nScreen
);
2425 m_aGraphics
[i
].pGraphics
->SetWindow( m_pWindow
);
2429 if( m_aTitle
.Len() )
2430 SetTitle( m_aTitle
);
2435 std::list
< GtkSalFrame
* > aChildren
= m_aChildren
;
2436 m_aChildren
.clear();
2437 for( std::list
< GtkSalFrame
* >::iterator it
= aChildren
.begin(); it
!= aChildren
.end(); ++it
)
2438 (*it
)->createNewWindow( None
, false, m_nScreen
);
2440 // FIXME: SalObjects
2443 bool GtkSalFrame::SetPluginParent( SystemParentData
* pSysParent
)
2445 if( pSysParent
) // this may be the first system child frame now
2446 getDisplay()->setHaveSystemChildFrame();
2447 createNewWindow( pSysParent
->aWindow
, (pSysParent
->nSize
> sizeof(long)) ? pSysParent
->bXEmbedSupport
: false, m_nScreen
);
2451 void GtkSalFrame::ResetClipRegion()
2454 gdk_window_shape_combine_region( m_pWindow
->window
, NULL
, 0, 0 );
2457 void GtkSalFrame::BeginSetClipRegion( ULONG
)
2460 gdk_region_destroy( m_pRegion
);
2461 m_pRegion
= gdk_region_new();
2464 void GtkSalFrame::UnionClipRegion( long nX
, long nY
, long nWidth
, long nHeight
)
2471 aRect
.width
= nWidth
;
2472 aRect
.height
= nHeight
;
2474 gdk_region_union_with_rect( m_pRegion
, &aRect
);
2478 void GtkSalFrame::EndSetClipRegion()
2480 if( m_pWindow
&& m_pRegion
)
2481 gdk_window_shape_combine_region( m_pWindow
->window
, m_pRegion
, 0, 0 );
2484 bool GtkSalFrame::Dispatch( const XEvent
* pEvent
)
2486 bool bContinueDispatch
= true;
2488 if( pEvent
->type
== PropertyNotify
)
2490 vcl_sal::WMAdaptor
* pAdaptor
= getDisplay()->getWMAdaptor();
2491 Atom nDesktopAtom
= pAdaptor
->getAtom( vcl_sal::WMAdaptor::NET_WM_DESKTOP
);
2492 if( pEvent
->xproperty
.atom
== nDesktopAtom
&&
2493 pEvent
->xproperty
.state
== PropertyNewValue
)
2495 m_nWorkArea
= pAdaptor
->getWindowWorkArea( GDK_WINDOW_XWINDOW( m_pWindow
->window
) );
2498 else if( pEvent
->type
== ConfigureNotify
)
2500 if( m_pForeignParent
&& pEvent
->xconfigure
.window
== m_aForeignParentWindow
)
2502 bContinueDispatch
= false;
2503 gtk_window_resize( GTK_WINDOW(m_pWindow
), pEvent
->xconfigure
.width
, pEvent
->xconfigure
.height
);
2504 if( ( sal::static_int_cast
< int >(maGeometry
.nWidth
) !=
2505 pEvent
->xconfigure
.width
) ||
2506 ( sal::static_int_cast
< int >(maGeometry
.nHeight
) !=
2507 pEvent
->xconfigure
.height
) )
2509 maGeometry
.nWidth
= pEvent
->xconfigure
.width
;
2510 maGeometry
.nHeight
= pEvent
->xconfigure
.height
;
2512 getDisplay()->SendInternalEvent( this, NULL
, SALEVENT_RESIZE
);
2515 else if( m_pForeignTopLevel
&& pEvent
->xconfigure
.window
== m_aForeignTopLevelWindow
)
2517 bContinueDispatch
= false;
2521 XTranslateCoordinates( getDisplay()->GetDisplay(),
2522 GDK_WINDOW_XWINDOW( m_pWindow
->window
),
2523 getDisplay()->GetRootWindow( getDisplay()->GetDefaultScreenNumber() ),
2527 if( x
!= maGeometry
.nX
|| y
!= maGeometry
.nY
)
2531 getDisplay()->SendInternalEvent( this, NULL
, SALEVENT_MOVE
);
2535 else if( pEvent
->type
== ClientMessage
&&
2536 pEvent
->xclient
.message_type
== getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED
) &&
2537 pEvent
->xclient
.window
== GDK_WINDOW_XWINDOW(m_pWindow
->window
) &&
2541 // FIXME: this should not be necessary, GtkPlug should do this
2542 // transparently for us
2543 if( pEvent
->xclient
.data
.l
[1] == 1 || // XEMBED_WINDOW_ACTIVATE
2544 pEvent
->xclient
.data
.l
[1] == 2 // XEMBED_WINDOW_DEACTIVATE
2547 GdkEventFocus aEvent
;
2548 aEvent
.type
= GDK_FOCUS_CHANGE
;
2549 aEvent
.window
= m_pWindow
->window
;
2550 aEvent
.send_event
= TRUE
;
2551 aEvent
.in
= (pEvent
->xclient
.data
.l
[1] == 1);
2552 signalFocus( m_pWindow
, &aEvent
, this );
2556 return bContinueDispatch
;
2559 void GtkSalFrame::SetBackgroundBitmap( SalBitmap
* pBitmap
)
2561 if( m_hBackgroundPixmap
)
2563 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
2564 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
2566 XFreePixmap( getDisplay()->GetDisplay(), m_hBackgroundPixmap
);
2567 m_hBackgroundPixmap
= None
;
2571 X11SalBitmap
* pBM
= static_cast<X11SalBitmap
*>(pBitmap
);
2572 Size aSize
= pBM
->GetSize();
2573 if( aSize
.Width() && aSize
.Height() )
2575 m_hBackgroundPixmap
=
2576 XCreatePixmap( getDisplay()->GetDisplay(),
2577 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
2580 getDisplay()->GetVisual(m_nScreen
).GetDepth() );
2581 if( m_hBackgroundPixmap
)
2583 SalTwoRect aTwoRect
;
2584 aTwoRect
.mnSrcX
= aTwoRect
.mnSrcY
= aTwoRect
.mnDestX
= aTwoRect
.mnDestY
= 0;
2585 aTwoRect
.mnSrcWidth
= aTwoRect
.mnDestWidth
= aSize
.Width();
2586 aTwoRect
.mnSrcHeight
= aTwoRect
.mnDestHeight
= aSize
.Height();
2587 pBM
->ImplDraw( m_hBackgroundPixmap
,
2589 getDisplay()->GetVisual(m_nScreen
).GetDepth(),
2591 getDisplay()->GetCopyGC(m_nScreen
) );
2592 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
2593 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
2594 m_hBackgroundPixmap
);
2600 gboolean
GtkSalFrame::signalButton( GtkWidget
*, GdkEventButton
* pEvent
, gpointer frame
)
2602 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2603 SalMouseEvent aEvent
;
2604 USHORT nEventType
= 0;
2605 switch( pEvent
->type
)
2607 case GDK_BUTTON_PRESS
:
2608 nEventType
= SALEVENT_MOUSEBUTTONDOWN
;
2610 case GDK_BUTTON_RELEASE
:
2611 nEventType
= SALEVENT_MOUSEBUTTONUP
;
2616 switch( pEvent
->button
)
2618 case 1: aEvent
.mnButton
= MOUSE_LEFT
; break;
2619 case 2: aEvent
.mnButton
= MOUSE_MIDDLE
; break;
2620 case 3: aEvent
.mnButton
= MOUSE_RIGHT
; break;
2621 default: return FALSE
;
2623 aEvent
.mnTime
= pEvent
->time
;
2624 aEvent
.mnX
= (long)pEvent
->x_root
- pThis
->maGeometry
.nX
;
2625 aEvent
.mnY
= (long)pEvent
->y_root
- pThis
->maGeometry
.nY
;
2626 aEvent
.mnCode
= GetMouseModCode( pEvent
->state
);
2628 bool bClosePopups
= false;
2629 if( pEvent
->type
== GDK_BUTTON_PRESS
&&
2630 (pThis
->m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) == 0
2635 // close popups if user clicks outside our application
2637 bClosePopups
= (gdk_display_get_window_at_pointer( pThis
->getGdkDisplay(), &x
, &y
) == NULL
);
2639 /* #i30306# release implicit pointer grab if no popups are open; else
2640 * Drag cannot grab the pointer and will fail.
2642 if( m_nFloats
< 1 || bClosePopups
)
2643 gdk_display_pointer_ungrab( pThis
->getGdkDisplay(), GDK_CURRENT_TIME
);
2648 if( pThis
->m_bWindowIsGtkPlug
&&
2649 pEvent
->type
== GDK_BUTTON_PRESS
&&
2650 pEvent
->button
== 1 )
2652 pThis
->askForXEmbedFocus( pEvent
->time
);
2655 // --- RTL --- (mirror mouse pos)
2656 if( Application::GetSettings().GetLayoutRTL() )
2657 aEvent
.mnX
= pThis
->maGeometry
.nWidth
-1-aEvent
.mnX
;
2659 vcl::DeletionListener
aDel( pThis
);
2661 pThis
->CallCallback( nEventType
, &aEvent
);
2663 if( ! aDel
.isDeleted() )
2667 ImplSVData
* pSVData
= ImplGetSVData();
2668 if ( pSVData
->maWinData
.mpFirstFloat
)
2670 static const char* pEnv
= getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
2671 if ( !(pSVData
->maWinData
.mpFirstFloat
->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE
) && !(pEnv
&& *pEnv
) )
2672 pSVData
->maWinData
.mpFirstFloat
->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL
| FLOATWIN_POPUPMODEEND_CLOSEALL
);
2676 if( ! aDel
.isDeleted() )
2678 int frame_x
= (int)(pEvent
->x_root
- pEvent
->x
);
2679 int frame_y
= (int)(pEvent
->y_root
- pEvent
->y
);
2680 if( frame_x
!= pThis
->maGeometry
.nX
|| frame_y
!= pThis
->maGeometry
.nY
)
2682 pThis
->maGeometry
.nX
= frame_x
;
2683 pThis
->maGeometry
.nY
= frame_y
;
2684 pThis
->CallCallback( SALEVENT_MOVE
, NULL
);
2692 gboolean
GtkSalFrame::signalScroll( GtkWidget
*, GdkEvent
* pEvent
, gpointer frame
)
2694 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2695 GdkEventScroll
* pSEvent
= (GdkEventScroll
*)pEvent
;
2697 static ULONG nLines
= 0;
2700 char* pEnv
= getenv( "SAL_WHEELLINES" );
2701 nLines
= pEnv
? atoi( pEnv
) : 3;
2703 nLines
= SAL_WHEELMOUSE_EVENT_PAGESCROLL
;
2706 bool bNeg
= (pSEvent
->direction
== GDK_SCROLL_DOWN
|| pSEvent
->direction
== GDK_SCROLL_RIGHT
);
2707 SalWheelMouseEvent aEvent
;
2708 aEvent
.mnTime
= pSEvent
->time
;
2709 aEvent
.mnX
= (ULONG
)pSEvent
->x
;
2710 aEvent
.mnY
= (ULONG
)pSEvent
->y
;
2711 aEvent
.mnDelta
= bNeg
? -120 : 120;
2712 aEvent
.mnNotchDelta
= bNeg
? -1 : 1;
2713 aEvent
.mnScrollLines
= nLines
;
2714 aEvent
.mnCode
= GetMouseModCode( pSEvent
->state
);
2715 aEvent
.mbHorz
= (pSEvent
->direction
== GDK_SCROLL_LEFT
|| pSEvent
->direction
== GDK_SCROLL_RIGHT
);
2719 // --- RTL --- (mirror mouse pos)
2720 if( Application::GetSettings().GetLayoutRTL() )
2721 aEvent
.mnX
= pThis
->maGeometry
.nWidth
-1-aEvent
.mnX
;
2723 pThis
->CallCallback( SALEVENT_WHEELMOUSE
, &aEvent
);
2728 gboolean
GtkSalFrame::signalMotion( GtkWidget
*, GdkEventMotion
* pEvent
, gpointer frame
)
2730 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2732 SalMouseEvent aEvent
;
2733 aEvent
.mnTime
= pEvent
->time
;
2734 aEvent
.mnX
= (long)pEvent
->x_root
- pThis
->maGeometry
.nX
;
2735 aEvent
.mnY
= (long)pEvent
->y_root
- pThis
->maGeometry
.nY
;
2736 aEvent
.mnCode
= GetMouseModCode( pEvent
->state
);
2737 aEvent
.mnButton
= 0;
2742 // --- RTL --- (mirror mouse pos)
2743 if( Application::GetSettings().GetLayoutRTL() )
2744 aEvent
.mnX
= pThis
->maGeometry
.nWidth
-1-aEvent
.mnX
;
2746 vcl::DeletionListener
aDel( pThis
);
2748 pThis
->CallCallback( SALEVENT_MOUSEMOVE
, &aEvent
);
2750 if( ! aDel
.isDeleted() )
2752 int frame_x
= (int)(pEvent
->x_root
- pEvent
->x
);
2753 int frame_y
= (int)(pEvent
->y_root
- pEvent
->y
);
2754 if( frame_x
!= pThis
->maGeometry
.nX
|| frame_y
!= pThis
->maGeometry
.nY
)
2756 pThis
->maGeometry
.nX
= frame_x
;
2757 pThis
->maGeometry
.nY
= frame_y
;
2758 pThis
->CallCallback( SALEVENT_MOVE
, NULL
);
2761 if( ! aDel
.isDeleted() )
2763 // ask for the next hint
2765 GdkModifierType mask
;
2766 gdk_window_get_pointer( GTK_WIDGET(pThis
->m_pWindow
)->window
, &x
, &y
, &mask
);
2773 gboolean
GtkSalFrame::signalCrossing( GtkWidget
*, GdkEventCrossing
* pEvent
, gpointer frame
)
2775 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2776 SalMouseEvent aEvent
;
2777 aEvent
.mnTime
= pEvent
->time
;
2778 aEvent
.mnX
= (long)pEvent
->x_root
- pThis
->maGeometry
.nX
;
2779 aEvent
.mnY
= (long)pEvent
->y_root
- pThis
->maGeometry
.nY
;
2780 aEvent
.mnCode
= GetMouseModCode( pEvent
->state
);
2781 aEvent
.mnButton
= 0;
2784 pThis
->CallCallback( (pEvent
->type
== GDK_ENTER_NOTIFY
) ? SALEVENT_MOUSEMOVE
: SALEVENT_MOUSELEAVE
, &aEvent
);
2790 gboolean
GtkSalFrame::signalExpose( GtkWidget
*, GdkEventExpose
* pEvent
, gpointer frame
)
2792 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2794 struct SalPaintEvent
aEvent( pEvent
->area
.x
, pEvent
->area
.y
, pEvent
->area
.width
, pEvent
->area
.height
);
2797 pThis
->CallCallback( SALEVENT_PAINT
, &aEvent
);
2802 gboolean
GtkSalFrame::signalFocus( GtkWidget
*, GdkEventFocus
* pEvent
, gpointer frame
)
2804 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2808 // check if printers have changed (analogous to salframe focus handler)
2809 vcl_sal::PrinterUpdate::update();
2813 pThis
->m_nKeyModifiers
= 0;
2814 pThis
->m_bSingleAltPress
= false;
2815 pThis
->m_bSendModChangeOnRelease
= false;
2818 if( pThis
->m_pIMHandler
)
2819 pThis
->m_pIMHandler
->focusChanged( pEvent
->in
);
2821 // ask for changed printers like generic implementation
2823 if( static_cast< X11SalInstance
* >(GetSalData()->m_pInstance
)->isPrinterInit() )
2824 vcl_sal::PrinterUpdate::update();
2826 // FIXME: find out who the hell steals the focus from our frame
2827 // while we have the pointer grabbed, this should not come from
2828 // the window manager. Is this an event that was still queued ?
2829 // The focus does not seem to get set inside our process
2831 // in the meantime do not propagate focus get/lose if floats are open
2832 if( m_nFloats
== 0 )
2833 pThis
->CallCallback( pEvent
->in
? SALEVENT_GETFOCUS
: SALEVENT_LOSEFOCUS
, NULL
);
2838 gboolean
GtkSalFrame::signalMap( GtkWidget
*, GdkEvent
*, gpointer frame
)
2840 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2844 if( ImplGetSVData()->mbIsTestTool
)
2846 /* #i76541# testtool needs the focus to be in a new document
2847 * however e.g. metacity does not necessarily put the focus into
2848 * a newly shown window. An extra little hint seems to help here.
2849 * however we don't want to interfere with the normal user experience
2850 * so this is done when running in testtool only
2852 if( ! pThis
->m_pParent
&& (pThis
->m_nStyle
& SAL_FRAME_STYLE_MOVEABLE
) != 0 )
2853 XSetInputFocus( pThis
->getDisplay()->GetDisplay(),
2854 GDK_WINDOW_XWINDOW( GTK_WIDGET(pThis
->m_pWindow
)->window
),
2855 RevertToParent
, CurrentTime
);
2858 pThis
->CallCallback( SALEVENT_RESIZE
, NULL
);
2863 gboolean
GtkSalFrame::signalUnmap( GtkWidget
*, GdkEvent
*, gpointer frame
)
2865 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2868 pThis
->CallCallback( SALEVENT_RESIZE
, NULL
);
2873 gboolean
GtkSalFrame::signalConfigure( GtkWidget
*, GdkEventConfigure
* pEvent
, gpointer frame
)
2875 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2877 bool bMoved
= false, bSized
= false;
2878 int x
= pEvent
->x
, y
= pEvent
->y
;
2880 /* HACK: during sizing/moving a toolbar pThis->maGeometry is actually
2881 * already exact; even worse: due to the asynchronicity of configure
2882 * events the borderwindow which would evaluate this event
2883 * would size/move based on wrong data if we would actually evaluate
2884 * this event. So let's swallow it; this is also a performance
2885 * improvement as one can omit the synchronous XTranslateCoordinates
2888 if( (pThis
->m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) &&
2889 pThis
->getDisplay()->GetCaptureFrame() == pThis
)
2893 // in child case the coordinates are not root coordinates,
2894 // need to transform
2896 /* #i31785# sadly one cannot really trust the x,y members of the event;
2897 * they are e.g. not set correctly on maximize/demaximize; this rather
2898 * sounds like a bug in gtk we have to workaround.
2901 XTranslateCoordinates( pThis
->getDisplay()->GetDisplay(),
2902 GDK_WINDOW_XWINDOW(GTK_WIDGET(pThis
->m_pWindow
)->window
),
2903 pThis
->getDisplay()->GetRootWindow( pThis
->getDisplay()->GetDefaultScreenNumber() ),
2908 if( x
!= pThis
->maGeometry
.nX
|| y
!= pThis
->maGeometry
.nY
)
2911 pThis
->maGeometry
.nX
= x
;
2912 pThis
->maGeometry
.nY
= y
;
2915 * for non sizeable windows we set the min and max hint for the window manager to
2916 * achieve correct sizing. However this is asynchronous and e.g. on Compiz
2917 * it sometimes happens that the window gets resized to another size (some default)
2918 * if we update the size here, subsequent setMinMaxSize will use this wrong size
2919 * - which is not good since the window manager will now size the window back to this
2920 * wrong size at some point.
2922 if( (pThis
->m_nStyle
& (SAL_FRAME_STYLE_SIZEABLE
| SAL_FRAME_STYLE_PLUG
)) == SAL_FRAME_STYLE_SIZEABLE
)
2924 if( pEvent
->width
!= (int)pThis
->maGeometry
.nWidth
|| pEvent
->height
!= (int)pThis
->maGeometry
.nHeight
)
2927 pThis
->maGeometry
.nWidth
= pEvent
->width
;
2928 pThis
->maGeometry
.nHeight
= pEvent
->height
;
2932 // update decoration hints
2933 if( ! (pThis
->m_nStyle
& SAL_FRAME_STYLE_PLUG
) )
2936 gdk_window_get_frame_extents( GTK_WIDGET(pThis
->m_pWindow
)->window
, &aRect
);
2937 pThis
->maGeometry
.nTopDecoration
= y
- aRect
.y
;
2938 pThis
->maGeometry
.nBottomDecoration
= aRect
.y
+ aRect
.height
- y
- pEvent
->height
;
2939 pThis
->maGeometry
.nLeftDecoration
= x
- aRect
.x
;
2940 pThis
->maGeometry
.nRightDecoration
= aRect
.x
+ aRect
.width
- x
- pEvent
->width
;
2944 pThis
->maGeometry
.nTopDecoration
=
2945 pThis
->maGeometry
.nBottomDecoration
=
2946 pThis
->maGeometry
.nLeftDecoration
=
2947 pThis
->maGeometry
.nRightDecoration
= 0;
2951 pThis
->updateScreenNumber();
2952 if( bMoved
&& bSized
)
2953 pThis
->CallCallback( SALEVENT_MOVERESIZE
, NULL
);
2955 pThis
->CallCallback( SALEVENT_MOVE
, NULL
);
2957 pThis
->CallCallback( SALEVENT_RESIZE
, NULL
);
2962 gboolean
GtkSalFrame::signalKey( GtkWidget
*, GdkEventKey
* pEvent
, gpointer frame
)
2964 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2966 vcl::DeletionListener
aDel( pThis
);
2968 if( pThis
->m_pIMHandler
)
2970 if( pThis
->m_pIMHandler
->handleKeyEvent( pEvent
) )
2972 pThis
->m_bSingleAltPress
= false;
2979 if( pEvent
->keyval
== GDK_Shift_L
|| pEvent
->keyval
== GDK_Shift_R
||
2980 pEvent
->keyval
== GDK_Control_L
|| pEvent
->keyval
== GDK_Control_R
||
2981 pEvent
->keyval
== GDK_Alt_L
|| pEvent
->keyval
== GDK_Alt_R
||
2982 pEvent
->keyval
== GDK_Meta_L
|| pEvent
->keyval
== GDK_Meta_R
||
2983 pEvent
->keyval
== GDK_Super_L
|| pEvent
->keyval
== GDK_Super_R
)
2985 SalKeyModEvent aModEvt
;
2987 USHORT nModCode
= GetKeyModCode( pEvent
->state
);
2989 aModEvt
.mnModKeyCode
= 0; // emit no MODKEYCHANGE events
2990 if( pEvent
->type
== GDK_KEY_PRESS
&& !pThis
->m_nKeyModifiers
)
2991 pThis
->m_bSendModChangeOnRelease
= true;
2993 else if( pEvent
->type
== GDK_KEY_RELEASE
&&
2994 pThis
->m_bSendModChangeOnRelease
)
2996 aModEvt
.mnModKeyCode
= pThis
->m_nKeyModifiers
;
2997 pThis
->m_nKeyModifiers
= 0;
3000 USHORT nExtModMask
= 0;
3001 USHORT nModMask
= 0;
3002 // pressing just the ctrl key leads to a keysym of XK_Control but
3003 // the event state does not contain ControlMask. In the release
3004 // event its the other way round: it does contain the Control mask.
3005 // The modifier mode therefore has to be adapted manually.
3006 switch( pEvent
->keyval
)
3009 nExtModMask
= MODKEY_LMOD1
;
3010 nModMask
= KEY_MOD1
;
3013 nExtModMask
= MODKEY_RMOD1
;
3014 nModMask
= KEY_MOD1
;
3017 nExtModMask
= MODKEY_LMOD2
;
3018 nModMask
= KEY_MOD2
;
3021 nExtModMask
= MODKEY_RMOD2
;
3022 nModMask
= KEY_MOD2
;
3025 nExtModMask
= MODKEY_LSHIFT
;
3026 nModMask
= KEY_SHIFT
;
3029 nExtModMask
= MODKEY_RSHIFT
;
3030 nModMask
= KEY_SHIFT
;
3032 // Map Meta/Super to MOD3 modifier on all Unix systems
3036 nExtModMask
= MODKEY_LMOD3
;
3037 nModMask
= KEY_MOD3
;
3041 nExtModMask
= MODKEY_RMOD3
;
3042 nModMask
= KEY_MOD3
;
3045 if( pEvent
->type
== GDK_KEY_RELEASE
)
3047 nModCode
&= ~nModMask
;
3048 pThis
->m_nKeyModifiers
&= ~nExtModMask
;
3052 nModCode
|= nModMask
;
3053 pThis
->m_nKeyModifiers
|= nExtModMask
;
3056 aModEvt
.mnCode
= nModCode
;
3057 aModEvt
.mnTime
= pEvent
->time
;
3059 pThis
->CallCallback( SALEVENT_KEYMODCHANGE
, &aModEvt
);
3061 if( ! aDel
.isDeleted() )
3064 if( ( pEvent
->keyval
== GDK_Alt_L
|| pEvent
->keyval
== GDK_Alt_R
) &&
3065 ( nModCode
& ~(KEY_MOD3
|KEY_MOD2
)) == 0 )
3067 if( pEvent
->type
== GDK_KEY_PRESS
)
3068 pThis
->m_bSingleAltPress
= true;
3070 else if( pThis
->m_bSingleAltPress
)
3072 SalKeyEvent aKeyEvt
;
3074 aKeyEvt
.mnCode
= KEY_MENU
| nModCode
;
3075 aKeyEvt
.mnRepeat
= 0;
3076 aKeyEvt
.mnTime
= pEvent
->time
;
3077 aKeyEvt
.mnCharCode
= 0;
3079 // simulate KEY_MENU
3080 pThis
->CallCallback( SALEVENT_KEYINPUT
, &aKeyEvt
);
3081 if( ! aDel
.isDeleted() )
3083 pThis
->CallCallback( SALEVENT_KEYUP
, &aKeyEvt
);
3084 pThis
->m_bSingleAltPress
= false;
3089 pThis
->m_bSingleAltPress
= false;
3094 pThis
->doKeyCallback( pEvent
->state
,
3096 pEvent
->hardware_keycode
,
3099 sal_Unicode(gdk_keyval_to_unicode( pEvent
->keyval
)),
3100 (pEvent
->type
== GDK_KEY_PRESS
),
3102 if( ! aDel
.isDeleted() )
3104 pThis
->m_bSendModChangeOnRelease
= false;
3105 pThis
->m_bSingleAltPress
= false;
3109 if( !aDel
.isDeleted() && pThis
->m_pIMHandler
)
3110 pThis
->m_pIMHandler
->updateIMSpotLocation();
3115 gboolean
GtkSalFrame::signalDelete( GtkWidget
*, GdkEvent
*, gpointer frame
)
3117 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3120 pThis
->CallCallback( SALEVENT_CLOSE
, NULL
);
3125 void GtkSalFrame::signalStyleSet( GtkWidget
*, GtkStyle
* pPrevious
, gpointer frame
)
3127 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3129 // every frame gets an initial style set on creation
3130 // do not post these as the whole application tends to
3131 // redraw itself to adjust to the new style
3132 // where there IS no new style resulting in tremendous unnecessary flickering
3133 if( pPrevious
!= NULL
)
3134 // signalStyleSet does NOT usually have the gdk lock
3135 // so post user event to safely dispatch the SALEVENT_SETTINGSCHANGED
3136 // note: settings changed for multiple frames is avoided in winproc.cxx ImplHandleSettings
3137 pThis
->getDisplay()->SendInternalEvent( pThis
, NULL
, SALEVENT_SETTINGSCHANGED
);
3139 /* #i64117# gtk sets a nice background pixmap
3140 * but we actually don't really want that, so save
3141 * some time on the Xserver as well as prevent
3144 GdkWindow
* pWin
= GTK_WIDGET(pThis
->getWindow())->window
;
3147 XLIB_Window aWin
= GDK_WINDOW_XWINDOW(pWin
);
3149 XSetWindowBackgroundPixmap( pThis
->getDisplay()->GetDisplay(),
3151 pThis
->m_hBackgroundPixmap
);
3154 if( ! pThis
->m_pParent
)
3156 // signalize theme changed for NWF caches
3157 // FIXME: should be called only once for a style change
3158 GtkSalGraphics::bThemeChanged
= TRUE
;
3162 gboolean
GtkSalFrame::signalState( GtkWidget
*, GdkEvent
* pEvent
, gpointer frame
)
3164 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3165 if( (pThis
->m_nState
& GDK_WINDOW_STATE_ICONIFIED
) != (pEvent
->window_state
.new_window_state
& GDK_WINDOW_STATE_ICONIFIED
) )
3166 pThis
->getDisplay()->SendInternalEvent( pThis
, NULL
, SALEVENT_RESIZE
);
3168 if( (pEvent
->window_state
.new_window_state
& GDK_WINDOW_STATE_MAXIMIZED
) &&
3169 ! (pThis
->m_nState
& GDK_WINDOW_STATE_MAXIMIZED
) )
3171 pThis
->m_aRestorePosSize
=
3172 Rectangle( Point( pThis
->maGeometry
.nX
, pThis
->maGeometry
.nY
),
3173 Size( pThis
->maGeometry
.nWidth
, pThis
->maGeometry
.nHeight
) );
3175 pThis
->m_nState
= pEvent
->window_state
.new_window_state
;
3180 gboolean
GtkSalFrame::signalVisibility( GtkWidget
*, GdkEventVisibility
* pEvent
, gpointer frame
)
3182 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3183 pThis
->m_nVisibility
= pEvent
->state
;
3188 void GtkSalFrame::signalDestroy( GtkObject
* pObj
, gpointer frame
)
3190 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3191 if( GTK_WIDGET( pObj
) == pThis
->m_pWindow
)
3193 pThis
->m_pFixedContainer
= NULL
;
3194 pThis
->m_pWindow
= NULL
;
3198 // ----------------------------------------------------------------------
3199 // GtkSalFrame::IMHandler
3200 // ----------------------------------------------------------------------
3202 GtkSalFrame::IMHandler::IMHandler( GtkSalFrame
* pFrame
)
3204 m_nPrevKeyPresses( 0 ),
3205 m_pIMContext( NULL
),
3208 m_aInputEvent
.mpTextAttr
= NULL
;
3212 GtkSalFrame::IMHandler::~IMHandler()
3214 // cancel an eventual event posted to begin preedit again
3215 m_pFrame
->getDisplay()->CancelInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3219 void GtkSalFrame::IMHandler::createIMContext()
3221 if( ! m_pIMContext
)
3223 m_pIMContext
= gtk_im_multicontext_new ();
3224 g_signal_connect( m_pIMContext
, "commit",
3225 G_CALLBACK (signalIMCommit
), this );
3226 g_signal_connect( m_pIMContext
, "preedit_changed",
3227 G_CALLBACK (signalIMPreeditChanged
), this );
3228 g_signal_connect( m_pIMContext
, "retrieve_surrounding",
3229 G_CALLBACK (signalIMRetrieveSurrounding
), this );
3230 g_signal_connect( m_pIMContext
, "delete_surrounding",
3231 G_CALLBACK (signalIMDeleteSurrounding
), this );
3232 g_signal_connect( m_pIMContext
, "preedit_start",
3233 G_CALLBACK (signalIMPreeditStart
), this );
3234 g_signal_connect( m_pIMContext
, "preedit_end",
3235 G_CALLBACK (signalIMPreeditEnd
), this );
3237 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3238 gtk_im_context_set_client_window( m_pIMContext
, GTK_WIDGET(m_pFrame
->m_pWindow
)->window
);
3239 gtk_im_context_focus_in( m_pIMContext
);
3240 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3245 void GtkSalFrame::IMHandler::deleteIMContext()
3249 // first give IC a chance to deinitialize
3250 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3251 gtk_im_context_set_client_window( m_pIMContext
, NULL
);
3252 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3254 g_object_unref( m_pIMContext
);
3255 m_pIMContext
= NULL
;
3259 void GtkSalFrame::IMHandler::doCallEndExtTextInput()
3261 m_aInputEvent
.mpTextAttr
= NULL
;
3262 m_pFrame
->CallCallback( SALEVENT_ENDEXTTEXTINPUT
, NULL
);
3265 void GtkSalFrame::IMHandler::updateIMSpotLocation()
3267 SalExtTextInputPosEvent aPosEvent
;
3268 m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUTPOS
, (void*)&aPosEvent
);
3270 aArea
.x
= aPosEvent
.mnX
;
3271 aArea
.y
= aPosEvent
.mnY
;
3272 aArea
.width
= aPosEvent
.mnWidth
;
3273 aArea
.height
= aPosEvent
.mnHeight
;
3274 gtk_im_context_set_cursor_location( m_pIMContext
, &aArea
);
3277 void GtkSalFrame::IMHandler::setInputContext( SalInputContext
* )
3281 void GtkSalFrame::IMHandler::sendEmptyCommit()
3283 vcl::DeletionListener
aDel( m_pFrame
);
3285 SalExtTextInputEvent aEmptyEv
;
3286 aEmptyEv
.mnTime
= 0;
3287 aEmptyEv
.mpTextAttr
= 0;
3288 aEmptyEv
.maText
= String();
3289 aEmptyEv
.mnCursorPos
= 0;
3290 aEmptyEv
.mnCursorFlags
= 0;
3291 aEmptyEv
.mnDeltaStart
= 0;
3292 aEmptyEv
.mbOnlyCursor
= False
;
3293 m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&aEmptyEv
);
3294 if( ! aDel
.isDeleted() )
3295 m_pFrame
->CallCallback( SALEVENT_ENDEXTTEXTINPUT
, NULL
);
3298 void GtkSalFrame::IMHandler::endExtTextInput( USHORT
/*nFlags*/ )
3300 gtk_im_context_reset ( m_pIMContext
);
3302 if( m_aInputEvent
.mpTextAttr
)
3304 vcl::DeletionListener
aDel( m_pFrame
);
3305 // delete preedit in sal (commit an empty string)
3307 if( ! aDel
.isDeleted() )
3309 // mark previous preedit state again (will e.g. be sent at focus gain)
3310 m_aInputEvent
.mpTextAttr
= &m_aInputFlags
[0];
3313 // begin preedit again
3314 m_pFrame
->getDisplay()->SendInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3320 void GtkSalFrame::IMHandler::focusChanged( bool bFocusIn
)
3322 m_bFocused
= bFocusIn
;
3325 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3326 gtk_im_context_focus_in( m_pIMContext
);
3327 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3328 if( m_aInputEvent
.mpTextAttr
)
3331 // begin preedit again
3332 m_pFrame
->getDisplay()->SendInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3337 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3338 gtk_im_context_focus_out( m_pIMContext
);
3339 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3340 // cancel an eventual event posted to begin preedit again
3341 m_pFrame
->getDisplay()->CancelInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3345 bool GtkSalFrame::IMHandler::handleKeyEvent( GdkEventKey
* pEvent
)
3347 vcl::DeletionListener
aDel( m_pFrame
);
3349 if( pEvent
->type
== GDK_KEY_PRESS
)
3351 // Add this key press event to the list of previous key presses
3352 // to which we compare key release events. If a later key release
3353 // event has a matching key press event in this list, we swallow
3354 // the key release because some GTK Input Methods don't swallow it
3356 m_aPrevKeyPresses
.push_back( PreviousKeyPress(pEvent
) );
3357 m_nPrevKeyPresses
++;
3359 // Also pop off the earliest key press event if there are more than 10
3361 while (m_nPrevKeyPresses
> 10)
3363 m_aPrevKeyPresses
.pop_front();
3364 m_nPrevKeyPresses
--;
3367 GObject
* pRef
= G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext
) ) );
3369 // #i51353# update spot location on every key input since we cannot
3370 // know which key may activate a preedit choice window
3371 updateIMSpotLocation();
3372 if( aDel
.isDeleted() )
3375 gboolean bResult
= gtk_im_context_filter_keypress( m_pIMContext
, pEvent
);
3376 g_object_unref( pRef
);
3378 if( aDel
.isDeleted() )
3385 DBG_ASSERT( m_nPrevKeyPresses
> 0, "key press has vanished !" );
3386 if( ! m_aPrevKeyPresses
.empty() ) // sanity check
3388 // event was not swallowed, do not filter a following
3389 // key release event
3390 // note: this relies on gtk_im_context_filter_keypress
3391 // returning without calling a handler (in the "not swallowed"
3392 // case ) which might change the previous key press list so
3393 // we would pop the wrong event here
3394 m_aPrevKeyPresses
.pop_back();
3395 m_nPrevKeyPresses
--;
3400 // Determine if we got an earlier key press event corresponding to this key release
3401 if (pEvent
->type
== GDK_KEY_RELEASE
)
3403 GObject
* pRef
= G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext
) ) );
3404 gboolean bResult
= gtk_im_context_filter_keypress( m_pIMContext
, pEvent
);
3405 g_object_unref( pRef
);
3407 if( aDel
.isDeleted() )
3410 std::list
<PreviousKeyPress
>::iterator iter
= m_aPrevKeyPresses
.begin();
3411 std::list
<PreviousKeyPress
>::iterator iter_end
= m_aPrevKeyPresses
.end();
3412 while (iter
!= iter_end
)
3414 // If we found a corresponding previous key press event, swallow the release
3415 // and remove the earlier key press from our list
3416 if (*iter
== pEvent
)
3418 m_aPrevKeyPresses
.erase(iter
);
3419 m_nPrevKeyPresses
--;
3433 * #122282# still more hacking: some IMEs never start a preedit but simply commit
3434 * in this case we cannot commit a single character. Workaround: do not do the
3435 * single key hack for enter or space if the unicode commited does not match
3438 static bool checkSingleKeyCommitHack( guint keyval
, sal_Unicode cCode
)
3445 if( cCode
!= '\n' && cCode
!= '\r' )
3460 #define CONTEXT_ARG pContext
3462 #define CONTEXT_ARG EMPTYARG
3464 void GtkSalFrame::IMHandler::signalIMCommit( GtkIMContext
* CONTEXT_ARG
, gchar
* pText
, gpointer im_handler
)
3466 GtkSalFrame::IMHandler
* pThis
= (GtkSalFrame::IMHandler
*)im_handler
;
3468 vcl::DeletionListener
aDel( pThis
->m_pFrame
);
3469 // open a block that will end the GTK_YIELD_GRAB before calling preedit changed again
3473 bool bWasPreedit
= (pThis
->m_aInputEvent
.mpTextAttr
!= 0);
3475 pThis
->m_aInputEvent
.mnTime
= 0;
3476 pThis
->m_aInputEvent
.mpTextAttr
= 0;
3477 pThis
->m_aInputEvent
.maText
= String( pText
, RTL_TEXTENCODING_UTF8
);
3478 pThis
->m_aInputEvent
.mnCursorPos
= pThis
->m_aInputEvent
.maText
.Len();
3479 pThis
->m_aInputEvent
.mnCursorFlags
= 0;
3480 pThis
->m_aInputEvent
.mnDeltaStart
= 0;
3481 pThis
->m_aInputEvent
.mbOnlyCursor
= False
;
3483 pThis
->m_aInputFlags
.clear();
3485 /* necessary HACK: all keyboard input comes in here as soon as a IMContext is set
3486 * which is logical and consequent. But since even simple input like
3487 * <space> comes through the commit signal instead of signalKey
3488 * and all kinds of windows only implement KeyInput (e.g. PushButtons,
3489 * RadioButtons and a lot of other Controls), will send a single
3490 * KeyInput/KeyUp sequence instead of an ExtText event if there
3491 * never was a preedit and the text is only one character.
3493 * In this case there the last ExtText event must have been
3494 * SALEVENT_ENDEXTTEXTINPUT, either because of a regular commit
3495 * or because there never was a preedit.
3497 bool bSingleCommit
= false;
3499 && pThis
->m_aInputEvent
.maText
.Len() == 1
3500 && ! pThis
->m_aPrevKeyPresses
.empty()
3503 const PreviousKeyPress
& rKP
= pThis
->m_aPrevKeyPresses
.back();
3504 sal_Unicode aOrigCode
= pThis
->m_aInputEvent
.maText
.GetChar(0);
3506 if( checkSingleKeyCommitHack( rKP
.keyval
, aOrigCode
) )
3508 pThis
->m_pFrame
->doKeyCallback( rKP
.state
, rKP
.keyval
, rKP
.hardware_keycode
, rKP
.group
, rKP
.time
, aOrigCode
, true, true );
3509 bSingleCommit
= true;
3513 if( ! bSingleCommit
)
3515 pThis
->m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&pThis
->m_aInputEvent
);
3516 if( ! aDel
.isDeleted() )
3517 pThis
->doCallEndExtTextInput();
3519 if( ! aDel
.isDeleted() )
3521 // reset input event
3522 pThis
->m_aInputEvent
.maText
= String();
3523 pThis
->m_aInputEvent
.mnCursorPos
= 0;
3524 pThis
->updateIMSpotLocation();
3528 // #i51356# workaround a solaris IIIMP bug
3529 // in case of partial commits the preedit changed signal
3530 // and commit signal come in wrong order
3531 if( ! aDel
.isDeleted() )
3532 signalIMPreeditChanged( pContext
, im_handler
);
3536 void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext
*, gpointer im_handler
)
3538 GtkSalFrame::IMHandler
* pThis
= (GtkSalFrame::IMHandler
*)im_handler
;
3541 PangoAttrList
* pAttrs
= NULL
;
3542 gint nCursorPos
= 0;
3544 gtk_im_context_get_preedit_string( pThis
->m_pIMContext
,
3548 if( pText
&& ! *pText
) // empty string
3550 // change from nothing to nothing -> do not start preedit
3551 // e.g. this will activate input into a calc cell without
3553 if( pThis
->m_aInputEvent
.maText
.Len() == 0 )
3560 bool bEndPreedit
= (!pText
|| !*pText
) && pThis
->m_aInputEvent
.mpTextAttr
!= NULL
;
3561 pThis
->m_aInputEvent
.mnTime
= 0;
3562 pThis
->m_aInputEvent
.maText
= String( pText
, RTL_TEXTENCODING_UTF8
);
3563 pThis
->m_aInputEvent
.mnCursorPos
= nCursorPos
;
3564 pThis
->m_aInputEvent
.mnCursorFlags
= 0;
3565 pThis
->m_aInputEvent
.mnDeltaStart
= 0;
3566 pThis
->m_aInputEvent
.mbOnlyCursor
= False
;
3568 pThis
->m_aInputFlags
= std::vector
<USHORT
>( std::max( 1, (int)pThis
->m_aInputEvent
.maText
.Len() ), 0 );
3570 PangoAttrIterator
*iter
= pango_attr_list_get_iterator (pAttrs
);
3573 GSList
*attr_list
= NULL
;
3574 GSList
*tmp_list
= NULL
;
3578 pango_attr_iterator_range (iter
, &start
, &end
);
3579 if (end
== G_MAXINT
)
3580 end
= pText
? strlen (pText
) : 0;
3584 start
= g_utf8_pointer_to_offset (pText
, pText
+ start
);
3585 end
= g_utf8_pointer_to_offset (pText
, pText
+ end
);
3587 tmp_list
= attr_list
= pango_attr_iterator_get_attrs (iter
);
3590 PangoAttribute
*pango_attr
= (PangoAttribute
*)(tmp_list
->data
);
3592 switch (pango_attr
->klass
->type
)
3594 case PANGO_ATTR_BACKGROUND
:
3595 sal_attr
|= (SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT
| SAL_EXTTEXTINPUT_CURSOR_INVISIBLE
);
3597 case PANGO_ATTR_UNDERLINE
:
3598 sal_attr
|= SAL_EXTTEXTINPUT_ATTR_UNDERLINE
;
3600 case PANGO_ATTR_STRIKETHROUGH
:
3601 sal_attr
|= SAL_EXTTEXTINPUT_ATTR_REDTEXT
;
3606 pango_attribute_destroy (pango_attr
);
3607 tmp_list
= tmp_list
->next
;
3610 sal_attr
|= SAL_EXTTEXTINPUT_ATTR_UNDERLINE
;
3611 g_slist_free (attr_list
);
3613 // Set the sal attributes on our text
3614 for (int i
= start
; i
< end
; i
++)
3615 pThis
->m_aInputFlags
[i
] |= sal_attr
;
3616 } while (pango_attr_iterator_next (iter
));
3618 pThis
->m_aInputEvent
.mpTextAttr
= &pThis
->m_aInputFlags
[0];
3621 pango_attr_list_unref( pAttrs
);
3625 vcl::DeletionListener
aDel( pThis
->m_pFrame
);
3627 pThis
->m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&pThis
->m_aInputEvent
);
3628 if( bEndPreedit
&& ! aDel
.isDeleted() )
3629 pThis
->doCallEndExtTextInput();
3630 if( ! aDel
.isDeleted() )
3631 pThis
->updateIMSpotLocation();
3634 void GtkSalFrame::IMHandler::signalIMPreeditStart( GtkIMContext
*, gpointer
/*im_handler*/ )
3638 void GtkSalFrame::IMHandler::signalIMPreeditEnd( GtkIMContext
*, gpointer im_handler
)
3640 GtkSalFrame::IMHandler
* pThis
= (GtkSalFrame::IMHandler
*)im_handler
;
3643 vcl::DeletionListener
aDel( pThis
->m_pFrame
);
3644 pThis
->doCallEndExtTextInput();
3645 if( ! aDel
.isDeleted() )
3646 pThis
->updateIMSpotLocation();
3649 uno::Reference
<accessibility::XAccessibleEditableText
>
3650 FindFocus(uno::Reference
< accessibility::XAccessibleContext
> xContext
)
3653 uno::Reference
< accessibility::XAccessibleEditableText
>();
3655 uno::Reference
<accessibility::XAccessibleStateSet
> xState
= xContext
->getAccessibleStateSet();
3658 if (xState
->contains(accessibility::AccessibleStateType::FOCUSED
))
3659 return uno::Reference
<accessibility::XAccessibleEditableText
>(xContext
, uno::UNO_QUERY
);
3662 for (sal_Int32 i
= 0; i
< xContext
->getAccessibleChildCount(); ++i
)
3664 uno::Reference
< accessibility::XAccessible
> xChild
= xContext
->getAccessibleChild(i
);
3667 uno::Reference
< accessibility::XAccessibleContext
> xChildContext
= xChild
->getAccessibleContext();
3668 if (!xChildContext
.is())
3670 uno::Reference
< accessibility::XAccessibleEditableText
> xText
= FindFocus(xChildContext
);
3674 return uno::Reference
< accessibility::XAccessibleEditableText
>();
3677 uno::Reference
<accessibility::XAccessibleEditableText
> lcl_GetxText()
3679 uno::Reference
<accessibility::XAccessibleEditableText
> xText
;
3680 Window
* pFocusWin
= ImplGetSVData()->maWinData
.mpFocusWin
;
3684 uno::Reference
< accessibility::XAccessible
> xAccessible( pFocusWin
->GetAccessible( true ) );
3685 if (xAccessible
.is())
3686 xText
= FindFocus(xAccessible
->getAccessibleContext());
3690 gboolean
GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext
* pContext
, gpointer
/*im_handler*/ )
3692 uno::Reference
<accessibility::XAccessibleEditableText
> xText
= lcl_GetxText();
3696 sal_uInt32 nPosition
= xText
->getCaretPosition();
3697 rtl::OUString sAllText
= xText
->getText();
3698 if (!sAllText
.getLength())
3700 rtl::OString sUTF
= rtl::OUStringToOString(sAllText
, RTL_TEXTENCODING_UTF8
);
3701 rtl::OUString
sCursorText(sAllText
, nPosition
);
3702 gtk_im_context_set_surrounding(pContext
, sUTF
.getStr(), sUTF
.getLength(),
3703 rtl::OUStringToOString(sCursorText
, RTL_TEXTENCODING_UTF8
).getLength());
3710 gboolean
GtkSalFrame::IMHandler::signalIMDeleteSurrounding( GtkIMContext
*, gint offset
, gint nchars
,
3711 gpointer
/*im_handler*/ )
3713 uno::Reference
<accessibility::XAccessibleEditableText
> xText
= lcl_GetxText();
3717 sal_uInt32 nPosition
= xText
->getCaretPosition();
3718 xText
->deleteText(nPosition
+ offset
, nPosition
+ offset
+ nchars
);