19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
59f62ea84SAndrew Rist * distributed with this work for additional information
69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
109f62ea84SAndrew Rist *
119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist *
139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist * software distributed under the License is distributed on an
159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
179f62ea84SAndrew Rist * specific language governing permissions and limitations
189f62ea84SAndrew Rist * under the License.
199f62ea84SAndrew Rist *
209f62ea84SAndrew Rist *************************************************************/
219f62ea84SAndrew Rist
229f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #define _SV_SALDATA_CXX
28cdf0e10cSrcweir
29cdf0e10cSrcweir // -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30cdf0e10cSrcweir
31cdf0e10cSrcweir #include <unistd.h>
32cdf0e10cSrcweir #include <fcntl.h>
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include <stdio.h>
35cdf0e10cSrcweir #include <string.h>
36cdf0e10cSrcweir #include <stdlib.h>
37cdf0e10cSrcweir #include <limits.h>
38cdf0e10cSrcweir #include <errno.h>
39cdf0e10cSrcweir #include <poll.h>
40cdf0e10cSrcweir #ifdef FREEBSD
41cdf0e10cSrcweir #include <sys/types.h>
42cdf0e10cSrcweir #include <sys/time.h>
43cdf0e10cSrcweir #include <unistd.h>
44cdf0e10cSrcweir #endif
45cdf0e10cSrcweir #include <unx/gtk/gtkdata.hxx>
46cdf0e10cSrcweir #include <unx/gtk/gtkinst.hxx>
47cdf0e10cSrcweir #include <unx/gtk/gtkframe.hxx>
48cdf0e10cSrcweir #include <unx/salobj.h>
49cdf0e10cSrcweir #include <osl/thread.h>
50cdf0e10cSrcweir #include <osl/process.h>
51cdf0e10cSrcweir
52cdf0e10cSrcweir #include <tools/debug.hxx>
53cdf0e10cSrcweir #include "unx/i18n_im.hxx"
54cdf0e10cSrcweir #include "unx/i18n_xkb.hxx"
55cdf0e10cSrcweir #include <unx/wmadaptor.hxx>
56cdf0e10cSrcweir
57cdf0e10cSrcweir #include "unx/x11_cursors/salcursors.h"
58cdf0e10cSrcweir
59cdf0e10cSrcweir #include <vcl/svapp.hxx>
60cdf0e10cSrcweir
61cdf0e10cSrcweir using namespace rtl;
62cdf0e10cSrcweir using namespace vcl_sal;
63cdf0e10cSrcweir
64cdf0e10cSrcweir /***************************************************************************
65cdf0e10cSrcweir * class GtkDisplay *
66cdf0e10cSrcweir ***************************************************************************/
67cdf0e10cSrcweir
GtkSalDisplay(GdkDisplay * pDisplay)68cdf0e10cSrcweir GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay )
69cdf0e10cSrcweir : SalDisplay( gdk_x11_display_get_xdisplay( pDisplay ) ),
70cdf0e10cSrcweir m_pGdkDisplay( pDisplay ),
71cdf0e10cSrcweir m_bStartupCompleted( false )
72cdf0e10cSrcweir {
73cdf0e10cSrcweir m_bUseRandRWrapper = false; // use gdk signal instead
74cdf0e10cSrcweir for(int i = 0; i < POINTER_COUNT; i++)
75cdf0e10cSrcweir m_aCursors[ i ] = NULL;
76cdf0e10cSrcweir Init ();
77cdf0e10cSrcweir }
78cdf0e10cSrcweir
~GtkSalDisplay()79cdf0e10cSrcweir GtkSalDisplay::~GtkSalDisplay()
80cdf0e10cSrcweir {
81cdf0e10cSrcweir if( !m_bStartupCompleted )
82cdf0e10cSrcweir gdk_notify_startup_complete();
83cdf0e10cSrcweir doDestruct();
84cdf0e10cSrcweir
85cdf0e10cSrcweir for(int i = 0; i < POINTER_COUNT; i++)
86cdf0e10cSrcweir if( m_aCursors[ i ] )
87cdf0e10cSrcweir gdk_cursor_unref( m_aCursors[ i ] );
88cdf0e10cSrcweir
89cdf0e10cSrcweir pDisp_ = NULL;
90cdf0e10cSrcweir }
91cdf0e10cSrcweir
deregisterFrame(SalFrame * pFrame)92cdf0e10cSrcweir void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir if( m_pCapture == pFrame )
95cdf0e10cSrcweir {
96cdf0e10cSrcweir static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
97cdf0e10cSrcweir m_pCapture = NULL;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir SalDisplay::deregisterFrame( pFrame );
100cdf0e10cSrcweir }
101cdf0e10cSrcweir
102cdf0e10cSrcweir extern "C" {
call_filterGdkEvent(GdkXEvent * sys_event,GdkEvent * event,gpointer data)103cdf0e10cSrcweir GdkFilterReturn call_filterGdkEvent( GdkXEvent* sys_event,
104cdf0e10cSrcweir GdkEvent* event,
105cdf0e10cSrcweir gpointer data )
106cdf0e10cSrcweir {
107cdf0e10cSrcweir return GtkSalDisplay::filterGdkEvent( sys_event, event, data );
108cdf0e10cSrcweir }
109cdf0e10cSrcweir
signalKeysChanged(GdkKeymap *,gpointer data)110cdf0e10cSrcweir void signalKeysChanged( GdkKeymap*, gpointer data )
111cdf0e10cSrcweir {
112cdf0e10cSrcweir GtkSalDisplay* pDisp = (GtkSalDisplay*)data;
113cdf0e10cSrcweir pDisp->GetKeyboardName(TRUE);
114cdf0e10cSrcweir }
115cdf0e10cSrcweir
signalScreenSizeChanged(GdkScreen * pScreen,gpointer data)116cdf0e10cSrcweir void signalScreenSizeChanged( GdkScreen* pScreen, gpointer data )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir GtkSalDisplay* pDisp = (GtkSalDisplay*)data;
119cdf0e10cSrcweir pDisp->screenSizeChanged( pScreen );
120cdf0e10cSrcweir }
121cdf0e10cSrcweir
signalMonitorsChanged(GdkScreen * pScreen,gpointer data)122cdf0e10cSrcweir void signalMonitorsChanged( GdkScreen* pScreen, gpointer data )
123cdf0e10cSrcweir {
124cdf0e10cSrcweir GtkSalDisplay* pDisp = (GtkSalDisplay*)data;
125cdf0e10cSrcweir pDisp->monitorsChanged( pScreen );
126cdf0e10cSrcweir }
127cdf0e10cSrcweir
128cdf0e10cSrcweir }
129cdf0e10cSrcweir
filterGdkEvent(GdkXEvent * sys_event,GdkEvent *,gpointer data)130cdf0e10cSrcweir GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event,
131cdf0e10cSrcweir GdkEvent*,
132cdf0e10cSrcweir gpointer data )
133cdf0e10cSrcweir {
134cdf0e10cSrcweir GdkFilterReturn aFilterReturn = GDK_FILTER_CONTINUE;
135cdf0e10cSrcweir
136cdf0e10cSrcweir XEvent *pEvent = (XEvent *)sys_event;
137cdf0e10cSrcweir GtkSalDisplay *pDisplay = (GtkSalDisplay *)data;
138cdf0e10cSrcweir
139cdf0e10cSrcweir // dispatch all XEvents to event callback
140cdf0e10cSrcweir if( GetSalData()->m_pInstance->
141cdf0e10cSrcweir CallEventCallback( pEvent, sizeof( XEvent ) ) )
142cdf0e10cSrcweir aFilterReturn = GDK_FILTER_REMOVE;
143cdf0e10cSrcweir
144cdf0e10cSrcweir GTK_YIELD_GRAB();
145cdf0e10cSrcweir
146cdf0e10cSrcweir if (pDisplay->GetDisplay() == pEvent->xany.display )
147cdf0e10cSrcweir {
148cdf0e10cSrcweir // #i53471# gtk has no callback mechanism that lets us be notified
149cdf0e10cSrcweir // when settings (as in XSETTING and opposed to styles) are changed.
150cdf0e10cSrcweir // so we need to listen for corresponding property notifications here
151cdf0e10cSrcweir // these should be rare enough so that we can assume that the settings
152cdf0e10cSrcweir // actually change when a corresponding PropertyNotify occurs
153cdf0e10cSrcweir if( pEvent->type == PropertyNotify &&
154cdf0e10cSrcweir pEvent->xproperty.atom == pDisplay->getWMAdaptor()->getAtom( WMAdaptor::XSETTINGS ) &&
155cdf0e10cSrcweir ! pDisplay->m_aFrames.empty()
156cdf0e10cSrcweir )
157cdf0e10cSrcweir {
158cdf0e10cSrcweir pDisplay->SendInternalEvent( pDisplay->m_aFrames.front(), NULL, SALEVENT_SETTINGSCHANGED );
159cdf0e10cSrcweir }
160cdf0e10cSrcweir // let's see if one of our frames wants to swallow these events
161cdf0e10cSrcweir // get the frame
162cdf0e10cSrcweir for( std::list< SalFrame* >::const_iterator it = pDisplay->m_aFrames.begin();
163cdf0e10cSrcweir it != pDisplay->m_aFrames.end(); ++it )
164cdf0e10cSrcweir {
165cdf0e10cSrcweir GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(*it);
166cdf0e10cSrcweir if( (GdkNativeWindow)pFrame->GetSystemData()->aWindow == pEvent->xany.window ||
167cdf0e10cSrcweir ( pFrame->getForeignParent() && pFrame->getForeignParentWindow() == pEvent->xany.window ) ||
168cdf0e10cSrcweir ( pFrame->getForeignTopLevel() && pFrame->getForeignTopLevelWindow() == pEvent->xany.window )
169cdf0e10cSrcweir )
170cdf0e10cSrcweir {
171cdf0e10cSrcweir if( ! pFrame->Dispatch( pEvent ) )
172cdf0e10cSrcweir aFilterReturn = GDK_FILTER_REMOVE;
173cdf0e10cSrcweir break;
174cdf0e10cSrcweir }
175cdf0e10cSrcweir }
176cdf0e10cSrcweir X11SalObject::Dispatch( pEvent );
177cdf0e10cSrcweir }
178cdf0e10cSrcweir
179cdf0e10cSrcweir return aFilterReturn;
180cdf0e10cSrcweir }
181cdf0e10cSrcweir
screenSizeChanged(GdkScreen * pScreen)182cdf0e10cSrcweir void GtkSalDisplay::screenSizeChanged( GdkScreen* pScreen )
183cdf0e10cSrcweir {
184cdf0e10cSrcweir if( pScreen )
185cdf0e10cSrcweir {
186cdf0e10cSrcweir int nScreen = gdk_screen_get_number( pScreen );
187cdf0e10cSrcweir if( nScreen < static_cast<int>(m_aScreens.size()) )
188cdf0e10cSrcweir {
189cdf0e10cSrcweir ScreenData& rSD = const_cast<ScreenData&>(m_aScreens[nScreen]);
190cdf0e10cSrcweir if( rSD.m_bInit )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir rSD.m_aSize = Size( gdk_screen_get_width( pScreen ),
193cdf0e10cSrcweir gdk_screen_get_height( pScreen ) );
194cdf0e10cSrcweir if( ! m_aFrames.empty() )
195cdf0e10cSrcweir m_aFrames.front()->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
196cdf0e10cSrcweir }
197cdf0e10cSrcweir }
198cdf0e10cSrcweir else
199cdf0e10cSrcweir {
200cdf0e10cSrcweir DBG_ERROR( "unknown screen changed size" );
201cdf0e10cSrcweir }
202cdf0e10cSrcweir }
203cdf0e10cSrcweir }
204cdf0e10cSrcweir
monitorsChanged(GdkScreen * pScreen)205cdf0e10cSrcweir void GtkSalDisplay::monitorsChanged( GdkScreen* pScreen )
206cdf0e10cSrcweir {
207cdf0e10cSrcweir /* Caution: since we support the _NET_WM_FULLSCREEN_MONITORS property now and
208cdf0e10cSrcweir the EWMH spec says, the index used for that needs to be that of the
209cdf0e10cSrcweir Xinerama extension, we need to ensure that the order of m_aXineramaScreens is actually intact.
210cdf0e10cSrcweir
211cdf0e10cSrcweir gdk_screen_get_monitor_geometry however has a different sort order that has a default monitor number
212cdf0e10cSrcweir Xinerama returns the default monitor as 0.
213cdf0e10cSrcweir That means if we fill in the multiple montors vector from gdk, we'll get the wrong order unless
214cdf0e10cSrcweir the default monitor is incidentally the same (number 0).
215cdf0e10cSrcweir
216cdf0e10cSrcweir Given that XRandR (which is what gdk_screen_get_monitor_geometry is based on) is
217cdf0e10cSrcweir supposed to replace Xinerama, this is bound to get a problem at some time again,
218cdf0e10cSrcweir unfortunately there does not currently seem to be a way to map the returns of xinerama to
219cdf0e10cSrcweir that of randr. Currently getting Xinerama values again works with updated values, given
220cdf0e10cSrcweir a new enough Xserver.
221cdf0e10cSrcweir */
222cdf0e10cSrcweir InitXinerama();
223cdf0e10cSrcweir (void)pScreen;
224cdf0e10cSrcweir
225cdf0e10cSrcweir #if 0
226cdf0e10cSrcweir if( pScreen )
227cdf0e10cSrcweir {
228cdf0e10cSrcweir if( gdk_display_get_n_screens(m_pGdkDisplay) == 1 )
229cdf0e10cSrcweir {
230cdf0e10cSrcweir int nScreen = gdk_screen_get_number( pScreen );
231cdf0e10cSrcweir if( nScreen == m_nDefaultScreen ) //To-Do, make m_aXineramaScreens a per-screen thing ?
232cdf0e10cSrcweir {
233cdf0e10cSrcweir gint nMonitors = gdk_screen_get_n_monitors(pScreen);
234cdf0e10cSrcweir m_aXineramaScreens = std::vector<Rectangle>();
235cdf0e10cSrcweir m_aXineramaScreenIndexMap = std::vector<int>(nMonitors);
236cdf0e10cSrcweir for (gint i = 0; i < nMonitors; ++i)
237cdf0e10cSrcweir {
238cdf0e10cSrcweir GdkRectangle dest;
239cdf0e10cSrcweir gdk_screen_get_monitor_geometry(pScreen, i, &dest);
240cdf0e10cSrcweir m_aXineramaScreenIndexMap[i] = addXineramaScreenUnique( dest.x, dest.y, dest.width, dest.height );
241cdf0e10cSrcweir }
242cdf0e10cSrcweir m_bXinerama = m_aXineramaScreens.size() > 1;
243cdf0e10cSrcweir if( ! m_aFrames.empty() )
244cdf0e10cSrcweir m_aFrames.front()->CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
245cdf0e10cSrcweir }
246cdf0e10cSrcweir else
247cdf0e10cSrcweir {
248cdf0e10cSrcweir DBG_ERROR( "monitors for non-default screen changed, extend-me" );
249cdf0e10cSrcweir }
250cdf0e10cSrcweir }
251cdf0e10cSrcweir }
252cdf0e10cSrcweir #endif
253cdf0e10cSrcweir }
254cdf0e10cSrcweir
255cdf0e10cSrcweir extern "C"
256cdf0e10cSrcweir {
257cdf0e10cSrcweir typedef gint(* screen_get_primary_monitor)(GdkScreen *screen);
258cdf0e10cSrcweir }
259cdf0e10cSrcweir
GetDefaultMonitorNumber() const260cdf0e10cSrcweir int GtkSalDisplay::GetDefaultMonitorNumber() const
261cdf0e10cSrcweir {
262cdf0e10cSrcweir int n = 0;
263cdf0e10cSrcweir
264cdf0e10cSrcweir // currently disabled, see remarks in monitorsChanged
265cdf0e10cSrcweir #if 0
266cdf0e10cSrcweir GdkScreen* pScreen = gdk_display_get_screen( m_pGdkDisplay, m_nDefaultScreen );
267cdf0e10cSrcweir #if GTK_CHECK_VERSION(2,20,0)
268cdf0e10cSrcweir n = gdk_screen_get_primary_monitor(pScreen);
269cdf0e10cSrcweir #else
270cdf0e10cSrcweir static screen_get_primary_monitor sym_gdk_screen_get_primary_monitor =
271cdf0e10cSrcweir (screen_get_primary_monitor)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_screen_get_primary_monitor" );
272cdf0e10cSrcweir if (sym_gdk_screen_get_primary_monitor)
273cdf0e10cSrcweir n = sym_gdk_screen_get_primary_monitor( pScreen );
274cdf0e10cSrcweir #endif
275cdf0e10cSrcweir if( n >= 0 && size_t(n) < m_aXineramaScreenIndexMap.size() )
276cdf0e10cSrcweir n = m_aXineramaScreenIndexMap[n];
277cdf0e10cSrcweir #endif
278cdf0e10cSrcweir return n;
279cdf0e10cSrcweir }
280cdf0e10cSrcweir
initScreen(int nScreen) const281cdf0e10cSrcweir void GtkSalDisplay::initScreen( int nScreen ) const
282cdf0e10cSrcweir {
283cdf0e10cSrcweir if( nScreen < 0 || nScreen >= static_cast<int>(m_aScreens.size()) )
284cdf0e10cSrcweir nScreen = m_nDefaultScreen;
285cdf0e10cSrcweir ScreenData& rSD = const_cast<ScreenData&>(m_aScreens[nScreen]);
286cdf0e10cSrcweir if( rSD.m_bInit )
287cdf0e10cSrcweir return;
288cdf0e10cSrcweir
289cdf0e10cSrcweir // choose visual for screen
290cdf0e10cSrcweir SalDisplay::initScreen( nScreen );
291cdf0e10cSrcweir // now set a gdk default colormap matching the chosen visual to the screen
292cdf0e10cSrcweir GdkVisual* pVis = gdkx_visual_get( rSD.m_aVisual.visualid );
293cdf0e10cSrcweir GdkScreen* pScreen = gdk_display_get_screen( m_pGdkDisplay, nScreen );
294cdf0e10cSrcweir if( pVis )
295cdf0e10cSrcweir {
296cdf0e10cSrcweir GdkColormap* pDefCol = gdk_screen_get_default_colormap( pScreen );
297cdf0e10cSrcweir GdkVisual* pDefVis = gdk_colormap_get_visual( pDefCol );
298cdf0e10cSrcweir if( pDefVis != pVis )
299cdf0e10cSrcweir {
300cdf0e10cSrcweir pDefCol = gdk_x11_colormap_foreign_new( pVis, rSD.m_aColormap.GetXColormap() );
301cdf0e10cSrcweir gdk_screen_set_default_colormap( pScreen, pDefCol );
302cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
303cdf0e10cSrcweir fprintf( stderr, "set new gdk color map for screen %d\n", nScreen );
304cdf0e10cSrcweir #endif
305cdf0e10cSrcweir }
306cdf0e10cSrcweir }
307cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
308cdf0e10cSrcweir else
309cdf0e10cSrcweir fprintf( stderr, "not GdkVisual for visual id %d\n", (int)rSD.m_aVisual.visualid );
310cdf0e10cSrcweir #endif
311cdf0e10cSrcweir }
312cdf0e10cSrcweir
Dispatch(XEvent * pEvent)313cdf0e10cSrcweir long GtkSalDisplay::Dispatch( XEvent* pEvent )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir if( GetDisplay() == pEvent->xany.display )
316cdf0e10cSrcweir {
317cdf0e10cSrcweir // let's see if one of our frames wants to swallow these events
318cdf0e10cSrcweir // get the child frame
319cdf0e10cSrcweir for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
320cdf0e10cSrcweir it != m_aFrames.end(); ++it )
321cdf0e10cSrcweir {
322cdf0e10cSrcweir if( (GdkNativeWindow)(*it)->GetSystemData()->aWindow == pEvent->xany.window )
323cdf0e10cSrcweir return static_cast<GtkSalFrame*>(*it)->Dispatch( pEvent );
324cdf0e10cSrcweir }
325cdf0e10cSrcweir }
326cdf0e10cSrcweir
327cdf0e10cSrcweir return GDK_FILTER_CONTINUE;
328cdf0e10cSrcweir }
329cdf0e10cSrcweir
getFromXPM(const char * pBitmap,const char * pMask,int nWidth,int nHeight,int nXHot,int nYHot)330cdf0e10cSrcweir GdkCursor* GtkSalDisplay::getFromXPM( const char *pBitmap,
331cdf0e10cSrcweir const char *pMask,
332cdf0e10cSrcweir int nWidth, int nHeight,
333cdf0e10cSrcweir int nXHot, int nYHot )
334cdf0e10cSrcweir {
335cdf0e10cSrcweir GdkScreen *pScreen = gdk_display_get_default_screen( m_pGdkDisplay );
336cdf0e10cSrcweir GdkDrawable *pDrawable = GDK_DRAWABLE( gdk_screen_get_root_window (pScreen) );
337cdf0e10cSrcweir GdkBitmap *pBitmapPix = gdk_bitmap_create_from_data
338cdf0e10cSrcweir ( pDrawable, pBitmap, nWidth, nHeight );
339cdf0e10cSrcweir GdkBitmap *pMaskPix = gdk_bitmap_create_from_data
340cdf0e10cSrcweir ( pDrawable, pMask, nWidth, nHeight );
341cdf0e10cSrcweir GdkColormap *pColormap = gdk_drawable_get_colormap( pDrawable );
342cdf0e10cSrcweir
343cdf0e10cSrcweir GdkColor aWhite = { 0, 0xffff, 0xffff, 0xffff };
344cdf0e10cSrcweir GdkColor aBlack = { 0, 0, 0, 0 };
345cdf0e10cSrcweir
346cdf0e10cSrcweir gdk_colormap_alloc_color( pColormap, &aBlack, FALSE, TRUE);
347cdf0e10cSrcweir gdk_colormap_alloc_color( pColormap, &aWhite, FALSE, TRUE);
348cdf0e10cSrcweir
349cdf0e10cSrcweir return gdk_cursor_new_from_pixmap
350cdf0e10cSrcweir ( pBitmapPix, pMaskPix,
351cdf0e10cSrcweir &aBlack, &aWhite, nXHot, nYHot);
352cdf0e10cSrcweir }
353cdf0e10cSrcweir
354cdf0e10cSrcweir #define MAKE_CURSOR( vcl_name, name ) \
355cdf0e10cSrcweir case vcl_name: \
35630c1b1efSHerbert Dürr pCursor = getFromXPM( (const char*)name##curs##_bits, (const char*)name##mask##_bits, \
357cdf0e10cSrcweir name##curs_width, name##curs_height, \
358cdf0e10cSrcweir name##curs_x_hot, name##curs_y_hot ); \
359cdf0e10cSrcweir break
360cdf0e10cSrcweir #define MAP_BUILTIN( vcl_name, gdk_name ) \
361cdf0e10cSrcweir case vcl_name: \
362cdf0e10cSrcweir pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, gdk_name ); \
363cdf0e10cSrcweir break
364cdf0e10cSrcweir
getCursor(PointerStyle ePointerStyle)365cdf0e10cSrcweir GdkCursor *GtkSalDisplay::getCursor( PointerStyle ePointerStyle )
366cdf0e10cSrcweir {
36793ed1f29SArmin Le Grand if (ePointerStyle >= POINTER_COUNT)
368cdf0e10cSrcweir return NULL;
369cdf0e10cSrcweir
370cdf0e10cSrcweir if ( !m_aCursors[ ePointerStyle ] )
371cdf0e10cSrcweir {
372cdf0e10cSrcweir GdkCursor *pCursor = NULL;
373cdf0e10cSrcweir
374cdf0e10cSrcweir switch( ePointerStyle )
375cdf0e10cSrcweir {
376cdf0e10cSrcweir MAP_BUILTIN( POINTER_ARROW, GDK_LEFT_PTR );
377cdf0e10cSrcweir MAP_BUILTIN( POINTER_TEXT, GDK_XTERM );
378cdf0e10cSrcweir MAP_BUILTIN( POINTER_HELP, GDK_QUESTION_ARROW );
379cdf0e10cSrcweir MAP_BUILTIN( POINTER_CROSS, GDK_CROSSHAIR );
380cdf0e10cSrcweir MAP_BUILTIN( POINTER_WAIT, GDK_WATCH );
381cdf0e10cSrcweir
382cdf0e10cSrcweir MAP_BUILTIN( POINTER_NSIZE, GDK_SB_V_DOUBLE_ARROW );
383cdf0e10cSrcweir MAP_BUILTIN( POINTER_SSIZE, GDK_SB_V_DOUBLE_ARROW );
384cdf0e10cSrcweir MAP_BUILTIN( POINTER_WSIZE, GDK_SB_H_DOUBLE_ARROW );
385cdf0e10cSrcweir MAP_BUILTIN( POINTER_ESIZE, GDK_SB_H_DOUBLE_ARROW );
386cdf0e10cSrcweir
387cdf0e10cSrcweir MAP_BUILTIN( POINTER_NWSIZE, GDK_TOP_LEFT_CORNER );
388cdf0e10cSrcweir MAP_BUILTIN( POINTER_NESIZE, GDK_TOP_RIGHT_CORNER );
389cdf0e10cSrcweir MAP_BUILTIN( POINTER_SWSIZE, GDK_BOTTOM_LEFT_CORNER );
390cdf0e10cSrcweir MAP_BUILTIN( POINTER_SESIZE, GDK_BOTTOM_RIGHT_CORNER );
391cdf0e10cSrcweir
392cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_NSIZE, GDK_TOP_SIDE );
393cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_SSIZE, GDK_BOTTOM_SIDE );
394cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_WSIZE, GDK_LEFT_SIDE );
395cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_ESIZE, GDK_RIGHT_SIDE );
396cdf0e10cSrcweir
397cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_NWSIZE, GDK_TOP_LEFT_CORNER );
398cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_NESIZE, GDK_TOP_RIGHT_CORNER );
399cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_SWSIZE, GDK_BOTTOM_LEFT_CORNER );
400cdf0e10cSrcweir MAP_BUILTIN( POINTER_WINDOW_SESIZE, GDK_BOTTOM_RIGHT_CORNER );
401cdf0e10cSrcweir
402cdf0e10cSrcweir MAP_BUILTIN( POINTER_HSIZEBAR, GDK_SB_H_DOUBLE_ARROW );
403cdf0e10cSrcweir MAP_BUILTIN( POINTER_VSIZEBAR, GDK_SB_V_DOUBLE_ARROW );
404cdf0e10cSrcweir
405cdf0e10cSrcweir MAP_BUILTIN( POINTER_REFHAND, GDK_HAND1 );
406cdf0e10cSrcweir MAP_BUILTIN( POINTER_HAND, GDK_HAND2 );
407cdf0e10cSrcweir MAP_BUILTIN( POINTER_PEN, GDK_PENCIL );
408cdf0e10cSrcweir
409cdf0e10cSrcweir MAP_BUILTIN( POINTER_HSPLIT, GDK_SB_H_DOUBLE_ARROW );
410cdf0e10cSrcweir MAP_BUILTIN( POINTER_VSPLIT, GDK_SB_V_DOUBLE_ARROW );
411cdf0e10cSrcweir
412cdf0e10cSrcweir MAP_BUILTIN( POINTER_MOVE, GDK_FLEUR );
413cdf0e10cSrcweir
414cdf0e10cSrcweir MAKE_CURSOR( POINTER_NULL, null );
415cdf0e10cSrcweir MAKE_CURSOR( POINTER_MAGNIFY, magnify_ );
416cdf0e10cSrcweir MAKE_CURSOR( POINTER_FILL, fill_ );
417cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEDATA, movedata_ );
418cdf0e10cSrcweir MAKE_CURSOR( POINTER_COPYDATA, copydata_ );
419cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEFILE, movefile_ );
420cdf0e10cSrcweir MAKE_CURSOR( POINTER_COPYFILE, copyfile_ );
421cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEFILES, movefiles_ );
422cdf0e10cSrcweir MAKE_CURSOR( POINTER_COPYFILES, copyfiles_ );
423cdf0e10cSrcweir MAKE_CURSOR( POINTER_NOTALLOWED, nodrop_ );
424cdf0e10cSrcweir MAKE_CURSOR( POINTER_ROTATE, rotate_ );
425cdf0e10cSrcweir MAKE_CURSOR( POINTER_HSHEAR, hshear_ );
426cdf0e10cSrcweir MAKE_CURSOR( POINTER_VSHEAR, vshear_ );
427cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_LINE, drawline_ );
428cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_RECT, drawrect_ );
429cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_POLYGON, drawpolygon_ );
430cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_BEZIER, drawbezier_ );
431cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_ARC, drawarc_ );
432cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_PIE, drawpie_ );
433cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_CIRCLECUT, drawcirclecut_ );
434cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_ELLIPSE, drawellipse_ );
435cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_CONNECT, drawconnect_ );
436cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_TEXT, drawtext_ );
437cdf0e10cSrcweir MAKE_CURSOR( POINTER_MIRROR, mirror_ );
438cdf0e10cSrcweir MAKE_CURSOR( POINTER_CROOK, crook_ );
439cdf0e10cSrcweir MAKE_CURSOR( POINTER_CROP, crop_ );
440cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEPOINT, movepoint_ );
441cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEBEZIERWEIGHT, movebezierweight_ );
442cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_FREEHAND, drawfreehand_ );
443cdf0e10cSrcweir MAKE_CURSOR( POINTER_DRAW_CAPTION, drawcaption_ );
444cdf0e10cSrcweir MAKE_CURSOR( POINTER_LINKDATA, linkdata_ );
445cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEDATALINK, movedlnk_ );
446cdf0e10cSrcweir MAKE_CURSOR( POINTER_COPYDATALINK, copydlnk_ );
447cdf0e10cSrcweir MAKE_CURSOR( POINTER_LINKFILE, linkfile_ );
448cdf0e10cSrcweir MAKE_CURSOR( POINTER_MOVEFILELINK, moveflnk_ );
449cdf0e10cSrcweir MAKE_CURSOR( POINTER_COPYFILELINK, copyflnk_ );
450cdf0e10cSrcweir MAKE_CURSOR( POINTER_CHART, chart_ );
451cdf0e10cSrcweir MAKE_CURSOR( POINTER_DETECTIVE, detective_ );
452cdf0e10cSrcweir MAKE_CURSOR( POINTER_PIVOT_COL, pivotcol_ );
453cdf0e10cSrcweir MAKE_CURSOR( POINTER_PIVOT_ROW, pivotrow_ );
454cdf0e10cSrcweir MAKE_CURSOR( POINTER_PIVOT_FIELD, pivotfld_ );
455cdf0e10cSrcweir MAKE_CURSOR( POINTER_PIVOT_DELETE, pivotdel_ );
456cdf0e10cSrcweir MAKE_CURSOR( POINTER_CHAIN, chain_ );
457cdf0e10cSrcweir MAKE_CURSOR( POINTER_CHAIN_NOTALLOWED, chainnot_ );
458cdf0e10cSrcweir MAKE_CURSOR( POINTER_TIMEEVENT_MOVE, timemove_ );
459cdf0e10cSrcweir MAKE_CURSOR( POINTER_TIMEEVENT_SIZE, timesize_ );
460cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_N, asn_ );
461cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_S, ass_ );
462cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_W, asw_ );
463cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_E, ase_ );
464cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_NW, asnw_ );
465cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_NE, asne_ );
466cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_SW, assw_ );
467cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_SE, asse_ );
468cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_NS, asns_ );
469cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_WE, aswe_ );
470cdf0e10cSrcweir MAKE_CURSOR( POINTER_AUTOSCROLL_NSWE, asnswe_ );
471cdf0e10cSrcweir MAKE_CURSOR( POINTER_AIRBRUSH, airbrush_ );
472cdf0e10cSrcweir MAKE_CURSOR( POINTER_TEXT_VERTICAL, vertcurs_ );
473cdf0e10cSrcweir
474cdf0e10cSrcweir // --> FME 2004-07-30 #i32329# Enhanced table selection
475cdf0e10cSrcweir MAKE_CURSOR( POINTER_TAB_SELECT_S, tblsels_ );
476cdf0e10cSrcweir MAKE_CURSOR( POINTER_TAB_SELECT_E, tblsele_ );
477cdf0e10cSrcweir MAKE_CURSOR( POINTER_TAB_SELECT_SE, tblselse_ );
478cdf0e10cSrcweir MAKE_CURSOR( POINTER_TAB_SELECT_W, tblselw_ );
479cdf0e10cSrcweir MAKE_CURSOR( POINTER_TAB_SELECT_SW, tblselsw_ );
480cdf0e10cSrcweir // <--
481cdf0e10cSrcweir
482cdf0e10cSrcweir // --> FME 2004-08-16 #i20119# Paintbrush tool
483cdf0e10cSrcweir MAKE_CURSOR( POINTER_PAINTBRUSH, paintbrush_ );
484cdf0e10cSrcweir // <--
485cdf0e10cSrcweir
486cdf0e10cSrcweir default:
487cdf0e10cSrcweir fprintf( stderr, "pointer %d not implemented", ePointerStyle );
488cdf0e10cSrcweir break;
489cdf0e10cSrcweir }
490cdf0e10cSrcweir if( !pCursor )
491cdf0e10cSrcweir pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, GDK_LEFT_PTR );
492cdf0e10cSrcweir
493cdf0e10cSrcweir m_aCursors[ ePointerStyle ] = pCursor;
494cdf0e10cSrcweir }
495cdf0e10cSrcweir
496cdf0e10cSrcweir return m_aCursors[ ePointerStyle ];
497cdf0e10cSrcweir }
498cdf0e10cSrcweir
CaptureMouse(SalFrame * pSFrame)499cdf0e10cSrcweir int GtkSalDisplay::CaptureMouse( SalFrame* pSFrame )
500cdf0e10cSrcweir {
501cdf0e10cSrcweir GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(pSFrame);
502cdf0e10cSrcweir
503cdf0e10cSrcweir if( !pFrame )
504cdf0e10cSrcweir {
505cdf0e10cSrcweir if( m_pCapture )
506cdf0e10cSrcweir static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
507cdf0e10cSrcweir m_pCapture = NULL;
508cdf0e10cSrcweir return 0;
509cdf0e10cSrcweir }
510cdf0e10cSrcweir
511cdf0e10cSrcweir if( m_pCapture )
512cdf0e10cSrcweir {
513cdf0e10cSrcweir if( pFrame == m_pCapture )
514cdf0e10cSrcweir return 1;
515cdf0e10cSrcweir static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
516cdf0e10cSrcweir }
517cdf0e10cSrcweir
518cdf0e10cSrcweir m_pCapture = pFrame;
519cdf0e10cSrcweir static_cast<GtkSalFrame*>(pFrame)->grabPointer( TRUE );
520cdf0e10cSrcweir return 1;
521cdf0e10cSrcweir }
522cdf0e10cSrcweir
523cdf0e10cSrcweir /***************************************************************************
524cdf0e10cSrcweir * class GtkXLib *
525cdf0e10cSrcweir ***************************************************************************/
526cdf0e10cSrcweir
527cdf0e10cSrcweir class GtkXLib : public SalXLib
528cdf0e10cSrcweir {
529cdf0e10cSrcweir GtkSalDisplay *m_pGtkSalDisplay;
530cdf0e10cSrcweir std::list<GSource *> m_aSources;
531cdf0e10cSrcweir GSource *m_pTimeout;
532cdf0e10cSrcweir GSource *m_pUserEvent;
533cdf0e10cSrcweir oslMutex m_aDispatchMutex;
534cdf0e10cSrcweir oslCondition m_aDispatchCondition;
535cdf0e10cSrcweir XIOErrorHandler m_aOrigGTKXIOErrorHandler;
536cdf0e10cSrcweir
537cdf0e10cSrcweir public:
538cdf0e10cSrcweir static gboolean timeoutFn(gpointer data);
539cdf0e10cSrcweir static gboolean userEventFn(gpointer data);
540cdf0e10cSrcweir
541cdf0e10cSrcweir GtkXLib();
542cdf0e10cSrcweir virtual ~GtkXLib();
543cdf0e10cSrcweir
544cdf0e10cSrcweir virtual void Init();
545cdf0e10cSrcweir virtual void Yield( bool bWait, bool bHandleAllCurrentEvents );
546cdf0e10cSrcweir virtual void Insert( int fd, void* data,
547cdf0e10cSrcweir YieldFunc pending,
548cdf0e10cSrcweir YieldFunc queued,
549cdf0e10cSrcweir YieldFunc handle );
550cdf0e10cSrcweir virtual void Remove( int fd );
551cdf0e10cSrcweir
552cdf0e10cSrcweir virtual void StartTimer( sal_uLong nMS );
553cdf0e10cSrcweir virtual void StopTimer();
554cdf0e10cSrcweir virtual void Wakeup();
555cdf0e10cSrcweir virtual void PostUserEvent();
556cdf0e10cSrcweir };
557cdf0e10cSrcweir
GtkXLib()558cdf0e10cSrcweir GtkXLib::GtkXLib()
559cdf0e10cSrcweir {
560cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
561cdf0e10cSrcweir fprintf( stderr, "GtkXLib::GtkXLib()\n" );
562cdf0e10cSrcweir #endif
563cdf0e10cSrcweir m_pGtkSalDisplay = NULL;
564cdf0e10cSrcweir m_pTimeout = NULL;
565cdf0e10cSrcweir m_nTimeoutMS = 0;
566cdf0e10cSrcweir m_pUserEvent = NULL;
567cdf0e10cSrcweir m_aDispatchCondition = osl_createCondition();
568cdf0e10cSrcweir m_aDispatchMutex = osl_createMutex();
569cdf0e10cSrcweir m_aOrigGTKXIOErrorHandler = NULL;
570cdf0e10cSrcweir }
571cdf0e10cSrcweir
~GtkXLib()572cdf0e10cSrcweir GtkXLib::~GtkXLib()
573cdf0e10cSrcweir {
574cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
575cdf0e10cSrcweir fprintf( stderr, "GtkXLib::~GtkXLib()\n" );
576cdf0e10cSrcweir #endif
577cdf0e10cSrcweir StopTimer();
578cdf0e10cSrcweir // sanity check: at this point nobody should be yielding, but wake them
579cdf0e10cSrcweir // up anyway before the condition they're waiting on gets destroyed.
580cdf0e10cSrcweir osl_setCondition( m_aDispatchCondition );
581cdf0e10cSrcweir osl_destroyCondition( m_aDispatchCondition );
582cdf0e10cSrcweir osl_destroyMutex( m_aDispatchMutex );
583cdf0e10cSrcweir
584cdf0e10cSrcweir PopXErrorLevel();
585cdf0e10cSrcweir XSetIOErrorHandler (m_aOrigGTKXIOErrorHandler);
586cdf0e10cSrcweir }
587cdf0e10cSrcweir
Init()588cdf0e10cSrcweir void GtkXLib::Init()
589cdf0e10cSrcweir {
590cdf0e10cSrcweir int i;
591cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
592cdf0e10cSrcweir fprintf( stderr, "GtkXLib::Init()\n" );
593cdf0e10cSrcweir #endif
594cdf0e10cSrcweir XrmInitialize();
595cdf0e10cSrcweir
596cdf0e10cSrcweir gtk_set_locale();
597cdf0e10cSrcweir
598cdf0e10cSrcweir /*
599cdf0e10cSrcweir * open connection to X11 Display
600cdf0e10cSrcweir * try in this order:
601cdf0e10cSrcweir * o -display command line parameter,
602cdf0e10cSrcweir * o $DISPLAY environment variable
603cdf0e10cSrcweir * o default display
604cdf0e10cSrcweir */
605cdf0e10cSrcweir
606cdf0e10cSrcweir GdkDisplay *pGdkDisp = NULL;
607cdf0e10cSrcweir
608cdf0e10cSrcweir // is there a -display command line parameter?
609cdf0e10cSrcweir rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
610cdf0e10cSrcweir int nParams = osl_getCommandArgCount();
611cdf0e10cSrcweir rtl::OString aDisplay;
612cdf0e10cSrcweir rtl::OUString aParam, aBin;
613cdf0e10cSrcweir char** pCmdLineAry = new char*[ nParams+1 ];
614cdf0e10cSrcweir osl_getExecutableFile( &aParam.pData );
615cdf0e10cSrcweir osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
616cdf0e10cSrcweir pCmdLineAry[0] = g_strdup( OUStringToOString( aBin, aEnc ).getStr() );
617cdf0e10cSrcweir for (i=0; i<nParams; i++)
618cdf0e10cSrcweir {
619cdf0e10cSrcweir osl_getCommandArg(i, &aParam.pData );
620cdf0e10cSrcweir OString aBParam( OUStringToOString( aParam, aEnc ) );
621cdf0e10cSrcweir
622cdf0e10cSrcweir if( aParam.equalsAscii( "-display" ) || aParam.equalsAscii( "--display" ) )
623cdf0e10cSrcweir {
624cdf0e10cSrcweir pCmdLineAry[i+1] = g_strdup( "--display" );
625cdf0e10cSrcweir osl_getCommandArg(i+1, &aParam.pData );
626cdf0e10cSrcweir aDisplay = rtl::OUStringToOString( aParam, aEnc );
627cdf0e10cSrcweir }
628cdf0e10cSrcweir else
629cdf0e10cSrcweir pCmdLineAry[i+1] = g_strdup( aBParam.getStr() );
630cdf0e10cSrcweir }
631cdf0e10cSrcweir // add executable
632cdf0e10cSrcweir nParams++;
633cdf0e10cSrcweir
634cdf0e10cSrcweir g_set_application_name(X11SalData::getFrameClassName());
635cdf0e10cSrcweir
636cdf0e10cSrcweir // Set consistant name of the root accessible
637cdf0e10cSrcweir rtl::OUString aAppName = Application::GetAppName();
638cdf0e10cSrcweir if( aAppName.getLength() > 0 )
639cdf0e10cSrcweir {
640cdf0e10cSrcweir rtl::OString aPrgName = rtl::OUStringToOString(aAppName, aEnc);
641*24c56ab9SHerbert Dürr g_set_prgname( aPrgName.getStr());
642cdf0e10cSrcweir }
643cdf0e10cSrcweir
644cdf0e10cSrcweir // init gtk/gdk
645cdf0e10cSrcweir gtk_init_check( &nParams, &pCmdLineAry );
646cdf0e10cSrcweir
647cdf0e10cSrcweir //gtk_init_check sets XError/XIOError handlers, we want our own one
648cdf0e10cSrcweir m_aOrigGTKXIOErrorHandler = XSetIOErrorHandler ( (XIOErrorHandler)X11SalData::XIOErrorHdl );
649cdf0e10cSrcweir PushXErrorLevel( !!getenv( "SAL_IGNOREXERRORS" ) );
650cdf0e10cSrcweir
651cdf0e10cSrcweir for (i = 0; i < nParams; i++ )
652cdf0e10cSrcweir g_free( pCmdLineAry[i] );
653cdf0e10cSrcweir delete [] pCmdLineAry;
654cdf0e10cSrcweir
655cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
656cdf0e10cSrcweir if (g_getenv ("SAL_DEBUG_UPDATES"))
657cdf0e10cSrcweir gdk_window_set_debug_updates (TRUE);
658cdf0e10cSrcweir #endif
659cdf0e10cSrcweir
660cdf0e10cSrcweir pGdkDisp = gdk_display_get_default();
661cdf0e10cSrcweir if ( !pGdkDisp )
662cdf0e10cSrcweir {
663cdf0e10cSrcweir rtl::OUString aProgramFileURL;
664cdf0e10cSrcweir osl_getExecutableFile( &aProgramFileURL.pData );
665cdf0e10cSrcweir rtl::OUString aProgramSystemPath;
666cdf0e10cSrcweir osl_getSystemPathFromFileURL (aProgramFileURL.pData, &aProgramSystemPath.pData);
667cdf0e10cSrcweir rtl::OString aProgramName = rtl::OUStringToOString(
668cdf0e10cSrcweir aProgramSystemPath,
669cdf0e10cSrcweir osl_getThreadTextEncoding() );
670cdf0e10cSrcweir fprintf( stderr, "%s X11 error: Can't open display: %s\n",
671cdf0e10cSrcweir aProgramName.getStr(), aDisplay.getStr());
672cdf0e10cSrcweir fprintf( stderr, " Set DISPLAY environment variable, use -display option\n");
673cdf0e10cSrcweir fprintf( stderr, " or check permissions of your X-Server\n");
674cdf0e10cSrcweir fprintf( stderr, " (See \"man X\" resp. \"man xhost\" for details)\n");
675cdf0e10cSrcweir fflush( stderr );
676cdf0e10cSrcweir exit(0);
677cdf0e10cSrcweir }
678cdf0e10cSrcweir
679cdf0e10cSrcweir /*
680cdf0e10cSrcweir * if a -display switch was used, we need
681cdf0e10cSrcweir * to set the environment accoringly since
682cdf0e10cSrcweir * the clipboard build another connection
683cdf0e10cSrcweir * to the xserver using $DISPLAY
684cdf0e10cSrcweir */
685cdf0e10cSrcweir rtl::OUString envVar(RTL_CONSTASCII_USTRINGPARAM("DISPLAY"));
686cdf0e10cSrcweir const gchar *name = gdk_display_get_name( pGdkDisp );
687cdf0e10cSrcweir rtl::OUString envValue(name, strlen(name), aEnc);
688cdf0e10cSrcweir osl_setEnvironment(envVar.pData, envValue.pData);
689cdf0e10cSrcweir
690cdf0e10cSrcweir Display *pDisp = gdk_x11_display_get_xdisplay( pGdkDisp );
691cdf0e10cSrcweir
692cdf0e10cSrcweir m_pGtkSalDisplay = new GtkSalDisplay( pGdkDisp );
693cdf0e10cSrcweir
694cdf0e10cSrcweir gdk_window_add_filter( NULL, call_filterGdkEvent, m_pGtkSalDisplay );
695cdf0e10cSrcweir
696cdf0e10cSrcweir PushXErrorLevel( true );
697cdf0e10cSrcweir SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
698cdf0e10cSrcweir XSync( pDisp, False );
699cdf0e10cSrcweir
700cdf0e10cSrcweir pKbdExtension->UseExtension( ! HasXErrorOccured() );
701cdf0e10cSrcweir PopXErrorLevel();
702cdf0e10cSrcweir
703cdf0e10cSrcweir m_pGtkSalDisplay->SetKbdExtension( pKbdExtension );
704cdf0e10cSrcweir
705cdf0e10cSrcweir g_signal_connect( G_OBJECT(gdk_keymap_get_default()), "keys_changed", G_CALLBACK(signalKeysChanged), m_pGtkSalDisplay );
706cdf0e10cSrcweir
707cdf0e10cSrcweir // add signal handler to notify screen size changes
708cdf0e10cSrcweir int nScreens = gdk_display_get_n_screens( pGdkDisp );
709cdf0e10cSrcweir for( int n = 0; n < nScreens; n++ )
710cdf0e10cSrcweir {
711cdf0e10cSrcweir GdkScreen *pScreen = gdk_display_get_screen( pGdkDisp, n );
712cdf0e10cSrcweir if( pScreen )
713cdf0e10cSrcweir {
714cdf0e10cSrcweir g_signal_connect( G_OBJECT(pScreen), "size-changed", G_CALLBACK(signalScreenSizeChanged), m_pGtkSalDisplay );
715cdf0e10cSrcweir if( ! gtk_check_version( 2, 14, 0 ) ) // monitors-changed came in with 2.14, avoid an assertion
716cdf0e10cSrcweir g_signal_connect( G_OBJECT(pScreen), "monitors-changed", G_CALLBACK(signalMonitorsChanged), m_pGtkSalDisplay );
717cdf0e10cSrcweir }
718cdf0e10cSrcweir }
719cdf0e10cSrcweir }
720cdf0e10cSrcweir
721cdf0e10cSrcweir extern "C"
722cdf0e10cSrcweir {
call_timeoutFn(gpointer data)723cdf0e10cSrcweir gboolean call_timeoutFn(gpointer data)
724cdf0e10cSrcweir {
725cdf0e10cSrcweir return GtkXLib::timeoutFn(data);
726cdf0e10cSrcweir }
727cdf0e10cSrcweir }
728cdf0e10cSrcweir
timeoutFn(gpointer data)729cdf0e10cSrcweir gboolean GtkXLib::timeoutFn(gpointer data)
730cdf0e10cSrcweir {
731cdf0e10cSrcweir SalData *pSalData = GetSalData();
732cdf0e10cSrcweir GtkXLib *pThis = (GtkXLib *) data;
733cdf0e10cSrcweir
734cdf0e10cSrcweir pSalData->m_pInstance->GetYieldMutex()->acquire();
735cdf0e10cSrcweir
736cdf0e10cSrcweir if( pThis->m_pTimeout )
737cdf0e10cSrcweir {
738cdf0e10cSrcweir g_source_unref (pThis->m_pTimeout);
739cdf0e10cSrcweir pThis->m_pTimeout = NULL;
740cdf0e10cSrcweir }
741cdf0e10cSrcweir
742cdf0e10cSrcweir // Auto-restart immediately
743cdf0e10cSrcweir pThis->StartTimer( pThis->m_nTimeoutMS );
744cdf0e10cSrcweir
745cdf0e10cSrcweir GetX11SalData()->Timeout();
746cdf0e10cSrcweir
747cdf0e10cSrcweir pSalData->m_pInstance->GetYieldMutex()->release();
748cdf0e10cSrcweir
749cdf0e10cSrcweir return FALSE;
750cdf0e10cSrcweir }
751cdf0e10cSrcweir
StartTimer(sal_uLong nMS)752cdf0e10cSrcweir void GtkXLib::StartTimer( sal_uLong nMS )
753cdf0e10cSrcweir {
754cdf0e10cSrcweir m_nTimeoutMS = nMS; // for restarting
755cdf0e10cSrcweir
756cdf0e10cSrcweir if (m_pTimeout)
757cdf0e10cSrcweir {
758cdf0e10cSrcweir g_source_destroy (m_pTimeout);
759cdf0e10cSrcweir g_source_unref (m_pTimeout);
760cdf0e10cSrcweir }
761cdf0e10cSrcweir
762cdf0e10cSrcweir m_pTimeout = g_timeout_source_new (m_nTimeoutMS);
763cdf0e10cSrcweir // #i36226# timers should be executed with lower priority
764cdf0e10cSrcweir // than XEvents like in generic plugin
765cdf0e10cSrcweir g_source_set_priority( m_pTimeout, G_PRIORITY_LOW );
766cdf0e10cSrcweir g_source_set_can_recurse (m_pTimeout, TRUE);
767cdf0e10cSrcweir g_source_set_callback (m_pTimeout, call_timeoutFn,
768cdf0e10cSrcweir (gpointer) this, NULL);
769cdf0e10cSrcweir g_source_attach (m_pTimeout, g_main_context_default ());
770cdf0e10cSrcweir
771cdf0e10cSrcweir SalXLib::StartTimer( nMS );
772cdf0e10cSrcweir }
773cdf0e10cSrcweir
StopTimer()774cdf0e10cSrcweir void GtkXLib::StopTimer()
775cdf0e10cSrcweir {
776cdf0e10cSrcweir SalXLib::StopTimer();
777cdf0e10cSrcweir
778cdf0e10cSrcweir if (m_pTimeout)
779cdf0e10cSrcweir {
780cdf0e10cSrcweir g_source_destroy (m_pTimeout);
781cdf0e10cSrcweir g_source_unref (m_pTimeout);
782cdf0e10cSrcweir m_pTimeout = NULL;
783cdf0e10cSrcweir }
784cdf0e10cSrcweir }
785cdf0e10cSrcweir
786cdf0e10cSrcweir extern "C"
787cdf0e10cSrcweir {
call_userEventFn(gpointer data)788cdf0e10cSrcweir gboolean call_userEventFn( gpointer data )
789cdf0e10cSrcweir {
790cdf0e10cSrcweir return GtkXLib::userEventFn( data );
791cdf0e10cSrcweir }
792cdf0e10cSrcweir }
793cdf0e10cSrcweir
userEventFn(gpointer data)794cdf0e10cSrcweir gboolean GtkXLib::userEventFn(gpointer data)
795cdf0e10cSrcweir {
796cdf0e10cSrcweir gboolean bContinue;
797cdf0e10cSrcweir GtkXLib *pThis = (GtkXLib *) data;
798cdf0e10cSrcweir SalData *pSalData = GetSalData();
799cdf0e10cSrcweir
800cdf0e10cSrcweir pSalData->m_pInstance->GetYieldMutex()->acquire();
801cdf0e10cSrcweir pThis->m_pGtkSalDisplay->EventGuardAcquire();
802cdf0e10cSrcweir
803cdf0e10cSrcweir if( !pThis->m_pGtkSalDisplay->HasMoreEvents() )
804cdf0e10cSrcweir {
805cdf0e10cSrcweir if( pThis->m_pUserEvent )
806cdf0e10cSrcweir {
807cdf0e10cSrcweir g_source_unref (pThis->m_pUserEvent);
808cdf0e10cSrcweir pThis->m_pUserEvent = NULL;
809cdf0e10cSrcweir }
810cdf0e10cSrcweir bContinue = FALSE;
811cdf0e10cSrcweir }
812cdf0e10cSrcweir else
813cdf0e10cSrcweir bContinue = TRUE;
814cdf0e10cSrcweir
815cdf0e10cSrcweir pThis->m_pGtkSalDisplay->EventGuardRelease();
816cdf0e10cSrcweir
817cdf0e10cSrcweir pThis->m_pGtkSalDisplay->DispatchInternalEvent();
818cdf0e10cSrcweir
819cdf0e10cSrcweir pSalData->m_pInstance->GetYieldMutex()->release();
820cdf0e10cSrcweir
821cdf0e10cSrcweir return bContinue;
822cdf0e10cSrcweir }
823cdf0e10cSrcweir
824cdf0e10cSrcweir // hEventGuard_ held during this invocation
PostUserEvent()825cdf0e10cSrcweir void GtkXLib::PostUserEvent()
826cdf0e10cSrcweir {
827cdf0e10cSrcweir if( !m_pUserEvent ) // not pending anyway
828cdf0e10cSrcweir {
829cdf0e10cSrcweir m_pUserEvent = g_idle_source_new();
830cdf0e10cSrcweir g_source_set_priority( m_pUserEvent, G_PRIORITY_HIGH );
831cdf0e10cSrcweir g_source_set_can_recurse (m_pUserEvent, TRUE);
832cdf0e10cSrcweir g_source_set_callback (m_pUserEvent, call_userEventFn,
833cdf0e10cSrcweir (gpointer) this, NULL);
834cdf0e10cSrcweir g_source_attach (m_pUserEvent, g_main_context_default ());
835cdf0e10cSrcweir }
836cdf0e10cSrcweir Wakeup();
837cdf0e10cSrcweir }
838cdf0e10cSrcweir
Wakeup()839cdf0e10cSrcweir void GtkXLib::Wakeup()
840cdf0e10cSrcweir {
841cdf0e10cSrcweir g_main_context_wakeup( g_main_context_default () );
842cdf0e10cSrcweir }
843cdf0e10cSrcweir
Yield(bool bWait,bool bHandleAllCurrentEvents)844cdf0e10cSrcweir void GtkXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
845cdf0e10cSrcweir {
846cdf0e10cSrcweir /* #i33212# only enter g_main_context_iteration in one thread at any one
847cdf0e10cSrcweir * time, else one of them potentially will never end as long as there is
848cdf0e10cSrcweir * another thread in in there. Having only one yieldin thread actually dispatch
849cdf0e10cSrcweir * fits the vcl event model (see e.g. the generic plugin).
850cdf0e10cSrcweir */
851cdf0e10cSrcweir
852cdf0e10cSrcweir bool bDispatchThread = false;
853cdf0e10cSrcweir gboolean wasEvent = FALSE;
854cdf0e10cSrcweir {
855cdf0e10cSrcweir // release YieldMutex (and re-acquire at block end)
856cdf0e10cSrcweir YieldMutexReleaser aReleaser;
857cdf0e10cSrcweir if( osl_tryToAcquireMutex( m_aDispatchMutex ) )
858cdf0e10cSrcweir bDispatchThread = true;
859cdf0e10cSrcweir else if( ! bWait )
860cdf0e10cSrcweir return; // someone else is waiting already, return
861cdf0e10cSrcweir
862cdf0e10cSrcweir
863cdf0e10cSrcweir if( bDispatchThread )
864cdf0e10cSrcweir {
865cdf0e10cSrcweir int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
866cdf0e10cSrcweir gboolean wasOneEvent = TRUE;
867cdf0e10cSrcweir while( nMaxEvents-- && wasOneEvent )
868cdf0e10cSrcweir {
869cdf0e10cSrcweir wasOneEvent = g_main_context_iteration( NULL, FALSE );
870cdf0e10cSrcweir if( wasOneEvent )
871cdf0e10cSrcweir wasEvent = TRUE;
872cdf0e10cSrcweir }
873cdf0e10cSrcweir if( bWait && ! wasEvent )
874cdf0e10cSrcweir wasEvent = g_main_context_iteration( NULL, TRUE );
875cdf0e10cSrcweir }
876cdf0e10cSrcweir else if( bWait )
877cdf0e10cSrcweir {
878cdf0e10cSrcweir /* #i41693# in case the dispatch thread hangs in join
879cdf0e10cSrcweir * for this thread the condition will never be set
880cdf0e10cSrcweir * workaround: timeout of 1 second a emergency exit
881cdf0e10cSrcweir */
882cdf0e10cSrcweir // we are the dispatch thread
883cdf0e10cSrcweir osl_resetCondition( m_aDispatchCondition );
884cdf0e10cSrcweir TimeValue aValue = { 1, 0 };
885cdf0e10cSrcweir osl_waitCondition( m_aDispatchCondition, &aValue );
886cdf0e10cSrcweir }
887cdf0e10cSrcweir }
888cdf0e10cSrcweir
889cdf0e10cSrcweir if( bDispatchThread )
890cdf0e10cSrcweir {
891cdf0e10cSrcweir osl_releaseMutex( m_aDispatchMutex );
892cdf0e10cSrcweir if( wasEvent )
893cdf0e10cSrcweir osl_setCondition( m_aDispatchCondition ); // trigger non dispatch thread yields
894cdf0e10cSrcweir }
895cdf0e10cSrcweir }
896cdf0e10cSrcweir
897cdf0e10cSrcweir extern "C" {
898cdf0e10cSrcweir
899cdf0e10cSrcweir typedef struct {
900cdf0e10cSrcweir GSource source;
901cdf0e10cSrcweir
902cdf0e10cSrcweir GPollFD pollfd;
903cdf0e10cSrcweir GIOCondition condition;
904cdf0e10cSrcweir
905cdf0e10cSrcweir YieldFunc pending;
906cdf0e10cSrcweir YieldFunc handle;
907cdf0e10cSrcweir gpointer user_data;
908cdf0e10cSrcweir } SalWatch;
909cdf0e10cSrcweir
910cdf0e10cSrcweir static gboolean
sal_source_prepare(GSource * source,gint * timeout)911cdf0e10cSrcweir sal_source_prepare (GSource *source,
912cdf0e10cSrcweir gint *timeout)
913cdf0e10cSrcweir {
914cdf0e10cSrcweir SalWatch *watch = (SalWatch *)source;
915cdf0e10cSrcweir
916cdf0e10cSrcweir *timeout = -1;
917cdf0e10cSrcweir
918cdf0e10cSrcweir if (watch->pending &&
919cdf0e10cSrcweir watch->pending (watch->pollfd.fd, watch->user_data)) {
920cdf0e10cSrcweir watch->pollfd.revents |= watch->condition;
921cdf0e10cSrcweir return TRUE;
922cdf0e10cSrcweir }
923cdf0e10cSrcweir
924cdf0e10cSrcweir return FALSE;
925cdf0e10cSrcweir }
926cdf0e10cSrcweir
927cdf0e10cSrcweir static gboolean
sal_source_check(GSource * source)928cdf0e10cSrcweir sal_source_check (GSource *source)
929cdf0e10cSrcweir {
930cdf0e10cSrcweir SalWatch *watch = (SalWatch *)source;
931cdf0e10cSrcweir
932cdf0e10cSrcweir return watch->pollfd.revents & watch->condition;
933cdf0e10cSrcweir }
934cdf0e10cSrcweir
935cdf0e10cSrcweir static gboolean
sal_source_dispatch(GSource * source,GSourceFunc,gpointer)936cdf0e10cSrcweir sal_source_dispatch (GSource *source,
937cdf0e10cSrcweir GSourceFunc,
938cdf0e10cSrcweir gpointer)
939cdf0e10cSrcweir {
940cdf0e10cSrcweir SalData *pSalData = GetSalData();
941cdf0e10cSrcweir SalWatch *watch = (SalWatch *) source;
942cdf0e10cSrcweir
943cdf0e10cSrcweir pSalData->m_pInstance->GetYieldMutex()->acquire();
944cdf0e10cSrcweir
945cdf0e10cSrcweir watch->handle (watch->pollfd.fd, watch->user_data);
946cdf0e10cSrcweir
947cdf0e10cSrcweir pSalData->m_pInstance->GetYieldMutex()->release();
948cdf0e10cSrcweir
949cdf0e10cSrcweir return TRUE;
950cdf0e10cSrcweir }
951cdf0e10cSrcweir
952cdf0e10cSrcweir static void
sal_source_finalize(GSource *)953cdf0e10cSrcweir sal_source_finalize (GSource*)
954cdf0e10cSrcweir {
955cdf0e10cSrcweir }
956cdf0e10cSrcweir
957cdf0e10cSrcweir static GSourceFuncs sal_source_watch_funcs = {
958cdf0e10cSrcweir sal_source_prepare,
959cdf0e10cSrcweir sal_source_check,
960cdf0e10cSrcweir sal_source_dispatch,
961cdf0e10cSrcweir sal_source_finalize,
962cdf0e10cSrcweir NULL,
963cdf0e10cSrcweir NULL
964cdf0e10cSrcweir };
965cdf0e10cSrcweir
966cdf0e10cSrcweir static GSource *
sal_source_create_watch(int fd,GIOCondition condition,YieldFunc pending,YieldFunc handle,gpointer user_data)967cdf0e10cSrcweir sal_source_create_watch (int fd,
968cdf0e10cSrcweir GIOCondition condition,
969cdf0e10cSrcweir YieldFunc pending,
970cdf0e10cSrcweir YieldFunc handle,
971cdf0e10cSrcweir gpointer user_data)
972cdf0e10cSrcweir {
973cdf0e10cSrcweir GSource *source;
974cdf0e10cSrcweir SalWatch *watch;
975cdf0e10cSrcweir GMainContext *context = g_main_context_default ();
976cdf0e10cSrcweir
977cdf0e10cSrcweir source = g_source_new (&sal_source_watch_funcs,
978cdf0e10cSrcweir sizeof (SalWatch));
979cdf0e10cSrcweir watch = (SalWatch *) source;
980cdf0e10cSrcweir
981cdf0e10cSrcweir watch->pollfd.fd = fd;
982cdf0e10cSrcweir watch->pollfd.events = condition;
983cdf0e10cSrcweir watch->condition = condition;
984cdf0e10cSrcweir watch->pending = pending;
985cdf0e10cSrcweir watch->handle = handle;
986cdf0e10cSrcweir watch->user_data = user_data;
987cdf0e10cSrcweir
988cdf0e10cSrcweir g_source_set_can_recurse (source, TRUE);
989cdf0e10cSrcweir g_source_add_poll (source, &watch->pollfd);
990cdf0e10cSrcweir g_source_attach (source, context);
991cdf0e10cSrcweir
992cdf0e10cSrcweir return source;
993cdf0e10cSrcweir }
994cdf0e10cSrcweir
995cdf0e10cSrcweir } // extern "C"
996cdf0e10cSrcweir
Insert(int nFD,void * data,YieldFunc pending,YieldFunc,YieldFunc handle)997cdf0e10cSrcweir void GtkXLib::Insert( int nFD,
998cdf0e10cSrcweir void *data,
999cdf0e10cSrcweir YieldFunc pending,
1000cdf0e10cSrcweir YieldFunc,
1001cdf0e10cSrcweir YieldFunc handle )
1002cdf0e10cSrcweir {
1003cdf0e10cSrcweir GSource *source = sal_source_create_watch
1004cdf0e10cSrcweir ( nFD, (GIOCondition) ((G_IO_IN|G_IO_PRI) |
1005cdf0e10cSrcweir (G_IO_ERR|G_IO_HUP|G_IO_NVAL)),
1006cdf0e10cSrcweir pending, handle, data );
1007cdf0e10cSrcweir m_aSources.push_back( source );
1008cdf0e10cSrcweir }
1009cdf0e10cSrcweir
Remove(int nFD)1010cdf0e10cSrcweir void GtkXLib::Remove( int nFD )
1011cdf0e10cSrcweir {
1012cdf0e10cSrcweir ::std::list< GSource * >::iterator it;
1013cdf0e10cSrcweir
1014cdf0e10cSrcweir for (it = m_aSources.begin(); it != m_aSources.end(); ++it)
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir SalWatch *watch = (SalWatch *) *it;
1017cdf0e10cSrcweir
1018cdf0e10cSrcweir if (watch->pollfd.fd == nFD)
1019cdf0e10cSrcweir {
1020cdf0e10cSrcweir m_aSources.erase( it );
1021cdf0e10cSrcweir
1022cdf0e10cSrcweir g_source_destroy ((GSource *)watch);
1023cdf0e10cSrcweir g_source_unref ((GSource *)watch);
1024cdf0e10cSrcweir return;
1025cdf0e10cSrcweir }
1026cdf0e10cSrcweir }
1027cdf0e10cSrcweir }
1028cdf0e10cSrcweir
1029cdf0e10cSrcweir /**********************************************************************
1030cdf0e10cSrcweir * class GtkData *
1031cdf0e10cSrcweir **********************************************************************/
1032cdf0e10cSrcweir
~GtkData()1033cdf0e10cSrcweir GtkData::~GtkData()
1034cdf0e10cSrcweir {
1035cdf0e10cSrcweir }
1036cdf0e10cSrcweir
Init()1037cdf0e10cSrcweir void GtkData::Init()
1038cdf0e10cSrcweir {
1039cdf0e10cSrcweir pXLib_ = new GtkXLib();
1040cdf0e10cSrcweir pXLib_->Init();
1041cdf0e10cSrcweir }
1042