Advertisement
Guest User

workspace-suspend.py

a guest
Mar 10th, 2018
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.15 KB | None | 0 0
  1. #!/usr/bin/python2
  2.  
  3. """ A small script to suspend resource-hungry programs when they are not
  4. on the current workspace. They will continue after switching back
  5. to their workspace. Note that all processes spawned by those programs
  6. are suspended via 'kill -STOP pid', so music, video, download, computations
  7. etc will halt until back in focus. """
  8.  
  9. """ Needs python2, python2-gobject and an EWMH-compliant window manager (almost
  10. all WMs support EWMH, except ratpoison and a few others)."""
  11.  
  12. import gi
  13. import subprocess
  14.  
  15. gi.require_version('Wnck', '3.0')
  16.  
  17. from gi.repository import GLib
  18. from gi.repository import Wnck
  19.  
  20. """ This is the place to specify which programs should be suspended. """
  21. applications = ['firefox', 'chromium']
  22.  
  23.  
  24. def check_suspend(ws_active_number, window_data, activate_all=False):
  25.     """ Find all pid's spawned by the applications and either suspend them
  26.    or activate them, depending on if the main application is on the current
  27.    workspace.
  28.  
  29.    Arguments:
  30.    ws_active_number -- the number of the current workspace
  31.    window_data      -- dict holding pid's and workspace positions
  32.                        of all windows
  33.    active_all       -- if True, ignore current workspace and activate all
  34.                        windows
  35.    """
  36.     processes = {}
  37.     for app in applications:
  38.         processes[app] = get_shell_output('pidof %s' % app).split()
  39.     for window in window_data:
  40.         for app in processes.keys():
  41.             if window['pid'] in processes[app]:
  42.                 if ws_active_number != window['workspace']:
  43.                     for pid in processes[app]:
  44.                         subprocess.call('kill -STOP %s' % pid, shell=True)
  45.                 if ws_active_number == window['workspace'] or activate_all:
  46.                     for pid in processes[app]:
  47.                         subprocess.call('kill -CONT %s' % pid, shell=True)
  48.  
  49. def evt_on_ws_switch(screen, workspace):
  50.     """ Get the number of the current workspace, gather all window information
  51.    and call out suspend function.
  52.  
  53.    Arguments:
  54.    screen    -- instance of gi.repository.Wnck.Screen
  55.    workspace -- instance of gi.repository.Wnck.Workspace
  56.    """
  57.     ws_active = screen.get_active_workspace()
  58.     ws_active_number = ws_active.get_number()
  59.     window_data = get_windows(screen)
  60.     check_suspend(ws_active_number, window_data)
  61.  
  62. def get_shell_output(command):
  63.     """ Execute a shell command and return the output.
  64.    
  65.    Arguments:
  66.    command  -- a shell command as string
  67.    """
  68.     process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
  69.     output = process.communicate()[0]
  70.     return output
  71.  
  72. def get_windows(screen):
  73.     """ Find all windows. Return a list of dicts. Each dict represents a
  74.    window and holds its pid and workspace number.
  75.    
  76.    Arguments:
  77.    screen  -- instance of gi.repository.Wnck.screen
  78.    """
  79.     window_data = []
  80.     windows = screen.get_windows()
  81.     for w in windows:
  82.         w_workspace = w.get_workspace()
  83.         if w_workspace:
  84.             window = {}
  85.             window['pid'] = str(w.get_pid())
  86.             window['workspace'] = w_workspace.get_number()
  87.             window_data.append(window)
  88.     return window_data
  89.  
  90. if __name__ == '__main__':
  91.     """ Do an initial check for workspaces, apps and processes and then
  92.    start our MainLoop waiting for workspace-change-events. """
  93.     screen = Wnck.Screen.get_default()
  94.     screen.force_update()
  95.     listener = screen.connect('active_workspace_changed', evt_on_ws_switch)
  96.     ws_active_number = screen.get_active_workspace().get_number()
  97.     window_data = get_windows(screen)
  98.     check_suspend(ws_active_number, window_data)
  99.     main_loop = GLib.MainLoop()
  100.     try:
  101.         main_loop.run()
  102.     except:
  103.         """ When our MainLoop fails or gets killed for whatever reason,
  104.        activate all windows, disconnect our listener, clear our objects
  105.        and exit gracefully. """
  106.         window_data = get_windows(screen)
  107.         check_suspend(ws_active_number, window_data, activate_all=True)
  108.         screen.disconnect(listener)
  109.         screen = None
  110.         Wnck.shutdown()
  111.         main_loop.quit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement