1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: npwrap.cxx,v $
10 * $Revision: 1.16.90.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
40 #include <plugin/unx/plugcon.hxx>
43 #include <osl/module.h>
45 PluginConnector
* pConnector
= NULL
;
47 int nAppArguments
= 0;
48 char** pAppArguments
= NULL
;
49 Display
* pAppDisplay
= NULL
;
50 Display
* pXtAppDisplay
= NULL
;
52 extern oslModule pPluginLib
;
53 extern NPError (*pNP_Shutdown
)();
55 void LoadAdditionalLibs(const char*);
57 XtAppContext app_context
;
58 Widget topLevel
= NULL
, topBox
= NULL
;
59 int wakeup_fd
[2] = { 0, 0 };
60 static bool bPluginAppQuit
= false;
62 static long GlobalConnectionLostHdl( void* /*pInst*/, void* /*pArg*/ )
64 medDebug( 1, "pluginapp exiting due to connection lost\n" );
66 write( wakeup_fd
[1], "xxxx", 4 );
72 static int plugin_x_error_handler( Display
*, XErrorEvent
* )
78 static void ThreadEventHandler( XtPointer
/*client_data*/, int* /*source*/, XtInputId
* id
)
84 while( (len
= read( wakeup_fd
[0], buf
, sizeof( buf
) ) ) > 0 )
86 if( ! bPluginAppQuit
)
88 if( ( nLast
== -1 || buf
[nLast
] != 'x' ) && pConnector
)
89 pConnector
->CallWorkHandler();
92 // it seems you can use XtRemoveInput only
93 // safely from within the callback
95 medDebug( 1, "removing wakeup pipe\n" );
97 XtAppSetExitFlag( app_context
);
98 bPluginAppQuit
= true;
109 IMPL_LINK( PluginConnector
, NewMessageHdl
, Mediator
*, /*pMediator*/ )
111 medDebug( 1, "new message handler\n" );
112 write( wakeup_fd
[1], "cccc", 4 );
117 Widget
createSubWidget( char* /*pPluginText*/, Widget shell
, XLIB_Window aParentWindow
)
119 Widget newWidget
= XtVaCreateManagedWidget(
120 #if defined USE_MOTIF
122 xmDrawingAreaWidgetClass
,
125 # if defined DISABLE_XAW
126 compositeWidgetClass
,
135 XtRealizeWidget( shell
);
136 XtRealizeWidget( newWidget
);
138 medDebug( 1, "Reparenting new widget %x to %x\n", XtWindow( newWidget
), aParentWindow
);
139 XReparentWindow( pXtAppDisplay
,
143 XtMapWidget( shell
);
144 XtMapWidget( newWidget
);
145 XRaiseWindow( pXtAppDisplay
, XtWindow( shell
) );
146 XSync( pXtAppDisplay
, False
);
151 void* CreateNewShell( void** pShellReturn
, XLIB_Window aParentWindow
)
154 XtGetApplicationNameAndClass(pXtAppDisplay
, &n
, &c
);
157 XtVaAppCreateShell( "pane", c
,
158 topLevelShellWidgetClass
,
162 XtNoverrideRedirect
, True
,
164 *pShellReturn
= newShell
;
167 sprintf( pText
, "starting plugin %s ...", pAppArguments
[2] );
169 Widget newWidget
= createSubWidget( pText
, newShell
, aParentWindow
);
174 static oslModule
LoadModule( const char* pPath
)
176 ::rtl::OUString
sSystemPath( ::rtl::OUString::createFromAscii( pPath
) );
177 ::rtl::OUString sFileURL
;
178 osl_getFileURLFromSystemPath( sSystemPath
.pData
, &sFileURL
.pData
);
180 oslModule pLib
= osl_loadModule( sFileURL
.pData
, SAL_LOADMODULE_LAZY
);
183 medDebug( 1, "could not open %s: %s\n", pPath
, dlerror() );
188 // Unix specific implementation
189 static void CheckPlugin( const char* pPath
)
191 oslModule pLib
= LoadModule( pPath
);
193 char*(*pNP_GetMIMEDescription
)() = (char*(*)())
194 osl_getAsciiFunctionSymbol( pLib
, "NP_GetMIMEDescription" );
195 if( pNP_GetMIMEDescription
)
196 printf( "%s\n", pNP_GetMIMEDescription() );
198 medDebug( 1, "could not get symbol NP_GetMIMEDescription %s\n", dlerror() );
200 osl_unloadModule( pLib
);
203 #if OSL_DEBUG_LEVEL > 1 && defined LINUX
204 #include <execinfo.h>
209 static void signal_handler( int nSig
)
211 #if OSL_DEBUG_LEVEL > 1
212 fprintf( stderr
, "caught signal %d, exiting\n", nSig
);
215 int nStackLevels
= backtrace( pStack
, sizeof(pStack
)/sizeof(pStack
[0]) );
216 backtrace_symbols_fd( pStack
, nStackLevels
, STDERR_FILENO
);
221 // ensure that a read on the other side will wakeup
231 static gboolean
noClosure( gpointer
)
237 static gboolean
prepareXtEvent( GSource
*, gint
* )
239 int nMask
= XtAppPending( app_context
);
240 return (nMask
& XtIMAll
) != 0;
243 static gboolean
checkXtEvent( GSource
* )
245 int nMask
= XtAppPending( app_context
);
246 return (nMask
& XtIMAll
) != 0;
249 static gboolean
dispatchXtEvent( GSource
*, GSourceFunc
, gpointer
)
251 XtAppProcessEvent( app_context
, XtIMAll
);
255 static GSourceFuncs aXtEventFuncs
=
265 static gboolean
pollXtTimerCallback(gpointer
)
267 for(int i
= 0; i
< 5; i
++)
269 if( (XtAppPending(app_context
) & (XtIMAll
& ~XtIMXEvent
)) == 0 )
271 XtAppProcessEvent(app_context
, XtIMAll
& ~XtIMXEvent
);
276 static gboolean
prepareWakeupEvent( GSource
*, gint
* )
278 struct pollfd aPoll
= { wakeup_fd
[0], POLLIN
, 0 };
279 poll( &aPoll
, 1, 0 );
280 return (aPoll
.revents
& POLLIN
) != 0;
283 static gboolean
checkWakeupEvent( GSource
* pSource
)
286 return prepareWakeupEvent( pSource
, &nDum
);
289 static gboolean
dispatchWakeupEvent( GSource
*, GSourceFunc
, gpointer
)
295 while( (len
= read( wakeup_fd
[0], buf
, sizeof( buf
) ) ) > 0 )
297 if( ( nLast
== -1 || buf
[nLast
] != 'x' ) && pConnector
)
298 pConnector
->CallWorkHandler();
301 XtAppSetExitFlag( app_context
);
302 bPluginAppQuit
= true;
311 static GSourceFuncs aWakeupEventFuncs
= {
324 int main( int argc
, char **argv
)
326 struct sigaction aSigAction
;
327 aSigAction
.sa_handler
= signal_handler
;
328 sigemptyset( &aSigAction
.sa_mask
);
329 aSigAction
.sa_flags
= SA_NOCLDSTOP
;
330 sigaction( SIGSEGV
, &aSigAction
, NULL
);
331 sigaction( SIGBUS
, &aSigAction
, NULL
);
332 sigaction( SIGABRT
, &aSigAction
, NULL
);
333 sigaction( SIGTERM
, &aSigAction
, NULL
);
334 sigaction( SIGILL
, &aSigAction
, NULL
);
336 int nArg
= (argc
< 3) ? 1 : 2;
337 char* pBaseName
= argv
[nArg
] + strlen(argv
[nArg
]);
338 while( pBaseName
> argv
[nArg
] && pBaseName
[-1] != '/' )
340 LoadAdditionalLibs( pBaseName
);
344 CheckPlugin(argv
[1]);
347 nAppArguments
= argc
;
348 pAppArguments
= argv
;
350 XSetErrorHandler( plugin_x_error_handler
);
352 if( pipe( wakeup_fd
) )
354 medDebug( 1, "could not pipe()\n" );
357 // initialize 'wakeup' pipe.
360 // set close-on-exec descriptor flag.
361 if ((flags
= fcntl (wakeup_fd
[0], F_GETFD
)) != -1)
364 fcntl (wakeup_fd
[0], F_SETFD
, flags
);
366 if ((flags
= fcntl (wakeup_fd
[1], F_GETFD
)) != -1)
369 fcntl (wakeup_fd
[1], F_SETFD
, flags
);
372 // set non-blocking I/O flag.
373 if ((flags
= fcntl (wakeup_fd
[0], F_GETFL
)) != -1)
376 fcntl (wakeup_fd
[0], F_SETFL
, flags
);
378 if ((flags
= fcntl (wakeup_fd
[1], F_GETFL
)) != -1)
381 fcntl (wakeup_fd
[1], F_SETFL
, flags
);
384 pPluginLib
= LoadModule( argv
[2] );
389 int nSocket
= atol( argv
[1] );
393 gtk_init(&argc
, &argv
);
396 pConnector
= new PluginConnector( nSocket
);
397 pConnector
->SetConnectionLostHdl( Link( NULL
, GlobalConnectionLostHdl
) );
399 XtSetLanguageProc( NULL
, NULL
, NULL
);
401 XtToolkitInitialize();
402 app_context
= XtCreateApplicationContext();
403 pXtAppDisplay
= XtOpenDisplay( app_context
, NULL
, "SOPlugin", "SOPlugin", NULL
, 0, &argc
, argv
);
407 // integrate Xt events into GTK event loop
408 GPollFD aXtPollDesc
, aWakeupPollDesc
;
410 GSource
* pXTSource
= g_source_new( &aXtEventFuncs
, sizeof(GSource
) );
413 medDebug( 1, "could not get Xt GSource" );
417 g_source_set_priority( pXTSource
, GDK_PRIORITY_EVENTS
);
418 g_source_set_can_recurse( pXTSource
, TRUE
);
419 g_source_attach( pXTSource
, NULL
);
420 aXtPollDesc
.fd
= ConnectionNumber( pXtAppDisplay
);
421 aXtPollDesc
.events
= G_IO_IN
;
422 aXtPollDesc
.revents
= 0;
423 g_source_add_poll( pXTSource
, &aXtPollDesc
);
425 gint xt_polling_timer_id
= g_timeout_add( 25, pollXtTimerCallback
, NULL
);
426 // Initialize wakeup events listener
427 GSource
*pWakeupSource
= g_source_new( &aWakeupEventFuncs
, sizeof(GSource
) );
428 if ( pWakeupSource
== NULL
)
430 medDebug( 1, "could not get wakeup source" );
433 g_source_set_priority( pWakeupSource
, GDK_PRIORITY_EVENTS
);
434 g_source_attach( pWakeupSource
, NULL
);
435 aWakeupPollDesc
.fd
= wakeup_fd
[0];
436 aWakeupPollDesc
.events
= G_IO_IN
;
437 aWakeupPollDesc
.revents
= 0;
438 g_source_add_poll( pWakeupSource
, &aWakeupPollDesc
);
440 pAppDisplay
= gdk_x11_display_get_xdisplay( gdk_display_get_default() );
442 pAppDisplay
= pXtAppDisplay
;
443 XtAppAddInput( app_context
,
445 (XtPointer
)XtInputReadMask
,
446 ThreadEventHandler
, NULL
);
449 // send that we are ready to go
450 MediatorMessage
* pMessage
=
451 pConnector
->Transact( "init req", 8,
455 #if OSL_DEBUG_LEVEL > 3
461 char* pArgs
[] = { "xterm", "-sl", "2000", "-sb", "-e", "gdb", "pluginapp.bin", pidbuf
, NULL
};
462 sprintf( pidbuf
, "%d", nPID
);
463 execvp( pArgs
[0], pArgs
);
473 // for some reason XtAppSetExitFlag won't quit the application
474 // in ThreadEventHandler most of times; Xt will hang in select
475 // (hat is in XtAppNextEvent). Have our own mainloop instead
480 g_main_context_iteration( NULL
, TRUE
);
482 XtAppProcessEvent( app_context
, XtIMAll
);
484 } while( ! XtAppGetExitFlag( app_context
) && ! bPluginAppQuit
);
486 medDebug( 1, "left plugin app main loop\n" );
488 g_source_remove(xt_polling_timer_id
);
491 medDebug( 1, "NP_Shutdown done\n" );
492 osl_unloadModule( pPluginLib
);
493 medDebug( 1, "plugin close\n" );
495 close( wakeup_fd
[0] );
496 close( wakeup_fd
[1] );
503 void __pure_virtual()
506 void* __builtin_new( int nBytes
)
507 { return malloc(nBytes
); }
508 void* __builtin_vec_new( int nBytes
)
509 { return malloc(nBytes
); }
510 void __builtin_delete( char* pMem
)
512 void __builtin_vec_delete( char* pMem
)