Kaydet (Commit) 7adec6ba authored tarafından Caolán McNamara's avatar Caolán McNamara

split gtkdata into gtk3 and gtk3 versions

Change-Id: Ic102a5a1193a8bc50b460e5897b1ca488f0d4a65
üst 2ba53aee
......@@ -47,15 +47,6 @@
#include <vcl/svapp.hxx>
#if GTK_CHECK_VERSION(3,0,0)
# ifdef GDK_WINDOWING_X11
# include <gdk/gdkx.h>
# endif
#else
# define GDK_WINDOWING_X11
# define GDK_IS_X11_DISPLAY(foo) (true)
#endif
using namespace vcl_sal;
/***************************************************************
......@@ -72,19 +63,15 @@ GdkFilterReturn call_filterGdkEvent( GdkXEvent* sys_event,
}
GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay ) :
#if !GTK_CHECK_VERSION(3,0,0)
SalDisplay( gdk_x11_display_get_xdisplay( pDisplay ) ),
#endif
m_pSys( GtkSalSystem::GetSingleton() ),
m_pGdkDisplay( pDisplay ),
m_bStartupCompleted( false )
{
for(GdkCursor* & rpCsr : m_aCursors)
rpCsr = nullptr;
#if !GTK_CHECK_VERSION(3,0,0)
m_bUseRandRWrapper = false; // use gdk signal instead
Init ();
#endif
// FIXME: unify this with SalInst's filter too ?
gdk_window_add_filter( nullptr, call_filterGdkEvent, this );
......@@ -92,23 +79,7 @@ GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay ) :
if ( getenv( "SAL_IGNOREXERRORS" ) )
GetGenericData()->ErrorTrapPush(); // and leak the trap
#if GTK_CHECK_VERSION(3,0,0)
m_bX11Display = GDK_IS_X11_DISPLAY( m_pGdkDisplay );
#else
m_bX11Display = true;
#endif
#if GTK_CHECK_VERSION(3,10,0)
#ifdef GDK_WINDOWING_X11
if (m_bX11Display)
{
if (!getenv("GDK_SCALE"))
{
gdk_x11_display_set_window_scale(m_pGdkDisplay, 1);
}
}
#endif
#endif
gtk_widget_set_default_direction(AllSettings::GetLayoutRTL() ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
}
......@@ -120,10 +91,8 @@ GtkSalDisplay::~GtkSalDisplay()
if( !m_bStartupCompleted )
gdk_notify_startup_complete();
#if !GTK_CHECK_VERSION(3,0,0)
doDestruct();
pDisp_ = nullptr;
#endif
for(GdkCursor* & rpCsr : m_aCursors)
if( rpCsr )
......@@ -149,7 +118,6 @@ void signalMonitorsChanged( GdkScreen* pScreen, gpointer data )
GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event,
GdkEvent* )
{
#if !GTK_CHECK_VERSION(3,0,0)
GdkFilterReturn aFilterReturn = GDK_FILTER_CONTINUE;
XEvent *pEvent = static_cast<XEvent *>(sys_event);
......@@ -192,12 +160,6 @@ GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event,
}
return aFilterReturn;
#else
(void) this; // loplugin:staticmethods
(void) sys_event;
//FIXME: implement filterGdkEvent ...
return GDK_FILTER_CONTINUE;
#endif
}
void GtkSalDisplay::screenSizeChanged( GdkScreen* pScreen )
......@@ -214,7 +176,6 @@ void GtkSalDisplay::monitorsChanged( GdkScreen* pScreen )
emitDisplayChanged();
}
#if !GTK_CHECK_VERSION(3,0,0)
SalDisplay::ScreenData *
GtkSalDisplay::initScreen( SalX11Screen nXScreen ) const
{
......@@ -262,73 +223,12 @@ bool GtkSalDisplay::Dispatch( XEvent* pEvent )
return false;
}
#endif
#if GTK_CHECK_VERSION(3,0,0)
namespace
{
//cairo annoyingly won't take raw xbm data unless it fits
//the required cairo stride
unsigned char* ensurePaddedForCairo(const unsigned char *pXBM,
int nWidth, int nHeight, int nStride)
{
unsigned char *pPaddedXBM = const_cast<unsigned char*>(pXBM);
int bytes_per_row = (nWidth + 7) / 8;
if (nStride != bytes_per_row)
{
pPaddedXBM = new unsigned char[nStride * nHeight];
for (int row = 0; row < nHeight; ++row)
{
memcpy(pPaddedXBM + (nStride * row),
pXBM + (bytes_per_row * row), bytes_per_row);
memset(pPaddedXBM + (nStride * row) + bytes_per_row,
0, nStride - bytes_per_row);
}
}
return pPaddedXBM;
}
}
#endif
GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
const unsigned char *pMask,
int nWidth, int nHeight,
int nXHot, int nYHot )
{
#if GTK_CHECK_VERSION(3,0,0)
int cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, nWidth);
unsigned char *pPaddedXBM = ensurePaddedForCairo(pBitmap, nWidth, nHeight, cairo_stride);
cairo_surface_t *s = cairo_image_surface_create_for_data(
pPaddedXBM,
CAIRO_FORMAT_A1, nWidth, nHeight,
cairo_stride);
cairo_t *cr = cairo_create(s);
unsigned char *pPaddedMaskXBM = ensurePaddedForCairo(pMask, nWidth, nHeight, cairo_stride);
cairo_surface_t *mask = cairo_image_surface_create_for_data(
pPaddedMaskXBM,
CAIRO_FORMAT_A1, nWidth, nHeight,
cairo_stride);
cairo_mask_surface(cr, mask, 0, 0);
cairo_destroy(cr);
cairo_surface_destroy(mask);
if (pPaddedMaskXBM != pMask)
delete [] pPaddedMaskXBM;
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, nWidth, nHeight);
cairo_surface_destroy(s);
if (pPaddedXBM != pBitmap)
delete [] pPaddedXBM;
GdkCursor *cursor = gdk_cursor_new_from_pixbuf(m_pGdkDisplay, pixbuf, nXHot, nYHot);
g_object_unref(pixbuf);
return cursor;
#else
GdkScreen *pScreen = gdk_display_get_default_screen( m_pGdkDisplay );
GdkDrawable *pDrawable = GDK_DRAWABLE( gdk_screen_get_root_window (pScreen) );
GdkBitmap *pBitmapPix = gdk_bitmap_create_from_data
......@@ -346,7 +246,6 @@ GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
return gdk_cursor_new_from_pixmap
( pBitmapPix, pMaskPix,
&aBlack, &aWhite, nXHot, nYHot);
#endif
}
#define MAKE_CURSOR( vcl_name, name ) \
......@@ -521,11 +420,7 @@ int GtkSalDisplay::CaptureMouse( SalFrame* pSFrame )
**********************************************************************/
GtkData::GtkData( SalInstance *pInstance )
#if GTK_CHECK_VERSION(3,0,0)
: SalGenericData( SAL_DATA_GTK3, pInstance )
#else
: SalGenericData( SAL_DATA_GTK, pInstance )
#endif
, m_aDispatchMutex()
, blockIdleTimeout( false )
{
......@@ -533,7 +428,6 @@ GtkData::GtkData( SalInstance *pInstance )
m_aDispatchCondition = osl_createCondition();
}
#if defined(GDK_WINDOWING_X11)
XIOErrorHandler aOrigXIOErrorHandler = nullptr;
extern "C" {
......@@ -547,7 +441,6 @@ static int XIOErrorHdl(Display *)
}
}
#endif
GtkData::~GtkData()
{
......@@ -566,10 +459,7 @@ GtkData::~GtkData()
m_pUserEvent = nullptr;
}
osl_destroyCondition( m_aDispatchCondition );
#if defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
XSetIOErrorHandler(aOrigXIOErrorHandler);
#endif
XSetIOErrorHandler(aOrigXIOErrorHandler);
}
void GtkData::Dispose()
......@@ -642,9 +532,7 @@ void GtkData::Init()
SAL_INFO( "vcl.gtk", "GtkMainloop::Init()" );
XrmInitialize();
#if !GTK_CHECK_VERSION(3,0,0)
gtk_set_locale();
#endif
/*
* open connection to X11 Display
......@@ -724,12 +612,8 @@ void GtkData::Init()
exit(0);
}
#if defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY(pGdkDisp))
aOrigXIOErrorHandler = XSetIOErrorHandler(XIOErrorHdl);
#endif
aOrigXIOErrorHandler = XSetIOErrorHandler(XIOErrorHdl);
#if !GTK_CHECK_VERSION(3,0,0)
/*
* if a -display switch was used, we need
* to set the environment accordingly since
......@@ -740,12 +624,10 @@ void GtkData::Init()
const gchar *name = gdk_display_get_name( pGdkDisp );
OUString envValue(name, strlen(name), aEnc);
osl_setEnvironment(envVar.pData, envValue.pData);
#endif
GtkSalDisplay *pDisplay = new GtkSalDisplay( pGdkDisp );
SetDisplay( pDisplay );
#if !GTK_CHECK_VERSION(3,0,0)
Display *pDisp = gdk_x11_display_get_xdisplay( pGdkDisp );
gdk_error_trap_push();
......@@ -755,9 +637,6 @@ void GtkData::Init()
pKbdExtension->UseExtension( bErrorOccured );
gdk_error_trap_pop();
GetGtkDisplay()->SetKbdExtension( pKbdExtension );
#else
//FIXME: unwind keyboard extension bits
#endif
// add signal handler to notify screen size changes
int nScreens = gdk_display_get_n_screens( pGdkDisp );
......@@ -783,15 +662,7 @@ void GtkData::ErrorTrapPush()
bool GtkData::ErrorTrapPop( bool bIgnoreError )
{
#if GTK_CHECK_VERSION(3,0,0)
if( bIgnoreError )
{
gdk_error_trap_pop_ignored (); // faster
return false;
}
#else
(void) bIgnoreError;
#endif
return gdk_error_trap_pop () != 0;
}
......
......@@ -5,8 +5,850 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "../gtk/gtkdata.cxx"
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <poll.h>
#if defined(FREEBSD) || defined(NETBSD)
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <unx/gtk/gtkdata.hxx>
#include <unx/gtk/gtkinst.hxx>
#include <unx/gtk/gtkframe.hxx>
#include <unx/gtk/gtksalmenu.hxx>
#include <unx/salobj.h>
#include <unx/geninst.h>
#include <osl/thread.h>
#include <osl/process.h>
#include "unx/i18n_im.hxx"
#include "unx/i18n_xkb.hxx"
#include <unx/wmadaptor.hxx>
#include "unx/x11_cursors/salcursors.h"
#include <vcl/svapp.hxx>
#ifdef GDK_WINDOWING_X11
# include <gdk/gdkx.h>
#endif
using namespace vcl_sal;
/***************************************************************
* class GtkSalDisplay *
***************************************************************/
extern "C" {
GdkFilterReturn call_filterGdkEvent( GdkXEvent* sys_event,
GdkEvent* event,
gpointer data )
{
GtkSalDisplay *pDisplay = static_cast<GtkSalDisplay *>(data);
return pDisplay->filterGdkEvent( sys_event, event );
}
}
GtkSalDisplay::GtkSalDisplay( GdkDisplay* pDisplay ) :
m_pSys( GtkSalSystem::GetSingleton() ),
m_pGdkDisplay( pDisplay ),
m_bStartupCompleted( false )
{
for(GdkCursor* & rpCsr : m_aCursors)
rpCsr = nullptr;
// FIXME: unify this with SalInst's filter too ?
gdk_window_add_filter( nullptr, call_filterGdkEvent, this );
if ( getenv( "SAL_IGNOREXERRORS" ) )
GetGenericData()->ErrorTrapPush(); // and leak the trap
m_bX11Display = GDK_IS_X11_DISPLAY( m_pGdkDisplay );
#ifdef GDK_WINDOWING_X11
if (m_bX11Display)
{
if (!getenv("GDK_SCALE"))
{
gdk_x11_display_set_window_scale(m_pGdkDisplay, 1);
}
}
#endif
gtk_widget_set_default_direction(AllSettings::GetLayoutRTL() ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
}
GtkSalDisplay::~GtkSalDisplay()
{
gdk_window_remove_filter( nullptr, call_filterGdkEvent, this );
if( !m_bStartupCompleted )
gdk_notify_startup_complete();
for(GdkCursor* & rpCsr : m_aCursors)
if( rpCsr )
gdk_cursor_unref( rpCsr );
}
extern "C" {
void signalScreenSizeChanged( GdkScreen* pScreen, gpointer data )
{
GtkSalDisplay* pDisp = static_cast<GtkSalDisplay*>(data);
pDisp->screenSizeChanged( pScreen );
}
void signalMonitorsChanged( GdkScreen* pScreen, gpointer data )
{
GtkSalDisplay* pDisp = static_cast<GtkSalDisplay*>(data);
pDisp->monitorsChanged( pScreen );
}
}
GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* sys_event,
GdkEvent* )
{
(void) this; // loplugin:staticmethods
(void) sys_event;
//FIXME: implement filterGdkEvent ...
return GDK_FILTER_CONTINUE;
}
void GtkSalDisplay::screenSizeChanged( GdkScreen* pScreen )
{
m_pSys->countScreenMonitors();
if (pScreen)
emitDisplayChanged();
}
void GtkSalDisplay::monitorsChanged( GdkScreen* pScreen )
{
m_pSys->countScreenMonitors();
if (pScreen)
emitDisplayChanged();
}
namespace
{
//cairo annoyingly won't take raw xbm data unless it fits
//the required cairo stride
unsigned char* ensurePaddedForCairo(const unsigned char *pXBM,
int nWidth, int nHeight, int nStride)
{
unsigned char *pPaddedXBM = const_cast<unsigned char*>(pXBM);
int bytes_per_row = (nWidth + 7) / 8;
if (nStride != bytes_per_row)
{
pPaddedXBM = new unsigned char[nStride * nHeight];
for (int row = 0; row < nHeight; ++row)
{
memcpy(pPaddedXBM + (nStride * row),
pXBM + (bytes_per_row * row), bytes_per_row);
memset(pPaddedXBM + (nStride * row) + bytes_per_row,
0, nStride - bytes_per_row);
}
}
return pPaddedXBM;
}
}
GdkCursor* GtkSalDisplay::getFromXBM( const unsigned char *pBitmap,
const unsigned char *pMask,
int nWidth, int nHeight,
int nXHot, int nYHot )
{
int cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, nWidth);
unsigned char *pPaddedXBM = ensurePaddedForCairo(pBitmap, nWidth, nHeight, cairo_stride);
cairo_surface_t *s = cairo_image_surface_create_for_data(
pPaddedXBM,
CAIRO_FORMAT_A1, nWidth, nHeight,
cairo_stride);
cairo_t *cr = cairo_create(s);
unsigned char *pPaddedMaskXBM = ensurePaddedForCairo(pMask, nWidth, nHeight, cairo_stride);
cairo_surface_t *mask = cairo_image_surface_create_for_data(
pPaddedMaskXBM,
CAIRO_FORMAT_A1, nWidth, nHeight,
cairo_stride);
cairo_mask_surface(cr, mask, 0, 0);
cairo_destroy(cr);
cairo_surface_destroy(mask);
if (pPaddedMaskXBM != pMask)
delete [] pPaddedMaskXBM;
GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(s, 0, 0, nWidth, nHeight);
cairo_surface_destroy(s);
if (pPaddedXBM != pBitmap)
delete [] pPaddedXBM;
GdkCursor *cursor = gdk_cursor_new_from_pixbuf(m_pGdkDisplay, pixbuf, nXHot, nYHot);
g_object_unref(pixbuf);
return cursor;
}
#define MAKE_CURSOR( vcl_name, name ) \
case vcl_name: \
pCursor = getFromXBM( name##curs##_bits, name##mask##_bits, \
name##curs_width, name##curs_height, \
name##curs_x_hot, name##curs_y_hot ); \
break
#define MAP_BUILTIN( vcl_name, gdk_name ) \
case vcl_name: \
pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, gdk_name ); \
break
GdkCursor *GtkSalDisplay::getCursor( PointerStyle ePointerStyle )
{
if ( !m_aCursors[ ePointerStyle ] )
{
GdkCursor *pCursor = nullptr;
switch( ePointerStyle )
{
MAP_BUILTIN( PointerStyle::Arrow, GDK_LEFT_PTR );
MAP_BUILTIN( PointerStyle::Text, GDK_XTERM );
MAP_BUILTIN( PointerStyle::Help, GDK_QUESTION_ARROW );
MAP_BUILTIN( PointerStyle::Cross, GDK_CROSSHAIR );
MAP_BUILTIN( PointerStyle::Wait, GDK_WATCH );
MAP_BUILTIN( PointerStyle::NSize, GDK_SB_V_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::SSize, GDK_SB_V_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::WSize, GDK_SB_H_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::ESize, GDK_SB_H_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::NWSize, GDK_TOP_LEFT_CORNER );
MAP_BUILTIN( PointerStyle::NESize, GDK_TOP_RIGHT_CORNER );
MAP_BUILTIN( PointerStyle::SWSize, GDK_BOTTOM_LEFT_CORNER );
MAP_BUILTIN( PointerStyle::SESize, GDK_BOTTOM_RIGHT_CORNER );
MAP_BUILTIN( PointerStyle::WindowNSize, GDK_TOP_SIDE );
MAP_BUILTIN( PointerStyle::WindowSSize, GDK_BOTTOM_SIDE );
MAP_BUILTIN( PointerStyle::WindowWSize, GDK_LEFT_SIDE );
MAP_BUILTIN( PointerStyle::WindowESize, GDK_RIGHT_SIDE );
MAP_BUILTIN( PointerStyle::WindowNWSize, GDK_TOP_LEFT_CORNER );
MAP_BUILTIN( PointerStyle::WindowNESize, GDK_TOP_RIGHT_CORNER );
MAP_BUILTIN( PointerStyle::WindowSWSize, GDK_BOTTOM_LEFT_CORNER );
MAP_BUILTIN( PointerStyle::WindowSESize, GDK_BOTTOM_RIGHT_CORNER );
MAP_BUILTIN( PointerStyle::HSizeBar, GDK_SB_H_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::VSizeBar, GDK_SB_V_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::RefHand, GDK_HAND2 );
MAP_BUILTIN( PointerStyle::Hand, GDK_HAND2 );
MAP_BUILTIN( PointerStyle::Pen, GDK_PENCIL );
MAP_BUILTIN( PointerStyle::HSplit, GDK_SB_H_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::VSplit, GDK_SB_V_DOUBLE_ARROW );
MAP_BUILTIN( PointerStyle::Move, GDK_FLEUR );
MAKE_CURSOR( PointerStyle::Null, null );
MAKE_CURSOR( PointerStyle::Magnify, magnify_ );
MAKE_CURSOR( PointerStyle::Fill, fill_ );
MAKE_CURSOR( PointerStyle::MoveData, movedata_ );
MAKE_CURSOR( PointerStyle::CopyData, copydata_ );
MAKE_CURSOR( PointerStyle::MoveFile, movefile_ );
MAKE_CURSOR( PointerStyle::CopyFile, copyfile_ );
MAKE_CURSOR( PointerStyle::MoveFiles, movefiles_ );
MAKE_CURSOR( PointerStyle::CopyFiles, copyfiles_ );
MAKE_CURSOR( PointerStyle::NotAllowed, nodrop_ );
MAKE_CURSOR( PointerStyle::Rotate, rotate_ );
MAKE_CURSOR( PointerStyle::HShear, hshear_ );
MAKE_CURSOR( PointerStyle::VShear, vshear_ );
MAKE_CURSOR( PointerStyle::DrawLine, drawline_ );
MAKE_CURSOR( PointerStyle::DrawRect, drawrect_ );
MAKE_CURSOR( PointerStyle::DrawPolygon, drawpolygon_ );
MAKE_CURSOR( PointerStyle::DrawBezier, drawbezier_ );
MAKE_CURSOR( PointerStyle::DrawArc, drawarc_ );
MAKE_CURSOR( PointerStyle::DrawPie, drawpie_ );
MAKE_CURSOR( PointerStyle::DrawCircleCut, drawcirclecut_ );
MAKE_CURSOR( PointerStyle::DrawEllipse, drawellipse_ );
MAKE_CURSOR( PointerStyle::DrawConnect, drawconnect_ );
MAKE_CURSOR( PointerStyle::DrawText, drawtext_ );
MAKE_CURSOR( PointerStyle::Mirror, mirror_ );
MAKE_CURSOR( PointerStyle::Crook, crook_ );
MAKE_CURSOR( PointerStyle::Crop, crop_ );
MAKE_CURSOR( PointerStyle::MovePoint, movepoint_ );
MAKE_CURSOR( PointerStyle::MoveBezierWeight, movebezierweight_ );
MAKE_CURSOR( PointerStyle::DrawFreehand, drawfreehand_ );
MAKE_CURSOR( PointerStyle::DrawCaption, drawcaption_ );
MAKE_CURSOR( PointerStyle::LinkData, linkdata_ );
MAKE_CURSOR( PointerStyle::MoveDataLink, movedlnk_ );
MAKE_CURSOR( PointerStyle::CopyDataLink, copydlnk_ );
MAKE_CURSOR( PointerStyle::LinkFile, linkfile_ );
MAKE_CURSOR( PointerStyle::MoveFileLink, moveflnk_ );
MAKE_CURSOR( PointerStyle::CopyFileLink, copyflnk_ );
MAKE_CURSOR( PointerStyle::Chart, chart_ );
MAKE_CURSOR( PointerStyle::Detective, detective_ );
MAKE_CURSOR( PointerStyle::PivotCol, pivotcol_ );
MAKE_CURSOR( PointerStyle::PivotRow, pivotrow_ );
MAKE_CURSOR( PointerStyle::PivotField, pivotfld_ );
MAKE_CURSOR( PointerStyle::PivotDelete, pivotdel_ );
MAKE_CURSOR( PointerStyle::Chain, chain_ );
MAKE_CURSOR( PointerStyle::ChainNotAllowed, chainnot_ );
MAKE_CURSOR( PointerStyle::TimeEventMove, timemove_ );
MAKE_CURSOR( PointerStyle::TimeEventSize, timesize_ );
MAKE_CURSOR( PointerStyle::AutoScrollN, asn_ );
MAKE_CURSOR( PointerStyle::AutoScrollS, ass_ );
MAKE_CURSOR( PointerStyle::AutoScrollW, asw_ );
MAKE_CURSOR( PointerStyle::AutoScrollE, ase_ );
MAKE_CURSOR( PointerStyle::AutoScrollNW, asnw_ );
MAKE_CURSOR( PointerStyle::AutoScrollNE, asne_ );
MAKE_CURSOR( PointerStyle::AutoScrollSW, assw_ );
MAKE_CURSOR( PointerStyle::AutoScrollSE, asse_ );
MAKE_CURSOR( PointerStyle::AutoScrollNS, asns_ );
MAKE_CURSOR( PointerStyle::AutoScrollWE, aswe_ );
MAKE_CURSOR( PointerStyle::AutoScrollNSWE, asnswe_ );
MAKE_CURSOR( PointerStyle::Airbrush, airbrush_ );
MAKE_CURSOR( PointerStyle::TextVertical, vertcurs_ );
// #i32329#
MAKE_CURSOR( PointerStyle::TabSelectS, tblsels_ );
MAKE_CURSOR( PointerStyle::TabSelectE, tblsele_ );
MAKE_CURSOR( PointerStyle::TabSelectSE, tblselse_ );
MAKE_CURSOR( PointerStyle::TabSelectW, tblselw_ );
MAKE_CURSOR( PointerStyle::TabSelectSW, tblselsw_ );
// #i20119#
MAKE_CURSOR( PointerStyle::Paintbrush, paintbrush_ );
MAKE_CURSOR( PointerStyle::HideWhitespace, hidewhitespace_ );
MAKE_CURSOR( PointerStyle::ShowWhitespace, showwhitespace_ );
default:
SAL_WARN( "vcl.gtk", "pointer " << static_cast<int>(ePointerStyle) << "not implemented" );
break;
}
if( !pCursor )
pCursor = gdk_cursor_new_for_display( m_pGdkDisplay, GDK_LEFT_PTR );
m_aCursors[ ePointerStyle ] = pCursor;
}
return m_aCursors[ ePointerStyle ];
}
int GtkSalDisplay::CaptureMouse( SalFrame* pSFrame )
{
GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(pSFrame);
if( !pFrame )
{
if( m_pCapture )
static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
m_pCapture = nullptr;
return 0;
}
if( m_pCapture )
{
if( pFrame == m_pCapture )
return 1;
static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
}
m_pCapture = pFrame;
static_cast<GtkSalFrame*>(pFrame)->grabPointer( TRUE );
return 1;
}
/**********************************************************************
* class GtkData *
**********************************************************************/
GtkData::GtkData( SalInstance *pInstance )
: SalGenericData( SAL_DATA_GTK3, pInstance )
, m_aDispatchMutex()
, blockIdleTimeout( false )
{
m_pUserEvent = nullptr;
m_aDispatchCondition = osl_createCondition();
}
#if defined(GDK_WINDOWING_X11)
XIOErrorHandler aOrigXIOErrorHandler = nullptr;
extern "C" {
static int XIOErrorHdl(Display *)
{
fprintf(stderr, "X IO Error\n");
_exit(1);
// avoid crashes in unrelated threads that still run while atexit
// handlers are in progress
}
}
#endif
GtkData::~GtkData()
{
Yield( true, true );
g_warning ("TESTME: We used to have a stop-timer here, but the central code should do this");
// sanity check: at this point nobody should be yielding, but wake them
// up anyway before the condition they're waiting on gets destroyed.
osl_setCondition( m_aDispatchCondition );
osl::MutexGuard g( m_aDispatchMutex );
if (m_pUserEvent)
{
g_source_destroy (m_pUserEvent);
g_source_unref (m_pUserEvent);
m_pUserEvent = nullptr;
}
osl_destroyCondition( m_aDispatchCondition );
#if defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
XSetIOErrorHandler(aOrigXIOErrorHandler);
#endif
}
void GtkData::Dispose()
{
deInitNWF();
}
/// Allows events to be processed, returns true if we processed an event.
SalYieldResult GtkData::Yield( bool bWait, bool bHandleAllCurrentEvents )
{
blockIdleTimeout = !bWait;
/* #i33212# only enter g_main_context_iteration in one thread at any one
* time, else one of them potentially will never end as long as there is
* another thread in there. Having only one yielding thread actually dispatch
* fits the vcl event model (see e.g. the generic plugin).
*/
bool bDispatchThread = false;
bool bWasEvent = false;
{
// release YieldMutex (and re-acquire at block end)
SalYieldMutexReleaser aReleaser;
if( m_aDispatchMutex.tryToAcquire() )
bDispatchThread = true;
else if( ! bWait )
{
blockIdleTimeout = false;
return SalYieldResult::TIMEOUT; // someone else is waiting already, return
}
if( bDispatchThread )
{
int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
gboolean wasOneEvent = TRUE;
while( nMaxEvents-- && wasOneEvent )
{
wasOneEvent = g_main_context_iteration( nullptr, bWait && !bWasEvent );
if( wasOneEvent )
bWasEvent = true;
}
}
else if( bWait )
{
/* #i41693# in case the dispatch thread hangs in join
* for this thread the condition will never be set
* workaround: timeout of 1 second a emergency exit
*/
// we are the dispatch thread
osl_resetCondition( m_aDispatchCondition );
TimeValue aValue = { 1, 0 };
osl_waitCondition( m_aDispatchCondition, &aValue );
}
}
if( bDispatchThread )
{
m_aDispatchMutex.release();
if( bWasEvent )
osl_setCondition( m_aDispatchCondition ); // trigger non dispatch thread yields
}
blockIdleTimeout = false;
return bWasEvent ? SalYieldResult::EVENT
: SalYieldResult::TIMEOUT;
}
void GtkData::Init()
{
int i;
SAL_INFO( "vcl.gtk", "GtkMainloop::Init()" );
XrmInitialize();
/*
* open connection to X11 Display
* try in this order:
* o -display command line parameter,
* o $DISPLAY environment variable
* o default display
*/
GdkDisplay *pGdkDisp = nullptr;
// is there a -display command line parameter?
rtl_TextEncoding aEnc = osl_getThreadTextEncoding();
int nParams = osl_getCommandArgCount();
OString aDisplay;
OUString aParam, aBin;
char** pCmdLineAry = new char*[ nParams+1 ];
osl_getExecutableFile( &aParam.pData );
osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
pCmdLineAry[0] = g_strdup( OUStringToOString( aBin, aEnc ).getStr() );
for (i=0; i<nParams; i++)
{
osl_getCommandArg(i, &aParam.pData );
OString aBParam( OUStringToOString( aParam, aEnc ) );
if( aParam == "-display" || aParam == "--display" )
{
pCmdLineAry[i+1] = g_strdup( "--display" );
osl_getCommandArg(i+1, &aParam.pData );
aDisplay = OUStringToOString( aParam, aEnc );
}
else
pCmdLineAry[i+1] = g_strdup( aBParam.getStr() );
}
// add executable
nParams++;
g_set_application_name(SalGenericSystem::getFrameClassName());
// Set consistent name of the root accessible
OUString aAppName = Application::GetAppName();
if( !aAppName.isEmpty() )
{
OString aPrgName = OUStringToOString(aAppName, aEnc);
g_set_prgname(aPrgName.getStr());
}
// init gtk/gdk
gtk_init_check( &nParams, &pCmdLineAry );
gdk_error_trap_push();
for (i = 0; i < nParams; i++ )
g_free( pCmdLineAry[i] );
delete [] pCmdLineAry;
#if OSL_DEBUG_LEVEL > 1
if (g_getenv("SAL_DEBUG_UPDATES"))
gdk_window_set_debug_updates (TRUE);
#endif
pGdkDisp = gdk_display_get_default();
if ( !pGdkDisp )
{
OUString aProgramFileURL;
osl_getExecutableFile( &aProgramFileURL.pData );
OUString aProgramSystemPath;
osl_getSystemPathFromFileURL (aProgramFileURL.pData, &aProgramSystemPath.pData);
OString aProgramName = OUStringToOString(
aProgramSystemPath,
osl_getThreadTextEncoding() );
fprintf( stderr, "%s X11 error: Can't open display: %s\n",
aProgramName.getStr(), aDisplay.getStr());
fprintf( stderr, " Set DISPLAY environment variable, use -display option\n");
fprintf( stderr, " or check permissions of your X-Server\n");
fprintf( stderr, " (See \"man X\" resp. \"man xhost\" for details)\n");
fflush( stderr );
exit(0);
}
#if defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY(pGdkDisp))
aOrigXIOErrorHandler = XSetIOErrorHandler(XIOErrorHdl);
#endif
GtkSalDisplay *pDisplay = new GtkSalDisplay( pGdkDisp );
SetDisplay( pDisplay );
//FIXME: unwind keyboard extension bits
// add signal handler to notify screen size changes
int nScreens = gdk_display_get_n_screens( pGdkDisp );
for( int n = 0; n < nScreens; n++ )
{
GdkScreen *pScreen = gdk_display_get_screen( pGdkDisp, n );
if( pScreen )
{
pDisplay->screenSizeChanged( pScreen );
pDisplay->monitorsChanged( pScreen );
g_signal_connect( G_OBJECT(pScreen), "size-changed",
G_CALLBACK(signalScreenSizeChanged), pDisplay );
g_signal_connect( G_OBJECT(pScreen), "monitors-changed",
G_CALLBACK(signalMonitorsChanged), GetGtkDisplay() );
}
}
}
void GtkData::ErrorTrapPush()
{
gdk_error_trap_push ();
}
bool GtkData::ErrorTrapPop( bool bIgnoreError )
{
if (bIgnoreError)
{
gdk_error_trap_pop_ignored (); // faster
return false;
}
return gdk_error_trap_pop () != 0;
}
extern "C" {
struct SalGtkTimeoutSource {
GSource aParent;
GTimeVal aFireTime;
GtkSalTimer *pInstance;
};
static void sal_gtk_timeout_defer( SalGtkTimeoutSource *pTSource )
{
g_get_current_time( &pTSource->aFireTime );
g_time_val_add( &pTSource->aFireTime, pTSource->pInstance->m_nTimeoutMS * 1000 );
}
static gboolean sal_gtk_timeout_expired( SalGtkTimeoutSource *pTSource,
gint *nTimeoutMS, GTimeVal *pTimeNow )
{
glong nDeltaSec = pTSource->aFireTime.tv_sec - pTimeNow->tv_sec;
glong nDeltaUSec = pTSource->aFireTime.tv_usec - pTimeNow->tv_usec;
if( nDeltaSec < 0 || ( nDeltaSec == 0 && nDeltaUSec < 0) )
{
*nTimeoutMS = 0;
return TRUE;
}
if( nDeltaUSec < 0 )
{
nDeltaUSec += 1000000;
nDeltaSec -= 1;
}
// if the clock changes backwards we need to cope ...
if( (unsigned long) nDeltaSec > 1 + ( pTSource->pInstance->m_nTimeoutMS / 1000 ) )
{
sal_gtk_timeout_defer( pTSource );
return TRUE;
}
*nTimeoutMS = MIN( G_MAXINT, ( nDeltaSec * 1000 + (nDeltaUSec + 999) / 1000 ) );
return *nTimeoutMS == 0;
}
static gboolean sal_gtk_timeout_prepare( GSource *pSource, gint *nTimeoutMS )
{
SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
GTimeVal aTimeNow;
g_get_current_time( &aTimeNow );
return sal_gtk_timeout_expired( pTSource, nTimeoutMS, &aTimeNow );
}
static gboolean sal_gtk_timeout_check( GSource *pSource )
{
SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
GTimeVal aTimeNow;
g_get_current_time( &aTimeNow );
return ( pTSource->aFireTime.tv_sec < aTimeNow.tv_sec ||
( pTSource->aFireTime.tv_sec == aTimeNow.tv_sec &&
pTSource->aFireTime.tv_usec < aTimeNow.tv_usec ) );
}
static gboolean sal_gtk_timeout_dispatch( GSource *pSource, GSourceFunc, gpointer )
{
SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
if( !pTSource->pInstance )
return FALSE;
GtkData *pSalData = static_cast< GtkData* >( GetSalData());
osl::Guard< comphelper::SolarMutex > aGuard( pSalData->m_pInstance->GetYieldMutex() );
sal_gtk_timeout_defer( pTSource );
ImplSVData* pSVData = ImplGetSVData();
if( pSVData->mpSalTimer )
{
// TODO: context_pending should be probably checked too, but it causes locking assertion failures
bool idle = !pSalData->BlockIdleTimeout() && /*!g_main_context_pending( NULL ) &&*/ !gdk_events_pending();
pSVData->mpSalTimer->CallCallback( idle );
}
return TRUE;
}
static GSourceFuncs sal_gtk_timeout_funcs =
{
sal_gtk_timeout_prepare,
sal_gtk_timeout_check,
sal_gtk_timeout_dispatch,
nullptr, nullptr, nullptr
};
}
static SalGtkTimeoutSource *
create_sal_gtk_timeout( GtkSalTimer *pTimer )
{
GSource *pSource = g_source_new( &sal_gtk_timeout_funcs, sizeof( SalGtkTimeoutSource ) );
SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource);
pTSource->pInstance = pTimer;
// #i36226# timers should be executed with lower priority
// than XEvents like in generic plugin
g_source_set_priority( pSource, G_PRIORITY_LOW );
g_source_set_can_recurse( pSource, TRUE );
g_source_set_callback( pSource,
/* unused dummy */ g_idle_remove_by_data,
nullptr, nullptr );
g_source_attach( pSource, g_main_context_default() );
#ifdef DBG_UTIL
g_source_set_name( pSource, "VCL timeout source" );
#endif
sal_gtk_timeout_defer( pTSource );
return pTSource;
}
GtkSalTimer::GtkSalTimer()
: m_pTimeout(nullptr)
, m_nTimeoutMS(0)
{
}
GtkSalTimer::~GtkSalTimer()
{
GtkInstance *pInstance = static_cast<GtkInstance *>(GetSalData()->m_pInstance);
pInstance->RemoveTimer( this );
Stop();
}
bool GtkSalTimer::Expired()
{
if( !m_pTimeout )
return false;
gint nDummy = 0;
GTimeVal aTimeNow;
g_get_current_time( &aTimeNow );
return !!sal_gtk_timeout_expired( m_pTimeout, &nDummy, &aTimeNow);
}
void GtkSalTimer::Start( sal_uLong nMS )
{
// glib is not 64bit safe in this regard.
assert( nMS <= G_MAXINT );
m_nTimeoutMS = nMS; // for restarting
Stop(); // FIXME: ideally re-use an existing m_pTimeout
m_pTimeout = create_sal_gtk_timeout( this );
}
void GtkSalTimer::Stop()
{
if( m_pTimeout )
{
g_source_destroy( &m_pTimeout->aParent );
g_source_unref( &m_pTimeout->aParent );
m_pTimeout = nullptr;
}
}
gboolean GtkData::userEventFn( gpointer data )
{
gboolean bContinue = FALSE;
GtkData *pThis = static_cast<GtkData *>(data);
SalGenericData *pData = GetGenericData();
osl::Guard< comphelper::SolarMutex > aGuard( pData->m_pInstance->GetYieldMutex() );
const SalGenericDisplay *pDisplay = pData->GetDisplay();
if (pDisplay)
{
OSL_ASSERT(static_cast<const SalGenericDisplay *>(pThis->GetGtkDisplay()) == pDisplay);
{
osl::MutexGuard g (pThis->GetGtkDisplay()->getEventGuardMutex());
if( !pThis->GetGtkDisplay()->HasUserEvents() )
{
if( pThis->m_pUserEvent )
{
g_source_unref (pThis->m_pUserEvent);
pThis->m_pUserEvent = nullptr;
}
bContinue = FALSE;
}
else
bContinue = TRUE;
}
pThis->GetGtkDisplay()->DispatchInternalEvent();
}
return bContinue;
}
extern "C" {
static gboolean call_userEventFn( void *data )
{
SolarMutexGuard aGuard;
return GtkData::userEventFn( data );
}
}
// hEventGuard_ held during this invocation
void GtkData::PostUserEvent()
{
if (m_pUserEvent)
g_main_context_wakeup (nullptr); // really needed ?
else // nothing pending anyway
{
m_pUserEvent = g_idle_source_new();
g_source_set_priority (m_pUserEvent, G_PRIORITY_HIGH);
g_source_set_can_recurse (m_pUserEvent, TRUE);
g_source_set_callback (m_pUserEvent, call_userEventFn,
static_cast<gpointer>(this), nullptr);
g_source_attach (m_pUserEvent, g_main_context_default ());
}
}
void GtkSalDisplay::PostUserEvent()
{
GetGtkSalData()->PostUserEvent();
}
void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
{
if( m_pCapture == pFrame )
{
static_cast<GtkSalFrame*>(m_pCapture)->grabPointer( FALSE );
m_pCapture = nullptr;
}
SalGenericDisplay::deregisterFrame( pFrame );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment