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

Revision 24578, 4.7 KB checked in by rbasch, 14 years ago (diff)
In kiosk: * Add session management support via the D-Bus interface to the gdm launcher, so it terminates upon the end of the gdm session. (Trac: #548) * Make r-kiosk work in Firefox 3.6, by supplying a chrome.manifest and disabling the version-specific compatibility check. (Trac: #571)
  • 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        self.kioskDialog.set_decorated(False)
44        # Position the window near the bottom of the screen, in the center.
45        self.kioskWindow.set_gravity(gtk.gdk.GRAVITY_SOUTH)
46        width, height = self.kioskWindow.get_size()
47        self.kioskWindow.move((gtk.gdk.screen_width() - width) / 2,
48                              gtk.gdk.screen_height() - height - 80)
49        self.kioskWindow.show_all()
50
51    def kioskButton_on_click(self, button):
52        if not self.sessionEnding:
53            self.kioskDialog.show()
54
55    def kioskDialogResponseHandler(self, dialog, response_id):
56        if response_id == 1 and not self.sessionEnding:
57            self.launch()
58        self.kioskDialog.hide()
59
60    def launch(self):
61        pid = os.fork()
62        if pid == 0:
63            # Start a new session.
64            os.setsid();
65            # Fork another child to launch the command.
66            pid = os.fork()
67            if pid == 0:
68                # Here in the second child, exec the command.
69                try:
70                    os.execlp("sudo", "sudo", "-n", LAUNCH_COMMAND)
71                except OSError, e:
72                    print "error: Could not run %s as root: %s" % (LAUNCH_COMMAND, e.strerror)
73                    os._exit(255)
74            else:
75                # The first child exits immediately.
76                os._exit(0)
77        else:
78            # Here in the parent: wait for the first child to exit.
79            (pid, status) = os.waitpid(pid, 0)
80            if status != 0:
81                print "error launching command, status %d" % status
82
83    # Connect to the session manager, and register our client.
84    def register_with_sm(self):
85        proxy = self.sessionBus.get_object(SM_DBUS_NAME, SM_DBUS_PATH)
86        sm = dbus.Interface(proxy, SM_DBUS_INTERFACE)
87        autostart_id = os.getenv("DESKTOP_AUTOSTART_ID", default="")
88        self.smClientId = sm.RegisterClient(APP_ID, autostart_id)
89
90    # Set up to handle signals from the session manager.
91    def init_sm_client(self):
92        proxy = self.sessionBus.get_object(SM_DBUS_NAME, self.smClientId)
93        self.smClient = dbus.Interface(proxy, SM_CLIENT_DBUS_INTERFACE)
94        self.smClient.connect_to_signal("QueryEndSession",
95                                         self.sm_on_QueryEndSession)
96        self.smClient.connect_to_signal("EndSession", self.sm_on_EndSession)
97        self.smClient.connect_to_signal("CancelEndSession",
98                                         self.sm_on_CancelEndSession)
99        self.smClient.connect_to_signal("Stop", self.sm_on_Stop)
100
101    # Here on a QueryEndSession signal from the session manager.
102    def sm_on_QueryEndSession(self, flags):
103        self.sessionEnding = True
104        # Response args: is_ok, reason.
105        self.smClient.EndSessionResponse(True, "")
106
107    # Here on an EndSession signal from the session manager.
108    def sm_on_EndSession(self, flags):
109        self.sessionEnding = True
110        # Response args: is_ok, reason.
111        self.smClient.EndSessionResponse(True, "")
112
113    # Here on a CancelEndSession signal from the session manager.
114    def sm_on_CancelEndSession(self):
115        self.sessionEnding = False
116
117    # Here on a Stop signal from the session manager.
118    def sm_on_Stop(self):
119        gtk.main_quit()
120
121def main():
122    if not os.access(GLADE_FILE, os.R_OK):
123        print 'error: Unable to read glade file "' + GLADE_FILE + '"'
124        sys.exit(1)
125    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
126    Kiosk()
127    gtk.main()
128
129if __name__ == '__main__':
130    main()
Note: See TracBrowser for help on using the repository browser.