source: trunk/debathena/debathena/kiosk/gdm-launch-kiosk @ 25348

Revision 25348, 4.8 KB checked in by jdreed, 13 years ago (diff)
In kiosk: * Call .run() on the dialog so that people can press Esc (Trac: #1007) * Make the button window non-resizable because the resize anchor is giant and ugly these days
  • Property svn:executable set to *
Line 
1#!/usr/bin/python -Wall
2
3import dbus
4import dbus.mainloop.glib
5import gtk
6import gtk.glade
7import gobject
8import time
9import os
10import sys
11import subprocess
12from optparse import OptionParser
13
14GLADE_FILE = "/usr/share/debathena-kiosk/gdm-launch-kiosk.glade"
15LAUNCH_COMMAND = "/usr/lib/debathena-kiosk/launch-kiosk"
16
17SM_DBUS_NAME = "org.gnome.SessionManager"
18SM_DBUS_PATH = "/org/gnome/SessionManager"
19SM_DBUS_INTERFACE = "org.gnome.SessionManager"
20SM_CLIENT_DBUS_INTERFACE = "org.gnome.SessionManager.ClientPrivate"
21APP_ID = "debathena-kiosk"
22
23class Kiosk:
24    def __init__(self):
25        self.sessionEnding = False
26        self.sessionBus = dbus.SessionBus()
27        try:
28            self.register_with_sm()
29            self.init_sm_client()
30        except:
31            print "Warning: Cannot register with session manager."
32
33        try:
34            self.xml = gtk.glade.XML(GLADE_FILE)
35        except:
36            print "Failed to create Glade XML object."
37            sys.exit(1)
38        self.kioskWindow = self.xml.get_widget('KioskWindow')
39        self.kioskDialog = self.xml.get_widget('KioskDialog')
40        self.xml.signal_autoconnect(self)
41        # Turn off all window decorations for the login screen.
42        self.kioskWindow.set_decorated(False)
43        # Because the resize anchor in Natty is obscenely large
44        self.kioskWindow.set_property('resizable', False)
45        self.kioskDialog.set_decorated(False)
46        # Position the window near the bottom of the screen, in the center.
47        self.kioskWindow.set_gravity(gtk.gdk.GRAVITY_SOUTH)
48        width, height = self.kioskWindow.get_size()
49        self.kioskWindow.move((gtk.gdk.screen_width() - width) / 2,
50                              gtk.gdk.screen_height() - height - 80)
51        self.kioskWindow.show_all()
52
53    def kioskButton_on_click(self, button):
54        if not self.sessionEnding:
55            self.kioskDialog.run()
56
57    def kioskDialogResponseHandler(self, dialog, response_id):
58        if response_id == 1 and not self.sessionEnding:
59            self.launch()
60        self.kioskDialog.hide()
61
62    def launch(self):
63        pid = os.fork()
64        if pid == 0:
65            # Start a new session.
66            os.setsid();
67            # Fork another child to launch the command.
68            pid = os.fork()
69            if pid == 0:
70                # Here in the second child, exec the command.
71                try:
72                    os.execlp("sudo", "sudo", "-n", LAUNCH_COMMAND)
73                except OSError, e:
74                    print "error: Could not run %s as root: %s" % (LAUNCH_COMMAND, e.strerror)
75                    os._exit(255)
76            else:
77                # The first child exits immediately.
78                os._exit(0)
79        else:
80            # Here in the parent: wait for the first child to exit.
81            (pid, status) = os.waitpid(pid, 0)
82            if status != 0:
83                print "error launching command, status %d" % status
84
85    # Connect to the session manager, and register our client.
86    def register_with_sm(self):
87        proxy = self.sessionBus.get_object(SM_DBUS_NAME, SM_DBUS_PATH)
88        sm = dbus.Interface(proxy, SM_DBUS_INTERFACE)
89        autostart_id = os.getenv("DESKTOP_AUTOSTART_ID", default="")
90        self.smClientId = sm.RegisterClient(APP_ID, autostart_id)
91
92    # Set up to handle signals from the session manager.
93    def init_sm_client(self):
94        proxy = self.sessionBus.get_object(SM_DBUS_NAME, self.smClientId)
95        self.smClient = dbus.Interface(proxy, SM_CLIENT_DBUS_INTERFACE)
96        self.smClient.connect_to_signal("QueryEndSession",
97                                         self.sm_on_QueryEndSession)
98        self.smClient.connect_to_signal("EndSession", self.sm_on_EndSession)
99        self.smClient.connect_to_signal("CancelEndSession",
100                                         self.sm_on_CancelEndSession)
101        self.smClient.connect_to_signal("Stop", self.sm_on_Stop)
102
103    # Here on a QueryEndSession signal from the session manager.
104    def sm_on_QueryEndSession(self, flags):
105        self.sessionEnding = True
106        # Response args: is_ok, reason.
107        self.smClient.EndSessionResponse(True, "")
108
109    # Here on an EndSession signal from the session manager.
110    def sm_on_EndSession(self, flags):
111        self.sessionEnding = True
112        # Response args: is_ok, reason.
113        self.smClient.EndSessionResponse(True, "")
114
115    # Here on a CancelEndSession signal from the session manager.
116    def sm_on_CancelEndSession(self):
117        self.sessionEnding = False
118
119    # Here on a Stop signal from the session manager.
120    def sm_on_Stop(self):
121        gtk.main_quit()
122
123def main():
124    if not os.access(GLADE_FILE, os.R_OK):
125        print 'error: Unable to read glade file "' + GLADE_FILE + '"'
126        sys.exit(1)
127    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
128    Kiosk()
129    gtk.main()
130
131if __name__ == '__main__':
132    main()
Note: See TracBrowser for help on using the repository browser.