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 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 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 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" { 103cdf0e10cSrcweir GdkFilterReturn call_filterGdkEvent( GdkXEvent* sys_event, 104cdf0e10cSrcweir GdkEvent* event, 105cdf0e10cSrcweir gpointer data ) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir return GtkSalDisplay::filterGdkEvent( sys_event, event, data ); 108cdf0e10cSrcweir } 109cdf0e10cSrcweir 110cdf0e10cSrcweir void signalKeysChanged( GdkKeymap*, gpointer data ) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir GtkSalDisplay* pDisp = (GtkSalDisplay*)data; 113cdf0e10cSrcweir pDisp->GetKeyboardName(TRUE); 114cdf0e10cSrcweir } 115cdf0e10cSrcweir 116cdf0e10cSrcweir void signalScreenSizeChanged( GdkScreen* pScreen, gpointer data ) 117cdf0e10cSrcweir { 118cdf0e10cSrcweir GtkSalDisplay* pDisp = (GtkSalDisplay*)data; 119cdf0e10cSrcweir pDisp->screenSizeChanged( pScreen ); 120cdf0e10cSrcweir } 121cdf0e10cSrcweir 122cdf0e10cSrcweir void signalMonitorsChanged( GdkScreen* pScreen, gpointer data ) 123cdf0e10cSrcweir { 124cdf0e10cSrcweir GtkSalDisplay* pDisp = (GtkSalDisplay*)data; 125cdf0e10cSrcweir pDisp->monitorsChanged( pScreen ); 126cdf0e10cSrcweir } 127cdf0e10cSrcweir 128cdf0e10cSrcweir } 129cdf0e10cSrcweir 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 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 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 260cdf0e10cSrcweir 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 281cdf0e10cSrcweir 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 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 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: \ 356*30c1b1efSHerbert 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 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 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 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 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 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); 641cdf0e10cSrcweir g_set_prgname(aPrgName); 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 { 723cdf0e10cSrcweir gboolean call_timeoutFn(gpointer data) 724cdf0e10cSrcweir { 725cdf0e10cSrcweir return GtkXLib::timeoutFn(data); 726cdf0e10cSrcweir } 727cdf0e10cSrcweir } 728cdf0e10cSrcweir 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 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 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 { 788cdf0e10cSrcweir gboolean call_userEventFn( gpointer data ) 789cdf0e10cSrcweir { 790cdf0e10cSrcweir return GtkXLib::userEventFn( data ); 791cdf0e10cSrcweir } 792cdf0e10cSrcweir } 793cdf0e10cSrcweir 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 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 839cdf0e10cSrcweir void GtkXLib::Wakeup() 840cdf0e10cSrcweir { 841cdf0e10cSrcweir g_main_context_wakeup( g_main_context_default () ); 842cdf0e10cSrcweir } 843cdf0e10cSrcweir 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 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 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 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 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 * 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 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 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 1033cdf0e10cSrcweir GtkData::~GtkData() 1034cdf0e10cSrcweir { 1035cdf0e10cSrcweir } 1036cdf0e10cSrcweir 1037cdf0e10cSrcweir void GtkData::Init() 1038cdf0e10cSrcweir { 1039cdf0e10cSrcweir pXLib_ = new GtkXLib(); 1040cdf0e10cSrcweir pXLib_->Init(); 1041cdf0e10cSrcweir } 1042