mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 17:01:24 +12:00
This commit is contained in:
parent
de070bf485
commit
a90b5cf37a
1998 changed files with 1034301 additions and 0 deletions
83
wxWidgets/src/unix/baseunix.cpp
Normal file
83
wxWidgets/src/unix/baseunix.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/baseunix.cpp
|
||||
// Purpose: misc stuff only used in console applications under Unix
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 23.06.2003
|
||||
// RCS-ID: $Id: baseunix.cpp 40599 2006-08-13 21:00:32Z VZ $
|
||||
// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
|
||||
// License: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/utils.h"
|
||||
#endif //WX_PRECOMP
|
||||
|
||||
#include "wx/apptrait.h"
|
||||
#include "wx/unix/execute.h"
|
||||
|
||||
// for waitpid()
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
// ============================================================================
|
||||
// wxConsoleAppTraits implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxExecute support
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxConsoleAppTraits::CreateEndProcessPipe(wxExecuteData& WXUNUSED(data))
|
||||
{
|
||||
// nothing to do, so always ok
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wxConsoleAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(data),
|
||||
int WXUNUSED(fd))
|
||||
{
|
||||
// we don't have any pipe
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
wxConsoleAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(data))
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
wxConsoleAppTraits::WaitForChild(wxExecuteData& execData)
|
||||
{
|
||||
wxASSERT_MSG( execData.flags & wxEXEC_SYNC,
|
||||
wxT("async execution not supported yet") );
|
||||
|
||||
int exitcode = 0;
|
||||
if ( waitpid(execData.pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) )
|
||||
{
|
||||
wxLogSysError(_("Waiting for subprocess termination failed"));
|
||||
}
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
120
wxWidgets/src/unix/descrip.mms
Normal file
120
wxWidgets/src/unix/descrip.mms
Normal file
|
@ -0,0 +1,120 @@
|
|||
#*****************************************************************************
|
||||
# *
|
||||
# Make file for VMS *
|
||||
# Author : J.Jansen (joukj@hrem.nano.tudelft.nl) *
|
||||
# Date : 13 February 2006 *
|
||||
# *
|
||||
#*****************************************************************************
|
||||
.first
|
||||
define wx [--.include.wx]
|
||||
|
||||
.ifdef __WXMOTIF__
|
||||
CXX_DEFINE = /define=(__WXMOTIF__=1)/name=(as_is,short)\
|
||||
/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXMOTIF__=1)/name=(as_is,short)
|
||||
.else
|
||||
.ifdef __WXGTK__
|
||||
CXX_DEFINE = /define=(__WXGTK__=1)/float=ieee/name=(as_is,short)/ieee=denorm\
|
||||
/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXGTK__=1)/float=ieee/name=(as_is,short)/ieee=denorm
|
||||
.else
|
||||
.ifdef __WXGTK2__
|
||||
CXX_DEFINE = /define=(__WXGTK__=1,VMS_GTK2)/float=ieee/name=(as_is,short)/ieee=denorm\
|
||||
/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXGTK__=1,VMS_GTK2)/float=ieee/name=(as_is,short)/ieee=denorm
|
||||
.else
|
||||
.ifdef __WXX11__
|
||||
CXX_DEFINE = /define=(__WXX11__=1,__WXUNIVERSAL__==1)/float=ieee\
|
||||
/name=(as_is,short)/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXX11__=1,__WXUNIVERSAL__==1)/float=ieee\
|
||||
/name=(as_is,short)
|
||||
.else
|
||||
CXX_DEFINE =
|
||||
CC_DEFINE =
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.suffixes : .cpp
|
||||
|
||||
.cpp.obj :
|
||||
cxx $(CXXFLAGS)$(CXX_DEFINE) $(MMS$TARGET_NAME).cpp
|
||||
.c.obj :
|
||||
cc $(CFLAGS)$(CC_DEFINE) $(MMS$TARGET_NAME).c
|
||||
|
||||
OBJECTS = baseunix.obj,\
|
||||
dialup.obj,\
|
||||
dir.obj,\
|
||||
displayx11.obj,\
|
||||
dlunix.obj,\
|
||||
fontenum.obj,\
|
||||
fontutil.obj,\
|
||||
gsocket.obj,\
|
||||
mimetype.obj,\
|
||||
threadpsx.obj,\
|
||||
utilsunx.obj,\
|
||||
utilsx11.obj,\
|
||||
joystick.obj,\
|
||||
snglinst.obj,\
|
||||
sound.obj,\
|
||||
sound_sdl.obj,\
|
||||
stdpaths.obj,\
|
||||
taskbarx11.obj
|
||||
|
||||
SOURCES = baseunix.cpp,\
|
||||
dialup.cpp,\
|
||||
dir.cpp,\
|
||||
displayx11.cpp,\
|
||||
dlunix.cpp,\
|
||||
fontenum.cpp,\
|
||||
fontutil.cpp,\
|
||||
gsocket.cpp,\
|
||||
mimetype.cpp,\
|
||||
threadpsx.cpp,\
|
||||
utilsunx.cpp,\
|
||||
utilsx11.cpp,\
|
||||
joystick.cpp,\
|
||||
snglinst.cpp,\
|
||||
sound.cpp,\
|
||||
sound_sdl.cpp,\
|
||||
stdpaths.cpp,\
|
||||
taskbarx11.cpp
|
||||
|
||||
all : $(SOURCES)
|
||||
$(MMS)$(MMSQUALIFIERS) $(OBJECTS)
|
||||
.ifdef __WXMOTIF__
|
||||
library [--.lib]libwx_motif.olb $(OBJECTS)
|
||||
.else
|
||||
.ifdef __WXGTK__
|
||||
library [--.lib]libwx_gtk.olb $(OBJECTS)
|
||||
.else
|
||||
.ifdef __WXGTK2__
|
||||
library [--.lib]libwx_gtk2.olb $(OBJECTS)
|
||||
.else
|
||||
.ifdef __WXX11__
|
||||
library [--.lib]libwx_x11_univ.olb $(OBJECTS)
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
|
||||
baseunix.obj : baseunix.cpp
|
||||
dialup.obj : dialup.cpp
|
||||
dir.obj : dir.cpp
|
||||
dlunix.obj : dlunix.cpp
|
||||
fontenum.obj : fontenum.cpp
|
||||
fontutil.obj : fontutil.cpp
|
||||
gsocket.obj : gsocket.cpp
|
||||
cxx $(CXXFLAGS)$(CXX_DEFINE)/nowarn gsocket.cpp
|
||||
mimetype.obj : mimetype.cpp
|
||||
threadpsx.obj : threadpsx.cpp
|
||||
utilsunx.obj : utilsunx.cpp
|
||||
utilsx11.obj : utilsx11.cpp
|
||||
joystick.obj : joystick.cpp
|
||||
snglinst.obj : snglinst.cpp
|
||||
sound.obj : sound.cpp
|
||||
sound_sdl.obj : sound_sdl.cpp
|
||||
stdpaths.obj : stdpaths.cpp
|
||||
taskbarx11.obj : taskbarx11.cpp
|
||||
displayx11.obj : displayx11.cpp
|
828
wxWidgets/src/unix/dialup.cpp
Normal file
828
wxWidgets/src/unix/dialup.cpp
Normal file
|
@ -0,0 +1,828 @@
|
|||
// -*- c++ -*- ////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/dialup.cpp
|
||||
// Purpose: Network related wxWidgets classes and functions
|
||||
// Author: Karsten Ballüder
|
||||
// Modified by:
|
||||
// Created: 03.10.99
|
||||
// RCS-ID: $Id: dialup.cpp 41020 2006-09-05 20:47:48Z VZ $
|
||||
// Copyright: (c) Karsten Ballüder
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if wxUSE_DIALUP_MANAGER
|
||||
|
||||
#include "wx/dialup.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/event.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/timer.h"
|
||||
#endif // !PCH
|
||||
|
||||
#include "wx/filefn.h"
|
||||
#include "wx/ffile.h"
|
||||
#include "wx/process.h"
|
||||
#include "wx/wxchar.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#define __STRICT_ANSI__
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
DEFINE_EVENT_TYPE(wxEVT_DIALUP_CONNECTED)
|
||||
DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// A class which groups functions dealing with connecting to the network from a
|
||||
// workstation using dial-up access to the net. There is at most one instance
|
||||
// of this class in the program accessed via GetDialUpManager().
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* TODO
|
||||
*
|
||||
* 1. more configurability for Unix: i.e. how to initiate the connection, how
|
||||
* to check for online status, &c.
|
||||
* 2. add a "long Dial(long connectionId = -1)" function which asks the user
|
||||
* about which connection to dial (this may be done using native dialogs
|
||||
* under NT, need generic dialogs for all others) and returns the identifier
|
||||
* of the selected connection (it's opaque to the application) - it may be
|
||||
* reused later to dial the same connection later (or use strings instead of
|
||||
* longs may be?)
|
||||
* 3. add an async version of dialing functions which notify the caller about
|
||||
* the progress (or may be even start another thread to monitor it)
|
||||
* 4. the static creation/accessor functions are not MT-safe - but is this
|
||||
* really crucial? I think we may suppose they're always called from the
|
||||
* main thread?
|
||||
*/
|
||||
|
||||
class WXDLLEXPORT wxDialUpManagerImpl : public wxDialUpManager
|
||||
{
|
||||
public:
|
||||
wxDialUpManagerImpl();
|
||||
virtual ~wxDialUpManagerImpl();
|
||||
|
||||
/** Could the dialup manager be initialized correctly? If this function
|
||||
returns false, no other functions will work neither, so it's a good idea
|
||||
to call this function and check its result before calling any other
|
||||
wxDialUpManager methods.
|
||||
*/
|
||||
virtual bool IsOk() const
|
||||
{ return true; }
|
||||
|
||||
/** The simplest way to initiate a dial up: this function dials the given
|
||||
ISP (exact meaning of the parameter depends on the platform), returns
|
||||
true on success or false on failure and logs the appropriate error
|
||||
message in the latter case.
|
||||
@param nameOfISP optional paramater for dial program
|
||||
@param username unused
|
||||
@param password unused
|
||||
*/
|
||||
virtual bool Dial(const wxString& nameOfISP,
|
||||
const wxString& WXUNUSED(username),
|
||||
const wxString& WXUNUSED(password),
|
||||
bool async);
|
||||
|
||||
// Hang up the currently active dial up connection.
|
||||
virtual bool HangUp();
|
||||
|
||||
// returns true if the computer is connected to the network: under Windows,
|
||||
// this just means that a RAS connection exists, under Unix we check that
|
||||
// the "well-known host" (as specified by SetWellKnownHost) is reachable
|
||||
virtual bool IsOnline() const
|
||||
{
|
||||
CheckStatus();
|
||||
return m_IsOnline == Net_Connected;
|
||||
}
|
||||
|
||||
// do we have a constant net connection?
|
||||
virtual bool IsAlwaysOnline() const;
|
||||
|
||||
// returns true if (async) dialing is in progress
|
||||
virtual bool IsDialing() const
|
||||
{ return m_DialProcess != NULL; }
|
||||
|
||||
// cancel dialing the number initiated with Dial(async = true)
|
||||
// NB: this won't result in DISCONNECTED event being sent
|
||||
virtual bool CancelDialing();
|
||||
|
||||
size_t GetISPNames(class wxArrayString &) const
|
||||
{ return 0; }
|
||||
|
||||
// sometimes the built-in logic for determining the online status may fail,
|
||||
// so, in general, the user should be allowed to override it. This function
|
||||
// allows to forcefully set the online status - whatever our internal
|
||||
// algorithm may think about it.
|
||||
virtual void SetOnlineStatus(bool isOnline = true)
|
||||
{ m_IsOnline = isOnline ? Net_Connected : Net_No; }
|
||||
|
||||
// set misc wxDialUpManager options
|
||||
// --------------------------------
|
||||
|
||||
// enable automatical checks for the connection status and sending of
|
||||
// wxEVT_DIALUP_CONNECTED/wxEVT_DIALUP_DISCONNECTED events. The interval
|
||||
// parameter is only for Unix where we do the check manually: under
|
||||
// Windows, the notification about the change of connection status is
|
||||
// instantenous.
|
||||
//
|
||||
// Returns false if couldn't set up automatic check for online status.
|
||||
virtual bool EnableAutoCheckOnlineStatus(size_t nSeconds);
|
||||
|
||||
// disable automatic check for connection status change - notice that the
|
||||
// wxEVT_DIALUP_XXX events won't be sent any more neither.
|
||||
virtual void DisableAutoCheckOnlineStatus();
|
||||
|
||||
// under Unix, the value of well-known host is used to check whether we're
|
||||
// connected to the internet. It's unused under Windows, but this function
|
||||
// is always safe to call. The default value is www.yahoo.com.
|
||||
virtual void SetWellKnownHost(const wxString& hostname,
|
||||
int portno = 80);
|
||||
/** Sets the commands to start up the network and to hang up
|
||||
again. Used by the Unix implementations only.
|
||||
*/
|
||||
virtual void SetConnectCommand(const wxString &command, const wxString &hupcmd)
|
||||
{ m_ConnectCommand = command; m_HangUpCommand = hupcmd; }
|
||||
|
||||
//private: -- Sun CC 4.2 objects to using NetConnection enum as the return
|
||||
// type if it is declared private
|
||||
|
||||
// the possible results of testing for Online() status
|
||||
enum NetConnection
|
||||
{
|
||||
Net_Unknown = -1, // we couldn't learn anything
|
||||
Net_No, // no network connection [currently]
|
||||
Net_Connected // currently connected
|
||||
};
|
||||
|
||||
// the possible net connection types
|
||||
enum NetDeviceType
|
||||
{
|
||||
NetDevice_None = 0x0000, // no network devices (authoritative)
|
||||
NetDevice_Unknown = 0x0001, // test doesn't work on this OS
|
||||
NetDevice_Modem = 0x0002, // we have a modem
|
||||
NetDevice_LAN = 0x0004 // a network card
|
||||
};
|
||||
|
||||
private:
|
||||
// the current status
|
||||
NetConnection m_IsOnline;
|
||||
|
||||
// the connection we have with the network card
|
||||
NetConnection m_connCard;
|
||||
|
||||
// Can we use ifconfig to list active devices?
|
||||
int m_CanUseIfconfig;
|
||||
|
||||
// The path to ifconfig
|
||||
wxString m_IfconfigPath;
|
||||
|
||||
// Can we use ping to find hosts?
|
||||
int m_CanUsePing;
|
||||
// The path to ping program
|
||||
wxString m_PingPath;
|
||||
|
||||
// beacon host:
|
||||
wxString m_BeaconHost;
|
||||
// beacon host portnumber for connect:
|
||||
int m_BeaconPort;
|
||||
|
||||
// command to connect to network
|
||||
wxString m_ConnectCommand;
|
||||
// command to hang up
|
||||
wxString m_HangUpCommand;
|
||||
// name of ISP
|
||||
wxString m_ISPname;
|
||||
// a timer for regular testing
|
||||
class AutoCheckTimer *m_timer;
|
||||
friend class AutoCheckTimer;
|
||||
|
||||
// a wxProcess for dialling in background
|
||||
class wxDialProcess *m_DialProcess;
|
||||
// pid of dial process
|
||||
int m_DialPId;
|
||||
friend class wxDialProcess;
|
||||
|
||||
// determine status
|
||||
void CheckStatus(bool fromAsync = false) const;
|
||||
|
||||
// real status check
|
||||
void CheckStatusInternal();
|
||||
|
||||
// check /proc/net (Linux only) for ppp/eth interfaces, returns the bit
|
||||
// mask of NetDeviceType constants
|
||||
int CheckProcNet();
|
||||
|
||||
// check output of ifconfig command for PPP/SLIP/PLIP devices, returns the
|
||||
// bit mask of NetDeviceType constants
|
||||
int CheckIfconfig();
|
||||
|
||||
// combines the 2 possible checks for determining the connection status
|
||||
NetConnection CheckConnectAndPing();
|
||||
|
||||
// pings a host
|
||||
NetConnection CheckPing();
|
||||
|
||||
// check by connecting to host on given port.
|
||||
NetConnection CheckConnect();
|
||||
};
|
||||
|
||||
|
||||
class AutoCheckTimer : public wxTimer
|
||||
{
|
||||
public:
|
||||
AutoCheckTimer(wxDialUpManagerImpl *dupman)
|
||||
{
|
||||
m_dupman = dupman;
|
||||
}
|
||||
|
||||
virtual void Notify()
|
||||
{
|
||||
wxLogTrace(_T("dialup"), wxT("Checking dial up network status."));
|
||||
|
||||
m_dupman->CheckStatus();
|
||||
}
|
||||
|
||||
public:
|
||||
wxDialUpManagerImpl *m_dupman;
|
||||
};
|
||||
|
||||
class wxDialProcess : public wxProcess
|
||||
{
|
||||
public:
|
||||
wxDialProcess(wxDialUpManagerImpl *dupman)
|
||||
{
|
||||
m_DupMan = dupman;
|
||||
}
|
||||
void Disconnect() { m_DupMan = NULL; }
|
||||
virtual void OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
|
||||
{
|
||||
if(m_DupMan)
|
||||
{
|
||||
m_DupMan->m_DialProcess = NULL;
|
||||
m_DupMan->CheckStatus(true);
|
||||
}
|
||||
}
|
||||
private:
|
||||
wxDialUpManagerImpl *m_DupMan;
|
||||
};
|
||||
|
||||
|
||||
wxDialUpManagerImpl::wxDialUpManagerImpl()
|
||||
{
|
||||
m_IsOnline =
|
||||
m_connCard = Net_Unknown;
|
||||
m_DialProcess = NULL;
|
||||
m_timer = NULL;
|
||||
m_CanUseIfconfig = -1; // unknown
|
||||
m_CanUsePing = -1; // unknown
|
||||
m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
|
||||
m_BeaconPort = 80;
|
||||
|
||||
#ifdef __SGI__
|
||||
m_ConnectCommand = _T("/usr/etc/ppp");
|
||||
#elif defined(__LINUX__)
|
||||
// default values for Debian/GNU linux
|
||||
m_ConnectCommand = _T("pon");
|
||||
m_HangUpCommand = _T("poff");
|
||||
#endif
|
||||
|
||||
wxChar * dial = wxGetenv(_T("WXDIALUP_DIALCMD"));
|
||||
wxChar * hup = wxGetenv(_T("WXDIALUP_HUPCMD"));
|
||||
SetConnectCommand(dial ? wxString(dial) : m_ConnectCommand,
|
||||
hup ? wxString(hup) : m_HangUpCommand);
|
||||
}
|
||||
|
||||
wxDialUpManagerImpl::~wxDialUpManagerImpl()
|
||||
{
|
||||
if(m_timer) delete m_timer;
|
||||
if(m_DialProcess)
|
||||
{
|
||||
m_DialProcess->Disconnect();
|
||||
m_DialProcess->Detach();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
wxDialUpManagerImpl::Dial(const wxString &isp,
|
||||
const wxString & WXUNUSED(username),
|
||||
const wxString & WXUNUSED(password),
|
||||
bool async)
|
||||
{
|
||||
if(m_IsOnline == Net_Connected)
|
||||
return false;
|
||||
m_ISPname = isp;
|
||||
wxString cmd;
|
||||
if(m_ConnectCommand.Find(wxT("%s")))
|
||||
cmd.Printf(m_ConnectCommand,m_ISPname.c_str());
|
||||
else
|
||||
cmd = m_ConnectCommand;
|
||||
|
||||
if ( async )
|
||||
{
|
||||
m_DialProcess = new wxDialProcess(this);
|
||||
m_DialPId = (int)wxExecute(cmd, false, m_DialProcess);
|
||||
if(m_DialPId == 0)
|
||||
{
|
||||
delete m_DialProcess;
|
||||
m_DialProcess = NULL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return wxExecute(cmd, /* sync */ true) == 0;
|
||||
}
|
||||
|
||||
bool wxDialUpManagerImpl::HangUp()
|
||||
{
|
||||
if(m_IsOnline == Net_No)
|
||||
return false;
|
||||
if(IsDialing())
|
||||
{
|
||||
wxLogError(_("Already dialling ISP."));
|
||||
return false;
|
||||
}
|
||||
wxString cmd;
|
||||
if(m_HangUpCommand.Find(wxT("%s")))
|
||||
cmd.Printf(m_HangUpCommand,m_ISPname.c_str(), m_DialProcess);
|
||||
else
|
||||
cmd = m_HangUpCommand;
|
||||
return wxExecute(cmd, /* sync */ true) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool wxDialUpManagerImpl::CancelDialing()
|
||||
{
|
||||
if(! IsDialing())
|
||||
return false;
|
||||
return kill(m_DialPId, SIGTERM) > 0;
|
||||
}
|
||||
|
||||
bool wxDialUpManagerImpl::EnableAutoCheckOnlineStatus(size_t nSeconds)
|
||||
{
|
||||
DisableAutoCheckOnlineStatus();
|
||||
m_timer = new AutoCheckTimer(this);
|
||||
bool rc = m_timer->Start(nSeconds*1000);
|
||||
if(! rc)
|
||||
{
|
||||
delete m_timer;
|
||||
m_timer = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void wxDialUpManagerImpl::DisableAutoCheckOnlineStatus()
|
||||
{
|
||||
if(m_timer != NULL)
|
||||
{
|
||||
m_timer->Stop();
|
||||
delete m_timer;
|
||||
m_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxDialUpManagerImpl::SetWellKnownHost(const wxString& hostname, int portno)
|
||||
{
|
||||
if(hostname.length() == 0)
|
||||
{
|
||||
m_BeaconHost = WXDIALUP_MANAGER_DEFAULT_BEACONHOST;
|
||||
m_BeaconPort = 80;
|
||||
return;
|
||||
}
|
||||
|
||||
// does hostname contain a port number?
|
||||
wxString port = hostname.After(wxT(':'));
|
||||
if(port.length())
|
||||
{
|
||||
m_BeaconHost = hostname.Before(wxT(':'));
|
||||
m_BeaconPort = wxAtoi(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BeaconHost = hostname;
|
||||
m_BeaconPort = portno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxDialUpManagerImpl::CheckStatus(bool fromAsync) const
|
||||
{
|
||||
// This function calls the CheckStatusInternal() helper function
|
||||
// which is OS - specific and then sends the events.
|
||||
|
||||
NetConnection oldIsOnline = m_IsOnline;
|
||||
( /* non-const */ (wxDialUpManagerImpl *)this)->CheckStatusInternal();
|
||||
|
||||
// now send the events as appropriate: i.e. if the status changed and
|
||||
// if we're in defined state
|
||||
if(m_IsOnline != oldIsOnline
|
||||
&& m_IsOnline != Net_Unknown
|
||||
&& oldIsOnline != Net_Unknown )
|
||||
{
|
||||
wxDialUpEvent event(m_IsOnline == Net_Connected, ! fromAsync);
|
||||
(void)wxTheApp->ProcessEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
We first try to find out if ppp interface is active. If it is, we assume
|
||||
that we're online but don't have a permanent connection (this is false if a
|
||||
networked machine uses modem to connect to somewhere else, but we can't do
|
||||
anything in this case anyhow).
|
||||
|
||||
If no ppp interface is detected, we check for eth interface. If it is
|
||||
found, we check that we can, indeed, connect to an Internet host. The logic
|
||||
here is that connection check should be fast enough in this case and we
|
||||
don't want to give false positives in a (common) case of a machine on a LAN
|
||||
which is not connected to the outside.
|
||||
|
||||
If we didn't find either ppp or eth interfaces, we stop here and decide
|
||||
that we're connected. However, if couldn't check for this, we try to ping a
|
||||
remote host just in case.
|
||||
|
||||
NB1: Checking for the interface presence can be done in 2 ways
|
||||
a) reading /proc/net/dev under Linux
|
||||
b) spawning ifconfig under any OS
|
||||
|
||||
The first method is faster but only works under Linux.
|
||||
|
||||
NB2: pinging, actually, means that we first try to connect "manually" to
|
||||
a port on remove machine and if it fails, we run ping.
|
||||
*/
|
||||
|
||||
void wxDialUpManagerImpl::CheckStatusInternal()
|
||||
{
|
||||
m_IsOnline = Net_Unknown;
|
||||
|
||||
// first do quick checks to determine what kind of network devices do we
|
||||
// have
|
||||
int netDeviceType = CheckProcNet();
|
||||
if ( netDeviceType == NetDevice_Unknown )
|
||||
{
|
||||
// nothing found, try ifconfig too
|
||||
netDeviceType = CheckIfconfig();
|
||||
}
|
||||
|
||||
switch ( netDeviceType )
|
||||
{
|
||||
case NetDevice_None:
|
||||
// no network devices, no connection
|
||||
m_IsOnline = Net_No;
|
||||
break;
|
||||
|
||||
case NetDevice_LAN:
|
||||
// we still do ping to confirm that we're connected but we only do
|
||||
// it once and hope that the purpose of the network card (i.e.
|
||||
// whether it used for connecting to the Internet or just to a
|
||||
// LAN) won't change during the program lifetime
|
||||
if ( m_connCard == Net_Unknown )
|
||||
{
|
||||
m_connCard = CheckConnectAndPing();
|
||||
}
|
||||
m_IsOnline = m_connCard;
|
||||
break;
|
||||
|
||||
case NetDevice_Unknown:
|
||||
// try to ping just in case
|
||||
m_IsOnline = CheckConnectAndPing();
|
||||
break;
|
||||
|
||||
case NetDevice_LAN + NetDevice_Modem:
|
||||
case NetDevice_Modem:
|
||||
// assume we're connected
|
||||
m_IsOnline = Net_Connected;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG(_T("Unexpected netDeviceType"));
|
||||
}
|
||||
}
|
||||
|
||||
bool wxDialUpManagerImpl::IsAlwaysOnline() const
|
||||
{
|
||||
wxDialUpManagerImpl *self = wxConstCast(this, wxDialUpManagerImpl);
|
||||
|
||||
int netDeviceType = self->CheckProcNet();
|
||||
if ( netDeviceType == NetDevice_Unknown )
|
||||
{
|
||||
// nothing found, try ifconfig too
|
||||
netDeviceType = self->CheckIfconfig();
|
||||
}
|
||||
|
||||
if ( netDeviceType == NetDevice_Unknown )
|
||||
{
|
||||
// this is the only thing we can do unfortunately...
|
||||
self->HangUp();
|
||||
return IsOnline();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are only permanently online if we have a network card
|
||||
return (netDeviceType & NetDevice_LAN) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckConnectAndPing()
|
||||
{
|
||||
NetConnection conn;
|
||||
|
||||
// first try connecting - faster
|
||||
conn = CheckConnect();
|
||||
if ( conn == Net_Unknown )
|
||||
{
|
||||
// try pinging too
|
||||
conn = CheckPing();
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckConnect()
|
||||
{
|
||||
// second method: try to connect to a well known host:
|
||||
// This can be used under Win 9x, too!
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
if((hp = gethostbyname(m_BeaconHost.mb_str())) == NULL)
|
||||
return Net_No; // no DNS no net
|
||||
|
||||
serv_addr.sin_family = hp->h_addrtype;
|
||||
memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length);
|
||||
serv_addr.sin_port = htons(m_BeaconPort);
|
||||
|
||||
int sockfd;
|
||||
if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
return Net_Unknown; // no info
|
||||
}
|
||||
|
||||
if( connect(sockfd, (struct sockaddr *) &serv_addr,
|
||||
sizeof(serv_addr)) >= 0)
|
||||
{
|
||||
close(sockfd);
|
||||
return Net_Connected; // we can connect, so we have a network!
|
||||
}
|
||||
else // failed to connect
|
||||
{
|
||||
#ifdef ENETUNREACH
|
||||
if(errno == ENETUNREACH)
|
||||
return Net_No; // network is unreachable
|
||||
else
|
||||
#endif
|
||||
return Net_Unknown; // connect failed, but don't know why
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
wxDialUpManagerImpl::CheckProcNet()
|
||||
{
|
||||
// assume that the test doesn't work
|
||||
int netDevice = NetDevice_Unknown;
|
||||
|
||||
#ifdef __LINUX__
|
||||
if (wxFileExists(_T("/proc/net/route")))
|
||||
{
|
||||
// cannot use wxFile::Length because file doesn't support seeking, so
|
||||
// use stdio directly
|
||||
FILE *f = fopen("/proc/net/route", "rt");
|
||||
if (f != NULL)
|
||||
{
|
||||
// now we know that we will find all devices we may have
|
||||
netDevice = NetDevice_None;
|
||||
|
||||
char output[256];
|
||||
|
||||
while (fgets(output, 256, f) != NULL)
|
||||
{
|
||||
if ( strstr(output, "eth") ) // network card
|
||||
{
|
||||
netDevice |= NetDevice_LAN;
|
||||
}
|
||||
else if (strstr(output,"ppp") // ppp
|
||||
|| strstr(output,"sl") // slip
|
||||
|| strstr(output,"pl")) // plip
|
||||
{
|
||||
netDevice |= NetDevice_Modem;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
#endif // __LINUX__
|
||||
|
||||
return netDevice;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
wxDialUpManagerImpl::CheckIfconfig()
|
||||
{
|
||||
#ifdef __VMS
|
||||
m_CanUseIfconfig = 0;
|
||||
return -1;
|
||||
#else
|
||||
// assume that the test doesn't work
|
||||
int netDevice = NetDevice_Unknown;
|
||||
|
||||
// first time check for ifconfig location
|
||||
if ( m_CanUseIfconfig == -1 ) // unknown
|
||||
{
|
||||
static const wxChar *ifconfigLocations[] =
|
||||
{
|
||||
_T("/sbin"), // Linux, FreeBSD, Darwin
|
||||
_T("/usr/sbin"), // SunOS, Solaris, AIX, HP-UX
|
||||
_T("/usr/etc"), // IRIX
|
||||
_T("/etc"), // AIX 5
|
||||
};
|
||||
|
||||
for ( size_t n = 0; n < WXSIZEOF(ifconfigLocations); n++ )
|
||||
{
|
||||
wxString path(ifconfigLocations[n]);
|
||||
path << _T("/ifconfig");
|
||||
|
||||
if ( wxFileExists(path) )
|
||||
{
|
||||
m_IfconfigPath = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_CanUseIfconfig != 0 ) // unknown or yes
|
||||
{
|
||||
wxLogNull ln; // suppress all error messages
|
||||
|
||||
wxASSERT_MSG( m_IfconfigPath.length(),
|
||||
_T("can't use ifconfig if it wasn't found") );
|
||||
|
||||
wxString tmpfile = wxGetTempFileName( wxT("_wxdialuptest") );
|
||||
wxString cmd = wxT("/bin/sh -c \'");
|
||||
cmd << m_IfconfigPath;
|
||||
#if defined(__AIX__) || \
|
||||
defined(__OSF__) || \
|
||||
defined(__SOLARIS__) || defined (__SUNOS__)
|
||||
// need to add -a flag
|
||||
cmd << wxT(" -a");
|
||||
#elif defined(__LINUX__) || defined(__SGI__)
|
||||
// nothing to be added to ifconfig
|
||||
#elif defined(__FREEBSD__) || defined(__DARWIN__)
|
||||
// add -l flag
|
||||
cmd << wxT(" -l");
|
||||
#elif defined(__HPUX__)
|
||||
// VZ: a wild guess (but without it, ifconfig fails completely)
|
||||
cmd << wxT(" ppp0");
|
||||
#else
|
||||
#if defined(__GNUG__)
|
||||
#warning "No ifconfig information for this OS."
|
||||
#else
|
||||
#pragma warning "No ifconfig information for this OS."
|
||||
#endif
|
||||
|
||||
m_CanUseIfconfig = 0;
|
||||
return -1;
|
||||
#endif
|
||||
cmd << wxT(" >") << tmpfile << wxT('\'');
|
||||
/* I tried to add an option to wxExecute() to not close stdout,
|
||||
so we could let ifconfig write directly to the tmpfile, but
|
||||
this does not work. That should be faster, as it doesn´t call
|
||||
the shell first. I have no idea why. :-( (KB) */
|
||||
if ( wxExecute(cmd,true /* sync */) == 0 )
|
||||
{
|
||||
m_CanUseIfconfig = 1;
|
||||
wxFFile file;
|
||||
if( file.Open(tmpfile) )
|
||||
{
|
||||
wxString output;
|
||||
if ( file.ReadAll(&output) )
|
||||
{
|
||||
// FIXME shouldn't we grep for "^ppp"? (VZ)
|
||||
|
||||
bool hasModem = false,
|
||||
hasLAN = false;
|
||||
|
||||
#if defined(__SOLARIS__) || defined (__SUNOS__)
|
||||
// dialup device under SunOS/Solaris
|
||||
hasModem = strstr(output.fn_str(),"ipdptp") != (char *)NULL;
|
||||
hasLAN = strstr(output.fn_str(), "hme") != (char *)NULL;
|
||||
#elif defined(__LINUX__) || defined (__FREEBSD__)
|
||||
hasModem = strstr(output.fn_str(),"ppp") // ppp
|
||||
|| strstr(output.fn_str(),"sl") // slip
|
||||
|| strstr(output.fn_str(),"pl"); // plip
|
||||
hasLAN = strstr(output.fn_str(), "eth") != NULL;
|
||||
#elif defined(__SGI__) // IRIX
|
||||
hasModem = strstr(output.fn_str(), "ppp") != NULL; // PPP
|
||||
#elif defined(__HPUX__)
|
||||
// if could run ifconfig on interface, then it exists
|
||||
hasModem = true;
|
||||
#endif
|
||||
|
||||
netDevice = NetDevice_None;
|
||||
if ( hasModem )
|
||||
netDevice |= NetDevice_Modem;
|
||||
if ( hasLAN )
|
||||
netDevice |= NetDevice_LAN;
|
||||
}
|
||||
//else: error reading the file
|
||||
}
|
||||
//else: error opening the file
|
||||
}
|
||||
else // could not run ifconfig correctly
|
||||
{
|
||||
m_CanUseIfconfig = 0; // don´t try again
|
||||
}
|
||||
|
||||
(void) wxRemoveFile(tmpfile);
|
||||
}
|
||||
|
||||
return netDevice;
|
||||
#endif
|
||||
}
|
||||
|
||||
wxDialUpManagerImpl::NetConnection wxDialUpManagerImpl::CheckPing()
|
||||
{
|
||||
// First time check for ping location. We only use the variant
|
||||
// which does not take arguments, a la GNU.
|
||||
if(m_CanUsePing == -1) // unknown
|
||||
{
|
||||
#ifdef __VMS
|
||||
if (wxFileExists( wxT("SYS$SYSTEM:TCPIP$PING.EXE") ))
|
||||
m_PingPath = wxT("$SYS$SYSTEM:TCPIP$PING");
|
||||
#elif defined(__AIX__)
|
||||
m_PingPath = _T("/etc/ping");
|
||||
#elif defined(__SGI__)
|
||||
m_PingPath = _T("/usr/etc/ping");
|
||||
#else
|
||||
if (wxFileExists( wxT("/bin/ping") ))
|
||||
m_PingPath = wxT("/bin/ping");
|
||||
else if (wxFileExists( wxT("/usr/sbin/ping") ))
|
||||
m_PingPath = wxT("/usr/sbin/ping");
|
||||
#endif
|
||||
if (!m_PingPath)
|
||||
{
|
||||
m_CanUsePing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(! m_CanUsePing)
|
||||
{
|
||||
// we didn't find ping
|
||||
return Net_Unknown;
|
||||
}
|
||||
|
||||
wxLogNull ln; // suppress all error messages
|
||||
wxASSERT(m_PingPath.length());
|
||||
wxString cmd;
|
||||
cmd << m_PingPath << wxT(' ');
|
||||
#if defined(__SOLARIS__) || defined (__SUNOS__)
|
||||
// nothing to add to ping command
|
||||
#elif defined(__AIX__) || \
|
||||
defined (__BSD__) || \
|
||||
defined(__LINUX__) || \
|
||||
defined(__OSF__) || \
|
||||
defined(__SGI__) || \
|
||||
defined(__VMS)
|
||||
cmd << wxT("-c 1 "); // only ping once
|
||||
#elif defined(__HPUX__)
|
||||
cmd << wxT("64 1 "); // only ping once (need also specify the packet size)
|
||||
#else
|
||||
#if defined(__GNUG__)
|
||||
#warning "No Ping information for this OS."
|
||||
#else
|
||||
#pragma warning "No Ping information for this OS."
|
||||
#endif
|
||||
|
||||
m_CanUsePing = 0;
|
||||
return Net_Unknown;
|
||||
#endif
|
||||
cmd << m_BeaconHost;
|
||||
if(wxExecute(cmd, true /* sync */) == 0)
|
||||
return Net_Connected;
|
||||
else
|
||||
return Net_No;
|
||||
}
|
||||
|
||||
/* static */
|
||||
wxDialUpManager *wxDialUpManager::Create()
|
||||
{
|
||||
return new wxDialUpManagerImpl;
|
||||
}
|
||||
|
||||
#endif // wxUSE_DIALUP_MANAGER
|
334
wxWidgets/src/unix/dir.cpp
Normal file
334
wxWidgets/src/unix/dir.cpp
Normal file
|
@ -0,0 +1,334 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: unix/dir.cpp
|
||||
// Purpose: wxDir implementation for Unix/POSIX systems
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 08.12.99
|
||||
// RCS-ID: $Id: dir.cpp 56867 2008-11-20 18:12:43Z VZ $
|
||||
// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#endif // PCH
|
||||
|
||||
#include "wx/dir.h"
|
||||
#include "wx/filefn.h" // for wxMatchWild
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// macros
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define M_DIR ((wxDirData *)m_data)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private classes
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// this class stores everything we need to enumerate the files
|
||||
class wxDirData
|
||||
{
|
||||
public:
|
||||
wxDirData(const wxString& dirname);
|
||||
~wxDirData();
|
||||
|
||||
bool IsOk() const { return m_dir != NULL; }
|
||||
|
||||
void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
|
||||
void SetFlags(int flags) { m_flags = flags; }
|
||||
|
||||
void Rewind() { rewinddir(m_dir); }
|
||||
bool Read(wxString *filename);
|
||||
|
||||
const wxString& GetName() const { return m_dirname; }
|
||||
|
||||
private:
|
||||
DIR *m_dir;
|
||||
|
||||
wxString m_dirname;
|
||||
wxString m_filespec;
|
||||
|
||||
int m_flags;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDirData
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !defined( __VMS__ ) || ( __VMS_VER >= 70000000 )
|
||||
|
||||
wxDirData::wxDirData(const wxString& dirname)
|
||||
: m_dirname(dirname)
|
||||
{
|
||||
m_dir = NULL;
|
||||
|
||||
// throw away the trailing slashes
|
||||
size_t n = m_dirname.length();
|
||||
wxCHECK_RET( n, _T("empty dir name in wxDir") );
|
||||
|
||||
while ( n > 0 && m_dirname[--n] == '/' )
|
||||
;
|
||||
|
||||
m_dirname.Truncate(n + 1);
|
||||
|
||||
// do open the dir
|
||||
m_dir = opendir(m_dirname.fn_str());
|
||||
}
|
||||
|
||||
wxDirData::~wxDirData()
|
||||
{
|
||||
if ( m_dir )
|
||||
{
|
||||
if ( closedir(m_dir) != 0 )
|
||||
{
|
||||
wxLogLastError(_T("closedir"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wxDirData::Read(wxString *filename)
|
||||
{
|
||||
dirent *de = (dirent *)NULL; // just to silence compiler warnings
|
||||
bool matches = false;
|
||||
|
||||
// speed up string concatenation in the loop a bit
|
||||
wxString path = m_dirname;
|
||||
path += _T('/');
|
||||
path.reserve(path.length() + 255);
|
||||
|
||||
wxString de_d_name;
|
||||
|
||||
while ( !matches )
|
||||
{
|
||||
de = readdir(m_dir);
|
||||
if ( !de )
|
||||
return false;
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
de_d_name = wxConvFileName->cMB2WC( de->d_name );
|
||||
#else
|
||||
de_d_name = de->d_name;
|
||||
#endif
|
||||
|
||||
// don't return "." and ".." unless asked for
|
||||
if ( de->d_name[0] == '.' &&
|
||||
((de->d_name[1] == '.' && de->d_name[2] == '\0') ||
|
||||
(de->d_name[1] == '\0')) )
|
||||
{
|
||||
if ( !(m_flags & wxDIR_DOTDOT) )
|
||||
continue;
|
||||
|
||||
// we found a valid match
|
||||
break;
|
||||
}
|
||||
|
||||
// check the type now
|
||||
if ( !(m_flags & wxDIR_FILES) && !wxDir::Exists(path + de_d_name) )
|
||||
{
|
||||
// it's a file, but we don't want them
|
||||
continue;
|
||||
}
|
||||
else if ( !(m_flags & wxDIR_DIRS) && wxDir::Exists(path + de_d_name) )
|
||||
{
|
||||
// it's a dir, and we don't want it
|
||||
continue;
|
||||
}
|
||||
|
||||
// finally, check the name
|
||||
if ( m_filespec.empty() )
|
||||
{
|
||||
matches = m_flags & wxDIR_HIDDEN ? true : de->d_name[0] != '.';
|
||||
}
|
||||
else
|
||||
{
|
||||
// test against the pattern
|
||||
matches = wxMatchWild(m_filespec, de_d_name,
|
||||
!(m_flags & wxDIR_HIDDEN));
|
||||
}
|
||||
}
|
||||
|
||||
*filename = de_d_name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // old VMS (TODO)
|
||||
|
||||
wxDirData::wxDirData(const wxString& WXUNUSED(dirname))
|
||||
{
|
||||
wxFAIL_MSG(_T("not implemented"));
|
||||
}
|
||||
|
||||
wxDirData::~wxDirData()
|
||||
{
|
||||
}
|
||||
|
||||
bool wxDirData::Read(wxString * WXUNUSED(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // not or new VMS/old VMS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDir helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
bool wxDir::Exists(const wxString& dir)
|
||||
{
|
||||
return wxDirExists(dir);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDir construction/destruction
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxDir::wxDir(const wxString& dirname)
|
||||
{
|
||||
m_data = NULL;
|
||||
|
||||
(void)Open(dirname);
|
||||
}
|
||||
|
||||
bool wxDir::Open(const wxString& dirname)
|
||||
{
|
||||
delete M_DIR;
|
||||
m_data = new wxDirData(dirname);
|
||||
|
||||
if ( !M_DIR->IsOk() )
|
||||
{
|
||||
delete M_DIR;
|
||||
m_data = NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxDir::IsOpened() const
|
||||
{
|
||||
return m_data != NULL;
|
||||
}
|
||||
|
||||
wxString wxDir::GetName() const
|
||||
{
|
||||
wxString name;
|
||||
if ( m_data )
|
||||
{
|
||||
name = M_DIR->GetName();
|
||||
if ( !name.empty() && (name.Last() == _T('/')) )
|
||||
{
|
||||
// chop off the last (back)slash
|
||||
name.Truncate(name.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
wxDir::~wxDir()
|
||||
{
|
||||
delete M_DIR;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDir enumerating
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxDir::GetFirst(wxString *filename,
|
||||
const wxString& filespec,
|
||||
int flags) const
|
||||
{
|
||||
wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
|
||||
|
||||
M_DIR->Rewind();
|
||||
|
||||
M_DIR->SetFileSpec(filespec);
|
||||
M_DIR->SetFlags(flags);
|
||||
|
||||
return GetNext(filename);
|
||||
}
|
||||
|
||||
bool wxDir::GetNext(wxString *filename) const
|
||||
{
|
||||
wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
|
||||
|
||||
wxCHECK_MSG( filename, false, _T("bad pointer in wxDir::GetNext()") );
|
||||
|
||||
return M_DIR->Read(filename);
|
||||
}
|
||||
|
||||
bool wxDir::HasSubDirs(const wxString& spec)
|
||||
{
|
||||
wxCHECK_MSG( IsOpened(), false, _T("must wxDir::Open() first") );
|
||||
|
||||
if ( spec.empty() )
|
||||
{
|
||||
// faster check for presence of any subdirectory: normally each subdir
|
||||
// has a hard link to the parent directory and so, knowing that there
|
||||
// are at least "." and "..", we have a subdirectory if and only if
|
||||
// links number is > 2 - this is just a guess but it works fairly well
|
||||
// in practice
|
||||
//
|
||||
// note that we may guess wrongly in one direction only: i.e. we may
|
||||
// return true when there are no subdirectories but this is ok as the
|
||||
// caller will learn it soon enough when it calls GetFirst(wxDIR)
|
||||
// anyhow
|
||||
wxStructStat stBuf;
|
||||
if ( wxStat(M_DIR->GetName().c_str(), &stBuf) == 0 )
|
||||
{
|
||||
switch ( stBuf.st_nlink )
|
||||
{
|
||||
case 2:
|
||||
// just "." and ".."
|
||||
return false;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
// weird filesystem, don't try to guess for it, use dumb
|
||||
// method below
|
||||
break;
|
||||
|
||||
default:
|
||||
// assume we have subdirs - may turn out to be wrong if we
|
||||
// have other hard links to this directory but it's not
|
||||
// that bad as explained above
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just try to find first directory
|
||||
wxString s;
|
||||
return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
|
||||
}
|
||||
|
426
wxWidgets/src/unix/displayx11.cpp
Normal file
426
wxWidgets/src/unix/displayx11.cpp
Normal file
|
@ -0,0 +1,426 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/displayx11.cpp
|
||||
// Purpose: Unix/X11 implementation of wxDisplay class
|
||||
// Author: Brian Victor, Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 12/05/02
|
||||
// RCS-ID: $Id: displayx11.cpp 50143 2007-11-22 02:52:10Z PC $
|
||||
// Copyright: (c) wxWidgets team
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_DISPLAY
|
||||
|
||||
#include "wx/display.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/gdicmn.h"
|
||||
#include "wx/string.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#endif /* WX_PRECOMP */
|
||||
|
||||
#include "wx/display_impl.h"
|
||||
|
||||
/* These must be included after the wx files. Otherwise the Data macro in
|
||||
* Xlibint.h conflicts with a function declaration in wx/list.h. */
|
||||
extern "C"
|
||||
{
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlibint.h>
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||
#include <X11/extensions/xf86vmode.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// helper class to automatically free XineramaQueryScreens() return value
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ScreensInfo
|
||||
{
|
||||
public:
|
||||
ScreensInfo()
|
||||
{
|
||||
m_screens = XineramaQueryScreens((Display *)wxGetDisplay(), &m_num);
|
||||
}
|
||||
|
||||
~ScreensInfo()
|
||||
{
|
||||
XFree(m_screens);
|
||||
}
|
||||
|
||||
operator const XineramaScreenInfo *() const { return m_screens; }
|
||||
|
||||
unsigned GetCount() const { return wx_static_cast(unsigned, m_num); }
|
||||
|
||||
private:
|
||||
XineramaScreenInfo *m_screens;
|
||||
int m_num;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// display and display factory classes
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxDisplayImplX11 : public wxDisplayImpl
|
||||
{
|
||||
public:
|
||||
wxDisplayImplX11(unsigned n, const XineramaScreenInfo& info)
|
||||
: wxDisplayImpl(n),
|
||||
m_rect(info.x_org, info.y_org, info.width, info.height)
|
||||
{
|
||||
}
|
||||
|
||||
virtual wxRect GetGeometry() const { return m_rect; }
|
||||
virtual wxRect GetClientArea() const
|
||||
{
|
||||
// we intentionally don't cache the result here because the client
|
||||
// display area may change (e.g. the user resized or hid a panel) and
|
||||
// we don't currently react to its changes
|
||||
return IsPrimary() ? wxGetClientDisplayRect() : m_rect;
|
||||
}
|
||||
|
||||
virtual wxString GetName() const { return wxString(); }
|
||||
|
||||
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
|
||||
virtual wxVideoMode GetCurrentMode() const;
|
||||
virtual bool ChangeMode(const wxVideoMode& mode);
|
||||
|
||||
private:
|
||||
wxRect m_rect;
|
||||
int m_depth;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxDisplayImplX11)
|
||||
};
|
||||
|
||||
class wxDisplayFactoryX11 : public wxDisplayFactory
|
||||
{
|
||||
public:
|
||||
wxDisplayFactoryX11() { }
|
||||
|
||||
virtual wxDisplayImpl *CreateDisplay(unsigned n);
|
||||
virtual unsigned GetCount();
|
||||
virtual int GetFromPoint(const wxPoint& pt);
|
||||
|
||||
protected:
|
||||
DECLARE_NO_COPY_CLASS(wxDisplayFactoryX11)
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// wxDisplayFactoryX11 implementation
|
||||
// ============================================================================
|
||||
|
||||
unsigned wxDisplayFactoryX11::GetCount()
|
||||
{
|
||||
return ScreensInfo().GetCount();
|
||||
}
|
||||
|
||||
int wxDisplayFactoryX11::GetFromPoint(const wxPoint& p)
|
||||
{
|
||||
ScreensInfo screens;
|
||||
|
||||
const unsigned numscreens(screens.GetCount());
|
||||
for ( unsigned i = 0; i < numscreens; ++i )
|
||||
{
|
||||
const XineramaScreenInfo& s = screens[i];
|
||||
if ( p.x >= s.x_org && p.x < s.x_org + s.width &&
|
||||
p.y >= s.y_org && p.y < s.y_org + s.height )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
|
||||
wxDisplayImpl *wxDisplayFactoryX11::CreateDisplay(unsigned n)
|
||||
{
|
||||
ScreensInfo screens;
|
||||
|
||||
return n < screens.GetCount() ? new wxDisplayImplX11(n, screens[n]) : NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxDisplayImplX11 implementation
|
||||
// ============================================================================
|
||||
|
||||
#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||
|
||||
//
|
||||
// See (http://www.xfree86.org/4.2.0/XF86VidModeDeleteModeLine.3.html) for more
|
||||
// info about xf86 video mode extensions
|
||||
//
|
||||
|
||||
//free private data common to x (usually s3) servers
|
||||
#define wxClearXVM(vm) if(vm.privsize) XFree(vm.c_private)
|
||||
|
||||
// Correct res rate from GLFW
|
||||
#define wxCRR2(v,dc) (int) (((1000.0f * (float) dc) /*PIXELS PER SECOND */) / ((float) v.htotal * v.vtotal /*PIXELS PER FRAME*/) + 0.5f)
|
||||
#define wxCRR(v) wxCRR2(v,v.dotclock)
|
||||
#define wxCVM2(v, dc) wxVideoMode(v.hdisplay, v.vdisplay, DefaultDepth((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay())), wxCRR2(v,dc))
|
||||
#define wxCVM(v) wxCVM2(v, v.dotclock)
|
||||
|
||||
wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& mode) const
|
||||
{
|
||||
//Convenience...
|
||||
Display* pDisplay = (Display*) wxGetDisplay(); //default display
|
||||
int nScreen = DefaultScreen(pDisplay); //default screen of (default) display...
|
||||
|
||||
//Some variables..
|
||||
XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
|
||||
int nNumModes; //Number of modes enumerated....
|
||||
|
||||
wxArrayVideoModes Modes; //modes to return...
|
||||
|
||||
if (XF86VidModeGetAllModeLines(pDisplay, nScreen, &nNumModes, &ppXModes) == TRUE)
|
||||
{
|
||||
for (int i = 0; i < nNumModes; ++i)
|
||||
{
|
||||
if (mode == wxDefaultVideoMode || //According to display.h All modes valid if dafault mode...
|
||||
mode.Matches(wxCVM((*ppXModes[i]))) ) //...?
|
||||
{
|
||||
Modes.Add(wxCVM((*ppXModes[i])));
|
||||
}
|
||||
wxClearXVM((*ppXModes[i]));
|
||||
// XFree(ppXModes[i]); //supposed to free?
|
||||
}
|
||||
XFree(ppXModes);
|
||||
}
|
||||
else //OOPS!
|
||||
{
|
||||
wxLogSysError(_("Failed to enumerate video modes"));
|
||||
}
|
||||
|
||||
return Modes;
|
||||
}
|
||||
|
||||
wxVideoMode wxDisplayImplX11::GetCurrentMode() const
|
||||
{
|
||||
XF86VidModeModeLine VM;
|
||||
int nDotClock;
|
||||
XF86VidModeGetModeLine((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
|
||||
&nDotClock, &VM);
|
||||
wxClearXVM(VM);
|
||||
return wxCVM2(VM, nDotClock);
|
||||
}
|
||||
|
||||
bool wxDisplayImplX11::ChangeMode(const wxVideoMode& mode)
|
||||
{
|
||||
XF86VidModeModeInfo** ppXModes; //Enumerated Modes (Don't forget XFree() :))
|
||||
int nNumModes; //Number of modes enumerated....
|
||||
|
||||
if( !XF86VidModeGetAllModeLines((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()), &nNumModes, &ppXModes) )
|
||||
{
|
||||
wxLogSysError(_("Failed to change video mode"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bRet = false;
|
||||
if (mode == wxDefaultVideoMode)
|
||||
{
|
||||
bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
|
||||
ppXModes[0]) == TRUE;
|
||||
|
||||
for (int i = 0; i < nNumModes; ++i)
|
||||
{
|
||||
wxClearXVM((*ppXModes[i]));
|
||||
// XFree(ppXModes[i]); //supposed to free?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < nNumModes; ++i)
|
||||
{
|
||||
if (!bRet &&
|
||||
ppXModes[i]->hdisplay == mode.w &&
|
||||
ppXModes[i]->vdisplay == mode.h &&
|
||||
wxCRR((*ppXModes[i])) == mode.refresh)
|
||||
{
|
||||
//switch!
|
||||
bRet = XF86VidModeSwitchToMode((Display*)wxGetDisplay(), DefaultScreen((Display*)wxGetDisplay()),
|
||||
ppXModes[i]) == TRUE;
|
||||
}
|
||||
wxClearXVM((*ppXModes[i]));
|
||||
// XFree(ppXModes[i]); //supposed to free?
|
||||
}
|
||||
}
|
||||
|
||||
XFree(ppXModes);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
#else // !HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||
|
||||
wxArrayVideoModes wxDisplayImplX11::GetModes(const wxVideoMode& modeMatch) const
|
||||
{
|
||||
int count_return;
|
||||
int* depths = XListDepths((Display*)wxGetDisplay(), 0, &count_return);
|
||||
wxArrayVideoModes modes;
|
||||
if ( depths )
|
||||
{
|
||||
for ( int x = 0; x < count_return; ++x )
|
||||
{
|
||||
wxVideoMode mode(m_rect.GetWidth(), m_rect.GetHeight(), depths[x]);
|
||||
if ( mode.Matches(modeMatch) )
|
||||
{
|
||||
modes.Add(modeMatch);
|
||||
}
|
||||
}
|
||||
|
||||
XFree(depths);
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
wxVideoMode wxDisplayImplX11::GetCurrentMode() const
|
||||
{
|
||||
// Not implemented
|
||||
return wxVideoMode();
|
||||
}
|
||||
|
||||
bool wxDisplayImplX11::ChangeMode(const wxVideoMode& WXUNUSED(mode))
|
||||
{
|
||||
// Not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // !HAVE_X11_EXTENSIONS_XF86VMODE_H
|
||||
|
||||
// ============================================================================
|
||||
// wxDisplay::CreateFactory()
|
||||
// ============================================================================
|
||||
|
||||
/* static */ wxDisplayFactory *wxDisplay::CreateFactory()
|
||||
{
|
||||
if ( XineramaIsActive((Display*)wxGetDisplay()) )
|
||||
{
|
||||
return new wxDisplayFactoryX11;
|
||||
}
|
||||
|
||||
return new wxDisplayFactorySingle;
|
||||
}
|
||||
|
||||
#endif /* wxUSE_DISPLAY */
|
||||
|
||||
#if defined(__WXGTK__) || defined(__X__)
|
||||
|
||||
#include "wx/utils.h"
|
||||
#include "wx/log.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
// TODO: make this a full-fledged class and move to a public header
|
||||
class wxX11Ptr
|
||||
{
|
||||
public:
|
||||
wxX11Ptr(void *ptr = NULL) : m_ptr(ptr) { }
|
||||
~wxX11Ptr() { if ( m_ptr ) XFree(m_ptr); }
|
||||
|
||||
private:
|
||||
void *m_ptr;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxX11Ptr)
|
||||
};
|
||||
|
||||
// NB: this function is implemented using X11 and not GDK calls as it's shared
|
||||
// by wxGTK[12], wxX11 and wxMotif ports
|
||||
void wxClientDisplayRect(int *x, int *y, int *width, int *height)
|
||||
{
|
||||
Display * const dpy = (Display *)wxGetDisplay();
|
||||
wxCHECK_RET( dpy, _T("can't be called before initializing the GUI") );
|
||||
|
||||
const Atom atomWorkArea = XInternAtom(dpy, "_NET_WORKAREA", True);
|
||||
if ( atomWorkArea )
|
||||
{
|
||||
long *workareas = NULL;
|
||||
unsigned long numItems;
|
||||
unsigned long bytesRemaining;
|
||||
Atom actualType;
|
||||
int format;
|
||||
|
||||
if ( XGetWindowProperty
|
||||
(
|
||||
dpy,
|
||||
XDefaultRootWindow(dpy),
|
||||
atomWorkArea,
|
||||
0, // offset of data to retrieve
|
||||
4, // number of items to retrieve
|
||||
False, // don't delete property
|
||||
XA_CARDINAL, // type of the items to get
|
||||
&actualType,
|
||||
&format,
|
||||
&numItems,
|
||||
&bytesRemaining,
|
||||
(unsigned char **)&workareas
|
||||
) == Success && workareas )
|
||||
{
|
||||
wxX11Ptr x11ptr(workareas); // ensure it will be freed
|
||||
|
||||
// check that we retrieved the property of the expected type and
|
||||
// that we did get back 4 longs (32 is the format for long), as
|
||||
// requested
|
||||
if ( actualType != XA_CARDINAL ||
|
||||
format != 32 ||
|
||||
numItems != 4 )
|
||||
{
|
||||
wxLogDebug(_T("XGetWindowProperty(\"_NET_WORKAREA\") failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( x )
|
||||
*x = workareas[0];
|
||||
if ( y )
|
||||
*y = workareas[1];
|
||||
if ( width )
|
||||
*width = workareas[2];
|
||||
if ( height )
|
||||
*height = workareas[3];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if we get here, _NET_WORKAREA is not supported so return the entire
|
||||
// screen size as fall back
|
||||
if (x)
|
||||
*x = 0;
|
||||
if (y)
|
||||
*y = 0;
|
||||
wxDisplaySize(width, height);
|
||||
}
|
||||
|
||||
#else // !(wxGTK or X)
|
||||
|
||||
void wxClientDisplayRect(int *x, int *y, int *width, int *height)
|
||||
{
|
||||
if (x)
|
||||
*x = 0;
|
||||
if (y)
|
||||
*y = 0;
|
||||
wxDisplaySize(width, height);
|
||||
}
|
||||
|
||||
#endif // wxGTK or X
|
461
wxWidgets/src/unix/dlunix.cpp
Normal file
461
wxWidgets/src/unix/dlunix.cpp
Normal file
|
@ -0,0 +1,461 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: unix/dlunix.cpp
|
||||
// Purpose: Unix-specific part of wxDynamicLibrary and related classes
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2005-01-16 (extracted from common/dynlib.cpp)
|
||||
// RCS-ID: $Id: dlunix.cpp 51903 2008-02-19 01:13:48Z DE $
|
||||
// Copyright: (c) 2000-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_DYNLIB_CLASS
|
||||
|
||||
#include "wx/dynlib.h"
|
||||
#include "wx/ffile.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DARWIN__
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
// if some flags are not supported, just ignore them
|
||||
#ifndef RTLD_LAZY
|
||||
#define RTLD_LAZY 0
|
||||
#endif
|
||||
|
||||
#ifndef RTLD_NOW
|
||||
#define RTLD_NOW 0
|
||||
#endif
|
||||
|
||||
#ifndef RTLD_GLOBAL
|
||||
#define RTLD_GLOBAL 0
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_DLOPEN) || defined(__DARWIN__)
|
||||
#define USE_POSIX_DL_FUNCS
|
||||
#elif !defined(HAVE_SHL_LOAD)
|
||||
#error "Don't know how to load dynamic libraries on this platform!"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// standard shared libraries extensions for different Unix versions
|
||||
#if defined(__HPUX__)
|
||||
const wxChar *wxDynamicLibrary::ms_dllext = _T(".sl");
|
||||
#elif defined(__DARWIN__)
|
||||
const wxChar *wxDynamicLibrary::ms_dllext = _T(".bundle");
|
||||
#else
|
||||
const wxChar *wxDynamicLibrary::ms_dllext = _T(".so");
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// wxDynamicLibrary implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// dlxxx() emulation for Darwin
|
||||
// Only useful if the OS X version could be < 10.3 at runtime
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__DARWIN__) && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3)
|
||||
// ---------------------------------------------------------------------------
|
||||
// For Darwin/Mac OS X
|
||||
// supply the sun style dlopen functions in terms of Darwin NS*
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* Porting notes:
|
||||
* The dlopen port is a port from dl_next.xs by Anno Siegel.
|
||||
* dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
|
||||
* The method used here is just to supply the sun style dlopen etc.
|
||||
* functions in terms of Darwin NS*.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <mach-o/dyld.h>
|
||||
|
||||
static char dl_last_error[1024];
|
||||
|
||||
static const char *wx_darwin_dlerror()
|
||||
{
|
||||
return dl_last_error;
|
||||
}
|
||||
|
||||
static void *wx_darwin_dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */)
|
||||
{
|
||||
NSObjectFileImage ofile;
|
||||
NSModule handle = NULL;
|
||||
|
||||
unsigned dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
|
||||
if ( dyld_result != NSObjectFileImageSuccess )
|
||||
{
|
||||
handle = NULL;
|
||||
|
||||
static const char *errorStrings[] =
|
||||
{
|
||||
"%d: Object Image Load Failure",
|
||||
"%d: Object Image Load Success",
|
||||
"%d: Not an recognisable object file",
|
||||
"%d: No valid architecture",
|
||||
"%d: Object image has an invalid format",
|
||||
"%d: Invalid access (permissions?)",
|
||||
"%d: Unknown error code from NSCreateObjectFileImageFromFile"
|
||||
};
|
||||
|
||||
const int index = dyld_result < WXSIZEOF(errorStrings)
|
||||
? dyld_result
|
||||
: WXSIZEOF(errorStrings) - 1;
|
||||
|
||||
// this call to sprintf() is safe as strings above are fixed at
|
||||
// compile-time and are shorter than WXSIZEOF(dl_last_error)
|
||||
sprintf(dl_last_error, errorStrings[index], dyld_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = NSLinkModule
|
||||
(
|
||||
ofile,
|
||||
path,
|
||||
NSLINKMODULE_OPTION_BINDNOW |
|
||||
NSLINKMODULE_OPTION_RETURN_ON_ERROR
|
||||
);
|
||||
|
||||
if ( !handle )
|
||||
{
|
||||
NSLinkEditErrors err;
|
||||
int code;
|
||||
const char *filename;
|
||||
const char *errmsg;
|
||||
|
||||
NSLinkEditError(&err, &code, &filename, &errmsg);
|
||||
strncpy(dl_last_error, errmsg, WXSIZEOF(dl_last_error)-1);
|
||||
dl_last_error[WXSIZEOF(dl_last_error)-1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static int wx_darwin_dlclose(void *handle)
|
||||
{
|
||||
NSUnLinkModule((NSModule)handle, NSUNLINKMODULE_OPTION_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *wx_darwin_dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
// as on many other systems, C symbols have prepended underscores under
|
||||
// Darwin but unlike the normal dlopen(), NSLookupSymbolInModule() is not
|
||||
// aware of this
|
||||
wxCharBuffer buf(strlen(symbol) + 1);
|
||||
char *p = buf.data();
|
||||
p[0] = '_';
|
||||
strcpy(p + 1, symbol);
|
||||
|
||||
NSSymbol nsSymbol = NSLookupSymbolInModule((NSModule)handle, p );
|
||||
return nsSymbol ? NSAddressOfSymbol(nsSymbol) : NULL;
|
||||
}
|
||||
|
||||
// Add the weak linking attribute to dlopen's declaration
|
||||
extern void * dlopen(const char * __path, int __mode) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
|
||||
|
||||
// For all of these methods we test dlopen since all of the dl functions we use were added
|
||||
// to OS X at the same time. This also ensures we don't dlopen with the real function then
|
||||
// dlclose with the internal implementation.
|
||||
|
||||
static inline void *wx_dlopen(const char *__path, int __mode)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
if(&dlopen != NULL)
|
||||
return dlopen(__path, __mode);
|
||||
else
|
||||
#endif
|
||||
return wx_darwin_dlopen(__path, __mode);
|
||||
}
|
||||
|
||||
static inline int wx_dlclose(void *__handle)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
if(&dlopen != NULL)
|
||||
return dlclose(__handle);
|
||||
else
|
||||
#endif
|
||||
return wx_darwin_dlclose(__handle);
|
||||
}
|
||||
|
||||
static inline const char *wx_dlerror()
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
if(&dlopen != NULL)
|
||||
return dlerror();
|
||||
else
|
||||
#endif
|
||||
return wx_darwin_dlerror();
|
||||
}
|
||||
|
||||
static inline void *wx_dlsym(void *__handle, const char *__symbol)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
if(&dlopen != NULL)
|
||||
return dlsym(__handle, __symbol);
|
||||
else
|
||||
#endif
|
||||
return wx_darwin_dlsym(__handle, __symbol);
|
||||
}
|
||||
|
||||
#else // __DARWIN__/!__DARWIN__
|
||||
|
||||
// Use preprocessor definitions for non-Darwin or OS X >= 10.3
|
||||
#define wx_dlopen(__path,__mode) dlopen(__path,__mode)
|
||||
#define wx_dlclose(__handle) dlclose(__handle)
|
||||
#define wx_dlerror() dlerror()
|
||||
#define wx_dlsym(__handle,__symbol) dlsym(__handle,__symbol)
|
||||
|
||||
#endif // defined(__DARWIN__)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// loading/unloading DLLs
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxDllType wxDynamicLibrary::GetProgramHandle()
|
||||
{
|
||||
#ifdef USE_POSIX_DL_FUNCS
|
||||
return wx_dlopen(0, RTLD_LAZY);
|
||||
#else
|
||||
return PROG_HANDLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */
|
||||
wxDllType wxDynamicLibrary::RawLoad(const wxString& libname, int flags)
|
||||
{
|
||||
wxASSERT_MSG( !(flags & wxDL_NOW) || !(flags & wxDL_LAZY),
|
||||
_T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
|
||||
|
||||
#ifdef USE_POSIX_DL_FUNCS
|
||||
// we need to use either RTLD_NOW or RTLD_LAZY because if we call dlopen()
|
||||
// with flags == 0 recent versions of glibc just fail the call, so use
|
||||
// RTLD_NOW even if wxDL_NOW was not specified
|
||||
int rtldFlags = flags & wxDL_LAZY ? RTLD_LAZY : RTLD_NOW;
|
||||
|
||||
if ( flags & wxDL_GLOBAL )
|
||||
rtldFlags |= RTLD_GLOBAL;
|
||||
|
||||
return wx_dlopen(libname.fn_str(), rtldFlags);
|
||||
#else // !USE_POSIX_DL_FUNCS
|
||||
int shlFlags = 0;
|
||||
|
||||
if ( flags & wxDL_LAZY )
|
||||
{
|
||||
shlFlags |= BIND_DEFERRED;
|
||||
}
|
||||
else if ( flags & wxDL_NOW )
|
||||
{
|
||||
shlFlags |= BIND_IMMEDIATE;
|
||||
}
|
||||
|
||||
return shl_load(libname.fn_str(), shlFlags, 0);
|
||||
#endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
|
||||
}
|
||||
|
||||
/* static */
|
||||
void wxDynamicLibrary::Unload(wxDllType handle)
|
||||
{
|
||||
#ifdef wxHAVE_DYNLIB_ERROR
|
||||
int rc =
|
||||
#endif
|
||||
|
||||
#ifdef USE_POSIX_DL_FUNCS
|
||||
wx_dlclose(handle);
|
||||
#else // !USE_POSIX_DL_FUNCS
|
||||
shl_unload(handle);
|
||||
#endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
|
||||
|
||||
#if defined(USE_POSIX_DL_FUNCS) && defined(wxHAVE_DYNLIB_ERROR)
|
||||
if ( rc != 0 )
|
||||
Error();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */
|
||||
void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
|
||||
{
|
||||
void *symbol;
|
||||
|
||||
#ifdef USE_POSIX_DL_FUNCS
|
||||
symbol = wx_dlsym(handle, name.fn_str());
|
||||
#else // !USE_POSIX_DL_FUNCS
|
||||
// note that shl_findsym modifies the handle argument to indicate where the
|
||||
// symbol was found, but it's ok to modify the local handle copy here
|
||||
if ( shl_findsym(&handle, name.fn_str(), TYPE_UNDEFINED, &symbol) != 0 )
|
||||
symbol = 0;
|
||||
#endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// error handling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef wxHAVE_DYNLIB_ERROR
|
||||
|
||||
/* static */
|
||||
void wxDynamicLibrary::Error()
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
wxWCharBuffer buffer = wxConvLocal.cMB2WC( wx_dlerror() );
|
||||
const wxChar *err = buffer;
|
||||
#else
|
||||
const wxChar *err = wx_dlerror();
|
||||
#endif
|
||||
|
||||
wxLogError(wxT("%s"), err ? err : _("Unknown dynamic library error"));
|
||||
}
|
||||
|
||||
#endif // wxHAVE_DYNLIB_ERROR
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// listing loaded modules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// wxDynamicLibraryDetails declares this class as its friend, so put the code
|
||||
// initializing new details objects here
|
||||
class wxDynamicLibraryDetailsCreator
|
||||
{
|
||||
public:
|
||||
// create a new wxDynamicLibraryDetails from the given data
|
||||
static wxDynamicLibraryDetails *
|
||||
New(void *start, void *end, const wxString& path)
|
||||
{
|
||||
wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails;
|
||||
details->m_path = path;
|
||||
details->m_name = path.AfterLast(_T('/'));
|
||||
details->m_address = start;
|
||||
details->m_length = (char *)end - (char *)start;
|
||||
|
||||
// try to extract the library version from its name
|
||||
const size_t posExt = path.rfind(_T(".so"));
|
||||
if ( posExt != wxString::npos )
|
||||
{
|
||||
if ( path.c_str()[posExt + 3] == _T('.') )
|
||||
{
|
||||
// assume "libfoo.so.x.y.z" case
|
||||
details->m_version.assign(path, posExt + 4, wxString::npos);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t posDash = path.find_last_of(_T('-'), posExt);
|
||||
if ( posDash != wxString::npos )
|
||||
{
|
||||
// assume "libbar-x.y.z.so" case
|
||||
posDash++;
|
||||
details->m_version.assign(path, posDash, posExt - posDash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return details;
|
||||
}
|
||||
};
|
||||
|
||||
/* static */
|
||||
wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
|
||||
{
|
||||
wxDynamicLibraryDetailsArray dlls;
|
||||
|
||||
#ifdef __LINUX__
|
||||
// examine /proc/self/maps to find out what is loaded in our address space
|
||||
wxFFile file(_T("/proc/self/maps"));
|
||||
if ( file.IsOpened() )
|
||||
{
|
||||
// details of the module currently being parsed
|
||||
wxString pathCur;
|
||||
void *startCur = NULL,
|
||||
*endCur = NULL;
|
||||
|
||||
char path[1024];
|
||||
char buf[1024];
|
||||
while ( fgets(buf, WXSIZEOF(buf), file.fp()) )
|
||||
{
|
||||
// format is: "start-end perm offset maj:min inode path", see proc(5)
|
||||
void *start,
|
||||
*end;
|
||||
switch ( sscanf(buf, "%p-%p %*4s %*p %*02x:%*02x %*d %1024s\n",
|
||||
&start, &end, path) )
|
||||
{
|
||||
case 2:
|
||||
// there may be no path column
|
||||
path[0] = '\0';
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// nothing to do, read everything we wanted
|
||||
break;
|
||||
|
||||
default:
|
||||
// chop '\n'
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
wxLogDebug(_T("Failed to parse line \"%s\" in /proc/self/maps."),
|
||||
buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( start >= endCur,
|
||||
_T("overlapping regions in /proc/self/maps?") );
|
||||
|
||||
wxString pathNew = wxString::FromAscii(path);
|
||||
if ( pathCur.empty() )
|
||||
{
|
||||
// new module start
|
||||
pathCur = pathNew;
|
||||
startCur = start;
|
||||
endCur = end;
|
||||
}
|
||||
else if ( pathCur == pathNew && endCur == end )
|
||||
{
|
||||
// continuation of the same module in the address space
|
||||
endCur = end;
|
||||
}
|
||||
else // end of the current module
|
||||
{
|
||||
dlls.Add(wxDynamicLibraryDetailsCreator::New(startCur,
|
||||
endCur,
|
||||
pathCur));
|
||||
pathCur.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // __LINUX__
|
||||
|
||||
return dlls;
|
||||
}
|
||||
|
||||
#endif // wxUSE_DYNLIB_CLASS
|
||||
|
362
wxWidgets/src/unix/fontenum.cpp
Normal file
362
wxWidgets/src/unix/fontenum.cpp
Normal file
|
@ -0,0 +1,362 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/fontenum.cpp
|
||||
// Purpose: wxFontEnumerator class for X11/GDK
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 01.10.99
|
||||
// RCS-ID: $Id: fontenum.cpp 43727 2006-12-01 10:14:28Z VS $
|
||||
// Copyright: (c) Vadim Zeitlin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include "wx/fontenum.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/string.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/utils.h"
|
||||
#endif
|
||||
|
||||
#include "wx/regex.h"
|
||||
#include "wx/fontmap.h"
|
||||
#include "wx/fontutil.h"
|
||||
#include "wx/encinfo.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Pango
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_PANGO
|
||||
|
||||
#include "pango/pango.h"
|
||||
|
||||
#ifdef __WXGTK20__
|
||||
#include "gtk/gtk.h"
|
||||
extern GtkWidget *wxGetRootWindow();
|
||||
#endif // __WXGTK20__
|
||||
|
||||
extern "C" int wxCMPFUNC_CONV
|
||||
wxCompareFamilies (const void *a, const void *b)
|
||||
{
|
||||
const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
|
||||
const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
|
||||
|
||||
return g_utf8_collate (a_name, b_name);
|
||||
}
|
||||
|
||||
bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
|
||||
bool fixedWidthOnly)
|
||||
{
|
||||
if ( encoding != wxFONTENCODING_SYSTEM && encoding != wxFONTENCODING_UTF8 )
|
||||
{
|
||||
// Pango supports only UTF-8 encoding (and system means any, so we
|
||||
// accept it too)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(__WXGTK20__) || !defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
|
||||
if ( fixedWidthOnly
|
||||
#if defined(__WXGTK24__)
|
||||
&& (gtk_check_version(2,4,0) != NULL)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
OnFacename( wxT("monospace") );
|
||||
}
|
||||
else // !fixedWidthOnly
|
||||
#endif // __WXGTK20__ || !HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
|
||||
{
|
||||
PangoFontFamily **families = NULL;
|
||||
gint n_families = 0;
|
||||
pango_context_list_families (
|
||||
#ifdef __WXGTK20__
|
||||
gtk_widget_get_pango_context( wxGetRootWindow() ),
|
||||
#else
|
||||
wxTheApp->GetPangoContext(),
|
||||
#endif
|
||||
&families, &n_families );
|
||||
qsort (families, n_families, sizeof (PangoFontFamily *), wxCompareFamilies);
|
||||
|
||||
for (int i=0; i<n_families; i++)
|
||||
{
|
||||
#if defined(__WXGTK24__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
|
||||
if (!fixedWidthOnly || (
|
||||
#ifdef __WXGTK24__
|
||||
!gtk_check_version(2,4,0) &&
|
||||
#endif
|
||||
pango_font_family_is_monospace(families[i])
|
||||
) )
|
||||
#endif
|
||||
{
|
||||
const gchar *name = pango_font_family_get_name(families[i]);
|
||||
OnFacename(wxString(name, wxConvUTF8));
|
||||
}
|
||||
}
|
||||
g_free(families);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxFontEnumerator::EnumerateEncodings(const wxString& facename)
|
||||
{
|
||||
return EnumerateEncodingsUTF8(facename);
|
||||
}
|
||||
|
||||
|
||||
#else // !wxUSE_PANGO
|
||||
|
||||
#ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++
|
||||
// The resulting warnings are switched off here
|
||||
#pragma message disable nosimpint
|
||||
#endif
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef __VMS__
|
||||
#pragma message enable nosimpint
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// create the list of all fonts with the given spacing and encoding
|
||||
static char **CreateFontList(wxChar spacing, wxFontEncoding encoding,
|
||||
int *nFonts);
|
||||
|
||||
// extract all font families from the given font list and call our
|
||||
// OnFacename() for each of them
|
||||
static bool ProcessFamiliesFromFontList(wxFontEnumerator *This,
|
||||
char **fonts,
|
||||
int nFonts);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private types
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !wxUSE_NANOX
|
||||
static char **CreateFontList(wxChar spacing,
|
||||
wxFontEncoding encoding,
|
||||
int *nFonts)
|
||||
{
|
||||
wxNativeEncodingInfo info;
|
||||
wxGetNativeFontEncoding(encoding, &info);
|
||||
|
||||
#if wxUSE_FONTMAP
|
||||
if ( !wxTestFontEncoding(info) )
|
||||
{
|
||||
// ask font mapper for a replacement
|
||||
(void)wxFontMapper::Get()->GetAltForEncoding(encoding, &info);
|
||||
}
|
||||
#endif // wxUSE_FONTMAP
|
||||
|
||||
wxString pattern;
|
||||
pattern.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-%c-*-%s-%s"),
|
||||
spacing,
|
||||
info.xregistry.c_str(),
|
||||
info.xencoding.c_str());
|
||||
|
||||
// get the list of all fonts
|
||||
return XListFonts((Display *)wxGetDisplay(), pattern.mb_str(), 32767, nFonts);
|
||||
}
|
||||
|
||||
static bool ProcessFamiliesFromFontList(wxFontEnumerator *This,
|
||||
char **fonts,
|
||||
int nFonts)
|
||||
{
|
||||
#if wxUSE_REGEX
|
||||
wxRegEx re(wxT("^(-[^-]*){14}$"), wxRE_NOSUB);
|
||||
#endif // wxUSE_REGEX
|
||||
|
||||
// extract the list of (unique) font families
|
||||
wxSortedArrayString families;
|
||||
for ( int n = 0; n < nFonts; n++ )
|
||||
{
|
||||
char *font = fonts[n];
|
||||
#if wxUSE_REGEX
|
||||
if ( !re.Matches(font) )
|
||||
#else // !wxUSE_REGEX
|
||||
if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
|
||||
#endif // wxUSE_REGEX/!wxUSE_REGEX
|
||||
{
|
||||
// it's not a full font name (probably an alias)
|
||||
continue;
|
||||
}
|
||||
|
||||
// coverity[returned_null]
|
||||
char *dash = strchr(font + 1, '-');
|
||||
char *family = dash + 1;
|
||||
dash = strchr(family, '-');
|
||||
*dash = '\0'; // !NULL because Matches() above succeeded
|
||||
wxString fam(family);
|
||||
|
||||
if ( families.Index(fam) == wxNOT_FOUND )
|
||||
{
|
||||
if ( !This->OnFacename(fam) )
|
||||
{
|
||||
// stop enumerating
|
||||
return false;
|
||||
}
|
||||
|
||||
families.Add(fam);
|
||||
}
|
||||
//else: already seen
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
// wxUSE_NANOX
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxFontEnumerator
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
|
||||
bool fixedWidthOnly)
|
||||
{
|
||||
#if wxUSE_NANOX
|
||||
return false;
|
||||
#else
|
||||
int nFonts;
|
||||
char **fonts;
|
||||
|
||||
if ( fixedWidthOnly )
|
||||
{
|
||||
bool cont = true;
|
||||
fonts = CreateFontList(wxT('m'), encoding, &nFonts);
|
||||
if ( fonts )
|
||||
{
|
||||
cont = ProcessFamiliesFromFontList(this, fonts, nFonts);
|
||||
|
||||
XFreeFontNames(fonts);
|
||||
}
|
||||
|
||||
if ( !cont )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
fonts = CreateFontList(wxT('c'), encoding, &nFonts);
|
||||
if ( !fonts )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fonts = CreateFontList(wxT('*'), encoding, &nFonts);
|
||||
|
||||
if ( !fonts )
|
||||
{
|
||||
// it's ok if there are no fonts in given encoding - but it's not
|
||||
// ok if there are no fonts at all
|
||||
wxASSERT_MSG(encoding != wxFONTENCODING_SYSTEM,
|
||||
wxT("No fonts at all on this system?"));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
(void)ProcessFamiliesFromFontList(this, fonts, nFonts);
|
||||
|
||||
XFreeFontNames(fonts);
|
||||
return true;
|
||||
#endif
|
||||
// wxUSE_NANOX
|
||||
}
|
||||
|
||||
bool wxFontEnumerator::EnumerateEncodings(const wxString& family)
|
||||
{
|
||||
#if wxUSE_NANOX
|
||||
return false;
|
||||
#else
|
||||
wxString pattern;
|
||||
pattern.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-*-*"),
|
||||
family.empty() ? wxT("*") : family.c_str());
|
||||
|
||||
// get the list of all fonts
|
||||
int nFonts;
|
||||
char **fonts = XListFonts((Display *)wxGetDisplay(), pattern.mb_str(),
|
||||
32767, &nFonts);
|
||||
|
||||
if ( !fonts )
|
||||
{
|
||||
// unknown family?
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract the list of (unique) encodings
|
||||
wxSortedArrayString encodings;
|
||||
for ( int n = 0; n < nFonts; n++ )
|
||||
{
|
||||
char *font = fonts[n];
|
||||
if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
|
||||
{
|
||||
// it's not a full font name (probably an alias)
|
||||
continue;
|
||||
}
|
||||
|
||||
// extract the family
|
||||
char *dash = strchr(font + 1, '-');
|
||||
char *familyFont = dash + 1;
|
||||
dash = strchr(familyFont, '-');
|
||||
*dash = '\0'; // !NULL because Matches() above succeeded
|
||||
|
||||
if ( !family.empty() && (family != familyFont) )
|
||||
{
|
||||
// family doesn't match
|
||||
continue;
|
||||
}
|
||||
|
||||
// now extract the registry/encoding
|
||||
char *p = dash + 1; // just after the dash after family
|
||||
dash = strrchr(p, '-');
|
||||
|
||||
wxString registry(dash + 1);
|
||||
*dash = '\0';
|
||||
|
||||
dash = strrchr(p, '-');
|
||||
wxString encoding(dash + 1);
|
||||
|
||||
encoding << wxT('-') << registry;
|
||||
if ( encodings.Index(encoding) == wxNOT_FOUND )
|
||||
{
|
||||
if ( !OnFontEncoding(familyFont, encoding) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
encodings.Add(encoding);
|
||||
}
|
||||
//else: already had this one
|
||||
}
|
||||
|
||||
XFreeFontNames(fonts);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
// wxUSE_NANOX
|
||||
}
|
||||
|
||||
#endif // !wxUSE_PANGO
|
1441
wxWidgets/src/unix/fontutil.cpp
Normal file
1441
wxWidgets/src/unix/fontutil.cpp
Normal file
File diff suppressed because it is too large
Load diff
2299
wxWidgets/src/unix/gsocket.cpp
Normal file
2299
wxWidgets/src/unix/gsocket.cpp
Normal file
File diff suppressed because it is too large
Load diff
496
wxWidgets/src/unix/joystick.cpp
Normal file
496
wxWidgets/src/unix/joystick.cpp
Normal file
|
@ -0,0 +1,496 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/joystick.cpp
|
||||
// Purpose: wxJoystick class
|
||||
// Author: Ported to Linux by Guilhem Lavaux
|
||||
// Modified by:
|
||||
// Created: 05/23/98
|
||||
// RCS-ID: $Id: joystick.cpp 40530 2006-08-09 11:18:24Z MW $
|
||||
// Copyright: (c) Guilhem Lavaux
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if wxUSE_JOYSTICK
|
||||
|
||||
#include "wx/joystick.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/event.h"
|
||||
#include "wx/window.h"
|
||||
#endif //WX_PRECOMP
|
||||
|
||||
#include <linux/joystick.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "wx/unix/private.h"
|
||||
|
||||
enum {
|
||||
wxJS_AXIS_X = 0,
|
||||
wxJS_AXIS_Y,
|
||||
wxJS_AXIS_Z,
|
||||
wxJS_AXIS_RUDDER,
|
||||
wxJS_AXIS_U,
|
||||
wxJS_AXIS_V,
|
||||
|
||||
wxJS_AXIS_MAX = 32767,
|
||||
wxJS_AXIS_MIN = -32767
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxJoystick, wxObject)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Background thread for reading the joystick device
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class wxJoystickThread : public wxThread
|
||||
{
|
||||
public:
|
||||
wxJoystickThread(int device, int joystick);
|
||||
void* Entry();
|
||||
|
||||
private:
|
||||
int m_device;
|
||||
int m_joystick;
|
||||
wxPoint m_lastposition;
|
||||
int m_axe[15];
|
||||
int m_buttons;
|
||||
wxWindow* m_catchwin;
|
||||
int m_polling;
|
||||
|
||||
friend class wxJoystick;
|
||||
};
|
||||
|
||||
|
||||
wxJoystickThread::wxJoystickThread(int device, int joystick)
|
||||
: m_device(device),
|
||||
m_joystick(joystick),
|
||||
m_lastposition(wxDefaultPosition),
|
||||
m_buttons(0),
|
||||
m_catchwin(NULL),
|
||||
m_polling(0)
|
||||
{
|
||||
for (int i=0; i<15; i++)
|
||||
m_axe[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
void* wxJoystickThread::Entry()
|
||||
{
|
||||
struct js_event j_evt;
|
||||
fd_set read_fds;
|
||||
struct timeval time_out = {0, 0};
|
||||
|
||||
wxFD_ZERO(&read_fds);
|
||||
while (true)
|
||||
{
|
||||
if (TestDestroy())
|
||||
break;
|
||||
|
||||
// We use select when either polling or 'blocking' as even in the
|
||||
// blocking case we need to check TestDestroy periodically
|
||||
if (m_polling)
|
||||
time_out.tv_usec = m_polling * 1000;
|
||||
else
|
||||
time_out.tv_usec = 10 * 1000; // check at least every 10 msec in blocking case
|
||||
|
||||
wxFD_SET(m_device, &read_fds);
|
||||
select(m_device+1, &read_fds, NULL, NULL, &time_out);
|
||||
if (wxFD_ISSET(m_device, &read_fds))
|
||||
{
|
||||
memset(&j_evt, 0, sizeof(j_evt));
|
||||
read(m_device, &j_evt, sizeof(j_evt));
|
||||
|
||||
//printf("time: %d\t value: %d\t type: %d\t number: %d\n",
|
||||
// j_evt.time, j_evt.value, j_evt.type, j_evt.number);
|
||||
|
||||
wxJoystickEvent jwx_event;
|
||||
|
||||
if (j_evt.type & JS_EVENT_AXIS)
|
||||
{
|
||||
m_axe[j_evt.number] = j_evt.value;
|
||||
|
||||
switch (j_evt.number)
|
||||
{
|
||||
case wxJS_AXIS_X:
|
||||
m_lastposition.x = j_evt.value;
|
||||
jwx_event.SetEventType(wxEVT_JOY_MOVE);
|
||||
break;
|
||||
case wxJS_AXIS_Y:
|
||||
m_lastposition.y = j_evt.value;
|
||||
jwx_event.SetEventType(wxEVT_JOY_MOVE);
|
||||
break;
|
||||
case wxJS_AXIS_Z:
|
||||
jwx_event.SetEventType(wxEVT_JOY_ZMOVE);
|
||||
break;
|
||||
default:
|
||||
jwx_event.SetEventType(wxEVT_JOY_MOVE);
|
||||
// TODO: There should be a way to indicate that the event
|
||||
// is for some other axes.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j_evt.type & JS_EVENT_BUTTON)
|
||||
{
|
||||
if (j_evt.value)
|
||||
{
|
||||
m_buttons |= (1 << j_evt.number);
|
||||
jwx_event.SetEventType(wxEVT_JOY_BUTTON_DOWN);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buttons &= ~(1 << j_evt.number);
|
||||
jwx_event.SetEventType(wxEVT_JOY_BUTTON_UP);
|
||||
}
|
||||
|
||||
jwx_event.SetButtonChange(j_evt.number);
|
||||
|
||||
jwx_event.SetTimestamp(j_evt.time);
|
||||
jwx_event.SetJoystick(m_joystick);
|
||||
jwx_event.SetButtonState(m_buttons);
|
||||
jwx_event.SetPosition(m_lastposition);
|
||||
jwx_event.SetZPosition(m_axe[3]);
|
||||
jwx_event.SetEventObject(m_catchwin);
|
||||
|
||||
if (m_catchwin)
|
||||
m_catchwin->AddPendingEvent(jwx_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(m_device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxJoystick::wxJoystick(int joystick)
|
||||
: m_device(-1),
|
||||
m_joystick(joystick),
|
||||
m_thread(NULL)
|
||||
{
|
||||
wxString dev_name;
|
||||
|
||||
// old /dev structure
|
||||
dev_name.Printf( wxT("/dev/js%d"), joystick);
|
||||
m_device = open(dev_name.fn_str(), O_RDONLY);
|
||||
|
||||
// new /dev structure with "input" subdirectory
|
||||
if (m_device == -1)
|
||||
{
|
||||
dev_name.Printf( wxT("/dev/input/js%d"), joystick);
|
||||
m_device = open(dev_name.fn_str(), O_RDONLY);
|
||||
}
|
||||
|
||||
if (m_device != -1)
|
||||
{
|
||||
m_thread = new wxJoystickThread(m_device, m_joystick);
|
||||
m_thread->Create();
|
||||
m_thread->Run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxJoystick::~wxJoystick()
|
||||
{
|
||||
ReleaseCapture();
|
||||
if (m_thread)
|
||||
m_thread->Delete(); // It's detached so it will delete itself
|
||||
m_device = -1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// State
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxPoint wxJoystick::GetPosition() const
|
||||
{
|
||||
wxPoint pos(wxDefaultPosition);
|
||||
if (m_thread) pos = m_thread->m_lastposition;
|
||||
return pos;
|
||||
}
|
||||
|
||||
int wxJoystick::GetZPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_Z];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wxJoystick::GetButtonState() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_buttons;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wxJoystick::GetPOVPosition() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wxJoystick::GetPOVCTSPosition() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wxJoystick::GetRudderPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_RUDDER];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wxJoystick::GetUPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_U];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wxJoystick::GetVPosition() const
|
||||
{
|
||||
if (m_thread)
|
||||
return m_thread->m_axe[wxJS_AXIS_V];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wxJoystick::GetMovementThreshold() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wxJoystick::SetMovementThreshold(int threshold)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Capabilities
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool wxJoystick::IsOk() const
|
||||
{
|
||||
return (m_device != -1);
|
||||
}
|
||||
|
||||
int wxJoystick::GetNumberJoysticks()
|
||||
{
|
||||
wxString dev_name;
|
||||
int fd, j;
|
||||
|
||||
for (j=0; j<4; j++) {
|
||||
dev_name.Printf(wxT("/dev/js%d"), j);
|
||||
fd = open(dev_name.fn_str(), O_RDONLY);
|
||||
if (fd == -1)
|
||||
break;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (j == 0) {
|
||||
for (j=0; j<4; j++) {
|
||||
dev_name.Printf(wxT("/dev/input/js%d"), j);
|
||||
fd = open(dev_name.fn_str(), O_RDONLY);
|
||||
if (fd == -1)
|
||||
return j;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
int wxJoystick::GetManufacturerId() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wxJoystick::GetProductId() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
wxString wxJoystick::GetProductName() const
|
||||
{
|
||||
char name[128];
|
||||
|
||||
if (ioctl(m_device, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||
strcpy(name, "Unknown");
|
||||
return wxString(name, wxConvLibc);
|
||||
}
|
||||
|
||||
int wxJoystick::GetXMin() const
|
||||
{
|
||||
return wxJS_AXIS_MIN;
|
||||
}
|
||||
|
||||
int wxJoystick::GetYMin() const
|
||||
{
|
||||
return wxJS_AXIS_MIN;
|
||||
}
|
||||
|
||||
int wxJoystick::GetZMin() const
|
||||
{
|
||||
return wxJS_AXIS_MIN;
|
||||
}
|
||||
|
||||
int wxJoystick::GetXMax() const
|
||||
{
|
||||
return wxJS_AXIS_MAX;
|
||||
}
|
||||
|
||||
int wxJoystick::GetYMax() const
|
||||
{
|
||||
return wxJS_AXIS_MAX;
|
||||
}
|
||||
|
||||
int wxJoystick::GetZMax() const
|
||||
{
|
||||
return wxJS_AXIS_MAX;
|
||||
}
|
||||
|
||||
int wxJoystick::GetNumberButtons() const
|
||||
{
|
||||
char nb=0;
|
||||
|
||||
if (m_device != -1)
|
||||
ioctl(m_device, JSIOCGBUTTONS, &nb);
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
int wxJoystick::GetNumberAxes() const
|
||||
{
|
||||
char nb=0;
|
||||
|
||||
if (m_device != -1)
|
||||
ioctl(m_device, JSIOCGAXES, &nb);
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
int wxJoystick::GetMaxButtons() const
|
||||
{
|
||||
return 15; // internal
|
||||
}
|
||||
|
||||
int wxJoystick::GetMaxAxes() const
|
||||
{
|
||||
return 15; // internal
|
||||
}
|
||||
|
||||
int wxJoystick::GetPollingMin() const
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
int wxJoystick::GetPollingMax() const
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
int wxJoystick::GetRudderMin() const
|
||||
{
|
||||
return wxJS_AXIS_MIN;
|
||||
}
|
||||
|
||||
int wxJoystick::GetRudderMax() const
|
||||
{
|
||||
return wxJS_AXIS_MAX;
|
||||
}
|
||||
|
||||
int wxJoystick::GetUMin() const
|
||||
{
|
||||
return wxJS_AXIS_MIN;
|
||||
}
|
||||
|
||||
int wxJoystick::GetUMax() const
|
||||
{
|
||||
return wxJS_AXIS_MAX;
|
||||
}
|
||||
|
||||
int wxJoystick::GetVMin() const
|
||||
{
|
||||
return wxJS_AXIS_MIN;
|
||||
}
|
||||
|
||||
int wxJoystick::GetVMax() const
|
||||
{
|
||||
return wxJS_AXIS_MAX;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasRudder() const
|
||||
{
|
||||
return GetNumberAxes() >= wxJS_AXIS_RUDDER;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasZ() const
|
||||
{
|
||||
return GetNumberAxes() >= wxJS_AXIS_Z;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasU() const
|
||||
{
|
||||
return GetNumberAxes() >= wxJS_AXIS_U;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasV() const
|
||||
{
|
||||
return GetNumberAxes() >= wxJS_AXIS_V;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasPOV() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasPOV4Dir() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxJoystick::HasPOVCTS() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Operations
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool wxJoystick::SetCapture(wxWindow* win, int pollingFreq)
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
m_thread->m_catchwin = win;
|
||||
m_thread->m_polling = pollingFreq;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxJoystick::ReleaseCapture()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
m_thread->m_catchwin = NULL;
|
||||
m_thread->m_polling = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // wxUSE_JOYSTICK
|
1607
wxWidgets/src/unix/mediactrl.cpp
Normal file
1607
wxWidgets/src/unix/mediactrl.cpp
Normal file
File diff suppressed because it is too large
Load diff
3011
wxWidgets/src/unix/mimetype.cpp
Normal file
3011
wxWidgets/src/unix/mimetype.cpp
Normal file
File diff suppressed because it is too large
Load diff
398
wxWidgets/src/unix/snglinst.cpp
Normal file
398
wxWidgets/src/unix/snglinst.cpp
Normal file
|
@ -0,0 +1,398 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/snglinst.cpp
|
||||
// Purpose: implements wxSingleInstanceChecker class for Unix using
|
||||
// lock files with fcntl(2) or flock(2)
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 09.06.01
|
||||
// RCS-ID: $Id: snglinst.cpp 55833 2008-09-24 13:47:41Z VZ $
|
||||
// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
||||
// License: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_SNGLINST_CHECKER
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/utils.h" // wxGetHomeDir()
|
||||
#endif //WX_PRECOMP
|
||||
|
||||
#include "wx/file.h"
|
||||
|
||||
#include "wx/snglinst.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h> // for S_I[RW]USR
|
||||
#include <signal.h> // for kill()
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_FCNTL
|
||||
#include <fcntl.h>
|
||||
#elif defined(HAVE_FLOCK)
|
||||
#include <sys/file.h>
|
||||
#else
|
||||
// normally, wxUSE_SNGLINST_CHECKER must have been reset by configure
|
||||
#error "wxSingleInstanceChecker can't be compiled on this platform"
|
||||
#endif // fcntl()/flock()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// argument of wxLockFile()
|
||||
enum LockOperation
|
||||
{
|
||||
LOCK,
|
||||
UNLOCK
|
||||
};
|
||||
|
||||
// return value of CreateLockFile()
|
||||
enum LockResult
|
||||
{
|
||||
LOCK_ERROR = -1,
|
||||
LOCK_EXISTS,
|
||||
LOCK_CREATED
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions: (exclusively) lock/unlock the file
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef HAVE_FCNTL
|
||||
|
||||
static int wxLockFile(int fd, LockOperation lock)
|
||||
{
|
||||
// init the flock parameter struct
|
||||
struct flock fl;
|
||||
fl.l_type = lock == LOCK ? F_WRLCK : F_UNLCK;
|
||||
|
||||
// lock the entire file
|
||||
fl.l_start =
|
||||
fl.l_len =
|
||||
fl.l_whence = 0;
|
||||
|
||||
// is this needed?
|
||||
fl.l_pid = getpid();
|
||||
|
||||
return fcntl(fd, F_SETLK, &fl);
|
||||
}
|
||||
|
||||
#else // HAVE_FLOCK
|
||||
|
||||
static int wxLockFile(int fd, LockOperation lock)
|
||||
{
|
||||
return flock(fd, lock == LOCK ? LOCK_EX | LOCK_NB : LOCK_UN);
|
||||
}
|
||||
|
||||
#endif // fcntl()/flock()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSingleInstanceCheckerImpl: the real implementation class
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxSingleInstanceCheckerImpl
|
||||
{
|
||||
public:
|
||||
wxSingleInstanceCheckerImpl()
|
||||
{
|
||||
m_fdLock = -1;
|
||||
m_pidLocker = 0;
|
||||
}
|
||||
|
||||
bool Create(const wxString& name);
|
||||
|
||||
pid_t GetLockerPID() const { return m_pidLocker; }
|
||||
|
||||
~wxSingleInstanceCheckerImpl() { Unlock(); }
|
||||
|
||||
private:
|
||||
// try to create and lock the file
|
||||
LockResult CreateLockFile();
|
||||
|
||||
// unlock and remove the lock file
|
||||
void Unlock();
|
||||
|
||||
// the descriptor of our lock file, -1 if none
|
||||
int m_fdLock;
|
||||
|
||||
// pid of the process owning the lock file
|
||||
pid_t m_pidLocker;
|
||||
|
||||
// the name of the lock file
|
||||
wxString m_nameLock;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// wxSingleInstanceCheckerImpl implementation
|
||||
// ============================================================================
|
||||
|
||||
LockResult wxSingleInstanceCheckerImpl::CreateLockFile()
|
||||
{
|
||||
// try to open the file
|
||||
m_fdLock = open(m_nameLock.fn_str(),
|
||||
O_WRONLY | O_CREAT | O_EXCL,
|
||||
S_IRUSR | S_IWUSR);
|
||||
|
||||
if ( m_fdLock != -1 )
|
||||
{
|
||||
// try to lock it
|
||||
if ( wxLockFile(m_fdLock, LOCK) == 0 )
|
||||
{
|
||||
// fine, we have the exclusive lock to the file, write our PID
|
||||
// into it
|
||||
m_pidLocker = getpid();
|
||||
|
||||
// use char here, not wxChar!
|
||||
char buf[256]; // enough for any PID size
|
||||
int len = sprintf(buf, "%d", (int)m_pidLocker) + 1;
|
||||
|
||||
if ( write(m_fdLock, buf, len) != len )
|
||||
{
|
||||
wxLogSysError(_("Failed to write to lock file '%s'"),
|
||||
m_nameLock.c_str());
|
||||
|
||||
Unlock();
|
||||
|
||||
return LOCK_ERROR;
|
||||
}
|
||||
|
||||
fsync(m_fdLock);
|
||||
|
||||
// change file's permission so that only this user can access it:
|
||||
if ( chmod(m_nameLock.fn_str(), S_IRUSR | S_IWUSR) != 0 )
|
||||
{
|
||||
wxLogSysError(_("Failed to set permissions on lock file '%s'"),
|
||||
m_nameLock.c_str());
|
||||
|
||||
Unlock();
|
||||
|
||||
return LOCK_ERROR;
|
||||
}
|
||||
|
||||
return LOCK_CREATED;
|
||||
}
|
||||
else // failure: see what exactly happened
|
||||
{
|
||||
close(m_fdLock);
|
||||
m_fdLock = -1;
|
||||
|
||||
if ( errno != EACCES && errno != EAGAIN )
|
||||
{
|
||||
wxLogSysError(_("Failed to lock the lock file '%s'"),
|
||||
m_nameLock.c_str());
|
||||
|
||||
unlink(m_nameLock.fn_str());
|
||||
|
||||
return LOCK_ERROR;
|
||||
}
|
||||
//else: couldn't lock because the lock is held by another process:
|
||||
// this might have happened because of a race condition:
|
||||
// maybe another instance opened and locked the file between
|
||||
// our calls to open() and flock(), so don't give an error
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't create and lock the file
|
||||
return LOCK_EXISTS;
|
||||
}
|
||||
|
||||
bool wxSingleInstanceCheckerImpl::Create(const wxString& name)
|
||||
{
|
||||
m_nameLock = name;
|
||||
|
||||
switch ( CreateLockFile() )
|
||||
{
|
||||
case LOCK_EXISTS:
|
||||
// there is a lock file, check below if it is still valid
|
||||
break;
|
||||
|
||||
case LOCK_CREATED:
|
||||
// nothing more to do
|
||||
return true;
|
||||
|
||||
case LOCK_ERROR:
|
||||
// oops...
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the file is owned by current user and has 0600 permissions.
|
||||
// If it doesn't, it's a fake file, possibly meant as a DoS attack, and
|
||||
// so we refuse to touch it:
|
||||
wxStructStat stats;
|
||||
if ( wxStat(name, &stats) != 0 )
|
||||
{
|
||||
wxLogSysError(_("Failed to inspect the lock file '%s'"), name.c_str());
|
||||
return false;
|
||||
}
|
||||
if ( stats.st_uid != getuid() )
|
||||
{
|
||||
wxLogError(_("Lock file '%s' has incorrect owner."), name.c_str());
|
||||
return false;
|
||||
}
|
||||
if ( stats.st_mode != (S_IFREG | S_IRUSR | S_IWUSR) )
|
||||
{
|
||||
wxLogError(_("Lock file '%s' has incorrect permissions."), name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to open the file for reading and get the PID of the process
|
||||
// which has it
|
||||
wxFile file(name, wxFile::read);
|
||||
if ( !file.IsOpened() )
|
||||
{
|
||||
// well, this is really weird - file doesn't exist and we can't
|
||||
// create it
|
||||
//
|
||||
// normally, this just means that we don't have write access to
|
||||
// the directory where we try to create it, so return failure,
|
||||
// even it might also be a rare case of a race condition when
|
||||
// another process managed to open and lock the file and terminate
|
||||
// (erasing it) before we got here, but this should happen so
|
||||
// rarely in practice that we don't care
|
||||
wxLogError(_("Failed to access lock file."));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
ssize_t count = file.Read(buf, WXSIZEOF(buf));
|
||||
if ( count == wxInvalidOffset )
|
||||
{
|
||||
wxLogError(_("Failed to read PID from lock file."));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sscanf(buf, "%d", (int *)&m_pidLocker) == 1 )
|
||||
{
|
||||
if ( kill(m_pidLocker, 0) != 0 )
|
||||
{
|
||||
if ( unlink(name.fn_str()) != 0 )
|
||||
{
|
||||
wxLogError(_("Failed to remove stale lock file '%s'."),
|
||||
name.c_str());
|
||||
|
||||
// return true in this case for now...
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogMessage(_("Deleted stale lock file '%s'."),
|
||||
name.c_str());
|
||||
|
||||
// retry now
|
||||
(void)CreateLockFile();
|
||||
}
|
||||
}
|
||||
//else: the other process is running
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogWarning(_("Invalid lock file '%s'."), name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// return true if we could get the PID of the process owning the lock file
|
||||
// (whether it is still running or not), FALSE otherwise as it is
|
||||
// unexpected
|
||||
return m_pidLocker != 0;
|
||||
}
|
||||
|
||||
void wxSingleInstanceCheckerImpl::Unlock()
|
||||
{
|
||||
if ( m_fdLock != -1 )
|
||||
{
|
||||
if ( unlink(m_nameLock.fn_str()) != 0 )
|
||||
{
|
||||
wxLogSysError(_("Failed to remove lock file '%s'"),
|
||||
m_nameLock.c_str());
|
||||
}
|
||||
|
||||
if ( wxLockFile(m_fdLock, UNLOCK) != 0 )
|
||||
{
|
||||
wxLogSysError(_("Failed to unlock lock file '%s'"),
|
||||
m_nameLock.c_str());
|
||||
}
|
||||
|
||||
if ( close(m_fdLock) != 0 )
|
||||
{
|
||||
wxLogSysError(_("Failed to close lock file '%s'"),
|
||||
m_nameLock.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
m_pidLocker = 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxSingleInstanceChecker implementation
|
||||
// ============================================================================
|
||||
|
||||
bool wxSingleInstanceChecker::Create(const wxString& name,
|
||||
const wxString& path)
|
||||
{
|
||||
wxASSERT_MSG( !m_impl,
|
||||
_T("calling wxSingleInstanceChecker::Create() twice?") );
|
||||
|
||||
// must have the file name to create a lock file
|
||||
wxASSERT_MSG( !name.empty(), _T("lock file name can't be empty") );
|
||||
|
||||
m_impl = new wxSingleInstanceCheckerImpl;
|
||||
|
||||
wxString fullname = path;
|
||||
if ( fullname.empty() )
|
||||
{
|
||||
fullname = wxGetHomeDir();
|
||||
}
|
||||
|
||||
if ( fullname.Last() != _T('/') )
|
||||
{
|
||||
fullname += _T('/');
|
||||
}
|
||||
|
||||
fullname << name;
|
||||
|
||||
return m_impl->Create(fullname);
|
||||
}
|
||||
|
||||
bool wxSingleInstanceChecker::IsAnotherRunning() const
|
||||
{
|
||||
wxCHECK_MSG( m_impl, false, _T("must call Create() first") );
|
||||
|
||||
const pid_t lockerPid = m_impl->GetLockerPID();
|
||||
|
||||
if ( !lockerPid )
|
||||
{
|
||||
// we failed to open the lock file, return false as we're definitely
|
||||
// not sure that another our process is running and so it's better not
|
||||
// to prevent this one from starting up
|
||||
return false;
|
||||
}
|
||||
|
||||
// if another instance is running, it must own the lock file - otherwise
|
||||
// we have it and the locker PID is ours one
|
||||
return lockerPid != getpid();
|
||||
}
|
||||
|
||||
wxSingleInstanceChecker::~wxSingleInstanceChecker()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
#endif // wxUSE_SNGLINST_CHECKER
|
722
wxWidgets/src/unix/sound.cpp
Normal file
722
wxWidgets/src/unix/sound.cpp
Normal file
|
@ -0,0 +1,722 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/sound.cpp
|
||||
// Purpose: wxSound
|
||||
// Author: Marcel Rasche, Vaclav Slavik
|
||||
// Modified by:
|
||||
// Created: 25/10/98
|
||||
// RCS-ID: $Id: sound.cpp 41020 2006-09-05 20:47:48Z VZ $
|
||||
// Copyright: (c) Julian Smart, Open Source Applications Foundation
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_SOUND
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOUNDCARD_H
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/event.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/module.h"
|
||||
#endif
|
||||
|
||||
#include "wx/thread.h"
|
||||
#include "wx/file.h"
|
||||
#include "wx/sound.h"
|
||||
#include "wx/dynlib.h"
|
||||
|
||||
|
||||
#if wxUSE_THREADS
|
||||
// mutex for all wxSound's synchronization
|
||||
static wxMutex gs_soundMutex;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSoundData
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxSoundData::IncRef()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxMutexLocker locker(gs_soundMutex);
|
||||
#endif
|
||||
m_refCnt++;
|
||||
}
|
||||
|
||||
void wxSoundData::DecRef()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxMutexLocker locker(gs_soundMutex);
|
||||
#endif
|
||||
if (--m_refCnt == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
wxSoundData::~wxSoundData()
|
||||
{
|
||||
delete[] m_dataWithHeader;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSoundBackendNull, used in absence of audio API or card
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxSoundBackendNull : public wxSoundBackend
|
||||
{
|
||||
public:
|
||||
wxString GetName() const { return _("No sound"); }
|
||||
int GetPriority() const { return 0; }
|
||||
bool IsAvailable() const { return true; }
|
||||
bool HasNativeAsyncPlayback() const { return true; }
|
||||
bool Play(wxSoundData *WXUNUSED(data), unsigned WXUNUSED(flags),
|
||||
volatile wxSoundPlaybackStatus *WXUNUSED(status))
|
||||
{ return true; }
|
||||
void Stop() {}
|
||||
bool IsPlaying() const { return false; }
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSoundBackendOSS, for Linux
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef HAVE_SYS_SOUNDCARD_H
|
||||
|
||||
#ifndef AUDIODEV
|
||||
#define AUDIODEV "/dev/dsp" // Default path for audio device
|
||||
#endif
|
||||
|
||||
class wxSoundBackendOSS : public wxSoundBackend
|
||||
{
|
||||
public:
|
||||
wxString GetName() const { return _T("Open Sound System"); }
|
||||
int GetPriority() const { return 10; }
|
||||
bool IsAvailable() const;
|
||||
bool HasNativeAsyncPlayback() const { return false; }
|
||||
bool Play(wxSoundData *data, unsigned flags,
|
||||
volatile wxSoundPlaybackStatus *status);
|
||||
void Stop() {}
|
||||
bool IsPlaying() const { return false; }
|
||||
|
||||
private:
|
||||
int OpenDSP(const wxSoundData *data);
|
||||
bool InitDSP(int dev, const wxSoundData *data);
|
||||
|
||||
int m_DSPblkSize; // Size of the DSP buffer
|
||||
bool m_needConversion;
|
||||
};
|
||||
|
||||
bool wxSoundBackendOSS::IsAvailable() const
|
||||
{
|
||||
int fd;
|
||||
fd = open(AUDIODEV, O_WRONLY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxSoundBackendOSS::Play(wxSoundData *data, unsigned flags,
|
||||
volatile wxSoundPlaybackStatus *status)
|
||||
{
|
||||
int dev = OpenDSP(data);
|
||||
|
||||
if (dev < 0)
|
||||
return false;
|
||||
|
||||
ioctl(dev, SNDCTL_DSP_SYNC, 0);
|
||||
|
||||
do
|
||||
{
|
||||
bool play = true;
|
||||
int i;
|
||||
unsigned l = 0;
|
||||
size_t datasize = data->m_dataBytes;
|
||||
|
||||
do
|
||||
{
|
||||
if (status->m_stopRequested)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("playback stopped"));
|
||||
close(dev);
|
||||
return true;
|
||||
}
|
||||
|
||||
i= (int)((l + m_DSPblkSize) < datasize ?
|
||||
m_DSPblkSize : (datasize - l));
|
||||
if (write(dev, &data->m_data[l], i) != i)
|
||||
{
|
||||
play = false;
|
||||
}
|
||||
l += i;
|
||||
} while (play && l < datasize);
|
||||
} while (flags & wxSOUND_LOOP);
|
||||
|
||||
close(dev);
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxSoundBackendOSS::OpenDSP(const wxSoundData *data)
|
||||
{
|
||||
int dev = -1;
|
||||
|
||||
if ((dev = open(AUDIODEV, O_WRONLY, 0)) <0)
|
||||
return -1;
|
||||
|
||||
if (!InitDSP(dev, data) || m_needConversion)
|
||||
{
|
||||
close(dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
|
||||
{
|
||||
unsigned tmp;
|
||||
|
||||
// Reset the dsp
|
||||
if (ioctl(dev, SNDCTL_DSP_RESET, 0) < 0)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("unable to reset dsp"));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_needConversion = false;
|
||||
|
||||
tmp = data->m_bitsPerSample;
|
||||
if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_SAMPLESIZE)"));
|
||||
return false;
|
||||
}
|
||||
if (tmp != data->m_bitsPerSample)
|
||||
{
|
||||
wxLogTrace(_T("sound"),
|
||||
_T("Unable to set DSP sample size to %d (wants %d)"),
|
||||
data->m_bitsPerSample, tmp);
|
||||
m_needConversion = true;
|
||||
}
|
||||
|
||||
unsigned stereo = data->m_channels == 1 ? 0 : 1;
|
||||
tmp = stereo;
|
||||
if (ioctl(dev, SNDCTL_DSP_STEREO, &tmp) < 0)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_STEREO)"));
|
||||
return false;
|
||||
}
|
||||
if (tmp != stereo)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("Unable to set DSP to %s."), stereo? _T("stereo"):_T("mono"));
|
||||
m_needConversion = true;
|
||||
}
|
||||
|
||||
tmp = data->m_samplingRate;
|
||||
if (ioctl(dev, SNDCTL_DSP_SPEED, &tmp) < 0)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_SPEED)"));
|
||||
return false;
|
||||
}
|
||||
if (tmp != data->m_samplingRate)
|
||||
{
|
||||
// If the rate the sound card is using is not within 1% of what the
|
||||
// data specified then override the data setting. The only reason not
|
||||
// to always override this is because of clock-rounding
|
||||
// problems. Sound cards will sometimes use things like 44101 when you
|
||||
// ask for 44100. No need overriding this and having strange output
|
||||
// file rates for something that we can't hear anyways.
|
||||
if (data->m_samplingRate - tmp > (tmp * .01) ||
|
||||
tmp - data->m_samplingRate > (tmp * .01)) {
|
||||
wxLogTrace(_T("sound"),
|
||||
_T("Unable to set DSP sampling rate to %d (wants %d)"),
|
||||
data->m_samplingRate, tmp);
|
||||
m_needConversion = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Do this last because some drivers can adjust the buffer sized based on
|
||||
// the sampling rate, etc.
|
||||
if (ioctl(dev, SNDCTL_DSP_GETBLKSIZE, &m_DSPblkSize) < 0)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("IOCTL failure (SNDCTL_DSP_GETBLKSIZE)"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // HAVE_SYS_SOUNDCARD_H
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSoundSyncOnlyAdaptor
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_THREADS
|
||||
|
||||
class wxSoundSyncOnlyAdaptor;
|
||||
|
||||
// this class manages asynchronous playback of audio if the backend doesn't
|
||||
// support it natively (e.g. OSS backend)
|
||||
class wxSoundAsyncPlaybackThread : public wxThread
|
||||
{
|
||||
public:
|
||||
wxSoundAsyncPlaybackThread(wxSoundSyncOnlyAdaptor *adaptor,
|
||||
wxSoundData *data, unsigned flags)
|
||||
: wxThread(), m_adapt(adaptor), m_data(data), m_flags(flags) {}
|
||||
virtual ExitCode Entry();
|
||||
|
||||
protected:
|
||||
wxSoundSyncOnlyAdaptor *m_adapt;
|
||||
wxSoundData *m_data;
|
||||
unsigned m_flags;
|
||||
};
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
// This class turns wxSoundBackend that doesn't support asynchronous playback
|
||||
// into one that does
|
||||
class wxSoundSyncOnlyAdaptor : public wxSoundBackend
|
||||
{
|
||||
public:
|
||||
wxSoundSyncOnlyAdaptor(wxSoundBackend *backend)
|
||||
: m_backend(backend), m_playing(false) {}
|
||||
virtual ~wxSoundSyncOnlyAdaptor()
|
||||
{
|
||||
delete m_backend;
|
||||
}
|
||||
wxString GetName() const
|
||||
{
|
||||
return m_backend->GetName();
|
||||
}
|
||||
int GetPriority() const
|
||||
{
|
||||
return m_backend->GetPriority();
|
||||
}
|
||||
bool IsAvailable() const
|
||||
{
|
||||
return m_backend->IsAvailable();
|
||||
}
|
||||
bool HasNativeAsyncPlayback() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool Play(wxSoundData *data, unsigned flags,
|
||||
volatile wxSoundPlaybackStatus *status);
|
||||
void Stop();
|
||||
bool IsPlaying() const;
|
||||
|
||||
private:
|
||||
friend class wxSoundAsyncPlaybackThread;
|
||||
|
||||
wxSoundBackend *m_backend;
|
||||
bool m_playing;
|
||||
#if wxUSE_THREADS
|
||||
// player thread holds this mutex and releases it after it finishes
|
||||
// playing, so that the main thread knows when it can play sound
|
||||
wxMutex m_mutexRightToPlay;
|
||||
wxSoundPlaybackStatus m_status;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#if wxUSE_THREADS
|
||||
wxThread::ExitCode wxSoundAsyncPlaybackThread::Entry()
|
||||
{
|
||||
m_adapt->m_backend->Play(m_data, m_flags & ~wxSOUND_ASYNC,
|
||||
&m_adapt->m_status);
|
||||
|
||||
m_data->DecRef();
|
||||
m_adapt->m_playing = false;
|
||||
m_adapt->m_mutexRightToPlay.Unlock();
|
||||
wxLogTrace(_T("sound"), _T("terminated async playback thread"));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool wxSoundSyncOnlyAdaptor::Play(wxSoundData *data, unsigned flags,
|
||||
volatile wxSoundPlaybackStatus *status)
|
||||
{
|
||||
Stop();
|
||||
if (flags & wxSOUND_ASYNC)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
m_mutexRightToPlay.Lock();
|
||||
m_status.m_playing = true;
|
||||
m_status.m_stopRequested = false;
|
||||
data->IncRef();
|
||||
wxThread *th = new wxSoundAsyncPlaybackThread(this, data, flags);
|
||||
th->Create();
|
||||
th->Run();
|
||||
wxLogTrace(_T("sound"), _T("launched async playback thread"));
|
||||
return true;
|
||||
#else
|
||||
wxLogError(_("Unable to play sound asynchronously."));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
m_mutexRightToPlay.Lock();
|
||||
#endif
|
||||
bool rv = m_backend->Play(data, flags, status);
|
||||
#if wxUSE_THREADS
|
||||
m_mutexRightToPlay.Unlock();
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
void wxSoundSyncOnlyAdaptor::Stop()
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("asking audio to stop"));
|
||||
|
||||
#if wxUSE_THREADS
|
||||
// tell the player thread (if running) to stop playback ASAP:
|
||||
m_status.m_stopRequested = true;
|
||||
|
||||
// acquire the mutex to be sure no sound is being played, then
|
||||
// release it because we don't need it for anything (the effect of this
|
||||
// is that calling thread will wait until playback thread reacts to
|
||||
// our request to interrupt playback):
|
||||
m_mutexRightToPlay.Lock();
|
||||
m_mutexRightToPlay.Unlock();
|
||||
wxLogTrace(_T("sound"), _T("audio was stopped"));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wxSoundSyncOnlyAdaptor::IsPlaying() const
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
return m_status.m_playing;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSound
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxSoundBackend *wxSound::ms_backend = NULL;
|
||||
|
||||
// FIXME - temporary, until we have plugins architecture
|
||||
#if wxUSE_LIBSDL
|
||||
#if wxUSE_PLUGINS
|
||||
wxDynamicLibrary *wxSound::ms_backendSDL = NULL;
|
||||
#else
|
||||
extern "C" wxSoundBackend *wxCreateSoundBackendSDL();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
wxSound::wxSound() : m_data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
wxSound::wxSound(const wxString& sFileName, bool isResource) : m_data(NULL)
|
||||
{
|
||||
Create(sFileName, isResource);
|
||||
}
|
||||
|
||||
wxSound::wxSound(int size, const wxByte* data) : m_data(NULL)
|
||||
{
|
||||
Create(size, data);
|
||||
}
|
||||
|
||||
wxSound::~wxSound()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
bool wxSound::Create(const wxString& fileName,
|
||||
bool WXUNUSED_UNLESS_DEBUG(isResource))
|
||||
{
|
||||
wxASSERT_MSG( !isResource,
|
||||
_T("Loading sound from resources is only supported on Windows") );
|
||||
|
||||
Free();
|
||||
|
||||
wxFile fileWave;
|
||||
if (!fileWave.Open(fileName, wxFile::read))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wxFileOffset lenOrig = fileWave.Length();
|
||||
if ( lenOrig == wxInvalidOffset )
|
||||
return false;
|
||||
|
||||
size_t len = wx_truncate_cast(size_t, lenOrig);
|
||||
wxUint8 *data = new wxUint8[len];
|
||||
if ( fileWave.Read(data, len) != lenOrig )
|
||||
{
|
||||
delete [] data;
|
||||
wxLogError(_("Couldn't load sound data from '%s'."), fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LoadWAV(data, len, false))
|
||||
{
|
||||
delete [] data;
|
||||
wxLogError(_("Sound file '%s' is in unsupported format."),
|
||||
fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxSound::Create(int size, const wxByte* data)
|
||||
{
|
||||
wxASSERT( data != NULL );
|
||||
|
||||
Free();
|
||||
if (!LoadWAV(data, size, true))
|
||||
{
|
||||
wxLogError(_("Sound data are in unsupported format."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ void wxSound::EnsureBackend()
|
||||
{
|
||||
if (!ms_backend)
|
||||
{
|
||||
// FIXME -- make this fully dynamic when plugins architecture is in
|
||||
// place
|
||||
#if wxUSE_LIBSDL
|
||||
//if (!ms_backend)
|
||||
{
|
||||
#if !wxUSE_PLUGINS
|
||||
ms_backend = wxCreateSoundBackendSDL();
|
||||
#else
|
||||
wxString dllname;
|
||||
dllname.Printf(_T("%s/%s"),
|
||||
wxDynamicLibrary::GetPluginsDirectory().c_str(),
|
||||
wxDynamicLibrary::CanonicalizePluginName(
|
||||
_T("sound_sdl"), wxDL_PLUGIN_BASE).c_str());
|
||||
wxLogTrace(_T("sound"),
|
||||
_T("trying to load SDL plugin from '%s'..."),
|
||||
dllname.c_str());
|
||||
wxLogNull null;
|
||||
ms_backendSDL = new wxDynamicLibrary(dllname, wxDL_NOW);
|
||||
if (!ms_backendSDL->IsLoaded())
|
||||
{
|
||||
wxDELETE(ms_backendSDL);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef wxSoundBackend *(*wxCreateSoundBackend_t)();
|
||||
wxDYNLIB_FUNCTION(wxCreateSoundBackend_t,
|
||||
wxCreateSoundBackendSDL, *ms_backendSDL);
|
||||
if (pfnwxCreateSoundBackendSDL)
|
||||
{
|
||||
ms_backend = (*pfnwxCreateSoundBackendSDL)();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ms_backend && !ms_backend->IsAvailable())
|
||||
{
|
||||
wxDELETE(ms_backend);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOUNDCARD_H
|
||||
if (!ms_backend)
|
||||
{
|
||||
ms_backend = new wxSoundBackendOSS();
|
||||
if (!ms_backend->IsAvailable())
|
||||
{
|
||||
wxDELETE(ms_backend);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ms_backend)
|
||||
ms_backend = new wxSoundBackendNull();
|
||||
|
||||
if (!ms_backend->HasNativeAsyncPlayback())
|
||||
ms_backend = new wxSoundSyncOnlyAdaptor(ms_backend);
|
||||
|
||||
wxLogTrace(_T("sound"),
|
||||
_T("using backend '%s'"), ms_backend->GetName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void wxSound::UnloadBackend()
|
||||
{
|
||||
if (ms_backend)
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("unloading backend"));
|
||||
|
||||
Stop();
|
||||
|
||||
delete ms_backend;
|
||||
ms_backend = NULL;
|
||||
#if wxUSE_LIBSDL && wxUSE_PLUGINS
|
||||
delete ms_backendSDL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool wxSound::DoPlay(unsigned flags) const
|
||||
{
|
||||
wxCHECK_MSG( IsOk(), false, _T("Attempt to play invalid wave data") );
|
||||
|
||||
EnsureBackend();
|
||||
wxSoundPlaybackStatus status;
|
||||
status.m_playing = true;
|
||||
status.m_stopRequested = false;
|
||||
return ms_backend->Play(m_data, flags, &status);
|
||||
}
|
||||
|
||||
/*static*/ void wxSound::Stop()
|
||||
{
|
||||
if (ms_backend)
|
||||
ms_backend->Stop();
|
||||
}
|
||||
|
||||
/*static*/ bool wxSound::IsPlaying()
|
||||
{
|
||||
if (ms_backend)
|
||||
return ms_backend->IsPlaying();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxSound::Free()
|
||||
{
|
||||
if (m_data)
|
||||
m_data->DecRef();
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wxUint32 uiSize;
|
||||
wxUint16 uiFormatTag;
|
||||
wxUint16 uiChannels;
|
||||
wxUint32 ulSamplesPerSec;
|
||||
wxUint32 ulAvgBytesPerSec;
|
||||
wxUint16 uiBlockAlign;
|
||||
wxUint16 uiBitsPerSample;
|
||||
} WAVEFORMAT;
|
||||
|
||||
#define WAVE_FORMAT_PCM 1
|
||||
#define WAVE_INDEX 8
|
||||
#define FMT_INDEX 12
|
||||
|
||||
bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
|
||||
{
|
||||
// the simplest wave file header consists of 44 bytes:
|
||||
//
|
||||
// 0 "RIFF"
|
||||
// 4 file size - 8
|
||||
// 8 "WAVE"
|
||||
//
|
||||
// 12 "fmt "
|
||||
// 16 chunk size |
|
||||
// 20 format tag |
|
||||
// 22 number of channels |
|
||||
// 24 sample rate | WAVEFORMAT
|
||||
// 28 average bytes per second |
|
||||
// 32 bytes per frame |
|
||||
// 34 bits per sample |
|
||||
//
|
||||
// 36 "data"
|
||||
// 40 number of data bytes
|
||||
// 44 (wave signal) data
|
||||
//
|
||||
// so check that we have at least as much
|
||||
if ( length < 44 )
|
||||
return false;
|
||||
|
||||
WAVEFORMAT waveformat;
|
||||
memcpy(&waveformat, &data[FMT_INDEX + 4], sizeof(WAVEFORMAT));
|
||||
waveformat.uiSize = wxUINT32_SWAP_ON_BE(waveformat.uiSize);
|
||||
waveformat.uiFormatTag = wxUINT16_SWAP_ON_BE(waveformat.uiFormatTag);
|
||||
waveformat.uiChannels = wxUINT16_SWAP_ON_BE(waveformat.uiChannels);
|
||||
waveformat.ulSamplesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulSamplesPerSec);
|
||||
waveformat.ulAvgBytesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulAvgBytesPerSec);
|
||||
waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign);
|
||||
waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample);
|
||||
|
||||
// get the sound data size
|
||||
wxUint32 ul;
|
||||
memcpy(&ul, &data[FMT_INDEX + waveformat.uiSize + 12], 4);
|
||||
ul = wxUINT32_SWAP_ON_BE(ul);
|
||||
|
||||
if ( length < ul + FMT_INDEX + waveformat.uiSize + 16 )
|
||||
return false;
|
||||
|
||||
if (memcmp(data, "RIFF", 4) != 0)
|
||||
return false;
|
||||
if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0)
|
||||
return false;
|
||||
if (memcmp(&data[FMT_INDEX], "fmt ", 4) != 0)
|
||||
return false;
|
||||
if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
|
||||
return false;
|
||||
|
||||
if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
|
||||
return false;
|
||||
|
||||
if (waveformat.ulSamplesPerSec !=
|
||||
waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
|
||||
return false;
|
||||
|
||||
m_data = new wxSoundData;
|
||||
m_data->m_channels = waveformat.uiChannels;
|
||||
m_data->m_samplingRate = waveformat.ulSamplesPerSec;
|
||||
m_data->m_bitsPerSample = waveformat.uiBitsPerSample;
|
||||
m_data->m_samples = ul / (m_data->m_channels * m_data->m_bitsPerSample / 8);
|
||||
m_data->m_dataBytes = ul;
|
||||
|
||||
if (copyData)
|
||||
{
|
||||
m_data->m_dataWithHeader = new wxUint8[length];
|
||||
memcpy(m_data->m_dataWithHeader, data, length);
|
||||
}
|
||||
else
|
||||
m_data->m_dataWithHeader = (wxUint8*)data;
|
||||
|
||||
m_data->m_data =
|
||||
(&m_data->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSoundCleanupModule
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxSoundCleanupModule: public wxModule
|
||||
{
|
||||
public:
|
||||
bool OnInit() { return true; }
|
||||
void OnExit() { wxSound::UnloadBackend(); }
|
||||
DECLARE_DYNAMIC_CLASS(wxSoundCleanupModule)
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxSoundCleanupModule, wxModule)
|
||||
|
||||
#endif
|
335
wxWidgets/src/unix/sound_sdl.cpp
Normal file
335
wxWidgets/src/unix/sound_sdl.cpp
Normal file
|
@ -0,0 +1,335 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/sound_sdl.cpp
|
||||
// Purpose: wxSound backend using SDL
|
||||
// Author: Vaclav Slavik
|
||||
// Modified by:
|
||||
// Created: 2004/01/31
|
||||
// RCS-ID: $Id: sound_sdl.cpp 40943 2006-08-31 19:31:43Z ABX $
|
||||
// Copyright: (c) 2004, Open Source Applications Foundation
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_SOUND && wxUSE_LIBSDL
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/event.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/module.h"
|
||||
#endif
|
||||
|
||||
#include "wx/thread.h"
|
||||
#include "wx/sound.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxSoundBackendSDL, for Unix with libSDL
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxSoundBackendSDLNotification : public wxEvent
|
||||
{
|
||||
public:
|
||||
DECLARE_DYNAMIC_CLASS(wxSoundBackendSDLNotification)
|
||||
wxSoundBackendSDLNotification();
|
||||
wxEvent *Clone() const { return new wxSoundBackendSDLNotification(*this); }
|
||||
};
|
||||
|
||||
typedef void (wxEvtHandler::*wxSoundBackendSDLNotificationFunction)
|
||||
(wxSoundBackendSDLNotification&);
|
||||
|
||||
BEGIN_DECLARE_EVENT_TYPES()
|
||||
DECLARE_LOCAL_EVENT_TYPE(wxEVT_SOUND_BACKEND_SDL_NOTIFICATION, -1)
|
||||
END_DECLARE_EVENT_TYPES()
|
||||
|
||||
#define EVT_SOUND_BACKEND_SDL_NOTIFICATON(func) \
|
||||
DECLARE_EVENT_TABLE_ENTRY(wxEVT_SOUND_BACKEND_SDL_NOTIFICATION, \
|
||||
-1, \
|
||||
-1, \
|
||||
(wxObjectEventFunction) wxStaticCastEvent( wxSoundBackendSDLNotificationFunction, & func ), \
|
||||
(wxObject *) NULL ),
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxSoundBackendSDLNotification, wxEvtHandler)
|
||||
DEFINE_EVENT_TYPE(wxEVT_SOUND_BACKEND_SDL_NOTIFICATION)
|
||||
|
||||
wxSoundBackendSDLNotification::wxSoundBackendSDLNotification()
|
||||
{
|
||||
SetEventType(wxEVT_SOUND_BACKEND_SDL_NOTIFICATION);
|
||||
}
|
||||
|
||||
class wxSoundBackendSDLEvtHandler;
|
||||
|
||||
class wxSoundBackendSDL : public wxSoundBackend
|
||||
{
|
||||
public:
|
||||
wxSoundBackendSDL()
|
||||
: m_initialized(false), m_playing(false), m_audioOpen(false),
|
||||
m_data(NULL), m_evtHandler(NULL) {}
|
||||
virtual ~wxSoundBackendSDL();
|
||||
|
||||
wxString GetName() const { return _T("Simple DirectMedia Layer"); }
|
||||
int GetPriority() const { return 9; }
|
||||
bool IsAvailable() const;
|
||||
bool HasNativeAsyncPlayback() const { return true; }
|
||||
bool Play(wxSoundData *data, unsigned flags,
|
||||
volatile wxSoundPlaybackStatus *status);
|
||||
|
||||
void FillAudioBuffer(Uint8 *stream, int len);
|
||||
void FinishedPlayback();
|
||||
|
||||
void Stop();
|
||||
bool IsPlaying() const { return m_playing; }
|
||||
|
||||
private:
|
||||
bool OpenAudio();
|
||||
void CloseAudio();
|
||||
|
||||
bool m_initialized;
|
||||
bool m_playing, m_audioOpen;
|
||||
// playback information:
|
||||
wxSoundData *m_data;
|
||||
unsigned m_pos;
|
||||
SDL_AudioSpec m_spec;
|
||||
bool m_loop;
|
||||
|
||||
wxSoundBackendSDLEvtHandler *m_evtHandler;
|
||||
};
|
||||
|
||||
class wxSoundBackendSDLEvtHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
wxSoundBackendSDLEvtHandler(wxSoundBackendSDL *bk) : m_backend(bk) {}
|
||||
|
||||
private:
|
||||
void OnNotify(wxSoundBackendSDLNotification& WXUNUSED(event))
|
||||
{
|
||||
wxLogTrace(_T("sound"),
|
||||
_T("received playback status change notification"));
|
||||
m_backend->FinishedPlayback();
|
||||
}
|
||||
wxSoundBackendSDL *m_backend;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(wxSoundBackendSDLEvtHandler, wxEvtHandler)
|
||||
EVT_SOUND_BACKEND_SDL_NOTIFICATON(wxSoundBackendSDLEvtHandler::OnNotify)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
wxSoundBackendSDL::~wxSoundBackendSDL()
|
||||
{
|
||||
Stop();
|
||||
CloseAudio();
|
||||
delete m_evtHandler;
|
||||
}
|
||||
|
||||
bool wxSoundBackendSDL::IsAvailable() const
|
||||
{
|
||||
if (m_initialized)
|
||||
return true;
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO) != SDL_INIT_AUDIO)
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE) == -1)
|
||||
return false;
|
||||
}
|
||||
wxConstCast(this, wxSoundBackendSDL)->m_initialized = true;
|
||||
wxLogTrace(_T("sound"), _T("initialized SDL audio subsystem"));
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void wx_sdl_audio_callback(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
wxSoundBackendSDL *bk = (wxSoundBackendSDL*)userdata;
|
||||
bk->FillAudioBuffer(stream, len);
|
||||
}
|
||||
|
||||
void wxSoundBackendSDL::FillAudioBuffer(Uint8 *stream, int len)
|
||||
{
|
||||
if (m_playing)
|
||||
{
|
||||
// finished playing the sample
|
||||
if (m_pos == m_data->m_dataBytes)
|
||||
{
|
||||
m_playing = false;
|
||||
wxSoundBackendSDLNotification event;
|
||||
m_evtHandler->AddPendingEvent(event);
|
||||
}
|
||||
// still something to play
|
||||
else
|
||||
{
|
||||
unsigned size = ((len + m_pos) < m_data->m_dataBytes) ?
|
||||
len :
|
||||
(m_data->m_dataBytes - m_pos);
|
||||
memcpy(stream, m_data->m_data + m_pos, size);
|
||||
m_pos += size;
|
||||
len -= size;
|
||||
stream += size;
|
||||
}
|
||||
}
|
||||
// the sample doesn't play, fill the buffer with silence and wait for
|
||||
// the main thread to shut the playback down:
|
||||
if (len > 0)
|
||||
{
|
||||
if (m_loop)
|
||||
{
|
||||
m_pos = 0;
|
||||
FillAudioBuffer(stream, len);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(stream, m_spec.silence, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxSoundBackendSDL::FinishedPlayback()
|
||||
{
|
||||
if (!m_playing)
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool wxSoundBackendSDL::OpenAudio()
|
||||
{
|
||||
if (!m_audioOpen)
|
||||
{
|
||||
if (!m_evtHandler)
|
||||
m_evtHandler = new wxSoundBackendSDLEvtHandler(this);
|
||||
|
||||
m_spec.silence = 0;
|
||||
m_spec.samples = 4096;
|
||||
m_spec.size = 0;
|
||||
m_spec.callback = wx_sdl_audio_callback;
|
||||
m_spec.userdata = (void*)this;
|
||||
|
||||
wxLogTrace(_T("sound"), _T("opening SDL audio..."));
|
||||
if (SDL_OpenAudio(&m_spec, NULL) >= 0)
|
||||
{
|
||||
#if wxUSE_LOG_DEBUG
|
||||
char driver[256];
|
||||
SDL_AudioDriverName(driver, 256);
|
||||
wxLogTrace(_T("sound"), _T("opened audio, driver '%s'"),
|
||||
wxString(driver, wxConvLocal).c_str());
|
||||
#endif
|
||||
m_audioOpen = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString err(SDL_GetError(), wxConvLocal);
|
||||
wxLogError(_("Couldn't open audio: %s"), err.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxSoundBackendSDL::CloseAudio()
|
||||
{
|
||||
if (m_audioOpen)
|
||||
{
|
||||
SDL_CloseAudio();
|
||||
wxLogTrace(_T("sound"), _T("closed audio"));
|
||||
m_audioOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxSoundBackendSDL::Play(wxSoundData *data, unsigned flags,
|
||||
volatile wxSoundPlaybackStatus *WXUNUSED(status))
|
||||
{
|
||||
Stop();
|
||||
|
||||
int format;
|
||||
if (data->m_bitsPerSample == 8)
|
||||
format = AUDIO_U8;
|
||||
else if (data->m_bitsPerSample == 16)
|
||||
format = AUDIO_S16LSB;
|
||||
else
|
||||
return false;
|
||||
|
||||
bool needsOpen = true;
|
||||
if (m_audioOpen)
|
||||
{
|
||||
if (format == m_spec.format &&
|
||||
m_spec.freq == (int)data->m_samplingRate &&
|
||||
m_spec.channels == data->m_channels)
|
||||
{
|
||||
needsOpen = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseAudio();
|
||||
}
|
||||
}
|
||||
|
||||
if (needsOpen)
|
||||
{
|
||||
m_spec.format = format;
|
||||
m_spec.freq = data->m_samplingRate;
|
||||
m_spec.channels = data->m_channels;
|
||||
if (!OpenAudio())
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_LockAudio();
|
||||
wxLogTrace(_T("sound"), _T("playing new sound"));
|
||||
m_playing = true;
|
||||
m_pos = 0;
|
||||
m_loop = (flags & wxSOUND_LOOP);
|
||||
m_data = data;
|
||||
data->IncRef();
|
||||
SDL_UnlockAudio();
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
// wait until playback finishes if called in sync mode:
|
||||
if (!(flags & wxSOUND_ASYNC))
|
||||
{
|
||||
wxLogTrace(_T("sound"), _T("waiting for sample to finish"));
|
||||
while (m_playing && m_data == data)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
// give the playback thread a chance to add event to pending
|
||||
// events queue, release GUI lock temporarily:
|
||||
if (wxThread::IsMain())
|
||||
wxMutexGuiLeave();
|
||||
#endif
|
||||
wxMilliSleep(10);
|
||||
#if wxUSE_THREADS
|
||||
if (wxThread::IsMain())
|
||||
wxMutexGuiEnter();
|
||||
#endif
|
||||
}
|
||||
wxLogTrace(_T("sound"), _T("sample finished"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxSoundBackendSDL::Stop()
|
||||
{
|
||||
SDL_LockAudio();
|
||||
SDL_PauseAudio(1);
|
||||
m_playing = false;
|
||||
if (m_data)
|
||||
{
|
||||
m_data->DecRef();
|
||||
m_data = NULL;
|
||||
}
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
|
||||
extern "C" wxSoundBackend *wxCreateSoundBackendSDL()
|
||||
{
|
||||
return new wxSoundBackendSDL();
|
||||
}
|
||||
|
||||
#endif // wxUSE_SOUND && wxUSE_LIBSDL
|
309
wxWidgets/src/unix/stackwalk.cpp
Normal file
309
wxWidgets/src/unix/stackwalk.cpp
Normal file
|
@ -0,0 +1,309 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: msw/stackwalk.cpp
|
||||
// Purpose: wxStackWalker implementation for Unix/glibc
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2005-01-18
|
||||
// RCS-ID: $Id: stackwalk.cpp 43965 2006-12-13 13:04:44Z VZ $
|
||||
// Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwindows.org>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_STACKWALKER
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/utils.h"
|
||||
#endif
|
||||
|
||||
#include "wx/stackwalk.h"
|
||||
#include "wx/stdpaths.h"
|
||||
|
||||
#include <execinfo.h>
|
||||
|
||||
#ifdef HAVE_CXA_DEMANGLE
|
||||
#include <cxxabi.h>
|
||||
#endif // HAVE_CXA_DEMANGLE
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// tiny helper wrapper around popen/pclose()
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxStdioPipe
|
||||
{
|
||||
public:
|
||||
// ctor parameters are passed to popen()
|
||||
wxStdioPipe(const char *command, const char *type)
|
||||
{
|
||||
m_fp = popen(command, type);
|
||||
}
|
||||
|
||||
// conversion to stdio FILE
|
||||
operator FILE *() const { return m_fp; }
|
||||
|
||||
// dtor closes the pipe
|
||||
~wxStdioPipe()
|
||||
{
|
||||
if ( m_fp )
|
||||
pclose(m_fp);
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *m_fp;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxStdioPipe)
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxStackFrame
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxStackFrame::OnGetName()
|
||||
{
|
||||
if ( !m_name.empty() )
|
||||
return;
|
||||
|
||||
// we already tried addr2line in wxStackWalker::InitFrames: it always
|
||||
// gives us demangled names (even if __cxa_demangle is not available) when
|
||||
// the function is part of the ELF (when it's in a shared object addr2line
|
||||
// will give "??") and because it seems less error-prone.
|
||||
// when it works, backtrace_symbols() sometimes returns incorrect results
|
||||
|
||||
// format is: "module(funcname+offset) [address]" but the part in
|
||||
// parentheses can be not present
|
||||
wxString syminfo = wxString::FromAscii(m_syminfo);
|
||||
const size_t posOpen = syminfo.find(_T('('));
|
||||
if ( posOpen != wxString::npos )
|
||||
{
|
||||
const size_t posPlus = syminfo.find(_T('+'), posOpen + 1);
|
||||
if ( posPlus != wxString::npos )
|
||||
{
|
||||
const size_t posClose = syminfo.find(_T(')'), posPlus + 1);
|
||||
if ( posClose != wxString::npos )
|
||||
{
|
||||
if ( m_name.empty() )
|
||||
{
|
||||
m_name.assign(syminfo, posOpen + 1, posPlus - posOpen - 1);
|
||||
|
||||
#ifdef HAVE_CXA_DEMANGLE
|
||||
int rc = -1;
|
||||
char *cppfunc = __cxxabiv1::__cxa_demangle
|
||||
(
|
||||
m_name.mb_str(),
|
||||
NULL, // output buffer (none, alloc it)
|
||||
NULL, // [out] len of output buffer
|
||||
&rc
|
||||
);
|
||||
if ( rc == 0 )
|
||||
m_name = wxString::FromAscii(cppfunc);
|
||||
|
||||
free(cppfunc);
|
||||
#endif // HAVE_CXA_DEMANGLE
|
||||
}
|
||||
|
||||
unsigned long ofs;
|
||||
if ( wxString(syminfo, posPlus + 1, posClose - posPlus - 1).
|
||||
ToULong(&ofs, 0) )
|
||||
m_offset = ofs;
|
||||
}
|
||||
}
|
||||
|
||||
m_module.assign(syminfo, posOpen);
|
||||
}
|
||||
else // not in "module(funcname+offset)" format
|
||||
{
|
||||
m_module = syminfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxStackWalker
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// that many frames should be enough for everyone
|
||||
#define MAX_FRAMES 200
|
||||
|
||||
// we need a char buffer big enough to contain a call to addr2line with
|
||||
// up to MAX_FRAMES addresses !
|
||||
// NB: %p specifier will print the pointer in hexadecimal form
|
||||
// and thus will require 2 chars for each byte + 3 for the
|
||||
// " 0x" prefix
|
||||
#define CHARS_PER_FRAME (sizeof(void*) * 2 + 3)
|
||||
|
||||
// BUFSIZE will be 2250 for 32 bit machines
|
||||
#define BUFSIZE (50 + MAX_FRAMES*CHARS_PER_FRAME)
|
||||
|
||||
// static data
|
||||
void *wxStackWalker::ms_addresses[MAX_FRAMES];
|
||||
char **wxStackWalker::ms_symbols = NULL;
|
||||
int wxStackWalker::m_depth = 0;
|
||||
wxString wxStackWalker::ms_exepath;
|
||||
static char g_buf[BUFSIZE];
|
||||
|
||||
|
||||
void wxStackWalker::SaveStack(size_t maxDepth)
|
||||
{
|
||||
// read all frames required
|
||||
maxDepth = wxMin(WXSIZEOF(ms_addresses)/sizeof(void*), maxDepth);
|
||||
m_depth = backtrace(ms_addresses, maxDepth*sizeof(void*));
|
||||
if ( !m_depth )
|
||||
return;
|
||||
|
||||
ms_symbols = backtrace_symbols(ms_addresses, m_depth);
|
||||
}
|
||||
|
||||
void wxStackWalker::ProcessFrames(size_t skip)
|
||||
{
|
||||
wxStackFrame frames[MAX_FRAMES];
|
||||
|
||||
if (!ms_symbols || !m_depth)
|
||||
return;
|
||||
|
||||
// we have 3 more "intermediate" frames which the calling code doesn't know
|
||||
// about, account for them
|
||||
skip += 3;
|
||||
|
||||
// call addr2line only once since this call may be very slow
|
||||
// (it has to load in memory the entire EXE of this app which may be quite
|
||||
// big, especially if it contains debug info and is compiled statically!)
|
||||
int towalk = InitFrames(frames, m_depth - skip, &ms_addresses[skip], &ms_symbols[skip]);
|
||||
|
||||
// now do user-defined operations on each frame
|
||||
for ( int n = 0; n < towalk - (int)skip; n++ )
|
||||
OnStackFrame(frames[n]);
|
||||
}
|
||||
|
||||
void wxStackWalker::FreeStack()
|
||||
{
|
||||
// ms_symbols has been allocated by backtrace_symbols() and it's the responsibility
|
||||
// of the caller, i.e. us, to free that pointer
|
||||
if (ms_symbols)
|
||||
free( ms_symbols );
|
||||
ms_symbols = NULL;
|
||||
m_depth = 0;
|
||||
}
|
||||
|
||||
int wxStackWalker::InitFrames(wxStackFrame *arr, size_t n, void **addresses, char **syminfo)
|
||||
{
|
||||
// we need to launch addr2line tool to get this information and we need to
|
||||
// have the program name for this
|
||||
wxString exepath = wxStackWalker::GetExePath();
|
||||
if ( exepath.empty() )
|
||||
{
|
||||
exepath = wxStandardPaths::Get().GetExecutablePath();
|
||||
if ( exepath.empty() )
|
||||
{
|
||||
wxLogDebug(wxT("Cannot parse stack frame because the executable ")
|
||||
wxT("path could not be detected"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// build the (long) command line for executing addr2line in an optimized way
|
||||
// (e.g. use always chars, even in Unicode build: popen() always takes chars)
|
||||
int len = snprintf(g_buf, BUFSIZE, "addr2line -C -f -e \"%s\"", (const char*) exepath.mb_str());
|
||||
len = (len <= 0) ? strlen(g_buf) : len; // in case snprintf() is broken
|
||||
for (size_t i=0; i<n; i++)
|
||||
{
|
||||
snprintf(&g_buf[len], BUFSIZE - len, " %p", addresses[i]);
|
||||
len = strlen(g_buf);
|
||||
}
|
||||
|
||||
//wxLogDebug(wxT("piping the command '%s'"), g_buf); // for debug only
|
||||
|
||||
wxStdioPipe fp(g_buf, "r");
|
||||
if ( !fp )
|
||||
return 0;
|
||||
|
||||
// parse addr2line output (should be exactly 2 lines for each address)
|
||||
// reusing the g_buf used for building the command line above
|
||||
wxString name, filename;
|
||||
unsigned long line = 0,
|
||||
curr = 0;
|
||||
for ( size_t i = 0; i < n; i++ )
|
||||
{
|
||||
// 1st line has function name
|
||||
if ( fgets(g_buf, WXSIZEOF(g_buf), fp) )
|
||||
{
|
||||
name = wxString::FromAscii(g_buf);
|
||||
name.RemoveLast(); // trailing newline
|
||||
|
||||
if ( name == _T("??") )
|
||||
name.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogDebug(_T("cannot read addr2line output for stack frame #%lu"),
|
||||
(unsigned long)i);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2nd one -- the file/line info
|
||||
if ( fgets(g_buf, WXSIZEOF(g_buf), fp) )
|
||||
{
|
||||
filename = wxString::FromAscii(g_buf);
|
||||
filename.RemoveLast();
|
||||
|
||||
const size_t posColon = filename.find(_T(':'));
|
||||
if ( posColon != wxString::npos )
|
||||
{
|
||||
// parse line number (it's ok if it fails, this will just leave
|
||||
// line at its current, invalid, 0 value)
|
||||
wxString(filename, posColon + 1, wxString::npos).ToULong(&line);
|
||||
|
||||
// remove line number from 'filename'
|
||||
filename.erase(posColon);
|
||||
if ( filename == _T("??") )
|
||||
filename.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogDebug(_T("Unexpected addr2line format: \"%s\" - ")
|
||||
_T("the semicolon is missing"),
|
||||
filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// now we've got enough info to initialize curr-th stack frame
|
||||
// (at worst, only addresses[i] and syminfo[i] have been initialized,
|
||||
// but wxStackFrame::OnGetName may still be able to get function name):
|
||||
arr[curr++].Set(name, filename, syminfo[i], i, line, addresses[i]);
|
||||
}
|
||||
|
||||
return curr;
|
||||
}
|
||||
|
||||
void wxStackWalker::Walk(size_t skip, size_t maxDepth)
|
||||
{
|
||||
// read all frames required
|
||||
SaveStack(maxDepth);
|
||||
|
||||
// process them
|
||||
ProcessFrames(skip);
|
||||
|
||||
// cleanup
|
||||
FreeStack();
|
||||
}
|
||||
|
||||
#endif // wxUSE_STACKWALKER
|
220
wxWidgets/src/unix/stdpaths.cpp
Normal file
220
wxWidgets/src/unix/stdpaths.cpp
Normal file
|
@ -0,0 +1,220 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: unix/stdpaths.cpp
|
||||
// Purpose: wxStandardPaths implementation for Unix & OpenVMS systems
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2004-10-19
|
||||
// RCS-ID: $Id: stdpaths.cpp 43443 2006-11-16 13:31:40Z JJ $
|
||||
// Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwindows.org>
|
||||
// License: wxWindows license
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_STDPATHS
|
||||
|
||||
#include "wx/stdpaths.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/utils.h"
|
||||
#endif //WX_PRECOMP
|
||||
|
||||
#include "wx/filename.h"
|
||||
|
||||
#if defined( __LINUX__ ) || defined( __VMS )
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// common VMS/Unix part of wxStandardPaths implementation
|
||||
// ============================================================================
|
||||
|
||||
void wxStandardPaths::SetInstallPrefix(const wxString& prefix)
|
||||
{
|
||||
m_prefix = prefix;
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetUserConfigDir() const
|
||||
{
|
||||
return wxFileName::GetHomeDir();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxStandardPaths implementation for VMS
|
||||
// ============================================================================
|
||||
|
||||
#ifdef __VMS
|
||||
|
||||
wxString wxStandardPaths::GetInstallPrefix() const
|
||||
{
|
||||
if ( m_prefix.empty() )
|
||||
{
|
||||
wx_const_cast(wxStandardPaths *, this)->m_prefix = wxT("/sys$system");
|
||||
}
|
||||
|
||||
return m_prefix;
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetConfigDir() const
|
||||
{
|
||||
return _T("/sys$manager");
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetDataDir() const
|
||||
{
|
||||
return AppendAppName(GetInstallPrefix() + _T("/sys$share"));
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetLocalDataDir() const
|
||||
{
|
||||
return AppendAppName(_T("/sys$manager"));
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetUserDataDir() const
|
||||
{
|
||||
return wxFileName::GetHomeDir();
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetPluginsDir() const
|
||||
{
|
||||
return wxString(); // TODO: this is wrong, it should return something
|
||||
}
|
||||
|
||||
wxString
|
||||
wxStandardPaths::GetLocalizedResourcesDir(const wxChar *lang,
|
||||
ResourceCat category) const
|
||||
{
|
||||
return wxStandardPathsBase::GetLocalizedResourcesDir(lang, category);
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetExecutablePath() const
|
||||
{
|
||||
return wxStandardPathsBase::GetExecutablePath();
|
||||
}
|
||||
|
||||
#else // !__VMS
|
||||
|
||||
// ============================================================================
|
||||
// wxStandardPaths implementation for Unix
|
||||
// ============================================================================
|
||||
|
||||
wxString wxStandardPaths::GetExecutablePath() const
|
||||
{
|
||||
#ifdef __LINUX__
|
||||
wxString exeStr;
|
||||
|
||||
char buf[4096];
|
||||
int result = readlink("/proc/self/exe", buf, WXSIZEOF(buf) - sizeof(char));
|
||||
if ( result != -1 )
|
||||
{
|
||||
buf[result] = '\0'; // readlink() doesn't NUL-terminate the buffer
|
||||
|
||||
// if the /proc/self/exe symlink has been dropped by the kernel for
|
||||
// some reason, then readlink() could also return success but
|
||||
// "(deleted)" as link destination...
|
||||
if ( strcmp(buf, "(deleted)") != 0 )
|
||||
exeStr = wxString(buf, wxConvLibc);
|
||||
}
|
||||
|
||||
if ( exeStr.empty() )
|
||||
{
|
||||
// UPX-specific hack: when using UPX on linux, the kernel will drop the
|
||||
// /proc/self/exe link; in this case we try to look for a special
|
||||
// environment variable called " " which is created by UPX to save
|
||||
// /proc/self/exe contents. See
|
||||
// http://sf.net/tracker/?func=detail&atid=309863&aid=1565357&group_id=9863
|
||||
// for more information about this issue.
|
||||
wxGetEnv(wxT(" "), &exeStr);
|
||||
}
|
||||
|
||||
if ( !exeStr.empty() )
|
||||
return exeStr;
|
||||
#endif // __LINUX__
|
||||
|
||||
return wxStandardPathsBase::GetExecutablePath();
|
||||
}
|
||||
|
||||
void wxStandardPaths::DetectPrefix()
|
||||
{
|
||||
// we can try to infer the prefix from the location of the executable
|
||||
wxString exeStr = GetExecutablePath();
|
||||
if ( !exeStr.empty() )
|
||||
{
|
||||
// consider that we're in the last "bin" subdirectory of our prefix
|
||||
size_t pos = exeStr.rfind(wxT("/bin/"));
|
||||
if ( pos != wxString::npos )
|
||||
m_prefix.assign(exeStr, 0, pos);
|
||||
}
|
||||
|
||||
if ( m_prefix.empty() )
|
||||
{
|
||||
m_prefix = wxT("/usr/local");
|
||||
}
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetInstallPrefix() const
|
||||
{
|
||||
if ( m_prefix.empty() )
|
||||
{
|
||||
wxStandardPaths *pathPtr = wx_const_cast(wxStandardPaths *, this);
|
||||
pathPtr->DetectPrefix();
|
||||
}
|
||||
|
||||
return m_prefix;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// public functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxString wxStandardPaths::GetConfigDir() const
|
||||
{
|
||||
return _T("/etc");
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetDataDir() const
|
||||
{
|
||||
return AppendAppName(GetInstallPrefix() + _T("/share"));
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetLocalDataDir() const
|
||||
{
|
||||
return AppendAppName(_T("/etc"));
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetUserDataDir() const
|
||||
{
|
||||
return AppendAppName(wxFileName::GetHomeDir() + _T("/."));
|
||||
}
|
||||
|
||||
wxString wxStandardPaths::GetPluginsDir() const
|
||||
{
|
||||
return AppendAppName(GetInstallPrefix() + _T("/lib"));
|
||||
}
|
||||
|
||||
wxString
|
||||
wxStandardPaths::GetLocalizedResourcesDir(const wxChar *lang,
|
||||
ResourceCat category) const
|
||||
{
|
||||
if ( category != ResourceCat_Messages )
|
||||
return wxStandardPathsBase::GetLocalizedResourcesDir(lang, category);
|
||||
|
||||
return GetInstallPrefix() + _T("/share/locale/") + lang + _T("/LC_MESSAGES");
|
||||
}
|
||||
|
||||
#endif // __VMS/!__VMS
|
||||
|
||||
#endif // wxUSE_STDPATHS
|
346
wxWidgets/src/unix/taskbarx11.cpp
Normal file
346
wxWidgets/src/unix/taskbarx11.cpp
Normal file
|
@ -0,0 +1,346 @@
|
|||
/////////////////////////////////////////////////////////////////////////
|
||||
// File: src/unix/taskbarx11.cpp
|
||||
// Purpose: wxTaskBarIcon class for common Unix desktops
|
||||
// Author: Vaclav Slavik
|
||||
// Modified by:
|
||||
// Created: 04/04/2003
|
||||
// RCS-ID: $Id: taskbarx11.cpp 53582 2008-05-12 23:54:34Z RD $
|
||||
// Copyright: (c) Vaclav Slavik, 2003
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// NB: This implementation does *not* work with every X11 window manager.
|
||||
// Currently only GNOME 1.2 and KDE 1,2,3 methods are implemented here.
|
||||
// Freedesktop.org's System Tray specification is implemented in
|
||||
// src/gtk/taskbar.cpp and used from here under wxGTK.
|
||||
//
|
||||
// Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
|
||||
// KDE and GNOME 1.2 methods.
|
||||
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef wxHAS_TASK_BAR_ICON
|
||||
|
||||
#include "wx/taskbar.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/frame.h"
|
||||
#include "wx/dcclient.h"
|
||||
#include "wx/statbmp.h"
|
||||
#include "wx/sizer.h"
|
||||
#include "wx/bitmap.h"
|
||||
#include "wx/image.h"
|
||||
#endif
|
||||
|
||||
#ifdef __VMS
|
||||
#pragma message disable nosimpint
|
||||
#endif
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#ifdef __VMS
|
||||
#pragma message enable nosimpint
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// base class that implements toolkit-specific method:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __WXGTK20__
|
||||
#include <gtk/gtk.h>
|
||||
#if GTK_CHECK_VERSION(2,1,0)
|
||||
#include "wx/gtk/taskbarpriv.h"
|
||||
#define TASKBAR_ICON_AREA_BASE_INCLUDED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TASKBAR_ICON_AREA_BASE_INCLUDED
|
||||
class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxFrame
|
||||
{
|
||||
public:
|
||||
wxTaskBarIconAreaBase()
|
||||
: wxFrame(NULL, wxID_ANY, _T("systray icon"),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR |
|
||||
wxSIMPLE_BORDER | wxFRAME_SHAPED) {}
|
||||
|
||||
bool IsProtocolSupported() const { return false; }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// toolkit dependent methods to set properties on helper window:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__WXGTK__)
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#define GetDisplay() GDK_DISPLAY()
|
||||
#define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
|
||||
#elif defined(__WXX11__) || defined(__WXMOTIF__)
|
||||
#include "wx/x11/privx.h"
|
||||
#define GetDisplay() ((Display*)wxGlobalDisplay())
|
||||
#define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
|
||||
#else
|
||||
#error "You must define X11 accessors for this port!"
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTaskBarIconArea is the real window that shows the icon:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_ADV wxTaskBarIconArea : public wxTaskBarIconAreaBase
|
||||
{
|
||||
public:
|
||||
wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp);
|
||||
void SetTrayIcon(const wxBitmap& bmp);
|
||||
bool IsOk() { return true; }
|
||||
|
||||
protected:
|
||||
void SetLegacyWMProperties();
|
||||
|
||||
void OnSizeChange(wxSizeEvent& event);
|
||||
void OnPaint(wxPaintEvent& evt);
|
||||
void OnMouseEvent(wxMouseEvent& event);
|
||||
void OnMenuEvent(wxCommandEvent& event);
|
||||
|
||||
wxTaskBarIcon *m_icon;
|
||||
wxPoint m_pos;
|
||||
wxBitmap m_bmp;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxTaskBarIconAreaBase)
|
||||
EVT_SIZE(wxTaskBarIconArea::OnSizeChange)
|
||||
EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent)
|
||||
EVT_MENU(wxID_ANY, wxTaskBarIconArea::OnMenuEvent)
|
||||
EVT_PAINT(wxTaskBarIconArea::OnPaint)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
|
||||
: wxTaskBarIconAreaBase(), m_icon(icon), m_pos(0,0)
|
||||
{
|
||||
#if defined(__WXGTK20__) && defined(TASKBAR_ICON_AREA_BASE_INCLUDED)
|
||||
m_invokingWindow = icon;
|
||||
#endif
|
||||
|
||||
// Set initial size to bitmap size (tray manager may and often will
|
||||
// change it):
|
||||
SetClientSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));
|
||||
|
||||
SetTrayIcon(bmp);
|
||||
|
||||
if (!IsProtocolSupported())
|
||||
{
|
||||
wxLogTrace(_T("systray"),
|
||||
_T("using legacy KDE1,2 and GNOME 1.2 methods"));
|
||||
SetLegacyWMProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void wxTaskBarIconArea::SetTrayIcon(const wxBitmap& bmp)
|
||||
{
|
||||
m_bmp = bmp;
|
||||
|
||||
// determine suitable bitmap size:
|
||||
wxSize winsize(GetClientSize());
|
||||
wxSize bmpsize(m_bmp.GetWidth(), m_bmp.GetHeight());
|
||||
wxSize iconsize(wxMin(winsize.x, bmpsize.x), wxMin(winsize.y, bmpsize.y));
|
||||
|
||||
// rescale the bitmap to fit into the tray icon window:
|
||||
if (bmpsize != iconsize)
|
||||
{
|
||||
wxImage img = m_bmp.ConvertToImage();
|
||||
img.Rescale(iconsize.x, iconsize.y);
|
||||
m_bmp = wxBitmap(img);
|
||||
}
|
||||
|
||||
wxRegion region;
|
||||
region.Union(m_bmp);
|
||||
|
||||
// if the bitmap is smaller than the window, offset it:
|
||||
if (winsize != iconsize)
|
||||
{
|
||||
m_pos.x = (winsize.x - iconsize.x) / 2;
|
||||
m_pos.y = (winsize.y - iconsize.y) / 2;
|
||||
region.Offset(m_pos.x, m_pos.y);
|
||||
}
|
||||
|
||||
// set frame's shape to correct value and redraw:
|
||||
SetShape(region);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void wxTaskBarIconArea::SetLegacyWMProperties()
|
||||
{
|
||||
#ifdef __WXGTK__
|
||||
gtk_widget_realize(m_widget);
|
||||
#endif
|
||||
|
||||
long data[1];
|
||||
|
||||
// KDE 2 & KDE 3:
|
||||
Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR =
|
||||
XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
|
||||
data[0] = 0;
|
||||
XChangeProperty(GetDisplay(), GetXWindow(this),
|
||||
_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR,
|
||||
XA_WINDOW, 32,
|
||||
PropModeReplace, (unsigned char*)data, 1);
|
||||
|
||||
// GNOME 1.2 & KDE 1:
|
||||
Atom KWM_DOCKWINDOW =
|
||||
XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False);
|
||||
data[0] = 1;
|
||||
XChangeProperty(GetDisplay(), GetXWindow(this),
|
||||
KWM_DOCKWINDOW,
|
||||
KWM_DOCKWINDOW, 32,
|
||||
PropModeReplace, (unsigned char*)data, 1);
|
||||
}
|
||||
|
||||
void wxTaskBarIconArea::OnSizeChange(wxSizeEvent& WXUNUSED(event))
|
||||
{
|
||||
wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"),
|
||||
GetSize().x, GetSize().y);
|
||||
// rescale or reposition the icon as needed:
|
||||
wxBitmap bmp(m_bmp);
|
||||
SetTrayIcon(bmp);
|
||||
}
|
||||
|
||||
void wxTaskBarIconArea::OnPaint(wxPaintEvent& WXUNUSED(event))
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
dc.DrawBitmap(m_bmp, m_pos.x, m_pos.y, true);
|
||||
}
|
||||
|
||||
void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event)
|
||||
{
|
||||
wxEventType type = 0;
|
||||
wxEventType mtype = event.GetEventType();
|
||||
|
||||
if (mtype == wxEVT_LEFT_DOWN)
|
||||
type = wxEVT_TASKBAR_LEFT_DOWN;
|
||||
else if (mtype == wxEVT_LEFT_UP)
|
||||
type = wxEVT_TASKBAR_LEFT_UP;
|
||||
else if (mtype == wxEVT_LEFT_DCLICK)
|
||||
type = wxEVT_TASKBAR_LEFT_DCLICK;
|
||||
else if (mtype == wxEVT_RIGHT_DOWN)
|
||||
type = wxEVT_TASKBAR_RIGHT_DOWN;
|
||||
else if (mtype == wxEVT_RIGHT_UP)
|
||||
type = wxEVT_TASKBAR_RIGHT_UP;
|
||||
else if (mtype == wxEVT_RIGHT_DCLICK)
|
||||
type = wxEVT_TASKBAR_RIGHT_DCLICK;
|
||||
else if (mtype == wxEVT_MOTION)
|
||||
type = wxEVT_TASKBAR_MOVE;
|
||||
else
|
||||
return;
|
||||
|
||||
wxTaskBarIconEvent e(type, m_icon);
|
||||
m_icon->ProcessEvent(e);
|
||||
}
|
||||
|
||||
void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent& event)
|
||||
{
|
||||
m_icon->ProcessEvent(event);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTaskBarIcon class:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
|
||||
|
||||
wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
wxTaskBarIcon::~wxTaskBarIcon()
|
||||
{
|
||||
if (m_iconWnd)
|
||||
{
|
||||
m_iconWnd->Disconnect(wxEVT_DESTROY, (wxObjectEventFunction)NULL,
|
||||
(wxObject*)NULL, this);
|
||||
RemoveIcon();
|
||||
}
|
||||
}
|
||||
|
||||
bool wxTaskBarIcon::IsOk() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxTaskBarIcon::IsIconInstalled() const
|
||||
{
|
||||
return m_iconWnd != NULL;
|
||||
}
|
||||
|
||||
// Destroy event from wxTaskBarIconArea
|
||||
void wxTaskBarIcon::OnDestroy(wxWindowDestroyEvent&)
|
||||
{
|
||||
// prevent crash if wxTaskBarIconArea is destroyed by something else,
|
||||
// for example if panel/kicker is killed
|
||||
m_iconWnd = NULL;
|
||||
}
|
||||
|
||||
bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
|
||||
{
|
||||
wxBitmap bmp;
|
||||
bmp.CopyFromIcon(icon);
|
||||
|
||||
if (!m_iconWnd)
|
||||
{
|
||||
m_iconWnd = new wxTaskBarIconArea(this, bmp);
|
||||
if (m_iconWnd->IsOk())
|
||||
{
|
||||
m_iconWnd->Connect(wxEVT_DESTROY,
|
||||
wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy),
|
||||
NULL, this);
|
||||
m_iconWnd->Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iconWnd->Destroy();
|
||||
m_iconWnd = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iconWnd->SetTrayIcon(bmp);
|
||||
}
|
||||
|
||||
#if wxUSE_TOOLTIPS
|
||||
if (!tooltip.empty())
|
||||
m_iconWnd->SetToolTip(tooltip);
|
||||
else
|
||||
m_iconWnd->SetToolTip(NULL);
|
||||
#else
|
||||
wxUnusedVar(tooltip);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxTaskBarIcon::RemoveIcon()
|
||||
{
|
||||
if (!m_iconWnd)
|
||||
return false;
|
||||
m_iconWnd->Destroy();
|
||||
m_iconWnd = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
|
||||
{
|
||||
if (!m_iconWnd)
|
||||
return false;
|
||||
m_iconWnd->PopupMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // wxHAS_TASK_BAR_ICON
|
1746
wxWidgets/src/unix/threadpsx.cpp
Normal file
1746
wxWidgets/src/unix/threadpsx.cpp
Normal file
File diff suppressed because it is too large
Load diff
1362
wxWidgets/src/unix/utilsunx.cpp
Normal file
1362
wxWidgets/src/unix/utilsunx.cpp
Normal file
File diff suppressed because it is too large
Load diff
847
wxWidgets/src/unix/utilsx11.cpp
Normal file
847
wxWidgets/src/unix/utilsx11.cpp
Normal file
|
@ -0,0 +1,847 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/utilsx11.cpp
|
||||
// Purpose: Miscellaneous X11 functions
|
||||
// Author: Mattia Barbon, Vaclav Slavik, Robert Roebling
|
||||
// Modified by:
|
||||
// Created: 25.03.02
|
||||
// RCS-ID: $Id: utilsx11.cpp 44895 2007-03-18 17:49:06Z VZ $
|
||||
// Copyright: (c) wxWidgets team
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__)
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include "wx/unix/utilsx11.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/icon.h"
|
||||
#include "wx/image.h"
|
||||
#endif
|
||||
|
||||
#include "wx/iconbndl.h"
|
||||
|
||||
#ifdef __VMS
|
||||
#pragma message disable nosimpint
|
||||
#endif
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#ifdef __VMS
|
||||
#pragma message enable nosimpint
|
||||
#endif
|
||||
|
||||
#ifdef __WXGTK__
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
// Various X11 Atoms used in this file:
|
||||
static Atom _NET_WM_ICON = 0;
|
||||
static Atom _NET_WM_STATE = 0;
|
||||
static Atom _NET_WM_STATE_FULLSCREEN = 0;
|
||||
static Atom _NET_WM_STATE_STAYS_ON_TOP = 0;
|
||||
static Atom _NET_WM_WINDOW_TYPE = 0;
|
||||
static Atom _NET_WM_WINDOW_TYPE_NORMAL = 0;
|
||||
static Atom _KDE_NET_WM_WINDOW_TYPE_OVERRIDE = 0;
|
||||
static Atom _WIN_LAYER = 0;
|
||||
static Atom KWIN_RUNNING = 0;
|
||||
#ifndef __WXGTK20__
|
||||
static Atom _NET_SUPPORTING_WM_CHECK = 0;
|
||||
static Atom _NET_SUPPORTED = 0;
|
||||
#endif
|
||||
|
||||
#define wxMAKE_ATOM(name, display) \
|
||||
if (name == 0) name = XInternAtom((display), #name, False)
|
||||
|
||||
|
||||
// X11 Window is an int type, so use the macro to suppress warnings when
|
||||
// converting to it
|
||||
#define WindowCast(w) (Window)(wxPtrToUInt(w))
|
||||
|
||||
// Is the window mapped?
|
||||
static bool IsMapped(Display *display, Window window)
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
XGetWindowAttributes(display, window, &attr);
|
||||
return (attr.map_state != IsUnmapped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Suspends X11 errors. Used when we expect errors but they are not fatal
|
||||
// for us.
|
||||
extern "C"
|
||||
{
|
||||
typedef int (*wxX11ErrorHandler)(Display *, XErrorEvent *);
|
||||
|
||||
static int wxX11ErrorsSuspender_handler(Display*, XErrorEvent*) { return 0; }
|
||||
}
|
||||
|
||||
class wxX11ErrorsSuspender
|
||||
{
|
||||
public:
|
||||
wxX11ErrorsSuspender(Display *d) : m_display(d)
|
||||
{
|
||||
m_old = XSetErrorHandler(wxX11ErrorsSuspender_handler);
|
||||
}
|
||||
~wxX11ErrorsSuspender()
|
||||
{
|
||||
XFlush(m_display);
|
||||
XSetErrorHandler(m_old);
|
||||
}
|
||||
|
||||
private:
|
||||
Display *m_display;
|
||||
wxX11ErrorHandler m_old;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Setting icons for window manager:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxSetIconsX11( WXDisplay* display, WXWindow window,
|
||||
const wxIconBundle& ib )
|
||||
{
|
||||
#if !wxUSE_NANOX
|
||||
size_t size = 0;
|
||||
size_t i, max = ib.m_icons.GetCount();
|
||||
|
||||
for( i = 0; i < max; ++i )
|
||||
if( ib.m_icons[i].Ok() )
|
||||
size += 2 + ib.m_icons[i].GetWidth() * ib.m_icons[i].GetHeight();
|
||||
|
||||
wxMAKE_ATOM(_NET_WM_ICON, (Display*)display);
|
||||
|
||||
if( size > 0 )
|
||||
{
|
||||
// The code below is correct for 64-bit machines also.
|
||||
// wxUint32* data = new wxUint32[size];
|
||||
// wxUint32* ptr = data;
|
||||
unsigned long* data = new unsigned long[size];
|
||||
unsigned long* ptr = data;
|
||||
|
||||
for( i = 0; i < max; ++i )
|
||||
{
|
||||
const wxImage image = ib.m_icons[i].ConvertToImage();
|
||||
int width = image.GetWidth(), height = image.GetHeight();
|
||||
unsigned char* imageData = image.GetData();
|
||||
unsigned char* imageDataEnd = imageData + ( width * height * 3 );
|
||||
bool hasMask = image.HasMask();
|
||||
unsigned char rMask, gMask, bMask;
|
||||
unsigned char r, g, b, a;
|
||||
|
||||
if( hasMask )
|
||||
{
|
||||
rMask = image.GetMaskRed();
|
||||
gMask = image.GetMaskGreen();
|
||||
bMask = image.GetMaskBlue();
|
||||
}
|
||||
else // no mask, but still init the variables to avoid warnings
|
||||
{
|
||||
rMask =
|
||||
gMask =
|
||||
bMask = 0;
|
||||
}
|
||||
|
||||
*ptr++ = width;
|
||||
*ptr++ = height;
|
||||
|
||||
while( imageData < imageDataEnd ) {
|
||||
r = imageData[0];
|
||||
g = imageData[1];
|
||||
b = imageData[2];
|
||||
if( hasMask && r == rMask && g == gMask && b == bMask )
|
||||
a = 0;
|
||||
else
|
||||
a = 255;
|
||||
|
||||
*ptr++ = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
|
||||
|
||||
imageData += 3;
|
||||
}
|
||||
}
|
||||
|
||||
XChangeProperty( (Display*)display,
|
||||
WindowCast(window),
|
||||
_NET_WM_ICON,
|
||||
XA_CARDINAL, 32,
|
||||
PropModeReplace,
|
||||
(unsigned char*)data, size );
|
||||
delete[] data;
|
||||
}
|
||||
else
|
||||
{
|
||||
XDeleteProperty( (Display*)display,
|
||||
WindowCast(window),
|
||||
_NET_WM_ICON );
|
||||
}
|
||||
#endif // !wxUSE_NANOX
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Fullscreen mode:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// NB: Setting fullscreen mode under X11 is a complicated matter. There was
|
||||
// no standard way of doing it until recently. ICCCM doesn't know the
|
||||
// concept of fullscreen windows and the only way to make a window
|
||||
// fullscreen is to remove decorations, resize it to cover entire screen
|
||||
// and set WIN_LAYER_ABOVE_DOCK.
|
||||
//
|
||||
// This doesn't always work, though. Specifically, at least kwin from
|
||||
// KDE 3 ignores the hint. The only way to make kwin accept our request
|
||||
// is to emulate the way Qt does it. That is, unmap the window, set
|
||||
// _NET_WM_WINDOW_TYPE to _KDE_NET_WM_WINDOW_TYPE_OVERRIDE (KDE extension),
|
||||
// add _NET_WM_STATE_STAYS_ON_TOP (ditto) to _NET_WM_STATE and map
|
||||
// the window again.
|
||||
//
|
||||
// Version 1.2 of Window Manager Specification (aka wm-spec aka
|
||||
// Extended Window Manager Hints) introduced _NET_WM_STATE_FULLSCREEN
|
||||
// window state which provides cleanest and simplest possible way of
|
||||
// making a window fullscreen. WM-spec is a de-facto standard adopted
|
||||
// by GNOME and KDE folks, but _NET_WM_STATE_FULLSCREEN isn't yet widely
|
||||
// supported. As of January 2003, only GNOME 2's default WM Metacity
|
||||
// implements, KDE will support it from version 3.2. At toolkits level,
|
||||
// GTK+ >= 2.1.2 uses it as the only method of making windows fullscreen
|
||||
// (that's why wxGTK will *not* switch to using gtk_window_fullscreen
|
||||
// unless it has better compatibility with older WMs).
|
||||
//
|
||||
//
|
||||
// This is what wxWidgets does in wxSetFullScreenStateX11:
|
||||
// 1) if _NET_WM_STATE_FULLSCREEN is supported, use it
|
||||
// 2) otherwise try WM-specific hacks (KDE, IceWM)
|
||||
// 3) use _WIN_LAYER and hope that the WM will recognize it
|
||||
// The code was tested with:
|
||||
// twm, IceWM, WindowMaker, Metacity, kwin, sawfish, lesstif-mwm
|
||||
|
||||
|
||||
#define WIN_LAYER_NORMAL 4
|
||||
#define WIN_LAYER_ABOVE_DOCK 10
|
||||
|
||||
static void wxWinHintsSetLayer(Display *display, Window rootWnd,
|
||||
Window window, int layer)
|
||||
{
|
||||
wxX11ErrorsSuspender noerrors(display);
|
||||
|
||||
XEvent xev;
|
||||
|
||||
wxMAKE_ATOM( _WIN_LAYER, display );
|
||||
|
||||
if (IsMapped(display, window))
|
||||
{
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.window = window;
|
||||
xev.xclient.message_type = _WIN_LAYER;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = (long)layer;
|
||||
xev.xclient.data.l[1] = CurrentTime;
|
||||
|
||||
XSendEvent(display, rootWnd, False,
|
||||
SubstructureNotifyMask, (XEvent*) &xev);
|
||||
}
|
||||
else
|
||||
{
|
||||
long data[1];
|
||||
|
||||
data[0] = layer;
|
||||
XChangeProperty(display, window,
|
||||
_WIN_LAYER, XA_CARDINAL, 32,
|
||||
PropModeReplace, (unsigned char *)data, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __WXGTK20__
|
||||
static bool wxQueryWMspecSupport(Display* WXUNUSED(display),
|
||||
Window WXUNUSED(rootWnd),
|
||||
Atom (feature))
|
||||
{
|
||||
GdkAtom gatom = gdk_x11_xatom_to_atom(feature);
|
||||
return gdk_net_wm_supports(gatom);
|
||||
}
|
||||
#else
|
||||
static bool wxQueryWMspecSupport(Display *display, Window rootWnd, Atom feature)
|
||||
{
|
||||
wxMAKE_ATOM(_NET_SUPPORTING_WM_CHECK, display);
|
||||
wxMAKE_ATOM(_NET_SUPPORTED, display);
|
||||
|
||||
// FIXME: We may want to cache these checks. Note that we can't simply
|
||||
// remember the results in global variable because the WM may go
|
||||
// away and be replaced by another one! One possible approach
|
||||
// would be invalidate the case every 15 seconds or so. Since this
|
||||
// code is currently only used by wxTopLevelWindow::ShowFullScreen,
|
||||
// it is not important that it is not optimized.
|
||||
//
|
||||
// If the WM supports ICCCM (i.e. the root window has
|
||||
// _NET_SUPPORTING_WM_CHECK property that points to a WM-owned
|
||||
// window), we could watch for DestroyNotify event on the window
|
||||
// and invalidate our cache when the windows goes away (= WM
|
||||
// is replaced by another one). This is what GTK+ 2 does.
|
||||
// Let's do it only if it is needed, it requires changes to
|
||||
// the event loop.
|
||||
|
||||
Atom type;
|
||||
Window *wins;
|
||||
Atom *atoms;
|
||||
int format;
|
||||
unsigned long after;
|
||||
unsigned long nwins, natoms;
|
||||
|
||||
// Is the WM ICCCM supporting?
|
||||
XGetWindowProperty(display, rootWnd,
|
||||
_NET_SUPPORTING_WM_CHECK, 0, LONG_MAX,
|
||||
False, XA_WINDOW, &type, &format, &nwins,
|
||||
&after, (unsigned char **)&wins);
|
||||
if ( type != XA_WINDOW || nwins <= 0 || wins[0] == None )
|
||||
return false;
|
||||
XFree(wins);
|
||||
|
||||
// Query for supported features:
|
||||
XGetWindowProperty(display, rootWnd,
|
||||
_NET_SUPPORTED, 0, LONG_MAX,
|
||||
False, XA_ATOM, &type, &format, &natoms,
|
||||
&after, (unsigned char **)&atoms);
|
||||
if ( type != XA_ATOM || atoms == NULL )
|
||||
return false;
|
||||
|
||||
// Lookup the feature we want:
|
||||
for (unsigned i = 0; i < natoms; i++)
|
||||
{
|
||||
if ( atoms[i] == feature )
|
||||
{
|
||||
XFree(atoms);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
XFree(atoms);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0
|
||||
#define _NET_WM_STATE_ADD 1
|
||||
|
||||
static void wxWMspecSetState(Display *display, Window rootWnd,
|
||||
Window window, int operation, Atom state)
|
||||
{
|
||||
wxMAKE_ATOM(_NET_WM_STATE, display);
|
||||
|
||||
if ( IsMapped(display, window) )
|
||||
{
|
||||
XEvent xev;
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.display = display;
|
||||
xev.xclient.window = window;
|
||||
xev.xclient.message_type = _NET_WM_STATE;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = operation;
|
||||
xev.xclient.data.l[1] = state;
|
||||
xev.xclient.data.l[2] = None;
|
||||
|
||||
XSendEvent(display, rootWnd,
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xev);
|
||||
}
|
||||
// FIXME - must modify _NET_WM_STATE property list if the window
|
||||
// wasn't mapped!
|
||||
}
|
||||
|
||||
static void wxWMspecSetFullscreen(Display *display, Window rootWnd,
|
||||
Window window, bool fullscreen)
|
||||
{
|
||||
wxMAKE_ATOM(_NET_WM_STATE_FULLSCREEN, display);
|
||||
wxWMspecSetState(display, rootWnd,
|
||||
window,
|
||||
fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
|
||||
_NET_WM_STATE_FULLSCREEN);
|
||||
}
|
||||
|
||||
|
||||
// Is the user running KDE's kwin window manager? At least kwin from KDE 3
|
||||
// sets KWIN_RUNNING property on the root window.
|
||||
static bool wxKwinRunning(Display *display, Window rootWnd)
|
||||
{
|
||||
wxMAKE_ATOM(KWIN_RUNNING, display);
|
||||
|
||||
long *data;
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long nitems, after;
|
||||
if (XGetWindowProperty(display, rootWnd,
|
||||
KWIN_RUNNING, 0, 1, False, KWIN_RUNNING,
|
||||
&type, &format, &nitems, &after,
|
||||
(unsigned char**)&data) != Success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool retval = (type == KWIN_RUNNING &&
|
||||
nitems == 1 && data && data[0] == 1);
|
||||
XFree(data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// KDE's kwin is Qt-centric so much than no normal method of fullscreen
|
||||
// mode will work with it. We have to carefully emulate the Qt way.
|
||||
static void wxSetKDEFullscreen(Display *display, Window rootWnd,
|
||||
Window w, bool fullscreen, wxRect *origRect)
|
||||
{
|
||||
long data[2];
|
||||
unsigned lng;
|
||||
|
||||
wxMAKE_ATOM(_NET_WM_WINDOW_TYPE, display);
|
||||
wxMAKE_ATOM(_NET_WM_WINDOW_TYPE_NORMAL, display);
|
||||
wxMAKE_ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE, display);
|
||||
wxMAKE_ATOM(_NET_WM_STATE_STAYS_ON_TOP, display);
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
data[0] = _KDE_NET_WM_WINDOW_TYPE_OVERRIDE;
|
||||
data[1] = _NET_WM_WINDOW_TYPE_NORMAL;
|
||||
lng = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0] = _NET_WM_WINDOW_TYPE_NORMAL;
|
||||
data[1] = None;
|
||||
lng = 1;
|
||||
}
|
||||
|
||||
// it is necessary to unmap the window, otherwise kwin will ignore us:
|
||||
XSync(display, False);
|
||||
|
||||
bool wasMapped = IsMapped(display, w);
|
||||
if (wasMapped)
|
||||
{
|
||||
XUnmapWindow(display, w);
|
||||
XSync(display, False);
|
||||
}
|
||||
|
||||
XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *) &data[0], lng);
|
||||
XSync(display, False);
|
||||
|
||||
if (wasMapped)
|
||||
{
|
||||
XMapRaised(display, w);
|
||||
XSync(display, False);
|
||||
}
|
||||
|
||||
wxWMspecSetState(display, rootWnd, w,
|
||||
fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
|
||||
_NET_WM_STATE_STAYS_ON_TOP);
|
||||
XSync(display, False);
|
||||
|
||||
if (!fullscreen)
|
||||
{
|
||||
// NB: like many other WMs, kwin ignores the first request for a window
|
||||
// position change after the window was mapped. This additional
|
||||
// move+resize event will ensure that the window is restored in
|
||||
// exactly the same position as before it was made fullscreen
|
||||
// (because wxTopLevelWindow::ShowFullScreen will call SetSize, thus
|
||||
// setting the position for the second time).
|
||||
XMoveResizeWindow(display, w,
|
||||
origRect->x, origRect->y,
|
||||
origRect->width, origRect->height);
|
||||
XSync(display, False);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxX11FullScreenMethod wxGetFullScreenMethodX11(WXDisplay* display,
|
||||
WXWindow rootWindow)
|
||||
{
|
||||
Window root = WindowCast(rootWindow);
|
||||
Display *disp = (Display*)display;
|
||||
|
||||
// if WM supports _NET_WM_STATE_FULLSCREEN from wm-spec 1.2, use it:
|
||||
wxMAKE_ATOM(_NET_WM_STATE_FULLSCREEN, disp);
|
||||
if (wxQueryWMspecSupport(disp, root, _NET_WM_STATE_FULLSCREEN))
|
||||
{
|
||||
wxLogTrace(_T("fullscreen"),
|
||||
_T("detected _NET_WM_STATE_FULLSCREEN support"));
|
||||
return wxX11_FS_WMSPEC;
|
||||
}
|
||||
|
||||
// if the user is running KDE's kwin WM, use a legacy hack because
|
||||
// kwin doesn't understand any other method:
|
||||
if (wxKwinRunning(disp, root))
|
||||
{
|
||||
wxLogTrace(_T("fullscreen"), _T("detected kwin"));
|
||||
return wxX11_FS_KDE;
|
||||
}
|
||||
|
||||
// finally, fall back to ICCCM heuristic method:
|
||||
wxLogTrace(_T("fullscreen"), _T("unknown WM, using _WIN_LAYER"));
|
||||
return wxX11_FS_GENERIC;
|
||||
}
|
||||
|
||||
|
||||
void wxSetFullScreenStateX11(WXDisplay* display, WXWindow rootWindow,
|
||||
WXWindow window, bool show,
|
||||
wxRect *origRect,
|
||||
wxX11FullScreenMethod method)
|
||||
{
|
||||
// NB: please see the comment under "Fullscreen mode:" title above
|
||||
// for implications of changing this code.
|
||||
|
||||
Window wnd = WindowCast(window);
|
||||
Window root = WindowCast(rootWindow);
|
||||
Display *disp = (Display*)display;
|
||||
|
||||
if (method == wxX11_FS_AUTODETECT)
|
||||
method = wxGetFullScreenMethodX11(display, rootWindow);
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case wxX11_FS_WMSPEC:
|
||||
wxWMspecSetFullscreen(disp, root, wnd, show);
|
||||
break;
|
||||
case wxX11_FS_KDE:
|
||||
wxSetKDEFullscreen(disp, root, wnd, show, origRect);
|
||||
break;
|
||||
default:
|
||||
wxWinHintsSetLayer(disp, root, wnd,
|
||||
show ? WIN_LAYER_ABOVE_DOCK : WIN_LAYER_NORMAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// keycode translations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <X11/keysym.h>
|
||||
|
||||
// FIXME what about tables??
|
||||
|
||||
int wxCharCodeXToWX(KeySym keySym)
|
||||
{
|
||||
int id;
|
||||
switch (keySym)
|
||||
{
|
||||
case XK_Shift_L:
|
||||
case XK_Shift_R:
|
||||
id = WXK_SHIFT; break;
|
||||
case XK_Control_L:
|
||||
case XK_Control_R:
|
||||
id = WXK_CONTROL; break;
|
||||
case XK_Meta_L:
|
||||
case XK_Meta_R:
|
||||
id = WXK_ALT; break;
|
||||
case XK_Caps_Lock:
|
||||
id = WXK_CAPITAL; break;
|
||||
case XK_BackSpace:
|
||||
id = WXK_BACK; break;
|
||||
case XK_Delete:
|
||||
id = WXK_DELETE; break;
|
||||
case XK_Clear:
|
||||
id = WXK_CLEAR; break;
|
||||
case XK_Tab:
|
||||
id = WXK_TAB; break;
|
||||
case XK_numbersign:
|
||||
id = '#'; break;
|
||||
case XK_Return:
|
||||
id = WXK_RETURN; break;
|
||||
case XK_Escape:
|
||||
id = WXK_ESCAPE; break;
|
||||
case XK_Pause:
|
||||
case XK_Break:
|
||||
id = WXK_PAUSE; break;
|
||||
case XK_Num_Lock:
|
||||
id = WXK_NUMLOCK; break;
|
||||
case XK_Scroll_Lock:
|
||||
id = WXK_SCROLL; break;
|
||||
|
||||
case XK_Home:
|
||||
id = WXK_HOME; break;
|
||||
case XK_End:
|
||||
id = WXK_END; break;
|
||||
case XK_Left:
|
||||
id = WXK_LEFT; break;
|
||||
case XK_Right:
|
||||
id = WXK_RIGHT; break;
|
||||
case XK_Up:
|
||||
id = WXK_UP; break;
|
||||
case XK_Down:
|
||||
id = WXK_DOWN; break;
|
||||
case XK_Next:
|
||||
id = WXK_PAGEDOWN; break;
|
||||
case XK_Prior:
|
||||
id = WXK_PAGEUP; break;
|
||||
case XK_Menu:
|
||||
id = WXK_MENU; break;
|
||||
case XK_Select:
|
||||
id = WXK_SELECT; break;
|
||||
case XK_Cancel:
|
||||
id = WXK_CANCEL; break;
|
||||
case XK_Print:
|
||||
id = WXK_PRINT; break;
|
||||
case XK_Execute:
|
||||
id = WXK_EXECUTE; break;
|
||||
case XK_Insert:
|
||||
id = WXK_INSERT; break;
|
||||
case XK_Help:
|
||||
id = WXK_HELP; break;
|
||||
|
||||
case XK_KP_Multiply:
|
||||
id = WXK_NUMPAD_MULTIPLY; break;
|
||||
case XK_KP_Add:
|
||||
id = WXK_NUMPAD_ADD; break;
|
||||
case XK_KP_Subtract:
|
||||
id = WXK_NUMPAD_SUBTRACT; break;
|
||||
case XK_KP_Divide:
|
||||
id = WXK_NUMPAD_DIVIDE; break;
|
||||
case XK_KP_Decimal:
|
||||
id = WXK_NUMPAD_DECIMAL; break;
|
||||
case XK_KP_Equal:
|
||||
id = WXK_NUMPAD_EQUAL; break;
|
||||
case XK_KP_Space:
|
||||
id = WXK_NUMPAD_SPACE; break;
|
||||
case XK_KP_Tab:
|
||||
id = WXK_NUMPAD_TAB; break;
|
||||
case XK_KP_Enter:
|
||||
id = WXK_NUMPAD_ENTER; break;
|
||||
case XK_KP_0:
|
||||
id = WXK_NUMPAD0; break;
|
||||
case XK_KP_1:
|
||||
id = WXK_NUMPAD1; break;
|
||||
case XK_KP_2:
|
||||
id = WXK_NUMPAD2; break;
|
||||
case XK_KP_3:
|
||||
id = WXK_NUMPAD3; break;
|
||||
case XK_KP_4:
|
||||
id = WXK_NUMPAD4; break;
|
||||
case XK_KP_5:
|
||||
id = WXK_NUMPAD5; break;
|
||||
case XK_KP_6:
|
||||
id = WXK_NUMPAD6; break;
|
||||
case XK_KP_7:
|
||||
id = WXK_NUMPAD7; break;
|
||||
case XK_KP_8:
|
||||
id = WXK_NUMPAD8; break;
|
||||
case XK_KP_9:
|
||||
id = WXK_NUMPAD9; break;
|
||||
case XK_KP_Insert:
|
||||
id = WXK_NUMPAD_INSERT; break;
|
||||
case XK_KP_End:
|
||||
id = WXK_NUMPAD_END; break;
|
||||
case XK_KP_Down:
|
||||
id = WXK_NUMPAD_DOWN; break;
|
||||
case XK_KP_Page_Down:
|
||||
id = WXK_NUMPAD_PAGEDOWN; break;
|
||||
case XK_KP_Left:
|
||||
id = WXK_NUMPAD_LEFT; break;
|
||||
case XK_KP_Right:
|
||||
id = WXK_NUMPAD_RIGHT; break;
|
||||
case XK_KP_Home:
|
||||
id = WXK_NUMPAD_HOME; break;
|
||||
case XK_KP_Up:
|
||||
id = WXK_NUMPAD_UP; break;
|
||||
case XK_KP_Page_Up:
|
||||
id = WXK_NUMPAD_PAGEUP; break;
|
||||
case XK_F1:
|
||||
id = WXK_F1; break;
|
||||
case XK_F2:
|
||||
id = WXK_F2; break;
|
||||
case XK_F3:
|
||||
id = WXK_F3; break;
|
||||
case XK_F4:
|
||||
id = WXK_F4; break;
|
||||
case XK_F5:
|
||||
id = WXK_F5; break;
|
||||
case XK_F6:
|
||||
id = WXK_F6; break;
|
||||
case XK_F7:
|
||||
id = WXK_F7; break;
|
||||
case XK_F8:
|
||||
id = WXK_F8; break;
|
||||
case XK_F9:
|
||||
id = WXK_F9; break;
|
||||
case XK_F10:
|
||||
id = WXK_F10; break;
|
||||
case XK_F11:
|
||||
id = WXK_F11; break;
|
||||
case XK_F12:
|
||||
id = WXK_F12; break;
|
||||
case XK_F13:
|
||||
id = WXK_F13; break;
|
||||
case XK_F14:
|
||||
id = WXK_F14; break;
|
||||
case XK_F15:
|
||||
id = WXK_F15; break;
|
||||
case XK_F16:
|
||||
id = WXK_F16; break;
|
||||
case XK_F17:
|
||||
id = WXK_F17; break;
|
||||
case XK_F18:
|
||||
id = WXK_F18; break;
|
||||
case XK_F19:
|
||||
id = WXK_F19; break;
|
||||
case XK_F20:
|
||||
id = WXK_F20; break;
|
||||
case XK_F21:
|
||||
id = WXK_F21; break;
|
||||
case XK_F22:
|
||||
id = WXK_F22; break;
|
||||
case XK_F23:
|
||||
id = WXK_F23; break;
|
||||
case XK_F24:
|
||||
id = WXK_F24; break;
|
||||
default:
|
||||
id = (keySym <= 255) ? (int)keySym : -1;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
KeySym wxCharCodeWXToX(int id)
|
||||
{
|
||||
KeySym keySym;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case WXK_CANCEL: keySym = XK_Cancel; break;
|
||||
case WXK_BACK: keySym = XK_BackSpace; break;
|
||||
case WXK_TAB: keySym = XK_Tab; break;
|
||||
case WXK_CLEAR: keySym = XK_Clear; break;
|
||||
case WXK_RETURN: keySym = XK_Return; break;
|
||||
case WXK_SHIFT: keySym = XK_Shift_L; break;
|
||||
case WXK_CONTROL: keySym = XK_Control_L; break;
|
||||
case WXK_ALT: keySym = XK_Meta_L; break;
|
||||
case WXK_CAPITAL: keySym = XK_Caps_Lock; break;
|
||||
case WXK_MENU : keySym = XK_Menu; break;
|
||||
case WXK_PAUSE: keySym = XK_Pause; break;
|
||||
case WXK_ESCAPE: keySym = XK_Escape; break;
|
||||
case WXK_SPACE: keySym = ' '; break;
|
||||
case WXK_PAGEUP: keySym = XK_Prior; break;
|
||||
case WXK_PAGEDOWN: keySym = XK_Next; break;
|
||||
case WXK_END: keySym = XK_End; break;
|
||||
case WXK_HOME : keySym = XK_Home; break;
|
||||
case WXK_LEFT : keySym = XK_Left; break;
|
||||
case WXK_UP: keySym = XK_Up; break;
|
||||
case WXK_RIGHT: keySym = XK_Right; break;
|
||||
case WXK_DOWN : keySym = XK_Down; break;
|
||||
case WXK_SELECT: keySym = XK_Select; break;
|
||||
case WXK_PRINT: keySym = XK_Print; break;
|
||||
case WXK_EXECUTE: keySym = XK_Execute; break;
|
||||
case WXK_INSERT: keySym = XK_Insert; break;
|
||||
case WXK_DELETE: keySym = XK_Delete; break;
|
||||
case WXK_HELP : keySym = XK_Help; break;
|
||||
case WXK_NUMPAD0: keySym = XK_KP_0; break; case WXK_NUMPAD_INSERT: keySym = XK_KP_Insert; break;
|
||||
case WXK_NUMPAD1: keySym = XK_KP_1; break; case WXK_NUMPAD_END: keySym = XK_KP_End; break;
|
||||
case WXK_NUMPAD2: keySym = XK_KP_2; break; case WXK_NUMPAD_DOWN: keySym = XK_KP_Down; break;
|
||||
case WXK_NUMPAD3: keySym = XK_KP_3; break; case WXK_NUMPAD_PAGEDOWN: keySym = XK_KP_Page_Down; break;
|
||||
case WXK_NUMPAD4: keySym = XK_KP_4; break; case WXK_NUMPAD_LEFT: keySym = XK_KP_Left; break;
|
||||
case WXK_NUMPAD5: keySym = XK_KP_5; break;
|
||||
case WXK_NUMPAD6: keySym = XK_KP_6; break; case WXK_NUMPAD_RIGHT: keySym = XK_KP_Right; break;
|
||||
case WXK_NUMPAD7: keySym = XK_KP_7; break; case WXK_NUMPAD_HOME: keySym = XK_KP_Home; break;
|
||||
case WXK_NUMPAD8: keySym = XK_KP_8; break; case WXK_NUMPAD_UP: keySym = XK_KP_Up; break;
|
||||
case WXK_NUMPAD9: keySym = XK_KP_9; break; case WXK_NUMPAD_PAGEUP: keySym = XK_KP_Page_Up; break;
|
||||
case WXK_NUMPAD_DECIMAL: keySym = XK_KP_Decimal; break; case WXK_NUMPAD_DELETE: keySym = XK_KP_Delete; break;
|
||||
case WXK_NUMPAD_MULTIPLY: keySym = XK_KP_Multiply; break;
|
||||
case WXK_NUMPAD_ADD: keySym = XK_KP_Add; break;
|
||||
case WXK_NUMPAD_SUBTRACT: keySym = XK_KP_Subtract; break;
|
||||
case WXK_NUMPAD_DIVIDE: keySym = XK_KP_Divide; break;
|
||||
case WXK_NUMPAD_ENTER: keySym = XK_KP_Enter; break;
|
||||
case WXK_NUMPAD_SEPARATOR: keySym = XK_KP_Separator; break;
|
||||
case WXK_F1: keySym = XK_F1; break;
|
||||
case WXK_F2: keySym = XK_F2; break;
|
||||
case WXK_F3: keySym = XK_F3; break;
|
||||
case WXK_F4: keySym = XK_F4; break;
|
||||
case WXK_F5: keySym = XK_F5; break;
|
||||
case WXK_F6: keySym = XK_F6; break;
|
||||
case WXK_F7: keySym = XK_F7; break;
|
||||
case WXK_F8: keySym = XK_F8; break;
|
||||
case WXK_F9: keySym = XK_F9; break;
|
||||
case WXK_F10: keySym = XK_F10; break;
|
||||
case WXK_F11: keySym = XK_F11; break;
|
||||
case WXK_F12: keySym = XK_F12; break;
|
||||
case WXK_F13: keySym = XK_F13; break;
|
||||
case WXK_F14: keySym = XK_F14; break;
|
||||
case WXK_F15: keySym = XK_F15; break;
|
||||
case WXK_F16: keySym = XK_F16; break;
|
||||
case WXK_F17: keySym = XK_F17; break;
|
||||
case WXK_F18: keySym = XK_F18; break;
|
||||
case WXK_F19: keySym = XK_F19; break;
|
||||
case WXK_F20: keySym = XK_F20; break;
|
||||
case WXK_F21: keySym = XK_F21; break;
|
||||
case WXK_F22: keySym = XK_F22; break;
|
||||
case WXK_F23: keySym = XK_F23; break;
|
||||
case WXK_F24: keySym = XK_F24; break;
|
||||
case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
|
||||
case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
|
||||
default: keySym = id <= 255 ? (KeySym)id : 0;
|
||||
}
|
||||
|
||||
return keySym;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// check current state of a key
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxGetKeyState(wxKeyCode key)
|
||||
{
|
||||
wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key !=
|
||||
WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons"));
|
||||
|
||||
Display *pDisplay = (Display*) wxGetDisplay();
|
||||
|
||||
int iKey = wxCharCodeWXToX(key);
|
||||
int iKeyMask = 0;
|
||||
Window wDummy1, wDummy2;
|
||||
int iDummy3, iDummy4, iDummy5, iDummy6;
|
||||
unsigned int iMask;
|
||||
KeyCode keyCode = XKeysymToKeycode(pDisplay,iKey);
|
||||
if (keyCode == NoSymbol)
|
||||
return false;
|
||||
|
||||
if ( IsModifierKey(iKey) ) // If iKey is a modifier key, use a different method
|
||||
{
|
||||
XModifierKeymap *map = XGetModifierMapping(pDisplay);
|
||||
wxCHECK_MSG( map, false, _T("failed to get X11 modifiers map") );
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if ( map->modifiermap[map->max_keypermod * i] == keyCode)
|
||||
{
|
||||
iKeyMask = 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
XQueryPointer(pDisplay, DefaultRootWindow(pDisplay), &wDummy1, &wDummy2,
|
||||
&iDummy3, &iDummy4, &iDummy5, &iDummy6, &iMask );
|
||||
XFreeModifiermap(map);
|
||||
return (iMask & iKeyMask) != 0;
|
||||
}
|
||||
|
||||
// From the XLib manual:
|
||||
// The XQueryKeymap() function returns a bit vector for the logical state of the keyboard,
|
||||
// where each bit set to 1 indicates that the corresponding key is currently pressed down.
|
||||
// The vector is represented as 32 bytes. Byte N (from 0) contains the bits for keys 8N to 8N + 7
|
||||
// with the least-significant bit in the byte representing key 8N.
|
||||
char key_vector[32];
|
||||
XQueryKeymap(pDisplay, key_vector);
|
||||
return key_vector[keyCode >> 3] & (1 << (keyCode & 7));
|
||||
}
|
||||
|
||||
#endif // __WXX11__ || __WXGTK__ || __WXMOTIF__
|
Loading…
Add table
Add a link
Reference in a new issue