diff options
Diffstat (limited to 'nsplugins/viewer/viewer.cpp')
-rw-r--r-- | nsplugins/viewer/viewer.cpp | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/nsplugins/viewer/viewer.cpp b/nsplugins/viewer/viewer.cpp new file mode 100644 index 000000000..3e23a944a --- /dev/null +++ b/nsplugins/viewer/viewer.cpp @@ -0,0 +1,312 @@ +/* + + This is a standalone application that executes Netscape plugins. + + + Copyright (c) 2000 Matthias Hoelzer-Kluepfel <mhk@caldera.de> + Stefan Schimanski <1Stein@gmx.de> + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include <config.h> + +#include "nsplugin.h" + +#include <dcopclient.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <qptrlist.h> +#include <qsocketnotifier.h> +#include <stdlib.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <unistd.h> + +#ifdef Bool +#undef Bool +#endif +#include <kconfig.h> + +#if QT_VERSION < 0x030100 +#include "kxt.h" +#include <X11/Intrinsic.h> +#include <X11/Shell.h> +#else +#include "qxteventloop.h" +#include "glibevents.h" +#endif + +/** + * Use RLIMIT_DATA on systems that don't define RLIMIT_AS, + * such as FreeBSD 4. + */ + +#ifndef RLIMIT_AS +#define RLIMIT_AS RLIMIT_DATA +#endif + +/** + * The error handler catches all X errors, writes the error + * message to the debug log and continues. + * + * This is done to prevent abortion of the plugin viewer + * in case the plugin does some invalid X operation. + * + */ +static int x_errhandler(Display *dpy, XErrorEvent *error) +{ + char errstr[256]; + XGetErrorText(dpy, error->error_code, errstr, 256); + kdDebug(1430) << "Detected X Error: " << errstr << endl; + return 1; +} + +/* + * As the plugin viewer needs to be a motif application, I give in to + * the "old style" and keep lot's of global vars. :-) + */ + +static QCString g_dcopId; + +/** + * parseCommandLine - get command line parameters + * + */ +void parseCommandLine(int argc, char *argv[]) +{ + for (int i=0; i<argc; i++) + { + if (!strcmp(argv[i], "-dcopid") && (i+1 < argc)) + { + g_dcopId = argv[i+1]; + i++; + } + } +} + +#if QT_VERSION < 0x030100 + +static XtAppContext g_appcon; +static bool g_quit = false; + +void quitXt() +{ + g_quit = true; +} + + +/** + * socket notifier handling + * + */ + +struct SocketNot +{ + int fd; + QObject *obj; + XtInputId id; +}; + +QPtrList<SocketNot> _notifiers[3]; + +/** + * socketCallback - send event to the socket notifier + * + */ +void socketCallback(void *client_data, int* /*source*/, XtInputId* /*id*/) +{ + kdDebug(1430) << "-> socketCallback( client_data=" << client_data << " )" << endl; + + QEvent event( QEvent::SockAct ); + SocketNot *socknot = (SocketNot *)client_data; + kdDebug(1430) << "obj=" << (void*)socknot->obj << endl; + QApplication::sendEvent( socknot->obj, &event ); + + kdDebug(1430) << "<- socketCallback" << endl; +} + + +/** + * qt_set_socket_handler - redefined internal qt function to register sockets + * The linker looks in the main binary first and finds this implementation before + * the original one in Qt. I hope this works with every dynamic library loader on any OS. + * + */ +extern bool qt_set_socket_handler( int, int, QObject *, bool ); +bool qt_set_socket_handler( int sockfd, int type, QObject *obj, bool enable ) +{ + if ( sockfd < 0 || type < 0 || type > 2 || obj == 0 ) { +#if defined(CHECK_RANGE) + qWarning( "QSocketNotifier: Internal error" ); +#endif + return FALSE; + } + + XtPointer inpMask = 0; + + switch (type) { + case QSocketNotifier::Read: inpMask = (XtPointer)XtInputReadMask; break; + case QSocketNotifier::Write: inpMask = (XtPointer)XtInputWriteMask; break; + case QSocketNotifier::Exception: inpMask = (XtPointer)XtInputExceptMask; break; + default: return FALSE; + } + + if (enable) { + SocketNot *sn = new SocketNot; + sn->obj = obj; + sn->fd = sockfd; + + if( _notifiers[type].isEmpty() ) { + _notifiers[type].insert( 0, sn ); + } else { + SocketNot *p = _notifiers[type].first(); + while ( p && p->fd > sockfd ) + p = _notifiers[type].next(); + +#if defined(CHECK_STATE) + if ( p && p->fd==sockfd ) { + static const char *t[] = { "read", "write", "exception" }; + qWarning( "QSocketNotifier: Multiple socket notifiers for " + "same socket %d and type %s", sockfd, t[type] ); + } +#endif + if ( p ) + _notifiers[type].insert( _notifiers[type].at(), sn ); + else + _notifiers[type].append( sn ); + } + + sn->id = XtAppAddInput( g_appcon, sockfd, inpMask, socketCallback, sn ); + + } else { + + SocketNot *sn = _notifiers[type].first(); + while ( sn && !(sn->obj == obj && sn->fd == sockfd) ) + sn = _notifiers[type].next(); + if ( !sn ) // not found + return FALSE; + + XtRemoveInput( sn->id ); + _notifiers[type].remove(); + } + + return TRUE; +} +#endif + + +int main(int argc, char** argv) +{ + // nspluginviewer is a helper app, it shouldn't do session management at all + setenv( "SESSION_MANAGER", "", 1 ); + + // trap X errors + kdDebug(1430) << "1 - XSetErrorHandler" << endl; + XSetErrorHandler(x_errhandler); + setvbuf( stderr, NULL, _IONBF, 0 ); + + kdDebug(1430) << "2 - parseCommandLine" << endl; + parseCommandLine(argc, argv); + +#if QT_VERSION < 0x030100 + // Create application + kdDebug(1430) << "3 - XtToolkitInitialize" << endl; + XtToolkitInitialize(); + g_appcon = XtCreateApplicationContext(); + Display *dpy = XtOpenDisplay(g_appcon, NULL, "nspluginviewer", "nspluginviewer", + 0, 0, &argc, argv); + + _notifiers[0].setAutoDelete( TRUE ); + _notifiers[1].setAutoDelete( TRUE ); + _notifiers[2].setAutoDelete( TRUE ); + + kdDebug(1430) << "4 - KXtApplication app" << endl; + KLocale::setMainCatalogue("nsplugin"); + KXtApplication app(dpy, argc, argv, "nspluginviewer"); +#else + kdDebug(1430) << "3 - create QXtEventLoop" << endl; + QXtEventLoop integrator( "nspluginviewer" ); + parseCommandLine(argc, argv); + KLocale::setMainCatalogue("nsplugin"); + + kdDebug(1430) << "4 - create KApplication" << endl; + KApplication app( argc, argv, "nspluginviewer" ); + GlibEvents glibevents; +#endif + + { + KConfig cfg("kcmnspluginrc", true); + cfg.setGroup("Misc"); + int v = KCLAMP(cfg.readNumEntry("Nice Level", 0), 0, 19); + if (v > 0) { + nice(v); + } + v = cfg.readNumEntry("Max Memory", 0); + if (v > 0) { + rlimit rl; + memset(&rl, 0, sizeof(rl)); + if (0 == getrlimit(RLIMIT_AS, &rl)) { + rl.rlim_cur = kMin(v, int(rl.rlim_max)); + setrlimit(RLIMIT_AS, &rl); + } + } + } + + // initialize the dcop client + kdDebug(1430) << "5 - app.dcopClient" << endl; + DCOPClient *dcop = app.dcopClient(); + if (!dcop->attach()) + { + KMessageBox::error(NULL, + i18n("There was an error connecting to the Desktop " + "communications server. Please make sure that " + "the 'dcopserver' process has been started, and " + "then try again."), + i18n("Error Connecting to DCOP Server")); + exit(1); + } + + kdDebug(1430) << "6 - dcop->registerAs" << endl; + if (g_dcopId) + g_dcopId = dcop->registerAs( g_dcopId, false ); + else + g_dcopId = dcop->registerAs("nspluginviewer"); + + dcop->setNotifications(true); + + // create dcop interface + kdDebug(1430) << "7 - new NSPluginViewer" << endl; + NSPluginViewer *viewer = new NSPluginViewer( "viewer", 0 ); + + // start main loop +#if QT_VERSION < 0x030100 + kdDebug(1430) << "8 - XtAppProcessEvent" << endl; + while (!g_quit) + XtAppProcessEvent( g_appcon, XtIMAll); +#else + kdDebug(1430) << "8 - app.exec()" << endl; + app.exec(); +#endif + + // delete viewer + delete viewer; +} |