Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <unistd.h>
30 : : #include <fcntl.h>
31 : :
32 : : #include <stdio.h>
33 : : #include <string.h>
34 : : #include <stdlib.h>
35 : : #include <limits.h>
36 : : #include <errno.h>
37 : : #include <poll.h>
38 : : #if defined(FREEBSD) || defined(NETBSD)
39 : : #include <sys/types.h>
40 : : #include <sys/time.h>
41 : : #include <unistd.h>
42 : : #endif
43 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
44 : : #include <unx/gtk/gtkdata.hxx>
45 : : #include <unx/gtk/gtkinst.hxx>
46 : : #include <unx/gtk/gtkframe.hxx>
47 : : #include <unx/salobj.h>
48 : : #include <generic/geninst.h>
49 : : #include <osl/thread.h>
50 : : #include <osl/process.h>
51 : :
52 : : #include "unx/i18n_im.hxx"
53 : : #include "unx/i18n_xkb.hxx"
54 : : #include <unx/wmadaptor.hxx>
55 : :
56 : : #include "unx/x11_cursors/salcursors.h"
57 : :
58 : : #include <vcl/svapp.hxx>
59 : :
60 : : using namespace vcl_sal;
61 : :
62 : : using ::rtl::OUString;
63 : :
64 : : /***************************************************************
65 : : * class GtkSalDisplay *
66 : : ***************************************************************/
67 : : extern "C" {
68 : 0 : GdkFilterReturn call_filterGdkEvent( GdkXEvent* sys_event,
69 : : GdkEvent* event,
70 : : gpointer data )
71 : : {
72 : 0 : GtkSalDisplay *pDisplay = (GtkSalDisplay *)data;
73 : 0 : return pDisplay->filterGdkEvent( sys_event, event );
74 : : }
75 : : }
76 : :
77 : 0 : GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay ) :
78 : : #if !GTK_CHECK_VERSION(3,0,0)
79 : : SalDisplay( gdk_x11_display_get_xdisplay( pDisplay ) ),
80 : : #endif
81 : 0 : m_pSys( GtkSalSystem::GetSingleton() ),
82 : : m_pGdkDisplay( pDisplay ),
83 : 0 : m_bStartupCompleted( false )
84 : : {
85 : 0 : for(int i = 0; i < POINTER_COUNT; i++)
86 : 0 : m_aCursors[ i ] = NULL;
87 : : #if !GTK_CHECK_VERSION(3,0,0)
88 : 0 : m_bUseRandRWrapper = false; // use gdk signal instead
89 : 0 : Init ();
90 : : #endif
91 : :
92 : : // FIXME: unify this with SalInst's filter too ?
93 : 0 : gdk_window_add_filter( NULL, call_filterGdkEvent, this );
94 : :
95 : 0 : if ( getenv( "SAL_IGNOREXERRORS" ) )
96 : 0 : GetGenericData()->ErrorTrapPush(); // and leak the trap
97 : :
98 : : #if GTK_CHECK_VERSION(3,0,0)
99 : : m_bX11Display = GDK_IS_X11_DISPLAY( m_pGdkDisplay );
100 : : #else
101 : 0 : m_bX11Display = true;
102 : : #endif
103 : 0 : }
104 : :
105 : 0 : GtkSalDisplay::~GtkSalDisplay()
106 : : {
107 : 0 : gdk_window_remove_filter( NULL, call_filterGdkEvent, this );
108 : :
109 : 0 : if( !m_bStartupCompleted )
110 : 0 : gdk_notify_startup_complete();
111 : :
112 : : #if !GTK_CHECK_VERSION(3,0,0)
113 : 0 : doDestruct();
114 : 0 : pDisp_ = NULL;
115 : : #endif
116 : :
117 : 0 : for(int i = 0; i < POINTER_COUNT; i++)
118 : 0 : if( m_aCursors[ i ] )
119 : 0 : gdk_cursor_unref( m_aCursors[ i ] );
120 : 0 : }
121 : :
122 : : extern "C" {
123 : :
124 : 0 : void signalScreenSizeChanged( GdkScreen* pScreen, gpointer data )
125 : : {
126 : 0 : GtkSalDisplay* pDisp = (GtkSalDisplay*)data;
127 : 0 : pDisp->screenSizeChanged( pScreen );
128 : 0 : }
129 : :
130 : 0 : void signalMonitorsChanged( GdkScreen* pScreen, gpointer data )
131 : : {
132 : 0 : GtkSalDisplay* pDisp = (GtkSalDisplay*)data;
133 : 0 : pDisp->monitorsChanged( pScreen );
134 : 0 : }
135 : :
136 : : }
137 : :
138 : 0 : GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event,
139 : : GdkEvent* )
140 : : {
141 : : #if !GTK_CHECK_VERSION(3,0,0)
142 : 0 : GdkFilterReturn aFilterReturn = GDK_FILTER_CONTINUE;
143 : 0 : XEvent *pEvent = (XEvent *)sys_event;
144 : :
145 : : // dispatch all XEvents to event callback
146 : 0 : if( GetSalData()->m_pInstance->
147 : 0 : CallEventCallback( pEvent, sizeof( XEvent ) ) )
148 : 0 : aFilterReturn = GDK_FILTER_REMOVE;
149 : :
150 : 0 : GTK_YIELD_GRAB();
151 : :
152 : 0 : if (GetDisplay() == pEvent->xany.display )
153 : : {
154 : : // #i53471# gtk has no callback mechanism that lets us be notified
155 : : // when settings (as in XSETTING and opposed to styles) are changed.
156 : : // so we need to listen for corresponding property notifications here
157 : : // these should be rare enough so that we can assume that the settings
158 : : // actually change when a corresponding PropertyNotify occurs
159 : 0 : if( pEvent->type == PropertyNotify &&
160 : 0 : pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::XSETTINGS ) &&
161 : 0 : ! m_aFrames.empty()
162 : : )
163 : : {
164 : 0 : SendInternalEvent( m_aFrames.front(), NULL, SALEVENT_SETTINGSCHANGED );
165 : : }
166 : : // let's see if one of our frames wants to swallow these events
167 : : // get the frame
168 : 0 : for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
169 : 0 : it != m_aFrames.end(); ++it )
170 : : {
171 : 0 : GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(*it);
172 : 0 : if( (GdkNativeWindow)pFrame->GetSystemData()->aWindow == pEvent->xany.window ||
173 : 0 : ( pFrame->getForeignParent() && pFrame->getForeignParentWindow() == pEvent->xany.window ) ||
174 : 0 : ( pFrame->getForeignTopLevel() && pFrame->getForeignTopLevelWindow() == pEvent->xany.window )
175 : : )
176 : : {
177 : 0 : if( ! pFrame->Dispatch( pEvent ) )
178 : 0 : aFilterReturn = GDK_FILTER_REMOVE;
179 : 0 : break;
180 : : }
181 : : }
182 : 0 : X11SalObject::Dispatch( pEvent );
183 : : }
184 : :
185 : 0 : return aFilterReturn;
186 : : #else
187 : : (void) sys_event;
188 : : #warning FIXME: implement filterGdkEvent ...
189 : : return GDK_FILTER_CONTINUE;
190 : : #endif
191 : : }
192 : :
193 : 0 : void GtkSalDisplay::screenSizeChanged( GdkScreen* pScreen )
194 : : {
195 : 0 : m_pSys->countScreenMonitors();
196 : 0 : if (pScreen)
197 : 0 : emitDisplayChanged();
198 : 0 : }
199 : :
200 : 0 : void GtkSalDisplay::monitorsChanged( GdkScreen* pScreen )
201 : : {
202 : 0 : m_pSys->countScreenMonitors();
203 : 0 : if (pScreen)
204 : 0 : emitDisplayChanged();
205 : 0 : }
206 : :
207 : : #if !GTK_CHECK_VERSION(3,0,0)
208 : : SalDisplay::ScreenData *
209 : 0 : GtkSalDisplay::initScreen( SalX11Screen nXScreen ) const
210 : : {
211 : : // choose visual for screen
212 : : ScreenData *pSD;
213 : 0 : if (!(pSD = SalDisplay::initScreen( nXScreen )))
214 : 0 : return NULL;
215 : :
216 : : // now set a gdk default colormap matching the chosen visual to the screen
217 : 0 : GdkScreen* pScreen = gdk_display_get_screen( m_pGdkDisplay, nXScreen.getXScreen() );
218 : : // should really use this:
219 : : // GdkVisual* pVis = gdk_x11_screen_lookup_visual_get( screen, pSD->m_aVisual.visualid );
220 : : // and not this:
221 : 0 : GdkVisual* pVis = gdkx_visual_get( pSD->m_aVisual.visualid );
222 : 0 : if( pVis )
223 : : {
224 : 0 : GdkColormap* pDefCol = gdk_screen_get_default_colormap( pScreen );
225 : 0 : GdkVisual* pDefVis = gdk_colormap_get_visual( pDefCol );
226 : 0 : if( pDefVis != pVis )
227 : : {
228 : 0 : pDefCol = gdk_x11_colormap_foreign_new( pVis, pSD->m_aColormap.GetXColormap() );
229 : 0 : gdk_screen_set_default_colormap( pScreen, pDefCol );
230 : : #if OSL_DEBUG_LEVEL > 1
231 : : fprintf( stderr, "set new gdk color map for screen %d\n", nXScreen.getXScreen() );
232 : : #endif
233 : : }
234 : : }
235 : : #if OSL_DEBUG_LEVEL > 1
236 : : else
237 : : fprintf( stderr, "not GdkVisual for visual id %d\n", (int)pSD->m_aVisual.visualid );
238 : : #endif
239 : 0 : return pSD;
240 : : }
241 : :
242 : 0 : long GtkSalDisplay::Dispatch( XEvent* pEvent )
243 : : {
244 : 0 : if( GetDisplay() == pEvent->xany.display )
245 : : {
246 : : // let's see if one of our frames wants to swallow these events
247 : : // get the child frame
248 : 0 : for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
249 : 0 : it != m_aFrames.end(); ++it )
250 : : {
251 : 0 : if( (GdkNativeWindow)(*it)->GetSystemData()->aWindow == pEvent->xany.window )
252 : 0 : return static_cast<GtkSalFrame*>(*it)->Dispatch( pEvent );
253 : : }
254 : : }
255 : :
256 : 0 : return GDK_FILTER_CONTINUE;
257 : : }
258 : : #endif
259 : :
260 : : #if GTK_CHECK_VERSION(3,0,0)
261 : : namespace
262 : : {
263 : : //cairo annoyingly won't take raw xbm data unless it fits
264 : : //the required cairo stride
265 : : unsigned char* ensurePaddedForCairo(const unsigned char *pXBM,
266 : : int nWidth, int nHeight, int nStride)
267 : : {
268 : : unsigned char *pPaddedXBM = const_cast<unsigned char*>(pXBM);
269 : :
270 : : int bytes_per_row = (nWidth + 7) / 8;
271 : :
272 : : if (nStride != bytes_per_row)
273 : : {
274 : : pPaddedXBM = new unsigned char[nStride * nHeight];
275 : : for (int row = 0; row < nHeight; ++row)
276 : : {
277 : : memcpy(pPaddedXBM + (nStride * row),
278 : : pXBM + (bytes_per_row * row), bytes_per_row);
279 : : memset(pPaddedXBM + (nStride * row) + bytes_per_row,
280 : : 0, nStride - bytes_per_row);
281 : : }
282 : : }
283 : :
284 : : return pPaddedXBM;
285 : : }
286 : : }
287 : : #endif
288 : :
289 : 0 : GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
290 : : const unsigned char *pMask,
291 : : int nWidth, int nHeight,
292 : : int nXHot, int nYHot )
293 : : {
294 : : #if GTK_CHECK_VERSION(3,0,0)
295 : : int cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, nWidth);
296 : :
297 : : unsigned char *pPaddedXBM = ensurePaddedForCairo(pBitmap, nWidth, nHeight, cairo_stride);
298 : : cairo_surface_t *s = cairo_image_surface_create_for_data(
299 : : pPaddedXBM,
300 : : CAIRO_FORMAT_A1, nWidth, nHeight,
301 : : cairo_stride);
302 : :
303 : : cairo_t *cr = cairo_create(s);
304 : : unsigned char *pPaddedMaskXBM = ensurePaddedForCairo(pMask, nWidth, nHeight, cairo_stride);
305 : : cairo_surface_t *mask = cairo_image_surface_create_for_data(
306 : : pPaddedMaskXBM,
307 : : CAIRO_FORMAT_A1, nWidth, nHeight,
308 : : cairo_stride);
309 : : cairo_mask_surface(cr, mask, 0, 0);
310 : : cairo_destroy(cr);
311 : : cairo_surface_destroy(mask);
312 : : if (pPaddedMaskXBM != pMask)
313 : : delete [] pPaddedMaskXBM;
314 : :
315 : : GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, nWidth, nHeight);
316 : : cairo_surface_destroy(s);
317 : : if (pPaddedXBM != pBitmap)
318 : : delete [] pPaddedXBM;
319 : :
320 : : GdkCursor *cursor = gdk_cursor_new_from_pixbuf(m_pGdkDisplay, pixbuf, nXHot, nYHot);
321 : : g_object_unref(pixbuf);
322 : :
323 : : return cursor;
324 : : #else
325 : 0 : GdkScreen *pScreen = gdk_display_get_default_screen( m_pGdkDisplay );
326 : 0 : GdkDrawable *pDrawable = GDK_DRAWABLE( gdk_screen_get_root_window (pScreen) );
327 : : GdkBitmap *pBitmapPix = gdk_bitmap_create_from_data
328 : 0 : ( pDrawable, reinterpret_cast<const char*>(pBitmap), nWidth, nHeight );
329 : : GdkBitmap *pMaskPix = gdk_bitmap_create_from_data
330 : 0 : ( pDrawable, reinterpret_cast<const char*>(pMask), nWidth, nHeight );
331 : 0 : GdkColormap *pColormap = gdk_drawable_get_colormap( pDrawable );
332 : :
333 : 0 : GdkColor aWhite = { 0, 0xffff, 0xffff, 0xffff };
334 : 0 : GdkColor aBlack = { 0, 0, 0, 0 };
335 : :
336 : 0 : gdk_colormap_alloc_color( pColormap, &aBlack, FALSE, TRUE);
337 : 0 : gdk_colormap_alloc_color( pColormap, &aWhite, FALSE, TRUE);
338 : :
339 : : return gdk_cursor_new_from_pixmap
340 : : ( pBitmapPix, pMaskPix,
341 : 0 : &aBlack, &aWhite, nXHot, nYHot);
342 : : #endif
343 : : }
344 : :
345 : : #define MAKE_CURSOR( vcl_name, name ) \
346 : : case vcl_name: \
347 : : pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
348 : : name##curs_width, name##curs_height, \
349 : : name##curs_x_hot, name##curs_y_hot ); \
350 : : break
351 : : #define MAP_BUILTIN( vcl_name, gdk_name ) \
352 : : case vcl_name: \
353 : : pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, gdk_name ); \
354 : : break
355 : :
356 : 0 : GdkCursor *GtkSalDisplay::getCursor( PointerStyle ePointerStyle )
357 : : {
358 : 0 : if( ePointerStyle >= POINTER_COUNT )
359 : 0 : return NULL;
360 : :
361 : 0 : if ( !m_aCursors[ ePointerStyle ] )
362 : : {
363 : 0 : GdkCursor *pCursor = NULL;
364 : :
365 : 0 : switch( ePointerStyle )
366 : : {
367 : 0 : MAP_BUILTIN( POINTER_ARROW, GDK_LEFT_PTR );
368 : 0 : MAP_BUILTIN( POINTER_TEXT, GDK_XTERM );
369 : 0 : MAP_BUILTIN( POINTER_HELP, GDK_QUESTION_ARROW );
370 : 0 : MAP_BUILTIN( POINTER_CROSS, GDK_CROSSHAIR );
371 : 0 : MAP_BUILTIN( POINTER_WAIT, GDK_WATCH );
372 : :
373 : 0 : MAP_BUILTIN( POINTER_NSIZE, GDK_SB_V_DOUBLE_ARROW );
374 : 0 : MAP_BUILTIN( POINTER_SSIZE, GDK_SB_V_DOUBLE_ARROW );
375 : 0 : MAP_BUILTIN( POINTER_WSIZE, GDK_SB_H_DOUBLE_ARROW );
376 : 0 : MAP_BUILTIN( POINTER_ESIZE, GDK_SB_H_DOUBLE_ARROW );
377 : :
378 : 0 : MAP_BUILTIN( POINTER_NWSIZE, GDK_TOP_LEFT_CORNER );
379 : 0 : MAP_BUILTIN( POINTER_NESIZE, GDK_TOP_RIGHT_CORNER );
380 : 0 : MAP_BUILTIN( POINTER_SWSIZE, GDK_BOTTOM_LEFT_CORNER );
381 : 0 : MAP_BUILTIN( POINTER_SESIZE, GDK_BOTTOM_RIGHT_CORNER );
382 : :
383 : 0 : MAP_BUILTIN( POINTER_WINDOW_NSIZE, GDK_TOP_SIDE );
384 : 0 : MAP_BUILTIN( POINTER_WINDOW_SSIZE, GDK_BOTTOM_SIDE );
385 : 0 : MAP_BUILTIN( POINTER_WINDOW_WSIZE, GDK_LEFT_SIDE );
386 : 0 : MAP_BUILTIN( POINTER_WINDOW_ESIZE, GDK_RIGHT_SIDE );
387 : :
388 : 0 : MAP_BUILTIN( POINTER_WINDOW_NWSIZE, GDK_TOP_LEFT_CORNER );
389 : 0 : MAP_BUILTIN( POINTER_WINDOW_NESIZE, GDK_TOP_RIGHT_CORNER );
390 : 0 : MAP_BUILTIN( POINTER_WINDOW_SWSIZE, GDK_BOTTOM_LEFT_CORNER );
391 : 0 : MAP_BUILTIN( POINTER_WINDOW_SESIZE, GDK_BOTTOM_RIGHT_CORNER );
392 : :
393 : 0 : MAP_BUILTIN( POINTER_HSIZEBAR, GDK_SB_H_DOUBLE_ARROW );
394 : 0 : MAP_BUILTIN( POINTER_VSIZEBAR, GDK_SB_V_DOUBLE_ARROW );
395 : :
396 : 0 : MAP_BUILTIN( POINTER_REFHAND, GDK_HAND2 );
397 : 0 : MAP_BUILTIN( POINTER_HAND, GDK_HAND2 );
398 : 0 : MAP_BUILTIN( POINTER_PEN, GDK_PENCIL );
399 : :
400 : 0 : MAP_BUILTIN( POINTER_HSPLIT, GDK_SB_H_DOUBLE_ARROW );
401 : 0 : MAP_BUILTIN( POINTER_VSPLIT, GDK_SB_V_DOUBLE_ARROW );
402 : :
403 : 0 : MAP_BUILTIN( POINTER_MOVE, GDK_FLEUR );
404 : :
405 : 0 : MAKE_CURSOR( POINTER_NULL, null );
406 : 0 : MAKE_CURSOR( POINTER_MAGNIFY, magnify_ );
407 : 0 : MAKE_CURSOR( POINTER_FILL, fill_ );
408 : 0 : MAKE_CURSOR( POINTER_MOVEDATA, movedata_ );
409 : 0 : MAKE_CURSOR( POINTER_COPYDATA, copydata_ );
410 : 0 : MAKE_CURSOR( POINTER_MOVEFILE, movefile_ );
411 : 0 : MAKE_CURSOR( POINTER_COPYFILE, copyfile_ );
412 : 0 : MAKE_CURSOR( POINTER_MOVEFILES, movefiles_ );
413 : 0 : MAKE_CURSOR( POINTER_COPYFILES, copyfiles_ );
414 : 0 : MAKE_CURSOR( POINTER_NOTALLOWED, nodrop_ );
415 : 0 : MAKE_CURSOR( POINTER_ROTATE, rotate_ );
416 : 0 : MAKE_CURSOR( POINTER_HSHEAR, hshear_ );
417 : 0 : MAKE_CURSOR( POINTER_VSHEAR, vshear_ );
418 : 0 : MAKE_CURSOR( POINTER_DRAW_LINE, drawline_ );
419 : 0 : MAKE_CURSOR( POINTER_DRAW_RECT, drawrect_ );
420 : 0 : MAKE_CURSOR( POINTER_DRAW_POLYGON, drawpolygon_ );
421 : 0 : MAKE_CURSOR( POINTER_DRAW_BEZIER, drawbezier_ );
422 : 0 : MAKE_CURSOR( POINTER_DRAW_ARC, drawarc_ );
423 : 0 : MAKE_CURSOR( POINTER_DRAW_PIE, drawpie_ );
424 : 0 : MAKE_CURSOR( POINTER_DRAW_CIRCLECUT, drawcirclecut_ );
425 : 0 : MAKE_CURSOR( POINTER_DRAW_ELLIPSE, drawellipse_ );
426 : 0 : MAKE_CURSOR( POINTER_DRAW_CONNECT, drawconnect_ );
427 : 0 : MAKE_CURSOR( POINTER_DRAW_TEXT, drawtext_ );
428 : 0 : MAKE_CURSOR( POINTER_MIRROR, mirror_ );
429 : 0 : MAKE_CURSOR( POINTER_CROOK, crook_ );
430 : 0 : MAKE_CURSOR( POINTER_CROP, crop_ );
431 : 0 : MAKE_CURSOR( POINTER_MOVEPOINT, movepoint_ );
432 : 0 : MAKE_CURSOR( POINTER_MOVEBEZIERWEIGHT, movebezierweight_ );
433 : 0 : MAKE_CURSOR( POINTER_DRAW_FREEHAND, drawfreehand_ );
434 : 0 : MAKE_CURSOR( POINTER_DRAW_CAPTION, drawcaption_ );
435 : 0 : MAKE_CURSOR( POINTER_LINKDATA, linkdata_ );
436 : 0 : MAKE_CURSOR( POINTER_MOVEDATALINK, movedlnk_ );
437 : 0 : MAKE_CURSOR( POINTER_COPYDATALINK, copydlnk_ );
438 : 0 : MAKE_CURSOR( POINTER_LINKFILE, linkfile_ );
439 : 0 : MAKE_CURSOR( POINTER_MOVEFILELINK, moveflnk_ );
440 : 0 : MAKE_CURSOR( POINTER_COPYFILELINK, copyflnk_ );
441 : 0 : MAKE_CURSOR( POINTER_CHART, chart_ );
442 : 0 : MAKE_CURSOR( POINTER_DETECTIVE, detective_ );
443 : 0 : MAKE_CURSOR( POINTER_PIVOT_COL, pivotcol_ );
444 : 0 : MAKE_CURSOR( POINTER_PIVOT_ROW, pivotrow_ );
445 : 0 : MAKE_CURSOR( POINTER_PIVOT_FIELD, pivotfld_ );
446 : 0 : MAKE_CURSOR( POINTER_PIVOT_DELETE, pivotdel_ );
447 : 0 : MAKE_CURSOR( POINTER_CHAIN, chain_ );
448 : 0 : MAKE_CURSOR( POINTER_CHAIN_NOTALLOWED, chainnot_ );
449 : 0 : MAKE_CURSOR( POINTER_TIMEEVENT_MOVE, timemove_ );
450 : 0 : MAKE_CURSOR( POINTER_TIMEEVENT_SIZE, timesize_ );
451 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_N, asn_ );
452 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_S, ass_ );
453 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_W, asw_ );
454 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_E, ase_ );
455 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_NW, asnw_ );
456 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_NE, asne_ );
457 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_SW, assw_ );
458 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_SE, asse_ );
459 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_NS, asns_ );
460 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_WE, aswe_ );
461 : 0 : MAKE_CURSOR( POINTER_AUTOSCROLL_NSWE, asnswe_ );
462 : 0 : MAKE_CURSOR( POINTER_AIRBRUSH, airbrush_ );
463 : 0 : MAKE_CURSOR( POINTER_TEXT_VERTICAL, vertcurs_ );
464 : :
465 : : // #i32329#
466 : 0 : MAKE_CURSOR( POINTER_TAB_SELECT_S, tblsels_ );
467 : 0 : MAKE_CURSOR( POINTER_TAB_SELECT_E, tblsele_ );
468 : 0 : MAKE_CURSOR( POINTER_TAB_SELECT_SE, tblselse_ );
469 : 0 : MAKE_CURSOR( POINTER_TAB_SELECT_W, tblselw_ );
470 : 0 : MAKE_CURSOR( POINTER_TAB_SELECT_SW, tblselsw_ );
471 : :
472 : : // #i20119#
473 : 0 : MAKE_CURSOR( POINTER_PAINTBRUSH, paintbrush_ );
474 : :
475 : : default:
476 : 0 : fprintf( stderr, "pointer %d not implemented", ePointerStyle );
477 : 0 : break;
478 : : }
479 : 0 : if( !pCursor )
480 : 0 : pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, GDK_LEFT_PTR );
481 : :
482 : 0 : m_aCursors[ ePointerStyle ] = pCursor;
483 : : }
484 : :
485 : 0 : return m_aCursors[ ePointerStyle ];
486 : : }
487 : :
488 : 0 : int GtkSalDisplay::CaptureMouse( SalFrame* pSFrame )
489 : : {
490 : 0 : GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(pSFrame);
491 : :
492 : 0 : if( !pFrame )
493 : : {
494 : 0 : if( m_pCapture )
495 : 0 : static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
496 : 0 : m_pCapture = NULL;
497 : 0 : return 0;
498 : : }
499 : :
500 : 0 : if( m_pCapture )
501 : : {
502 : 0 : if( pFrame == m_pCapture )
503 : 0 : return 1;
504 : 0 : static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
505 : : }
506 : :
507 : 0 : m_pCapture = pFrame;
508 : 0 : static_cast<GtkSalFrame*>(pFrame)->grabPointer( TRUE );
509 : 0 : return 1;
510 : : }
511 : :
512 : :
513 : : /**********************************************************************
514 : : * class GtkData *
515 : : **********************************************************************/
516 : :
517 : 0 : GtkData::GtkData( SalInstance *pInstance )
518 : : #if GTK_CHECK_VERSION(3,0,0)
519 : : : SalGenericData( SAL_DATA_GTK3, pInstance )
520 : : #else
521 : 0 : : SalGenericData( SAL_DATA_GTK, pInstance )
522 : : #endif
523 : : {
524 : 0 : m_pUserEvent = NULL;
525 : 0 : m_aDispatchMutex = osl_createMutex();
526 : 0 : m_aDispatchCondition = osl_createCondition();
527 : 0 : }
528 : :
529 : 0 : GtkData::~GtkData()
530 : : {
531 : 0 : Yield( true, true );
532 : 0 : g_warning ("TESTME: We used to have a stop-timer here, but the central code should do this");
533 : :
534 : : // sanity check: at this point nobody should be yielding, but wake them
535 : : // up anyway before the condition they're waiting on gets destroyed.
536 : 0 : osl_setCondition( m_aDispatchCondition );
537 : :
538 : 0 : osl_acquireMutex( m_aDispatchMutex );
539 : 0 : if (m_pUserEvent)
540 : : {
541 : 0 : g_source_destroy (m_pUserEvent);
542 : 0 : g_source_unref (m_pUserEvent);
543 : 0 : m_pUserEvent = NULL;
544 : : }
545 : 0 : osl_destroyCondition( m_aDispatchCondition );
546 : 0 : osl_releaseMutex( m_aDispatchMutex );
547 : 0 : osl_destroyMutex( m_aDispatchMutex );
548 : 0 : }
549 : :
550 : 0 : void GtkData::Dispose()
551 : : {
552 : 0 : deInitNWF();
553 : 0 : }
554 : :
555 : 0 : void GtkData::Yield( bool bWait, bool bHandleAllCurrentEvents )
556 : : {
557 : : /* #i33212# only enter g_main_context_iteration in one thread at any one
558 : : * time, else one of them potentially will never end as long as there is
559 : : * another thread in in there. Having only one yieldin thread actually dispatch
560 : : * fits the vcl event model (see e.g. the generic plugin).
561 : : */
562 : 0 : bool bDispatchThread = false;
563 : 0 : bool bWasEvent = false;
564 : : {
565 : : // release YieldMutex (and re-acquire at block end)
566 : 0 : SalYieldMutexReleaser aReleaser;
567 : 0 : if( osl_tryToAcquireMutex( m_aDispatchMutex ) )
568 : 0 : bDispatchThread = true;
569 : 0 : else if( ! bWait )
570 : 0 : return; // someone else is waiting already, return
571 : :
572 : 0 : if( bDispatchThread )
573 : : {
574 : 0 : int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
575 : 0 : gboolean wasOneEvent = TRUE;
576 : 0 : while( nMaxEvents-- && wasOneEvent )
577 : : {
578 : 0 : wasOneEvent = g_main_context_iteration( NULL, FALSE );
579 : 0 : if( wasOneEvent )
580 : 0 : bWasEvent = true;
581 : : }
582 : 0 : if( bWait && ! bWasEvent )
583 : 0 : bWasEvent = g_main_context_iteration( NULL, TRUE ) != 0;
584 : : }
585 : 0 : else if( bWait )
586 : : {
587 : : /* #i41693# in case the dispatch thread hangs in join
588 : : * for this thread the condition will never be set
589 : : * workaround: timeout of 1 second a emergency exit
590 : : */
591 : : // we are the dispatch thread
592 : 0 : osl_resetCondition( m_aDispatchCondition );
593 : 0 : TimeValue aValue = { 1, 0 };
594 : 0 : osl_waitCondition( m_aDispatchCondition, &aValue );
595 : 0 : }
596 : : }
597 : :
598 : 0 : if( bDispatchThread )
599 : : {
600 : 0 : osl_releaseMutex( m_aDispatchMutex );
601 : 0 : if( bWasEvent )
602 : 0 : osl_setCondition( m_aDispatchCondition ); // trigger non dispatch thread yields
603 : : }
604 : : }
605 : :
606 : 0 : void GtkData::Init()
607 : : {
608 : : int i;
609 : : #if OSL_DEBUG_LEVEL > 1
610 : : fprintf( stderr, "GtkMainloop::Init()\n" );
611 : : #endif
612 : 0 : XrmInitialize();
613 : :
614 : : #if !GTK_CHECK_VERSION(3,0,0)
615 : 0 : gtk_set_locale();
616 : : #endif
617 : :
618 : : /*
619 : : * open connection to X11 Display
620 : : * try in this order:
621 : : * o -display command line parameter,
622 : : * o $DISPLAY environment variable
623 : : * o default display
624 : : */
625 : :
626 : 0 : GdkDisplay *pGdkDisp = NULL;
627 : :
628 : : // is there a -display command line parameter?
629 : 0 : rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
630 : 0 : int nParams = osl_getCommandArgCount();
631 : 0 : rtl::OString aDisplay;
632 : 0 : rtl::OUString aParam, aBin;
633 : 0 : char** pCmdLineAry = new char*[ nParams+1 ];
634 : 0 : osl_getExecutableFile( &aParam.pData );
635 : 0 : osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
636 : 0 : pCmdLineAry[0] = g_strdup( OUStringToOString( aBin, aEnc ).getStr() );
637 : 0 : for (i=0; i<nParams; i++)
638 : : {
639 : 0 : osl_getCommandArg(i, &aParam.pData );
640 : 0 : OString aBParam( OUStringToOString( aParam, aEnc ) );
641 : :
642 : 0 : if( aParam == "-display" || aParam == "--display" )
643 : : {
644 : 0 : pCmdLineAry[i+1] = g_strdup( "--display" );
645 : 0 : osl_getCommandArg(i+1, &aParam.pData );
646 : 0 : aDisplay = rtl::OUStringToOString( aParam, aEnc );
647 : : }
648 : : else
649 : 0 : pCmdLineAry[i+1] = g_strdup( aBParam.getStr() );
650 : 0 : }
651 : : // add executable
652 : 0 : nParams++;
653 : :
654 : 0 : g_set_application_name(SalGenericSystem::getFrameClassName());
655 : :
656 : : // Set consistant name of the root accessible
657 : 0 : rtl::OUString aAppName = Application::GetAppName();
658 : 0 : if( !aAppName.isEmpty() )
659 : : {
660 : 0 : rtl::OString aPrgName = rtl::OUStringToOString(aAppName, aEnc);
661 : 0 : g_set_prgname(aPrgName.getStr());
662 : : }
663 : :
664 : : // init gtk/gdk
665 : 0 : gtk_init_check( &nParams, &pCmdLineAry );
666 : 0 : gdk_error_trap_push();
667 : :
668 : 0 : for (i = 0; i < nParams; i++ )
669 : 0 : g_free( pCmdLineAry[i] );
670 : 0 : delete [] pCmdLineAry;
671 : :
672 : : #if OSL_DEBUG_LEVEL > 1
673 : : if (g_getenv ("SAL_DEBUG_UPDATES"))
674 : : gdk_window_set_debug_updates (TRUE);
675 : : #endif
676 : :
677 : 0 : pGdkDisp = gdk_display_get_default();
678 : 0 : if ( !pGdkDisp )
679 : : {
680 : 0 : rtl::OUString aProgramFileURL;
681 : 0 : osl_getExecutableFile( &aProgramFileURL.pData );
682 : 0 : rtl::OUString aProgramSystemPath;
683 : 0 : osl_getSystemPathFromFileURL (aProgramFileURL.pData, &aProgramSystemPath.pData);
684 : : rtl::OString aProgramName = rtl::OUStringToOString(
685 : : aProgramSystemPath,
686 : 0 : osl_getThreadTextEncoding() );
687 : : fprintf( stderr, "%s X11 error: Can't open display: %s\n",
688 : 0 : aProgramName.getStr(), aDisplay.getStr());
689 : 0 : fprintf( stderr, " Set DISPLAY environment variable, use -display option\n");
690 : 0 : fprintf( stderr, " or check permissions of your X-Server\n");
691 : 0 : fprintf( stderr, " (See \"man X\" resp. \"man xhost\" for details)\n");
692 : 0 : fflush( stderr );
693 : 0 : exit(0);
694 : : }
695 : :
696 : : /*
697 : : * if a -display switch was used, we need
698 : : * to set the environment accoringly since
699 : : * the clipboard build another connection
700 : : * to the xserver using $DISPLAY
701 : : */
702 : 0 : rtl::OUString envVar(RTL_CONSTASCII_USTRINGPARAM("DISPLAY"));
703 : 0 : const gchar *name = gdk_display_get_name( pGdkDisp );
704 : 0 : rtl::OUString envValue(name, strlen(name), aEnc);
705 : 0 : osl_setEnvironment(envVar.pData, envValue.pData);
706 : :
707 : 0 : GtkSalDisplay *pDisplay = new GtkSalDisplay( pGdkDisp );
708 : 0 : SetDisplay( pDisplay );
709 : :
710 : : #if !GTK_CHECK_VERSION(3,0,0)
711 : 0 : Display *pDisp = gdk_x11_display_get_xdisplay( pGdkDisp );
712 : :
713 : 0 : gdk_error_trap_push();
714 : 0 : SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
715 : 0 : bool bErrorOccured = gdk_error_trap_pop() != 0;
716 : 0 : gdk_error_trap_push();
717 : 0 : pKbdExtension->UseExtension( bErrorOccured );
718 : 0 : gdk_error_trap_pop();
719 : 0 : GetGtkDisplay()->SetKbdExtension( pKbdExtension );
720 : : #else
721 : : # warning unwind keyboard extension bits
722 : : #endif
723 : :
724 : : // add signal handler to notify screen size changes
725 : 0 : int nScreens = gdk_display_get_n_screens( pGdkDisp );
726 : 0 : for( int n = 0; n < nScreens; n++ )
727 : : {
728 : 0 : GdkScreen *pScreen = gdk_display_get_screen( pGdkDisp, n );
729 : 0 : if( pScreen )
730 : : {
731 : 0 : pDisplay->screenSizeChanged( pScreen );
732 : 0 : pDisplay->monitorsChanged( pScreen );
733 : 0 : g_signal_connect( G_OBJECT(pScreen), "size-changed",
734 : 0 : G_CALLBACK(signalScreenSizeChanged), pDisplay );
735 : 0 : if( ! gtk_check_version( 2, 14, 0 ) ) // monitors-changed came in with 2.14, avoid an assertion
736 : 0 : g_signal_connect( G_OBJECT(pScreen), "monitors-changed",
737 : 0 : G_CALLBACK(signalMonitorsChanged), GetGtkDisplay() );
738 : : }
739 : 0 : }
740 : 0 : }
741 : :
742 : 0 : void GtkData::ErrorTrapPush()
743 : : {
744 : 0 : gdk_error_trap_push ();
745 : 0 : }
746 : :
747 : 0 : bool GtkData::ErrorTrapPop( bool bIgnoreError )
748 : : {
749 : : #if GTK_CHECK_VERSION(3,0,0)
750 : : if( bIgnoreError )
751 : : {
752 : : gdk_error_trap_pop_ignored (); // faster
753 : : return false;
754 : : }
755 : : #else
756 : : (void) bIgnoreError;
757 : : #endif
758 : 0 : return gdk_error_trap_pop () != 0;
759 : : }
760 : :
761 : : extern "C" {
762 : :
763 : : struct SalGtkTimeoutSource {
764 : : GSource aParent;
765 : : GTimeVal aFireTime;
766 : : GtkSalTimer *pInstance;
767 : : };
768 : :
769 : 0 : static void sal_gtk_timeout_defer( SalGtkTimeoutSource *pTSource )
770 : : {
771 : 0 : g_get_current_time( &pTSource->aFireTime );
772 : 0 : g_time_val_add( &pTSource->aFireTime, pTSource->pInstance->m_nTimeoutMS * 1000 );
773 : 0 : }
774 : :
775 : 0 : static gboolean sal_gtk_timeout_expired( SalGtkTimeoutSource *pTSource,
776 : : gint *nTimeoutMS, GTimeVal *pTimeNow )
777 : : {
778 : 0 : glong nDeltaSec = pTSource->aFireTime.tv_sec - pTimeNow->tv_sec;
779 : 0 : glong nDeltaUSec = pTSource->aFireTime.tv_usec - pTimeNow->tv_usec;
780 : 0 : if( nDeltaSec < 0 || ( nDeltaSec == 0 && nDeltaUSec < 0) )
781 : : {
782 : 0 : *nTimeoutMS = 0;
783 : 0 : return TRUE;
784 : : }
785 : 0 : if( nDeltaUSec < 0 )
786 : : {
787 : 0 : nDeltaUSec += 1000000;
788 : 0 : nDeltaSec -= 1;
789 : : }
790 : : // if the clock changes backwards we need to cope ...
791 : 0 : if( (unsigned long) nDeltaSec > 1 + ( pTSource->pInstance->m_nTimeoutMS / 1000 ) )
792 : : {
793 : 0 : sal_gtk_timeout_defer( pTSource );
794 : 0 : return TRUE;
795 : : }
796 : :
797 : 0 : *nTimeoutMS = MIN( G_MAXINT, ( nDeltaSec * 1000 + (nDeltaUSec + 999) / 1000 ) );
798 : :
799 : 0 : return *nTimeoutMS == 0;
800 : : }
801 : :
802 : 0 : static gboolean sal_gtk_timeout_prepare( GSource *pSource, gint *nTimeoutMS )
803 : : {
804 : 0 : SalGtkTimeoutSource *pTSource = (SalGtkTimeoutSource *)pSource;
805 : :
806 : : GTimeVal aTimeNow;
807 : 0 : g_get_current_time( &aTimeNow );
808 : :
809 : 0 : return sal_gtk_timeout_expired( pTSource, nTimeoutMS, &aTimeNow );
810 : : }
811 : :
812 : 0 : static gboolean sal_gtk_timeout_check( GSource *pSource )
813 : : {
814 : 0 : SalGtkTimeoutSource *pTSource = (SalGtkTimeoutSource *)pSource;
815 : :
816 : : GTimeVal aTimeNow;
817 : 0 : g_get_current_time( &aTimeNow );
818 : :
819 : : return ( pTSource->aFireTime.tv_sec < aTimeNow.tv_sec ||
820 : : ( pTSource->aFireTime.tv_sec == aTimeNow.tv_sec &&
821 : 0 : pTSource->aFireTime.tv_usec < aTimeNow.tv_usec ) );
822 : : }
823 : :
824 : 0 : static gboolean sal_gtk_timeout_dispatch( GSource *pSource, GSourceFunc, gpointer )
825 : : {
826 : 0 : SalGtkTimeoutSource *pTSource = (SalGtkTimeoutSource *)pSource;
827 : :
828 : 0 : if( !pTSource->pInstance )
829 : 0 : return FALSE;
830 : :
831 : 0 : SalData *pSalData = GetSalData();
832 : :
833 : 0 : osl::SolarGuard aGuard( pSalData->m_pInstance->GetYieldMutex() );
834 : :
835 : 0 : sal_gtk_timeout_defer( pTSource );
836 : :
837 : 0 : ImplSVData* pSVData = ImplGetSVData();
838 : 0 : if( pSVData->mpSalTimer )
839 : 0 : pSVData->mpSalTimer->CallCallback();
840 : :
841 : 0 : return TRUE;
842 : : }
843 : :
844 : : static GSourceFuncs sal_gtk_timeout_funcs =
845 : : {
846 : : sal_gtk_timeout_prepare,
847 : : sal_gtk_timeout_check,
848 : : sal_gtk_timeout_dispatch,
849 : : NULL, NULL, NULL
850 : : };
851 : : }
852 : :
853 : : static SalGtkTimeoutSource *
854 : 0 : create_sal_gtk_timeout( GtkSalTimer *pTimer )
855 : : {
856 : 0 : GSource *pSource = g_source_new( &sal_gtk_timeout_funcs, sizeof( SalGtkTimeoutSource ) );
857 : 0 : SalGtkTimeoutSource *pTSource = (SalGtkTimeoutSource *)pSource;
858 : 0 : pTSource->pInstance = pTimer;
859 : :
860 : : // #i36226# timers should be executed with lower priority
861 : : // than XEvents like in generic plugin
862 : 0 : g_source_set_priority( pSource, G_PRIORITY_LOW );
863 : 0 : g_source_set_can_recurse( pSource, TRUE );
864 : : g_source_set_callback( pSource,
865 : : /* unused dummy */ g_idle_remove_by_data,
866 : 0 : NULL, NULL );
867 : 0 : g_source_attach( pSource, g_main_context_default() );
868 : :
869 : 0 : sal_gtk_timeout_defer( pTSource );
870 : :
871 : 0 : return pTSource;
872 : : }
873 : :
874 : 0 : GtkSalTimer::GtkSalTimer()
875 : 0 : : m_pTimeout( NULL )
876 : : {
877 : 0 : }
878 : :
879 : 0 : GtkSalTimer::~GtkSalTimer()
880 : : {
881 : 0 : GtkInstance *pInstance = static_cast<GtkInstance *>(GetSalData()->m_pInstance);
882 : 0 : pInstance->RemoveTimer( this );
883 : 0 : Stop();
884 : 0 : }
885 : :
886 : 0 : bool GtkSalTimer::Expired()
887 : : {
888 : 0 : if( !m_pTimeout )
889 : 0 : return false;
890 : :
891 : 0 : gint nDummy = 0;
892 : : GTimeVal aTimeNow;
893 : 0 : g_get_current_time( &aTimeNow );
894 : 0 : return !!sal_gtk_timeout_expired( m_pTimeout, &nDummy, &aTimeNow);
895 : : }
896 : :
897 : 0 : void GtkSalTimer::Start( sal_uLong nMS )
898 : : {
899 : 0 : m_nTimeoutMS = nMS; // for restarting
900 : 0 : Stop(); // FIXME: ideally re-use an existing m_pTimeout
901 : 0 : m_pTimeout = create_sal_gtk_timeout( this );
902 : 0 : }
903 : :
904 : 0 : void GtkSalTimer::Stop()
905 : : {
906 : 0 : if( m_pTimeout )
907 : : {
908 : 0 : g_source_destroy( (GSource *)m_pTimeout );
909 : 0 : g_source_unref( (GSource *)m_pTimeout );
910 : 0 : m_pTimeout = NULL;
911 : : }
912 : 0 : }
913 : :
914 : 0 : gboolean GtkData::userEventFn( gpointer data )
915 : : {
916 : 0 : gboolean bContinue = FALSE;
917 : 0 : GtkData *pThis = (GtkData *) data;
918 : 0 : SalGenericData *pData = GetGenericData();
919 : 0 : osl::SolarGuard aGuard( pData->m_pInstance->GetYieldMutex() );
920 : 0 : const SalGenericDisplay *pDisplay = pData->GetDisplay();
921 : 0 : if (pDisplay)
922 : : {
923 : : OSL_ASSERT(static_cast<const SalGenericDisplay *>(pThis->GetGtkDisplay()) == pDisplay);
924 : 0 : pThis->GetGtkDisplay()->EventGuardAcquire();
925 : :
926 : 0 : if( !pThis->GetGtkDisplay()->HasUserEvents() )
927 : : {
928 : 0 : if( pThis->m_pUserEvent )
929 : : {
930 : 0 : g_source_unref (pThis->m_pUserEvent);
931 : 0 : pThis->m_pUserEvent = NULL;
932 : : }
933 : 0 : bContinue = FALSE;
934 : : }
935 : : else
936 : 0 : bContinue = TRUE;
937 : :
938 : 0 : pThis->GetGtkDisplay()->EventGuardRelease();
939 : :
940 : 0 : pThis->GetGtkDisplay()->DispatchInternalEvent();
941 : : }
942 : :
943 : 0 : return bContinue;
944 : : }
945 : :
946 : : extern "C" {
947 : 0 : static gboolean call_userEventFn( void *data )
948 : : {
949 : 0 : SolarMutexGuard aGuard;
950 : 0 : return GtkData::userEventFn( data );
951 : : }
952 : : }
953 : :
954 : : // hEventGuard_ held during this invocation
955 : 0 : void GtkData::PostUserEvent()
956 : : {
957 : 0 : if (m_pUserEvent)
958 : 0 : g_main_context_wakeup (NULL); // really needed ?
959 : : else // nothing pending anyway
960 : : {
961 : 0 : m_pUserEvent = g_idle_source_new();
962 : 0 : g_source_set_priority (m_pUserEvent, G_PRIORITY_HIGH);
963 : 0 : g_source_set_can_recurse (m_pUserEvent, TRUE);
964 : : g_source_set_callback (m_pUserEvent, call_userEventFn,
965 : 0 : (gpointer) this, NULL);
966 : 0 : g_source_attach (m_pUserEvent, g_main_context_default ());
967 : : }
968 : 0 : }
969 : :
970 : 0 : void GtkSalDisplay::PostUserEvent()
971 : : {
972 : 0 : GetGtkSalData()->PostUserEvent();
973 : 0 : }
974 : :
975 : 0 : void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
976 : : {
977 : 0 : if( m_pCapture == pFrame )
978 : : {
979 : 0 : static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
980 : 0 : m_pCapture = NULL;
981 : : }
982 : 0 : SalGenericDisplay::deregisterFrame( pFrame );
983 : 0 : }
984 : :
985 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|