mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-08-09 14:06:04 -05:00
From wxWidgets master 81570ae070b35c9d52de47b1f14897f3ff1a66c7. include/wx/defs.h -- __w64 warning disable patch by comex brought forward. include/wx/msw/window.h -- added GetContentScaleFactor() which was not implemented on Windows but is necessary for wxBitmap scaling on Mac OS X so it needs to work to avoid #ifdef-ing the code. src/gtk/window.cpp -- Modified DoSetClientSize() to direct call wxWindowGTK::DoSetSize() instead of using public wxWindowBase::SetSize() which now prevents derived classes (like wxAuiToolbar) intercepting the call and breaking it. This matches Windows which does NOT need to call DoSetSize internally. End result is this fixes Dolphin's debug tools toolbars on Linux. src/osx/window_osx.cpp -- Same fix as for GTK since it has the same issue. src/msw/radiobox.cpp -- Hacked to fix display in HiDPI (was clipping off end of text). Updated CMakeLists for Linux and Mac OS X. Small code changes to Dolphin to fix debug error boxes, deprecation warnings, and retain previous UI behavior on Windows.
306 lines
8.4 KiB
C++
306 lines
8.4 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/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)
|
|
// 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
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// loading/unloading DLLs
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxDllType wxDynamicLibrary::GetProgramHandle()
|
|
{
|
|
#ifdef USE_POSIX_DL_FUNCS
|
|
return 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),
|
|
wxT("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 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
|
|
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 = 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()
|
|
{
|
|
wxString err(dlerror());
|
|
|
|
if ( err.empty() )
|
|
err = _("Unknown dynamic library error");
|
|
|
|
wxLogError(wxT("%s"), err);
|
|
}
|
|
|
|
#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(wxT('/'));
|
|
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(wxT(".so"));
|
|
if ( posExt != wxString::npos )
|
|
{
|
|
if ( path.c_str()[posExt + 3] == wxT('.') )
|
|
{
|
|
// assume "libfoo.so.x.y.z" case
|
|
details->m_version.assign(path, posExt + 4, wxString::npos);
|
|
}
|
|
else
|
|
{
|
|
size_t posDash = path.find_last_of(wxT('-'), 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(wxT("/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(wxT("Failed to parse line \"%s\" in /proc/self/maps."),
|
|
buf);
|
|
continue;
|
|
}
|
|
|
|
wxASSERT_MSG( start >= endCur,
|
|
wxT("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;
|
|
}
|
|
|
|
|
|
/* static */
|
|
void* wxDynamicLibrary::GetModuleFromAddress(const void* addr, wxString* path)
|
|
{
|
|
#ifdef HAVE_DLADDR
|
|
Dl_info di = { 0 };
|
|
|
|
// At least under Solaris dladdr() takes non-const void*.
|
|
if ( dladdr(const_cast<void*>(addr), &di) == 0 )
|
|
return NULL;
|
|
|
|
if ( path )
|
|
*path = di.dli_fname;
|
|
|
|
return di.dli_fbase;
|
|
#endif // HAVE_DLADDR
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#endif // wxUSE_DYNLIB_CLASS
|
|
|