230 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
from i3ipc import Connection, Event
 | 
						|
from threading import Thread
 | 
						|
from time import sleep
 | 
						|
 | 
						|
 | 
						|
FRAME_T = 0.01  # time taken between each frame of fade
 | 
						|
 | 
						|
# transparency values
 | 
						|
CON_AC     = 1     # active window
 | 
						|
CON_INAC   = 0.5   # inactive window
 | 
						|
FLOAT_AC   = 1     # active floating window
 | 
						|
FLOAT_INAC = 0.5  # inactive floating window
 | 
						|
BOT_INAC   = 0.9   # bottom window
 | 
						|
 | 
						|
 | 
						|
# fade durations
 | 
						|
FADE_TIME      = 0.2
 | 
						|
ALT_FADE_TIME  = 0.1
 | 
						|
 | 
						|
CON_OUT        = FADE_TIME      # window fading out
 | 
						|
CON_IN         = 0.15           # window fading in
 | 
						|
FLOAT_OUT      = ALT_FADE_TIME  # floating window fading out
 | 
						|
FLOAT_IN       = ALT_FADE_TIME  # floating window fading in
 | 
						|
BOT_OUT        = ALT_FADE_TIME  # bottom window fading out
 | 
						|
BOT_IN         = ALT_FADE_TIME  # bottom window fading in
 | 
						|
BOT_SWITCH_IN  = FADE_TIME      # window becoming bottom window
 | 
						|
BOT_SWITCH_OUT = FADE_TIME      # bottom window becoming window
 | 
						|
FLOAT_BOT_OUT  = FADE_TIME      # floating window fading out from bottom
 | 
						|
FLOAT_BOT_IN   = FADE_TIME      # floating window fading in from bottom
 | 
						|
 | 
						|
 | 
						|
class Fader:
 | 
						|
    def __init__(self):
 | 
						|
        self.floating_windows = []
 | 
						|
        self.fader_running    = False
 | 
						|
        self.fade_queue       = []
 | 
						|
        self.fade_data        = {}
 | 
						|
        self.bottom_win       = None
 | 
						|
        self.old_win          = None
 | 
						|
        self.active_win       = None
 | 
						|
 | 
						|
        ipc = Connection()
 | 
						|
        ipc.on(Event.WINDOW_FOCUS,    self.on_window_focus)
 | 
						|
        ipc.on(Event.WINDOW_NEW,      self.on_window_new)
 | 
						|
        ipc.on(Event.WINDOW_FLOATING, self.on_window_floating)
 | 
						|
 | 
						|
        for win in ipc.get_tree():
 | 
						|
            if win.type == "floating_con":
 | 
						|
                self.floating_windows.append(win.id)
 | 
						|
                if win.focused:
 | 
						|
                    change_opacity(win, FLOAT_AC)
 | 
						|
                    self.active_win = win
 | 
						|
                else:
 | 
						|
                    change_opacity(win, FLOAT_INAC)
 | 
						|
            elif win.type == "con":
 | 
						|
                if win.focused:
 | 
						|
                    self.active_win = win
 | 
						|
                    change_opacity(win, CON_AC)
 | 
						|
                else:
 | 
						|
                    change_opacity(win, CON_INAC)
 | 
						|
 | 
						|
        ipc.main()
 | 
						|
 | 
						|
    def add_fade(self, win, start, target, duration):
 | 
						|
        if not duration:
 | 
						|
            if win.id in self.fade_queue:
 | 
						|
                self.fade_queue.remove(win.id)
 | 
						|
                del self.fade_data[win.id]
 | 
						|
            change_opacity(win, target)
 | 
						|
            return
 | 
						|
 | 
						|
        if win.id in self.fade_queue:
 | 
						|
            f = self.fade_data[win.id]
 | 
						|
            change = (FRAME_T / duration) * (target - f["opacity"])
 | 
						|
            f["change"] = change
 | 
						|
            f["target"] = target
 | 
						|
            return
 | 
						|
 | 
						|
        change_opacity(win, start)
 | 
						|
        change = (FRAME_T / duration) * (target - start)
 | 
						|
        fade_data = {"opacity": start, "change": change, "target": target, "win": win}
 | 
						|
        self.fade_queue.append(win.id)
 | 
						|
        self.fade_data[win.id] = fade_data
 | 
						|
 | 
						|
    def start_fader(self):
 | 
						|
        if not self.fader_running:
 | 
						|
            self.fader_running = True
 | 
						|
            Thread(target=self.fader).start()
 | 
						|
 | 
						|
    def fader(self):
 | 
						|
        while self.fade_queue:
 | 
						|
            for win_id in self.fade_queue.copy():
 | 
						|
                try:
 | 
						|
                    f = self.fade_data[win_id]
 | 
						|
                except KeyError:
 | 
						|
                    continue
 | 
						|
                f["opacity"] += f["change"]
 | 
						|
 | 
						|
                finished = False
 | 
						|
                if f["change"] > 0:
 | 
						|
                    if f["opacity"] >= f["target"]:
 | 
						|
                        finished = True
 | 
						|
                elif f["opacity"] <= f["target"]:
 | 
						|
                    finished = True
 | 
						|
 | 
						|
                if finished:
 | 
						|
                    change_opacity(f["win"], f["target"])
 | 
						|
                    try:
 | 
						|
                        self.fade_queue.remove(win_id)
 | 
						|
                        del self.fade_data[win_id]
 | 
						|
                    except (KeyError, ValueError):
 | 
						|
                        continue
 | 
						|
                else:
 | 
						|
                    change_opacity(f["win"], f["opacity"])
 | 
						|
 | 
						|
            sleep(FRAME_T)
 | 
						|
        self.fader_running = False
 | 
						|
 | 
						|
    def on_window_focus(self, ipc, e):
 | 
						|
        if self.active_win.id == e.container.id:
 | 
						|
            return
 | 
						|
 | 
						|
        if self.active_win.type == "con":
 | 
						|
            if e.container.type == "con":
 | 
						|
                self.add_fade(
 | 
						|
                    e.container, CON_INAC,
 | 
						|
                    CON_AC, CON_IN)
 | 
						|
                self.add_fade(
 | 
						|
                    self.active_win, CON_AC,
 | 
						|
                    CON_INAC, CON_OUT)
 | 
						|
 | 
						|
            else:
 | 
						|
                self.add_fade(
 | 
						|
                    e.container, FLOAT_INAC,
 | 
						|
                    FLOAT_AC, FLOAT_IN)
 | 
						|
                self.add_fade(
 | 
						|
                    self.active_win, CON_AC,
 | 
						|
                    BOT_INAC, BOT_OUT)
 | 
						|
                self.bottom_win = self.active_win
 | 
						|
 | 
						|
        else:
 | 
						|
            if e.container.type == "con":
 | 
						|
                self.add_fade(
 | 
						|
                    self.active_win, FLOAT_AC,
 | 
						|
                    FLOAT_INAC, FLOAT_BOT_OUT)
 | 
						|
 | 
						|
                if not self.bottom_win:
 | 
						|
                    self.add_fade(
 | 
						|
                        e.container, CON_INAC,
 | 
						|
                        CON_AC, CON_IN)
 | 
						|
 | 
						|
                elif e.container.id != self.bottom_win.id:
 | 
						|
                    self.add_fade(
 | 
						|
                        self.bottom_win, BOT_INAC,
 | 
						|
                        CON_INAC, BOT_SWITCH_OUT)
 | 
						|
                    self.add_fade(
 | 
						|
                        e.container, CON_INAC,
 | 
						|
                        CON_AC, BOT_SWITCH_IN)
 | 
						|
                    self.bottom_win = e.container
 | 
						|
 | 
						|
                else:
 | 
						|
                    self.add_fade(
 | 
						|
                        self.bottom_win, BOT_INAC,
 | 
						|
                        CON_AC, BOT_IN)
 | 
						|
 | 
						|
            else:
 | 
						|
                self.add_fade(
 | 
						|
                    self.active_win, FLOAT_AC,
 | 
						|
                    FLOAT_INAC, FLOAT_OUT)
 | 
						|
                self.add_fade(
 | 
						|
                    e.container, FLOAT_INAC,
 | 
						|
                    FLOAT_AC, FLOAT_IN)
 | 
						|
 | 
						|
        self.start_fader()
 | 
						|
        self.active_win = e.container
 | 
						|
 | 
						|
    def on_window_new(self, ipc, e):
 | 
						|
        if self.active_win:
 | 
						|
            if self.active_win.type == "con":
 | 
						|
                change_opacity(self.active_win, CON_INAC)
 | 
						|
            else:
 | 
						|
                change_opacity(self.active_win, FLOAT_INAC)
 | 
						|
 | 
						|
        if self.bottom_win:
 | 
						|
            change_opacity(self.bottom_win, CON_INAC)
 | 
						|
 | 
						|
        elif self.active_win and self.active_win.type == "con":
 | 
						|
            self.bottom_win = self.active_win
 | 
						|
            change_opacity(self.bottom_win, CON_INAC)
 | 
						|
 | 
						|
        change_opacity(e.container, CON_AC)
 | 
						|
        self.old_win = self.active_win
 | 
						|
        self.active_win = e.container
 | 
						|
 | 
						|
    def on_window_floating(self, ipc, e):
 | 
						|
        c_id = e.container.id
 | 
						|
        if c_id not in self.floating_windows:
 | 
						|
            self.floating_windows.append(c_id)
 | 
						|
 | 
						|
            if self.active_win.id != e.container.id:
 | 
						|
                change_opacity(e.container, FLOAT_INAC)
 | 
						|
 | 
						|
            else:
 | 
						|
                if self.old_win and self.bottom_win:
 | 
						|
                    if self.old_win.type == "con":
 | 
						|
                        self.bottom_win = self.old_win
 | 
						|
                    change_opacity(self.bottom_win, BOT_INAC)
 | 
						|
                change_opacity(e.container, FLOAT_AC)
 | 
						|
 | 
						|
        else:
 | 
						|
            self.floating_windows.remove(c_id)
 | 
						|
            if self.active_win.id != e.container.id:
 | 
						|
                change_opacity(e.container, CON_INAC)
 | 
						|
 | 
						|
            else:
 | 
						|
                if self.old_win and self.old_win.type == "con":
 | 
						|
                    change_opacity(self.old_win, CON_INAC)
 | 
						|
                change_opacity(self.active_win, CON_AC)
 | 
						|
 | 
						|
        self.active_win = e.container
 | 
						|
 | 
						|
 | 
						|
def change_opacity(win, trans):
 | 
						|
    win.command("opacity " + str(trans))
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    Fader()
 | 
						|
 |