diff options
| -rw-r--r-- | examples/x-window-focus | 120 | ||||
| -rwxr-xr-x | src/__main__.py | 21 | 
2 files changed, 138 insertions, 3 deletions
diff --git a/examples/x-window-focus b/examples/x-window-focus new file mode 100644 index 0000000..cf5798b --- /dev/null +++ b/examples/x-window-focus @@ -0,0 +1,120 @@ +# -*- python -*- + +# This configuration scripts can enable or disable Redshift +# depending on that window is in focus, by class or title. +# However this is actually window manager dependent and have +# only been tested on twm and xmonad. + + +# Copyright © 2014  Mattias Andrée (maandree@member.fsf.org) +#  +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +#  +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +#  +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + + +# This requires that python3-xlib is installed. + +import signal +import threading + +import Xlib.display + + +def x_window_focus_thread_function(proc): +    ''' +    The function that our thread runs +     +    @param  proc:Popen  The redshift process +    ''' +    # Acquire connection to X +    x_display = Xlib.display.Display() +    # Get root windows for each screen and list on most events +    mask  = ((1 <<  2) - 1) ^ ((1 <<  0) - 1) +    mask |= ((1 << 14) - 1) ^ ((1 <<  3) - 1) +    mask |= ((1 << 20) - 1) ^ ((1 << 15) - 1) +    mask |= ((1 << 25) - 1) ^ ((1 << 21) - 1) +    for x_screen_i in range(x_display.screen_count()): +        x_screen = x_display.screen(x_screen_i) +        x_root = x_screen.root +        x_root.change_attributes(event_mask = mask) +    x_display.flush() +     +    try: +        last = None +        we_disabled = False +        while True: +            try: +                # Get focused window +                window = x_display.get_input_focus().focus +                if isinstance(window, int): +                    x_display.next_event() +                    continue +                 +                # Get window specifications +                wm_class = window.get_wm_class() +                wm_name = window.get_wm_name() +                if (wm_class is None) and (wm_name is None): +                    x_display.next_event() +                    continue +                if (wm_name is not None) and (not isinstance(wm_name, str)): +                    wm_name = wm_name.decode('utf-8', 'replace') +                window = (None if wm_class is None else wm_class[0], +                          None if wm_class is None else wm_class[1], +                          wm_name) +                #sys.stderr.buffer.write((repr(window) + '\n').encode('utf-8')) +                #sys.stderr.buffer.flush() +            except: +                x_display.next_event() +                continue +             +            # Check that something changed +            if (last is not None) and (last == window): +                x_display.next_event() +                continue +            last = window +             +            # Check what window is in focus +            should_be_disabled = False +            if window[0] == 'inkscape': +                should_be_disabled = True +            elif window[0].startswith('gimp-'): # continues with the version number +                should_be_disabled = True +             +            # Perhaps toggle +            if red_running and (should_be_disabled == red_status): +                if red_status or we_disabled: +                    we_disabled = should_be_disabled +                    proc.send_signal(signal.SIGUSR1) +             +            # Wait for next update +            x_display.next_event() +    finally: +        # Close X connection on exit +        x_display.close() + + +start_daemon_threads_ = start_daemon_threads +def start_daemon_threads(proc, sock): +    ''' +    Start the threads for the daemon +     +    @param  sock:socket  The server socket +    @param  proc:Popen   The redshift process +    ''' +    start_daemon_threads_(proc, sock) +     +    # Start our thread +    thread = threading.Thread(target = x_window_focus_thread_function, args = (proc,)) +    thread.setDaemon(True) +    thread.start() + diff --git a/src/__main__.py b/src/__main__.py index 09a345b..ee55217 100755 --- a/src/__main__.py +++ b/src/__main__.py @@ -194,9 +194,9 @@ for arg in sys.argv[1:]:          for arg in subargs:              if (add_to_red_opts is None) or add_to_red_opts:                  add_to_red_opts = None -                red_arg += arg[1] +                red_arg += arg              elif isinstance(config_file, list): -                config_file.append(arg[1]) +                config_file.append(arg)              elif arg in ('-d', '--daemon'):             daemon = 1              elif arg in ('+d', '++daemon'):             daemon = 2              elif arg in ('-x', '--reset', '--kill'):    kill += 1 @@ -218,8 +218,11 @@ for arg in sys.argv[1:]:          if add_to_red_opts is None:              red_opts.append(red_arg)              add_to_red_opts = False -        if isinstance(config_file, list): +        if isinstance(config_file, list) and (len(config_file) > 0):              config_file = ''.join(config_file) +if isinstance(config_file, list): +    sys.stderr.write('%s: error: premature end of arguments\n' % sys.argv[0]) +    sys.exit(1)  # Parse help request for -l and -m @@ -400,6 +403,16 @@ def use_client(sock, proc):      sock.close() +def start_daemon_threads(proc, sock): +    ''' +    Start the threads for the daemon +     +    @param  sock:socket  The server socket +    @param  proc:Popen   The redshift process +    ''' +    pass + +  def run_as_daemon(sock):      '''      Perform daemon logic @@ -417,6 +430,8 @@ def run_as_daemon(sock):          command += red_args      proc = Popen(command, stdout = PIPE, stderr = open(os.devnull)) +    start_daemon_threads(proc, sock) +          # Read status from redshift      thread = threading.Thread(target = read_status, args = (proc, sock))      thread.setDaemon(True)  | 
