class I3Thread(threading.Thread): def __init__(self, queue): self.queue = queue self.i3 = Connection() super().__init__() def i3_update(self): self.queue.put(self.i3.get_tree().descendants()) def on_new_window(self, _, event): # when bar window becomes visible if event.container.name == TITLE: # make it floating and sticky self.i3.command( f"[title=\"{TITLE}\"] floating enable, sticky enable") # send the containers structure to it self.i3_update() # disable this event handler self.i3.off(self.on_new_window) def run(self): # this event is used to set up the bar window self.i3.on(Event.WINDOW_NEW, self.on_new_window) def update_on(event): self.i3.on(event, (lambda _, __: self.i3_update())) update_on(Event.WORKSPACE) update_on(Event.WINDOW_NEW) update_on(Event.WINDOW_CLOSE) self.i3.main() def switch_to_workspace(self, workspace_index): self.i3.command(f"workspace {workspace_index}")
def main(): parser = argparse.ArgumentParser() parser.add_argument("--debug", action="store_true", help="Print debug messages to stderr") parser.add_argument( "--version", "-v", action="version", version="%(prog)s {}, Python {}".format(__version__, sys.version), help="display version information", ) parser.add_argument( "--workspaces", "-w", help= "Restricts autotiling to certain workspaces. Example: autotiling --workspaces 8 9", nargs="*", type=str, default=[], ) args = parser.parse_args() if args.debug and args.workspaces: print("autotiling is only active on workspaces:", ','.join(args.workspaces)) handler = partial(switch_splitting, debug=args.debug, workspaces=args.workspaces) i3 = Connection() i3.on(Event.WINDOW_FOCUS, handler) i3.main()
def main(args): '''Connect to IPC, set transparencies, and set up listener''' ipc = Connection() set_opacities(ipc, args.focused, args.unfocused) ipc.on('window::focus', lambda ipc, _: set_opacities(ipc, args.focused, args.unfocused)) ipc.main()
def start(self): from i3ipc import Connection i3 = Connection() self.update(i3) for event in ["window::move", "window::urgent"]: i3.on(event, self.update) i3.main()
def main(): parser = argparse.ArgumentParser() parser.add_argument('--debug', action='store_true', help='Print debug messages to stderr') args = parser.parse_args() handler = partial(switch_splitting, debug=args.debug) i3 = Connection() i3.on(Event.WINDOW_FOCUS, handler) i3.main()
def start(self): from i3ipc import Connection i3 = Connection() self.change_title(i3) for event in ["workspace::focus", "window::close"]: i3.on(event, self.clear_title) for event in ["window::title", "window::focus", "binding"]: i3.on(event, self.change_title) i3.main()
def main(): i3 = Connection() i3swallow = I3Swallow(i3, "st") i3.on(Event.WINDOW_NEW, i3swallow.on_new) i3.on(Event.WINDOW_FOCUS, i3swallow.on_focus) i3.on(Event.WINDOW_CLOSE, i3swallow.on_close) i3.on(Event.WINDOW_MOVE, i3swallow.on_move) i3.on(Event.BINDING, i3swallow.on_binding) i3.on(Event.TICK, i3swallow.on_tick) i3.main()
def main(): parser = argparse.ArgumentParser() parser.add_argument("--debug", action="store_true", help="Print debug messages to stderr") parser.add_argument( "--version", "-v", action="version", version="%(prog)s {}, Python {}".format(1, sys.version), help="display version information", ) args = parser.parse_args() handler = partial(switch_splitting, debug=args.debug) i3 = Connection() i3.on(Event.WINDOW_FOCUS, handler) i3.main()
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 main(): """ Main function - listen for window focus changes and call set_layout when focus changes """ opt_list, _ = getopt.getopt(sys.argv[1:], 'hp:') pid_file = None for opt in opt_list: if opt[0] == "-h": print_help() sys.exit() if opt[0] == "-p": pid_file = opt[1] if pid_file: with open(pid_file, 'w') as f: f.write(str(os.getpid())) i3 = Connection() i3.on(Event.WINDOW_FOCUS, set_layout) i3.main()
def main(): i3 = Connection() rename_workspaces(i3, None) i3.on(Event.WINDOW_NEW, rename_workspaces) i3.on(Event.WINDOW_CLOSE, rename_workspaces) i3.on(Event.WINDOW_MOVE, rename_workspaces) i3.main()
def __init__(self): self.fader_running = False self.fade_queue = [] self.fade_data = {} self.current_win = None self.new_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.focused: change_opacity(win, AC_TRANS) self.current_win = win else: change_opacity(win, INAC_TRANS) ipc.main()
def start(self): 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 main(): """If indicator script is not already running, subscribe to events""" # Get a lock on a temporary file to prevent multiple instances from # running, which would cause nasty race conditions lockfile = os.path.normpath(gettempdir() + "/i3_layout_indicator.lock") fp = open(lockfile, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: print("i3 layout indicator is already running") print("To kill, run 'pkill -f \"python.*i3_layout_indicator.py\"'") sys.exit(1) # Bind events i3 = Connection() i3.on(Event.TICK, update_indicator) i3.on(Event.WINDOW_FOCUS, update_indicator) i3.on(Event.BINDING, update_indicator) # Update indicator once on startup update_indicator(i3, None) # Start listening for events i3.main()
cursor = origin i3.command('[con_id="{}"] focus'.format(cursor.id)) return None # only move if the cursor state is okay if get_cursor_state(direction) == 'okay': i3.command('[con_id="{}"] focus; focus {}'.format( cursor.id, direction )) def on_bind(i3, event): args = event.binding.command if not args.startswith('nop ipc'): return None args = args.split() commands = { 'resize': resize, 'flatten': flatten, 'focvis': focus_visible } try: commands[args[2]](i3, event, args[3:]) except: pass i3.on('binding', on_bind) i3.main()
#!/usr/bin/env python3 from i3ipc import Connection from subprocess import call # This shows i3 keybind actions with a notification. # It can be useful as an alternative to showkey. i3 = Connection() def notify(i3, event): # print(event.binding.__dict__) bind = event.binding mods_dict = [ ['Mod4', 'Super'], ['shift', 'Shift'], ['ctrl', 'Control'], ['Mod1', 'Alt'], ] mods = '+'.join([mod[1] for mod in mods_dict if mod[0] in bind.mods]) if mods: mods += '+' call('notify-send -t 1000 -a i3wm'.split(' ') + [bind.command, '%s%s' % (mods, bind.symbol)]) i3.on('binding', notify) i3.main()
#!/usr/bin/env python3 # budRich@budlabs - 2019 # # this will make all new windows floating # due to the way i3 handles for_window rules # setting a "global rule" to make all new # windows floating, may have undesired side effects. # # https://github.com/i3/i3/issues/3628 # https://github.com/i3/i3/pull/3188 # https://old.reddit.com/r/i3wm/comments/85ctji/when_windows_are_floating_by_default_how_do_i/ from i3ipc import Connection i3 = Connection() def set_floating(i3, event): event.container.command('floating enable') i3.on('window::new', set_floating) i3.main()
i3 = Connection() def thunar(event): if event.change in ['title']: # ins = format(event.container.window_instance) # wid = format(event.container.window) cid = format(event.container.id) ttl = format(event.container.name) cmd = [ "i3-msg", "[con_id=%s]" % (cid), "title_format", sub(" - File Manager$", "", ttl) ] call(cmd) def windownotify(i3, event): if event.container.window_class == 'ThunarD': thunar(event) i3.on('window', windownotify) i3.main()
print('window is thunar') # ins = format(event.container.window_instance) # wid = format(event.container.window) cid = format(event.container.id) ttl = format(event.container.name) newttl = sub(" - File Manager$", "", ttl) event.container.command("title_format %s" % (newttl)) cmd = [ "updatefm", newttl ] call(cmd) def windownotify(i3, event): print('window notify method') if event.container.window_class == 'ThunarD': thunar(event) i3.on('window::title', windownotify) i3.main()
# This shows i3 keybind actions with a notification. # It can be useful as an alternative to showkey. i3 = Connection() def notify(i3, event): # print(event.binding.__dict__) bind = event.binding mods_dict = [ ['Mod4', 'Super'], ['shift', 'Shift'], ['ctrl', 'Control'], ['Mod1', 'Alt'], ] mods = '+'.join([ mod[1] for mod in mods_dict if mod[0] in bind.mods ]) if mods: mods += '+' call('notify-send -t 1000 -a i3wm'.split(' ') + [bind.command, '%s%s' % (mods, bind.symbol)] ) i3.on('binding', notify) i3.main()
#!/usr/bin/env python3 from i3ipc import Connection i3 = Connection() def focus(i3, event): event.container.command('focus') i3.on('window::new', focus) i3.main()
# Loosely based on https://github.com/meelkor/polybar-i3-windows from i3ipc import Connection, Event def ws_win_number(i3_conn, e): # pylint:disable=unused-argument """Compute number of windows in active i3 workspace.""" # TODO: Can we show active windows per monitor workspace instead of active ws? curr_workspace = next(i for i in i3_conn.get_workspaces() if i.focused) windows = [ win for ws in i3_conn.get_tree().workspaces() for win in ws.leaves() if ws.name == curr_workspace.name ] nr_windows = len(windows) label = f"%{{T6}} %{{T-}}%{{T7}}{nr_windows}%{{T-}}" action_label = f"%{{A1:/home/pedro/.config/i3/font_aware_launcher.py rofi ws-win &:}}{label}%{{A}}" # noqa print(action_label, flush=True) if __name__ == '__main__': i3 = Connection() ws_win_number(i3, None) # to populate polybar on first run i3.on(Event.WINDOW_FOCUS, ws_win_number) # We need the next events to be able to handle the case where there are no windows # in the workspace (and hence a zero should be shown) i3.on(Event.WORKSPACE_FOCUS, ws_win_number) i3.on(Event.WINDOW, ws_win_number) i3.main()
class Fader: ipc = None def __init__(self, active_opacity, inactive_opacity, floating_opacity, fade_time, frame_time): self.active_opacity = active_opacity self.inactive_opacity = inactive_opacity self.floating_opacity = floating_opacity self.fade_time = fade_time self.frame_time = frame_time self.fader_running = False self.fade_queue = [] self.fade_data = {} self.current_win = None self.new_win = None def start(self): if self.ipc is not None: raise Exception('Already started') self.ipc = Connection() self.ipc.on(Event.WINDOW_FOCUS, self.on_window_focus) self.ipc.on(Event.WINDOW_NEW, self.on_window_new) self.ipc.on(Event.WINDOW_FLOATING, self.on_window_floating) for win in self.ipc.get_tree(): if win.focused: change_opacity(win, self.active_opacity) self.current_win = win else: change_opacity(win, self.inactive_opacity) self.ipc.main() def stop(self): if self.ipc is None: raise Exception('Not started') self.ipc.off(self.on_window_focus) self.ipc.off(self.on_window_new) self.ipc.off(self.on_window_floating) for win in self.ipc.get_tree(): change_opacity(win, 1) self.ipc.main_quit() def enqueue_fade(self, win, start, target, duration): if win.id in self.fade_queue: f = self.fade_data[win.id] change = (self.frame_time / duration) * (target - f['opacity']) f['change'] = change f['target'] = target else: change_opacity(win, start) change = (self.frame_time / 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(): f = self.fade_data[win_id] 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']) self.fade_queue.remove(win_id) del self.fade_data[win_id] else: change_opacity(f['win'], f['opacity']) sleep(self.frame_time) self.fader_running = False def on_window_new(self, ipc, event): if event.container.type == 'floating_con': change_opacity(event.container, self.floating_opacity) else: change_opacity(event.container, self.inactive_opacity) self.new_win = event.container.id def on_window_floating(self, ipc, event): if event.container.id == self.current_win.id: self.current_win = event.container def on_window_focus(self, ipc, event): if self.current_win.id == event.container.id: return if self.current_win.type == 'floating_con': trans = self.floating_opacity else: trans = self.inactive_opacity if event.container.id == self.new_win: change_opacity(self.current_win, trans) change_opacity(event.container, self.active_opacity) else: self.enqueue_fade(self.current_win, self.active_opacity, trans, self.fade_time) if event.container.type == 'floating_con': self.enqueue_fade(event.container, self.floating_opacity, self.active_opacity, self.fade_time) else: self.enqueue_fade(event.container, self.inactive_opacity, self.active_opacity, self.fade_time) self.start_fader() self.current_win = event.container self.new_win = None
manual_layout = False def handler(i3, event): con = i3.get_tree().find_focused() floating = "_on" in con.floating full_screen = con.fullscreen_mode == 1 stacked = con.parent.layout == "stacked" tabbed = con.parent.layout == "tabbed" global manual_layout if event.change == "run" and "split" in event.binding.command: manual_layout = True should_update_layout = not (floating or full_screen or stacked or tabbed or manual_layout) if event.change == "focus": manual_layout = False if should_update_layout: new_layout = "splitv" if con.rect.height * 1.4 > con.rect.width else "splith" if new_layout != con.parent.layout: i3.command(new_layout) if __name__ == "__main__": i3 = Connection() i3.on(Event.WINDOW_FOCUS, handler) i3.on(Event.BINDING, handler) i3.main()
mark_set = False if len(con.nodes) == 1: place_node(con.nodes[0], new_con) elif con.nodes[1] != new_con: mark_set = format_and_mark(con.nodes[1]) elif len(con.nodes) >= 3: mark_set = format_and_mark(con.nodes[2]) if mark_set: wsp = new_con.workspace() new_con.command('move window to mark {}'.format(get_insert_mark(wsp))) new_con.command('focus') def on_window_new(self, e): def get_workspace(cnx, e): return cnx.get_tree().find_by_id(e.container.id).workspace() cnx = Connection() wsp = get_workspace(cnx, e) if not wsp: # This removes problems on i3 start return new_con = wsp.find_by_id(e.container.id) place_node(wsp, new_con) i3 = Connection() i3.on('window::new', on_window_new) i3.main()
from i3ipc import Connection, Event from i3_helper_common import State import Pyro4 import Pyro4.util import threading import sys import subprocess sys.excepthook = Pyro4.util.excepthook state = Pyro4.Proxy("PYRONAME:i3.state") def on_window_focus(i3, e): global state state.on_window_focus() def on_workspace_focus(i3, e): global state state.on_workspace_focus() if __name__ == "__main__": arguments = len(sys.argv) - 1 if arguments == 0: i3 = Connection() i3.on(Event.WINDOW_FOCUS, on_window_focus) i3.on(Event.WORKSPACE, on_window_focus) i3.main()
def main(): parser = argparse.ArgumentParser() parser.add_argument("-d", "--debug", action="store_true", help="print debug messages to stderr") parser.add_argument( "-v", "--version", action="version", version="%(prog)s {}, Python {}".format(__version__, sys.version), help="display version information", ) parser.add_argument( "-w", "--workspaces", help= "restricts autotiling to certain workspaces; example: autotiling --workspaces 8 9", nargs="*", type=str, default=[], ) """ Changing event subscription has already been the objective of several pull request. To avoid doing this again and again, let's allow to specify them in the `--events` argument. """ parser.add_argument( "-e", "--events", help= "list of events to trigger switching split orientation; default: WINDOW MODE", nargs="*", type=str, default=["WINDOW", "MODE"]) args = parser.parse_args() if args.debug and args.workspaces: print("autotiling is only active on workspaces:", ','.join(args.workspaces)) # For use w/ nwg-panel if args.workspaces: save_string(','.join(args.workspaces), os.path.join(temp_dir(), "autotiling")) if not args.events: print("No events specified", file=sys.stderr) sys.exit(1) handler = partial(switch_splitting, debug=args.debug, workspaces=args.workspaces) i3 = Connection() for e in args.events: try: i3.on(Event[e], handler) print("{} subscribed".format(Event[e])) except KeyError: print("'{}' is not a valid event".format(e), file=sys.stderr) i3.main()
if state_a.get(w, 0) != state_b.get(w, 0): changed.append(w) return changed # Store current window numbers of all workspaces global_state = get_window_nums() def on_window_change(i3, event): ws = i3.get_tree().find_by_id(event.container.id).workspace() global global_state global_state.update({ws.name: get_workspace_window_num(ws)}) on_window_num_change(ws.name) def on_window_move(i3, event): current_state = get_window_nums() global global_state changed = diff_state(global_state, current_state) global_state = current_state for ws in changed: on_window_num_change(ws) i3.on(Event.WINDOW_NEW, on_window_change) i3.on(Event.WINDOW_FLOATING, on_window_change) i3.on(Event.WINDOW_MOVE, on_window_move) i3.on(Event.WINDOW_CLOSE, on_window_move) i3.main()
#!/usr/bin/env python3 from i3ipc import Event, Connection def set_urgency_hint(c, e): window = c.get_tree().find_by_id(e.container.id) if window.workspace().id != c.get_tree().find_focused().workspace().id: window.command("urgent enable") c = Connection() c.on(Event.WINDOW_TITLE, set_urgency_hint) c.on(Event.WINDOW_NEW, set_urgency_hint) c.main()
def display_workspace(workspace): append = "" if last_urgent_workspace_name is not None: append = ' %{F#ad471c}(' + last_urgent_workspace_name + '*)%{F-}' print(" %s%s%s" % (workspace.name, " %{F#002b36}%{F-}" if workspace.focused else "", append), flush=True) def on_window_urgent(self, e): display_current_workspace() def on_workspace_urgent(self, e): display_current_workspace() i3.on(Event.WORKSPACE_FOCUS, on_workspace_focus) i3.on(Event.WORKSPACE_RENAME, on_workspace_focus) i3.on(Event.WINDOW_URGENT, on_window_urgent) i3.on(Event.WORKSPACE_URGENT, on_workspace_urgent) display_current_workspace() i3.main()
from i3ipc import Connection from subprocess import call def window_notify(i3, event): if event.container.fullscreen_mode == 0: call ('polybar-msg cmd show'.split()) else: call ('polybar-msg cmd hide'.split()) if event.change in ["focus", "title"]: call("polybar-msg hook titlehook 1".split(" ")) def window_ws_notify(i3, event): if event.change in ["title", "focus"]: call('polybar-msg hook wshook 1'.split()) def ws_notify(i3, event): if event.change == "focus": if event.old.num != -1: call('polybar-msg hook wshook 1'.split()) if __name__ == "__main__": i3 = Connection() i3.on('window', window_ws_notify) i3.on('workspace', window_ws_notify) i3.main()
from subprocess import call i3 = Connection() def windownotify(i3, event): if event.container.fullscreen_mode == 0: call('polybar-msg cmd show'.split(' ')) else: call('polybar-msg cmd hide'.split(' ')) if event.change in "focus" "title": call('polybar-msg hook titlehook 2'.split(' ')) # print(event.container.fullscreen_mode) def wsnotify(i3, event): if event.change == "focus": if event.old.num != -1: call('polybar-msg hook wshook 1'.split(' ')) call('wswpswitcher'.split(' ') + [format(event.current.num)]) # print(event.container.fullscreen_mode) i3.on('window', windownotify) i3.on('workspace', wsnotify) i3.main()
def main(): i3 = Connection() i3.on(Event.WINDOW_FOCUS, float_status) i3.on(Event.WORKSPACE_MOVE, float_status) i3.main()