nspluginwrapper-0.9.91.5
Taken from Debian orig.tar.gz file.
This commit is contained in:
parent
9d165ef722
commit
485815be8a
172
ChangeLog
172
ChangeLog
|
@ -1,3 +1,175 @@
|
|||
2007-08-26 06:31 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Nuke the window border, it's quite disturbing
|
||||
to see it during resizing.
|
||||
|
||||
2007-08-25 23:03 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
|
||||
2007-08-25 22:48 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS, nspluginwrapper.spec: 0.9.91.5
|
||||
|
||||
2007-08-25 22:46 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npruntime.c, src/npw-viewer.c: Remove NPW_DISABLE_NPRUNTIME,
|
||||
npruntime support has been working for a long time now.
|
||||
Similarly, remove dummy npruntime handlers now that the common
|
||||
supported NPAPI version is passed down.
|
||||
|
||||
2007-08-25 22:37 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c: Pass down common NPAPI
|
||||
version supported by both the browser and nspluginwrapper. We no
|
||||
longer need to check for npruntime support ourselves, rely only
|
||||
on the NPAPI version reported. Yes, if the browser lies we may
|
||||
crash, but that's be browser's fault anyway.
|
||||
|
||||
2007-08-25 07:05 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Implement LONG64 NPP_New() and NPP_Destroy().
|
||||
Fix NPStream functions so that it works with correct 64-bit
|
||||
Konqueror versions too. i.e. check for identify stream.
|
||||
|
||||
2007-08-25 07:01 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix memory leak when we don't want the
|
||||
NPP_Destroy() NPSavedData. Remove useless comment since the
|
||||
feature was implemented.
|
||||
|
||||
2007-08-25 06:59 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix NPP_GetValue(NPPVformValue) and call new
|
||||
g_NPN_MemAlloc().
|
||||
|
||||
2007-08-24 16:07 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Run-time detect broken 64-bit Konqueror
|
||||
browsers and use another layer of thunks in that case.
|
||||
|
||||
2007-08-22 22:26 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
* NEWS, nspluginwrapper.spec: Updates.
|
||||
|
||||
2007-08-22 22:23 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* utils/xtrace.c: Add XCreateWindow() wrapper.
|
||||
|
||||
2007-08-22 22:20 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-rpc.c, src/npw-wrapper.c: Implement NPAPI 0.15
|
||||
FORM_VALUES, i.e. support NPP_GetValue(NPPVformValue,..).
|
||||
|
||||
2007-08-22 21:51 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-rpc.h, src/npw-viewer.c, src/npw-wrapper.c: Implement
|
||||
NPAPI 0.16 NPN_PushPopupsEnabledState() and
|
||||
NPN_PopPopupsEnabledState().
|
||||
|
||||
2007-08-22 20:43 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* npapi/npapi.h, src/npw-viewer.c, src/npw-wrapper.c: Implement
|
||||
NPAPI 0.17 RESPONSE_HEADERS, i.e. propagate NPStream::headers to
|
||||
the plug-in if it is available (NULL otherwise). Fix NPStream
|
||||
initialization for NPN_NewStream().
|
||||
|
||||
2007-08-22 19:23 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* Makefile: Fix build on Debian 4.0 'Etch' (and derivatives)
|
||||
though libxpcom.so is currently not used and other distributions
|
||||
were capable enough to compile it without the LSB build-env
|
||||
hacks.
|
||||
|
||||
2007-08-21 22:12 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Fix Flash Player 9 Update 3 beta plugin
|
||||
support with XEMBED.
|
||||
|
||||
2007-08-21 05:02 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Fix a (long) compiler warning.
|
||||
|
||||
2007-08-21 05:00 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Fix a potential buffer overflow.
|
||||
|
||||
2007-08-20 21:46 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS, configure, src/npw-config-template.h, src/npw-config.c:
|
||||
Add support for 64-bit plugins and fix elf_swap_sym_32() for
|
||||
st_shndx swapping (Martin Stransky).
|
||||
|
||||
2007-08-19 22:38 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
* Makefile: Make "make changelog" update the ChangeLog only,
|
||||
without committing the result.
|
||||
|
||||
2007-08-19 17:30 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* nspluginwrapper.spec: BuildRequires: gtk2-devel everywhere
|
||||
(gtk+2-devel was MDK specific).
|
||||
|
||||
2007-08-19 17:24 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* NEWS, nspluginwrapper.spec: Next release is 0.9.91.5.
|
||||
|
||||
2007-08-19 17:23 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-rpc.h, src/npw-viewer.c, src/npw-wrapper.c: Add
|
||||
NPN_NewStream(), NPN_DestroyStream(), NPN_Write() support. Fix
|
||||
NPP_Write() return value on error.
|
||||
|
||||
2007-08-19 09:31 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* npapi/npapi.h, npapi/nptypes.h, npapi/npupp.h: NPAPI updates.
|
||||
|
||||
2007-08-19 09:02 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/npw-wrapper.c: Rewrite protocol to pass
|
||||
cached MIME info and plugin name/description strings. This now
|
||||
is insensitive to possible garbage printed out during the call
|
||||
to the plugin functions.
|
||||
|
||||
2007-08-19 08:01 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-wrapper.c: Drop initialization/destruction locks since
|
||||
RPC handlers have been called from the Mozilla main loop for a
|
||||
long time now (and not from a separate thread).
|
||||
|
||||
2007-08-19 07:44 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Clean-up global NP funcs wrappers.
|
||||
|
||||
2007-08-19 06:45 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c: Override NPPVpluginNeedsXEmbed at a more
|
||||
natural place.
|
||||
|
||||
2007-08-18 23:43 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* src/npw-viewer.c, src/xembed.h: Fix focus problems (Debian bug
|
||||
#435912).
|
||||
|
||||
2007-08-18 23:13 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* utils/xtrace.c: Add a few more functions and details.
|
||||
|
||||
2007-08-11 10:55 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* tests/test-plugins.html: Add link for Debian bug report #435912.
|
||||
|
||||
2007-04-04 06:27 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* TODO, src/npw-config.c, src/npw-viewer.sh: Improve fix for
|
||||
"don't load native plugins".
|
||||
|
||||
2007-04-03 18:00 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* ChangeLog: Generated by svn2cl.
|
||||
|
||||
2007-04-03 17:59 Gwenole Beauchesne <gb.public@free.fr>
|
||||
|
||||
* lsb-build/headers/stddef.h: Fix NULL definition for C (openSUSE
|
||||
|
|
5
Makefile
5
Makefile
|
@ -121,6 +121,10 @@ libxpcom_RAWSRCS = libxpcom.c debug.c
|
|||
libxpcom_SOURCES = $(libxpcom_RAWSRCS:%.c=$(SRC_PATH)/src/%.c)
|
||||
libxpcom_OBJECTS = $(libxpcom_RAWSRCS:%.c=libxpcom-%.o)
|
||||
libxpcom_CFLAGS = -fPIC
|
||||
ifeq ($(biarch),yes)
|
||||
libxpcom_CFLAGS += -I$(LSB_INC_DIR)
|
||||
libxpcom_LDFLAGS = $(LDFLAGS_32) -L$(LSB_OBJ_DIR)
|
||||
endif
|
||||
|
||||
npconfig_PROGRAM = npconfig
|
||||
npconfig_RAWSRCS = npw-config.c
|
||||
|
@ -282,6 +286,7 @@ localrpm: $(archivedir)$(SRCARCHIVE).bz2
|
|||
changelog: ../common/authors.xml
|
||||
svn_prefix=`svn info .|sed -n '/^URL *: .*\/svn\/\(.*\)$$/s//\1\//p'`; \
|
||||
svn2cl --strip-prefix=$$svn_prefix --authors=../common/authors.xml || :
|
||||
changelog.commit: changelog
|
||||
svn commit -m "Generated by svn2cl." ChangeLog
|
||||
|
||||
$(npwrapper_LIBRARY): $(npwrapper_OBJECTS)
|
||||
|
|
10
NEWS
10
NEWS
|
@ -1,6 +1,14 @@
|
|||
nspluginwrapper NEWS -- history of user-visible changes. 2007-04-03
|
||||
nspluginwrapper NEWS -- history of user-visible changes. 2007-08-26
|
||||
Copyright (C) 2005-2007 Gwenole Beauchesne
|
||||
|
||||
Version 0.9.91.5 (BETA) - 26.Aug.2007
|
||||
* Fix a memory leak in NPP_Destroy()
|
||||
* Fix DiamondX XEmbed example plugin
|
||||
* Fix focus problems (Debian bug #435912)
|
||||
* Add support for 64-bit plugins (Martin Stransky)
|
||||
* Add support for newer NPAPI 0.17 functions and variables
|
||||
* Add support for broken 64-bit Konqueror versions (run-time detect)
|
||||
|
||||
Version 0.9.91.4 (BETA) - 03.Apr.2007
|
||||
* Don't try to wrap native plugins
|
||||
* Fix build on NetBSD (David Brownlee)
|
||||
|
|
5
TODO
5
TODO
|
@ -1,3 +1,8 @@
|
|||
- Fix "don't try to load native plugins"
|
||||
* This currently works because we don't ship with native viewers
|
||||
* Otherwise, the plugin OS,ARCH characterisation through ELF headers only
|
||||
works for Linux / FreeBSD where they have dedicated tags
|
||||
=> This was only useful for Linux/i386 platforms anyway ATM
|
||||
- Clean-ups
|
||||
* Re-indent -gnu -br -brs
|
||||
* Better split for RPC / NAPI level routines
|
||||
|
|
|
@ -647,6 +647,10 @@ if test "$target_cpu" = "i386" ; then
|
|||
echo "TARGET_ARCH=i386" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"i386\"" >> $config_h
|
||||
echo "#define TARGET_I386 1" >> $config_h
|
||||
elif test "$target_cpu" = "x86_64" ; then
|
||||
echo "TARGET_ARCH=x86_64" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
|
||||
echo "#define TARGET_X86_64 1" >> $config_h
|
||||
elif test "$target_cpu" = "ppc" ; then
|
||||
echo "TARGET_ARCH=ppc" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define NP_VERSION_MAJOR 0
|
||||
#define NP_VERSION_MINOR 14
|
||||
#define NP_VERSION_MINOR 17
|
||||
|
||||
|
||||
/* The OS/2 version of Netscape uses RC_DATA to define the
|
||||
|
@ -256,6 +256,16 @@ typedef struct _NPStream
|
|||
uint32 end;
|
||||
uint32 lastmodified;
|
||||
void* notifyData;
|
||||
const char* headers; /* Response headers from host.
|
||||
* Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
|
||||
* Used for HTTP only; NULL for non-HTTP.
|
||||
* Available from NPP_NewStream onwards.
|
||||
* Plugin should copy this data before storing it.
|
||||
* Includes HTTP status line and all headers,
|
||||
* preferably verbatim as received from server,
|
||||
* headers formatted as in HTTP ("Header: Value"),
|
||||
* and newlines (\n, NOT \r\n) separating lines.
|
||||
* Terminated by \n\0 (NOT \n\n\0). */
|
||||
} NPStream;
|
||||
|
||||
|
||||
|
@ -385,13 +395,24 @@ typedef enum {
|
|||
NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
|
||||
NPPVpluginScriptableIID = 11,
|
||||
|
||||
/* 12 and over are available on Mozilla builds starting with 0.9.9 */
|
||||
/* Introduced in Mozilla 0.9.9 */
|
||||
NPPVjavascriptPushCallerBool = 12,
|
||||
NPPVpluginKeepLibraryInMemory = 13, /* available in Mozilla 1.0 */
|
||||
|
||||
/* Introduced in Mozilla 1.0 */
|
||||
NPPVpluginKeepLibraryInMemory = 13,
|
||||
NPPVpluginNeedsXEmbed = 14,
|
||||
|
||||
/* Get the NPObject for scripting the plugin. */
|
||||
NPPVpluginScriptableNPObject = 15
|
||||
/* Get the NPObject for scripting the plugin. Introduced in Firefox
|
||||
* 1.0 (NPAPI minor version 14).
|
||||
*/
|
||||
NPPVpluginScriptableNPObject = 15,
|
||||
|
||||
/* Get the plugin value (as \0-terminated UTF-8 string data) for
|
||||
* form submission if the plugin is part of a form. Use
|
||||
* NPN_MemAlloc() to allocate memory for the string data. Introduced
|
||||
* in Mozilla 1.8b2 (NPAPI minor version 15).
|
||||
*/
|
||||
NPPVformValue = 16
|
||||
} NPPVariable;
|
||||
|
||||
/*
|
||||
|
@ -604,13 +625,17 @@ enum NPEventType {
|
|||
/*
|
||||
* Version feature information
|
||||
*/
|
||||
#define NPVERS_HAS_STREAMOUTPUT 8
|
||||
#define NPVERS_HAS_NOTIFICATION 9
|
||||
#define NPVERS_HAS_LIVECONNECT 9
|
||||
#define NPVERS_WIN16_HAS_LIVECONNECT 9
|
||||
#define NPVERS_68K_HAS_LIVECONNECT 11
|
||||
#define NPVERS_HAS_WINDOWLESS 11
|
||||
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
|
||||
#define NPVERS_HAS_STREAMOUTPUT 8
|
||||
#define NPVERS_HAS_NOTIFICATION 9
|
||||
#define NPVERS_HAS_LIVECONNECT 9
|
||||
#define NPVERS_WIN16_HAS_LIVECONNECT 9
|
||||
#define NPVERS_68K_HAS_LIVECONNECT 11
|
||||
#define NPVERS_HAS_WINDOWLESS 11
|
||||
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
|
||||
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
|
||||
#define NPVERS_HAS_FORM_VALUES 15
|
||||
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
|
||||
#define NPVERS_HAS_RESPONSE_HEADERS 17
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Function Prototypes */
|
||||
|
@ -663,9 +688,6 @@ void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
|
|||
jref NP_LOADDS NPP_GetJavaClass(void);
|
||||
#endif
|
||||
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
|
||||
/*
|
||||
* Uh, shouldn't NPP_SetValue() take an NPPVariable and not an NPNVariable?
|
||||
*/
|
||||
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
|
||||
|
||||
/*
|
||||
|
@ -704,6 +726,8 @@ NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable, void *value);
|
|||
void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
|
||||
void NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
|
||||
void NP_LOADDS NPN_ForceRedraw(NPP instance);
|
||||
void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
|
||||
void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
*/
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX)
|
||||
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
|
||||
/*
|
||||
* AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
|
||||
* but not bool for C.
|
||||
|
@ -67,19 +67,15 @@
|
|||
|
||||
/*
|
||||
* BSD/OS ships no header that defines uint32_t, nor bool (for C)
|
||||
* OpenBSD ships no header that defines uint32_t, but provides bool as a
|
||||
* macro.
|
||||
* OpenBSD ships no header that defines uint32_t and using its bool macro is
|
||||
* unsafe.
|
||||
*/
|
||||
#if defined(bsdi) || defined(OPENBSD)
|
||||
typedef u_int32_t uint32_t;
|
||||
|
||||
#if defined(bsdi)
|
||||
#if !defined(__cplusplus)
|
||||
typedef int bool;
|
||||
#endif
|
||||
#else /* OPENBSD is defined, so use its bool */
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
* FreeBSD defines uint32_t and bool.
|
||||
|
|
|
@ -1586,6 +1586,58 @@ typedef void (* NP_LOADDS NPN_SetExceptionUPP)(NPObject *obj, const NPUTF8 *mess
|
|||
|
||||
#endif
|
||||
|
||||
/* NPN_PushPopupsEnabledStateUPP */
|
||||
|
||||
#if _NPUPP_USE_UPP_
|
||||
|
||||
typedef UniversalProcPtr NPN_PushPopupsEnabledStateUPP;
|
||||
enum {
|
||||
uppNPN_PushPopupsEnabledStateProcInfo = kThinkCStackBased
|
||||
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP)))
|
||||
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPBool)))
|
||||
| RESULT_SIZE(SIZE_CODE(0))
|
||||
};
|
||||
|
||||
#define NewNPN_PushPopupsEnabledStateProc(FUNC) \
|
||||
(NPN_PushPopupsEnabledStateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PushPopupsEnabledStateProcInfo, GetCurrentArchitecture())
|
||||
#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \
|
||||
(jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PushPopupsEnabledStateProcInfo, (ARG1), (ARG2))
|
||||
|
||||
#else
|
||||
|
||||
typedef bool (* NP_LOADDS NPN_PushPopupsEnabledStateUPP)(NPP npp, NPBool enabled);
|
||||
#define NewNPN_PushPopupsEnabledStateProc(FUNC) \
|
||||
((NPN_PushPopupsEnabledStateUPP) (FUNC))
|
||||
#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \
|
||||
(*(FUNC))((ARG1), (ARG2))
|
||||
|
||||
#endif
|
||||
|
||||
/* NPN_PopPopupsEnabledState */
|
||||
|
||||
#if _NPUPP_USE_UPP_
|
||||
|
||||
typedef UniversalProcPtr NPN_PopPopupsEnabledStateUPP;
|
||||
enum {
|
||||
uppNPN_PopPopupsEnabledStateProcInfo = kThinkCStackBased
|
||||
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP)))
|
||||
| RESULT_SIZE(SIZE_CODE(0))
|
||||
};
|
||||
|
||||
#define NewNPN_PopPopupsEnabledStateProc(FUNC) \
|
||||
(NPN_PopPopupsEnabledStateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PopPopupsEnabledStateProcInfo, GetCurrentArchitecture())
|
||||
#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \
|
||||
(jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PopPopupsEnabledStateProcInfo, (ARG1))
|
||||
|
||||
#else
|
||||
|
||||
typedef bool (* NP_LOADDS NPN_PopPopupsEnabledStateUPP)(NPP npp);
|
||||
#define NewNPN_PopPopupsEnabledStateProc(FUNC) \
|
||||
((NPN_PopPopupsEnabledStateUPP) (FUNC))
|
||||
#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \
|
||||
(*(FUNC))((ARG1))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -1661,6 +1713,8 @@ typedef struct _NPNetscapeFuncs {
|
|||
NPN_HasMethodUPP hasmethod;
|
||||
NPN_ReleaseVariantValueUPP releasevariantvalue;
|
||||
NPN_SetExceptionUPP setexception;
|
||||
NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate;
|
||||
NPN_PopPopupsEnabledStateUPP poppopupsenabledstate;
|
||||
} NPNetscapeFuncs;
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%define name nspluginwrapper
|
||||
%define version 0.9.91.4
|
||||
%define version 0.9.91.5
|
||||
%define release 1
|
||||
#define svndate 20070403
|
||||
#define svndate 20070826
|
||||
|
||||
# define 32-bit arch of multiarch platforms
|
||||
%define arch_32 %{nil}
|
||||
|
@ -53,7 +53,7 @@ Source0: %{name}-%{version}%{?svndate:-%{svndate}}.tar.bz2
|
|||
License: GPL
|
||||
Group: Networking/WWW
|
||||
Url: http://gwenole.beauchesne.info/projects/nspluginwrapper/
|
||||
BuildRequires: gtk+2-devel
|
||||
BuildRequires: gtk2-devel
|
||||
Provides: %{name}-%{_arch} = %{version}-%{release}
|
||||
Requires: %{name}-%{target_arch} = %{version}-%{release}
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
|
||||
|
@ -158,6 +158,14 @@ fi
|
|||
%endif
|
||||
|
||||
%changelog
|
||||
* Sun Aug 26 2007 Gwenole Beauchesne <gb.public@free.fr> 0.9.91.5-1
|
||||
- fix a memory leak in NPP_Destroy()
|
||||
- fix DiamondX XEmbed example plugin
|
||||
- fix focus problems (debian bug #435912)
|
||||
- add support for 64-bit plugins (Martin Stransky)
|
||||
- add support for newer NPAPI 0.17 functions and variables
|
||||
- add support for broken 64-bit Konqueror versions (run-time detect)
|
||||
|
||||
* Mon Apr 2 2007 Gwenole Beauchesne <gb.public@free.fr> 0.9.91.4-1
|
||||
- use anonymous sockets by default
|
||||
- don't try to wrap native plugins
|
||||
|
|
|
@ -0,0 +1,753 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim:expandtab:shiftwidth=2:tabstop=2: */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Gtk2XtBin Widget Implementation.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* The GtkXtBin widget allows for Xt toolkit code to be used
|
||||
* inside a GTK application.
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include "xembed.h"
|
||||
#include "gtk2xtbin.h"
|
||||
|
||||
/* Xlib/Xt stuff */
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Shell.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/StringDefs.h>
|
||||
|
||||
/* uncomment this if you want debugging information about widget
|
||||
creation and destruction */
|
||||
#define DEBUG_XTBIN 1
|
||||
|
||||
static void gtk_xtbin_class_init (GtkXtBinClass *klass);
|
||||
static void gtk_xtbin_init (GtkXtBin *xtbin);
|
||||
static void gtk_xtbin_realize (GtkWidget *widget);
|
||||
static void gtk_xtbin_unrealize (GtkWidget *widget);
|
||||
static void gtk_xtbin_destroy (GtkObject *object);
|
||||
static void gtk_xtbin_shutdown (GtkObject *object);
|
||||
|
||||
/* Xt aware XEmbed */
|
||||
static void xt_client_init (XtClient * xtclient,
|
||||
Display *xtdisplay,
|
||||
Visual *xtvisual,
|
||||
Colormap xtcolormap,
|
||||
int xtdepth);
|
||||
static void xt_client_create (XtClient * xtclient,
|
||||
Window embeder,
|
||||
int height,
|
||||
int width );
|
||||
static void xt_client_unrealize (XtClient* xtclient);
|
||||
static void xt_client_destroy (XtClient* xtclient);
|
||||
static void xt_client_set_info (Widget xtplug,
|
||||
unsigned long flags);
|
||||
static void xt_client_event_handler (Widget w,
|
||||
XtPointer client_data,
|
||||
XEvent *event);
|
||||
static void xt_client_handle_xembed_message (Widget w,
|
||||
XtPointer client_data,
|
||||
XEvent *event);
|
||||
static void xt_client_focus_listener (Widget w,
|
||||
XtPointer user_data,
|
||||
XEvent *event);
|
||||
static void xt_add_focus_listener( Widget w, XtPointer user_data );
|
||||
static void xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data);
|
||||
static void xt_remove_focus_listener(Widget w, XtPointer user_data);
|
||||
static void send_xembed_message (XtClient *xtclient,
|
||||
long message,
|
||||
long detail,
|
||||
long data1,
|
||||
long data2,
|
||||
long time);
|
||||
static int error_handler (Display *display,
|
||||
XErrorEvent *error);
|
||||
/* For error trap of XEmbed */
|
||||
static void trap_errors(void);
|
||||
static int untrap_errors(void);
|
||||
static int (*old_error_handler) (Display *, XErrorEvent *);
|
||||
static int trapped_error_code = 0;
|
||||
|
||||
static GtkWidgetClass *parent_class = NULL;
|
||||
|
||||
GtkType
|
||||
gtk_xtbin_get_type (void)
|
||||
{
|
||||
static GtkType xtbin_type = 0;
|
||||
|
||||
if (!xtbin_type) {
|
||||
static const GtkTypeInfo xtbin_info =
|
||||
{
|
||||
"GtkXtBin",
|
||||
sizeof (GtkXtBin),
|
||||
sizeof (GtkXtBinClass),
|
||||
(GtkClassInitFunc) gtk_xtbin_class_init,
|
||||
(GtkObjectInitFunc) gtk_xtbin_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL
|
||||
};
|
||||
xtbin_type = gtk_type_unique (GTK_TYPE_SOCKET, &xtbin_info);
|
||||
}
|
||||
return xtbin_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_xtbin_class_init (GtkXtBinClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
parent_class = gtk_type_class (GTK_TYPE_SOCKET);
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
widget_class->realize = gtk_xtbin_realize;
|
||||
widget_class->unrealize = gtk_xtbin_unrealize;
|
||||
|
||||
object_class = GTK_OBJECT_CLASS (klass);
|
||||
object_class->destroy = gtk_xtbin_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_xtbin_init (GtkXtBin *xtbin)
|
||||
{
|
||||
xtbin->xtdisplay = NULL;
|
||||
xtbin->parent_window = NULL;
|
||||
xtbin->xtwindow = 0;
|
||||
xtbin->x = 0;
|
||||
xtbin->y = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_xtbin_realize (GtkWidget *widget)
|
||||
{
|
||||
GtkXtBin *xtbin;
|
||||
GtkAllocation allocation = { 0, 0, 200, 200 };
|
||||
gint x, y, w, h, d; /* geometry of window */
|
||||
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("gtk_xtbin_realize()\n");
|
||||
#endif
|
||||
|
||||
g_return_if_fail (GTK_IS_XTBIN (widget));
|
||||
|
||||
xtbin = GTK_XTBIN (widget);
|
||||
|
||||
/* caculate the allocation before realize */
|
||||
gdk_window_get_geometry(xtbin->parent_window, &x, &y, &w, &h, &d);
|
||||
allocation.width = w;
|
||||
allocation.height = h;
|
||||
gtk_widget_size_allocate (widget, &allocation);
|
||||
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("initial allocation %d %d %d %d\n", x, y, w, h);
|
||||
#endif
|
||||
|
||||
xtbin->width = widget->allocation.width;
|
||||
xtbin->height = widget->allocation.height;
|
||||
|
||||
/* use GtkSocket's realize */
|
||||
(*GTK_WIDGET_CLASS(parent_class)->realize)(widget);
|
||||
|
||||
/* create the Xt client widget */
|
||||
xt_client_create(&(xtbin->xtclient),
|
||||
gtk_socket_get_id(GTK_SOCKET(xtbin)),
|
||||
xtbin->height,
|
||||
xtbin->width);
|
||||
xtbin->xtwindow = XtWindow(xtbin->xtclient.child_widget);
|
||||
|
||||
gdk_flush();
|
||||
|
||||
/* now that we have created the xt client, add it to the socket. */
|
||||
gtk_socket_add_id(GTK_SOCKET(widget), xtbin->xtwindow);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GtkWidget*
|
||||
gtk_xtbin_new (GdkWindow *parent_window,
|
||||
Display *xtdisplay,
|
||||
Visual *xtvisual,
|
||||
Colormap xtcolormap,
|
||||
int xtdepth)
|
||||
{
|
||||
GtkXtBin *xtbin;
|
||||
gpointer user_data;
|
||||
|
||||
assert(parent_window != NULL);
|
||||
xtbin = gtk_type_new (GTK_TYPE_XTBIN);
|
||||
|
||||
if (!xtbin)
|
||||
return (GtkWidget*)NULL;
|
||||
|
||||
/* Initialize the Xt toolkit */
|
||||
xtbin->parent_window = parent_window;
|
||||
|
||||
xt_client_init(&(xtbin->xtclient), xtdisplay, xtvisual, xtcolormap, xtdepth);
|
||||
|
||||
/* Build the hierachy */
|
||||
assert(xtbin->xtclient.xtdisplay != NULL);
|
||||
xtbin->xtdisplay = xtbin->xtclient.xtdisplay;
|
||||
gtk_widget_set_parent_window(GTK_WIDGET(xtbin), parent_window);
|
||||
gdk_window_get_user_data(xtbin->parent_window, &user_data);
|
||||
if (user_data)
|
||||
gtk_container_add(GTK_CONTAINER(user_data), GTK_WIDGET(xtbin));
|
||||
|
||||
return GTK_WIDGET (xtbin);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_xtbin_set_position (GtkXtBin *xtbin,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
xtbin->x = x;
|
||||
xtbin->y = y;
|
||||
|
||||
if (GTK_WIDGET_REALIZED (xtbin))
|
||||
gdk_window_move (GTK_WIDGET (xtbin)->window, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_xtbin_resize (GtkWidget *widget,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
Arg args[2];
|
||||
GtkXtBin *xtbin = GTK_XTBIN (widget);
|
||||
GtkAllocation allocation;
|
||||
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("gtk_xtbin_resize %p %d %d\n", (void *)widget, width, height);
|
||||
#endif
|
||||
|
||||
XtSetArg(args[0], XtNheight, height);
|
||||
XtSetArg(args[1], XtNwidth, width);
|
||||
XtSetValues(xtbin->xtclient.top_widget, args, 2);
|
||||
xtbin->height = height;
|
||||
xtbin->width = width;
|
||||
|
||||
/* we need to send a size allocate so the socket knows about the
|
||||
size changes */
|
||||
allocation.x = xtbin->x;
|
||||
allocation.y = xtbin->y;
|
||||
allocation.width = xtbin->width;
|
||||
allocation.height = xtbin->height;
|
||||
|
||||
gtk_widget_size_allocate(widget, &allocation);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_xtbin_unrealize (GtkWidget *object)
|
||||
{
|
||||
GtkXtBin *xtbin;
|
||||
GtkWidget *widget;
|
||||
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("gtk_xtbin_unrealize()\n");
|
||||
#endif
|
||||
|
||||
/* gtk_object_destroy() will already hold a refcount on object
|
||||
*/
|
||||
xtbin = GTK_XTBIN(object);
|
||||
widget = GTK_WIDGET(object);
|
||||
|
||||
GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
|
||||
if (GTK_WIDGET_REALIZED (widget)) {
|
||||
xt_client_unrealize(&(xtbin->xtclient));
|
||||
}
|
||||
|
||||
(*GTK_WIDGET_CLASS (parent_class)->unrealize)(widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_xtbin_destroy (GtkObject *object)
|
||||
{
|
||||
GtkXtBin *xtbin;
|
||||
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("gtk_xtbin_destroy()\n");
|
||||
#endif
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GTK_IS_XTBIN (object));
|
||||
|
||||
xtbin = GTK_XTBIN (object);
|
||||
|
||||
if(xtbin->xtwindow) {
|
||||
/* remove the event handler */
|
||||
xt_client_destroy(&(xtbin->xtclient));
|
||||
xtbin->xtwindow = 0;
|
||||
}
|
||||
|
||||
GTK_OBJECT_CLASS(parent_class)->destroy(object);
|
||||
}
|
||||
|
||||
/*
|
||||
* Following is the implementation of Xt XEmbedded for client side
|
||||
*/
|
||||
|
||||
/* Initial Xt plugin */
|
||||
static void
|
||||
xt_client_init( XtClient * xtclient,
|
||||
Display *xtdisplay,
|
||||
Visual *xtvisual,
|
||||
Colormap xtcolormap,
|
||||
int xtdepth)
|
||||
{
|
||||
xtclient->top_widget = NULL;
|
||||
xtclient->child_widget = NULL;
|
||||
xtclient->xtdisplay = xtdisplay;
|
||||
xtclient->xtvisual = xtvisual;
|
||||
xtclient->xtcolormap = xtcolormap;
|
||||
xtclient->xtdepth = xtdepth;
|
||||
}
|
||||
|
||||
/* Create the Xt client widgets
|
||||
* */
|
||||
static void
|
||||
xt_client_create ( XtClient* xtclient ,
|
||||
Window embedderid,
|
||||
int height,
|
||||
int width )
|
||||
{
|
||||
int n;
|
||||
Arg args[6];
|
||||
Widget child_widget;
|
||||
Widget top_widget;
|
||||
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("xt_client_create() \n");
|
||||
#endif
|
||||
String app_name, app_class;
|
||||
XtGetApplicationNameAndClass(xtclient->xtdisplay, &app_name, &app_class);
|
||||
top_widget = XtAppCreateShell("drawingArea", app_class,
|
||||
applicationShellWidgetClass,
|
||||
xtclient->xtdisplay,
|
||||
NULL, 0);
|
||||
xtclient->top_widget = top_widget;
|
||||
|
||||
/* set size of Xt window */
|
||||
n = 0;
|
||||
XtSetArg(args[n], XtNheight, height);n++;
|
||||
XtSetArg(args[n], XtNwidth, width);n++;
|
||||
XtSetValues(top_widget, args, n);
|
||||
|
||||
child_widget = XtVaCreateWidget("form",
|
||||
compositeWidgetClass,
|
||||
top_widget, NULL);
|
||||
|
||||
n = 0;
|
||||
XtSetArg(args[n], XtNheight, height);n++;
|
||||
XtSetArg(args[n], XtNwidth, width);n++;
|
||||
XtSetArg(args[n], XtNvisual, xtclient->xtvisual ); n++;
|
||||
XtSetArg(args[n], XtNdepth, xtclient->xtdepth ); n++;
|
||||
XtSetArg(args[n], XtNcolormap, xtclient->xtcolormap ); n++;
|
||||
XtSetArg(args[n], XtNborderWidth, 0); n++;
|
||||
XtSetValues(child_widget, args, n);
|
||||
|
||||
XSync(xtclient->xtdisplay, FALSE);
|
||||
xtclient->oldwindow = top_widget->core.window;
|
||||
top_widget->core.window = embedderid;
|
||||
|
||||
/* this little trick seems to finish initializing the widget */
|
||||
#if XlibSpecificationRelease >= 6
|
||||
XtRegisterDrawable(xtclient->xtdisplay,
|
||||
embedderid,
|
||||
top_widget);
|
||||
#else
|
||||
_XtRegisterWindow( embedderid,
|
||||
top_widget);
|
||||
#endif
|
||||
XtRealizeWidget(child_widget);
|
||||
|
||||
/* listen to all Xt events */
|
||||
XSelectInput(xtclient->xtdisplay,
|
||||
XtWindow(top_widget),
|
||||
0x0FFFFF);
|
||||
xt_client_set_info (child_widget, 0);
|
||||
|
||||
XtManageChild(child_widget);
|
||||
xtclient->child_widget = child_widget;
|
||||
|
||||
/* set the event handler */
|
||||
#if 0
|
||||
XtAddEventHandler(child_widget,
|
||||
0x0FFFFF & ~ResizeRedirectMask,
|
||||
TRUE,
|
||||
(XtEventHandler)xt_client_event_handler, xtclient);
|
||||
XtAddEventHandler(child_widget,
|
||||
SubstructureNotifyMask | ButtonReleaseMask,
|
||||
TRUE,
|
||||
(XtEventHandler)xt_client_focus_listener,
|
||||
xtclient);
|
||||
#else
|
||||
XtAddEventHandler(child_widget,
|
||||
(SubstructureNotifyMask | ButtonReleaseMask),
|
||||
TRUE,
|
||||
(XtEventHandler)xt_client_event_handler, xtclient);
|
||||
#endif
|
||||
XSync(xtclient->xtdisplay, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
xt_client_unrealize ( XtClient* xtclient )
|
||||
{
|
||||
#if XlibSpecificationRelease >= 6
|
||||
XtUnregisterDrawable(xtclient->xtdisplay,
|
||||
xtclient->top_widget->core.window);
|
||||
#else
|
||||
_XtUnregisterWindow(xtclient->top_widget->core.window,
|
||||
xtclient->top_widget);
|
||||
#endif
|
||||
|
||||
/* flush the queue before we returning origin top_widget->core.window
|
||||
or we can get X error since the window is gone */
|
||||
XSync(xtclient->xtdisplay, False);
|
||||
|
||||
xtclient->top_widget->core.window = xtclient->oldwindow;
|
||||
XtUnrealizeWidget(xtclient->top_widget);
|
||||
}
|
||||
|
||||
static void
|
||||
xt_client_destroy (XtClient* xtclient)
|
||||
{
|
||||
if(xtclient->top_widget) {
|
||||
XtRemoveEventHandler(xtclient->child_widget, 0x0FFFFF, TRUE,
|
||||
(XtEventHandler)xt_client_event_handler, xtclient);
|
||||
XtDestroyWidget(xtclient->top_widget);
|
||||
xtclient->top_widget = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xt_client_set_info (Widget xtplug, unsigned long flags)
|
||||
{
|
||||
unsigned long buffer[2];
|
||||
|
||||
Atom infoAtom = XInternAtom(XtDisplay(xtplug), "_XEMBED_INFO", False);
|
||||
|
||||
buffer[1] = 0; /* Protocol version */
|
||||
buffer[1] = flags;
|
||||
|
||||
XChangeProperty (XtDisplay(xtplug), XtWindow(xtplug),
|
||||
infoAtom, infoAtom, 32,
|
||||
PropModeReplace,
|
||||
(unsigned char *)buffer, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
xt_client_handle_xembed_message(Widget w, XtPointer client_data, XEvent *event)
|
||||
{
|
||||
XtClient *xtplug = (XtClient*)client_data;
|
||||
switch (event->xclient.data.l[1])
|
||||
{
|
||||
case XEMBED_EMBEDDED_NOTIFY:
|
||||
break;
|
||||
case XEMBED_WINDOW_ACTIVATE:
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("Xt client get XEMBED_WINDOW_ACTIVATE\n");
|
||||
#endif
|
||||
break;
|
||||
case XEMBED_WINDOW_DEACTIVATE:
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("Xt client get XEMBED_WINDOW_DEACTIVATE\n");
|
||||
#endif
|
||||
break;
|
||||
case XEMBED_MODALITY_ON:
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("Xt client get XEMBED_MODALITY_ON\n");
|
||||
#endif
|
||||
break;
|
||||
case XEMBED_MODALITY_OFF:
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("Xt client get XEMBED_MODALITY_OFF\n");
|
||||
#endif
|
||||
break;
|
||||
case XEMBED_FOCUS_IN:
|
||||
case XEMBED_FOCUS_OUT:
|
||||
{
|
||||
XEvent xevent;
|
||||
memset(&xevent, 0, sizeof(xevent));
|
||||
|
||||
if(event->xclient.data.l[1] == XEMBED_FOCUS_IN) {
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("XTEMBED got focus in\n");
|
||||
#endif
|
||||
xevent.xfocus.type = FocusIn;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("XTEMBED got focus out\n");
|
||||
#endif
|
||||
xevent.xfocus.type = FocusOut;
|
||||
}
|
||||
|
||||
xevent.xfocus.window = XtWindow(xtplug->child_widget);
|
||||
xevent.xfocus.display = XtDisplay(xtplug->child_widget);
|
||||
XSendEvent(XtDisplay(xtplug->child_widget),
|
||||
xevent.xfocus.window,
|
||||
False, NoEventMask,
|
||||
&xevent );
|
||||
XSync( XtDisplay(xtplug->child_widget), False);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} /* End of XEmbed Message */
|
||||
}
|
||||
|
||||
static void
|
||||
xt_client_event_handler( Widget w, XtPointer client_data, XEvent *event)
|
||||
{
|
||||
XtClient *xtplug = (XtClient*)client_data;
|
||||
|
||||
switch(event->type)
|
||||
{
|
||||
case ClientMessage:
|
||||
/* Handle xembed message */
|
||||
if (event->xclient.message_type==
|
||||
XInternAtom (XtDisplay(xtplug->child_widget),
|
||||
"_XEMBED", False)) {
|
||||
xt_client_handle_xembed_message(w, client_data, event);
|
||||
}
|
||||
break;
|
||||
case ReparentNotify:
|
||||
break;
|
||||
case MappingNotify:
|
||||
xt_client_set_info (w, XEMBED_MAPPED);
|
||||
break;
|
||||
case UnmapNotify:
|
||||
xt_client_set_info (w, 0);
|
||||
break;
|
||||
case FocusIn:
|
||||
send_xembed_message ( xtplug,
|
||||
XEMBED_REQUEST_FOCUS, 0, 0, 0, 0);
|
||||
break;
|
||||
case FocusOut:
|
||||
break;
|
||||
case KeyPress:
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("Key Press Got!\n");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} /* End of switch(event->type) */
|
||||
}
|
||||
|
||||
static void
|
||||
send_xembed_message (XtClient *xtclient,
|
||||
long message,
|
||||
long detail,
|
||||
long data1,
|
||||
long data2,
|
||||
long time)
|
||||
{
|
||||
XEvent xevent;
|
||||
Window w=XtWindow(xtclient->top_widget);
|
||||
Display* dpy=xtclient->xtdisplay;
|
||||
int errorcode;
|
||||
|
||||
memset(&xevent,0,sizeof(xevent));
|
||||
xevent.xclient.window = w;
|
||||
xevent.xclient.type = ClientMessage;
|
||||
xevent.xclient.message_type = XInternAtom(dpy,"_XEMBED",False);
|
||||
xevent.xclient.format = 32;
|
||||
xevent.xclient.data.l[0] = time;
|
||||
xevent.xclient.data.l[1] = message;
|
||||
xevent.xclient.data.l[2] = detail;
|
||||
xevent.xclient.data.l[3] = data1;
|
||||
xevent.xclient.data.l[4] = data2;
|
||||
|
||||
trap_errors ();
|
||||
XSendEvent (dpy, w, False, NoEventMask, &xevent);
|
||||
XSync (dpy,False);
|
||||
|
||||
if((errorcode = untrap_errors())) {
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("send_xembed_message error(%d)!!!\n",errorcode);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
error_handler(Display *display, XErrorEvent *error)
|
||||
{
|
||||
trapped_error_code = error->error_code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
trap_errors(void)
|
||||
{
|
||||
trapped_error_code =0;
|
||||
old_error_handler = XSetErrorHandler(error_handler);
|
||||
}
|
||||
|
||||
static int
|
||||
untrap_errors(void)
|
||||
{
|
||||
XSetErrorHandler(old_error_handler);
|
||||
if(trapped_error_code) {
|
||||
#ifdef DEBUG_XTBIN
|
||||
printf("Get X Window Error = %d\n", trapped_error_code);
|
||||
#endif
|
||||
}
|
||||
return trapped_error_code;
|
||||
}
|
||||
|
||||
static void
|
||||
xt_client_focus_listener( Widget w, XtPointer user_data, XEvent *event)
|
||||
{
|
||||
Display *dpy = XtDisplay(w);
|
||||
XtClient *xtclient = user_data;
|
||||
Window win = XtWindow(w);
|
||||
|
||||
switch(event->type)
|
||||
{
|
||||
case CreateNotify:
|
||||
if(event->xcreatewindow.parent == win) {
|
||||
Widget child=XtWindowToWidget( dpy, event->xcreatewindow.window);
|
||||
if (child)
|
||||
xt_add_focus_listener_tree(child, user_data);
|
||||
}
|
||||
break;
|
||||
case DestroyNotify:
|
||||
xt_remove_focus_listener( w, user_data);
|
||||
break;
|
||||
case ReparentNotify:
|
||||
if(event->xreparent.parent == win) {
|
||||
/* I am the new parent */
|
||||
Widget child=XtWindowToWidget(dpy, event->xreparent.window);
|
||||
if (child)
|
||||
xt_add_focus_listener_tree( child, user_data);
|
||||
}
|
||||
else if(event->xreparent.window == win) {
|
||||
/* I am the new child */
|
||||
}
|
||||
else {
|
||||
/* I am the old parent */
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
#if 0
|
||||
XSetInputFocus(dpy, XtWindow(xtclient->child_widget), RevertToParent, event->xbutton.time);
|
||||
#endif
|
||||
send_xembed_message ( xtclient,
|
||||
XEMBED_REQUEST_FOCUS, 0, 0, 0, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} /* End of switch(event->type) */
|
||||
}
|
||||
|
||||
static void
|
||||
xt_add_focus_listener( Widget w, XtPointer user_data)
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
long eventmask;
|
||||
XtClient *xtclient = user_data;
|
||||
int errorcode;
|
||||
|
||||
trap_errors ();
|
||||
XGetWindowAttributes(XtDisplay(w), XtWindow(w), &attr);
|
||||
eventmask = attr.your_event_mask | SubstructureNotifyMask | ButtonReleaseMask;
|
||||
XSelectInput(XtDisplay(w),
|
||||
XtWindow(w),
|
||||
eventmask);
|
||||
|
||||
XtAddEventHandler(w,
|
||||
SubstructureNotifyMask | ButtonReleaseMask,
|
||||
TRUE,
|
||||
(XtEventHandler)xt_client_focus_listener,
|
||||
xtclient);
|
||||
untrap_errors();
|
||||
}
|
||||
|
||||
static void
|
||||
xt_remove_focus_listener(Widget w, XtPointer user_data)
|
||||
{
|
||||
int errorcode;
|
||||
|
||||
trap_errors ();
|
||||
XtRemoveEventHandler(w, SubstructureNotifyMask | ButtonReleaseMask, TRUE,
|
||||
(XtEventHandler)xt_client_focus_listener, user_data);
|
||||
|
||||
untrap_errors();
|
||||
}
|
||||
|
||||
static void
|
||||
xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data)
|
||||
{
|
||||
Window win = XtWindow(treeroot);
|
||||
Window *children;
|
||||
Window root, parent;
|
||||
Display *dpy = XtDisplay(treeroot);
|
||||
unsigned int i, nchildren;
|
||||
|
||||
/* ensure we don't add more than once */
|
||||
xt_remove_focus_listener( treeroot, user_data);
|
||||
xt_add_focus_listener( treeroot, user_data);
|
||||
trap_errors();
|
||||
if(!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) {
|
||||
untrap_errors();
|
||||
return;
|
||||
}
|
||||
|
||||
if(untrap_errors())
|
||||
return;
|
||||
|
||||
for(i=0; i<nchildren; ++i) {
|
||||
Widget child = XtWindowToWidget(dpy, children[i]);
|
||||
if (child)
|
||||
xt_add_focus_listener_tree( child, user_data);
|
||||
}
|
||||
XFree((void*)children);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim:expandtab:shiftwidth=2:tabstop=2: */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Gtk2XtBin Widget Implementation.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __GTK_XTBIN_H__
|
||||
#define __GTK_XTBIN_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#define GTKXTBIN_API(type) type
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _GtkXtBin GtkXtBin;
|
||||
typedef struct _GtkXtBinClass GtkXtBinClass;
|
||||
|
||||
#define GTK_TYPE_XTBIN (gtk_xtbin_get_type ())
|
||||
#define GTK_XTBIN(obj) (GTK_CHECK_CAST ((obj), \
|
||||
GTK_TYPE_XTBIN, GtkXtBin))
|
||||
#define GTK_XTBIN_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \
|
||||
GTK_TYPE_XTBIN, GtkXtBinClass))
|
||||
#define GTK_IS_XTBIN(obj) (GTK_CHECK_TYPE ((obj), \
|
||||
GTK_TYPE_XTBIN))
|
||||
#define GTK_IS_XTBIN_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \
|
||||
GTK_TYPE_XTBIN))
|
||||
typedef struct _XtClient XtClient;
|
||||
|
||||
struct _XtClient {
|
||||
Display *xtdisplay;
|
||||
Widget top_widget; /* The toplevel widget */
|
||||
Widget child_widget; /* The embedded widget */
|
||||
Visual *xtvisual;
|
||||
int xtdepth;
|
||||
Colormap xtcolormap;
|
||||
Window oldwindow;
|
||||
};
|
||||
|
||||
struct _GtkXtBin
|
||||
{
|
||||
GtkSocket gsocket;
|
||||
GdkWindow *parent_window;
|
||||
Display *xtdisplay; /* Xt Toolkit Display */
|
||||
|
||||
Window xtwindow; /* Xt Toolkit XWindow */
|
||||
gint x, y;
|
||||
gint width, height;
|
||||
XtClient xtclient; /* Xt Client for XEmbed */
|
||||
};
|
||||
|
||||
struct _GtkXtBinClass
|
||||
{
|
||||
GtkSocketClass widget_class;
|
||||
};
|
||||
|
||||
GTKXTBIN_API(GtkType) gtk_xtbin_get_type (void);
|
||||
GTKXTBIN_API(GtkWidget *) gtk_xtbin_new (GdkWindow *parent_window,
|
||||
Display *xtdisplay,
|
||||
Visual *xtvisual,
|
||||
Colormap xtcolormap,
|
||||
int xtdepth);
|
||||
GTKXTBIN_API(void) gtk_xtbin_set_position (GtkXtBin *xtbin,
|
||||
gint x,
|
||||
gint y);
|
||||
GTKXTBIN_API(void) gtk_xtbin_resize (GtkWidget *widget,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
typedef struct _XtTMRec {
|
||||
XtTranslations translations; /* private to Translation Manager */
|
||||
XtBoundActions proc_table; /* procedure bindings for actions */
|
||||
struct _XtStateRec *current_state; /* Translation Manager state ptr */
|
||||
unsigned long lastEventTime;
|
||||
} XtTMRec, *XtTM;
|
||||
|
||||
typedef struct _CorePart {
|
||||
Widget self; /* pointer to widget itself */
|
||||
WidgetClass widget_class; /* pointer to Widget's ClassRec */
|
||||
Widget parent; /* parent widget */
|
||||
XrmName xrm_name; /* widget resource name quarkified */
|
||||
Boolean being_destroyed; /* marked for destroy */
|
||||
XtCallbackList destroy_callbacks; /* who to call when widget destroyed */
|
||||
XtPointer constraints; /* constraint record */
|
||||
Position x, y; /* window position */
|
||||
Dimension width, height; /* window dimensions */
|
||||
Dimension border_width; /* window border width */
|
||||
Boolean managed; /* is widget geometry managed? */
|
||||
Boolean sensitive; /* is widget sensitive to user events*/
|
||||
Boolean ancestor_sensitive; /* are all ancestors sensitive? */
|
||||
XtEventTable event_table; /* private to event dispatcher */
|
||||
XtTMRec tm; /* translation management */
|
||||
XtTranslations accelerators; /* accelerator translations */
|
||||
Pixel border_pixel; /* window border pixel */
|
||||
Pixmap border_pixmap; /* window border pixmap or NULL */
|
||||
WidgetList popup_list; /* list of popups */
|
||||
Cardinal num_popups; /* how many popups */
|
||||
String name; /* widget resource name */
|
||||
Screen *screen; /* window's screen */
|
||||
Colormap colormap; /* colormap */
|
||||
Window window; /* window ID */
|
||||
Cardinal depth; /* number of planes in window */
|
||||
Pixel background_pixel; /* window background pixel */
|
||||
Pixmap background_pixmap; /* window background pixmap or NULL */
|
||||
Boolean visible; /* is window mapped and not occluded?*/
|
||||
Boolean mapped_when_managed;/* map window if it's managed? */
|
||||
} CorePart;
|
||||
|
||||
typedef struct _WidgetRec {
|
||||
CorePart core;
|
||||
} WidgetRec, CoreRec;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __GTK_XTBIN_H__ */
|
||||
|
|
@ -605,8 +605,10 @@ bool npobject_bridge_new(void)
|
|||
|
||||
void npobject_bridge_destroy(void)
|
||||
{
|
||||
g_hash_table_destroy(g_npobject_ids);
|
||||
g_hash_table_destroy(g_npobjects);
|
||||
if (g_npobject_ids)
|
||||
g_hash_table_destroy(g_npobject_ids);
|
||||
if (g_npobjects)
|
||||
g_hash_table_destroy(g_npobjects);
|
||||
}
|
||||
|
||||
void npobject_hash_table_insert(NPObject *npobj, NPObjectInfo *npobj_info)
|
||||
|
@ -636,71 +638,3 @@ NPObject *npobject_lookup(uint32_t npobj_id)
|
|||
{
|
||||
return g_hash_table_lookup(g_npobject_ids, (void *)(uintptr_t)npobj_id);
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Dummy npruntime accessors === */
|
||||
/* ====================================================================== */
|
||||
|
||||
static void dummy_function_do_nothing(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int dummy_function_return_zero(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool dummy_function_return_void_variant(NPVariant *variant)
|
||||
{
|
||||
if (variant)
|
||||
VOID_TO_NPVARIANT(*variant);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dummy_NPN_Invoke(NPP npp, NPObject* obj, NPIdentifier methodName,
|
||||
const NPVariant *args, uint32_t argCount, NPVariant *result)
|
||||
{
|
||||
return dummy_function_return_void_variant(result);
|
||||
}
|
||||
|
||||
static bool dummy_NPN_InvokeDefault(NPP npp, NPObject* obj, const NPVariant *args,
|
||||
uint32_t argCount, NPVariant *result)
|
||||
{
|
||||
return dummy_function_return_void_variant(result);
|
||||
}
|
||||
|
||||
static bool dummy_NPN_Evaluate(NPP npp, NPObject* obj, NPString *script,
|
||||
NPVariant *result)
|
||||
{
|
||||
return dummy_function_return_void_variant(result);
|
||||
}
|
||||
|
||||
static bool dummy_NPN_GetProperty(NPP npp, NPObject* obj, NPIdentifier propertyName,
|
||||
NPVariant *result)
|
||||
{
|
||||
return dummy_function_return_void_variant(result);
|
||||
}
|
||||
|
||||
void npruntime_init_callbacks(NPNetscapeFuncs *mozilla_funcs)
|
||||
{
|
||||
mozilla_funcs->getstringidentifier = NewNPN_GetStringIdentifierProc(dummy_function_return_zero);
|
||||
mozilla_funcs->getstringidentifiers = NewNPN_GetStringIdentifiersProc(dummy_function_do_nothing);
|
||||
mozilla_funcs->getintidentifier = NewNPN_GetIntIdentifierProc(dummy_function_return_zero);
|
||||
mozilla_funcs->identifierisstring = NewNPN_IdentifierIsStringProc(dummy_function_return_zero);
|
||||
mozilla_funcs->utf8fromidentifier = NewNPN_UTF8FromIdentifierProc(dummy_function_return_zero);
|
||||
mozilla_funcs->intfromidentifier = NewNPN_IntFromIdentifierProc(dummy_function_return_zero);
|
||||
mozilla_funcs->createobject = NewNPN_CreateObjectProc(dummy_function_return_zero);
|
||||
mozilla_funcs->retainobject = NewNPN_RetainObjectProc(dummy_function_return_zero);
|
||||
mozilla_funcs->releaseobject = NewNPN_ReleaseObjectProc(dummy_function_do_nothing);
|
||||
mozilla_funcs->invoke = NewNPN_InvokeProc(dummy_NPN_Invoke);
|
||||
mozilla_funcs->invokeDefault = NewNPN_InvokeDefaultProc(dummy_NPN_InvokeDefault);
|
||||
mozilla_funcs->evaluate = NewNPN_EvaluateProc(dummy_NPN_Evaluate);
|
||||
mozilla_funcs->getproperty = NewNPN_GetPropertyProc(dummy_NPN_GetProperty);
|
||||
mozilla_funcs->setproperty = NewNPN_SetPropertyProc(dummy_function_return_zero);
|
||||
mozilla_funcs->removeproperty = NewNPN_RemovePropertyProc(dummy_function_return_zero);
|
||||
mozilla_funcs->hasproperty = NewNPN_HasPropertyProc(dummy_function_return_zero);
|
||||
mozilla_funcs->hasmethod = NewNPN_HasMethodProc(dummy_function_return_zero);
|
||||
mozilla_funcs->releasevariantvalue = NewNPN_ReleaseVariantValueProc(dummy_function_do_nothing);
|
||||
mozilla_funcs->setexception = NewNPN_SetExceptionProc(dummy_function_do_nothing);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* npw-config-template.h - nspluginwrapper configuration tool, template defs
|
||||
*
|
||||
* nspluginwrapper (C) 2005-2007 Gwenole Beauchesne
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef ELF_CLASS
|
||||
#ifndef ElfW
|
||||
# if ELF_CLASS == ELFCLASS32
|
||||
# define ElfW(x) Elf32_ ## x
|
||||
# define ELFW(x) ELF32_ ## x
|
||||
# define FUNC(x) x ## _32
|
||||
# define bswap_ad(x) bswap_32(x)
|
||||
# else
|
||||
# define ElfW(x) Elf64_ ## x
|
||||
# define ELFW(x) ELF64_ ## x
|
||||
# define FUNC(x) x ## _64
|
||||
# define bswap_ad(x) bswap_64(x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static void FUNC(elf_swap_ehdr)(ElfW(Ehdr) *hdr)
|
||||
{
|
||||
hdr->e_type = bswap_16(hdr->e_type);
|
||||
hdr->e_machine = bswap_16(hdr->e_machine);
|
||||
hdr->e_version = bswap_32(hdr->e_version);
|
||||
hdr->e_entry = bswap_ad(hdr->e_entry);
|
||||
hdr->e_phoff = bswap_ad(hdr->e_phoff);
|
||||
hdr->e_shoff = bswap_ad(hdr->e_shoff);
|
||||
hdr->e_flags = bswap_32(hdr->e_flags);
|
||||
hdr->e_ehsize = bswap_16(hdr->e_ehsize);
|
||||
hdr->e_phentsize = bswap_16(hdr->e_phentsize);
|
||||
hdr->e_phnum = bswap_16(hdr->e_phnum);
|
||||
hdr->e_shentsize = bswap_16(hdr->e_shentsize);
|
||||
hdr->e_shnum = bswap_16(hdr->e_shnum);
|
||||
hdr->e_shstrndx = bswap_16(hdr->e_shstrndx);
|
||||
}
|
||||
|
||||
static void FUNC(elf_swap_shdr)(ElfW(Shdr) *shdr)
|
||||
{
|
||||
shdr->sh_name = bswap_32(shdr->sh_name);
|
||||
shdr->sh_type = bswap_32(shdr->sh_type);
|
||||
shdr->sh_flags = bswap_ad(shdr->sh_flags);
|
||||
shdr->sh_addr = bswap_ad(shdr->sh_addr);
|
||||
shdr->sh_offset = bswap_ad(shdr->sh_offset);
|
||||
shdr->sh_size = bswap_ad(shdr->sh_size);
|
||||
shdr->sh_link = bswap_32(shdr->sh_link);
|
||||
shdr->sh_info = bswap_32(shdr->sh_info);
|
||||
shdr->sh_addralign = bswap_ad(shdr->sh_addralign);
|
||||
shdr->sh_entsize = bswap_ad(shdr->sh_entsize);
|
||||
}
|
||||
|
||||
static void FUNC(elf_swap_sym)(ElfW(Sym) *sym)
|
||||
{
|
||||
sym->st_name = bswap_32(sym->st_name);
|
||||
sym->st_value = bswap_ad(sym->st_value);
|
||||
sym->st_size = bswap_ad(sym->st_size);
|
||||
sym->st_shndx = bswap_16(sym->st_shndx);
|
||||
}
|
||||
|
||||
static bool FUNC(is_elf_plugin_fd)(int fd, NPW_PluginInfo *out_plugin_info)
|
||||
{
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
||||
ElfW(Ehdr) ehdr;
|
||||
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
|
||||
return false;
|
||||
|
||||
bool do_swap = (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) && !is_little_endian();
|
||||
if (do_swap)
|
||||
FUNC(elf_swap_ehdr)(&ehdr);
|
||||
|
||||
if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
|
||||
return false;
|
||||
if (ehdr.e_type != ET_DYN)
|
||||
return false;
|
||||
if (ehdr.e_version != EV_CURRENT)
|
||||
return false;
|
||||
|
||||
if (out_plugin_info) {
|
||||
const char *target_arch = "";
|
||||
switch (ehdr.e_machine) {
|
||||
case EM_386: target_arch = "i386"; break;
|
||||
case EM_X86_64: target_arch = "x86_64"; break;
|
||||
case EM_SPARC: target_arch = "sparc"; break;
|
||||
case EM_PPC: target_arch = "ppc"; break;
|
||||
case EM_PPC64: target_arch = "ppc64"; break;
|
||||
}
|
||||
strcpy(out_plugin_info->target_arch, target_arch);
|
||||
const char *target_os = "";
|
||||
switch (ehdr.e_ident[EI_OSABI]) {
|
||||
case ELFOSABI_LINUX: target_os = "linux"; break;
|
||||
case ELFOSABI_SOLARIS: target_os = "solaris"; break;
|
||||
case ELFOSABI_FREEBSD: target_os = "freebsd"; break;
|
||||
}
|
||||
strcpy(out_plugin_info->target_os, target_os);
|
||||
}
|
||||
|
||||
ElfW(Shdr) *shdr = (ElfW(Shdr) *)load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(*shdr));
|
||||
if (do_swap) {
|
||||
for (i = 0; i < ehdr.e_shnum; i++)
|
||||
FUNC(elf_swap_shdr)(&shdr[i]);
|
||||
}
|
||||
|
||||
char **sdata = (char **)calloc(ehdr.e_shnum, sizeof(*sdata));
|
||||
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||
ElfW(Shdr) *sec = &shdr[i];
|
||||
if (sec->sh_type != SHT_NOBITS)
|
||||
sdata[i] = (char *)load_data(fd, sec->sh_offset, sec->sh_size);
|
||||
}
|
||||
|
||||
ElfW(Shdr) *symtab_sec = NULL;
|
||||
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||
ElfW(Shdr) *sec = &shdr[i];
|
||||
if (sec->sh_type == SHT_DYNSYM
|
||||
&& strcmp(sdata[ehdr.e_shstrndx] + sec->sh_name, ".dynsym") == 0) {
|
||||
symtab_sec = sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (symtab_sec == NULL)
|
||||
goto done;
|
||||
ElfW(Sym) *symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
|
||||
char *strtab = sdata[symtab_sec->sh_link];
|
||||
|
||||
int nb_syms = symtab_sec->sh_size / sizeof(*symtab);
|
||||
if (do_swap) {
|
||||
for (i = 0; i < nb_syms; i++)
|
||||
FUNC(elf_swap_sym)(&symtab[i]);
|
||||
}
|
||||
|
||||
int nb_np_syms;
|
||||
int is_wrapper_plugin = 0;
|
||||
for (i = 0, nb_np_syms = 0; i < nb_syms; i++) {
|
||||
ElfW(Sym) *sym = &symtab[i];
|
||||
const char *name = strtab + sym->st_name;
|
||||
if (ELFW(ST_BIND)(sym->st_info) != STB_GLOBAL)
|
||||
continue;
|
||||
if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT && strcmp(name, "NPW_Plugin") == 0)
|
||||
is_wrapper_plugin = 1;
|
||||
if (ELFW(ST_TYPE)(sym->st_info) != STT_FUNC)
|
||||
continue;
|
||||
if (!strcmp(name, "NP_GetMIMEDescription") ||
|
||||
!strcmp(name, "NP_Initialize") ||
|
||||
!strcmp(name, "NP_Shutdown"))
|
||||
nb_np_syms++;
|
||||
}
|
||||
ret = (nb_np_syms == 3) && !is_wrapper_plugin;
|
||||
|
||||
done:
|
||||
for (i = 0; i < ehdr.e_shnum; i++)
|
||||
free(sdata[i]);
|
||||
free(sdata);
|
||||
free(shdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef bswap_ad
|
||||
#undef ElfW
|
||||
#undef ELFW
|
||||
#undef FUNC
|
||||
#undef ELF_CLASS
|
||||
#endif
|
237
src/npw-config.c
237
src/npw-config.c
|
@ -254,11 +254,31 @@ static const char **get_mozilla_plugin_dirs(void)
|
|||
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
|
||||
|
||||
/* 32-bit ELF base types. */
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Word;
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint32_t Elf32_Off;
|
||||
#undef bswap_64
|
||||
#define bswap_64(x) \
|
||||
( \
|
||||
(((x) & 0xff00000000000000) >> 56) | (((x) & 0x00ff000000000000) >> 40) | \
|
||||
(((x) & 0x00000000000000ff) << 56) | (((x) & 0x000000000000ff00) << 40) | \
|
||||
(((x) & 0x0000ff0000000000) >> 24) | (((x) & 0x000000ff00000000) >> 8) | \
|
||||
(((x) & 0x0000000000ff0000) << 24) | (((x) & 0x00000000ff000000) << 8) \
|
||||
)
|
||||
|
||||
/* 32-bit ELF base types. */
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Off;
|
||||
typedef int32_t Elf32_Sword;
|
||||
typedef uint32_t Elf32_Word;
|
||||
|
||||
/* 64-bit ELF base types. */
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef int16_t Elf64_SHalf;
|
||||
typedef uint64_t Elf64_Off;
|
||||
typedef int32_t Elf64_Sword;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef int64_t Elf64_Sxword;
|
||||
|
||||
/* The ELF file header. This appears at the start of every ELF file. */
|
||||
#define EI_NIDENT (16)
|
||||
|
@ -281,6 +301,30 @@ typedef struct
|
|||
Elf32_Half e_shstrndx; /* Section header string table index */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry; /* Entry point virtual address */
|
||||
Elf64_Off e_phoff; /* Program header table file offset */
|
||||
Elf64_Off e_shoff; /* Section header table file offset */
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
/* Base structure - used to distinguish between 32/64 bit version */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
} Elf_hdr_base;
|
||||
|
||||
#define EI_MAG0 0 /* File identification byte 0 index */
|
||||
#define ELFMAG0 0x7f /* Magic number byte 0 */
|
||||
#define EI_MAG1 1 /* File identification byte 1 index */
|
||||
|
@ -326,6 +370,21 @@ typedef struct
|
|||
Elf32_Word sh_entsize; /* Entry size if section holds table */
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word sh_name; /* Section name, index in string tbl */
|
||||
Elf64_Word sh_type; /* Type of section */
|
||||
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
|
||||
Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
||||
Elf64_Off sh_offset; /* Section file offset */
|
||||
Elf64_Xword sh_size; /* Size of section in bytes */
|
||||
Elf64_Word sh_link; /* Index of another section */
|
||||
Elf64_Word sh_info; /* Additional section information */
|
||||
Elf64_Xword sh_addralign; /* Section alignment */
|
||||
Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
||||
} Elf64_Shdr;
|
||||
|
||||
|
||||
#define SHT_NOBITS 8 /* Program space with no data (bss) */
|
||||
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
||||
|
||||
|
@ -340,18 +399,27 @@ typedef struct
|
|||
Elf32_Half st_shndx; /* Section index */
|
||||
} Elf32_Sym;
|
||||
|
||||
#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
|
||||
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word st_name; /* Symbol name, index in string tbl */
|
||||
unsigned char st_info; /* Type and binding attributes */
|
||||
unsigned char st_other; /* No defined meaning, 0 */
|
||||
Elf64_Half st_shndx; /* Associated section index */
|
||||
Elf64_Addr st_value; /* Value of the symbol */
|
||||
Elf64_Xword st_size; /* Associated symbol size */
|
||||
} Elf64_Sym;
|
||||
|
||||
#define ELF_ST_BIND(x) ((x) >> 4)
|
||||
#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf)
|
||||
#define ELF32_ST_BIND(x) ELF_ST_BIND(x)
|
||||
#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x)
|
||||
#define ELF64_ST_BIND(x) ELF_ST_BIND(x)
|
||||
#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x)
|
||||
|
||||
#define STB_GLOBAL 1 /* Global symbol */
|
||||
#define STT_OBJECT 1 /* Symbol is a data object */
|
||||
#define STT_FUNC 2 /* Symbol is a code object */
|
||||
|
||||
/* We handle 32-bit ELF plugins only */
|
||||
#undef ELF_CLASS
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ElfW(x) Elf32_ ## x
|
||||
#define ELFW(x) ELF32_ ## x
|
||||
|
||||
void *load_data(int fd, long offset, unsigned int size)
|
||||
{
|
||||
char *data = (char *)malloc(size);
|
||||
|
@ -374,51 +442,16 @@ static bool is_little_endian(void)
|
|||
return x.b[0] == 0x04;
|
||||
}
|
||||
|
||||
static void elf_swap_ehdr(ElfW(Ehdr) *hdr)
|
||||
{
|
||||
hdr->e_type = bswap_16(hdr->e_type);
|
||||
hdr->e_machine = bswap_16(hdr->e_machine);
|
||||
hdr->e_version = bswap_32(hdr->e_version);
|
||||
hdr->e_entry = bswap_32(hdr->e_entry);
|
||||
hdr->e_phoff = bswap_32(hdr->e_phoff);
|
||||
hdr->e_shoff = bswap_32(hdr->e_shoff);
|
||||
hdr->e_flags = bswap_32(hdr->e_flags);
|
||||
hdr->e_ehsize = bswap_16(hdr->e_ehsize);
|
||||
hdr->e_phentsize = bswap_16(hdr->e_phentsize);
|
||||
hdr->e_phnum = bswap_16(hdr->e_phnum);
|
||||
hdr->e_shentsize = bswap_16(hdr->e_shentsize);
|
||||
hdr->e_shnum = bswap_16(hdr->e_shnum);
|
||||
hdr->e_shstrndx = bswap_16(hdr->e_shstrndx);
|
||||
}
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#include "npw-config-template.h"
|
||||
|
||||
static void elf_swap_shdr(ElfW(Shdr) *shdr)
|
||||
{
|
||||
shdr->sh_name = bswap_32(shdr->sh_name);
|
||||
shdr->sh_type = bswap_32(shdr->sh_type);
|
||||
shdr->sh_flags = bswap_32(shdr->sh_flags);
|
||||
shdr->sh_addr = bswap_32(shdr->sh_addr);
|
||||
shdr->sh_offset = bswap_32(shdr->sh_offset);
|
||||
shdr->sh_size = bswap_32(shdr->sh_size);
|
||||
shdr->sh_link = bswap_32(shdr->sh_link);
|
||||
shdr->sh_info = bswap_32(shdr->sh_info);
|
||||
shdr->sh_addralign = bswap_32(shdr->sh_addralign);
|
||||
shdr->sh_entsize = bswap_32(shdr->sh_entsize);
|
||||
}
|
||||
|
||||
static void elf_swap_sym(ElfW(Sym) *sym)
|
||||
{
|
||||
sym->st_name = bswap_32(sym->st_name);
|
||||
sym->st_value = bswap_32(sym->st_value);
|
||||
sym->st_size = bswap_32(sym->st_size);
|
||||
sym->st_shndx = bswap_32(sym->st_shndx);
|
||||
}
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#include "npw-config-template.h"
|
||||
|
||||
static bool is_plugin_fd(int fd, NPW_PluginInfo *out_plugin_info)
|
||||
{
|
||||
int i;
|
||||
bool ret = false;
|
||||
|
||||
ElfW(Ehdr) ehdr;
|
||||
Elf_hdr_base ehdr;
|
||||
|
||||
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
|
||||
return false;
|
||||
|
||||
|
@ -428,91 +461,13 @@ static bool is_plugin_fd(int fd, NPW_PluginInfo *out_plugin_info)
|
|||
|| ehdr.e_ident[EI_MAG3] != ELFMAG3)
|
||||
return false;
|
||||
|
||||
bool do_swap = (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) && !is_little_endian();
|
||||
if (do_swap)
|
||||
elf_swap_ehdr(&ehdr);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
|
||||
return false;
|
||||
if (ehdr.e_type != ET_DYN)
|
||||
return false;
|
||||
if (ehdr.e_version != EV_CURRENT)
|
||||
return false;
|
||||
|
||||
if (out_plugin_info) {
|
||||
const char *target_arch = "";
|
||||
switch (ehdr.e_machine) {
|
||||
case EM_386: target_arch = "i386"; break;
|
||||
case EM_SPARC: target_arch = "sparc"; break;
|
||||
case EM_PPC: target_arch = "ppc"; break;
|
||||
}
|
||||
strcpy(out_plugin_info->target_arch, target_arch);
|
||||
const char *target_os = "";
|
||||
switch (ehdr.e_ident[EI_OSABI]) {
|
||||
case ELFOSABI_LINUX: target_os = "linux"; break;
|
||||
case ELFOSABI_SOLARIS: target_os = "solaris"; break;
|
||||
case ELFOSABI_FREEBSD: target_os = "freebsd"; break;
|
||||
}
|
||||
strcpy(out_plugin_info->target_os, target_os);
|
||||
switch (ehdr.e_ident[EI_CLASS]) {
|
||||
case ELFCLASS32: return is_elf_plugin_fd_32(fd, out_plugin_info);
|
||||
case ELFCLASS64: return is_elf_plugin_fd_64(fd, out_plugin_info);
|
||||
}
|
||||
|
||||
ElfW(Shdr) *shdr = (ElfW(Shdr) *)load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(*shdr));
|
||||
if (do_swap) {
|
||||
for (i = 0; i < ehdr.e_shnum; i++)
|
||||
elf_swap_shdr(&shdr[i]);
|
||||
}
|
||||
|
||||
char **sdata = (char **)calloc(ehdr.e_shnum, sizeof(*sdata));
|
||||
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||
ElfW(Shdr) *sec = &shdr[i];
|
||||
if (sec->sh_type != SHT_NOBITS)
|
||||
sdata[i] = (char *)load_data(fd, sec->sh_offset, sec->sh_size);
|
||||
}
|
||||
|
||||
ElfW(Shdr) *symtab_sec = NULL;
|
||||
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||
ElfW(Shdr) *sec = &shdr[i];
|
||||
if (sec->sh_type == SHT_DYNSYM
|
||||
&& strcmp(sdata[ehdr.e_shstrndx] + sec->sh_name, ".dynsym") == 0) {
|
||||
symtab_sec = sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (symtab_sec == NULL)
|
||||
goto done;
|
||||
ElfW(Sym) *symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
|
||||
char *strtab = sdata[symtab_sec->sh_link];
|
||||
|
||||
int nb_syms = symtab_sec->sh_size / sizeof(*symtab);
|
||||
if (do_swap) {
|
||||
for (i = 0; i < nb_syms; i++)
|
||||
elf_swap_sym(&symtab[i]);
|
||||
}
|
||||
|
||||
int nb_np_syms;
|
||||
int is_wrapper_plugin = 0;
|
||||
for (i = 0, nb_np_syms = 0; i < nb_syms; i++) {
|
||||
ElfW(Sym) *sym = &symtab[i];
|
||||
const char *name = strtab + sym->st_name;
|
||||
if (ELFW(ST_BIND)(sym->st_info) != STB_GLOBAL)
|
||||
continue;
|
||||
if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT && strcmp(name, "NPW_Plugin") == 0)
|
||||
is_wrapper_plugin = 1;
|
||||
if (ELFW(ST_TYPE)(sym->st_info) != STT_FUNC)
|
||||
continue;
|
||||
if (!strcmp(name, "NP_GetMIMEDescription") ||
|
||||
!strcmp(name, "NP_Initialize") ||
|
||||
!strcmp(name, "NP_Shutdown"))
|
||||
nb_np_syms++;
|
||||
}
|
||||
ret = (nb_np_syms == 3) && !is_wrapper_plugin;
|
||||
|
||||
done:
|
||||
for (i = 0; i < ehdr.e_shnum; i++)
|
||||
free(sdata[i]);
|
||||
free(sdata);
|
||||
free(shdr);
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
enum {
|
||||
|
@ -548,6 +503,12 @@ static int detect_plugin_viewer(const char *filename, NPW_PluginInfo *out_plugin
|
|||
else
|
||||
target_os_table[0] = NULL;
|
||||
|
||||
// don't wrap plugins for host OS/ARCH
|
||||
if (out_plugin_info
|
||||
&& out_plugin_info->target_arch && strcmp(out_plugin_info->target_arch, HOST_ARCH) == 0
|
||||
&& out_plugin_info->target_os && strcmp(out_plugin_info->target_os, HOST_OS) == 0)
|
||||
return EXIT_VIEWER_NATIVE;
|
||||
|
||||
for (int i = 0; i < target_arch_table_size; i++) {
|
||||
const char *target_arch = target_arch_table[i];
|
||||
if (target_arch == NULL)
|
||||
|
@ -562,8 +523,6 @@ static int detect_plugin_viewer(const char *filename, NPW_PluginInfo *out_plugin
|
|||
const char *target_os = target_os_table[j];
|
||||
if (target_os == NULL)
|
||||
continue;
|
||||
if (strcmp(target_arch, HOST_ARCH) == 0 && strcmp(target_os, HOST_OS) == 0)
|
||||
return EXIT_VIEWER_NATIVE; // don't wrap plugins for host OS/ARCH
|
||||
char viewer_path[PATH_MAX];
|
||||
sprintf(viewer_path, "%s/%s/%s", viewer_arch_path, target_os, NPW_VIEWER);
|
||||
if (access(viewer_path, F_OK) != 0)
|
||||
|
|
|
@ -66,6 +66,7 @@ int rpc_type_of_NPPVariable(int variable)
|
|||
switch (variable) {
|
||||
case NPPVpluginNameString:
|
||||
case NPPVpluginDescriptionString:
|
||||
case NPPVformValue: // byte values of 0 does not appear in the UTF-8 encoding but for U+0000
|
||||
type = RPC_TYPE_STRING;
|
||||
break;
|
||||
case NPPVpluginWindowBool:
|
||||
|
|
|
@ -37,6 +37,11 @@ enum {
|
|||
RPC_METHOD_NPN_STATUS,
|
||||
RPC_METHOD_NPN_PRINT_DATA,
|
||||
RPC_METHOD_NPN_REQUEST_READ,
|
||||
RPC_METHOD_NPN_NEW_STREAM,
|
||||
RPC_METHOD_NPN_DESTROY_STREAM,
|
||||
RPC_METHOD_NPN_WRITE,
|
||||
RPC_METHOD_NPN_PUSH_POPUPS_ENABLED_STATE,
|
||||
RPC_METHOD_NPN_POP_POPUPS_ENABLED_STATE,
|
||||
|
||||
RPC_METHOD_NPP_NEW,
|
||||
RPC_METHOD_NPP_DESTROY,
|
||||
|
|
850
src/npw-viewer.c
850
src/npw-viewer.c
File diff suppressed because it is too large
Load Diff
|
@ -71,15 +71,6 @@ if test "$ARCH" != "$TARGET_ARCH"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Don't wrap host plugins
|
||||
case " $@ " in
|
||||
*" --test "*|*" -t "*)
|
||||
if test "$TARGET_OS" = "$OS" -a "$TARGET_ARCH" = "$ARCH"; then
|
||||
exit 20 # EXIT_VIEWER_NATIVE
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Expand PATH for RealPlayer package on NetBSD (realplay)
|
||||
if test "$OS" = "NetBSD"; then
|
||||
REALPLAYER_HOME="/usr/pkg/lib/RealPlayer"
|
||||
|
|
|
@ -18,16 +18,17 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1 /* RTLD_DEFAULT */
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
@ -94,12 +95,12 @@ typedef struct _PluginInstance {
|
|||
typedef struct _StreamInstance {
|
||||
NPStream *stream;
|
||||
uint32_t stream_id;
|
||||
int is_plugin_stream;
|
||||
} StreamInstance;
|
||||
|
||||
// Prototypes
|
||||
static void plugin_init(int is_NP_Initialize);
|
||||
static void plugin_exit(void);
|
||||
static pthread_mutex_t plugin_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// Helpers
|
||||
#ifndef min
|
||||
|
@ -140,12 +141,40 @@ static gboolean rpc_event_dispatch(GSource *source, GSourceFunc callback, gpoint
|
|||
/* === Browser side plug-in API === */
|
||||
/* ====================================================================== */
|
||||
|
||||
// Does browser have specified feature?
|
||||
#define NPN_HAS_FEATURE(FEATURE) ((mozilla_funcs.version & 0xff) >= NPVERS_HAS_##FEATURE)
|
||||
|
||||
// NPN_MemAlloc
|
||||
static inline void *g_NPN_MemAlloc(uint32 size)
|
||||
{
|
||||
return CallNPN_MemAllocProc(mozilla_funcs.memalloc, size);
|
||||
}
|
||||
|
||||
// NPN_MemFree
|
||||
static inline void g_NPN_MemFree(void* ptr)
|
||||
{
|
||||
CallNPN_MemFreeProc(mozilla_funcs.memfree, ptr);
|
||||
}
|
||||
|
||||
// NPN_MemFlush
|
||||
static inline uint32 g_NPN_MemFlush(uint32 size)
|
||||
{
|
||||
return CallNPN_MemFlushProc(mozilla_funcs.memflush, size);
|
||||
}
|
||||
|
||||
// NPN_UserAgent
|
||||
static const char *g_NPN_UserAgent(NPP instance)
|
||||
{
|
||||
if (mozilla_funcs.uagent == NULL)
|
||||
return NULL;
|
||||
return mozilla_funcs.uagent(instance);
|
||||
}
|
||||
|
||||
static int handle_NPN_UserAgent(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_NPN_UserAgent\n"));
|
||||
|
||||
const char *user_agent = mozilla_funcs.uagent ? mozilla_funcs.uagent(NULL) : NULL;
|
||||
const char *user_agent = g_NPN_UserAgent(NULL);
|
||||
return rpc_method_send_reply(connection, RPC_TYPE_STRING, user_agent, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
|
@ -463,6 +492,237 @@ static int handle_NPN_RequestRead(rpc_connection_t *connection)
|
|||
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
// NPN_NewStream
|
||||
static NPError g_NPN_NewStream(NPP instance, NPMIMEType type, const char *target, NPStream **stream)
|
||||
{
|
||||
if (mozilla_funcs.newstream == NULL)
|
||||
return NPERR_INVALID_FUNCTABLE_ERROR;
|
||||
|
||||
if (stream == NULL)
|
||||
return NPERR_INVALID_PARAM;
|
||||
|
||||
D(bug("NPN_NewStream instance=%p, type='%s', target='%s'\n", instance, type, target));
|
||||
NPError ret = CallNPN_NewStreamProc(mozilla_funcs.newstream, instance, type, target, stream);
|
||||
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
|
||||
|
||||
if (ret == NPERR_NO_ERROR) {
|
||||
StreamInstance *stream_pdata = malloc(sizeof(*stream_pdata));
|
||||
if (stream_pdata == NULL)
|
||||
return NPERR_OUT_OF_MEMORY_ERROR;
|
||||
memset(stream_pdata, 0, sizeof(*stream_pdata));
|
||||
stream_pdata->stream = *stream;
|
||||
stream_pdata->stream_id = id_create(stream_pdata);
|
||||
stream_pdata->is_plugin_stream = 1;
|
||||
(*stream)->pdata = stream_pdata;
|
||||
}
|
||||
else {
|
||||
static const StreamInstance fake_StreamInstance = {
|
||||
.stream = NULL,
|
||||
.stream_id = 0
|
||||
};
|
||||
static const NPStream fake_NPStream = {
|
||||
.pdata = (void *)&fake_StreamInstance,
|
||||
.url = NULL,
|
||||
.end = 0,
|
||||
.lastmodified = 0,
|
||||
.notifyData = NULL
|
||||
};
|
||||
*stream = (void *)&fake_NPStream;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_NPN_NewStream(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_NPN_NewStream\n"));
|
||||
|
||||
NPP instance;
|
||||
char *type;
|
||||
char *target;
|
||||
int error = rpc_method_get_args(connection,
|
||||
RPC_TYPE_NPP, &instance,
|
||||
RPC_TYPE_STRING, &type,
|
||||
RPC_TYPE_STRING, &target,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error != RPC_ERROR_NO_ERROR) {
|
||||
npw_perror("NPN_NewStream() get args", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
NPStream *stream;
|
||||
NPError ret = g_NPN_NewStream(instance, type, target, &stream);
|
||||
|
||||
if (type)
|
||||
free(type);
|
||||
if (target)
|
||||
free(target);
|
||||
|
||||
return rpc_method_send_reply(connection,
|
||||
RPC_TYPE_INT32, ret,
|
||||
RPC_TYPE_UINT32, ((StreamInstance *)stream->pdata)->stream_id,
|
||||
RPC_TYPE_STRING, stream->url,
|
||||
RPC_TYPE_UINT32, stream->end,
|
||||
RPC_TYPE_UINT32, stream->lastmodified,
|
||||
RPC_TYPE_NP_NOTIFY_DATA, stream->notifyData,
|
||||
RPC_TYPE_STRING, NPN_HAS_FEATURE(RESPONSE_HEADERS) ? stream->headers : NULL,
|
||||
RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
// NPN_DestroySream
|
||||
static NPError
|
||||
g_NPN_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
|
||||
{
|
||||
if (mozilla_funcs.destroystream == NULL)
|
||||
return NPERR_INVALID_FUNCTABLE_ERROR;
|
||||
|
||||
if (stream == NULL)
|
||||
return NPERR_INVALID_PARAM;
|
||||
|
||||
// Mozilla calls NPP_DestroyStream() for its streams, keep stream
|
||||
// info in that case
|
||||
StreamInstance *stream_pdata = stream->pdata;
|
||||
if (stream_pdata && stream_pdata->is_plugin_stream) {
|
||||
id_remove(stream_pdata->stream_id);
|
||||
free(stream->pdata);
|
||||
stream->pdata = NULL;
|
||||
}
|
||||
|
||||
D(bug("NPN_DestroyStream instance=%p, stream=%p, reason=%s\n",
|
||||
instance, stream, string_of_NPReason(reason)));
|
||||
NPError ret = CallNPN_DestroyStreamProc(mozilla_funcs.destroystream, instance, stream, reason);
|
||||
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_NPN_DestroyStream(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_NPN_DestroyStream\n"));
|
||||
|
||||
NPP instance;
|
||||
NPStream *stream;
|
||||
int32_t reason;
|
||||
int error = rpc_method_get_args(connection,
|
||||
RPC_TYPE_NPP, &instance,
|
||||
RPC_TYPE_NP_STREAM, &stream,
|
||||
RPC_TYPE_INT32, &reason,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error != RPC_ERROR_NO_ERROR) {
|
||||
npw_perror("NPN_DestroyStream() get args", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
NPError ret = g_NPN_DestroyStream(instance, stream, reason);
|
||||
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
// NPN_Write
|
||||
static int32 g_NPN_Write(NPP instance, NPStream *stream, int32 len, void *buf)
|
||||
{
|
||||
if (mozilla_funcs.write == NULL)
|
||||
return -1;
|
||||
|
||||
if (stream == NULL)
|
||||
return -1;
|
||||
|
||||
D(bug("NPP_Write instance=%p\n", instance));
|
||||
int32 ret = CallNPN_WriteProc(mozilla_funcs.write, instance, stream, len, buf);
|
||||
D(bug(" return: %d\n", ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_NPN_Write(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_NPN_Write\n"));
|
||||
|
||||
NPP instance;
|
||||
NPStream *stream;
|
||||
unsigned char *buf;
|
||||
int32_t len;
|
||||
int error = rpc_method_get_args(connection,
|
||||
RPC_TYPE_NPP, &instance,
|
||||
RPC_TYPE_NP_STREAM, &stream,
|
||||
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, &len, &buf,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error != RPC_ERROR_NO_ERROR) {
|
||||
npw_perror("NPN_Write() get args", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
int32 ret = g_NPN_Write(instance, stream, len, buf);
|
||||
|
||||
if (buf)
|
||||
free(buf);
|
||||
|
||||
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
|
||||
}
|
||||
|
||||
// NPN_PushPopupsEnabledState
|
||||
static void g_NPN_PushPopupsEnabledState(NPP instance, NPBool enabled)
|
||||
{
|
||||
if (mozilla_funcs.pushpopupsenabledstate == NULL)
|
||||
return;
|
||||
|
||||
D(bug("NPN_PushPopupsEnabledState instance=%p, enabled=%d\n", instance, enabled));
|
||||
CallNPN_PushPopupsEnabledStateProc(mozilla_funcs.pushpopupsenabledstate, instance, enabled);
|
||||
D(bug(" done\n"));
|
||||
}
|
||||
|
||||
static int handle_NPN_PushPopupsEnabledState(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_NPN_PushPopupsEnabledState\n"));
|
||||
|
||||
NPP instance;
|
||||
uint32_t enabled;
|
||||
int error = rpc_method_get_args(connection,
|
||||
RPC_TYPE_NPP, &instance,
|
||||
RPC_TYPE_UINT32, &enabled,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error != RPC_ERROR_NO_ERROR) {
|
||||
npw_perror("NPN_PushPopupsEnabledState() get args", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
g_NPN_PushPopupsEnabledState(instance, enabled);
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// NPN_PopPopupsEnabledState
|
||||
static void g_NPN_PopPopupsEnabledState(NPP instance)
|
||||
{
|
||||
if (mozilla_funcs.poppopupsenabledstate == NULL)
|
||||
return;
|
||||
|
||||
D(bug("NPN_PopPopupsEnabledState instance=%p\n", instance));
|
||||
CallNPN_PopPopupsEnabledStateProc(mozilla_funcs.poppopupsenabledstate, instance);
|
||||
D(bug(" done\n"));
|
||||
}
|
||||
|
||||
static int handle_NPN_PopPopupsEnabledState(rpc_connection_t *connection)
|
||||
{
|
||||
D(bug("handle_NPN_PopPopupsEnabledState\n"));
|
||||
|
||||
NPP instance;
|
||||
int error = rpc_method_get_args(connection,
|
||||
RPC_TYPE_NPP, &instance,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error != RPC_ERROR_NO_ERROR) {
|
||||
npw_perror("NPN_PopPopupsEnabledState() get args", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
g_NPN_PopPopupsEnabledState(instance);
|
||||
|
||||
return RPC_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// NPN_CreateObject
|
||||
static int handle_NPN_CreateObject(rpc_connection_t *connection)
|
||||
{
|
||||
|
@ -982,7 +1242,6 @@ g_NPP_New(NPMIMEType mime_type, NPP instance,
|
|||
static NPError
|
||||
invoke_NPP_Destroy(NPP instance, NPSavedData **save)
|
||||
{
|
||||
// XXX handle save area (transfer raw bytes but keep size information somewhere)
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NPP_DESTROY,
|
||||
RPC_TYPE_NPP, instance,
|
||||
|
@ -1007,6 +1266,11 @@ invoke_NPP_Destroy(NPP instance, NPSavedData **save)
|
|||
|
||||
if (save)
|
||||
*save = save_area;
|
||||
else if (save_area) {
|
||||
if (save_area->len > 0 && save_area->buf)
|
||||
free(save_area->buf);
|
||||
free(save_area);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1097,7 +1361,24 @@ invoke_NPP_GetValue(NPP instance, NPPVariable variable, void *value)
|
|||
ret = NPERR_GENERIC_ERROR;
|
||||
}
|
||||
D(bug(" value: %s\n", str));
|
||||
*((char **)value) = str; // XXX memory leak
|
||||
switch (variable) {
|
||||
case NPPVformValue:
|
||||
// this is a '\0'-terminated UTF-8 string data allocated by NPN_MemAlloc()
|
||||
if (ret == NPERR_NO_ERROR && str) {
|
||||
char *utf8_str = g_NPN_MemAlloc(strlen(str) + 1);
|
||||
if (utf8_str == NULL)
|
||||
ret = NPERR_OUT_OF_MEMORY_ERROR;
|
||||
else
|
||||
strcpy(utf8_str, str);
|
||||
free(str);
|
||||
str = utf8_str;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// XXX memory leak (add to a deallocation pool?)
|
||||
break;
|
||||
}
|
||||
*((char **)value) = str;
|
||||
break;
|
||||
}
|
||||
case RPC_TYPE_INT32:
|
||||
|
@ -1232,6 +1513,7 @@ invoke_NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool see
|
|||
RPC_TYPE_UINT32, stream->end,
|
||||
RPC_TYPE_UINT32, stream->lastmodified,
|
||||
RPC_TYPE_NP_NOTIFY_DATA, stream->notifyData,
|
||||
RPC_TYPE_STRING, NPN_HAS_FEATURE(RESPONSE_HEADERS) ? stream->headers : NULL,
|
||||
RPC_TYPE_BOOLEAN, seekable,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
|
@ -1269,6 +1551,7 @@ g_NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable
|
|||
memset(stream_pdata, 0, sizeof(*stream_pdata));
|
||||
stream_pdata->stream = stream;
|
||||
stream_pdata->stream_id = id_create(stream_pdata);
|
||||
stream_pdata->is_plugin_stream = 0;
|
||||
stream->pdata = stream_pdata;
|
||||
|
||||
D(bug("NPP_NewStream instance=%p\n", instance));
|
||||
|
@ -1391,7 +1674,7 @@ static int32
|
|||
g_NPP_WriteReady(NPP instance, NPStream *stream)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
return -1;
|
||||
|
||||
D(bug("NPP_WriteReady instance=%p\n", instance));
|
||||
int32 ret = invoke_NPP_WriteReady(instance, stream);
|
||||
|
@ -1434,7 +1717,7 @@ static int32
|
|||
g_NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buf)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
return -1;
|
||||
|
||||
D(bug("NPP_Write instance=%p\n", instance));
|
||||
int32 ret = invoke_NPP_Write(instance, stream, offset, len, buf);
|
||||
|
@ -1590,6 +1873,442 @@ NP_GetMIMEDescription(void)
|
|||
return g_plugin.formats;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === LONG64 NPAPI support === */
|
||||
/* ====================================================================== */
|
||||
|
||||
/*
|
||||
* Dependent on NPSavedData
|
||||
* NPP_New
|
||||
* NPP_Destroy
|
||||
* NOTE: the browsers don't seem to care about NPSavedData
|
||||
*
|
||||
* Dependent on NPWindow / NPSetWindowCallbackStruct
|
||||
* NPP_SetWindow
|
||||
*
|
||||
* Dependent on NPStream (plug-in side)
|
||||
* NPP_NewStream
|
||||
* NPP_DestroyStream
|
||||
* NPP_WriteReady
|
||||
* NPP_Write
|
||||
* NPP_StreamAsFile
|
||||
*
|
||||
* Dependent on NPStream (browser-side)
|
||||
* NPN_RequestRead
|
||||
* NPN_NewStream
|
||||
* NPN_DestroyStream
|
||||
* NPN_Write
|
||||
* NOTE: Konqueror does not implement those
|
||||
*
|
||||
* Dependent on NPPrintCallbackStruct
|
||||
* NPP_Print
|
||||
*/
|
||||
|
||||
// Check if another thunking layer is necessary
|
||||
static int g_use_long64_thunks = -1;
|
||||
|
||||
static void set_use_long64_thunks(bool enabled)
|
||||
{
|
||||
g_use_long64_thunks = enabled;
|
||||
|
||||
if (g_use_long64_thunks) {
|
||||
// XXX update mozilla_funcs with g_LONG64_*() variants
|
||||
}
|
||||
}
|
||||
|
||||
#define NP_CVT32(VAL) ptr32->VAL = ptr64->VAL
|
||||
#define NP_CVT64(VAL) ptr64->VAL = ptr32->VAL
|
||||
|
||||
// Check display is valid
|
||||
static bool is_browser_display(Display *display)
|
||||
{
|
||||
Display *browser_display = NULL;
|
||||
if (mozilla_funcs.getvalue == NULL)
|
||||
return 0;
|
||||
if (mozilla_funcs.getvalue(NULL, NPNVxDisplay, (void *)&browser_display) != NPERR_NO_ERROR)
|
||||
return 0;
|
||||
return display == browser_display;
|
||||
}
|
||||
|
||||
// NPStream
|
||||
typedef struct _LONG64_NPStream {
|
||||
void* pdata;
|
||||
void* ndata;
|
||||
const char* url;
|
||||
uint64 end;
|
||||
uint64 lastmodified;
|
||||
void* notifyData;
|
||||
const char* headers;
|
||||
} LONG64_NPStream;
|
||||
|
||||
static void convert_from_LONG64_NPStream(NPStream *ptr32, const LONG64_NPStream *ptr64)
|
||||
{
|
||||
NP_CVT32(pdata);
|
||||
NP_CVT32(ndata);
|
||||
NP_CVT32(url);
|
||||
NP_CVT32(end);
|
||||
NP_CVT32(lastmodified);
|
||||
NP_CVT32(notifyData);
|
||||
NP_CVT32(headers);
|
||||
}
|
||||
|
||||
#define NP_STREAM32(STREAM) get_stream32(STREAM)
|
||||
|
||||
static inline NPStream *get_stream32(LONG64_NPStream *stream64)
|
||||
{
|
||||
NPStream *stream32 = stream64->pdata;
|
||||
if (stream32 && stream32->ndata == stream64)
|
||||
return stream32;
|
||||
return (NPStream *)stream64;
|
||||
}
|
||||
|
||||
// NPByteRange
|
||||
typedef struct _LONG64_NPByteRange {
|
||||
int64 offset;
|
||||
uint64 length;
|
||||
struct _LONG64_NPByteRange* next;
|
||||
} LONG64_NPByteRange;
|
||||
|
||||
// NPSavedData
|
||||
typedef struct _LONG64_NPSavedData {
|
||||
int64 len;
|
||||
void* buf;
|
||||
} LONG64_NPSavedData;
|
||||
|
||||
static void convert_from_LONG64_NPSavedData(NPSavedData *ptr32, const LONG64_NPSavedData *ptr64)
|
||||
{
|
||||
NP_CVT32(len);
|
||||
NP_CVT32(buf);
|
||||
}
|
||||
|
||||
static void convert_from_NPSavedData(LONG64_NPSavedData *ptr64, const NPSavedData *ptr32)
|
||||
{
|
||||
NP_CVT64(len);
|
||||
NP_CVT64(buf);
|
||||
}
|
||||
|
||||
// NPSetWindowCallbackStruct
|
||||
typedef struct {
|
||||
int64 type;
|
||||
#ifdef MOZ_X11
|
||||
Display* display;
|
||||
Visual* visual;
|
||||
Colormap colormap;
|
||||
unsigned int depth;
|
||||
#endif
|
||||
} LONG64_NPSetWindowCallbackStruct;
|
||||
|
||||
static bool is_LONG64_NPSetWindowCallbackStruct(void *ws_info)
|
||||
{
|
||||
LONG64_NPSetWindowCallbackStruct *ws_info64 = (LONG64_NPSetWindowCallbackStruct *)ws_info;
|
||||
|
||||
return (/* LONG64_NPSetWindowCallbacStruct.type valid? */
|
||||
(ws_info64->type == 0 || ws_info64->type == NP_SETWINDOW) &&
|
||||
#ifdef MOZ_X11
|
||||
/* LONG64_NPSetWindowCallbacStruct.display valid? */
|
||||
is_browser_display(ws_info64->display) &&
|
||||
#endif
|
||||
1);
|
||||
}
|
||||
|
||||
static void convert_from_LONG64_NPSetWindowCallbackStruct(NPSetWindowCallbackStruct *ptr32,
|
||||
const LONG64_NPSetWindowCallbackStruct *ptr64)
|
||||
{
|
||||
NP_CVT32(type);
|
||||
#ifdef MOZ_X11
|
||||
NP_CVT32(display);
|
||||
NP_CVT32(visual);
|
||||
NP_CVT32(colormap);
|
||||
NP_CVT32(depth);
|
||||
#endif
|
||||
}
|
||||
|
||||
// NPPrintCallbackStruct
|
||||
typedef struct {
|
||||
int64 type;
|
||||
FILE* fp;
|
||||
} LONG64_NPPrintCallbackStruct;
|
||||
|
||||
static bool is_LONG64_NPPrintCallbackStruct(void *platformPrint)
|
||||
{
|
||||
LONG64_NPPrintCallbackStruct *platformPrint64 = (LONG64_NPPrintCallbackStruct *)platformPrint;
|
||||
|
||||
return (/* LONG64_NPPrintCallbackStruct.type valid? */
|
||||
platformPrint64->type == NP_PRINT &&
|
||||
/* LONG64_NPPrintCallbackStruct.file valid? */
|
||||
platformPrint64->fp != NULL);
|
||||
}
|
||||
|
||||
static void convert_from_LONG64_NPPrintCallbackStruct(NPPrintCallbackStruct *ptr32,
|
||||
const LONG64_NPPrintCallbackStruct *ptr64)
|
||||
{
|
||||
NP_CVT32(type);
|
||||
NP_CVT32(fp);
|
||||
}
|
||||
|
||||
// NPWindow
|
||||
typedef struct _LONG64_NPWindow {
|
||||
void* window;
|
||||
int64 x;
|
||||
int64 y;
|
||||
uint64 width;
|
||||
uint64 height;
|
||||
NPRect clipRect;
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
void * ws_info;
|
||||
#endif /* XP_UNIX */
|
||||
NPWindowType type;
|
||||
} LONG64_NPWindow;
|
||||
|
||||
static bool is_LONG64_NPWindow(void *window)
|
||||
{
|
||||
NPWindow *window32 = (NPWindow *)window;
|
||||
LONG64_NPWindow *window64 = (LONG64_NPWindow *)window;
|
||||
|
||||
return (/* MSW32(LONG64_NPWindow.x) */
|
||||
(window32->x == 0 || window32->x == 0xffffffff) &&
|
||||
/* MSW32(LONG64_NPWindow.y) */
|
||||
(window32->width == 0 || window32->width == 0xffffffff) &&
|
||||
/* LONG64_NPWindow.clipRect.top, LONG64_NPWindow.clipRect.left */
|
||||
(window32->type != NPWindowTypeWindow && window32->type != NPWindowTypeDrawable) &&
|
||||
/* LONG64_NPWindow.type valid? */
|
||||
(window64->type == NPWindowTypeWindow || window64->type == NPWindowTypeDrawable) &&
|
||||
/* LONG64_NPWindow.ws_info valid? */
|
||||
is_LONG64_NPSetWindowCallbackStruct(window64->ws_info));
|
||||
}
|
||||
|
||||
static void convert_from_LONG64_NPWindow(NPWindow *ptr32, const LONG64_NPWindow *ptr64)
|
||||
{
|
||||
NP_CVT32(type);
|
||||
NP_CVT32(window);
|
||||
NP_CVT32(x);
|
||||
NP_CVT32(y);
|
||||
NP_CVT32(width);
|
||||
NP_CVT32(height);
|
||||
NP_CVT32(clipRect.top);
|
||||
NP_CVT32(clipRect.left);
|
||||
NP_CVT32(clipRect.bottom);
|
||||
NP_CVT32(clipRect.right);
|
||||
convert_from_LONG64_NPSetWindowCallbackStruct(ptr32->ws_info, ptr64->ws_info);
|
||||
}
|
||||
|
||||
// NPP_SetWindow (LONG64)
|
||||
static NPError
|
||||
g_LONG64_NPP_SetWindow(NPP instance, void *window)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
|
||||
// Detect broken 64-bit NPAPI
|
||||
if (g_use_long64_thunks < 0)
|
||||
set_use_long64_thunks(is_LONG64_NPWindow(window));
|
||||
|
||||
NPWindow window32;
|
||||
NPSetWindowCallbackStruct ws_info32;
|
||||
if (g_use_long64_thunks) {
|
||||
window32.ws_info = &ws_info32;
|
||||
convert_from_LONG64_NPWindow(&window32, window);
|
||||
window = &window32;
|
||||
}
|
||||
|
||||
return g_NPP_SetWindow(instance, window);
|
||||
}
|
||||
|
||||
// NPP_New (LONG64)
|
||||
static NPError
|
||||
g_LONG64_NPP_New(NPMIMEType mime_type, NPP instance,
|
||||
uint16_t mode, int16_t argc, char *argn[], char *argv[],
|
||||
void *saved)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
|
||||
NPSavedData saved32;
|
||||
if (saved && g_use_long64_thunks > 0) {
|
||||
convert_from_LONG64_NPSavedData(&saved32, saved);
|
||||
saved = &saved32;
|
||||
}
|
||||
|
||||
return g_NPP_New(mime_type, instance, mode, argc, argn, argv, saved);
|
||||
}
|
||||
|
||||
// NPP_Destroy (LONG64)
|
||||
static NPError
|
||||
g_LONG64_NPP_Destroy(NPP instance, void **save)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
|
||||
NPSavedData *save_area32 = NULL;
|
||||
NPError ret = g_NPP_Destroy(instance, &save_area32);
|
||||
|
||||
if (save && g_use_long64_thunks > 0) {
|
||||
LONG64_NPSavedData *save_area64 = NULL;
|
||||
if (ret == NPERR_NO_ERROR && save_area32) {
|
||||
if ((save_area64 = g_NPN_MemAlloc(save_area32->len)) != NULL)
|
||||
convert_from_NPSavedData(save_area64, save_area32);
|
||||
free(save_area32);
|
||||
}
|
||||
*save = save_area64;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPP_NewStream (LONG64)
|
||||
static NPError
|
||||
g_LONG64_NPP_NewStream(NPP instance, NPMIMEType type, void *stream, NPBool seekable, uint16 *stype)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
|
||||
// Detect broken 64-bit NPAPI
|
||||
if (g_use_long64_thunks < 0) {
|
||||
npw_printf("WARNING: function using an NPStream was called too early, could not determine LONG64 data structure\n");
|
||||
set_use_long64_thunks(false);
|
||||
}
|
||||
|
||||
if (g_use_long64_thunks) {
|
||||
NPStream *stream32;
|
||||
if ((stream32 = malloc(sizeof(*stream32))) == NULL)
|
||||
return NPERR_OUT_OF_MEMORY_ERROR;
|
||||
convert_from_LONG64_NPStream(stream32, stream);
|
||||
stream32->ndata = stream;
|
||||
((NPStream *)stream)->pdata = stream32;
|
||||
}
|
||||
|
||||
return g_NPP_NewStream(instance, type, NP_STREAM32(stream), seekable, stype);
|
||||
}
|
||||
|
||||
// NPP_DestroyStream (LONG64)
|
||||
static NPError
|
||||
g_LONG64_NPP_DestroyStream(NPP instance, void *stream, NPReason reason)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
|
||||
if (stream == NULL)
|
||||
return NPERR_INVALID_PARAM;
|
||||
|
||||
NPError ret = g_NPP_DestroyStream(instance, NP_STREAM32(stream), reason);
|
||||
|
||||
if (g_use_long64_thunks) {
|
||||
free(((NPStream *)stream)->pdata);
|
||||
((NPStream *)stream)->pdata = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NPP_WriteReady (LONG64)
|
||||
static int64
|
||||
g_LONG64_NPP_WriteReady(NPP instance, void *stream)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return -1L;
|
||||
|
||||
if (stream == NULL)
|
||||
return -1L;
|
||||
|
||||
return (int64)(int32)g_NPP_WriteReady(instance, NP_STREAM32(stream));
|
||||
}
|
||||
|
||||
// NPP_Write (LONG64)
|
||||
static int64
|
||||
g_LONG64_NPP_Write(NPP instance, void *stream, int64 offset, int64 len, void *buf)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return -1L;
|
||||
|
||||
if (stream == NULL)
|
||||
return -1L;
|
||||
|
||||
return (int64)(int32)g_NPP_Write(instance, NP_STREAM32(stream), offset, len, buf);
|
||||
}
|
||||
|
||||
// NPP_StreamAsFile (LONG64)
|
||||
static void
|
||||
g_LONG64_NPP_StreamAsFile(NPP instance, void *stream, const char *fname)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return;
|
||||
|
||||
if (stream == NULL)
|
||||
return;
|
||||
|
||||
g_NPP_StreamAsFile(instance, NP_STREAM32(stream), fname);
|
||||
}
|
||||
|
||||
// NPP_Print (LONG64)
|
||||
static void g_LONG64_NPP_Print(NPP instance, void *PrintInfo)
|
||||
{
|
||||
if (instance == NULL)
|
||||
return;
|
||||
|
||||
if (PrintInfo == NULL)
|
||||
return;
|
||||
|
||||
// Detect broken 64-bit NPAPI
|
||||
if (g_use_long64_thunks < 0)
|
||||
set_use_long64_thunks(is_LONG64_NPPrintCallbackStruct(PrintInfo));
|
||||
|
||||
NPPrint PrintInfo32;
|
||||
NPPrintCallbackStruct platformPrint32;
|
||||
if (g_use_long64_thunks) {
|
||||
memcpy(&PrintInfo32, PrintInfo, sizeof(PrintInfo32));
|
||||
void *platformPrint;
|
||||
switch (((NPPrint *)PrintInfo)->mode) {
|
||||
case NP_FULL:
|
||||
platformPrint = ((NPPrint *)PrintInfo)->print.fullPrint.platformPrint;
|
||||
convert_from_LONG64_NPPrintCallbackStruct(&platformPrint32, platformPrint);
|
||||
PrintInfo32.print.fullPrint.platformPrint = &platformPrint32;
|
||||
break;
|
||||
case NP_EMBED:
|
||||
platformPrint = ((NPPrint *)PrintInfo)->print.embedPrint.platformPrint;
|
||||
convert_from_LONG64_NPPrintCallbackStruct(&platformPrint32, platformPrint);
|
||||
PrintInfo32.print.embedPrint.platformPrint = &platformPrint32;
|
||||
break;
|
||||
}
|
||||
PrintInfo = &PrintInfo32;
|
||||
}
|
||||
|
||||
g_NPP_Print(instance, PrintInfo);
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Plug-in initialization === */
|
||||
/* ====================================================================== */
|
||||
|
||||
// Detect Konqueror
|
||||
static bool is_konqueror(void)
|
||||
{
|
||||
if (dlsym(RTLD_DEFAULT, "qApp") == NULL)
|
||||
return false;
|
||||
if (mozilla_funcs.getvalue == NULL)
|
||||
return false;
|
||||
Display *x_display = NULL;
|
||||
if (mozilla_funcs.getvalue(NULL, NPNVxDisplay, (void *)&x_display) != NPERR_NO_ERROR)
|
||||
return false;
|
||||
XtAppContext x_app_context = NULL;
|
||||
if (mozilla_funcs.getvalue(NULL, NPNVxtAppContext, (void *)&x_app_context) != NPERR_NO_ERROR)
|
||||
return false;
|
||||
if (x_display == NULL || x_app_context == NULL)
|
||||
return false;
|
||||
String name, class;
|
||||
XtGetApplicationNameAndClass(x_display, &name, &class);
|
||||
if (strcmp(name, "nspluginviewer") == 0)
|
||||
return true;
|
||||
// XXX user-agent string can be changed, but it's still an heuristic
|
||||
const char *user_agent = g_NPN_UserAgent(NULL);
|
||||
if (user_agent == NULL)
|
||||
return false;
|
||||
if (strstr(user_agent, "Konqueror") != NULL)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Provides global initialization for a plug-in
|
||||
NPError
|
||||
NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
|
||||
|
@ -1630,6 +2349,21 @@ NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
|
|||
plugin_funcs->getvalue = NewNPP_GetValueProc(g_NPP_GetValue);
|
||||
plugin_funcs->setvalue = NewNPP_SetValueProc(g_NPP_SetValue);
|
||||
|
||||
// override function table with an additional thunking layer for
|
||||
// possibly broken 64-bit Konqueror versions (NPAPI 0.11)
|
||||
if (is_konqueror() && sizeof(void *) == 8 && ! NPN_HAS_FEATURE(NPRUNTIME_SCRIPTING)) {
|
||||
D(bug("Installing Konqueror workarounds\n"));
|
||||
plugin_funcs->setwindow = NewNPP_SetWindowProc(g_LONG64_NPP_SetWindow);
|
||||
plugin_funcs->newstream = NewNPP_NewStreamProc(g_LONG64_NPP_NewStream);
|
||||
plugin_funcs->destroystream = NewNPP_DestroyStreamProc(g_LONG64_NPP_DestroyStream);
|
||||
plugin_funcs->asfile = NewNPP_StreamAsFileProc(g_LONG64_NPP_StreamAsFile);
|
||||
plugin_funcs->writeready = NewNPP_WriteReadyProc(g_LONG64_NPP_WriteReady);
|
||||
plugin_funcs->write = NewNPP_WriteProc(g_LONG64_NPP_Write);
|
||||
plugin_funcs->print = NewNPP_PrintProc(g_LONG64_NPP_Print);
|
||||
plugin_funcs->newp = NewNPP_NewProc(g_LONG64_NPP_New);
|
||||
plugin_funcs->destroy = NewNPP_DestroyProc(g_LONG64_NPP_Destroy);
|
||||
}
|
||||
|
||||
if (g_plugin.initialized == 0 || g_plugin.initialized == 1)
|
||||
plugin_init(1);
|
||||
if (g_plugin.initialized <= 0)
|
||||
|
@ -1638,17 +2372,13 @@ NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
|
|||
if (!npobject_bridge_new())
|
||||
return NPERR_MODULE_LOAD_FAILED_ERROR;
|
||||
|
||||
// NPRuntime appeared in NPAPI >= 0.14
|
||||
bool has_npruntime = true;
|
||||
if ((moz_funcs->version >> 8) == 0 && (moz_funcs->version & 0xff) < 14)
|
||||
has_npruntime = false;
|
||||
// check that the browser doesn't lie
|
||||
if (moz_funcs->size < (offsetof(NPNetscapeFuncs, setexception) + sizeof(NPN_SetExceptionUPP)))
|
||||
has_npruntime = false;
|
||||
// pass down common NPAPI version supported by both the underlying
|
||||
// browser and the thunking capabilities of nspluginwrapper
|
||||
uint32_t version = min(moz_funcs->version, plugin_funcs->version);
|
||||
|
||||
int error = rpc_method_invoke(g_rpc_connection,
|
||||
RPC_METHOD_NP_INITIALIZE,
|
||||
RPC_TYPE_UINT32, (uint32_t)has_npruntime,
|
||||
RPC_TYPE_UINT32, (uint32_t)version,
|
||||
RPC_TYPE_INVALID);
|
||||
|
||||
if (error != RPC_ERROR_NO_ERROR) {
|
||||
|
@ -1707,13 +2437,8 @@ NP_Shutdown(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* === Plug initialization === */
|
||||
/* ====================================================================== */
|
||||
|
||||
// Initialize wrapper plugin and execute viewer
|
||||
static void do_plugin_init(int is_NP_Initialize)
|
||||
static void plugin_init(int is_NP_Initialize)
|
||||
{
|
||||
if (g_plugin.initialized < 0)
|
||||
return;
|
||||
|
@ -1754,28 +2479,30 @@ static void do_plugin_init(int is_NP_Initialize)
|
|||
FILE *viewer_fp = popen(command, "r");
|
||||
if (viewer_fp == NULL)
|
||||
return;
|
||||
char **strings[] = { &g_plugin.name, &g_plugin.description, &g_plugin.formats, NULL };
|
||||
int i, error = 0;
|
||||
for (i = 0; strings[i] != NULL; i++) {
|
||||
int len;
|
||||
if (fscanf(viewer_fp, "%d\n", &len) != 1) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
char *str = malloc(len + 1);
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), viewer_fp)) {
|
||||
// Read line
|
||||
int len = strlen(line);
|
||||
if (len == 0)
|
||||
str[0] = '\0';
|
||||
else {
|
||||
if (fgets(str, len, viewer_fp) == NULL) {
|
||||
error = 1;
|
||||
break;
|
||||
continue;
|
||||
line[len - 1] = '\0';
|
||||
|
||||
// Parse line
|
||||
char tag[sizeof(line)];
|
||||
if (sscanf(line, "%s %d", tag, &len) == 2) {
|
||||
char *str = malloc(++len);
|
||||
if (str && fgets(str, len, viewer_fp)) {
|
||||
if (strcmp(tag, "PLUGIN_NAME") == 0)
|
||||
g_plugin.name = str;
|
||||
else if (strcmp(tag, "PLUGIN_DESC") == 0)
|
||||
g_plugin.description = str;
|
||||
else if (strcmp(tag, "PLUGIN_MIME") == 0)
|
||||
g_plugin.formats = str;
|
||||
}
|
||||
}
|
||||
*(strings[i]) = str;
|
||||
}
|
||||
pclose(viewer_fp);
|
||||
if (error == 0)
|
||||
g_plugin.initialized = 1;
|
||||
g_plugin.initialized = 1;
|
||||
}
|
||||
|
||||
if (!is_NP_Initialize)
|
||||
|
@ -1817,6 +2544,11 @@ static void do_plugin_init(int is_NP_Initialize)
|
|||
{ RPC_METHOD_NPN_STATUS, handle_NPN_Status },
|
||||
{ RPC_METHOD_NPN_PRINT_DATA, handle_NPN_PrintData },
|
||||
{ RPC_METHOD_NPN_REQUEST_READ, handle_NPN_RequestRead },
|
||||
{ RPC_METHOD_NPN_NEW_STREAM, handle_NPN_NewStream },
|
||||
{ RPC_METHOD_NPN_DESTROY_STREAM, handle_NPN_DestroyStream },
|
||||
{ RPC_METHOD_NPN_WRITE, handle_NPN_Write },
|
||||
{ RPC_METHOD_NPN_PUSH_POPUPS_ENABLED_STATE, handle_NPN_PushPopupsEnabledState },
|
||||
{ RPC_METHOD_NPN_POP_POPUPS_ENABLED_STATE, handle_NPN_PopPopupsEnabledState },
|
||||
{ RPC_METHOD_NPN_CREATE_OBJECT, handle_NPN_CreateObject },
|
||||
{ RPC_METHOD_NPN_RETAIN_OBJECT, handle_NPN_RetainObject },
|
||||
{ RPC_METHOD_NPN_RELEASE_OBJECT, handle_NPN_ReleaseObject },
|
||||
|
@ -1909,15 +2641,8 @@ static void do_plugin_init(int is_NP_Initialize)
|
|||
D(bug("--- INIT ---\n"));
|
||||
}
|
||||
|
||||
static void plugin_init(int is_NP_Initialize)
|
||||
{
|
||||
pthread_mutex_lock(&plugin_init_lock);
|
||||
do_plugin_init(is_NP_Initialize);
|
||||
pthread_mutex_unlock(&plugin_init_lock);
|
||||
}
|
||||
|
||||
// Kill NSPlugin Viewer process
|
||||
static void do_plugin_exit(void)
|
||||
static void plugin_exit(void)
|
||||
{
|
||||
D(bug("plugin_exit\n"));
|
||||
|
||||
|
@ -1964,13 +2689,6 @@ static void do_plugin_exit(void)
|
|||
g_plugin.initialized = 0;
|
||||
}
|
||||
|
||||
static void plugin_exit(void)
|
||||
{
|
||||
pthread_mutex_lock(&plugin_init_lock);
|
||||
do_plugin_exit();
|
||||
pthread_mutex_unlock(&plugin_init_lock);
|
||||
}
|
||||
|
||||
static void __attribute__((destructor)) plugin_exit_sentinel(void)
|
||||
{
|
||||
plugin_exit();
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* xembed.h - XEMBED definitions
|
||||
*
|
||||
* nspluginwrapper (C) 2005-2007 Gwenole Beauchesne
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef XEMBED_H
|
||||
#define XEMBED_H
|
||||
|
||||
// XEMBED messages
|
||||
#define XEMBED_EMBEDDED_NOTIFY 0
|
||||
#define XEMBED_WINDOW_ACTIVATE 1
|
||||
#define XEMBED_WINDOW_DEACTIVATE 2
|
||||
#define XEMBED_REQUEST_FOCUS 3
|
||||
#define XEMBED_FOCUS_IN 4
|
||||
#define XEMBED_FOCUS_OUT 5
|
||||
#define XEMBED_FOCUS_NEXT 6
|
||||
#define XEMBED_FOCUS_PREV 7
|
||||
#define XEMBED_GRAB_KEY 8
|
||||
#define XEMBED_UNGRAB_KEY 9
|
||||
#define XEMBED_MODALITY_ON 10
|
||||
#define XEMBED_MODALITY_OFF 11
|
||||
|
||||
// Non-standard messages
|
||||
#define XEMBED_GTK_GRAB_KEY 108
|
||||
#define XEMBED_GTK_UNGRAB_KEY 109
|
||||
|
||||
// Details for XEMBED_FOCUS_IN
|
||||
#define XEMBED_FOCUS_CURRENT 0
|
||||
#define XEMBED_FOCUS_FIRST 1
|
||||
#define XEMBED_FOCUS_LAST 2
|
||||
|
||||
// Flags for _XEMBED_INFO
|
||||
#define XEMBED_MAPPED (1 << 0)
|
||||
|
||||
#endif /* XEMBED_H */
|
|
@ -30,5 +30,12 @@ Various sample data to exercise the NPAPI plugins compatibility layer
|
|||
<li><p><b>Citrix ICA Client demo</b><br>
|
||||
<a href="http://www.rentonlinesoftware.com/store/tryademo.asp">http://www.rentonlinesoftware.com/store/tryademo.asp</a>
|
||||
</ul>
|
||||
|
||||
Individual testcases:
|
||||
<ul>
|
||||
<li><p>Debian bug <a
|
||||
href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=435912">#435912</a> (focus problem)<br>
|
||||
<a href="http://www.addictinggames.com/bloxors.html">http://www.addictinggames.com/bloxors.html</a>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
|
234
utils/xtrace.c
234
utils/xtrace.c
|
@ -1,11 +1,13 @@
|
|||
#define _GNU_SOURCE 1 /* RTLD_NEXT */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
@ -15,11 +17,12 @@
|
|||
#include <X11/StringDefs.h>
|
||||
|
||||
|
||||
static int g_debug_level = -1;
|
||||
static int g_debug_level = 1;
|
||||
static FILE *g_log_file = NULL;
|
||||
|
||||
void npw_printf(const char *format, ...)
|
||||
{
|
||||
#if 0
|
||||
if (g_debug_level < 0) {
|
||||
g_debug_level = 0;
|
||||
const char *debug_str = getenv("NPW_DEBUG");
|
||||
|
@ -38,6 +41,9 @@ void npw_printf(const char *format, ...)
|
|||
if (log_file == NULL)
|
||||
g_log_file = stderr;
|
||||
}
|
||||
#else
|
||||
g_log_file = stderr;
|
||||
#endif
|
||||
|
||||
if (g_debug_level > 0) {
|
||||
va_list args;
|
||||
|
@ -47,7 +53,102 @@ void npw_printf(const char *format, ...)
|
|||
}
|
||||
}
|
||||
|
||||
#define PREPARE_FUNC(NAME, RET, ARGS) \
|
||||
static RET (*lib_##NAME) ARGS; \
|
||||
if (lib_##NAME == NULL) \
|
||||
lib_##NAME = dlsym(RTLD_NEXT, #NAME); \
|
||||
assert(lib_##NAME != NULL)
|
||||
|
||||
#if 0
|
||||
char *getenv(const char *name)
|
||||
{
|
||||
PREPARE_FUNC(getenv, char *, (const char *));
|
||||
char *str = lib_getenv(name);
|
||||
npw_printf("getenv '%s' => '%s'\n", name ? name : "<null>", str ? str : "<null>");
|
||||
return str;
|
||||
}
|
||||
|
||||
int putenv(char *string)
|
||||
{
|
||||
PREPARE_FUNC(putenv, int, (char *));
|
||||
npw_printf("putenv '%s'\n", string ? string : "<null>");
|
||||
return lib_putenv(string);
|
||||
}
|
||||
#endif
|
||||
|
||||
int XSetClassHints(Display *display, Window w, XClassHint *class_hints)
|
||||
{
|
||||
PREPARE_FUNC(XSetClassHints, int, (Display *, Window, XClassHint *));
|
||||
npw_printf("XSetClassHints(window %p, class_hints { %s, '%s' }\n", w, class_hints->res_name, class_hints->res_class);
|
||||
return lib_XSetClassHints(display, w, class_hints);
|
||||
}
|
||||
|
||||
static void print_backtrace(void)
|
||||
{
|
||||
#if 0
|
||||
#define N_LEVELS 64
|
||||
void *trace[N_LEVELS];
|
||||
int n_levels = backtrace(trace, sizeof(trace)/sizeof(trace[0]));
|
||||
backtrace_symbols_fd(trace, n_levels, STDERR_FILENO);
|
||||
#endif
|
||||
}
|
||||
|
||||
Status XSendEvent(Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send)
|
||||
{
|
||||
PREPARE_FUNC(XSendEvent, Status, (Display *, Window, Bool, long, XEvent *));
|
||||
if (event_send && (1 || ((XAnyEvent *)event_send)->send_event)) {
|
||||
npw_printf("XSendEvent(window %p, propagate %d, event_mask %08x, event type %d, SendEvent %x)\n",
|
||||
w, propagate, event_mask, event_send->type, event_send->xany.send_event);
|
||||
}
|
||||
print_backtrace();
|
||||
if (event_send->xclient.message_type == XInternAtom(display, "_XEMBED", False))
|
||||
npw_printf("[X11] Handle XEMBED message %d for window %p\n", event_send->xclient.data.l[1], event_send->xany.window);
|
||||
return lib_XSendEvent(display, w, propagate, event_mask, event_send);
|
||||
}
|
||||
|
||||
#if 0
|
||||
Window XCreateWindow(Display *display, Window parent, int x, int y,
|
||||
unsigned int width, unsigned int height,
|
||||
unsigned int border_width, int depth, unsigned int class, Visual *visual,
|
||||
unsigned long valuemask, XSetWindowAttributes *attributes)
|
||||
{
|
||||
PREPARE_FUNC(XCreateWindow, Window, (Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *));
|
||||
Window ret = lib_XCreateWindow(display, parent, x, y, width, height,
|
||||
border_width, depth, class, visual,
|
||||
valuemask, attributes);
|
||||
npw_printf("[X11] XCreateWindow() -> %p\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int XChangeProperty(Display *display, Window w, Atom property, Atom type,
|
||||
int format, int mode, const unsigned char *data, int nelements)
|
||||
{
|
||||
PREPARE_FUNC(XChangeProperty, int, (Display *, Window, Atom, Atom, int, int, const unsigned char *, int));
|
||||
const char *property_str = XGetAtomName(display, property);
|
||||
const char *type_str = XGetAtomName(display, type);
|
||||
npw_printf("XChangeProperty(window %p, property %s, type %s, format %d, mode %d)\n",
|
||||
w, property_str, type_str, format, mode);
|
||||
int ret = lib_XChangeProperty(display, w, property, type, format, mode, data, nelements);
|
||||
if (property == XInternAtom(display, "WM_HINTS", False) && format == 32) {
|
||||
XWMHints *hints = XGetWMHints(display, w);
|
||||
if (hints) {
|
||||
npw_printf(" InputHint %d\n", hints->input);
|
||||
XFree((void *)hints);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void XtConfigureWidget(Widget w, Position x, Position y, Dimension width, Dimension height, Dimension border_width)
|
||||
{
|
||||
PREPARE_FUNC(XtConfigureWidget, void, (Widget, Position, Position, Dimension, Dimension, Dimension));
|
||||
lib_XtConfigureWidget(w, x, y, width, height, border_width);
|
||||
}
|
||||
|
||||
#if 0
|
||||
Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists)
|
||||
{
|
||||
static Atom (*x_XInternAtom)(Display *, const char *, Bool) = NULL;
|
||||
|
@ -58,21 +159,38 @@ Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists)
|
|||
Atom ret = x_XInternAtom(display, atom_name, only_if_exists);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static XtEventHandler app_event_handler = NULL;
|
||||
typedef struct {
|
||||
void *client_data;
|
||||
XtEventHandler event_handler;
|
||||
} fake_event_handler_data;
|
||||
|
||||
static void fake_event_handler(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
|
||||
{
|
||||
fake_event_handler_data *pdata = (fake_event_handler_data *)client_data;
|
||||
|
||||
switch (event->type) {
|
||||
case ButtonPress:
|
||||
npw_printf("ButtonPress\n");
|
||||
break;
|
||||
case ButtonRelease:
|
||||
npw_printf("ButtonRelease\n");
|
||||
break;
|
||||
case KeyPress:
|
||||
npw_printf("KeyPress\n");
|
||||
break;
|
||||
case ButtonPress:
|
||||
npw_printf("ButtonPress\n");
|
||||
// asm volatile ("int3");
|
||||
case KeyRelease:
|
||||
npw_printf("KeyRelease\n");
|
||||
break;
|
||||
case FocusIn:
|
||||
npw_printf("[X11] FocusIn for window %p\n", event->xfocus.window);
|
||||
break;
|
||||
case FocusOut:
|
||||
npw_printf("[X11] FocusOut for window %p\n", event->xfocus.window);
|
||||
break;
|
||||
}
|
||||
app_event_handler(w, client_data, event, cont);
|
||||
pdata->event_handler(w, pdata->client_data, event, cont);
|
||||
}
|
||||
|
||||
static const char *dlname(void *addr)
|
||||
|
@ -83,6 +201,37 @@ static const char *dlname(void *addr)
|
|||
return dlinfo.dli_sname;
|
||||
}
|
||||
|
||||
static void print_event_mask(EventMask event_mask)
|
||||
{
|
||||
#define P(EVENT) if (event_mask & (EVENT##Mask)) npw_printf(" " #EVENT "\n")
|
||||
P(KeyPress);
|
||||
P(KeyRelease);
|
||||
P(ButtonPress);
|
||||
P(ButtonRelease);
|
||||
P(EnterWindow);
|
||||
P(LeaveWindow);
|
||||
P(PointerMotion);
|
||||
P(PointerMotionHint);
|
||||
P(Button1Motion);
|
||||
P(Button2Motion);
|
||||
P(Button3Motion);
|
||||
P(Button4Motion);
|
||||
P(Button5Motion);
|
||||
P(ButtonMotion);
|
||||
P(KeymapState);
|
||||
P(Exposure);
|
||||
P(VisibilityChange);
|
||||
P(StructureNotify);
|
||||
P(ResizeRedirect);
|
||||
P(SubstructureNotify);
|
||||
P(SubstructureRedirect);
|
||||
P(FocusChange);
|
||||
P(PropertyChange);
|
||||
P(ColormapChange);
|
||||
P(OwnerGrabButton);
|
||||
}
|
||||
|
||||
#if 1
|
||||
void XtAddEventHandler(Widget w, EventMask event_mask, Bool nonmaskable,
|
||||
XtEventHandler proc, XtPointer client_data)
|
||||
{
|
||||
|
@ -90,15 +239,67 @@ void XtAddEventHandler(Widget w, EventMask event_mask, Bool nonmaskable,
|
|||
if (x_XtAddEventHandler == NULL)
|
||||
x_XtAddEventHandler = dlsym(RTLD_NEXT, "XtAddEventHandler");
|
||||
|
||||
npw_printf("[X11] XtAddEventHandler(Widget=%p[0x%08x], event_mask=%x, nonmaskable=%d, proc=%p[%s])\n",
|
||||
w, XtWindow(w), event_mask, nonmaskable, proc, dlname(proc));
|
||||
if (event_mask & ButtonPressMask) {
|
||||
app_event_handler = proc;
|
||||
proc = fake_event_handler;
|
||||
if (0 || (event_mask & (KeyPressMask|KeyReleaseMask))) {
|
||||
npw_printf("[X11] XtAddEventHandler(Widget=%p[0x%08x], event_mask=%x, nonmaskable=%d, proc=%p[%s])\n",
|
||||
w, XtWindow(w), event_mask, nonmaskable, proc, dlname(proc));
|
||||
print_event_mask(event_mask);
|
||||
}
|
||||
#if 1
|
||||
if (event_mask & (KeyPressMask|KeyReleaseMask)) {
|
||||
fake_event_handler_data *pdata = malloc(sizeof(*pdata));
|
||||
pdata->client_data = client_data;
|
||||
pdata->event_handler = proc;
|
||||
proc = fake_event_handler;
|
||||
client_data = pdata;
|
||||
}
|
||||
#endif
|
||||
x_XtAddEventHandler(w, event_mask, nonmaskable, proc, client_data);
|
||||
#if 0
|
||||
if (event_mask & (KeyPressMask|KeyReleaseMask))
|
||||
x_XtAddEventHandler(w, event_mask, nonmaskable, fake_event_handler, client_data);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void XtAddCallback(Widget w, _Xconst _XtString callback_name, XtCallbackProc callback, XtPointer client_data)
|
||||
{
|
||||
static void (*x_XtAddCallback)(Widget, _Xconst _XtString, XtCallbackProc, XtPointer);
|
||||
if (x_XtAddCallback == NULL)
|
||||
x_XtAddCallback = dlsym(RTLD_NEXT, "XtAddCallback");
|
||||
|
||||
npw_printf("[X11] XtAddCallback(widget %p[0x%08x], callback_name '%s', callback %p[%s], client_data %p)\n",
|
||||
w, XtWindow(w), callback_name, callback, dlname(callback), client_data);
|
||||
x_XtAddCallback(w, callback_name, callback, client_data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int XtGrabKeyboard(Widget w, _XtBoolean owner_events, int pointer_mode, int keyboard_mode, Time time)
|
||||
{
|
||||
static int (*x_XtGrabKeyboard)(Widget, _XtBoolean, int, int, Time);
|
||||
if (x_XtGrabKeyboard == NULL)
|
||||
x_XtGrabKeyboard = dlsym(RTLD_NEXT, "XtGrabKeyboard");
|
||||
|
||||
npw_printf("[X11] XtGrabKeyboard(widget %p[0x%08x], owner_events %08x, pointer_mode %08x, keyboard_mode %08x, time %d)\n",
|
||||
w, XtWindow(w), owner_events, pointer_mode, keyboard_mode, time);
|
||||
int rc = x_XtGrabKeyboard(w, owner_events, pointer_mode, keyboard_mode, time);
|
||||
npw_printf(" returns %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void XtUngrabKeyboard(Widget w, Time time)
|
||||
{
|
||||
static void (*x_XtUngrabKeyboard)(Widget, Time);
|
||||
if (x_XtUngrabKeyboard == NULL)
|
||||
x_XtUngrabKeyboard = dlsym(RTLD_NEXT, "XtUngrabKeyboard");
|
||||
|
||||
npw_printf("[X11] XtUngrabKeyboard(widget %p[%08x], time %d)\n", w, XtWindow(w), time);
|
||||
x_XtUngrabKeyboard(w, time);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
XtIntervalId XtAppAddTimeOut(XtAppContext app_context, unsigned long
|
||||
interval, XtTimerCallbackProc proc, XtPointer client_data)
|
||||
{
|
||||
|
@ -143,7 +344,9 @@ Status XGetWindowAttributes(Display *display, Window w, XWindowAttributes *attr)
|
|||
attr->x, attr->y, attr->width, attr->height, attr->border_width);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
Widget XtCreatePopupShell(const char *name, WidgetClass widget_class, Widget
|
||||
parent, ArgList args, Cardinal num_args)
|
||||
{
|
||||
|
@ -159,6 +362,7 @@ Widget XtCreatePopupShell(const char *name, WidgetClass widget_class, Widget
|
|||
npw_printf(" return: %p [0x%08x]\n", ret, XtWindow(ret));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
Status XQueryTree(Display *display, Window w, Window *root_return, Window *parent_return,
|
||||
|
@ -180,7 +384,6 @@ Status XQueryTree(Display *display, Window w, Window *root_return, Window *paren
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Bool XQueryPointer(Display *display, Window w, Window *root_return,
|
||||
Window *child_return, int *root_x_return, int *root_y_return,
|
||||
|
@ -201,6 +404,7 @@ Bool XQueryPointer(Display *display, Window w, Window *root_return,
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
Widget XtWindowToWidget(Display *display, Window window)
|
||||
|
@ -214,7 +418,6 @@ Widget XtWindowToWidget(Display *display, Window window)
|
|||
npw_printf(" return: %p\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Widget XtParent(Widget w)
|
||||
{
|
||||
|
@ -227,7 +430,9 @@ Widget XtParent(Widget w)
|
|||
npw_printf(" return: 0x%08x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static XErrorHandler app_error_handler = NULL;
|
||||
|
||||
static int fake_error_handler(Display *display, XErrorEvent *error_event)
|
||||
|
@ -247,7 +452,9 @@ XErrorHandler XSetErrorHandler(XErrorHandler handler)
|
|||
XErrorHandler ret = fn(fake_error_handler);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int XPutImage(Display *display, Drawable d, GC gc, XImage *image,
|
||||
int src_x, int src_y, int dest_x, int dest_y, unsigned int width,
|
||||
unsigned int height)
|
||||
|
@ -282,3 +489,4 @@ Status XShmPutImage(Display *display, Drawable d, GC gc, XImage *image,
|
|||
npw_printf(" return: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue