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>
49 #include <X11/Xatom.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 using namespace com::sun::star
;
80 int GtkSalFrame::m_nFloats
= 0;
82 static USHORT
GetKeyModCode( guint state
)
85 if( (state
& GDK_SHIFT_MASK
) )
87 if( (state
& GDK_CONTROL_MASK
)
89 || (state
& GDK_MOD2_MASK
) // map Meta (aka Command key) to Ctrl
93 if( (state
& GDK_MOD1_MASK
) )
97 if( ! (nCode
& KEY_MOD1
) )
104 static USHORT
GetMouseModCode( guint state
)
106 USHORT nCode
= GetKeyModCode( state
);
107 if( (state
& GDK_BUTTON1_MASK
) )
109 if( (state
& GDK_BUTTON2_MASK
) )
110 nCode
|= MOUSE_MIDDLE
;
111 if( (state
& GDK_BUTTON3_MASK
) )
112 nCode
|= MOUSE_RIGHT
;
117 static USHORT
GetKeyCode( guint keyval
)
120 if( keyval
>= GDK_0
&& keyval
<= GDK_9
)
121 nCode
= KEY_0
+ (keyval
-GDK_0
);
122 else if( keyval
>= GDK_KP_0
&& keyval
<= GDK_KP_9
)
123 nCode
= KEY_0
+ (keyval
-GDK_KP_0
);
124 else if( keyval
>= GDK_A
&& keyval
<= GDK_Z
)
125 nCode
= KEY_A
+ (keyval
-GDK_A
);
126 else if( keyval
>= GDK_a
&& keyval
<= GDK_z
)
127 nCode
= KEY_A
+ (keyval
-GDK_a
);
128 else if( keyval
>= GDK_F1
&& keyval
<= GDK_F26
)
130 if( GetX11SalData()->GetDisplay()->IsNumLockFromXS() )
132 nCode
= KEY_F1
+ (keyval
-GDK_F1
);
138 // - - - - - Sun keyboard, see vcl/unx/source/app/saldisp.cxx
140 if( GetX11SalData()->GetDisplay()->GetServerVendor() == vendor_sun
)
145 case GDK_L3
: nCode
= KEY_PROPERTIES
; break;
146 case GDK_L4
: nCode
= KEY_UNDO
; break;
147 case GDK_L6
: nCode
= KEY_COPY
; break; // KEY_F16
148 case GDK_L8
: nCode
= KEY_PASTE
; break; // KEY_F18
149 case GDK_L10
: nCode
= KEY_CUT
; break; // KEY_F20
151 nCode
= KEY_F1
+ (keyval
-GDK_F1
); break;
160 case GDK_Down
: nCode
= KEY_DOWN
; break;
162 case GDK_Up
: nCode
= KEY_UP
; break;
164 case GDK_Left
: nCode
= KEY_LEFT
; break;
166 case GDK_Right
: nCode
= KEY_RIGHT
; break;
170 case GDK_Home
: nCode
= KEY_HOME
; break;
172 case GDK_End
: nCode
= KEY_END
; break;
174 case GDK_Page_Up
: nCode
= KEY_PAGEUP
; break;
175 case GDK_KP_Page_Down
:
176 case GDK_Page_Down
: nCode
= KEY_PAGEDOWN
; break;
178 case GDK_Return
: nCode
= KEY_RETURN
; break;
179 case GDK_Escape
: nCode
= KEY_ESCAPE
; break;
180 case GDK_ISO_Left_Tab
:
182 case GDK_Tab
: nCode
= KEY_TAB
; break;
183 case GDK_BackSpace
: nCode
= KEY_BACKSPACE
; break;
185 case GDK_space
: nCode
= KEY_SPACE
; break;
187 case GDK_Insert
: nCode
= KEY_INSERT
; break;
189 case GDK_Delete
: nCode
= KEY_DELETE
; break;
191 case GDK_KP_Add
: nCode
= KEY_ADD
; break;
193 case GDK_KP_Subtract
: nCode
= KEY_SUBTRACT
; break;
195 case GDK_KP_Multiply
: nCode
= KEY_MULTIPLY
; break;
197 case GDK_KP_Divide
: nCode
= KEY_DIVIDE
; break;
199 case GDK_decimalpoint
: nCode
= KEY_POINT
; break;
200 case GDK_comma
: nCode
= KEY_COMMA
; break;
201 case GDK_less
: nCode
= KEY_LESS
; break;
202 case GDK_greater
: nCode
= KEY_GREATER
; break;
204 case GDK_equal
: nCode
= KEY_EQUAL
; break;
205 case GDK_Find
: nCode
= KEY_FIND
; break;
206 case GDK_Menu
: nCode
= KEY_CONTEXTMENU
;break;
207 case GDK_Help
: nCode
= KEY_HELP
; break;
208 case GDK_Undo
: nCode
= KEY_UNDO
; break;
209 case GDK_Redo
: nCode
= KEY_REPEAT
; break;
211 case GDK_KP_Separator
: nCode
= KEY_DECIMAL
; break;
212 case GDK_asciitilde
: nCode
= KEY_TILDE
; break;
213 case GDK_leftsinglequotemark
:
214 case GDK_quoteleft
: nCode
= KEY_QUOTELEFT
; break;
215 case GDK_bracketleft
: nCode
= KEY_BRACKETLEFT
; break;
216 case GDK_bracketright
: nCode
= KEY_BRACKETRIGHT
; break;
217 // some special cases, also see saldisp.cxx
218 // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
219 case 0x1000FF02: // apXK_Copy
222 case 0x1000FF03: // apXK_Cut
225 case 0x1000FF04: // apXK_Paste
228 case 0x1000FF14: // apXK_Repeat
232 // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
236 // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
237 case 0x1000FF73: // hpXK_DeleteChar
240 case 0x1000FF74: // hpXK_BackTab
241 case 0x1000FF75: // hpXK_KP_BackTab
244 // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
245 // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
246 case 0x1004FF02: // osfXK_Copy
249 case 0x1004FF03: // osfXK_Cut
252 case 0x1004FF04: // osfXK_Paste
255 case 0x1004FF07: // osfXK_BackTab
258 case 0x1004FF08: // osfXK_BackSpace
259 nCode
= KEY_BACKSPACE
;
261 case 0x1004FF1B: // osfXK_Escape
264 // Up, Down, Left, Right, PageUp, PageDown
265 // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
266 // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
267 // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
268 // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
269 case 0x1005FF10: // SunXK_F36
272 case 0x1005FF11: // SunXK_F37
275 case 0x1005FF70: // SunXK_Props
276 nCode
= KEY_PROPERTIES
;
278 case 0x1005FF71: // SunXK_Front
281 case 0x1005FF72: // SunXK_Copy
284 case 0x1005FF73: // SunXK_Open
287 case 0x1005FF74: // SunXK_Paste
290 case 0x1005FF75: // SunXK_Cut
299 // F10 means either KEY_F10 or KEY_MENU, which has to be decided
300 // in the independent part.
304 sal_Unicode nCharCode
;
305 KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
306 KeyAlternate( USHORT nKey
, sal_Unicode nChar
= 0 ) : nKeyCode( nKey
), nCharCode( nChar
) {}
310 GetAlternateKeyCode( const USHORT nKeyCode
)
312 KeyAlternate aAlternate
;
316 case KEY_F10
: aAlternate
= KeyAlternate( KEY_MENU
);break;
317 case KEY_F24
: aAlternate
= KeyAlternate( KEY_SUBTRACT
, '-' );break;
323 void GtkSalFrame::doKeyCallback( guint state
,
325 guint16 hardware_keycode
,
328 sal_Unicode aOrigCode
,
335 aEvent
.mnTime
= time
;
336 aEvent
.mnCharCode
= aOrigCode
;
339 vcl::DeletionListener
aDel( this );
340 /* #i42122# translate all keys with Ctrl and/or Alt to group 0
341 * else shortcuts (e.g. Ctrl-o) will not work but be inserted by
344 /* #i52338# do this for all keys that the independent part has no key code for
346 aEvent
.mnCode
= GetKeyCode( keyval
);
347 if( aEvent
.mnCode
== 0 )
349 // check other mapping
350 gint eff_group
, level
;
351 GdkModifierType consumed
;
352 guint updated_keyval
= 0;
353 // use gdk_keymap_get_default instead of NULL;
354 // workaround a crahs fixed in gtk 2.4
355 if( gdk_keymap_translate_keyboard_state( gdk_keymap_get_default(),
364 aEvent
.mnCode
= GetKeyCode( updated_keyval
);
367 aEvent
.mnCode
|= GetKeyModCode( state
);
371 bool bHandled
= CallCallback( SALEVENT_KEYINPUT
, &aEvent
);
372 // #i46889# copy AlternatKeyCode handling from generic plugin
375 KeyAlternate aAlternate
= GetAlternateKeyCode( aEvent
.mnCode
);
376 if( aAlternate
.nKeyCode
)
378 aEvent
.mnCode
= aAlternate
.nKeyCode
;
379 if( aAlternate
.nCharCode
)
380 aEvent
.mnCharCode
= aAlternate
.nCharCode
;
381 bHandled
= CallCallback( SALEVENT_KEYINPUT
, &aEvent
);
384 if( bSendRelease
&& ! aDel
.isDeleted() )
386 CallCallback( SALEVENT_KEYUP
, &aEvent
);
390 CallCallback( SALEVENT_KEYUP
, &aEvent
);
393 GtkSalFrame::GraphicsHolder::~GraphicsHolder()
398 GtkSalFrame::GtkSalFrame( SalFrame
* pParent
, ULONG nStyle
)
400 m_nScreen
= getDisplay()->GetDefaultScreenNumber();
401 getDisplay()->registerFrame( this );
402 m_bDefaultPos
= true;
403 m_bDefaultSize
= ( (nStyle
& SAL_FRAME_STYLE_SIZEABLE
) && ! pParent
);
404 m_bWindowIsGtkPlug
= false;
405 Init( pParent
, nStyle
);
408 GtkSalFrame::GtkSalFrame( SystemParentData
* pSysData
)
410 m_nScreen
= getDisplay()->GetDefaultScreenNumber();
411 getDisplay()->registerFrame( this );
412 getDisplay()->setHaveSystemChildFrame();
413 m_bDefaultPos
= true;
414 m_bDefaultSize
= true;
418 GtkSalFrame::~GtkSalFrame()
421 m_pParent
->m_aChildren
.remove( this );
423 getDisplay()->deregisterFrame( this );
426 gdk_region_destroy( m_pRegion
);
428 if( m_hBackgroundPixmap
)
430 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
431 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
433 XFreePixmap( getDisplay()->GetDisplay(), m_hBackgroundPixmap
);
439 if( m_pFixedContainer
)
440 gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer
) );
443 g_object_set_data( G_OBJECT( m_pWindow
), "SalFrame", NULL
);
444 gtk_widget_destroy( m_pWindow
);
446 if( m_pForeignParent
)
447 g_object_unref( G_OBJECT(m_pForeignParent
) );
448 if( m_pForeignTopLevel
)
449 g_object_unref(G_OBJECT( m_pForeignTopLevel
) );
452 void GtkSalFrame::moveWindow( long nX
, long nY
)
454 if( isChild( false, true ) )
457 gtk_fixed_move( m_pParent
->getFixedContainer(),
459 nX
- m_pParent
->maGeometry
.nX
, nY
- m_pParent
->maGeometry
.nY
);
462 gtk_window_move( GTK_WINDOW(m_pWindow
), nX
, nY
);
465 void GtkSalFrame::resizeWindow( long nWidth
, long nHeight
)
467 if( isChild( false, true ) )
468 gtk_widget_set_size_request( m_pWindow
, nWidth
, nHeight
);
469 else if( ! isChild( true, false ) )
470 gtk_window_resize( GTK_WINDOW(m_pWindow
), nWidth
, nHeight
);
474 * Always use a sub-class of GtkFixed we can tag for a11y. This allows us to
475 * utilize GAIL for the toplevel window and toolkit implementation incl.
476 * key event listener support ..
482 static GType type
= 0;
485 static const GTypeInfo tinfo
=
487 sizeof (GtkFixedClass
),
488 (GBaseInitFunc
) NULL
, /* base init */
489 (GBaseFinalizeFunc
) NULL
, /* base finalize */
490 (GClassInitFunc
) NULL
, /* class init */
491 (GClassFinalizeFunc
) NULL
, /* class finalize */
492 NULL
, /* class data */
493 sizeof (GtkFixed
), /* instance size */
494 0, /* nb preallocs */
495 (GInstanceInitFunc
) NULL
, /* instance init */
496 NULL
/* value table */
499 type
= g_type_register_static( GTK_TYPE_FIXED
, "OOoFixed",
500 &tinfo
, (GTypeFlags
) 0);
506 void GtkSalFrame::updateScreenNumber()
508 if( getDisplay()->IsXinerama() && getDisplay()->GetXineramaScreens().size() > 1 )
510 Point
aPoint( maGeometry
.nX
, maGeometry
.nY
);
511 const std::vector
<Rectangle
>& rScreenRects( getDisplay()->GetXineramaScreens() );
512 size_t nScreens
= rScreenRects
.size();
513 for( size_t i
= 0; i
< nScreens
; i
++ )
515 if( rScreenRects
[i
].IsInside( aPoint
) )
517 maGeometry
.nScreenNumber
= static_cast<unsigned int>(i
);
523 maGeometry
.nScreenNumber
= static_cast<unsigned int>(m_nScreen
);
526 void GtkSalFrame::InitCommon()
529 g_signal_connect( G_OBJECT(m_pWindow
), "style-set", G_CALLBACK(signalStyleSet
), this );
530 g_signal_connect( G_OBJECT(m_pWindow
), "button-press-event", G_CALLBACK(signalButton
), this );
531 g_signal_connect( G_OBJECT(m_pWindow
), "button-release-event", G_CALLBACK(signalButton
), this );
532 g_signal_connect( G_OBJECT(m_pWindow
), "expose-event", G_CALLBACK(signalExpose
), this );
533 g_signal_connect( G_OBJECT(m_pWindow
), "focus-in-event", G_CALLBACK(signalFocus
), this );
534 g_signal_connect( G_OBJECT(m_pWindow
), "focus-out-event", G_CALLBACK(signalFocus
), this );
535 g_signal_connect( G_OBJECT(m_pWindow
), "map-event", G_CALLBACK(signalMap
), this );
536 g_signal_connect( G_OBJECT(m_pWindow
), "unmap-event", G_CALLBACK(signalUnmap
), this );
537 g_signal_connect( G_OBJECT(m_pWindow
), "configure-event", G_CALLBACK(signalConfigure
), this );
538 g_signal_connect( G_OBJECT(m_pWindow
), "motion-notify-event", G_CALLBACK(signalMotion
), this );
539 g_signal_connect( G_OBJECT(m_pWindow
), "key-press-event", G_CALLBACK(signalKey
), this );
540 g_signal_connect( G_OBJECT(m_pWindow
), "key-release-event", G_CALLBACK(signalKey
), this );
541 g_signal_connect( G_OBJECT(m_pWindow
), "delete-event", G_CALLBACK(signalDelete
), this );
542 g_signal_connect( G_OBJECT(m_pWindow
), "window-state-event", G_CALLBACK(signalState
), this );
543 g_signal_connect( G_OBJECT(m_pWindow
), "scroll-event", G_CALLBACK(signalScroll
), this );
544 g_signal_connect( G_OBJECT(m_pWindow
), "leave-notify-event", G_CALLBACK(signalCrossing
), this );
545 g_signal_connect( G_OBJECT(m_pWindow
), "enter-notify-event", G_CALLBACK(signalCrossing
), this );
546 g_signal_connect( G_OBJECT(m_pWindow
), "visibility-notify-event", G_CALLBACK(signalVisibility
), this );
547 g_signal_connect( G_OBJECT(m_pWindow
), "destroy", G_CALLBACK(signalDestroy
), this );
550 m_pCurrentCursor
= NULL
;
552 m_bSingleAltPress
= false;
553 m_bFullscreen
= false;
554 m_nState
= GDK_WINDOW_STATE_WITHDRAWN
;
555 m_nVisibility
= GDK_VISIBILITY_FULLY_OBSCURED
;
556 m_bSendModChangeOnRelease
= false;
558 m_hBackgroundPixmap
= None
;
559 m_nSavedScreenSaverTimeout
= 0;
563 m_ePointerStyle
= 0xffff;
565 gtk_widget_set_app_paintable( m_pWindow
, TRUE
);
566 gtk_widget_set_double_buffered( m_pWindow
, FALSE
);
567 gtk_widget_set_redraw_on_allocate( m_pWindow
, FALSE
);
568 gtk_widget_add_events( m_pWindow
,
569 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
|
570 GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK
|
571 GDK_VISIBILITY_NOTIFY_MASK
574 // add the fixed container child,
575 // fixed is needed since we have to position plugin windows
576 m_pFixedContainer
= GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL
));
577 gtk_container_add( GTK_CONTAINER(m_pWindow
), GTK_WIDGET(m_pFixedContainer
) );
580 gtk_widget_show( GTK_WIDGET(m_pFixedContainer
) );
582 // realize the window, we need an XWindow id
583 gtk_widget_realize( m_pWindow
);
586 SalDisplay
* pDisp
= GetX11SalData()->GetDisplay();
587 m_aSystemData
.nSize
= sizeof( SystemChildData
);
588 m_aSystemData
.pDisplay
= pDisp
->GetDisplay();
589 m_aSystemData
.aWindow
= GDK_WINDOW_XWINDOW(m_pWindow
->window
);
590 m_aSystemData
.pSalFrame
= this;
591 m_aSystemData
.pWidget
= m_pWindow
;
592 m_aSystemData
.pVisual
= pDisp
->GetVisual( m_nScreen
).GetVisual();
593 m_aSystemData
.nScreen
= m_nScreen
;
594 m_aSystemData
.nDepth
= pDisp
->GetVisual( m_nScreen
).GetDepth();
595 m_aSystemData
.aColormap
= pDisp
->GetColormap( m_nScreen
).GetXColormap();
596 m_aSystemData
.pAppContext
= NULL
;
597 m_aSystemData
.aShellWindow
= m_aSystemData
.aWindow
;
598 m_aSystemData
.pShellWidget
= m_aSystemData
.pWidget
;
601 // fake an initial geometry, gets updated via configure event or SetPosSize
602 if( m_bDefaultPos
|| m_bDefaultSize
)
604 Size aDefSize
= calcDefaultSize();
607 maGeometry
.nWidth
= aDefSize
.Width();
608 maGeometry
.nHeight
= aDefSize
.Height();
612 maGeometry
.nTopDecoration
= m_pParent
->maGeometry
.nTopDecoration
;
613 maGeometry
.nBottomDecoration
= m_pParent
->maGeometry
.nBottomDecoration
;
614 maGeometry
.nLeftDecoration
= m_pParent
->maGeometry
.nLeftDecoration
;
615 maGeometry
.nRightDecoration
= m_pParent
->maGeometry
.nRightDecoration
;
619 maGeometry
.nTopDecoration
= 0;
620 maGeometry
.nBottomDecoration
= 0;
621 maGeometry
.nLeftDecoration
= 0;
622 maGeometry
.nRightDecoration
= 0;
627 resizeWindow( maGeometry
.nWidth
, maGeometry
.nHeight
);
628 moveWindow( maGeometry
.nX
, maGeometry
.nY
);
630 updateScreenNumber();
633 m_nWorkArea
= pDisp
->getWMAdaptor()->getCurrentWorkArea();
635 /* #i64117# gtk sets a nice background pixmap
636 * but we actually don't really want that, so save
637 * some time on the Xserver as well as prevent
640 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
641 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
642 m_hBackgroundPixmap
);
645 /* Sadly gtk_window_set_accept_focus exists only since gtk 2.4
646 * for achieving the same effect we will remove the WM_TAKE_FOCUS
647 * protocol from the window and set the input hint to false.
648 * But gtk_window_set_accept_focus needs to be called before
649 * window realization whereas the removal obviously can only happen
654 typedef void(*setAcceptFn
)( GtkWindow
*, gboolean
);
655 static setAcceptFn p_gtk_window_set_accept_focus
= NULL
;
656 static bool bGetAcceptFocusFn
= true;
658 typedef void(*setUserTimeFn
)( GdkWindow
*, guint32
);
659 static setUserTimeFn p_gdk_x11_window_set_user_time
= NULL
;
660 static bool bGetSetUserTimeFn
= true;
663 static void lcl_set_accept_focus( GtkWindow
* pWindow
, gboolean bAccept
, bool bBeforeRealize
)
665 if( bGetAcceptFocusFn
)
667 bGetAcceptFocusFn
= false;
668 p_gtk_window_set_accept_focus
= (setAcceptFn
)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin
, "gtk_window_set_accept_focus" );
670 if( p_gtk_window_set_accept_focus
&& bBeforeRealize
)
671 p_gtk_window_set_accept_focus( pWindow
, bAccept
);
672 else if( ! bBeforeRealize
)
674 Display
* pDisplay
= GetX11SalData()->GetDisplay()->GetDisplay();
675 XLIB_Window aWindow
= GDK_WINDOW_XWINDOW( GTK_WIDGET(pWindow
)->window
);
676 XWMHints
* pHints
= XGetWMHints( pDisplay
, aWindow
);
679 pHints
= XAllocWMHints();
682 pHints
->flags
|= InputHint
;
683 pHints
->input
= bAccept
? True
: False
;
684 XSetWMHints( pDisplay
, aWindow
, pHints
);
687 if (GetX11SalData()->GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz"))
690 /* remove WM_TAKE_FOCUS protocol; this would usually be the
691 * right thing, but gtk handles it internally whereas we
692 * want to handle it ourselves (as to sometimes not get
695 Atom
* pProtocols
= NULL
;
697 XGetWMProtocols( pDisplay
,
699 &pProtocols
, &nProtocols
);
703 Atom nTakeFocus
= XInternAtom( pDisplay
, "WM_TAKE_FOCUS", True
);
706 for( int i
= 0; i
< nProtocols
; i
++ )
708 if( pProtocols
[i
] == nTakeFocus
)
710 for( int n
= i
; n
< nProtocols
-1; n
++ )
711 pProtocols
[n
] = pProtocols
[n
+1];
719 XSetWMProtocols( pDisplay
, aWindow
, pProtocols
, nProtocols
);
724 static void lcl_set_user_time( GdkWindow
* i_pWindow
, guint32 i_nTime
)
726 if( bGetSetUserTimeFn
)
728 bGetSetUserTimeFn
= false;
729 p_gdk_x11_window_set_user_time
= (setUserTimeFn
)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin
, "gdk_x11_window_set_user_time" );
731 if( p_gdk_x11_window_set_user_time
)
732 p_gdk_x11_window_set_user_time( i_pWindow
, i_nTime
);
735 Display
* pDisplay
= GetX11SalData()->GetDisplay()->GetDisplay();
736 XLIB_Window aWindow
= GDK_WINDOW_XWINDOW( i_pWindow
);
737 Atom nUserTime
= XInternAtom( pDisplay
, "_NET_WM_USER_TIME", True
);
740 XChangeProperty( pDisplay
, aWindow
,
741 nUserTime
, XA_CARDINAL
, 32,
742 PropModeReplace
, (unsigned char*)&i_nTime
, 1 );
747 GtkSalFrame
*GtkSalFrame::getFromWindow( GtkWindow
*pWindow
)
749 return (GtkSalFrame
*) g_object_get_data( G_OBJECT( pWindow
), "SalFrame" );
752 void GtkSalFrame::Init( SalFrame
* pParent
, ULONG nStyle
)
754 if( nStyle
& SAL_FRAME_STYLE_DEFAULT
) // ensure default style
756 nStyle
|= SAL_FRAME_STYLE_MOVEABLE
| SAL_FRAME_STYLE_SIZEABLE
| SAL_FRAME_STYLE_CLOSEABLE
;
757 nStyle
&= ~SAL_FRAME_STYLE_FLOAT
;
760 m_pParent
= static_cast<GtkSalFrame
*>(pParent
);
761 m_pForeignParent
= NULL
;
762 m_aForeignParentWindow
= None
;
763 m_pForeignTopLevel
= NULL
;
764 m_aForeignTopLevelWindow
= None
;
767 GtkWindowType eWinType
= ((nStyle
& SAL_FRAME_STYLE_FLOAT
) && ! (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
))
768 ? GTK_WINDOW_POPUP
: GTK_WINDOW_TOPLEVEL
;
770 if( nStyle
& SAL_FRAME_STYLE_SYSTEMCHILD
)
772 m_pWindow
= gtk_event_box_new();
775 // insert into container
776 gtk_fixed_put( m_pParent
->getFixedContainer(),
782 m_pWindow
= gtk_widget_new( GTK_TYPE_WINDOW
, "type", eWinType
, "visible", FALSE
, NULL
);
783 g_object_set_data( G_OBJECT( m_pWindow
), "SalFrame", this );
785 // force wm class hint
787 SetExtendedFrameStyle( 0 );
789 if( m_pParent
&& m_pParent
->m_pWindow
&& ! isChild() )
790 gtk_window_set_screen( GTK_WINDOW(m_pWindow
), gtk_window_get_screen( GTK_WINDOW(m_pParent
->m_pWindow
) ) );
795 ( ! (nStyle
& SAL_FRAME_STYLE_FLOAT
) ||
796 (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) );
798 /* #i100116# metacity has a peculiar behavior regarding WM_HINT accept focus and _NET_WM_USER_TIME
799 at some point that may be fixed in metacity and we will have to revisit this
801 bool bMetaCityToolWindowHack
= getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") &&
802 (nStyle
& SAL_FRAME_STYLE_TOOLWINDOW
);
805 bool bNoDecor
= ! (nStyle
& (SAL_FRAME_STYLE_MOVEABLE
| SAL_FRAME_STYLE_SIZEABLE
| SAL_FRAME_STYLE_CLOSEABLE
) );
806 GdkWindowTypeHint eType
= GDK_WINDOW_TYPE_HINT_NORMAL
;
807 if( (nStyle
& SAL_FRAME_STYLE_DIALOG
) && m_pParent
!= 0 )
808 eType
= GDK_WINDOW_TYPE_HINT_DIALOG
;
809 if( (nStyle
& SAL_FRAME_STYLE_INTRO
) )
811 gtk_window_set_role( GTK_WINDOW(m_pWindow
), "splashscreen" );
812 eType
= GDK_WINDOW_TYPE_HINT_SPLASHSCREEN
;
814 else if( (nStyle
& SAL_FRAME_STYLE_TOOLWINDOW
) )
816 eType
= GDK_WINDOW_TYPE_HINT_UTILITY
;
817 gtk_window_set_skip_taskbar_hint( GTK_WINDOW(m_pWindow
), true );
818 if( bMetaCityToolWindowHack
)
819 lcl_set_accept_focus( GTK_WINDOW(m_pWindow
), FALSE
, true );
821 else if( (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) )
823 eType
= GDK_WINDOW_TYPE_HINT_TOOLBAR
;
824 lcl_set_accept_focus( GTK_WINDOW(m_pWindow
), FALSE
, true );
827 if( (nStyle
& SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
) )
829 eType
= GDK_WINDOW_TYPE_HINT_TOOLBAR
;
830 gtk_window_set_keep_above( GTK_WINDOW(m_pWindow
), true );
833 gtk_window_set_type_hint( GTK_WINDOW(m_pWindow
), eType
);
835 gtk_window_set_decorated( GTK_WINDOW(m_pWindow
), FALSE
);
836 gtk_window_set_gravity( GTK_WINDOW(m_pWindow
), GDK_GRAVITY_STATIC
);
837 if( m_pParent
&& ! (m_pParent
->m_nStyle
& SAL_FRAME_STYLE_PLUG
) )
838 gtk_window_set_transient_for( GTK_WINDOW(m_pWindow
), GTK_WINDOW(m_pParent
->m_pWindow
) );
840 else if( (nStyle
& SAL_FRAME_STYLE_FLOAT
) )
842 gtk_window_set_type_hint( GTK_WINDOW(m_pWindow
), GDK_WINDOW_TYPE_HINT_UTILITY
);
845 m_pParent
->m_aChildren
.push_back( this );
849 if( eWinType
== GTK_WINDOW_TOPLEVEL
)
851 guint32 nUserTime
= 0;
852 if( (nStyle
& (SAL_FRAME_STYLE_OWNERDRAWDECORATION
|SAL_FRAME_STYLE_TOOLWINDOW
)) == 0 )
854 /* #i99360# ugly workaround an X11 library bug */
855 nUserTime
= getDisplay()->GetLastUserEventTime( true );
856 // nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
858 lcl_set_user_time(GTK_WIDGET(m_pWindow
)->window
, nUserTime
);
863 gtk_window_set_resizable( GTK_WINDOW(m_pWindow
), (nStyle
& SAL_FRAME_STYLE_SIZEABLE
) ? TRUE
: FALSE
);
864 if( ( (nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) ) || bMetaCityToolWindowHack
)
865 lcl_set_accept_focus( GTK_WINDOW(m_pWindow
), FALSE
, false );
870 GdkNativeWindow
GtkSalFrame::findTopLevelSystemWindow( GdkNativeWindow aWindow
)
872 XLIB_Window aRoot
, aParent
;
873 XLIB_Window
* pChildren
;
874 unsigned int nChildren
;
880 aParent
= aRoot
= None
;
881 XQueryTree( getDisplay()->GetDisplay(), aWindow
,
882 &aRoot
, &aParent
, &pChildren
, &nChildren
);
884 if( aParent
!= aRoot
)
887 Atom
* pProps
= XListProperties( getDisplay()->GetDisplay(),
890 for( int i
= 0; i
< nCount
&& ! bBreak
; ++i
)
891 bBreak
= (pProps
[i
] == XA_WM_HINTS
);
894 } while( aParent
!= aRoot
&& ! bBreak
);
899 void GtkSalFrame::Init( SystemParentData
* pSysData
)
902 m_aForeignParentWindow
= (GdkNativeWindow
)pSysData
->aWindow
;
903 m_pForeignParent
= NULL
;
904 m_aForeignTopLevelWindow
= findTopLevelSystemWindow( (GdkNativeWindow
)pSysData
->aWindow
);
905 m_pForeignTopLevel
= gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignTopLevelWindow
);
906 gdk_window_set_events( m_pForeignTopLevel
, GDK_STRUCTURE_MASK
);
908 if( pSysData
->nSize
> sizeof(pSysData
->nSize
)+sizeof(pSysData
->aWindow
) && pSysData
->bXEmbedSupport
)
910 m_pWindow
= gtk_plug_new( pSysData
->aWindow
);
911 m_bWindowIsGtkPlug
= true;
912 GTK_WIDGET_SET_FLAGS( m_pWindow
, GTK_CAN_FOCUS
| GTK_SENSITIVE
| GTK_CAN_DEFAULT
);
913 gtk_widget_set_sensitive( m_pWindow
, true );
917 m_pWindow
= gtk_window_new( GTK_WINDOW_POPUP
);
918 m_bWindowIsGtkPlug
= false;
920 m_nStyle
= SAL_FRAME_STYLE_PLUG
;
923 m_pForeignParent
= gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignParentWindow
);
924 gdk_window_set_events( m_pForeignParent
, GDK_STRUCTURE_MASK
);
926 unsigned int w
, h
, bw
, d
;
928 XGetGeometry( getDisplay()->GetDisplay(), pSysData
->aWindow
,
929 &aRoot
, &x_ret
, &y_ret
, &w
, &h
, &bw
, &d
);
930 maGeometry
.nWidth
= w
;
931 maGeometry
.nHeight
= h
;
932 gtk_window_resize( GTK_WINDOW(m_pWindow
), w
, h
);
933 gtk_window_move( GTK_WINDOW(m_pWindow
), 0, 0 );
934 if( ! m_bWindowIsGtkPlug
)
936 XReparentWindow( getDisplay()->GetDisplay(),
937 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
938 (XLIB_Window
)pSysData
->aWindow
,
943 void GtkSalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode
)
947 rtl_zeroMemory( &aEvent
, sizeof(aEvent
) );
948 aEvent
.xclient
.window
= m_aForeignParentWindow
;
949 aEvent
.xclient
.type
= ClientMessage
;
950 aEvent
.xclient
.message_type
= getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED
);
951 aEvent
.xclient
.format
= 32;
952 aEvent
.xclient
.data
.l
[0] = i_nTimeCode
? i_nTimeCode
: CurrentTime
;
953 aEvent
.xclient
.data
.l
[1] = 3; // XEMBED_REQUEST_FOCUS
954 aEvent
.xclient
.data
.l
[2] = 0;
955 aEvent
.xclient
.data
.l
[3] = 0;
956 aEvent
.xclient
.data
.l
[4] = 0;
958 getDisplay()->GetXLib()->PushXErrorLevel( true );
959 XSendEvent( getDisplay()->GetDisplay(),
960 m_aForeignParentWindow
,
961 False
, NoEventMask
, &aEvent
);
962 XSync( getDisplay()->GetDisplay(), False
);
963 getDisplay()->GetXLib()->PopXErrorLevel();
966 void GtkSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle
)
968 if( nStyle
!= m_nExtStyle
&& ! isChild() )
970 m_nExtStyle
= nStyle
;
971 if( GTK_WIDGET_REALIZED( m_pWindow
) )
973 XClassHint
* pClass
= XAllocClassHint();
974 rtl::OString aResHint
= X11SalData::getFrameResName( m_nExtStyle
);
975 pClass
->res_name
= const_cast<char*>(aResHint
.getStr());
976 pClass
->res_class
= const_cast<char*>(X11SalData::getFrameClassName());
977 XSetClassHint( getDisplay()->GetDisplay(),
978 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
983 gtk_window_set_wmclass( GTK_WINDOW(m_pWindow
),
984 X11SalData::getFrameResName( m_nExtStyle
),
985 X11SalData::getFrameClassName() );
990 SalGraphics
* GtkSalFrame::GetGraphics()
994 for( int i
= 0; i
< nMaxGraphics
; i
++ )
996 if( ! m_aGraphics
[i
].bInUse
)
998 m_aGraphics
[i
].bInUse
= true;
999 if( ! m_aGraphics
[i
].pGraphics
)
1001 m_aGraphics
[i
].pGraphics
= new GtkSalGraphics( m_pWindow
);
1002 m_aGraphics
[i
].pGraphics
->Init( this, GDK_WINDOW_XWINDOW(m_pWindow
->window
), m_nScreen
);
1004 return m_aGraphics
[i
].pGraphics
;
1012 void GtkSalFrame::ReleaseGraphics( SalGraphics
* pGraphics
)
1014 for( int i
= 0; i
< nMaxGraphics
; i
++ )
1016 if( m_aGraphics
[i
].pGraphics
== pGraphics
)
1018 m_aGraphics
[i
].bInUse
= false;
1024 BOOL
GtkSalFrame::PostEvent( void* pData
)
1026 getDisplay()->SendInternalEvent( this, pData
);
1030 void GtkSalFrame::SetTitle( const String
& rTitle
)
1033 if( m_pWindow
&& ! isChild() )
1034 gtk_window_set_title( GTK_WINDOW(m_pWindow
), rtl::OUStringToOString( rTitle
, RTL_TEXTENCODING_UTF8
).getStr() );
1037 static inline BYTE
*
1038 getRow( BitmapBuffer
*pBuffer
, ULONG nRow
)
1040 if( BMP_SCANLINE_ADJUSTMENT( pBuffer
->mnFormat
) == BMP_FORMAT_TOP_DOWN
)
1041 return pBuffer
->mpBits
+ nRow
* pBuffer
->mnScanlineSize
;
1043 return pBuffer
->mpBits
+ ( pBuffer
->mnHeight
- nRow
- 1 ) * pBuffer
->mnScanlineSize
;
1047 bitmapToPixbuf( SalBitmap
*pSalBitmap
, SalBitmap
*pSalAlpha
)
1049 g_return_val_if_fail( pSalBitmap
!= NULL
, NULL
);
1050 g_return_val_if_fail( pSalAlpha
!= NULL
, NULL
);
1052 BitmapBuffer
*pBitmap
= pSalBitmap
->AcquireBuffer( TRUE
);
1053 g_return_val_if_fail( pBitmap
!= NULL
, NULL
);
1054 g_return_val_if_fail( pBitmap
->mnBitCount
== 24, NULL
);
1056 BitmapBuffer
*pAlpha
= pSalAlpha
->AcquireBuffer( TRUE
);
1057 g_return_val_if_fail( pAlpha
!= NULL
, NULL
);
1058 g_return_val_if_fail( pAlpha
->mnBitCount
== 8, NULL
);
1060 Size aSize
= pSalBitmap
->GetSize();
1061 g_return_val_if_fail( pSalAlpha
->GetSize() == aSize
, NULL
);
1064 guchar
*pPixbufData
= (guchar
*)g_malloc (4 * aSize
.Width() * aSize
.Height() );
1065 guchar
*pDestData
= pPixbufData
;
1067 for( nY
= 0; nY
< pBitmap
->mnHeight
; nY
++ )
1069 BYTE
*pData
= getRow( pBitmap
, nY
);
1070 BYTE
*pAlphaData
= getRow( pAlpha
, nY
);
1072 for( nX
= 0; nX
< pBitmap
->mnWidth
; nX
++ )
1074 if( pBitmap
->mnFormat
== BMP_FORMAT_24BIT_TC_BGR
)
1076 pDestData
[2] = *pData
++;
1077 pDestData
[1] = *pData
++;
1078 pDestData
[0] = *pData
++;
1080 else // BMP_FORMAT_24BIT_TC_RGB
1082 pDestData
[0] = *pData
++;
1083 pDestData
[1] = *pData
++;
1084 pDestData
[2] = *pData
++;
1087 *pDestData
++ = 255 - *pAlphaData
++;
1091 pSalBitmap
->ReleaseBuffer( pBitmap
, TRUE
);
1092 pSalAlpha
->ReleaseBuffer( pAlpha
, TRUE
);
1094 return gdk_pixbuf_new_from_data( pPixbufData
,
1095 GDK_COLORSPACE_RGB
, TRUE
, 8,
1096 aSize
.Width(), aSize
.Height(),
1098 (GdkPixbufDestroyNotify
) g_free
,
1102 void GtkSalFrame::SetIcon( USHORT nIcon
)
1104 if( (m_nStyle
& (SAL_FRAME_STYLE_PLUG
|SAL_FRAME_STYLE_SYSTEMCHILD
|SAL_FRAME_STYLE_FLOAT
|SAL_FRAME_STYLE_INTRO
|SAL_FRAME_STYLE_OWNERDRAWDECORATION
))
1108 if( !ImplGetResMgr() )
1112 GList
*pIcons
= NULL
;
1114 USHORT nOffsets
[2] = { SV_ICON_SMALL_START
, SV_ICON_LARGE_START
};
1117 // Use high contrast icons where appropriate
1118 if( Application::GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
1120 nOffsets
[0] = SV_ICON_LARGE_HC_START
;
1121 nOffsets
[1] = SV_ICON_SMALL_HC_START
;
1124 for( nIndex
= 0; nIndex
< sizeof(nOffsets
)/ sizeof(USHORT
); nIndex
++ )
1126 // #i44723# workaround gcc temporary problem
1127 ResId
aResId( nOffsets
[nIndex
] + nIcon
, *ImplGetResMgr() );
1130 aIcon
= BitmapEx( aResId
);
1131 } catch (com::sun::star::uno::RuntimeException
&) {
1132 // UCB not initialized for splash screen creation; very exceptional.
1136 // #i81083# convert to 24bit/8bit alpha bitmap
1137 Bitmap aBmp
= aIcon
.GetBitmap();
1138 if( aBmp
.GetBitCount() != 24 || ! aIcon
.IsAlpha() )
1140 if( aBmp
.GetBitCount() != 24 )
1141 aBmp
.Convert( BMP_CONVERSION_24BIT
);
1143 if( ! aIcon
.IsAlpha() )
1145 switch( aIcon
.GetTransparentType() )
1147 case TRANSPARENT_NONE
:
1150 aMask
= AlphaMask( aBmp
.GetSizePixel(), &nTrans
);
1153 case TRANSPARENT_COLOR
:
1154 aMask
= AlphaMask( aBmp
.CreateMask( aIcon
.GetTransparentColor() ) );
1156 case TRANSPARENT_BITMAP
:
1157 aMask
= AlphaMask( aIcon
.GetMask() );
1160 DBG_ERROR( "unhandled transparent type" );
1165 aMask
= aIcon
.GetAlpha();
1166 aIcon
= BitmapEx( aBmp
, aMask
);
1169 ImpBitmap
*pIconImpBitmap
= aIcon
.ImplGetBitmapImpBitmap();
1170 ImpBitmap
*pIconImpMask
= aIcon
.ImplGetMaskImpBitmap();
1173 if( pIconImpBitmap
&& pIconImpMask
)
1175 SalBitmap
*pIconBitmap
=
1176 pIconImpBitmap
->ImplGetSalBitmap();
1177 SalBitmap
*pIconMask
=
1178 pIconImpMask
->ImplGetSalBitmap();
1180 if( ( pBuf
= bitmapToPixbuf( pIconBitmap
, pIconMask
) ) )
1181 pIcons
= g_list_prepend( pIcons
, pBuf
);
1185 gtk_window_set_icon_list( GTK_WINDOW(m_pWindow
), pIcons
);
1187 g_list_foreach( pIcons
, (GFunc
) g_object_unref
, NULL
);
1188 g_list_free( pIcons
);
1191 void GtkSalFrame::SetMenu( SalMenu
* )
1195 void GtkSalFrame::DrawMenuBar()
1199 void GtkSalFrame::Center()
1205 nX
= ((long)m_pParent
->maGeometry
.nWidth
- (long)maGeometry
.nWidth
)/2;
1206 nY
= ((long)m_pParent
->maGeometry
.nHeight
- (long)maGeometry
.nHeight
)/2;
1211 long nScreenWidth
, nScreenHeight
;
1212 long nScreenX
= 0, nScreenY
= 0;
1214 Size aScreenSize
= GetX11SalData()->GetDisplay()->GetScreenSize( m_nScreen
);
1215 nScreenWidth
= aScreenSize
.Width();
1216 nScreenHeight
= aScreenSize
.Height();
1217 if( GetX11SalData()->GetDisplay()->IsXinerama() )
1219 // get xinerama screen we are on
1220 // if there is a parent, use its center for screen determination
1221 // else use the pointer
1224 GdkModifierType aMask
;
1225 gdk_display_get_pointer( getGdkDisplay(), &pScreen
, &x
, &y
, &aMask
);
1227 const std::vector
< Rectangle
>& rScreens
= GetX11SalData()->GetDisplay()->GetXineramaScreens();
1228 for( unsigned int i
= 0; i
< rScreens
.size(); i
++ )
1229 if( rScreens
[i
].IsInside( Point( x
, y
) ) )
1231 nScreenX
= rScreens
[i
].Left();
1232 nScreenY
= rScreens
[i
].Top();
1233 nScreenWidth
= rScreens
[i
].GetWidth();
1234 nScreenHeight
= rScreens
[i
].GetHeight();
1238 nX
= nScreenX
+ (nScreenWidth
- (long)maGeometry
.nWidth
)/2;
1239 nY
= nScreenY
+ (nScreenHeight
- (long)maGeometry
.nHeight
)/2;
1241 SetPosSize( nX
, nY
, 0, 0, SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
);
1244 Size
GtkSalFrame::calcDefaultSize()
1246 Size aScreenSize
= GetX11SalData()->GetDisplay()->GetScreenSize( m_nScreen
);
1247 long w
= aScreenSize
.Width();
1248 long h
= aScreenSize
.Height();
1250 // fill in holy default values brought to us by product management
1251 if( aScreenSize
.Width() >= 800 )
1253 if( aScreenSize
.Width() >= 1024 )
1256 if( aScreenSize
.Height() >= 600 )
1258 if( aScreenSize
.Height() >= 768 )
1260 if( aScreenSize
.Height() >= 1024 )
1263 return Size( w
, h
);
1266 void GtkSalFrame::SetDefaultSize()
1268 Size aDefSize
= calcDefaultSize();
1270 SetPosSize( 0, 0, aDefSize
.Width(), aDefSize
.Height(),
1271 SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
);
1273 if( (m_nStyle
& SAL_FRAME_STYLE_DEFAULT
) && m_pWindow
)
1274 gtk_window_maximize( GTK_WINDOW(m_pWindow
) );
1277 static void initClientId()
1279 static bool bOnce
= false;
1283 const ByteString
& rID
= SessionManagerClient::getSessionID();
1285 gdk_set_sm_client_id(rID
.GetBuffer());
1289 void GtkSalFrame::Show( BOOL bVisible
, BOOL bNoActivate
)
1293 if( m_pParent
&& (m_pParent
->m_nStyle
& SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
) )
1294 gtk_window_set_keep_above( GTK_WINDOW(m_pWindow
), bVisible
);
1297 SessionManagerClient::open(); // will simply return after the first time
1299 getDisplay()->startupNotificationCompleted();
1303 if( m_bDefaultSize
)
1307 // #i45160# switch to desktop where a dialog with parent will appear
1308 if( m_pParent
&& m_pParent
->m_nWorkArea
!= m_nWorkArea
)
1309 getDisplay()->getWMAdaptor()->switchToWorkArea( m_pParent
->m_nWorkArea
);
1311 if( isFloatGrabWindow() &&
1314 ! getDisplay()->GetCaptureFrame() )
1317 * outsmart Metacity's "focus:mouse" mode
1318 * which insists on taking the focus from the document
1319 * to the new float. Grab focus to parent frame BEFORE
1320 * showing the float (cannot grab it to the float
1323 m_pParent
->grabPointer( TRUE
, TRUE
);
1326 guint32 nUserTime
= 0;
1327 if( ! bNoActivate
&& (m_nStyle
& (SAL_FRAME_STYLE_OWNERDRAWDECORATION
|SAL_FRAME_STYLE_TOOLWINDOW
)) == 0 )
1328 /* #i99360# ugly workaround an X11 library bug */
1329 nUserTime
= getDisplay()->GetLastUserEventTime( true );
1330 //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
1332 //For these floating windows we don't want the main window to lose focus, and metacity has...
1333 // metacity-2.24.0/src/core/window.c
1335 // if ((focus_window != NULL) && XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time))
1336 // "compare" window focus prevented by other activity
1338 // where "compare" is this window
1340 // which leads to...
1342 // /* This happens for error dialogs or alerts; these need to remain on
1343 // * top, but it would be confusing to have its ancestor remain
1346 // if (meta_window_is_ancestor_of_transient (focus_window, window))
1347 // "The focus window %s is an ancestor of the newly mapped "
1348 // "window %s which isn't being focused. Unfocusing the "
1351 // i.e. having a time < that of the toplevel frame means that the toplevel frame gets unfocused.
1353 if( nUserTime
== 0 &&
1355 getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") ||
1357 getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz") &&
1358 (m_nStyle
& (SAL_FRAME_STYLE_OWNERDRAWDECORATION
))
1363 /* #i99360# ugly workaround an X11 library bug */
1364 nUserTime
= getDisplay()->GetLastUserEventTime( true );
1365 //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
1368 lcl_set_user_time( GTK_WIDGET(m_pWindow
)->window
, nUserTime
);
1370 gtk_widget_show( m_pWindow
);
1372 if( isFloatGrabWindow() )
1375 if( ! getDisplay()->GetCaptureFrame() && m_nFloats
== 1 )
1376 grabPointer( TRUE
, TRUE
);
1377 // #i44068# reset parent's IM context
1379 m_pParent
->EndExtTextInput(0);
1381 if( m_bWindowIsGtkPlug
)
1382 askForXEmbedFocus( 0 );
1386 if( isFloatGrabWindow() )
1389 if( ! getDisplay()->GetCaptureFrame() && m_nFloats
== 0)
1390 grabPointer( FALSE
);
1392 gtk_widget_hide( m_pWindow
);
1394 m_pIMHandler
->focusChanged( false );
1396 CallCallback( SALEVENT_RESIZE
, NULL
);
1400 void GtkSalFrame::Enable( BOOL
/*bEnable*/ )
1402 // Not implemented by X11SalFrame either
1405 void GtkSalFrame::setMinMaxSize()
1407 /* FIXME: for yet unknown reasons the reported size is a little smaller
1408 * than the max size hint; one would guess that this was due to the border
1409 * sizes of the widgets involved (GtkWindow and GtkFixed), but setting the
1410 * their border to 0 (which is the default anyway) does not change the
1411 * behaviour. Until the reason is known we'll add some pixels here.
1413 #define CONTAINER_ADJUSTMENT 6
1415 /* #i34504# metacity (and possibly others) do not treat
1416 * _NET_WM_STATE_FULLSCREEN and max_width/heigth independently;
1417 * whether they should is undefined. So don't set the max size hint
1418 * for a full screen window.
1420 if( m_pWindow
&& ! isChild() )
1424 if( m_nStyle
& SAL_FRAME_STYLE_SIZEABLE
)
1426 if( m_aMinSize
.Width() && m_aMinSize
.Height() )
1428 aGeo
.min_width
= m_aMinSize
.Width()+CONTAINER_ADJUSTMENT
;
1429 aGeo
.min_height
= m_aMinSize
.Height()+CONTAINER_ADJUSTMENT
;
1430 aHints
|= GDK_HINT_MIN_SIZE
;
1432 if( m_aMaxSize
.Width() && m_aMaxSize
.Height() && ! m_bFullscreen
)
1434 aGeo
.max_width
= m_aMaxSize
.Width()+CONTAINER_ADJUSTMENT
;
1435 aGeo
.max_height
= m_aMaxSize
.Height()+CONTAINER_ADJUSTMENT
;
1436 aHints
|= GDK_HINT_MAX_SIZE
;
1441 aGeo
.min_width
= maGeometry
.nWidth
;
1442 aGeo
.min_height
= maGeometry
.nHeight
;
1443 aHints
|= GDK_HINT_MIN_SIZE
;
1444 if( ! m_bFullscreen
)
1446 aGeo
.max_width
= maGeometry
.nWidth
;
1447 aGeo
.max_height
= maGeometry
.nHeight
;
1448 aHints
|= GDK_HINT_MAX_SIZE
;
1452 gtk_window_set_geometry_hints( GTK_WINDOW(m_pWindow
),
1455 GdkWindowHints( aHints
) );
1459 void GtkSalFrame::SetMaxClientSize( long nWidth
, long nHeight
)
1463 m_aMaxSize
= Size( nWidth
, nHeight
);
1464 // Show does a setMinMaxSize
1465 if( GTK_WIDGET_MAPPED( m_pWindow
) )
1469 void GtkSalFrame::SetMinClientSize( long nWidth
, long nHeight
)
1473 m_aMinSize
= Size( nWidth
, nHeight
);
1476 gtk_widget_set_size_request( m_pWindow
, nWidth
, nHeight
);
1477 // Show does a setMinMaxSize
1478 if( GTK_WIDGET_MAPPED( m_pWindow
) )
1484 void GtkSalFrame::SetPosSize( long nX
, long nY
, long nWidth
, long nHeight
, USHORT nFlags
)
1486 if( !m_pWindow
|| isChild( true, false ) )
1489 bool bSized
= false, bMoved
= false;
1491 if( (nFlags
& ( SAL_FRAME_POSSIZE_WIDTH
| SAL_FRAME_POSSIZE_HEIGHT
)) &&
1492 (nWidth
> 0 && nHeight
> 0 ) // sometimes stupid things happen
1495 m_bDefaultSize
= false;
1497 if( (unsigned long)nWidth
!= maGeometry
.nWidth
|| (unsigned long)nHeight
!= maGeometry
.nHeight
)
1499 maGeometry
.nWidth
= nWidth
;
1500 maGeometry
.nHeight
= nHeight
;
1502 if( isChild( false, true ) )
1503 gtk_widget_set_size_request( m_pWindow
, nWidth
, nHeight
);
1505 gtk_window_resize( GTK_WINDOW(m_pWindow
), nWidth
, nHeight
);
1508 else if( m_bDefaultSize
)
1511 m_bDefaultSize
= false;
1513 if( nFlags
& ( SAL_FRAME_POSSIZE_X
| SAL_FRAME_POSSIZE_Y
) )
1517 if( Application::GetSettings().GetLayoutRTL() )
1518 nX
= m_pParent
->maGeometry
.nWidth
-maGeometry
.nWidth
-1-nX
;
1519 nX
+= m_pParent
->maGeometry
.nX
;
1520 nY
+= m_pParent
->maGeometry
.nY
;
1523 // adjust position to avoid off screen windows
1524 // but allow toolbars to be positioned partly off screen by the user
1525 Size aScreenSize
= GetX11SalData()->GetDisplay()->GetScreenSize( m_nScreen
);
1526 if( ! (m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) )
1528 if( nX
< (long)maGeometry
.nLeftDecoration
)
1529 nX
= maGeometry
.nLeftDecoration
;
1530 if( nY
< (long)maGeometry
.nTopDecoration
)
1531 nY
= maGeometry
.nTopDecoration
;
1532 if( (nX
+ (long)maGeometry
.nWidth
+ (long)maGeometry
.nRightDecoration
) > (long)aScreenSize
.Width() )
1533 nX
= aScreenSize
.Width() - maGeometry
.nWidth
- maGeometry
.nRightDecoration
;
1534 if( (nY
+ (long)maGeometry
.nHeight
+ (long)maGeometry
.nBottomDecoration
) > (long)aScreenSize
.Height() )
1535 nY
= aScreenSize
.Height() - maGeometry
.nHeight
- maGeometry
.nBottomDecoration
;
1539 if( nX
+ (long)maGeometry
.nWidth
< 10 )
1540 nX
= 10 - (long)maGeometry
.nWidth
;
1541 if( nY
+ (long)maGeometry
.nHeight
< 10 )
1542 nY
= 10 - (long)maGeometry
.nHeight
;
1543 if( nX
> (long)aScreenSize
.Width() - 10 )
1544 nX
= (long)aScreenSize
.Width() - 10;
1545 if( nY
> (long)aScreenSize
.Height() - 10 )
1546 nY
= (long)aScreenSize
.Height() - 10;
1549 if( nX
!= maGeometry
.nX
|| nY
!= maGeometry
.nY
)
1554 m_bDefaultPos
= false;
1556 moveWindow( maGeometry
.nX
, maGeometry
.nY
);
1558 updateScreenNumber();
1560 else if( m_bDefaultPos
)
1563 m_bDefaultPos
= false;
1565 if( bSized
&& ! bMoved
)
1566 CallCallback( SALEVENT_RESIZE
, NULL
);
1567 else if( bMoved
&& ! bSized
)
1568 CallCallback( SALEVENT_MOVE
, NULL
);
1569 else if( bMoved
&& bSized
)
1570 CallCallback( SALEVENT_MOVERESIZE
, NULL
);
1573 void GtkSalFrame::GetClientSize( long& rWidth
, long& rHeight
)
1575 if( m_pWindow
&& !(m_nState
& GDK_WINDOW_STATE_ICONIFIED
) )
1577 rWidth
= maGeometry
.nWidth
;
1578 rHeight
= maGeometry
.nHeight
;
1581 rWidth
= rHeight
= 0;
1584 void GtkSalFrame::GetWorkArea( Rectangle
& rRect
)
1586 rRect
= GetX11SalData()->GetDisplay()->getWMAdaptor()->getWorkArea( 0 );
1589 SalFrame
* GtkSalFrame::GetParent() const
1594 void GtkSalFrame::SetWindowState( const SalFrameState
* pState
)
1596 if( ! m_pWindow
|| ! pState
|| isChild( true, false ) )
1599 const ULONG nMaxGeometryMask
=
1600 SAL_FRAMESTATE_MASK_X
| SAL_FRAMESTATE_MASK_Y
|
1601 SAL_FRAMESTATE_MASK_WIDTH
| SAL_FRAMESTATE_MASK_HEIGHT
|
1602 SAL_FRAMESTATE_MASK_MAXIMIZED_X
| SAL_FRAMESTATE_MASK_MAXIMIZED_Y
|
1603 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH
| SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT
;
1605 if( (pState
->mnMask
& SAL_FRAMESTATE_MASK_STATE
) &&
1606 (pState
->mnState
& SAL_FRAMESTATE_MAXIMIZED
) &&
1607 (pState
->mnMask
& nMaxGeometryMask
) == nMaxGeometryMask
)
1609 resizeWindow( pState
->mnWidth
, pState
->mnHeight
);
1610 moveWindow( pState
->mnX
, pState
->mnY
);
1611 m_bDefaultPos
= m_bDefaultSize
= false;
1613 maGeometry
.nX
= pState
->mnMaximizedX
;
1614 maGeometry
.nY
= pState
->mnMaximizedY
;
1615 maGeometry
.nWidth
= pState
->mnMaximizedWidth
;
1616 maGeometry
.nHeight
= pState
->mnMaximizedHeight
;
1617 updateScreenNumber();
1619 m_nState
= GdkWindowState( m_nState
| GDK_WINDOW_STATE_MAXIMIZED
);
1620 m_aRestorePosSize
= Rectangle( Point( pState
->mnX
, pState
->mnY
),
1621 Size( pState
->mnWidth
, pState
->mnHeight
) );
1623 else if( pState
->mnMask
& (SAL_FRAMESTATE_MASK_X
| SAL_FRAMESTATE_MASK_Y
|
1624 SAL_FRAMESTATE_MASK_WIDTH
| SAL_FRAMESTATE_MASK_HEIGHT
) )
1626 USHORT nPosSizeFlags
= 0;
1627 long nX
= pState
->mnX
- (m_pParent
? m_pParent
->maGeometry
.nX
: 0);
1628 long nY
= pState
->mnY
- (m_pParent
? m_pParent
->maGeometry
.nY
: 0);
1629 long nWidth
= pState
->mnWidth
;
1630 long nHeight
= pState
->mnHeight
;
1631 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_X
)
1632 nPosSizeFlags
|= SAL_FRAME_POSSIZE_X
;
1634 nX
= maGeometry
.nX
- (m_pParent
? m_pParent
->maGeometry
.nX
: 0);
1635 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_Y
)
1636 nPosSizeFlags
|= SAL_FRAME_POSSIZE_Y
;
1638 nY
= maGeometry
.nY
- (m_pParent
? m_pParent
->maGeometry
.nY
: 0);
1639 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_WIDTH
)
1640 nPosSizeFlags
|= SAL_FRAME_POSSIZE_WIDTH
;
1642 nWidth
= maGeometry
.nWidth
;
1643 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_HEIGHT
)
1644 nPosSizeFlags
|= SAL_FRAME_POSSIZE_HEIGHT
;
1646 nHeight
= maGeometry
.nHeight
;
1647 SetPosSize( nX
, nY
, pState
->mnWidth
, pState
->mnHeight
, nPosSizeFlags
);
1649 if( pState
->mnMask
& SAL_FRAMESTATE_MASK_STATE
&& ! isChild() )
1651 if( pState
->mnState
& SAL_FRAMESTATE_MAXIMIZED
)
1652 gtk_window_maximize( GTK_WINDOW(m_pWindow
) );
1654 gtk_window_unmaximize( GTK_WINDOW(m_pWindow
) );
1655 /* #i42379# there is no rollup state in GDK; and rolled up windows are
1656 * (probably depending on the WM) reported as iconified. If we iconify a
1657 * window here that was e.g. a dialog, then it will be unmapped but still
1658 * not be displayed in the task list, so it's an iconified window that
1659 * the user cannot get out of this state. So do not set the iconified state
1660 * on windows with a parent (that is transient frames) since these tend
1661 * to not be represented in an icon task list.
1663 if( (pState
->mnState
& SAL_FRAMESTATE_MINIMIZED
)
1665 gtk_window_iconify( GTK_WINDOW(m_pWindow
) );
1667 gtk_window_deiconify( GTK_WINDOW(m_pWindow
) );
1671 BOOL
GtkSalFrame::GetWindowState( SalFrameState
* pState
)
1673 pState
->mnState
= SAL_FRAMESTATE_NORMAL
;
1674 pState
->mnMask
= SAL_FRAMESTATE_MASK_STATE
;
1675 // rollup ? gtk 2.2 does not seem to support the shaded state
1676 if( (m_nState
& GDK_WINDOW_STATE_ICONIFIED
) )
1677 pState
->mnState
|= SAL_FRAMESTATE_MINIMIZED
;
1678 if( m_nState
& GDK_WINDOW_STATE_MAXIMIZED
)
1680 pState
->mnState
|= SAL_FRAMESTATE_MAXIMIZED
;
1681 pState
->mnX
= m_aRestorePosSize
.Left();
1682 pState
->mnY
= m_aRestorePosSize
.Top();
1683 pState
->mnWidth
= m_aRestorePosSize
.GetWidth();
1684 pState
->mnHeight
= m_aRestorePosSize
.GetHeight();
1685 pState
->mnMaximizedX
= maGeometry
.nX
;
1686 pState
->mnMaximizedY
= maGeometry
.nY
;
1687 pState
->mnMaximizedWidth
= maGeometry
.nWidth
;
1688 pState
->mnMaximizedHeight
= maGeometry
.nHeight
;
1689 pState
->mnMask
|= SAL_FRAMESTATE_MASK_MAXIMIZED_X
|
1690 SAL_FRAMESTATE_MASK_MAXIMIZED_Y
|
1691 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH
|
1692 SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT
;
1697 pState
->mnX
= maGeometry
.nX
;
1698 pState
->mnY
= maGeometry
.nY
;
1699 pState
->mnWidth
= maGeometry
.nWidth
;
1700 pState
->mnHeight
= maGeometry
.nHeight
;
1702 pState
->mnMask
|= SAL_FRAMESTATE_MASK_X
|
1703 SAL_FRAMESTATE_MASK_Y
|
1704 SAL_FRAMESTATE_MASK_WIDTH
|
1705 SAL_FRAMESTATE_MASK_HEIGHT
;
1710 void GtkSalFrame::moveToScreen( int nScreen
)
1715 if( nScreen
< 0 || nScreen
>= gdk_display_get_n_screens( getGdkDisplay() ) )
1716 nScreen
= m_nScreen
;
1717 if( nScreen
== m_nScreen
)
1720 GdkScreen
* pScreen
= gdk_display_get_screen( getGdkDisplay(), nScreen
);
1723 m_nScreen
= nScreen
;
1724 gtk_window_set_screen( GTK_WINDOW(m_pWindow
), pScreen
);
1725 // realize the window, we need an XWindow id
1726 gtk_widget_realize( m_pWindow
);
1727 // update system data
1728 GtkSalDisplay
* pDisp
= getDisplay();
1729 m_aSystemData
.aWindow
= GDK_WINDOW_XWINDOW(m_pWindow
->window
);
1730 m_aSystemData
.pVisual
= pDisp
->GetVisual( m_nScreen
).GetVisual();
1731 m_aSystemData
.nScreen
= nScreen
;
1732 m_aSystemData
.nDepth
= pDisp
->GetVisual( m_nScreen
).GetDepth();
1733 m_aSystemData
.aColormap
= pDisp
->GetColormap( m_nScreen
).GetXColormap();
1734 m_aSystemData
.pAppContext
= NULL
;
1735 m_aSystemData
.aShellWindow
= m_aSystemData
.aWindow
;
1736 // update graphics if necessary
1737 for( unsigned int i
= 0; i
< sizeof(m_aGraphics
)/sizeof(m_aGraphics
[0]); i
++ )
1739 if( m_aGraphics
[i
].bInUse
)
1740 m_aGraphics
[i
].pGraphics
->SetDrawable( GDK_WINDOW_XWINDOW(m_pWindow
->window
), m_nScreen
);
1742 updateScreenNumber();
1745 if( m_pParent
&& m_pParent
->m_nScreen
!= m_nScreen
)
1747 std::list
< GtkSalFrame
* > aChildren
= m_aChildren
;
1748 for( std::list
< GtkSalFrame
* >::iterator it
= aChildren
.begin(); it
!= aChildren
.end(); ++it
)
1749 (*it
)->moveToScreen( m_nScreen
);
1751 // FIXME: SalObjects
1754 void GtkSalFrame::SetScreenNumber( unsigned int nNewScreen
)
1756 if( nNewScreen
== maGeometry
.nScreenNumber
)
1759 if( m_pWindow
&& ! isChild() )
1761 GtkSalDisplay
* pDisp
= getDisplay();
1762 if( pDisp
->IsXinerama() && pDisp
->GetXineramaScreens().size() > 1 )
1764 if( nNewScreen
>= pDisp
->GetXineramaScreens().size() )
1767 Rectangle
aOldScreenRect( pDisp
->GetXineramaScreens()[maGeometry
.nScreenNumber
] );
1768 Rectangle
aNewScreenRect( pDisp
->GetXineramaScreens()[nNewScreen
] );
1769 bool bVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
1772 maGeometry
.nX
= aNewScreenRect
.Left() + (maGeometry
.nX
- aOldScreenRect
.Left());
1773 maGeometry
.nY
= aNewScreenRect
.Top() + (maGeometry
.nY
- aOldScreenRect
.Top());
1774 createNewWindow( None
, false, m_nScreen
);
1775 gtk_window_move( GTK_WINDOW(m_pWindow
), maGeometry
.nX
, maGeometry
.nY
);
1778 maGeometry
.nScreenNumber
= nNewScreen
;
1780 else if( sal_Int32(nNewScreen
) < pDisp
->GetScreenCount() )
1782 moveToScreen( (int)nNewScreen
);
1783 maGeometry
.nScreenNumber
= nNewScreen
;
1784 gtk_window_move( GTK_WINDOW(m_pWindow
), maGeometry
.nX
, maGeometry
.nY
);
1789 void GtkSalFrame::ShowFullScreen( BOOL bFullScreen
, sal_Int32 nScreen
)
1791 if( m_pWindow
&& ! isChild() )
1793 GtkSalDisplay
* pDisp
= getDisplay();
1795 if( pDisp
->IsXinerama() && pDisp
->GetXineramaScreens().size() > 1 )
1799 m_aRestorePosSize
= Rectangle( Point( maGeometry
.nX
, maGeometry
.nY
),
1800 Size( maGeometry
.nWidth
, maGeometry
.nHeight
) );
1801 // workaround different window managers have different opinions about
1802 // _NET_WM_STATE_FULLSCREEN (Metacity <-> KWin)
1803 bool bVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
1806 m_nStyle
|= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
;
1807 createNewWindow( None
, false, m_nScreen
);
1808 Rectangle aNewPosSize
;
1809 if( nScreen
< 0 || nScreen
>= static_cast<int>(pDisp
->GetXineramaScreens().size()) )
1810 aNewPosSize
= Rectangle( Point( 0, 0 ), pDisp
->GetScreenSize(m_nScreen
) );
1812 aNewPosSize
= pDisp
->GetXineramaScreens()[ nScreen
];
1813 gtk_window_resize( GTK_WINDOW(m_pWindow
),
1814 maGeometry
.nWidth
= aNewPosSize
.GetWidth(),
1815 maGeometry
.nHeight
= aNewPosSize
.GetHeight() );
1816 gtk_window_move( GTK_WINDOW(m_pWindow
),
1817 maGeometry
.nX
= aNewPosSize
.Left(),
1818 maGeometry
.nY
= aNewPosSize
.Top() );
1824 bool bVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
1827 m_nStyle
&= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN
;
1828 createNewWindow( None
, false, m_nScreen
);
1829 if( ! m_aRestorePosSize
.IsEmpty() )
1831 gtk_window_resize( GTK_WINDOW(m_pWindow
),
1832 maGeometry
.nWidth
= m_aRestorePosSize
.GetWidth(),
1833 maGeometry
.nHeight
= m_aRestorePosSize
.GetHeight() );
1834 gtk_window_move( GTK_WINDOW(m_pWindow
),
1835 maGeometry
.nX
= m_aRestorePosSize
.Left(),
1836 maGeometry
.nY
= m_aRestorePosSize
.Top() );
1837 m_aRestorePosSize
= Rectangle();
1847 if( !(m_nStyle
& SAL_FRAME_STYLE_SIZEABLE
) )
1848 gtk_window_set_resizable( GTK_WINDOW(m_pWindow
), TRUE
);
1849 gtk_window_fullscreen( GTK_WINDOW(m_pWindow
) );
1850 moveToScreen( nScreen
);
1851 Size aScreenSize
= pDisp
->GetScreenSize( m_nScreen
);
1854 maGeometry
.nWidth
= aScreenSize
.Width();
1855 maGeometry
.nHeight
= aScreenSize
.Height();
1859 gtk_window_unfullscreen( GTK_WINDOW(m_pWindow
) );
1860 if( !(m_nStyle
& SAL_FRAME_STYLE_SIZEABLE
) )
1861 gtk_window_set_resizable( GTK_WINDOW(m_pWindow
), FALSE
);
1862 moveToScreen( nScreen
);
1865 m_bDefaultPos
= m_bDefaultSize
= false;
1866 updateScreenNumber();
1867 CallCallback( SALEVENT_MOVERESIZE
, NULL
);
1869 m_bFullscreen
= bFullScreen
;
1872 /* definitions from xautolock.c (pl15) */
1873 #define XAUTOLOCK_DISABLE 1
1874 #define XAUTOLOCK_ENABLE 2
1876 void GtkSalFrame::setAutoLock( bool bLock
)
1881 GdkScreen
*pScreen
= gtk_window_get_screen( GTK_WINDOW(m_pWindow
) );
1882 GdkDisplay
*pDisplay
= gdk_screen_get_display( pScreen
);
1883 GdkWindow
*pRootWin
= gdk_screen_get_root_window( pScreen
);
1885 Atom nAtom
= XInternAtom( GDK_DISPLAY_XDISPLAY( pDisplay
),
1886 "XAUTOLOCK_MESSAGE", False
);
1888 int nMessage
= bLock
? XAUTOLOCK_ENABLE
: XAUTOLOCK_DISABLE
;
1890 XChangeProperty( GDK_DISPLAY_XDISPLAY( pDisplay
),
1891 GDK_WINDOW_XID( pRootWin
),
1894 (unsigned char*)&nMessage
,
1895 sizeof( nMessage
) );
1899 /** cookie is returned as an unsigned integer */
1901 dbus_inhibit_gss (const gchar
*appname
,
1902 const gchar
*reason
)
1906 GError
*error
= NULL
;
1907 DBusGProxy
*proxy
= NULL
;
1908 DBusGConnection
*session_connection
= NULL
;
1910 /* get the DBUS session connection */
1911 session_connection
= dbus_g_bus_get (DBUS_BUS_SESSION
, &error
);
1912 if (error
!= NULL
) {
1913 g_warning ("DBUS cannot connect : %s", error
->message
);
1914 g_error_free (error
);
1918 /* get the proxy with gnome-screensaver */
1919 proxy
= dbus_g_proxy_new_for_name (session_connection
,
1922 GSS_DBUS_INTERFACE
);
1923 if (proxy
== NULL
) {
1924 g_warning ("Could not get DBUS proxy: %s", GSS_DBUS_SERVICE
);
1928 res
= dbus_g_proxy_call (proxy
,
1930 G_TYPE_STRING
, appname
,
1931 G_TYPE_STRING
, reason
,
1933 G_TYPE_UINT
, &cookie
,
1936 /* check the return value */
1939 g_warning ("Inhibit method failed");
1942 /* check the error value */
1943 if (error
!= NULL
) {
1944 g_warning ("Inhibit problem : %s", error
->message
);
1945 g_error_free (error
);
1949 g_object_unref (G_OBJECT (proxy
));
1954 dbus_uninhibit_gss (guint cookie
)
1957 GError
*error
= NULL
;
1958 DBusGProxy
*proxy
= NULL
;
1959 DBusGConnection
*session_connection
= NULL
;
1961 /* cookies have to be positive as unsigned */
1963 g_warning ("Invalid cookie");
1967 /* get the DBUS session connection */
1968 session_connection
= dbus_g_bus_get (DBUS_BUS_SESSION
, &error
);
1970 g_warning ("DBUS cannot connect : %s", error
->message
);
1971 g_error_free (error
);
1975 /* get the proxy with gnome-screensaver */
1976 proxy
= dbus_g_proxy_new_for_name (session_connection
,
1979 GSS_DBUS_INTERFACE
);
1980 if (proxy
== NULL
) {
1981 g_warning ("Could not get DBUS proxy: %s", GSS_DBUS_SERVICE
);
1985 res
= dbus_g_proxy_call (proxy
,
1988 G_TYPE_UINT
, cookie
,
1992 /* check the return value */
1994 g_warning ("UnInhibit method failed");
1997 /* check the error value */
1998 if (error
!= NULL
) {
1999 g_warning ("Inhibit problem : %s", error
->message
);
2000 g_error_free (error
);
2003 g_object_unref (G_OBJECT (proxy
));
2007 void GtkSalFrame::StartPresentation( BOOL bStart
)
2009 Display
*pDisplay
= GDK_DISPLAY_XDISPLAY( getGdkDisplay() );
2011 setAutoLock( !bStart
);
2013 int nTimeout
, nInterval
, bPreferBlanking
, bAllowExposures
;
2015 XGetScreenSaver( pDisplay
, &nTimeout
, &nInterval
,
2016 &bPreferBlanking
, &bAllowExposures
);
2021 m_nSavedScreenSaverTimeout
= nTimeout
;
2022 XResetScreenSaver( pDisplay
);
2023 XSetScreenSaver( pDisplay
, 0, nInterval
,
2024 bPreferBlanking
, bAllowExposures
);
2027 m_nGSSCookie
= dbus_inhibit_gss(g_get_application_name(), "presentation");
2032 if( m_nSavedScreenSaverTimeout
)
2033 XSetScreenSaver( pDisplay
, m_nSavedScreenSaverTimeout
,
2034 nInterval
, bPreferBlanking
,
2036 m_nSavedScreenSaverTimeout
= 0;
2038 dbus_uninhibit_gss(m_nGSSCookie
);
2043 void GtkSalFrame::SetAlwaysOnTop( BOOL
/*bOnTop*/ )
2047 void GtkSalFrame::ToTop( USHORT nFlags
)
2051 if( isChild( false, true ) )
2052 gtk_widget_grab_focus( m_pWindow
);
2053 else if( GTK_WIDGET_MAPPED( m_pWindow
) )
2055 if( ! (nFlags
& SAL_FRAME_TOTOP_GRABFOCUS_ONLY
) )
2056 gtk_window_present( GTK_WINDOW(m_pWindow
) );
2059 // gdk_window_focus( m_pWindow->window, gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window) );
2060 /* #i99360# ugly workaround an X11 library bug */
2061 guint32 nUserTime
= getDisplay()->GetLastUserEventTime( true );
2062 gdk_window_focus( m_pWindow
->window
, nUserTime
);
2064 /* need to do an XSetInputFocus here because
2065 * gdk_window_focus will ask a EWMH compliant WM to put the focus
2066 * to our window - which it of course won't since our input hint
2069 if( (m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) )
2070 XSetInputFocus( getDisplay()->GetDisplay(), GDK_WINDOW_XWINDOW( m_pWindow
->window
), RevertToParent
, CurrentTime
);
2074 if( nFlags
& SAL_FRAME_TOTOP_RESTOREWHENMIN
)
2075 gtk_window_present( GTK_WINDOW(m_pWindow
) );
2080 void GtkSalFrame::SetPointer( PointerStyle ePointerStyle
)
2082 if( m_pWindow
&& ePointerStyle
!= m_ePointerStyle
)
2084 m_ePointerStyle
= ePointerStyle
;
2085 GdkCursor
*pCursor
= getDisplay()->getCursor( ePointerStyle
);
2086 gdk_window_set_cursor( m_pWindow
->window
, pCursor
);
2087 m_pCurrentCursor
= pCursor
;
2089 // #i80791# use grabPointer the same way as CaptureMouse, respective float grab
2090 if( getDisplay()->MouseCaptured( this ) )
2091 grabPointer( TRUE
, FALSE
);
2092 else if( m_nFloats
> 0 )
2093 grabPointer( TRUE
, TRUE
);
2097 void GtkSalFrame::grabPointer( BOOL bGrab
, BOOL bOwnerEvents
)
2103 bool bUseGdkGrab
= true;
2104 if( getDisplay()->getHaveSystemChildFrame() )
2106 const std::list
< SalFrame
* >& rFrames
= getDisplay()->getFrames();
2107 for( std::list
< SalFrame
* >::const_iterator it
= rFrames
.begin(); it
!= rFrames
.end(); ++it
)
2109 const GtkSalFrame
* pFrame
= static_cast< const GtkSalFrame
* >(*it
);
2110 if( pFrame
->m_bWindowIsGtkPlug
)
2112 bUseGdkGrab
= false;
2119 const int nMask
= ( GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK
);
2121 gdk_pointer_grab( m_pWindow
->window
, bOwnerEvents
,
2122 (GdkEventMask
) nMask
, NULL
, m_pCurrentCursor
,
2127 // FIXME: for some unknown reason gdk_pointer_grab does not
2128 // really produce owner events for GtkPlug windows
2129 // the cause is yet unknown
2131 // this is of course a bad hack, especially as we cannot
2132 // set the right cursor this way
2133 XGrabPointer( getDisplay()->GetDisplay(),
2134 GDK_WINDOW_XWINDOW( m_pWindow
->window
),
2136 PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
,
2148 // Two GdkDisplays may be open
2149 gdk_display_pointer_ungrab( getGdkDisplay(), GDK_CURRENT_TIME
);
2154 void GtkSalFrame::CaptureMouse( BOOL bCapture
)
2156 getDisplay()->CaptureMouse( bCapture
? this : NULL
);
2159 void GtkSalFrame::SetPointerPos( long nX
, long nY
)
2161 GtkSalFrame
* pFrame
= this;
2162 while( pFrame
&& pFrame
->isChild( false, true ) )
2163 pFrame
= pFrame
->m_pParent
;
2167 GdkScreen
*pScreen
= gtk_window_get_screen( GTK_WINDOW(pFrame
->m_pWindow
) );
2168 GdkDisplay
*pDisplay
= gdk_screen_get_display( pScreen
);
2170 /* #87921# when the application tries to center the mouse in the dialog the
2171 * window isn't mapped already. So use coordinates relative to the root window.
2173 unsigned int nWindowLeft
= maGeometry
.nX
+ nX
;
2174 unsigned int nWindowTop
= maGeometry
.nY
+ nY
;
2176 XWarpPointer( GDK_DISPLAY_XDISPLAY (pDisplay
), None
,
2177 GDK_WINDOW_XID (gdk_screen_get_root_window( pScreen
) ),
2178 0, 0, 0, 0, nWindowLeft
, nWindowTop
);
2179 // #i38648# ask for the next motion hint
2181 GdkModifierType mask
;
2182 gdk_window_get_pointer( pFrame
->m_pWindow
->window
, &x
, &y
, &mask
);
2185 void GtkSalFrame::Flush()
2187 #ifdef HAVE_A_RECENT_GTK
2188 gdk_display_flush( getGdkDisplay() );
2190 XFlush (GDK_DISPLAY_XDISPLAY (getGdkDisplay()));
2194 void GtkSalFrame::Sync()
2196 gdk_display_sync( getGdkDisplay() );
2199 String
GtkSalFrame::GetSymbolKeyName( const String
&, USHORT nKeyCode
)
2201 return getDisplay()->GetKeyName( nKeyCode
);
2204 String
GtkSalFrame::GetKeyName( USHORT nKeyCode
)
2206 return getDisplay()->GetKeyName( nKeyCode
);
2209 GdkDisplay
*GtkSalFrame::getGdkDisplay()
2211 return static_cast<GtkSalDisplay
*>(GetX11SalData()->GetDisplay())->GetGdkDisplay();
2214 GtkSalDisplay
*GtkSalFrame::getDisplay()
2216 return static_cast<GtkSalDisplay
*>(GetX11SalData()->GetDisplay());
2219 SalFrame::SalPointerState
GtkSalFrame::GetPointerState()
2221 SalPointerState aState
;
2224 GdkModifierType aMask
;
2225 gdk_display_get_pointer( getGdkDisplay(), &pScreen
, &x
, &y
, &aMask
);
2226 aState
.maPos
= Point( x
- maGeometry
.nX
, y
- maGeometry
.nY
);
2227 aState
.mnState
= GetMouseModCode( aMask
);
2231 SalFrame::SalIndicatorState
GtkSalFrame::GetIndicatorState()
2233 SalIndicatorState aState
;
2234 aState
.mnState
= GetX11SalData()->GetDisplay()->GetIndicatorState();
2238 void GtkSalFrame::SimulateKeyPress( USHORT nKeyCode
)
2240 GetX11SalData()->GetDisplay()->SimulateKeyPress(nKeyCode
);
2243 void GtkSalFrame::SetInputContext( SalInputContext
* pContext
)
2248 if( ! (pContext
->mnOptions
& SAL_INPUTCONTEXT_TEXT
) )
2251 // create a new im context
2252 if( ! m_pIMHandler
)
2253 m_pIMHandler
= new IMHandler( this );
2254 m_pIMHandler
->setInputContext( pContext
);
2257 void GtkSalFrame::EndExtTextInput( USHORT nFlags
)
2260 m_pIMHandler
->endExtTextInput( nFlags
);
2263 BOOL
GtkSalFrame::MapUnicodeToKeyCode( sal_Unicode
, LanguageType
, KeyCode
& )
2265 // not supported yet
2269 LanguageType
GtkSalFrame::GetInputLanguage()
2271 return LANGUAGE_DONTKNOW
;
2274 SalBitmap
* GtkSalFrame::SnapShot()
2279 X11SalBitmap
*pBmp
= new X11SalBitmap
;
2280 GdkWindow
*pWin
= m_pWindow
->window
;
2281 if( pBmp
->SnapShot( GDK_DISPLAY_XDISPLAY( getGdkDisplay() ),
2282 GDK_WINDOW_XID( pWin
) ) )
2290 void GtkSalFrame::UpdateSettings( AllSettings
& rSettings
)
2295 GtkSalGraphics
* pGraphics
= static_cast<GtkSalGraphics
*>(m_aGraphics
[0].pGraphics
);
2296 bool bFreeGraphics
= false;
2299 pGraphics
= static_cast<GtkSalGraphics
*>(GetGraphics());
2300 bFreeGraphics
= true;
2303 pGraphics
->updateSettings( rSettings
);
2306 ReleaseGraphics( pGraphics
);
2309 void GtkSalFrame::Beep( SoundType eType
)
2315 gdk_display_beep( getGdkDisplay() );
2322 const SystemEnvData
* GtkSalFrame::GetSystemData() const
2324 return &m_aSystemData
;
2327 void GtkSalFrame::SetParent( SalFrame
* pNewParent
)
2330 m_pParent
->m_aChildren
.remove( this );
2331 m_pParent
= static_cast<GtkSalFrame
*>(pNewParent
);
2333 m_pParent
->m_aChildren
.push_back( this );
2335 gtk_window_set_transient_for( GTK_WINDOW(m_pWindow
),
2336 (m_pParent
&& ! m_pParent
->isChild(true,false)) ? GTK_WINDOW(m_pParent
->m_pWindow
) : NULL
2340 void GtkSalFrame::createNewWindow( XLIB_Window aNewParent
, bool bXEmbed
, int nScreen
)
2342 bool bWasVisible
= GTK_WIDGET_MAPPED(m_pWindow
);
2346 if( nScreen
< 0 || nScreen
>= getDisplay()->GetScreenCount() )
2347 nScreen
= m_nScreen
;
2349 SystemParentData aParentData
;
2350 aParentData
.aWindow
= aNewParent
;
2351 aParentData
.bXEmbedSupport
= bXEmbed
;
2352 if( aNewParent
== None
)
2354 aNewParent
= getDisplay()->GetRootWindow(nScreen
);
2355 aParentData
.aWindow
= None
;
2356 aParentData
.bXEmbedSupport
= false;
2360 // is new parent a root window ?
2361 Display
* pDisp
= getDisplay()->GetDisplay();
2362 int nScreens
= getDisplay()->GetScreenCount();
2363 for( int i
= 0; i
< nScreens
; i
++ )
2365 if( aNewParent
== RootWindow( pDisp
, i
) )
2368 aParentData
.aWindow
= None
;
2369 aParentData
.bXEmbedSupport
= false;
2375 // first deinit frame
2378 delete m_pIMHandler
;
2379 m_pIMHandler
= NULL
;
2382 gdk_region_destroy( m_pRegion
);
2383 if( m_pFixedContainer
)
2384 gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer
) );
2386 gtk_widget_destroy( m_pWindow
);
2387 if( m_pForeignParent
)
2388 g_object_unref( G_OBJECT(m_pForeignParent
) );
2389 if( m_pForeignTopLevel
)
2390 g_object_unref( G_OBJECT(m_pForeignTopLevel
) );
2393 m_bDefaultPos
= m_bDefaultSize
= false;
2394 if( aParentData
.aWindow
!= None
)
2396 m_nStyle
|= SAL_FRAME_STYLE_PLUG
;
2397 Init( &aParentData
);
2401 m_nStyle
&= ~SAL_FRAME_STYLE_PLUG
;
2402 Init( (m_pParent
&& m_pParent
->m_nScreen
== m_nScreen
) ? m_pParent
: NULL
, m_nStyle
);
2406 for( unsigned int i
= 0; i
< sizeof(m_aGraphics
)/sizeof(m_aGraphics
[0]); i
++ )
2408 if( m_aGraphics
[i
].bInUse
)
2410 m_aGraphics
[i
].pGraphics
->SetDrawable( GDK_WINDOW_XWINDOW(m_pWindow
->window
), m_nScreen
);
2411 m_aGraphics
[i
].pGraphics
->SetWindow( m_pWindow
);
2415 if( m_aTitle
.Len() )
2416 SetTitle( m_aTitle
);
2421 std::list
< GtkSalFrame
* > aChildren
= m_aChildren
;
2422 m_aChildren
.clear();
2423 for( std::list
< GtkSalFrame
* >::iterator it
= aChildren
.begin(); it
!= aChildren
.end(); ++it
)
2424 (*it
)->createNewWindow( None
, false, m_nScreen
);
2426 // FIXME: SalObjects
2429 bool GtkSalFrame::SetPluginParent( SystemParentData
* pSysParent
)
2431 if( pSysParent
) // this may be the first system child frame now
2432 getDisplay()->setHaveSystemChildFrame();
2433 createNewWindow( pSysParent
->aWindow
, (pSysParent
->nSize
> sizeof(long)) ? pSysParent
->bXEmbedSupport
: false, m_nScreen
);
2437 void GtkSalFrame::ResetClipRegion()
2440 gdk_window_shape_combine_region( m_pWindow
->window
, NULL
, 0, 0 );
2443 void GtkSalFrame::BeginSetClipRegion( ULONG
)
2446 gdk_region_destroy( m_pRegion
);
2447 m_pRegion
= gdk_region_new();
2450 void GtkSalFrame::UnionClipRegion( long nX
, long nY
, long nWidth
, long nHeight
)
2457 aRect
.width
= nWidth
;
2458 aRect
.height
= nHeight
;
2460 gdk_region_union_with_rect( m_pRegion
, &aRect
);
2464 void GtkSalFrame::EndSetClipRegion()
2466 if( m_pWindow
&& m_pRegion
)
2467 gdk_window_shape_combine_region( m_pWindow
->window
, m_pRegion
, 0, 0 );
2470 bool GtkSalFrame::Dispatch( const XEvent
* pEvent
)
2472 bool bContinueDispatch
= true;
2474 if( pEvent
->type
== PropertyNotify
)
2476 vcl_sal::WMAdaptor
* pAdaptor
= getDisplay()->getWMAdaptor();
2477 Atom nDesktopAtom
= pAdaptor
->getAtom( vcl_sal::WMAdaptor::NET_WM_DESKTOP
);
2478 if( pEvent
->xproperty
.atom
== nDesktopAtom
&&
2479 pEvent
->xproperty
.state
== PropertyNewValue
)
2481 m_nWorkArea
= pAdaptor
->getWindowWorkArea( GDK_WINDOW_XWINDOW( m_pWindow
->window
) );
2484 else if( pEvent
->type
== ConfigureNotify
)
2486 if( m_pForeignParent
&& pEvent
->xconfigure
.window
== m_aForeignParentWindow
)
2488 bContinueDispatch
= false;
2489 gtk_window_resize( GTK_WINDOW(m_pWindow
), pEvent
->xconfigure
.width
, pEvent
->xconfigure
.height
);
2490 if( ( sal::static_int_cast
< int >(maGeometry
.nWidth
) !=
2491 pEvent
->xconfigure
.width
) ||
2492 ( sal::static_int_cast
< int >(maGeometry
.nHeight
) !=
2493 pEvent
->xconfigure
.height
) )
2495 maGeometry
.nWidth
= pEvent
->xconfigure
.width
;
2496 maGeometry
.nHeight
= pEvent
->xconfigure
.height
;
2498 getDisplay()->SendInternalEvent( this, NULL
, SALEVENT_RESIZE
);
2501 else if( m_pForeignTopLevel
&& pEvent
->xconfigure
.window
== m_aForeignTopLevelWindow
)
2503 bContinueDispatch
= false;
2507 XTranslateCoordinates( getDisplay()->GetDisplay(),
2508 GDK_WINDOW_XWINDOW( m_pWindow
->window
),
2509 getDisplay()->GetRootWindow( getDisplay()->GetDefaultScreenNumber() ),
2513 if( x
!= maGeometry
.nX
|| y
!= maGeometry
.nY
)
2517 getDisplay()->SendInternalEvent( this, NULL
, SALEVENT_MOVE
);
2521 else if( pEvent
->type
== ClientMessage
&&
2522 pEvent
->xclient
.message_type
== getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED
) &&
2523 pEvent
->xclient
.window
== GDK_WINDOW_XWINDOW(m_pWindow
->window
) &&
2527 // FIXME: this should not be necessary, GtkPlug should do this
2528 // transparently for us
2529 if( pEvent
->xclient
.data
.l
[1] == 1 || // XEMBED_WINDOW_ACTIVATE
2530 pEvent
->xclient
.data
.l
[1] == 2 // XEMBED_WINDOW_DEACTIVATE
2533 GdkEventFocus aEvent
;
2534 aEvent
.type
= GDK_FOCUS_CHANGE
;
2535 aEvent
.window
= m_pWindow
->window
;
2536 aEvent
.send_event
= TRUE
;
2537 aEvent
.in
= (pEvent
->xclient
.data
.l
[1] == 1);
2538 signalFocus( m_pWindow
, &aEvent
, this );
2542 return bContinueDispatch
;
2545 void GtkSalFrame::SetBackgroundBitmap( SalBitmap
* pBitmap
)
2547 if( m_hBackgroundPixmap
)
2549 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
2550 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
2552 XFreePixmap( getDisplay()->GetDisplay(), m_hBackgroundPixmap
);
2553 m_hBackgroundPixmap
= None
;
2557 X11SalBitmap
* pBM
= static_cast<X11SalBitmap
*>(pBitmap
);
2558 Size aSize
= pBM
->GetSize();
2559 if( aSize
.Width() && aSize
.Height() )
2561 m_hBackgroundPixmap
=
2562 XCreatePixmap( getDisplay()->GetDisplay(),
2563 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
2566 getDisplay()->GetVisual(m_nScreen
).GetDepth() );
2567 if( m_hBackgroundPixmap
)
2569 SalTwoRect aTwoRect
;
2570 aTwoRect
.mnSrcX
= aTwoRect
.mnSrcY
= aTwoRect
.mnDestX
= aTwoRect
.mnDestY
= 0;
2571 aTwoRect
.mnSrcWidth
= aTwoRect
.mnDestWidth
= aSize
.Width();
2572 aTwoRect
.mnSrcHeight
= aTwoRect
.mnDestHeight
= aSize
.Height();
2573 pBM
->ImplDraw( m_hBackgroundPixmap
,
2575 getDisplay()->GetVisual(m_nScreen
).GetDepth(),
2577 getDisplay()->GetCopyGC(m_nScreen
) );
2578 XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
2579 GDK_WINDOW_XWINDOW(m_pWindow
->window
),
2580 m_hBackgroundPixmap
);
2586 gboolean
GtkSalFrame::signalButton( GtkWidget
*, GdkEventButton
* pEvent
, gpointer frame
)
2588 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2589 SalMouseEvent aEvent
;
2590 USHORT nEventType
= 0;
2591 switch( pEvent
->type
)
2593 case GDK_BUTTON_PRESS
:
2594 nEventType
= SALEVENT_MOUSEBUTTONDOWN
;
2596 case GDK_BUTTON_RELEASE
:
2597 nEventType
= SALEVENT_MOUSEBUTTONUP
;
2602 switch( pEvent
->button
)
2604 case 1: aEvent
.mnButton
= MOUSE_LEFT
; break;
2605 case 2: aEvent
.mnButton
= MOUSE_MIDDLE
; break;
2606 case 3: aEvent
.mnButton
= MOUSE_RIGHT
; break;
2607 default: return FALSE
;
2609 aEvent
.mnTime
= pEvent
->time
;
2610 aEvent
.mnX
= (long)pEvent
->x_root
- pThis
->maGeometry
.nX
;
2611 aEvent
.mnY
= (long)pEvent
->y_root
- pThis
->maGeometry
.nY
;
2612 aEvent
.mnCode
= GetMouseModCode( pEvent
->state
);
2614 bool bClosePopups
= false;
2615 if( pEvent
->type
== GDK_BUTTON_PRESS
&&
2616 (pThis
->m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) == 0
2621 // close popups if user clicks outside our application
2623 bClosePopups
= (gdk_display_get_window_at_pointer( pThis
->getGdkDisplay(), &x
, &y
) == NULL
);
2625 /* #i30306# release implicit pointer grab if no popups are open; else
2626 * Drag cannot grab the pointer and will fail.
2628 if( m_nFloats
< 1 || bClosePopups
)
2629 gdk_display_pointer_ungrab( pThis
->getGdkDisplay(), GDK_CURRENT_TIME
);
2634 if( pThis
->m_bWindowIsGtkPlug
&&
2635 pEvent
->type
== GDK_BUTTON_PRESS
&&
2636 pEvent
->button
== 1 )
2638 pThis
->askForXEmbedFocus( pEvent
->time
);
2641 // --- RTL --- (mirror mouse pos)
2642 if( Application::GetSettings().GetLayoutRTL() )
2643 aEvent
.mnX
= pThis
->maGeometry
.nWidth
-1-aEvent
.mnX
;
2645 vcl::DeletionListener
aDel( pThis
);
2647 pThis
->CallCallback( nEventType
, &aEvent
);
2649 if( ! aDel
.isDeleted() )
2653 ImplSVData
* pSVData
= ImplGetSVData();
2654 if ( pSVData
->maWinData
.mpFirstFloat
)
2656 static const char* pEnv
= getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
2657 if ( !(pSVData
->maWinData
.mpFirstFloat
->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE
) && !(pEnv
&& *pEnv
) )
2658 pSVData
->maWinData
.mpFirstFloat
->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL
| FLOATWIN_POPUPMODEEND_CLOSEALL
);
2662 if( ! aDel
.isDeleted() )
2664 int frame_x
= (int)(pEvent
->x_root
- pEvent
->x
);
2665 int frame_y
= (int)(pEvent
->y_root
- pEvent
->y
);
2666 if( frame_x
!= pThis
->maGeometry
.nX
|| frame_y
!= pThis
->maGeometry
.nY
)
2668 pThis
->maGeometry
.nX
= frame_x
;
2669 pThis
->maGeometry
.nY
= frame_y
;
2670 pThis
->CallCallback( SALEVENT_MOVE
, NULL
);
2678 gboolean
GtkSalFrame::signalScroll( GtkWidget
*, GdkEvent
* pEvent
, gpointer frame
)
2680 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2681 GdkEventScroll
* pSEvent
= (GdkEventScroll
*)pEvent
;
2683 static ULONG nLines
= 0;
2686 char* pEnv
= getenv( "SAL_WHEELLINES" );
2687 nLines
= pEnv
? atoi( pEnv
) : 3;
2689 nLines
= SAL_WHEELMOUSE_EVENT_PAGESCROLL
;
2692 bool bNeg
= (pSEvent
->direction
== GDK_SCROLL_DOWN
|| pSEvent
->direction
== GDK_SCROLL_RIGHT
);
2693 SalWheelMouseEvent aEvent
;
2694 aEvent
.mnTime
= pSEvent
->time
;
2695 aEvent
.mnX
= (ULONG
)pSEvent
->x
;
2696 aEvent
.mnY
= (ULONG
)pSEvent
->y
;
2697 aEvent
.mnDelta
= bNeg
? -120 : 120;
2698 aEvent
.mnNotchDelta
= bNeg
? -1 : 1;
2699 aEvent
.mnScrollLines
= nLines
;
2700 aEvent
.mnCode
= GetMouseModCode( pSEvent
->state
);
2701 aEvent
.mbHorz
= (pSEvent
->direction
== GDK_SCROLL_LEFT
|| pSEvent
->direction
== GDK_SCROLL_RIGHT
);
2705 // --- RTL --- (mirror mouse pos)
2706 if( Application::GetSettings().GetLayoutRTL() )
2707 aEvent
.mnX
= pThis
->maGeometry
.nWidth
-1-aEvent
.mnX
;
2709 pThis
->CallCallback( SALEVENT_WHEELMOUSE
, &aEvent
);
2714 gboolean
GtkSalFrame::signalMotion( GtkWidget
*, GdkEventMotion
* pEvent
, gpointer frame
)
2716 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2718 SalMouseEvent aEvent
;
2719 aEvent
.mnTime
= pEvent
->time
;
2720 aEvent
.mnX
= (long)pEvent
->x_root
- pThis
->maGeometry
.nX
;
2721 aEvent
.mnY
= (long)pEvent
->y_root
- pThis
->maGeometry
.nY
;
2722 aEvent
.mnCode
= GetMouseModCode( pEvent
->state
);
2723 aEvent
.mnButton
= 0;
2728 // --- RTL --- (mirror mouse pos)
2729 if( Application::GetSettings().GetLayoutRTL() )
2730 aEvent
.mnX
= pThis
->maGeometry
.nWidth
-1-aEvent
.mnX
;
2732 vcl::DeletionListener
aDel( pThis
);
2734 pThis
->CallCallback( SALEVENT_MOUSEMOVE
, &aEvent
);
2736 if( ! aDel
.isDeleted() )
2738 int frame_x
= (int)(pEvent
->x_root
- pEvent
->x
);
2739 int frame_y
= (int)(pEvent
->y_root
- pEvent
->y
);
2740 if( frame_x
!= pThis
->maGeometry
.nX
|| frame_y
!= pThis
->maGeometry
.nY
)
2742 pThis
->maGeometry
.nX
= frame_x
;
2743 pThis
->maGeometry
.nY
= frame_y
;
2744 pThis
->CallCallback( SALEVENT_MOVE
, NULL
);
2747 if( ! aDel
.isDeleted() )
2749 // ask for the next hint
2751 GdkModifierType mask
;
2752 gdk_window_get_pointer( GTK_WIDGET(pThis
->m_pWindow
)->window
, &x
, &y
, &mask
);
2759 gboolean
GtkSalFrame::signalCrossing( GtkWidget
*, GdkEventCrossing
* pEvent
, gpointer frame
)
2761 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2762 SalMouseEvent aEvent
;
2763 aEvent
.mnTime
= pEvent
->time
;
2764 aEvent
.mnX
= (long)pEvent
->x_root
- pThis
->maGeometry
.nX
;
2765 aEvent
.mnY
= (long)pEvent
->y_root
- pThis
->maGeometry
.nY
;
2766 aEvent
.mnCode
= GetMouseModCode( pEvent
->state
);
2767 aEvent
.mnButton
= 0;
2770 pThis
->CallCallback( (pEvent
->type
== GDK_ENTER_NOTIFY
) ? SALEVENT_MOUSEMOVE
: SALEVENT_MOUSELEAVE
, &aEvent
);
2776 gboolean
GtkSalFrame::signalExpose( GtkWidget
*, GdkEventExpose
* pEvent
, gpointer frame
)
2778 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2780 struct SalPaintEvent
aEvent( pEvent
->area
.x
, pEvent
->area
.y
, pEvent
->area
.width
, pEvent
->area
.height
);
2783 pThis
->CallCallback( SALEVENT_PAINT
, &aEvent
);
2788 gboolean
GtkSalFrame::signalFocus( GtkWidget
*, GdkEventFocus
* pEvent
, gpointer frame
)
2790 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2794 // check if printers have changed (analogous to salframe focus handler)
2795 vcl_sal::PrinterUpdate::update();
2799 pThis
->m_nKeyModifiers
= 0;
2800 pThis
->m_bSingleAltPress
= false;
2801 pThis
->m_bSendModChangeOnRelease
= false;
2804 if( pThis
->m_pIMHandler
)
2805 pThis
->m_pIMHandler
->focusChanged( pEvent
->in
);
2807 // ask for changed printers like generic implementation
2809 if( static_cast< X11SalInstance
* >(GetSalData()->m_pInstance
)->isPrinterInit() )
2810 vcl_sal::PrinterUpdate::update();
2812 // FIXME: find out who the hell steals the focus from our frame
2813 // while we have the pointer grabbed, this should not come from
2814 // the window manager. Is this an event that was still queued ?
2815 // The focus does not seem to get set inside our process
2817 // in the meantime do not propagate focus get/lose if floats are open
2818 if( m_nFloats
== 0 )
2819 pThis
->CallCallback( pEvent
->in
? SALEVENT_GETFOCUS
: SALEVENT_LOSEFOCUS
, NULL
);
2824 gboolean
GtkSalFrame::signalMap( GtkWidget
*, GdkEvent
*, gpointer frame
)
2826 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2830 if( ImplGetSVData()->mbIsTestTool
)
2832 /* #i76541# testtool needs the focus to be in a new document
2833 * however e.g. metacity does not necessarily put the focus into
2834 * a newly shown window. An extra little hint seems to help here.
2835 * however we don't want to interfere with the normal user experience
2836 * so this is done when running in testtool only
2838 if( ! pThis
->m_pParent
&& (pThis
->m_nStyle
& SAL_FRAME_STYLE_MOVEABLE
) != 0 )
2839 XSetInputFocus( pThis
->getDisplay()->GetDisplay(),
2840 GDK_WINDOW_XWINDOW( GTK_WIDGET(pThis
->m_pWindow
)->window
),
2841 RevertToParent
, CurrentTime
);
2844 pThis
->CallCallback( SALEVENT_RESIZE
, NULL
);
2849 gboolean
GtkSalFrame::signalUnmap( GtkWidget
*, GdkEvent
*, gpointer frame
)
2851 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2854 pThis
->CallCallback( SALEVENT_RESIZE
, NULL
);
2859 gboolean
GtkSalFrame::signalConfigure( GtkWidget
*, GdkEventConfigure
* pEvent
, gpointer frame
)
2861 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2863 bool bMoved
= false, bSized
= false;
2864 int x
= pEvent
->x
, y
= pEvent
->y
;
2866 /* HACK: during sizing/moving a toolbar pThis->maGeometry is actually
2867 * already exact; even worse: due to the asynchronicity of configure
2868 * events the borderwindow which would evaluate this event
2869 * would size/move based on wrong data if we would actually evaluate
2870 * this event. So let's swallow it; this is also a performance
2871 * improvement as one can omit the synchronous XTranslateCoordinates
2874 if( (pThis
->m_nStyle
& SAL_FRAME_STYLE_OWNERDRAWDECORATION
) &&
2875 pThis
->getDisplay()->GetCaptureFrame() == pThis
)
2879 // in child case the coordinates are not root coordinates,
2880 // need to transform
2882 /* #i31785# sadly one cannot really trust the x,y members of the event;
2883 * they are e.g. not set correctly on maximize/demaximize; this rather
2884 * sounds like a bug in gtk we have to workaround.
2887 XTranslateCoordinates( pThis
->getDisplay()->GetDisplay(),
2888 GDK_WINDOW_XWINDOW(GTK_WIDGET(pThis
->m_pWindow
)->window
),
2889 pThis
->getDisplay()->GetRootWindow( pThis
->getDisplay()->GetDefaultScreenNumber() ),
2894 if( x
!= pThis
->maGeometry
.nX
|| y
!= pThis
->maGeometry
.nY
)
2897 pThis
->maGeometry
.nX
= x
;
2898 pThis
->maGeometry
.nY
= y
;
2901 * for non sizeable windows we set the min and max hint for the window manager to
2902 * achieve correct sizing. However this is asynchronous and e.g. on Compiz
2903 * it sometimes happens that the window gets resized to another size (some default)
2904 * if we update the size here, subsequent setMinMaxSize will use this wrong size
2905 * - which is not good since the window manager will now size the window back to this
2906 * wrong size at some point.
2908 if( (pThis
->m_nStyle
& (SAL_FRAME_STYLE_SIZEABLE
| SAL_FRAME_STYLE_PLUG
)) == SAL_FRAME_STYLE_SIZEABLE
)
2910 if( pEvent
->width
!= (int)pThis
->maGeometry
.nWidth
|| pEvent
->height
!= (int)pThis
->maGeometry
.nHeight
)
2913 pThis
->maGeometry
.nWidth
= pEvent
->width
;
2914 pThis
->maGeometry
.nHeight
= pEvent
->height
;
2918 // update decoration hints
2919 if( ! (pThis
->m_nStyle
& SAL_FRAME_STYLE_PLUG
) )
2922 gdk_window_get_frame_extents( GTK_WIDGET(pThis
->m_pWindow
)->window
, &aRect
);
2923 pThis
->maGeometry
.nTopDecoration
= y
- aRect
.y
;
2924 pThis
->maGeometry
.nBottomDecoration
= aRect
.y
+ aRect
.height
- y
- pEvent
->height
;
2925 pThis
->maGeometry
.nLeftDecoration
= x
- aRect
.x
;
2926 pThis
->maGeometry
.nRightDecoration
= aRect
.x
+ aRect
.width
- x
- pEvent
->width
;
2930 pThis
->maGeometry
.nTopDecoration
=
2931 pThis
->maGeometry
.nBottomDecoration
=
2932 pThis
->maGeometry
.nLeftDecoration
=
2933 pThis
->maGeometry
.nRightDecoration
= 0;
2937 pThis
->updateScreenNumber();
2938 if( bMoved
&& bSized
)
2939 pThis
->CallCallback( SALEVENT_MOVERESIZE
, NULL
);
2941 pThis
->CallCallback( SALEVENT_MOVE
, NULL
);
2943 pThis
->CallCallback( SALEVENT_RESIZE
, NULL
);
2948 gboolean
GtkSalFrame::signalKey( GtkWidget
*, GdkEventKey
* pEvent
, gpointer frame
)
2950 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
2952 vcl::DeletionListener
aDel( pThis
);
2954 if( pThis
->m_pIMHandler
)
2956 if( pThis
->m_pIMHandler
->handleKeyEvent( pEvent
) )
2958 pThis
->m_bSingleAltPress
= false;
2965 if( pEvent
->keyval
== GDK_Shift_L
|| pEvent
->keyval
== GDK_Shift_R
||
2966 pEvent
->keyval
== GDK_Control_L
|| pEvent
->keyval
== GDK_Control_R
||
2967 pEvent
->keyval
== GDK_Alt_L
|| pEvent
->keyval
== GDK_Alt_R
||
2968 pEvent
->keyval
== GDK_Meta_L
|| pEvent
->keyval
== GDK_Meta_R
)
2970 SalKeyModEvent aModEvt
;
2972 USHORT nModCode
= GetKeyModCode( pEvent
->state
);
2974 aModEvt
.mnModKeyCode
= 0; // emit no MODKEYCHANGE events
2975 if( pEvent
->type
== GDK_KEY_PRESS
&& !pThis
->m_nKeyModifiers
)
2976 pThis
->m_bSendModChangeOnRelease
= true;
2978 else if( pEvent
->type
== GDK_KEY_RELEASE
&&
2979 pThis
->m_bSendModChangeOnRelease
)
2981 aModEvt
.mnModKeyCode
= pThis
->m_nKeyModifiers
;
2982 pThis
->m_nKeyModifiers
= 0;
2985 USHORT nExtModMask
= 0;
2986 USHORT nModMask
= 0;
2987 // pressing just the ctrl key leads to a keysym of XK_Control but
2988 // the event state does not contain ControlMask. In the release
2989 // event its the other way round: it does contain the Control mask.
2990 // The modifier mode therefore has to be adapted manually.
2991 switch( pEvent
->keyval
)
2994 case GDK_Meta_L
: // map Meta (aka Command key) to Ctrl
2997 nExtModMask
= MODKEY_LMOD1
;
2998 nModMask
= KEY_MOD1
;
3001 case GDK_Meta_R
: // map Meta (aka Command key) to Ctrl
3004 nExtModMask
= MODKEY_RMOD1
;
3005 nModMask
= KEY_MOD1
;
3008 nExtModMask
= MODKEY_LMOD2
;
3010 nModMask
= KEY_MOD3
;
3012 nModMask
= KEY_MOD2
;
3016 nExtModMask
= MODKEY_RMOD2
;
3018 nModMask
= KEY_MOD2
| (pEvent
->type
== GDK_KEY_RELEASE
? KEY_MOD3
: 0);
3020 nModMask
= KEY_MOD2
;
3024 nExtModMask
= MODKEY_LSHIFT
;
3025 nModMask
= KEY_SHIFT
;
3028 nExtModMask
= MODKEY_RSHIFT
;
3029 nModMask
= KEY_SHIFT
;
3032 if( pEvent
->type
== GDK_KEY_RELEASE
)
3034 nModCode
&= ~nModMask
;
3035 pThis
->m_nKeyModifiers
&= ~nExtModMask
;
3039 nModCode
|= nModMask
;
3040 pThis
->m_nKeyModifiers
|= nExtModMask
;
3043 aModEvt
.mnCode
= nModCode
;
3044 aModEvt
.mnTime
= pEvent
->time
;
3046 pThis
->CallCallback( SALEVENT_KEYMODCHANGE
, &aModEvt
);
3048 if( ! aDel
.isDeleted() )
3051 if( ( pEvent
->keyval
== GDK_Alt_L
|| pEvent
->keyval
== GDK_Alt_R
) &&
3052 ( nModCode
& ~(KEY_MOD3
|KEY_MOD2
)) == 0 )
3054 if( pEvent
->type
== GDK_KEY_PRESS
)
3055 pThis
->m_bSingleAltPress
= true;
3057 else if( pThis
->m_bSingleAltPress
)
3059 SalKeyEvent aKeyEvt
;
3061 aKeyEvt
.mnCode
= KEY_MENU
| nModCode
;
3062 aKeyEvt
.mnRepeat
= 0;
3063 aKeyEvt
.mnTime
= pEvent
->time
;
3064 aKeyEvt
.mnCharCode
= 0;
3066 // simulate KEY_MENU
3067 pThis
->CallCallback( SALEVENT_KEYINPUT
, &aKeyEvt
);
3068 if( ! aDel
.isDeleted() )
3070 pThis
->CallCallback( SALEVENT_KEYUP
, &aKeyEvt
);
3071 pThis
->m_bSingleAltPress
= false;
3076 pThis
->m_bSingleAltPress
= false;
3081 pThis
->doKeyCallback( pEvent
->state
,
3083 pEvent
->hardware_keycode
,
3086 sal_Unicode(gdk_keyval_to_unicode( pEvent
->keyval
)),
3087 (pEvent
->type
== GDK_KEY_PRESS
),
3089 if( ! aDel
.isDeleted() )
3091 pThis
->m_bSendModChangeOnRelease
= false;
3092 pThis
->m_bSingleAltPress
= false;
3096 if( !aDel
.isDeleted() && pThis
->m_pIMHandler
)
3097 pThis
->m_pIMHandler
->updateIMSpotLocation();
3102 gboolean
GtkSalFrame::signalDelete( GtkWidget
*, GdkEvent
*, gpointer frame
)
3104 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3107 pThis
->CallCallback( SALEVENT_CLOSE
, NULL
);
3112 void GtkSalFrame::signalStyleSet( GtkWidget
*, GtkStyle
* pPrevious
, gpointer frame
)
3114 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3116 // every frame gets an initial style set on creation
3117 // do not post these as the whole application tends to
3118 // redraw itself to adjust to the new style
3119 // where there IS no new style resulting in tremendous unnecessary flickering
3120 if( pPrevious
!= NULL
)
3121 // signalStyleSet does NOT usually have the gdk lock
3122 // so post user event to safely dispatch the SALEVENT_SETTINGSCHANGED
3123 // note: settings changed for multiple frames is avoided in winproc.cxx ImplHandleSettings
3124 pThis
->getDisplay()->SendInternalEvent( pThis
, NULL
, SALEVENT_SETTINGSCHANGED
);
3126 /* #i64117# gtk sets a nice background pixmap
3127 * but we actually don't really want that, so save
3128 * some time on the Xserver as well as prevent
3131 GdkWindow
* pWin
= GTK_WIDGET(pThis
->getWindow())->window
;
3134 XLIB_Window aWin
= GDK_WINDOW_XWINDOW(pWin
);
3136 XSetWindowBackgroundPixmap( pThis
->getDisplay()->GetDisplay(),
3138 pThis
->m_hBackgroundPixmap
);
3141 if( ! pThis
->m_pParent
)
3143 // signalize theme changed for NWF caches
3144 // FIXME: should be called only once for a style change
3145 GtkSalGraphics::bThemeChanged
= TRUE
;
3149 gboolean
GtkSalFrame::signalState( GtkWidget
*, GdkEvent
* pEvent
, gpointer frame
)
3151 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3152 if( (pThis
->m_nState
& GDK_WINDOW_STATE_ICONIFIED
) != (pEvent
->window_state
.new_window_state
& GDK_WINDOW_STATE_ICONIFIED
) )
3153 pThis
->getDisplay()->SendInternalEvent( pThis
, NULL
, SALEVENT_RESIZE
);
3155 if( (pEvent
->window_state
.new_window_state
& GDK_WINDOW_STATE_MAXIMIZED
) &&
3156 ! (pThis
->m_nState
& GDK_WINDOW_STATE_MAXIMIZED
) )
3158 pThis
->m_aRestorePosSize
=
3159 Rectangle( Point( pThis
->maGeometry
.nX
, pThis
->maGeometry
.nY
),
3160 Size( pThis
->maGeometry
.nWidth
, pThis
->maGeometry
.nHeight
) );
3162 pThis
->m_nState
= pEvent
->window_state
.new_window_state
;
3167 gboolean
GtkSalFrame::signalVisibility( GtkWidget
*, GdkEventVisibility
* pEvent
, gpointer frame
)
3169 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3170 pThis
->m_nVisibility
= pEvent
->state
;
3175 void GtkSalFrame::signalDestroy( GtkObject
* pObj
, gpointer frame
)
3177 GtkSalFrame
* pThis
= (GtkSalFrame
*)frame
;
3178 if( GTK_WIDGET( pObj
) == pThis
->m_pWindow
)
3180 pThis
->m_pFixedContainer
= NULL
;
3181 pThis
->m_pWindow
= NULL
;
3185 // ----------------------------------------------------------------------
3186 // GtkSalFrame::IMHandler
3187 // ----------------------------------------------------------------------
3189 GtkSalFrame::IMHandler::IMHandler( GtkSalFrame
* pFrame
)
3191 m_nPrevKeyPresses( 0 ),
3192 m_pIMContext( NULL
),
3195 m_aInputEvent
.mpTextAttr
= NULL
;
3199 GtkSalFrame::IMHandler::~IMHandler()
3201 // cancel an eventual event posted to begin preedit again
3202 m_pFrame
->getDisplay()->CancelInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3206 void GtkSalFrame::IMHandler::createIMContext()
3208 if( ! m_pIMContext
)
3210 m_pIMContext
= gtk_im_multicontext_new ();
3211 g_signal_connect( m_pIMContext
, "commit",
3212 G_CALLBACK (signalIMCommit
), this );
3213 g_signal_connect( m_pIMContext
, "preedit_changed",
3214 G_CALLBACK (signalIMPreeditChanged
), this );
3215 g_signal_connect( m_pIMContext
, "retrieve_surrounding",
3216 G_CALLBACK (signalIMRetrieveSurrounding
), this );
3217 g_signal_connect( m_pIMContext
, "delete_surrounding",
3218 G_CALLBACK (signalIMDeleteSurrounding
), this );
3219 g_signal_connect( m_pIMContext
, "preedit_start",
3220 G_CALLBACK (signalIMPreeditStart
), this );
3221 g_signal_connect( m_pIMContext
, "preedit_end",
3222 G_CALLBACK (signalIMPreeditEnd
), this );
3224 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3225 gtk_im_context_set_client_window( m_pIMContext
, GTK_WIDGET(m_pFrame
->m_pWindow
)->window
);
3226 gtk_im_context_focus_in( m_pIMContext
);
3227 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3232 void GtkSalFrame::IMHandler::deleteIMContext()
3236 // first give IC a chance to deinitialize
3237 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3238 gtk_im_context_set_client_window( m_pIMContext
, NULL
);
3239 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3241 g_object_unref( m_pIMContext
);
3242 m_pIMContext
= NULL
;
3246 void GtkSalFrame::IMHandler::doCallEndExtTextInput()
3248 m_aInputEvent
.mpTextAttr
= NULL
;
3249 m_pFrame
->CallCallback( SALEVENT_ENDEXTTEXTINPUT
, NULL
);
3252 void GtkSalFrame::IMHandler::updateIMSpotLocation()
3254 SalExtTextInputPosEvent aPosEvent
;
3255 m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUTPOS
, (void*)&aPosEvent
);
3257 aArea
.x
= aPosEvent
.mnX
;
3258 aArea
.y
= aPosEvent
.mnY
;
3259 aArea
.width
= aPosEvent
.mnWidth
;
3260 aArea
.height
= aPosEvent
.mnHeight
;
3261 gtk_im_context_set_cursor_location( m_pIMContext
, &aArea
);
3264 void GtkSalFrame::IMHandler::setInputContext( SalInputContext
* )
3268 void GtkSalFrame::IMHandler::sendEmptyCommit()
3270 vcl::DeletionListener
aDel( m_pFrame
);
3272 SalExtTextInputEvent aEmptyEv
;
3273 aEmptyEv
.mnTime
= 0;
3274 aEmptyEv
.mpTextAttr
= 0;
3275 aEmptyEv
.maText
= String();
3276 aEmptyEv
.mnCursorPos
= 0;
3277 aEmptyEv
.mnCursorFlags
= 0;
3278 aEmptyEv
.mnDeltaStart
= 0;
3279 aEmptyEv
.mbOnlyCursor
= False
;
3280 m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&aEmptyEv
);
3281 if( ! aDel
.isDeleted() )
3282 m_pFrame
->CallCallback( SALEVENT_ENDEXTTEXTINPUT
, NULL
);
3285 void GtkSalFrame::IMHandler::endExtTextInput( USHORT
/*nFlags*/ )
3287 gtk_im_context_reset ( m_pIMContext
);
3289 if( m_aInputEvent
.mpTextAttr
)
3291 vcl::DeletionListener
aDel( m_pFrame
);
3292 // delete preedit in sal (commit an empty string)
3294 if( ! aDel
.isDeleted() )
3296 // mark previous preedit state again (will e.g. be sent at focus gain)
3297 m_aInputEvent
.mpTextAttr
= &m_aInputFlags
[0];
3300 // begin preedit again
3301 m_pFrame
->getDisplay()->SendInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3307 void GtkSalFrame::IMHandler::focusChanged( bool bFocusIn
)
3309 m_bFocused
= bFocusIn
;
3312 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3313 gtk_im_context_focus_in( m_pIMContext
);
3314 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3315 if( m_aInputEvent
.mpTextAttr
)
3318 // begin preedit again
3319 m_pFrame
->getDisplay()->SendInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3324 m_pFrame
->getDisplay()->GetXLib()->PushXErrorLevel( true );
3325 gtk_im_context_focus_out( m_pIMContext
);
3326 m_pFrame
->getDisplay()->GetXLib()->PopXErrorLevel();
3327 // cancel an eventual event posted to begin preedit again
3328 m_pFrame
->getDisplay()->CancelInternalEvent( m_pFrame
, &m_aInputEvent
, SALEVENT_EXTTEXTINPUT
);
3332 bool GtkSalFrame::IMHandler::handleKeyEvent( GdkEventKey
* pEvent
)
3334 vcl::DeletionListener
aDel( m_pFrame
);
3336 if( pEvent
->type
== GDK_KEY_PRESS
)
3338 // Add this key press event to the list of previous key presses
3339 // to which we compare key release events. If a later key release
3340 // event has a matching key press event in this list, we swallow
3341 // the key release because some GTK Input Methods don't swallow it
3343 m_aPrevKeyPresses
.push_back( PreviousKeyPress(pEvent
) );
3344 m_nPrevKeyPresses
++;
3346 // Also pop off the earliest key press event if there are more than 10
3348 while (m_nPrevKeyPresses
> 10)
3350 m_aPrevKeyPresses
.pop_front();
3351 m_nPrevKeyPresses
--;
3354 GObject
* pRef
= G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext
) ) );
3356 // #i51353# update spot location on every key input since we cannot
3357 // know which key may activate a preedit choice window
3358 updateIMSpotLocation();
3359 if( aDel
.isDeleted() )
3362 gboolean bResult
= gtk_im_context_filter_keypress( m_pIMContext
, pEvent
);
3363 g_object_unref( pRef
);
3365 if( aDel
.isDeleted() )
3372 DBG_ASSERT( m_nPrevKeyPresses
> 0, "key press has vanished !" );
3373 if( ! m_aPrevKeyPresses
.empty() ) // sanity check
3375 // event was not swallowed, do not filter a following
3376 // key release event
3377 // note: this relies on gtk_im_context_filter_keypress
3378 // returning without calling a handler (in the "not swallowed"
3379 // case ) which might change the previous key press list so
3380 // we would pop the wrong event here
3381 m_aPrevKeyPresses
.pop_back();
3382 m_nPrevKeyPresses
--;
3387 // Determine if we got an earlier key press event corresponding to this key release
3388 if (pEvent
->type
== GDK_KEY_RELEASE
)
3390 GObject
* pRef
= G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext
) ) );
3391 gboolean bResult
= gtk_im_context_filter_keypress( m_pIMContext
, pEvent
);
3392 g_object_unref( pRef
);
3394 if( aDel
.isDeleted() )
3397 std::list
<PreviousKeyPress
>::iterator iter
= m_aPrevKeyPresses
.begin();
3398 std::list
<PreviousKeyPress
>::iterator iter_end
= m_aPrevKeyPresses
.end();
3399 while (iter
!= iter_end
)
3401 // If we found a corresponding previous key press event, swallow the release
3402 // and remove the earlier key press from our list
3403 if (*iter
== pEvent
)
3405 m_aPrevKeyPresses
.erase(iter
);
3406 m_nPrevKeyPresses
--;
3420 * #122282# still more hacking: some IMEs never start a preedit but simply commit
3421 * in this case we cannot commit a single character. Workaround: do not do the
3422 * single key hack for enter or space if the unicode commited does not match
3425 static bool checkSingleKeyCommitHack( guint keyval
, sal_Unicode cCode
)
3432 if( cCode
!= '\n' && cCode
!= '\r' )
3447 #define CONTEXT_ARG pContext
3449 #define CONTEXT_ARG EMPTYARG
3451 void GtkSalFrame::IMHandler::signalIMCommit( GtkIMContext
* CONTEXT_ARG
, gchar
* pText
, gpointer im_handler
)
3453 GtkSalFrame::IMHandler
* pThis
= (GtkSalFrame::IMHandler
*)im_handler
;
3455 vcl::DeletionListener
aDel( pThis
->m_pFrame
);
3456 // open a block that will end the GTK_YIELD_GRAB before calling preedit changed again
3460 bool bWasPreedit
= (pThis
->m_aInputEvent
.mpTextAttr
!= 0);
3462 pThis
->m_aInputEvent
.mnTime
= 0;
3463 pThis
->m_aInputEvent
.mpTextAttr
= 0;
3464 pThis
->m_aInputEvent
.maText
= String( pText
, RTL_TEXTENCODING_UTF8
);
3465 pThis
->m_aInputEvent
.mnCursorPos
= pThis
->m_aInputEvent
.maText
.Len();
3466 pThis
->m_aInputEvent
.mnCursorFlags
= 0;
3467 pThis
->m_aInputEvent
.mnDeltaStart
= 0;
3468 pThis
->m_aInputEvent
.mbOnlyCursor
= False
;
3470 pThis
->m_aInputFlags
.clear();
3472 /* necessary HACK: all keyboard input comes in here as soon as a IMContext is set
3473 * which is logical and consequent. But since even simple input like
3474 * <space> comes through the commit signal instead of signalKey
3475 * and all kinds of windows only implement KeyInput (e.g. PushButtons,
3476 * RadioButtons and a lot of other Controls), will send a single
3477 * KeyInput/KeyUp sequence instead of an ExtText event if there
3478 * never was a preedit and the text is only one character.
3480 * In this case there the last ExtText event must have been
3481 * SALEVENT_ENDEXTTEXTINPUT, either because of a regular commit
3482 * or because there never was a preedit.
3484 bool bSingleCommit
= false;
3486 && pThis
->m_aInputEvent
.maText
.Len() == 1
3487 && ! pThis
->m_aPrevKeyPresses
.empty()
3490 const PreviousKeyPress
& rKP
= pThis
->m_aPrevKeyPresses
.back();
3491 sal_Unicode aOrigCode
= pThis
->m_aInputEvent
.maText
.GetChar(0);
3493 if( checkSingleKeyCommitHack( rKP
.keyval
, aOrigCode
) )
3495 pThis
->m_pFrame
->doKeyCallback( rKP
.state
, rKP
.keyval
, rKP
.hardware_keycode
, rKP
.group
, rKP
.time
, aOrigCode
, true, true );
3496 bSingleCommit
= true;
3500 if( ! bSingleCommit
)
3502 pThis
->m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&pThis
->m_aInputEvent
);
3503 if( ! aDel
.isDeleted() )
3504 pThis
->doCallEndExtTextInput();
3506 if( ! aDel
.isDeleted() )
3508 // reset input event
3509 pThis
->m_aInputEvent
.maText
= String();
3510 pThis
->m_aInputEvent
.mnCursorPos
= 0;
3511 pThis
->updateIMSpotLocation();
3515 // #i51356# workaround a solaris IIIMP bug
3516 // in case of partial commits the preedit changed signal
3517 // and commit signal come in wrong order
3518 if( ! aDel
.isDeleted() )
3519 signalIMPreeditChanged( pContext
, im_handler
);
3523 void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext
*, gpointer im_handler
)
3525 GtkSalFrame::IMHandler
* pThis
= (GtkSalFrame::IMHandler
*)im_handler
;
3528 PangoAttrList
* pAttrs
= NULL
;
3529 gint nCursorPos
= 0;
3531 gtk_im_context_get_preedit_string( pThis
->m_pIMContext
,
3535 if( pText
&& ! *pText
) // empty string
3537 // change from nothing to nothing -> do not start preedit
3538 // e.g. this will activate input into a calc cell without
3540 if( pThis
->m_aInputEvent
.maText
.Len() == 0 )
3547 bool bEndPreedit
= (!pText
|| !*pText
) && pThis
->m_aInputEvent
.mpTextAttr
!= NULL
;
3548 pThis
->m_aInputEvent
.mnTime
= 0;
3549 pThis
->m_aInputEvent
.maText
= String( pText
, RTL_TEXTENCODING_UTF8
);
3550 pThis
->m_aInputEvent
.mnCursorPos
= nCursorPos
;
3551 pThis
->m_aInputEvent
.mnCursorFlags
= 0;
3552 pThis
->m_aInputEvent
.mnDeltaStart
= 0;
3553 pThis
->m_aInputEvent
.mbOnlyCursor
= False
;
3555 pThis
->m_aInputFlags
= std::vector
<USHORT
>( std::max( 1, (int)pThis
->m_aInputEvent
.maText
.Len() ), 0 );
3557 PangoAttrIterator
*iter
= pango_attr_list_get_iterator (pAttrs
);
3560 GSList
*attr_list
= NULL
;
3561 GSList
*tmp_list
= NULL
;
3565 pango_attr_iterator_range (iter
, &start
, &end
);
3566 if (end
== G_MAXINT
)
3567 end
= pText
? strlen (pText
) : 0;
3571 start
= g_utf8_pointer_to_offset (pText
, pText
+ start
);
3572 end
= g_utf8_pointer_to_offset (pText
, pText
+ end
);
3574 tmp_list
= attr_list
= pango_attr_iterator_get_attrs (iter
);
3577 PangoAttribute
*pango_attr
= (PangoAttribute
*)(tmp_list
->data
);
3579 switch (pango_attr
->klass
->type
)
3581 case PANGO_ATTR_BACKGROUND
:
3582 sal_attr
|= (SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT
| SAL_EXTTEXTINPUT_CURSOR_INVISIBLE
);
3584 case PANGO_ATTR_UNDERLINE
:
3585 sal_attr
|= SAL_EXTTEXTINPUT_ATTR_UNDERLINE
;
3587 case PANGO_ATTR_STRIKETHROUGH
:
3588 sal_attr
|= SAL_EXTTEXTINPUT_ATTR_REDTEXT
;
3593 pango_attribute_destroy (pango_attr
);
3594 tmp_list
= tmp_list
->next
;
3597 sal_attr
|= SAL_EXTTEXTINPUT_ATTR_UNDERLINE
;
3598 g_slist_free (attr_list
);
3600 // Set the sal attributes on our text
3601 for (int i
= start
; i
< end
; i
++)
3602 pThis
->m_aInputFlags
[i
] |= sal_attr
;
3603 } while (pango_attr_iterator_next (iter
));
3605 pThis
->m_aInputEvent
.mpTextAttr
= &pThis
->m_aInputFlags
[0];
3608 pango_attr_list_unref( pAttrs
);
3612 vcl::DeletionListener
aDel( pThis
->m_pFrame
);
3614 pThis
->m_pFrame
->CallCallback( SALEVENT_EXTTEXTINPUT
, (void*)&pThis
->m_aInputEvent
);
3615 if( bEndPreedit
&& ! aDel
.isDeleted() )
3616 pThis
->doCallEndExtTextInput();
3617 if( ! aDel
.isDeleted() )
3618 pThis
->updateIMSpotLocation();
3621 void GtkSalFrame::IMHandler::signalIMPreeditStart( GtkIMContext
*, gpointer
/*im_handler*/ )
3625 void GtkSalFrame::IMHandler::signalIMPreeditEnd( GtkIMContext
*, gpointer im_handler
)
3627 GtkSalFrame::IMHandler
* pThis
= (GtkSalFrame::IMHandler
*)im_handler
;
3630 vcl::DeletionListener
aDel( pThis
->m_pFrame
);
3631 pThis
->doCallEndExtTextInput();
3632 if( ! aDel
.isDeleted() )
3633 pThis
->updateIMSpotLocation();
3636 uno::Reference
<accessibility::XAccessibleEditableText
>
3637 FindFocus(uno::Reference
< accessibility::XAccessibleContext
> xContext
)
3640 uno::Reference
< accessibility::XAccessibleEditableText
>();
3642 uno::Reference
<accessibility::XAccessibleStateSet
> xState
= xContext
->getAccessibleStateSet();
3645 if (xState
->contains(accessibility::AccessibleStateType::FOCUSED
))
3646 return uno::Reference
<accessibility::XAccessibleEditableText
>(xContext
, uno::UNO_QUERY
);
3649 for (sal_Int32 i
= 0; i
< xContext
->getAccessibleChildCount(); ++i
)
3651 uno::Reference
< accessibility::XAccessible
> xChild
= xContext
->getAccessibleChild(i
);
3654 uno::Reference
< accessibility::XAccessibleContext
> xChildContext
= xChild
->getAccessibleContext();
3655 if (!xChildContext
.is())
3657 uno::Reference
< accessibility::XAccessibleEditableText
> xText
= FindFocus(xChildContext
);
3661 return uno::Reference
< accessibility::XAccessibleEditableText
>();
3664 uno::Reference
<accessibility::XAccessibleEditableText
> lcl_GetxText()
3666 uno::Reference
<accessibility::XAccessibleEditableText
> xText
;
3667 Window
* pFocusWin
= ImplGetSVData()->maWinData
.mpFocusWin
;
3671 uno::Reference
< accessibility::XAccessible
> xAccessible( pFocusWin
->GetAccessible( true ) );
3672 if (xAccessible
.is())
3673 xText
= FindFocus(xAccessible
->getAccessibleContext());
3677 gboolean
GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext
* pContext
, gpointer
/*im_handler*/ )
3679 uno::Reference
<accessibility::XAccessibleEditableText
> xText
= lcl_GetxText();
3683 sal_uInt32 nPosition
= xText
->getCaretPosition();
3684 rtl::OUString sAllText
= xText
->getText();
3685 if (!sAllText
.getLength())
3687 rtl::OString sUTF
= rtl::OUStringToOString(sAllText
, RTL_TEXTENCODING_UTF8
);
3688 rtl::OUString
sCursorText(sAllText
, nPosition
);
3689 gtk_im_context_set_surrounding(pContext
, sUTF
.getStr(), sUTF
.getLength(),
3690 rtl::OUStringToOString(sCursorText
, RTL_TEXTENCODING_UTF8
).getLength());
3697 gboolean
GtkSalFrame::IMHandler::signalIMDeleteSurrounding( GtkIMContext
*, gint offset
, gint nchars
,
3698 gpointer
/*im_handler*/ )
3700 uno::Reference
<accessibility::XAccessibleEditableText
> xText
= lcl_GetxText();
3704 sal_uInt32 nPosition
= xText
->getCaretPosition();
3705 xText
->deleteText(nPosition
+ offset
, nPosition
+ offset
+ nchars
);