summaryrefslogtreecommitdiffstats
path: root/kstart
diff options
context:
space:
mode:
Diffstat (limited to 'kstart')
-rw-r--r--kstart/LICENSE.readme124
-rw-r--r--kstart/Makefile.am21
-rw-r--r--kstart/kstart.cpp404
-rw-r--r--kstart/kstart.h36
-rw-r--r--kstart/version.h1
5 files changed, 586 insertions, 0 deletions
diff --git a/kstart/LICENSE.readme b/kstart/LICENSE.readme
new file mode 100644
index 000000000..1cc95fd53
--- /dev/null
+++ b/kstart/LICENSE.readme
@@ -0,0 +1,124 @@
+kstart --- the KDE legacy application starter
+
+Copyright (C) 1997, 1998 by Matthias Ettrich <ettrich@kde.org>
+
+ The "Artistic License"
+
+ Preamble
+
+ The intent of this document is to state the conditions under which a
+ Package may be copied, such that the Copyright Holder maintains some
+ semblance of artistic control over the development of the package,
+ while giving the users of the package the right to use and
+ distribute the Package in a more-or-less customary fashion, plus the
+ right to make reasonable modifications.
+
+ Definitions:
+
+ * "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ * "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes of
+ the Copyright Holder.
+
+ * "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ * "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ * "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people
+ involved, and so on. (You will not be required to justify it to
+ the Copyright Holder, but only to the computing community at
+ large as a market that must bear the fee.)
+
+ * "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+ 1. You may make and give away verbatim copies of the source form of
+ the Standard Version of this Package without restriction, provided
+ that you duplicate all of the original copyright notices and
+ associated disclaimers.
+
+ 2. You may apply bug fixes, portability fixes and other
+ modifications derived from the Public Domain or from the Copyright
+ Holder. A Package modified in such a way shall still be considered
+ the Standard Version.
+
+ 3. You may otherwise modify your copy of this Package in any way,
+ provided that you insert a prominent notice in each changed file
+ stating how and when you changed that file, and provided that you do
+ at least ONE of the following:
+
+ a) place your modifications in the Public Domain or
+ otherwise make them Freely Available, such as by posting
+ said modifications to Usenet or an equivalent medium, or
+ placing the modifications on a major archive site such as
+ ftp.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation
+ or organization.
+
+ c) rename any non-standard executables so the names do not
+ conflict with standard executables, which must also be
+ provided, and provide a separate manual page for each
+ non-standard executable that clearly documents how it
+ differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright
+ Holder.
+
+ 4. You may distribute the programs of this Package in object code or
+ executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and
+ library files, together with instructions (in the manual
+ page or equivalent) on where to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable
+ source of the Package with your modifications.
+
+ c) accompany any non-standard executables with their
+ corresponding Standard Version executables, giving the
+ non-standard executables non-standard names, and clearly
+ documenting the differences in manual pages (or
+ equivalent), together with instructions on where to get
+ the Standard Version.
+
+ d) make other distribution arrangements with the Copyright
+ Holder.
+
+ 5. You may charge a reasonable copying fee for any distribution of
+ this Package. You may charge any fee you choose for support of this
+ Package. You may not charge a fee for this Package itself. However,
+ you may distribute this Package in aggregate with other (possibly
+ commercial) programs as part of a larger (possibly commercial)
+ software distribution provided that you do not advertise this
+ Package as a product of your own.
+
+ 6. The scripts and library files supplied as input to or produced as
+ output from the programs of this Package do not automatically fall
+ under the copyright of this Package, but belong to whomever
+ generated them, and may be sold commercially, and may be aggregated
+ with this Package.
+
+ 7. C or perl subroutines supplied by you and linked into this
+ Package shall not be considered part of this Package.
+
+ 8. The name of the Copyright Holder may not be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+ 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
+
+
diff --git a/kstart/Makefile.am b/kstart/Makefile.am
new file mode 100644
index 000000000..01aeca492
--- /dev/null
+++ b/kstart/Makefile.am
@@ -0,0 +1,21 @@
+####### Fiddle here
+
+AM_CPPFLAGS = -DQT_NO_CAST_ASCII -DQT_CLEAN_NAMESPACE -DQT_NO_COMPAT
+
+INCLUDES = $(all_includes)
+
+####### Files
+
+bin_PROGRAMS = kstart
+kstart_SOURCES = kstart.cpp
+kstart_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kstart_LDADD = $(LIB_KDECORE)
+METASOURCES = kstart.moc
+
+noinst_HEADERS = kstart.h version.h
+
+messages:
+ $(XGETTEXT) $(kstart_SOURCES) -o $(podir)/kstart.pot
+
+EXTRA_DIST = CHANGES LICENSE.readme
+
diff --git a/kstart/kstart.cpp b/kstart/kstart.cpp
new file mode 100644
index 000000000..83105c86d
--- /dev/null
+++ b/kstart/kstart.cpp
@@ -0,0 +1,404 @@
+/*
+ * kstart.C. Part of the KDE project.
+ *
+ * Copyright (C) 1997-2000 Matthias Ettrich <ettrich@kde.org>
+ *
+ * First port to NETWM by David Faure <faure@kde.org>
+ * Send to system tray by Richard Moore <rich@kde.org>
+ */
+
+#include "kstart.moc"
+#include "version.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include <qregexp.h>
+#include <qtimer.h>
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kwin.h>
+#include <kwinmodule.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kstartupinfo.h>
+#include <kxmessages.h>
+
+#include <netwm.h>
+
+
+// some globals
+
+static KProcess proc;
+static QCString windowtitle = 0;
+static QCString windowclass = 0;
+static int desktop = 0;
+static bool activate = false;
+static bool iconify = false;
+static bool toSysTray = false;
+static bool fullscreen = false;
+static unsigned long state = 0;
+static unsigned long mask = 0;
+static NET::WindowType windowtype = NET::Unknown;
+static KWinModule* kwinmodule;
+
+KStart::KStart()
+ :QObject()
+{
+ NETRootInfo i( qt_xdisplay(), NET::Supported );
+ bool useRule = !toSysTray && i.isSupported( NET::WM2KDETemporaryRules );
+
+ if( useRule )
+ sendRule();
+ else {
+ // connect to window add to get the NEW windows
+ connect(kwinmodule, SIGNAL(windowAdded(WId)), SLOT(windowAdded(WId)));
+ if (windowtitle)
+ kwinmodule->doNotManage( windowtitle );
+ }
+ // propagate the app startup notification info to the started app
+ KStartupInfoId id;
+ id.initId( kapp->startupId());
+ id.setupStartupEnv();
+
+ //finally execute the comand
+ if( proc.start(KProcess::DontCare) ) {
+ KStartupInfoData data;
+ data.addPid( proc.pid() );
+ QCString bin = proc.args().first();
+ data.setName( bin );
+ data.setBin( bin.mid( bin.findRev( '/' ) + 1 ));
+ KStartupInfo::sendChange( id, data );
+ }
+ else
+ KStartupInfo::sendFinish( id ); // failed to start
+
+ QTimer::singleShot( useRule ? 0 : 120 * 1000, kapp, SLOT( quit()));
+}
+
+void KStart::sendRule() {
+ KXMessages msg;
+ QCString message;
+ if( windowtitle )
+ message += "title=" + windowtitle + "\ntitlematch=3\n"; // 3 = regexp match
+ if( windowclass )
+ message += "wmclass=" + windowclass + "\nwmclassmatch=1\n" // 1 = exact match
+ + "wmclasscomplete="
+ // if windowclass contains a space (i.e. 2 words, use whole WM_CLASS)
+ + ( windowclass.contains( ' ' ) ? "true" : "false" ) + "\n";
+ if( windowtitle || windowclass ) {
+ // always ignore these window types
+ message += "types=" + QCString().setNum( -1U &
+ ~( NET::TopMenuMask | NET::ToolbarMask | NET::DesktopMask | NET::SplashMask | NET::MenuMask )) + "\n";
+ } else {
+ // accept only "normal" windows
+ message += "types=" + QCString().setNum( NET::NormalMask | NET::DialogMask ) + "\n";
+ }
+ if ( ( desktop > 0 && desktop <= kwinmodule->numberOfDesktops() )
+ || desktop == NETWinInfo::OnAllDesktops ) {
+ message += "desktop=" + QCString().setNum( desktop ) + "\ndesktoprule=3\n";
+ }
+ if (activate)
+ message += "fsplevel=0\nfsplevelrule=2\n";
+ if (iconify)
+ message += "minimize=true\nminimizerule=3\n";
+ if ( windowtype != NET::Unknown ) {
+ message += "type=" + QCString().setNum( windowtype ) + "\ntyperule=2";
+ }
+ if ( state ) {
+ if( state & NET::KeepAbove )
+ message += "above=true\naboverule=3\n";
+ if( state & NET::KeepBelow )
+ message += "below=true\nbelowrule=3\n";
+ if( state & NET::SkipTaskbar )
+ message += "skiptaskbar=true\nskiptaskbarrule=3\n";
+ if( state & NET::SkipPager )
+ message += "skippager=true\nskippagerrule=3\n";
+ if( state & NET::MaxVert )
+ message += "maximizevert=true\nmaximizevertrule=3\n";
+ if( state & NET::MaxHoriz )
+ message += "maximizehoriz=true\nmaximizehorizrule=3\n";
+ if( state & NET::FullScreen )
+ message += "fullscreen=true\nfullscreenrule=3\n";
+ }
+
+ msg.broadcastMessage( "_KDE_NET_WM_TEMPORARY_RULES", message, -1, false );
+ kapp->flushX();
+}
+
+const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
+ | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
+ | NET::UtilityMask | NET::SplashMask;
+
+void KStart::windowAdded(WId w){
+
+ KWin::WindowInfo info = KWin::windowInfo( w );
+
+ // always ignore these window types
+ if( info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) == NET::TopMenu
+ || info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) == NET::Toolbar
+ || info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) == NET::Desktop )
+ return;
+
+ if ( windowtitle ) {
+ QString title = info.name().lower();
+ QRegExp r( windowtitle.lower());
+ if (r.match(title) == -1)
+ return; // no match
+ }
+ if ( windowclass ) {
+ XClassHint hint;
+ if( !XGetClassHint( qt_xdisplay(), w, &hint ))
+ return;
+ QCString cls = windowclass.contains( ' ' )
+ ? QCString( hint.res_name ) + ' ' + hint.res_class : QCString( hint.res_class );
+ cls = cls.lower();
+ XFree( hint.res_name );
+ XFree( hint.res_class );
+ if( cls != windowclass )
+ return;
+ }
+ if( !windowtitle && !windowclass ) {
+ // accept only "normal" windows
+ if( info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) != NET::Unknown
+ && info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) != NET::Normal
+ && info.windowType( SUPPORTED_WINDOW_TYPES_MASK ) != NET::Dialog )
+ return;
+ }
+ applyStyle( w );
+ QApplication::exit();
+}
+
+
+extern Atom qt_wm_state; // defined in qapplication_x11.cpp
+static bool wstate_withdrawn( WId winid )
+{
+ Atom type;
+ int format;
+ unsigned long length, after;
+ unsigned char *data;
+ int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
+ FALSE, AnyPropertyType, &type, &format,
+ &length, &after, &data );
+ bool withdrawn = TRUE;
+ if ( r == Success && data && format == 32 ) {
+ Q_UINT32 *wstate = (Q_UINT32*)data;
+ withdrawn = (*wstate == WithdrawnState );
+ XFree( (char *)data );
+ }
+ return withdrawn;
+}
+
+
+void KStart::applyStyle(WId w ) {
+
+ if ( toSysTray || state || iconify || windowtype != NET::Unknown || desktop >= 1 ) {
+
+ XWithdrawWindow(qt_xdisplay(), w, qt_xscreen());
+ QApplication::flushX();
+
+ while ( !wstate_withdrawn(w) )
+ ;
+ }
+
+ NETWinInfo info( qt_xdisplay(), w, qt_xrootwin(), NET::WMState );
+
+ if ( ( desktop > 0 && desktop <= kwinmodule->numberOfDesktops() )
+ || desktop == NETWinInfo::OnAllDesktops )
+ info.setDesktop( desktop );
+
+ if (iconify) {
+ XWMHints * hints = XGetWMHints(qt_xdisplay(), w );
+ if (hints ) {
+ hints->flags |= StateHint;
+ hints->initial_state = IconicState;
+ XSetWMHints( qt_xdisplay(), w, hints );
+ XFree(hints);
+ }
+ }
+
+ if ( windowtype != NET::Unknown ) {
+ info.setWindowType( windowtype );
+ }
+
+ if ( state )
+ info.setState( state, mask );
+
+ if ( toSysTray ) {
+ QApplication::beep();
+ KWin::setSystemTrayWindowFor( w, qt_xrootwin() );
+ }
+
+ if ( fullscreen ) {
+ QRect r = QApplication::desktop()->geometry();
+ XMoveResizeWindow( qt_xdisplay(), w, r.x(), r.y(), r.width(), r.height() );
+ }
+
+
+ XSync(qt_xdisplay(), False);
+
+ XMapWindow(qt_xdisplay(), w );
+ XSync(qt_xdisplay(), False);
+
+ if (activate)
+ KWin::forceActiveWindow( w );
+
+ QApplication::flushX();
+}
+
+// David, 05/03/2000
+static KCmdLineOptions options[] =
+{
+ { "!+command", I18N_NOOP("Command to execute"), 0 },
+ // "!" means: all options after command are treated as arguments to the command
+ { "window <regexp>", I18N_NOOP("A regular expression matching the window title"), 0 },
+ { "windowclass <class>", I18N_NOOP("A string matching the window class (WM_CLASS property)\n"
+ "The window class can be found out by running\n"
+ "'xprop | grep WM_CLASS' and clicking on a window\n"
+ "(use either both parts separated by a space or only the right part).\n"
+ "NOTE: If you specify neither window title nor window class,\n"
+ "then the very first window to appear will be taken;\n"
+ "omitting both options is NOT recommended."), 0 },
+ { "desktop <number>", I18N_NOOP("Desktop on which to make the window appear"), 0 },
+ { "currentdesktop", I18N_NOOP("Make the window appear on the desktop that was active\nwhen starting the application"), 0 },
+ { "alldesktops", I18N_NOOP("Make the window appear on all desktops"), 0 },
+ { "iconify", I18N_NOOP("Iconify the window"), 0 },
+ { "maximize", I18N_NOOP("Maximize the window"), 0 },
+ { "maximize-vertically", I18N_NOOP("Maximize the window vertically"), 0 },
+ { "maximize-horizontally", I18N_NOOP("Maximize the window horizontally"), 0 },
+ { "fullscreen", I18N_NOOP("Show window fullscreen"), 0 },
+ { "type <type>", I18N_NOOP("The window type: Normal, Desktop, Dock, Tool, \nMenu, Dialog, TopMenu or Override"), 0 },
+ { "activate", I18N_NOOP("Jump to the window even if it is started on a \n"
+ "different virtual desktop"), 0 },
+ { "ontop", 0, 0 },
+ { "keepabove", I18N_NOOP("Try to keep the window above other windows"), 0 },
+ { "onbottom", 0, 0 },
+ { "keepbelow", I18N_NOOP("Try to keep the window below other windows"), 0 },
+ { "skiptaskbar", I18N_NOOP("The window does not get an entry in the taskbar"), 0 },
+ { "skippager", I18N_NOOP("The window does not get an entry on the pager"), 0 },
+ { "tosystray", I18N_NOOP("The window is sent to the system tray in Kicker"), 0 },
+ KCmdLineLastOption
+};
+
+int main( int argc, char *argv[] )
+{
+ // David, 05/03/2000
+ KAboutData aboutData( "kstart", I18N_NOOP("KStart"), KSTART_VERSION,
+ I18N_NOOP(""
+ "Utility to launch applications with special window properties \n"
+ "such as iconified, maximized, a certain virtual desktop, a special decoration\n"
+ "and so on." ),
+ KAboutData::License_GPL,
+ "(C) 1997-2000 Matthias Ettrich (ettrich@kde.org)" );
+
+ aboutData.addAuthor( "Matthias Ettrich", 0, "ettrich@kde.org" );
+ aboutData.addAuthor( "David Faure", 0, "faure@kde.org" );
+ aboutData.addAuthor( "Richard J. Moore", 0, "rich@kde.org" );
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+
+ KApplication app;
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if ( args->count() == 0 )
+ KCmdLineArgs::usage(i18n("No command specified"));
+
+ for(int i=0; i < args->count(); i++)
+ proc << args->arg(i);
+
+ kwinmodule = new KWinModule;
+
+ desktop = args->getOption( "desktop" ).toInt();
+ if ( args->isSet ( "alldesktops") )
+ desktop = NETWinInfo::OnAllDesktops;
+ if ( args->isSet ( "currentdesktop") )
+ desktop = kwinmodule->currentDesktop();
+
+ windowtitle = args->getOption( "window" );
+ windowclass = args->getOption( "windowclass" );
+ if( windowclass )
+ windowclass = windowclass.lower();
+
+ if( windowtitle.isEmpty() && windowclass.isEmpty())
+ kdWarning() << "Omitting both --window and --windowclass arguments is not recommended" << endl;
+
+ QCString s = args->getOption( "type" );
+ if ( !s.isEmpty() ) {
+ s = s.lower();
+ if ( s == "desktop" )
+ windowtype = NET::Desktop;
+ else if ( s == "dock" )
+ windowtype = NET::Dock;
+ else if ( s == "tool" )
+ windowtype = NET::Tool;
+ else if ( s == "menu" )
+ windowtype = NET::Menu;
+ else if ( s == "dialog" )
+ windowtype = NET::Dialog;
+ else if ( s == "override" )
+ windowtype = NET::Override;
+ else if ( s == "topmenu" )
+ windowtype = NET::TopMenu;
+ else
+ windowtype = NET::Normal;
+ }
+
+ if ( args->isSet( "keepabove" ) ) {
+ state |= NET::KeepAbove;
+ mask |= NET::KeepAbove;
+ } else if ( args->isSet( "keepbelow" ) ) {
+ state |= NET::KeepBelow;
+ mask |= NET::KeepBelow;
+ }
+
+ if ( args->isSet( "skiptaskbar" ) ) {
+ state |= NET::SkipTaskbar;
+ mask |= NET::SkipTaskbar;
+ }
+
+ if ( args->isSet( "skippager" ) ) {
+ state |= NET::SkipPager;
+ mask |= NET::SkipPager;
+ }
+
+ activate = args->isSet("activate");
+
+ if ( args->isSet("maximize") ) {
+ state |= NET::Max;
+ mask |= NET::Max;
+ }
+ if ( args->isSet("maximize-vertically") ) {
+ state |= NET::MaxVert;
+ mask |= NET::MaxVert;
+ }
+ if ( args->isSet("maximize-horizontally") ) {
+ state |= NET::MaxHoriz;
+ mask |= NET::MaxHoriz;
+ }
+
+ iconify = args->isSet("iconify");
+ toSysTray = args->isSet("tosystray");
+ if ( args->isSet("fullscreen") ) {
+ NETRootInfo i( qt_xdisplay(), NET::Supported );
+ if( i.isSupported( NET::FullScreen )) {
+ state |= NET::FullScreen;
+ mask |= NET::FullScreen;
+ } else {
+ windowtype = NET::Override;
+ fullscreen = true;
+ }
+ }
+
+ fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, 1);
+ args->clear();
+
+ KStart start;
+
+ return app.exec();
+}
diff --git a/kstart/kstart.h b/kstart/kstart.h
new file mode 100644
index 000000000..0b5013387
--- /dev/null
+++ b/kstart/kstart.h
@@ -0,0 +1,36 @@
+/*
+ * kstart.h Part of the KDE project.
+ *
+ * Copyright (C) 1997-2000 Matthias Ettrich <ettrich@kde.org>
+ *
+ * Port to NETWM by David Faure <faure@kde.org>
+ *
+ */
+
+#ifndef KSTART_H
+#define KSTART_H
+
+
+#include <qobject.h>
+
+class KWinModule;
+
+class KStart: public QObject {
+ Q_OBJECT
+
+public:
+ KStart();
+ ~KStart(){};
+
+public slots:
+ void windowAdded(WId);
+
+private:
+
+ void applyStyle(WId );
+ void sendRule();
+
+};
+
+#endif
+
diff --git a/kstart/version.h b/kstart/version.h
new file mode 100644
index 000000000..3c866e946
--- /dev/null
+++ b/kstart/version.h
@@ -0,0 +1 @@
+#define KSTART_VERSION "kstart version 1.92"