Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python2
- """ A small script to suspend resource-hungry programs when they are not
- on the current workspace. They will continue after switching back
- to their workspace. Note that all processes spawned by those programs
- are suspended via 'kill -STOP pid', so music, video, download, computations
- etc will halt until back in focus. """
- """ Needs python2, python2-gobject and an EWMH-compliant window manager (almost
- all WMs support EWMH, except ratpoison and a few others)."""
- import gi
- import subprocess
- gi.require_version('Wnck', '3.0')
- from gi.repository import GLib
- from gi.repository import Wnck
- """ This is the place to specify which programs should be suspended. """
- applications = ['firefox', 'chromium']
- def check_suspend(ws_active_number, window_data, activate_all=False):
- """ Find all pid's spawned by the applications and either suspend them
- or activate them, depending on if the main application is on the current
- workspace.
- Arguments:
- ws_active_number -- the number of the current workspace
- window_data -- dict holding pid's and workspace positions
- of all windows
- active_all -- if True, ignore current workspace and activate all
- windows
- """
- processes = {}
- for app in applications:
- processes[app] = get_shell_output('pidof %s' % app).split()
- for window in window_data:
- for app in processes.keys():
- if window['pid'] in processes[app]:
- if ws_active_number != window['workspace']:
- for pid in processes[app]:
- subprocess.call('kill -STOP %s' % pid, shell=True)
- if ws_active_number == window['workspace'] or activate_all:
- for pid in processes[app]:
- subprocess.call('kill -CONT %s' % pid, shell=True)
- def evt_on_ws_switch(screen, workspace):
- """ Get the number of the current workspace, gather all window information
- and call out suspend function.
- Arguments:
- screen -- instance of gi.repository.Wnck.Screen
- workspace -- instance of gi.repository.Wnck.Workspace
- """
- ws_active = screen.get_active_workspace()
- ws_active_number = ws_active.get_number()
- window_data = get_windows(screen)
- check_suspend(ws_active_number, window_data)
- def get_shell_output(command):
- """ Execute a shell command and return the output.
- Arguments:
- command -- a shell command as string
- """
- process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
- output = process.communicate()[0]
- return output
- def get_windows(screen):
- """ Find all windows. Return a list of dicts. Each dict represents a
- window and holds its pid and workspace number.
- Arguments:
- screen -- instance of gi.repository.Wnck.screen
- """
- window_data = []
- windows = screen.get_windows()
- for w in windows:
- w_workspace = w.get_workspace()
- if w_workspace:
- window = {}
- window['pid'] = str(w.get_pid())
- window['workspace'] = w_workspace.get_number()
- window_data.append(window)
- return window_data
- if __name__ == '__main__':
- """ Do an initial check for workspaces, apps and processes and then
- start our MainLoop waiting for workspace-change-events. """
- screen = Wnck.Screen.get_default()
- screen.force_update()
- listener = screen.connect('active_workspace_changed', evt_on_ws_switch)
- ws_active_number = screen.get_active_workspace().get_number()
- window_data = get_windows(screen)
- check_suspend(ws_active_number, window_data)
- main_loop = GLib.MainLoop()
- try:
- main_loop.run()
- except:
- """ When our MainLoop fails or gets killed for whatever reason,
- activate all windows, disconnect our listener, clear our objects
- and exit gracefully. """
- window_data = get_windows(screen)
- check_suspend(ws_active_number, window_data, activate_all=True)
- screen.disconnect(listener)
- screen = None
- Wnck.shutdown()
- main_loop.quit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement