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: gtkdata.cxx,v $
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 #define _SV_SALDATA_CXX
36 // -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
48 #include <sys/types.h>
52 #include <plugins/gtk/gtkdata.hxx>
53 #include <plugins/gtk/gtkinst.hxx>
54 #include <plugins/gtk/gtkframe.hxx>
56 #include <osl/thread.h>
57 #include <osl/process.h>
59 #include <tools/debug.hxx>
60 #include "i18n_im.hxx"
61 #include "i18n_xkb.hxx"
62 #include <wmadaptor.hxx>
64 #include "../../unx/source/inc/salcursors.h"
66 #include <vcl/svapp.hxx>
69 using namespace vcl_sal
;
71 /***************************************************************************
73 ***************************************************************************/
75 GtkSalDisplay::GtkSalDisplay( GdkDisplay
* pDisplay
)
76 : SalDisplay( gdk_x11_display_get_xdisplay( pDisplay
) ),
77 m_pGdkDisplay( pDisplay
),
78 m_bStartupCompleted( false )
80 m_bUseRandRWrapper
= false; // use gdk signal instead
81 for(int i
= 0; i
< POINTER_COUNT
; i
++)
82 m_aCursors
[ i
] = NULL
;
86 GtkSalDisplay::~GtkSalDisplay()
88 if( !m_bStartupCompleted
)
89 gdk_notify_startup_complete();
92 for(int i
= 0; i
< POINTER_COUNT
; i
++)
94 gdk_cursor_unref( m_aCursors
[ i
] );
99 void GtkSalDisplay::deregisterFrame( SalFrame
* pFrame
)
101 if( m_pCapture
== pFrame
)
103 static_cast<GtkSalFrame
*>(m_pCapture
)->grabPointer( FALSE
);
106 SalDisplay::deregisterFrame( pFrame
);
110 GdkFilterReturn
call_filterGdkEvent( GdkXEvent
* sys_event
,
114 return GtkSalDisplay::filterGdkEvent( sys_event
, event
, data
);
117 void signalKeysChanged( GdkKeymap
*, gpointer data
)
119 GtkSalDisplay
* pDisp
= (GtkSalDisplay
*)data
;
120 pDisp
->GetKeyboardName(TRUE
);
123 void signalScreenSizeChanged( GdkScreen
* pScreen
, gpointer data
)
125 GtkSalDisplay
* pDisp
= (GtkSalDisplay
*)data
;
126 pDisp
->screenSizeChanged( pScreen
);
129 void signalMonitorsChanged( GdkScreen
* pScreen
, gpointer data
)
131 GtkSalDisplay
* pDisp
= (GtkSalDisplay
*)data
;
132 pDisp
->monitorsChanged( pScreen
);
137 GdkFilterReturn
GtkSalDisplay::filterGdkEvent( GdkXEvent
* sys_event
,
141 GdkFilterReturn aFilterReturn
= GDK_FILTER_CONTINUE
;
143 XEvent
*pEvent
= (XEvent
*)sys_event
;
144 GtkSalDisplay
*pDisplay
= (GtkSalDisplay
*)data
;
146 // dispatch all XEvents to event callback
147 if( GetSalData()->m_pInstance
->
148 CallEventCallback( pEvent
, sizeof( XEvent
) ) )
149 aFilterReturn
= GDK_FILTER_REMOVE
;
153 if (pDisplay
->GetDisplay() == pEvent
->xany
.display
)
155 // #i53471# gtk has no callback mechanism that lets us be notified
156 // when settings (as in XSETTING and opposed to styles) are changed.
157 // so we need to listen for corresponding property notifications here
158 // these should be rare enough so that we can assume that the settings
159 // actually change when a corresponding PropertyNotify occurs
160 if( pEvent
->type
== PropertyNotify
&&
161 pEvent
->xproperty
.atom
== pDisplay
->getWMAdaptor()->getAtom( WMAdaptor::XSETTINGS
) &&
162 ! pDisplay
->m_aFrames
.empty()
165 pDisplay
->SendInternalEvent( pDisplay
->m_aFrames
.front(), NULL
, SALEVENT_SETTINGSCHANGED
);
167 // let's see if one of our frames wants to swallow these events
169 for( std::list
< SalFrame
* >::const_iterator it
= pDisplay
->m_aFrames
.begin();
170 it
!= pDisplay
->m_aFrames
.end(); ++it
)
172 GtkSalFrame
* pFrame
= static_cast<GtkSalFrame
*>(*it
);
173 if( (GdkNativeWindow
)pFrame
->GetSystemData()->aWindow
== pEvent
->xany
.window
||
174 ( pFrame
->getForeignParent() && pFrame
->getForeignParentWindow() == pEvent
->xany
.window
) ||
175 ( pFrame
->getForeignTopLevel() && pFrame
->getForeignTopLevelWindow() == pEvent
->xany
.window
)
178 if( ! pFrame
->Dispatch( pEvent
) )
179 aFilterReturn
= GDK_FILTER_REMOVE
;
183 X11SalObject::Dispatch( pEvent
);
186 return aFilterReturn
;
189 void GtkSalDisplay::screenSizeChanged( GdkScreen
* pScreen
)
193 int nScreen
= gdk_screen_get_number( pScreen
);
194 if( nScreen
< static_cast<int>(m_aScreens
.size()) )
196 ScreenData
& rSD
= const_cast<ScreenData
&>(m_aScreens
[nScreen
]);
199 rSD
.m_aSize
= Size( gdk_screen_get_width( pScreen
),
200 gdk_screen_get_height( pScreen
) );
201 if( ! m_aFrames
.empty() )
202 m_aFrames
.front()->CallCallback( SALEVENT_DISPLAYCHANGED
, 0 );
207 DBG_ERROR( "unknown screen changed size" );
212 void GtkSalDisplay::monitorsChanged( GdkScreen
* pScreen
)
216 if( gdk_display_get_n_screens(m_pGdkDisplay
) == 1 )
218 int nScreen
= gdk_screen_get_number( pScreen
);
219 if( nScreen
== m_nDefaultScreen
) //To-Do, make m_aXineramaScreens a per-screen thing ?
221 gint nMonitors
= gdk_screen_get_n_monitors(pScreen
);
222 m_aXineramaScreens
= std::vector
<Rectangle
>();
223 for (gint i
= 0; i
< nMonitors
; ++i
)
226 gdk_screen_get_monitor_geometry(pScreen
, i
, &dest
);
227 m_aXineramaScreens
.push_back( Rectangle( Point(dest
.x
,
228 dest
.y
), Size( dest
.width
, dest
.height
) ) );
230 m_bXinerama
= m_aXineramaScreens
.size() > 1;
231 if( ! m_aFrames
.empty() )
232 m_aFrames
.front()->CallCallback( SALEVENT_DISPLAYCHANGED
, 0 );
236 DBG_ERROR( "monitors for non-default screen changed, extend-me" );
242 void GtkSalDisplay::initScreen( int nScreen
) const
244 if( nScreen
< 0 || nScreen
>= static_cast<int>(m_aScreens
.size()) )
245 nScreen
= m_nDefaultScreen
;
246 ScreenData
& rSD
= const_cast<ScreenData
&>(m_aScreens
[nScreen
]);
250 // choose visual for screen
251 SalDisplay::initScreen( nScreen
);
252 // now set a gdk default colormap matching the chosen visual to the screen
253 GdkVisual
* pVis
= gdkx_visual_get( rSD
.m_aVisual
.visualid
);
254 GdkScreen
* pScreen
= gdk_display_get_screen( m_pGdkDisplay
, nScreen
);
257 GdkColormap
* pDefCol
= gdk_screen_get_default_colormap( pScreen
);
258 GdkVisual
* pDefVis
= gdk_colormap_get_visual( pDefCol
);
259 if( pDefVis
!= pVis
)
261 pDefCol
= gdk_x11_colormap_foreign_new( pVis
, rSD
.m_aColormap
.GetXColormap() );
262 gdk_screen_set_default_colormap( pScreen
, pDefCol
);
263 #if OSL_DEBUG_LEVEL > 1
264 fprintf( stderr
, "set new gdk color map for screen %d\n", nScreen
);
268 #if OSL_DEBUG_LEVEL > 1
270 fprintf( stderr
, "not GdkVisual for visual id %d\n", (int)rSD
.m_aVisual
.visualid
);
274 long GtkSalDisplay::Dispatch( XEvent
* pEvent
)
276 if( GetDisplay() == pEvent
->xany
.display
)
278 // let's see if one of our frames wants to swallow these events
279 // get the child frame
280 for( std::list
< SalFrame
* >::const_iterator it
= m_aFrames
.begin();
281 it
!= m_aFrames
.end(); ++it
)
283 if( (GdkNativeWindow
)(*it
)->GetSystemData()->aWindow
== pEvent
->xany
.window
)
284 return static_cast<GtkSalFrame
*>(*it
)->Dispatch( pEvent
);
288 return GDK_FILTER_CONTINUE
;
291 GdkCursor
* GtkSalDisplay::getFromXPM( const char *pBitmap
,
293 int nWidth
, int nHeight
,
294 int nXHot
, int nYHot
)
296 GdkScreen
*pScreen
= gdk_display_get_default_screen( m_pGdkDisplay
);
297 GdkDrawable
*pDrawable
= GDK_DRAWABLE( gdk_screen_get_root_window (pScreen
) );
298 GdkBitmap
*pBitmapPix
= gdk_bitmap_create_from_data
299 ( pDrawable
, pBitmap
, nWidth
, nHeight
);
300 GdkBitmap
*pMaskPix
= gdk_bitmap_create_from_data
301 ( pDrawable
, pMask
, nWidth
, nHeight
);
302 GdkColormap
*pColormap
= gdk_drawable_get_colormap( pDrawable
);
304 GdkColor aWhite
= { 0, 0xffff, 0xffff, 0xffff };
305 GdkColor aBlack
= { 0, 0, 0, 0 };
307 gdk_colormap_alloc_color( pColormap
, &aBlack
, FALSE
, TRUE
);
308 gdk_colormap_alloc_color( pColormap
, &aWhite
, FALSE
, TRUE
);
310 return gdk_cursor_new_from_pixmap
311 ( pBitmapPix
, pMaskPix
,
312 &aBlack
, &aWhite
, nXHot
, nYHot
);
315 #define MAKE_CURSOR( vcl_name, name ) \
317 pCursor = getFromXPM( name##curs##_bits, name##mask##_bits, \
318 name##curs_width, name##curs_height, \
319 name##curs_x_hot, name##curs_y_hot ); \
321 #define MAP_BUILTIN( vcl_name, gdk_name ) \
323 pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, gdk_name ); \
326 GdkCursor
*GtkSalDisplay::getCursor( PointerStyle ePointerStyle
)
328 if( ePointerStyle
> POINTER_COUNT
)
331 if ( !m_aCursors
[ ePointerStyle
] )
333 GdkCursor
*pCursor
= NULL
;
335 switch( ePointerStyle
)
337 MAP_BUILTIN( POINTER_ARROW
, GDK_LEFT_PTR
);
338 MAP_BUILTIN( POINTER_TEXT
, GDK_XTERM
);
339 MAP_BUILTIN( POINTER_HELP
, GDK_QUESTION_ARROW
);
340 MAP_BUILTIN( POINTER_CROSS
, GDK_CROSSHAIR
);
341 MAP_BUILTIN( POINTER_WAIT
, GDK_WATCH
);
343 MAP_BUILTIN( POINTER_NSIZE
, GDK_SB_V_DOUBLE_ARROW
);
344 MAP_BUILTIN( POINTER_SSIZE
, GDK_SB_V_DOUBLE_ARROW
);
345 MAP_BUILTIN( POINTER_WSIZE
, GDK_SB_H_DOUBLE_ARROW
);
346 MAP_BUILTIN( POINTER_ESIZE
, GDK_SB_H_DOUBLE_ARROW
);
348 MAP_BUILTIN( POINTER_NWSIZE
, GDK_TOP_LEFT_CORNER
);
349 MAP_BUILTIN( POINTER_NESIZE
, GDK_TOP_RIGHT_CORNER
);
350 MAP_BUILTIN( POINTER_SWSIZE
, GDK_BOTTOM_LEFT_CORNER
);
351 MAP_BUILTIN( POINTER_SESIZE
, GDK_BOTTOM_RIGHT_CORNER
);
353 MAP_BUILTIN( POINTER_WINDOW_NSIZE
, GDK_TOP_SIDE
);
354 MAP_BUILTIN( POINTER_WINDOW_SSIZE
, GDK_BOTTOM_SIDE
);
355 MAP_BUILTIN( POINTER_WINDOW_WSIZE
, GDK_LEFT_SIDE
);
356 MAP_BUILTIN( POINTER_WINDOW_ESIZE
, GDK_RIGHT_SIDE
);
358 MAP_BUILTIN( POINTER_WINDOW_NWSIZE
, GDK_TOP_LEFT_CORNER
);
359 MAP_BUILTIN( POINTER_WINDOW_NESIZE
, GDK_TOP_RIGHT_CORNER
);
360 MAP_BUILTIN( POINTER_WINDOW_SWSIZE
, GDK_BOTTOM_LEFT_CORNER
);
361 MAP_BUILTIN( POINTER_WINDOW_SESIZE
, GDK_BOTTOM_RIGHT_CORNER
);
363 MAP_BUILTIN( POINTER_HSIZEBAR
, GDK_SB_H_DOUBLE_ARROW
);
364 MAP_BUILTIN( POINTER_VSIZEBAR
, GDK_SB_V_DOUBLE_ARROW
);
366 MAP_BUILTIN( POINTER_REFHAND
, GDK_HAND1
);
367 MAP_BUILTIN( POINTER_HAND
, GDK_HAND2
);
368 MAP_BUILTIN( POINTER_PEN
, GDK_PENCIL
);
370 MAP_BUILTIN( POINTER_HSPLIT
, GDK_SB_H_DOUBLE_ARROW
);
371 MAP_BUILTIN( POINTER_VSPLIT
, GDK_SB_V_DOUBLE_ARROW
);
373 MAP_BUILTIN( POINTER_MOVE
, GDK_FLEUR
);
375 MAKE_CURSOR( POINTER_NULL
, null
);
376 MAKE_CURSOR( POINTER_MAGNIFY
, magnify_
);
377 MAKE_CURSOR( POINTER_FILL
, fill_
);
378 MAKE_CURSOR( POINTER_MOVEDATA
, movedata_
);
379 MAKE_CURSOR( POINTER_COPYDATA
, copydata_
);
380 MAKE_CURSOR( POINTER_MOVEFILE
, movefile_
);
381 MAKE_CURSOR( POINTER_COPYFILE
, copyfile_
);
382 MAKE_CURSOR( POINTER_MOVEFILES
, movefiles_
);
383 MAKE_CURSOR( POINTER_COPYFILES
, copyfiles_
);
384 MAKE_CURSOR( POINTER_NOTALLOWED
, nodrop_
);
385 MAKE_CURSOR( POINTER_ROTATE
, rotate_
);
386 MAKE_CURSOR( POINTER_HSHEAR
, hshear_
);
387 MAKE_CURSOR( POINTER_VSHEAR
, vshear_
);
388 MAKE_CURSOR( POINTER_DRAW_LINE
, drawline_
);
389 MAKE_CURSOR( POINTER_DRAW_RECT
, drawrect_
);
390 MAKE_CURSOR( POINTER_DRAW_POLYGON
, drawpolygon_
);
391 MAKE_CURSOR( POINTER_DRAW_BEZIER
, drawbezier_
);
392 MAKE_CURSOR( POINTER_DRAW_ARC
, drawarc_
);
393 MAKE_CURSOR( POINTER_DRAW_PIE
, drawpie_
);
394 MAKE_CURSOR( POINTER_DRAW_CIRCLECUT
, drawcirclecut_
);
395 MAKE_CURSOR( POINTER_DRAW_ELLIPSE
, drawellipse_
);
396 MAKE_CURSOR( POINTER_DRAW_CONNECT
, drawconnect_
);
397 MAKE_CURSOR( POINTER_DRAW_TEXT
, drawtext_
);
398 MAKE_CURSOR( POINTER_MIRROR
, mirror_
);
399 MAKE_CURSOR( POINTER_CROOK
, crook_
);
400 MAKE_CURSOR( POINTER_CROP
, crop_
);
401 MAKE_CURSOR( POINTER_MOVEPOINT
, movepoint_
);
402 MAKE_CURSOR( POINTER_MOVEBEZIERWEIGHT
, movebezierweight_
);
403 MAKE_CURSOR( POINTER_DRAW_FREEHAND
, drawfreehand_
);
404 MAKE_CURSOR( POINTER_DRAW_CAPTION
, drawcaption_
);
405 MAKE_CURSOR( POINTER_LINKDATA
, linkdata_
);
406 MAKE_CURSOR( POINTER_MOVEDATALINK
, movedlnk_
);
407 MAKE_CURSOR( POINTER_COPYDATALINK
, copydlnk_
);
408 MAKE_CURSOR( POINTER_LINKFILE
, linkfile_
);
409 MAKE_CURSOR( POINTER_MOVEFILELINK
, moveflnk_
);
410 MAKE_CURSOR( POINTER_COPYFILELINK
, copyflnk_
);
411 MAKE_CURSOR( POINTER_CHART
, chart_
);
412 MAKE_CURSOR( POINTER_DETECTIVE
, detective_
);
413 MAKE_CURSOR( POINTER_PIVOT_COL
, pivotcol_
);
414 MAKE_CURSOR( POINTER_PIVOT_ROW
, pivotrow_
);
415 MAKE_CURSOR( POINTER_PIVOT_FIELD
, pivotfld_
);
416 MAKE_CURSOR( POINTER_PIVOT_DELETE
, pivotdel_
);
417 MAKE_CURSOR( POINTER_CHAIN
, chain_
);
418 MAKE_CURSOR( POINTER_CHAIN_NOTALLOWED
, chainnot_
);
419 MAKE_CURSOR( POINTER_TIMEEVENT_MOVE
, timemove_
);
420 MAKE_CURSOR( POINTER_TIMEEVENT_SIZE
, timesize_
);
421 MAKE_CURSOR( POINTER_AUTOSCROLL_N
, asn_
);
422 MAKE_CURSOR( POINTER_AUTOSCROLL_S
, ass_
);
423 MAKE_CURSOR( POINTER_AUTOSCROLL_W
, asw_
);
424 MAKE_CURSOR( POINTER_AUTOSCROLL_E
, ase_
);
425 MAKE_CURSOR( POINTER_AUTOSCROLL_NW
, asnw_
);
426 MAKE_CURSOR( POINTER_AUTOSCROLL_NE
, asne_
);
427 MAKE_CURSOR( POINTER_AUTOSCROLL_SW
, assw_
);
428 MAKE_CURSOR( POINTER_AUTOSCROLL_SE
, asse_
);
429 MAKE_CURSOR( POINTER_AUTOSCROLL_NS
, asns_
);
430 MAKE_CURSOR( POINTER_AUTOSCROLL_WE
, aswe_
);
431 MAKE_CURSOR( POINTER_AUTOSCROLL_NSWE
, asnswe_
);
432 MAKE_CURSOR( POINTER_AIRBRUSH
, airbrush_
);
433 MAKE_CURSOR( POINTER_TEXT_VERTICAL
, vertcurs_
);
435 // --> FME 2004-07-30 #i32329# Enhanced table selection
436 MAKE_CURSOR( POINTER_TAB_SELECT_S
, tblsels_
);
437 MAKE_CURSOR( POINTER_TAB_SELECT_E
, tblsele_
);
438 MAKE_CURSOR( POINTER_TAB_SELECT_SE
, tblselse_
);
439 MAKE_CURSOR( POINTER_TAB_SELECT_W
, tblselw_
);
440 MAKE_CURSOR( POINTER_TAB_SELECT_SW
, tblselsw_
);
443 // --> FME 2004-08-16 #i20119# Paintbrush tool
444 MAKE_CURSOR( POINTER_PAINTBRUSH
, paintbrush_
);
448 fprintf( stderr
, "pointer %d not implemented", ePointerStyle
);
452 pCursor
= gdk_cursor_new_for_display( m_pGdkDisplay
, GDK_LEFT_PTR
);
454 m_aCursors
[ ePointerStyle
] = pCursor
;
457 return m_aCursors
[ ePointerStyle
];
460 int GtkSalDisplay::CaptureMouse( SalFrame
* pSFrame
)
462 GtkSalFrame
* pFrame
= static_cast<GtkSalFrame
*>(pSFrame
);
467 static_cast<GtkSalFrame
*>(m_pCapture
)->grabPointer( FALSE
);
474 if( pFrame
== m_pCapture
)
476 static_cast<GtkSalFrame
*>(m_pCapture
)->grabPointer( FALSE
);
480 static_cast<GtkSalFrame
*>(pFrame
)->grabPointer( TRUE
);
484 /***************************************************************************
486 ***************************************************************************/
488 class GtkXLib
: public SalXLib
490 GtkSalDisplay
*m_pGtkSalDisplay
;
491 std::list
<GSource
*> m_aSources
;
493 GSource
*m_pUserEvent
;
494 oslMutex m_aDispatchMutex
;
495 oslCondition m_aDispatchCondition
;
498 static gboolean
timeoutFn(gpointer data
);
499 static gboolean
userEventFn(gpointer data
);
505 virtual void Yield( bool bWait
, bool bHandleAllCurrentEvents
);
506 virtual void Insert( int fd
, void* data
,
510 virtual void Remove( int fd
);
512 virtual void StartTimer( ULONG nMS
);
513 virtual void StopTimer();
514 virtual void Wakeup();
515 virtual void PostUserEvent();
520 #if OSL_DEBUG_LEVEL > 1
521 fprintf( stderr
, "GtkXLib::GtkXLib()\n" );
523 m_pGtkSalDisplay
= NULL
;
527 m_aDispatchCondition
= osl_createCondition();
528 m_aDispatchMutex
= osl_createMutex();
533 #if OSL_DEBUG_LEVEL > 1
534 fprintf( stderr
, "GtkXLib::~GtkXLib()\n" );
537 // sanity check: at this point nobody should be yielding, but wake them
538 // up anyway before the condition they're waiting on gets destroyed.
539 osl_setCondition( m_aDispatchCondition
);
540 osl_destroyCondition( m_aDispatchCondition
);
541 osl_destroyMutex( m_aDispatchMutex
);
547 #if OSL_DEBUG_LEVEL > 1
548 fprintf( stderr
, "GtkXLib::Init()\n" );
555 * open connection to X11 Display
557 * o -display command line parameter,
558 * o $DISPLAY environment variable
562 GdkDisplay
*pGdkDisp
= NULL
;
564 // is there a -display command line parameter?
565 rtl_TextEncoding aEnc
= osl_getThreadTextEncoding();
566 int nParams
= osl_getCommandArgCount();
567 rtl::OString aDisplay
;
568 rtl::OUString aParam
, aBin
;
569 char** pCmdLineAry
= new char*[ nParams
+1 ];
570 osl_getExecutableFile( &aParam
.pData
);
571 osl_getSystemPathFromFileURL( aParam
.pData
, &aBin
.pData
);
572 pCmdLineAry
[0] = g_strdup( OUStringToOString( aBin
, aEnc
).getStr() );
573 for (i
=0; i
<nParams
; i
++)
575 osl_getCommandArg(i
, &aParam
.pData
);
576 OString
aBParam( OUStringToOString( aParam
, aEnc
) );
578 if( aParam
.equalsAscii( "-display" ) || aParam
.equalsAscii( "--display" ) )
580 pCmdLineAry
[i
+1] = g_strdup( "--display" );
581 osl_getCommandArg(i
+1, &aParam
.pData
);
582 aDisplay
= rtl::OUStringToOString( aParam
, aEnc
);
585 pCmdLineAry
[i
+1] = g_strdup( aBParam
.getStr() );
590 g_set_application_name(X11SalData::getFrameClassName());
592 // Set consistant name of the root accessible
593 rtl::OUString aAppName
= Application::GetAppName();
594 if( aAppName
.getLength() > 0 )
596 rtl::OString aPrgName
= rtl::OUStringToOString(aAppName
, aEnc
);
597 g_set_prgname(aPrgName
);
601 gtk_init_check( &nParams
, &pCmdLineAry
);
603 for (i
= 0; i
< nParams
; i
++ )
604 g_free( pCmdLineAry
[i
] );
605 delete [] pCmdLineAry
;
607 #if OSL_DEBUG_LEVEL > 1
608 if (g_getenv ("SAL_DEBUG_UPDATES"))
609 gdk_window_set_debug_updates (TRUE
);
612 pGdkDisp
= gdk_display_get_default();
615 rtl::OUString aProgramFileURL
;
616 osl_getExecutableFile( &aProgramFileURL
.pData
);
617 rtl::OUString aProgramSystemPath
;
618 osl_getSystemPathFromFileURL (aProgramFileURL
.pData
, &aProgramSystemPath
.pData
);
619 rtl::OString aProgramName
= rtl::OUStringToOString(
621 osl_getThreadTextEncoding() );
622 fprintf( stderr
, "%s X11 error: Can't open display: %s\n",
623 aProgramName
.getStr(), aDisplay
.getStr());
624 fprintf( stderr
, " Set DISPLAY environment variable, use -display option\n");
625 fprintf( stderr
, " or check permissions of your X-Server\n");
626 fprintf( stderr
, " (See \"man X\" resp. \"man xhost\" for details)\n");
632 * if a -display switch was used, we need
633 * to set the environment accoringly since
634 * the clipboard build another connection
635 * to the xserver using $DISPLAY
637 char *pPutEnvIsBroken
= g_strdup_printf( "DISPLAY=%s",
638 gdk_display_get_name( pGdkDisp
) );
639 putenv( pPutEnvIsBroken
);
641 Display
*pDisp
= gdk_x11_display_get_xdisplay( pGdkDisp
);
643 XSetIOErrorHandler ( (XIOErrorHandler
)X11SalData::XIOErrorHdl
);
644 XSetErrorHandler ( (XErrorHandler
)X11SalData::XErrorHdl
);
646 m_pGtkSalDisplay
= new GtkSalDisplay( pGdkDisp
);
648 gdk_window_add_filter( NULL
, call_filterGdkEvent
, m_pGtkSalDisplay
);
650 PushXErrorLevel( true );
651 SalI18N_KeyboardExtension
*pKbdExtension
= new SalI18N_KeyboardExtension( pDisp
);
652 XSync( pDisp
, False
);
654 pKbdExtension
->UseExtension( ! HasXErrorOccured() );
657 m_pGtkSalDisplay
->SetKbdExtension( pKbdExtension
);
659 g_signal_connect( G_OBJECT(gdk_keymap_get_default()), "keys_changed", G_CALLBACK(signalKeysChanged
), m_pGtkSalDisplay
);
661 // add signal handler to notify screen size changes
662 int nScreens
= gdk_display_get_n_screens( pGdkDisp
);
663 for( int n
= 0; n
< nScreens
; n
++ )
665 GdkScreen
*pScreen
= gdk_display_get_screen( pGdkDisp
, n
);
668 g_signal_connect( G_OBJECT(pScreen
), "size-changed", G_CALLBACK(signalScreenSizeChanged
), m_pGtkSalDisplay
);
669 g_signal_connect( G_OBJECT(pScreen
), "monitors-changed", G_CALLBACK(signalMonitorsChanged
), m_pGtkSalDisplay
);
676 gboolean
call_timeoutFn(gpointer data
)
678 return GtkXLib::timeoutFn(data
);
682 gboolean
GtkXLib::timeoutFn(gpointer data
)
684 SalData
*pSalData
= GetSalData();
685 GtkXLib
*pThis
= (GtkXLib
*) data
;
687 pSalData
->m_pInstance
->GetYieldMutex()->acquire();
689 if( pThis
->m_pTimeout
)
691 g_source_unref (pThis
->m_pTimeout
);
692 pThis
->m_pTimeout
= NULL
;
695 // Auto-restart immediately
696 pThis
->StartTimer( pThis
->m_nTimeoutMS
);
698 GetX11SalData()->Timeout();
700 pSalData
->m_pInstance
->GetYieldMutex()->release();
705 void GtkXLib::StartTimer( ULONG nMS
)
707 m_nTimeoutMS
= nMS
; // for restarting
711 g_source_destroy (m_pTimeout
);
712 g_source_unref (m_pTimeout
);
715 m_pTimeout
= g_timeout_source_new (m_nTimeoutMS
);
716 // #i36226# timers should be executed with lower priority
717 // than XEvents like in generic plugin
718 g_source_set_priority( m_pTimeout
, G_PRIORITY_LOW
);
719 g_source_set_can_recurse (m_pTimeout
, TRUE
);
720 g_source_set_callback (m_pTimeout
, call_timeoutFn
,
721 (gpointer
) this, NULL
);
722 g_source_attach (m_pTimeout
, g_main_context_default ());
724 SalXLib::StartTimer( nMS
);
727 void GtkXLib::StopTimer()
729 SalXLib::StopTimer();
733 g_source_destroy (m_pTimeout
);
734 g_source_unref (m_pTimeout
);
741 gboolean
call_userEventFn( gpointer data
)
743 return GtkXLib::userEventFn( data
);
747 gboolean
GtkXLib::userEventFn(gpointer data
)
750 GtkXLib
*pThis
= (GtkXLib
*) data
;
751 SalData
*pSalData
= GetSalData();
753 pSalData
->m_pInstance
->GetYieldMutex()->acquire();
754 pThis
->m_pGtkSalDisplay
->EventGuardAcquire();
756 if( !pThis
->m_pGtkSalDisplay
->HasMoreEvents() )
758 if( pThis
->m_pUserEvent
)
760 g_source_unref (pThis
->m_pUserEvent
);
761 pThis
->m_pUserEvent
= NULL
;
768 pThis
->m_pGtkSalDisplay
->EventGuardRelease();
770 pThis
->m_pGtkSalDisplay
->DispatchInternalEvent();
772 pSalData
->m_pInstance
->GetYieldMutex()->release();
777 // hEventGuard_ held during this invocation
778 void GtkXLib::PostUserEvent()
780 if( !m_pUserEvent
) // not pending anyway
782 m_pUserEvent
= g_idle_source_new();
783 g_source_set_priority( m_pUserEvent
, G_PRIORITY_HIGH
);
784 g_source_set_can_recurse (m_pUserEvent
, TRUE
);
785 g_source_set_callback (m_pUserEvent
, call_userEventFn
,
786 (gpointer
) this, NULL
);
787 g_source_attach (m_pUserEvent
, g_main_context_default ());
792 void GtkXLib::Wakeup()
794 g_main_context_wakeup( g_main_context_default () );
797 void GtkXLib::Yield( bool bWait
, bool bHandleAllCurrentEvents
)
799 /* #i33212# only enter g_main_context_iteration in one thread at any one
800 * time, else one of them potentially will never end as long as there is
801 * another thread in in there. Having only one yieldin thread actually dispatch
802 * fits the vcl event model (see e.g. the generic plugin).
805 bool bDispatchThread
= false;
807 // release YieldMutex (and re-acquire at block end)
808 YieldMutexReleaser aReleaser
;
809 if( osl_tryToAcquireMutex( m_aDispatchMutex
) )
811 // we are the dispatch thread
812 osl_resetCondition( m_aDispatchCondition
);
813 bDispatchThread
= true;
816 return; // someone else is waiting already, return
819 if( bDispatchThread
)
821 int nMaxEvents
= bHandleAllCurrentEvents
? 100 : 1;
822 gboolean wasEvent
= FALSE
, wasOneEvent
= TRUE
;
823 while( nMaxEvents
-- && wasOneEvent
)
825 wasOneEvent
= g_main_context_iteration( NULL
, FALSE
);
829 if( bWait
&& ! wasEvent
)
830 g_main_context_iteration( NULL
, TRUE
);
832 else if( userEventFn( this ) )
834 /* #i41693# in case the dispatch thread hangs in join
835 * for this thread the condition will never be set
836 * workaround: timeout of 1 second a emergency exit
841 osl_waitCondition( m_aDispatchCondition
, &aValue
);
845 if( bDispatchThread
)
847 osl_releaseMutex( m_aDispatchMutex
);
848 osl_setCondition( m_aDispatchCondition
); // trigger non dispatch thread yields
849 osl_resetCondition( m_aDispatchCondition
);
859 GIOCondition condition
;
867 sal_source_prepare (GSource
*source
,
870 SalWatch
*watch
= (SalWatch
*)source
;
874 if (watch
->pending
&&
875 watch
->pending (watch
->pollfd
.fd
, watch
->user_data
)) {
876 watch
->pollfd
.revents
|= watch
->condition
;
884 sal_source_check (GSource
*source
)
886 SalWatch
*watch
= (SalWatch
*)source
;
888 return watch
->pollfd
.revents
& watch
->condition
;
892 sal_source_dispatch (GSource
*source
,
896 SalData
*pSalData
= GetSalData();
897 SalWatch
*watch
= (SalWatch
*) source
;
899 pSalData
->m_pInstance
->GetYieldMutex()->acquire();
901 watch
->handle (watch
->pollfd
.fd
, watch
->user_data
);
903 pSalData
->m_pInstance
->GetYieldMutex()->release();
909 sal_source_finalize (GSource
*)
913 static GSourceFuncs sal_source_watch_funcs
= {
923 sal_source_create_watch (int fd
,
924 GIOCondition condition
,
931 GMainContext
*context
= g_main_context_default ();
933 source
= g_source_new (&sal_source_watch_funcs
,
935 watch
= (SalWatch
*) source
;
937 watch
->pollfd
.fd
= fd
;
938 watch
->pollfd
.events
= condition
;
939 watch
->condition
= condition
;
940 watch
->pending
= pending
;
941 watch
->handle
= handle
;
942 watch
->user_data
= user_data
;
944 g_source_set_can_recurse (source
, TRUE
);
945 g_source_add_poll (source
, &watch
->pollfd
);
946 g_source_attach (source
, context
);
953 void GtkXLib::Insert( int nFD
,
959 GSource
*source
= sal_source_create_watch
960 ( nFD
, (GIOCondition
) ((G_IO_IN
|G_IO_PRI
) |
961 (G_IO_ERR
|G_IO_HUP
|G_IO_NVAL
)),
962 pending
, handle
, data
);
963 m_aSources
.push_back( source
);
966 void GtkXLib::Remove( int nFD
)
968 ::std::list
< GSource
* >::iterator it
;
970 for (it
= m_aSources
.begin(); it
!= m_aSources
.end(); ++it
)
972 SalWatch
*watch
= (SalWatch
*) *it
;
974 if (watch
->pollfd
.fd
== nFD
)
976 m_aSources
.erase( it
);
978 g_source_destroy ((GSource
*)watch
);
979 g_source_unref ((GSource
*)watch
);
985 /**********************************************************************
987 **********************************************************************/
995 pXLib_
= new GtkXLib();