~kklimonda/ubuntu/natty/hamster-applet/lp.697667

« back to all changes in this revision

Viewing changes to src/hamster/idle.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-02-10 02:52:31 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100210025231-x0q5h4q7nlvihl09
Tags: 2.29.90-0ubuntu1
* New upstream version
  - workspace tracking - switch activity, when switching desktops
  - chart improvements - theme friendly and less noisier
  - for those without GNOME panel there is now a standalone version, 
    accessible via Applications -> Accessories -> Time Tracker
  - overview window remembers position
  - maintaining cursor on the selected row after edits / refreshes
  - descriptions once again in the main input field, delimited by comma
  - activity suggestion box now sorts items by recency (Patryk Zawadzki)
  - searching
  - simplified save report dialog, thanks to the what you see is what you 
    report revamp
  - overview/stats replaced with activities / totals and stats accessible 
    from totals
  - interactive graphs to drill down in totals
  - miscellaneous performance improvements
  - pixel-perfect graphs
* Updated 01_startup-fix.patch to apply to new source layout
* debian/control:
  - Add build-depend on gnome-doc-utils

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# - coding: utf-8 -
 
2
 
 
3
# Copyright (C) 2008 Patryk Zawadzki <patrys at pld-linux.org>
 
4
 
 
5
# This file is part of Project Hamster.
 
6
 
 
7
# Project Hamster is free software: you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation, either version 3 of the License, or
 
10
# (at your option) any later version.
 
11
 
 
12
# Project Hamster is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU General Public License for more details.
 
16
 
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
import logging
 
21
import dbus
 
22
from dbus.lowlevel import Message
 
23
import gconf
 
24
import datetime as dt
 
25
import gobject
 
26
 
 
27
class DbusIdleListener(object):
 
28
    """
 
29
    Listen for idleness coming from org.gnome.ScreenSaver
 
30
 
 
31
    Monitors org.gnome.ScreenSaver for idleness. There are two types,
 
32
    implicit (due to inactivity) and explicit (lock screen), that need to be
 
33
    handled differently. An implicit idle state should subtract the
 
34
    time-to-become-idle (as specified in the gconf) from the last activity,
 
35
    but an explicit idle state should not.
 
36
 
 
37
    The signals are inspected for the "ActiveChanged" and "Lock"
 
38
    members coming from the org.gnome.ScreenSaver interface and the
 
39
    and is_screen_locked members are updated appropriately.
 
40
    """
 
41
    def __init__(self, dispatcher):
 
42
        self.screensaver_uri = "org.gnome.ScreenSaver"
 
43
 
 
44
        self.dispatcher = dispatcher
 
45
        self.screen_locked = False
 
46
        self.idle_from = None
 
47
        self.timeout_minutes = 0 # minutes after session is considered idle
 
48
        self.idle_was_there = False # a workaround variable for pre 2.26
 
49
 
 
50
        try:
 
51
            self.bus = dbus.SessionBus()
 
52
        except:
 
53
            return 0
 
54
        # Listen for chatter on the screensaver interface.
 
55
        # We cannot just add additional match strings to narrow down
 
56
        # what we hear because match strings are ORed together.
 
57
        # E.g., if we were to make the match string
 
58
        # "interface='org.gnome.ScreenSaver', type='method_call'",
 
59
        # we would not get only screensaver's method calls, rather
 
60
        # we would get anything on the screensaver interface, as well
 
61
        # as any method calls on *any* interface. Therefore the
 
62
        # bus_inspector needs to do some additional filtering.
 
63
        self.bus.add_match_string_non_blocking("interface='%s'" %
 
64
                                                           self.screensaver_uri)
 
65
        self.bus.add_message_filter(self.bus_inspector)
 
66
 
 
67
 
 
68
    def bus_inspector(self, bus, message):
 
69
        """
 
70
        Inspect the bus for screensaver messages of interest
 
71
        """
 
72
 
 
73
        # We only care about stuff on this interface.  We did filter
 
74
        # for it above, but even so we still hear from ourselves
 
75
        # (hamster messages).
 
76
        if message.get_interface() != self.screensaver_uri:
 
77
            return True
 
78
 
 
79
        member = message.get_member()
 
80
 
 
81
        if member in ("SessionIdleChanged", "ActiveChanged"):
 
82
            logging.debug("%s -> %s" % (member, message.get_args_list()))
 
83
 
 
84
            idle_state = message.get_args_list()[0]
 
85
            if idle_state:
 
86
                self.idle_from = dt.datetime.now()
 
87
 
 
88
                # from gnome screensaver 2.24 to 2.28 they have switched
 
89
                # configuration keys and signal types.
 
90
                # luckily we can determine key by signal type
 
91
                if member == "SessionIdleChanged":
 
92
                    delay_key = "/apps/gnome-screensaver/idle_delay"
 
93
                else:
 
94
                    delay_key = "/desktop/gnome/session/idle_delay"
 
95
 
 
96
                client = gconf.client_get_default()
 
97
                self.timeout_minutes = client.get_int(delay_key)
 
98
 
 
99
            else:
 
100
                self.screen_locked = False
 
101
                self.idle_from = None
 
102
 
 
103
            if member == "ActiveChanged":
 
104
                # ActiveChanged comes before SessionIdleChanged signal
 
105
                # as a workaround for pre 2.26, we will wait a second - maybe
 
106
                # SessionIdleChanged signal kicks in
 
107
                def dispatch_active_changed(idle_state):
 
108
                    if not self.idle_was_there:
 
109
                        self.dispatcher.dispatch('active_changed', idle_state)
 
110
                    self.idle_was_there = False
 
111
 
 
112
                gobject.timeout_add_seconds(1, dispatch_active_changed, idle_state)
 
113
 
 
114
            else:
 
115
                # dispatch idle status change to interested parties
 
116
                self.idle_was_there = True
 
117
                self.dispatcher.dispatch('active_changed', idle_state)
 
118
 
 
119
        elif member == "Lock":
 
120
            # in case of lock, lock signal will be sent first, followed by
 
121
            # ActiveChanged and SessionIdle signals
 
122
            logging.debug("Screen Lock Requested")
 
123
            self.screen_locked = True
 
124
 
 
125
        return
 
126
 
 
127
 
 
128
    def getIdleFrom(self):
 
129
        if not self.idle_from:
 
130
            return dt.datetime.now()
 
131
 
 
132
        if self.screen_locked:
 
133
            return self.idle_from
 
134
        else:
 
135
            # Only subtract idle time from the running task when
 
136
            # idleness is due to time out, not a screen lock.
 
137
            return self.idle_from - dt.timedelta(minutes = self.timeout_minutes)
 
138