summaryrefslogtreecommitdiffstats
path: root/tdm/kfrontend/kgapp.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2012-01-22 01:02:36 -0600
committerTimothy Pearson <[email protected]>2012-01-22 01:02:36 -0600
commitb81e43465b14836b17e4fe2dea91c78a2bdd29b3 (patch)
tree7815d61ce59a6ccb6e655ed44f5fea786f520985 /tdm/kfrontend/kgapp.cpp
parent7021f40c13f949b7cb5ded32d0241d648a43bf6c (diff)
downloadtdebase-b81e43465b14836b17e4fe2dea91c78a2bdd29b3.tar.gz
tdebase-b81e43465b14836b17e4fe2dea91c78a2bdd29b3.zip
Part 2 of prior commit
Diffstat (limited to 'tdm/kfrontend/kgapp.cpp')
-rw-r--r--tdm/kfrontend/kgapp.cpp469
1 files changed, 469 insertions, 0 deletions
diff --git a/tdm/kfrontend/kgapp.cpp b/tdm/kfrontend/kgapp.cpp
new file mode 100644
index 000000000..5ad52dda6
--- /dev/null
+++ b/tdm/kfrontend/kgapp.cpp
@@ -0,0 +1,469 @@
+/*
+
+Greeter module for xdm
+
+Copyright (C) 1997, 1998 Steffen Hansen <[email protected]>
+Copyright (C) 2000-2003 Oswald Buddenhagen <[email protected]>
+
+
+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 "tdm_greet.h"
+#include "tdmshutdown.h"
+#include "tdmconfig.h"
+#include "kgapp.h"
+#include "kgreeter.h"
+#ifdef XDMCP
+# include "kchooser.h"
+#endif
+#include "sakdlg.h"
+
+#include <kprocess.h>
+#include <kcmdlineargs.h>
+#include <kcrash.h>
+#include <kstandarddirs.h>
+#include <ksimpleconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#ifdef WITH_XRANDR
+#include <libkrandr/libkrandr.h>
+#endif
+
+#include <tqtimer.h>
+#include <tqstring.h>
+#include <tqcursor.h>
+#include <tqpalette.h>
+
+#include <stdlib.h> // free(), exit()
+#include <unistd.h> // alarm()
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+
+#ifdef HAVE_XCOMPOSITE
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/Xcomposite.h>
+#endif
+
+#include <pwd.h>
+
+bool argb_visual_available = false;
+bool has_twin = false;
+bool is_themed = false;
+bool trinity_desktop_lock_use_sak = TRUE;
+
+static int
+ignoreXError( Display *dpy ATTR_UNUSED, XErrorEvent *event ATTR_UNUSED )
+{
+ return 0;
+}
+
+extern "C" {
+
+static void
+sigAlarm( int )
+{
+ exit( EX_RESERVER_DPY );
+}
+
+}
+
+GreeterApp::GreeterApp()
+{
+ pingInterval = _isLocal ? 0 : _pingInterval;
+ if (pingInterval) {
+ struct sigaction sa;
+ sigemptyset( &sa.sa_mask );
+ sa.sa_flags = 0;
+ sa.sa_handler = sigAlarm;
+ sigaction( SIGALRM, &sa, 0 );
+ alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
+ startTimer( pingInterval * 60000 );
+ }
+}
+
+GreeterApp::GreeterApp(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap) : KApplication(dpy, visual, colormap)
+{
+ pingInterval = _isLocal ? 0 : _pingInterval;
+ if (pingInterval) {
+ struct sigaction sa;
+ sigemptyset( &sa.sa_mask );
+ sa.sa_flags = 0;
+ sa.sa_handler = sigAlarm;
+ sigaction( SIGALRM, &sa, 0 );
+ alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
+ startTimer( pingInterval * 60000 );
+ }
+}
+
+void
+GreeterApp::timerEvent( TQTimerEvent * )
+{
+ alarm( 0 );
+ if (!PingServer( qt_xdisplay() ))
+ ::exit( EX_RESERVER_DPY );
+ alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
+}
+
+bool
+GreeterApp::x11EventFilter( XEvent * ev )
+{
+ KeySym sym;
+
+ switch (ev->type) {
+ case FocusIn:
+ case FocusOut:
+ // Hack to tell dialogs to take focus when the keyboard is grabbed
+ ev->xfocus.mode = NotifyNormal;
+ break;
+ case KeyPress:
+ sym = XLookupKeysym( &ev->xkey, 0 );
+ if (sym != XK_Return && !IsModifierKey( sym ))
+ emit activity();
+ break;
+ case ButtonPress:
+ emit activity();
+ /* fall through */
+ case ButtonRelease:
+ // Hack to let the RMB work as LMB
+ if (ev->xbutton.button == 3)
+ ev->xbutton.button = 1;
+ /* fall through */
+ case MotionNotify:
+ if (ev->xbutton.state & Button3Mask)
+ ev->xbutton.state = (ev->xbutton.state & ~Button3Mask) | Button1Mask;
+ break;
+ }
+ return false;
+}
+
+extern bool kde_have_kipc;
+
+extern "C" {
+
+static int
+xIOErr( Display * )
+{
+ exit( EX_RESERVER_DPY );
+}
+
+//KSimpleConfig *iccconfig;
+
+void
+checkSAK(GreeterApp* app)
+{
+ app->restoreOverrideCursor();
+ SAKDlg sak(0);
+ sak.exec();
+ app->setOverrideCursor( Qt::WaitCursor );
+}
+
+void
+kg_main( const char *argv0 )
+{
+ static char *argv[] = { (char *)"tdmgreet", 0 };
+ KCmdLineArgs::init( 1, argv, *argv, 0, 0, 0, true );
+
+ kdDebug() << timestamp() << "start" << endl;
+ kde_have_kipc = false;
+ KApplication::disableAutoDcopRegistration();
+ KCrash::setSafer( true );
+
+ KProcess *tsak = 0;
+ KProcess *proc = 0;
+ KProcess *comp = 0;
+ KProcess *twin = 0;
+
+ trinity_desktop_lock_use_sak = _useSAK;
+ if (trinity_desktop_lock_use_sak) {
+ tsak = new KProcess;
+ *tsak << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + "tsak";
+ tsak->start(KProcess::Block);
+ }
+ if (tsak) {
+ tsak->closeStdin();
+ tsak->detach();
+ delete tsak;
+ }
+
+#ifdef HAVE_XCOMPOSITE
+ // Begin ARGB initialization
+ XSetErrorHandler( ignoreXError );
+ argb_visual_available = false;
+ char *display = 0;
+
+ Display *dpyi = XOpenDisplay( display );
+ if ( !dpyi ) {
+ kdError() << "cannot connect to X server " << display << endl;
+ exit( 1 );
+ }
+
+ int screen = DefaultScreen( dpyi );
+ Colormap colormap = 0;
+ Visual *visual = 0;
+ int event_base, error_base;
+
+ if ( XRenderQueryExtension( dpyi, &event_base, &error_base ) ) {
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = screen;
+ templ.depth = 32;
+ templ.c_class = TrueColor;
+ XVisualInfo *xvi = XGetVisualInfo( dpyi, VisualScreenMask | VisualDepthMask
+ | VisualClassMask, &templ, &nvi );
+
+ for ( int i = 0; i < nvi; i++ ) {
+ XRenderPictFormat *format = XRenderFindVisualFormat( dpyi, xvi[i].visual );
+ if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
+ visual = xvi[i].visual;
+ colormap = XCreateColormap( dpyi, RootWindow( dpyi, screen ), visual, AllocNone );
+ kdDebug() << "found visual with alpha support" << endl;
+ argb_visual_available = true;
+ break;
+ }
+ }
+ }
+ XSetErrorHandler( (XErrorHandler)0 );
+
+ GreeterApp *app;
+ if ( (argb_visual_available == true) && (!_compositor.isEmpty()) ) {
+ app = new GreeterApp(dpyi, Qt::HANDLE( visual ), Qt::HANDLE( colormap ));
+ }
+ else {
+ app = new GreeterApp();
+ }
+ // End ARGB initialization
+#else
+ GreeterApp *app = new GreeterApp();
+#endif
+
+ XSetIOErrorHandler( xIOErr );
+ TQString login_user;
+
+ Display *dpy = qt_xdisplay();
+
+ if (!_GUIStyle.isEmpty())
+ app->setStyle( _GUIStyle );
+
+ // Load up systemwide display settings
+#ifdef WITH_XRANDR
+ KRandrSimpleAPI *randrsimple = new KRandrSimpleAPI();
+ TQPoint primaryScreenPosition = randrsimple->applySystemwideDisplayConfiguration("", KDE_CONFDIR);
+ delete randrsimple;
+#endif
+
+ // Load up the systemwide ICC profile
+ TQString iccConfigFile = TQString(KDE_CONFDIR);
+ iccConfigFile += "/kicc/kiccconfigrc";
+ KSimpleConfig iccconfig(iccConfigFile, true);
+ if (iccconfig.readBoolEntry("EnableICC", false) == true) {
+ TQString iccCommand = TQString("/usr/bin/xcalib ");
+ iccCommand += iccconfig.readEntry("ICCFile");
+ iccCommand += TQString(" &");
+ system(iccCommand.ascii());
+ }
+
+ _colorScheme = locate( "data", "kdisplay/color-schemes/" + _colorScheme + ".kcsrc" );
+ if (!_colorScheme.isEmpty()) {
+ KSimpleConfig config( _colorScheme, true );
+ config.setGroup( "Color Scheme" );
+ app->setPalette( app->createApplicationPalette( &config, 7 ) );
+ }
+
+ app->setFont( _normalFont );
+
+ setup_modifiers( dpy, _numLockStatus );
+ SecureDisplay( dpy );
+ if (!_grabServer) {
+ if (_useBackground) {
+ proc = new KProcess;
+ *proc << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + "krootimage";
+ *proc << _backgroundCfg;
+ proc->start();
+ }
+ GSendInt( G_SetupDpy );
+ GRecvInt();
+ }
+
+ if (!_compositor.isEmpty()) {
+ comp = new KProcess;
+ *comp << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + _compositor.ascii();
+ comp->start(KProcess::NotifyOnExit, KProcess::Stdin);
+ }
+
+ if (!_windowManager.isEmpty()) {
+ twin = new KProcess;
+ *twin << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + _windowManager.ascii();
+ twin->start();
+ has_twin = true;
+ }
+
+ GSendInt( G_Ready );
+
+ kdDebug() << timestamp() << " main1" << endl;
+ setCursor( dpy, app->desktop()->winId(), XC_left_ptr );
+
+ for (;;) {
+ int rslt, cmd = GRecvInt();
+
+ if (cmd == G_ConfShutdown) {
+ int how = GRecvInt(), uid = GRecvInt();
+ char *os = GRecvStr();
+ TDMSlimShutdown::externShutdown( how, os, uid );
+ if (os)
+ free( os );
+ GSendInt( G_Ready );
+ _autoLoginDelay = 0;
+ continue;
+ }
+
+ if (cmd == G_ErrorGreet) {
+ if (KGVerify::handleFailVerify( TQT_TQWIDGET(tqApp->desktop()->screen( _greeterScreen )) ))
+ break;
+ _autoLoginDelay = 0;
+ cmd = G_Greet;
+ }
+
+ KProcess *proc2 = 0;
+ app->setOverrideCursor( Qt::WaitCursor );
+ FDialog *dialog = NULL;
+#ifdef XDMCP
+ if (cmd == G_Choose) {
+ dialog = new ChooserDlg;
+ GSendInt( G_Ready ); /* tell chooser to go into async mode */
+ GRecvInt(); /* ack */
+ } else
+#endif
+ {
+ if ((cmd != G_GreetTimed && !_autoLoginAgain) ||
+ _autoLoginUser.isEmpty())
+ _autoLoginDelay = 0;
+ if (_useTheme && !_theme.isEmpty()) {
+ // Qt4 has a nasty habit of generating BadWindow errors in normal operation, so we simply ignore them
+ // This also prevents the user from being dropped to a console login if Xorg glitches or is buggy
+ XSetErrorHandler( ignoreXError );
+ KThemedGreeter *tgrt;
+ bool has_twin_bkp = has_twin;
+ is_themed = true;
+ has_twin = false; // [FIXME] The themed greeter is built on the assumption that there is no window manager available (i.e. it keeps stealing focus) and needs to be repaired.
+ dialog = tgrt = new KThemedGreeter;
+ kdDebug() << timestamp() << " themed" << endl;
+ if (!tgrt->isOK()) {
+ is_themed = false;
+ has_twin = has_twin_bkp;
+ delete tgrt;
+ checkSAK(app);
+ dialog = new KStdGreeter;
+#ifdef WITH_XRANDR
+ dialog->move(dialog->x() + primaryScreenPosition.x(), dialog->y() + primaryScreenPosition.y());
+#endif
+ }
+ else {
+#ifdef WITH_XRANDR
+ dialog->move(primaryScreenPosition.x(), primaryScreenPosition.y());
+#endif
+ }
+ XSetErrorHandler( (XErrorHandler)0 );
+ } else {
+ checkSAK(app);
+ dialog = new KStdGreeter;
+#ifdef WITH_XRANDR
+ dialog->move(dialog->x() + primaryScreenPosition.x(), dialog->y() + primaryScreenPosition.y());
+#endif
+ }
+ TQPoint oldCursorPos = TQCursor::pos();
+#ifdef WITH_XRANDR
+ TQCursor::setPos(oldCursorPos.x() + primaryScreenPosition.x(), oldCursorPos.y() + primaryScreenPosition.y());
+#endif
+ if (*_preloader) {
+ proc2 = new KProcess;
+ *proc2 << _preloader;
+ proc2->start();
+ }
+ }
+ app->restoreOverrideCursor();
+ Debug( "entering event loop\n" );
+ // Qt4 has a nasty habit of generating BadWindow errors in normal operation, so we simply ignore them
+ // This also prevents the user from being dropped to a console login if Xorg glitches or is buggy
+ XSetErrorHandler( ignoreXError );
+ rslt = dialog->exec();
+ XSetErrorHandler( (XErrorHandler)0 );
+ Debug( "left event loop\n" );
+
+ login_user = static_cast<KGreeter*>(dialog)->curUser;
+
+ if (rslt != ex_greet) {
+ delete dialog;
+ }
+ delete proc2;
+#ifdef XDMCP
+ switch (rslt) {
+ case ex_greet:
+ GSendInt( G_DGreet );
+ continue;
+ case ex_choose:
+ GSendInt( G_DChoose );
+ continue;
+ default:
+ break;
+ }
+#endif
+ break;
+ }
+
+ KGVerify::done();
+
+ if (comp) {
+ if (_compositor == "kompmgr") {
+ // Change process UID
+ // Get user UID
+ passwd* userinfo = getpwnam(login_user.ascii());
+ if (userinfo) {
+ TQString newuid = TQString("%1").arg(userinfo->pw_uid);
+ // kompmgr allows us to change its uid in this manner:
+ // 1.) Send SIGUSER1
+ // 2.) Send the new UID to it on the command line
+ comp->kill(SIGUSR1);
+ comp->writeStdin(newuid.ascii(), newuid.length());
+ usleep(50000); // Give the above function some time to execute. Note that on REALLY slow systems this could fail, leaving kompmgr running as root. TODO: Look into ways to make this more robust.
+ }
+ }
+ comp->closeStdin();
+ comp->detach();
+ delete comp;
+ }
+ if (twin) {
+ twin->closeStdin();
+ twin->detach();
+ delete twin;
+ }
+ delete proc;
+ UnsecureDisplay( dpy );
+ restore_modifiers();
+
+ XSetInputFocus( qt_xdisplay(), PointerRoot, PointerRoot, CurrentTime );
+
+ delete app;
+}
+
+} // extern "C"
+
+#include "kgapp.moc"