def get_i3_connection(): '''Return a valid, cached i3 Connection instance ''' global conn if not conn: import i3ipc conn = i3ipc.Connection() try: conn.get_tree() except BrokenPipeError: import i3ipc conn = i3ipc.Connection() return conn
def main(): generate_keys() i3 = i3ipc.Connection() i3.on("mode", i3_mode_change) last_time = 0 focused_window = False logsocket = socket.socket(socket.AF_UNIX) logsocket.connect(sys.argv[1]) logsocket.setblocking(0) loglines = follow(logsocket, i3) settings = get_settings() for line in loglines: if line == None or len(line) == 0: continue if debug: print line try: data = json.loads(line) except: continue if debug: print data if data['event_type'] == 'focus_change': settings['state']['window_name'] = data['window_name'] if data['event_type'] == 'key': handle_modifiers(data, modifiers) if data['event_type'] == 'key': handle_event(data, settings,modifiers) continue
def main(workspace_name, get_index, visibility='invisible', *drek): get_index = int(get_index) conn = i3ipc.Connection() workspace = workspace_by_name(conn, workspace_name) # Find workspace. if workspace == None: print("Workspace not found") exit(1) windows = workspace.leaves() # Find windows in there. if visibility=='visible': windows = filter(window_is_visible, windows) elif visibility!='invisible': print("WARN: currently only support invisible and visible as selectors.") window = pick_from_list(list(windows), get_index) # Pick correct window from there. # conn.command("workspace " + workspace_name) # It already goes there. if window!=None: print("Focussing %d" % window.window) conn.command('[id="%d"] focus' % window.window) else: print("Did not find window(%d)"%get_index)
def on_window_focus(ipc, event): global prev_focused print("Got event") focused = event.container #if prev_focused and (True or prev_focused.app_id == 'termite'): # prev_focused.command('opacity 0.8') if True or focused.app_id == 'termite': tree = ipc.get_tree() focused = tree.find_by_id(focused.id) if focused: curent_workspace = focused.workspace() #from ipdb import set_trace; set_trace() for node in curent_workspace.descendants(): node.command('opacity 0.8') focused.command('opacity 1') print(f"last_focused: {prev_focused}, new: {focused}") if prev_focused and focused.id != prev_focused.id: current_layouts = { i.identifier: i.xkb_active_layout_index for i in ipc.get_inputs() } id_to_layouts[prev_focused.id] = current_layouts ipc = i3ipc.Connection() for l in current_layouts: try: ipc.command( f'input {l} xkb_switch_layout {id_to_layouts[focused.id][l]}' ) except KeyError: pass prev_focused = focused
def run(self, queue=None): polling_interval = self.__params['polling'] self.__queue = queue try: sway_ipc = sway.Connection() except: logger.error('Cannot find sway socket, exiting.') raise while True: sway_outputs = sway_ipc.get_outputs() #pprint(sway_outputs) # for now only first display is handled if len(sway_outputs) > 0: if (self.h != sway_outputs[0].rect.height or self.w != sway_outputs[0].rect.width): self.w = sway_outputs[0].rect.width self.h = sway_outputs[0].rect.height logger.info("Resolution changed w: {} h: {}".format( self.w, self.h)) # reporting only resolution of first display, in future we might need to compile "global" resolution based on position of displays and it sizes if (self.__queue): self.__queue.put({ field.EVENT: event.SCREEN_RESOLUTION, field.WIDTH: self.w, field.HEIGHT: self.h }) sleep( polling_interval ) # get screen resolution once per minute (do we actually need to get it repeatedly? We might need to report resolution changes to server.
def i3ipc_thread(use_ws=False, use_title=False): try: i3 = i3ipc.Connection() # conf = i3.get_bar_config("status") if renderer is not None: # "outputs" is not returned by i3ipc # if "outputs" in conf.keys(): # renderer.set_outputs(conf["outputs"]) if use_ws: renderer.update_workspace(i3.get_workspaces()) if use_title: renderer.clear_title() renderer.update_outputs(i3.get_outputs()) thread_render() if use_ws: i3.on("workspace", on_change_ws) if use_title: i3.on("window", on_change_title) i3.on("output", on_change_output) i3.main() thread_die("connection to i3 lost.") except Exception as e: thread_die(exception=e)
def i3(self): process = Popen(['i3', '-c', 'test/i3.config']) # wait for i3 to start up tries = 0 while True: try: IpcTest.i3_conn = i3ipc.Connection() break except Exception: tries += 1 if tries > 1000: raise Exception('could not start i3') time.sleep(0.01) yield IpcTest.i3_conn try: tree = IpcTest.i3_conn.get_tree() for l in tree.leaves(): l.command('kill') IpcTest.i3_conn.command('exit') except OSError: pass process.kill() IpcTest.i3_conn = None
def main(): parser = argparse.ArgumentParser() parser.add_argument("-c", "--compat", action="store_true", help="Output compatible with i3tree") parser.add_argument("-w", "--workspace", type=str, nargs="*", help="Workspace to display") parser.add_argument("-f", "--focused", action="store_true", help="Display info for focused workspace") args = parser.parse_args() i3 = i3ipc.Connection() tree = i3.get_tree() if args.compat: i3tree_walk_tree(tree, 0) else: if args.focused: current_workspace = find_focused_workspace(i3).name args.workspace = [current_workspace] if not args.workspace else \ args.workspace + [current_workspace] walk_tree(tree, 0, filter_workspaces=args.workspace, mute=args.workspace is not None)
def toggle_pin( target = argv[1], left_margin = int(argv[2]), # 10 desired_width = int(argv[3]) # 450 ): i3 = i3ipc.Connection() current_workspace = i3.get_tree().find_focused().workspace() windows = { "tabs_outliner" : pinnable_window(i3, "tabs_outliner"), "rover" : pinnable_window(i3, "rover") } other = { "tabs_outliner" : "rover", "rover" : "tabs_outliner" } other = windows[other[target]] target = windows[target] if other.is_running and (other.window.workspace().name == current_workspace.name): other.window.command("move scratchpad") if target.is_running and (target.window.workspace().name == current_workspace.name): target.window.command("move scratchpad") return if not target.is_running: target.start() pin(target, current_workspace, left_margin, desired_width)
def main(stdscr): ipc = i3ipc.Connection() def on_event(ipc, e): txt = '' for ws in ipc.get_tree().workspaces(): txt += container_to_text(ws, 0) + '\n' global last_txt if txt == last_txt: return stdscr.clear() for l in txt: try: stdscr.addstr(l) except Exception: break stdscr.refresh() last_txt = txt on_event(ipc, None) ipc.on('window', on_event) ipc.on('binding', on_event) ipc.on('workspace', on_event) ipc.main()
def __init__(self): self.conn = i3ipc.Connection() # Subscribe to Events self.conn.on('mode', self.on_mode) self.conn.on('workspace', self.on_workspace)
def workspaces(pl, only_show=None, output=None, strip=0): '''Return list of used workspaces :param list only_show: Specifies which workspaces to show. Valid entries are ``"visible"``, ``"urgent"`` and ``"focused"``. If omitted or ``null`` all workspaces are shown. :param str output: If specified, only workspaces on this output are shown. :param int strip: Specifies how many characters from the front of each workspace name should be stripped (e.g. to remove workspace numbers). Defaults to zero. Highlight groups used: ``workspace`` or ``w_visible``, ``workspace`` or ``w_focused``, ``workspace`` or ``w_urgent``. ''' global conn if not conn: try: import i3ipc except ImportError: import i3 as conn else: conn = i3ipc.Connection() return [{ 'contents': w['name'][min(len(w['name']), strip):], 'highlight_groups': calcgrp(w) } for w in conn.get_workspaces() if (not only_show or any( w[typ] for typ in only_show)) and (not output or w['output'] == output)]
def focus_i3(): if have_i3: regex = w.config_get_plugin("title.regex") i3conn = i3.Connection() weechat = i3conn.get_tree().find_named(regex)[0] weechat.command('focus')
def update_state(i3, e): t = timer.start("update_state") global last_update if not global_updates_running: return False if time.time() - last_update < float( args.interval if args.interval else 1): return False last_update = time.time() root = i3.get_tree() deleted = [] for num in global_knowledge.keys(): if type(num) is int and num not in [w.num for w in root.workspaces()]: deleted += [num] for num in deleted: del (global_knowledge[num]) current_workspace = root.find_focused().workspace() update_workspace(current_workspace) t.stop() screenshot = grab_screen() if current_workspace.num == i3ipc.Connection().get_tree().find_focused( ).workspace().num: global_knowledge[current_workspace.num]['screenshot'] = screenshot
def main(rofi_args=sys.argv[1:]): command_line = "rofi -dmenu -i -markup-rows -p '> '" i3 = i3ipc.Connection() pink = "w{} d{:<4} |<span color='pink'> {}</span>" yellow = "w{} d{:<4} |<span color='yellow'> {}</span>" coll = collections.deque() t = i3.get_tree() f = t.find_focused() for w, n in zip(t.leaves(), range(len(t.leaves()))): if f.id == w.id: coll.appendleft( (w.id, yellow.format(n + 1, w.workspace().name, w.name))) elif w.workspace().id == f.workspace().id: coll.appendleft( (w.id, pink.format(n + 1, w.workspace().name, w.name))) else: coll.append( (w.id, "w{} d{:<4} | {}".format(n + 1, w.workspace().name, w.name))) rofi = Menu(split(command_line) + rofi_args) result = rofi(collections.OrderedDict((v, k) for k, v in coll)) f = t.find_by_id(result.value) f.command('focus')
def __init__(self, engine, config): super(Module, self).__init__( engine, config ) # parsing of parameters self._scroll = bumblebee.util.asbool(self.parameter("scroll", False)) self._max = int(self.parameter("max", 64)) self._placeholder = self.parameter("placeholder", "...") # set output of the module self.widgets(bumblebee.output.Widget(full_text= self._scrolling_focused_title if self._scroll else self._focused_title)) # create a connection with i3ipc try: self._i3 = i3ipc.Connection() # event is called both on focus change and title change self._i3.on("window", lambda _p_i3, _p_e: self._pollTitle()) # begin listening for events threading.Thread(target=self._i3.main).start() except: pass # initialize the first title self._pollTitle()
def restore(workspace_name, saved_programs): """ Restore the running programs from an i3 workspace. """ # Remove already running programs from the list of program to restore. running_programs = get_programs(workspace_name, False) for program in running_programs: if program in saved_programs: saved_programs.remove(program) i3 = i3ipc.Connection() for entry in saved_programs: cmdline = entry['command'] working_directory = entry['working_directory'] # If the working directory does not exist, set working directory to # user's home directory. if not Path(working_directory).exists(): working_directory = Path.home() # If cmdline is array, join it into one string for use with i3's exec # command. if isinstance(cmdline, list): # Quote each argument of the command in case some of them contain # spaces. cmdline = [f'\\"{arg}\\"' for arg in cmdline if arg != ''] command = ' '.join(cmdline) else: command = cmdline # Execute command via i3 exec. i3.command(f'exec "cd \\"{working_directory}\\" && {command}"')
def main(args): conn = i3ipc.Connection() workspace = workspace_by_name(conn, args.workspace) # Find workspace. if workspace == None: print("Workspace not found, making it.") conn.command("workspace " + args.workspace) else: windows = workspace.leaves() # Find windows in there. if args.filter == 'visible': windows = filter(window_is_visible, windows) elif args.filter != 'none': print("WARN: currently only support `visible` as window filter.") window = pick_from_list(list(windows), args.nth) # Pick correct window from there. if window != None: print("Focussing %d" % window.window) conn.command('[id="%d"] focus' % window.window) else: print("Did not find window(%d) going to workspace anyway." % args.nth) conn.command("workspace " + args.workspace) if args.mode != 'no': conn.command("mode " + args.mode)
def update_state(i3, e): global last_update if not global_updates_running: return False if time.time() - last_update < 0.1: return False last_update = time.time() root = i3.get_tree() deleted = [] for num in global_knowledge.keys(): if type(num) is int and num not in [w.num for w in root.workspaces()]: deleted += [num] for num in deleted: del (global_knowledge[num]) current_workspace = root.find_focused().workspace() update_workspace(current_workspace) screenshot = grab_screen() #time.sleep(0.5) if current_workspace.num == i3ipc.Connection().get_tree().find_focused( ).workspace().num: global_knowledge[current_workspace.num]['screenshot'] = screenshot
def goto(char): i3 = i3ipc.Connection() workspaces = i3.get_workspaces() focused = i3.get_tree().find_focused() char_wp = [] for wp in workspaces: if wp["name"].lower().startswith(char): char_wp.append(wp) if len(char_wp) == 0: i3.command("workspace {}".format(char)) else: if not focused.workspace().name.startswith(char): i3.command("workspace {}".format(char_wp[0]["name"])) else: jump = False for wp in cycle(char_wp): if jump: i3.command("workspace {}".format(wp["name"])) exit(0) elif focused.workspace().name != wp["name"]: continue else: jump = True
def main(): connection = i3ipc.Connection() tree = connection.get_tree() args = parser() app, title, window_class = args.app, args.title, args.window_class if title: results = tree.find_named(title) elif window_class: results = tree.find_instanced(window_class) else: import sys sys.exit('Must either provide a -t/--tittle or a -c/--class') # if window is not found, open it if not results: cmd_open = f'i3-msg exec "{app}"' run(cmd_open) if title: while not title_exists(connection, title): time.sleep(0.01) window = title_exists(connection, title) elif window_class: while not class_exists(connection, window_class): time.sleep(0.01) window = class_exists(connection, window_class) window.command('move scratchpad, move position center') else: if title: command = f'i3-msg \\[title="{title}"\\] scratchpad show, move position center' elif window_class: command = f'i3-msg \\[instance="{window_class}"\\] scratchpad show, move position center' run(command)
def restore_workspace(workspace, numeric, directory, profile, target): """ Restore i3 workspace layout and programs. """ i3 = i3ipc.Connection() if workspace is None: workspace = i3.get_tree().find_focused().workspace().name directory = util.resolve_directory(directory, profile) if numeric and not workspace.isdigit(): util.eprint('Invalid workspace number.') sys.exit(1) # Get layout name from file. workspace_layout = layout.read(workspace, directory, profile) if 'name' in workspace_layout and profile is None: workspace_name = workspace_layout['name'] else: workspace_name = workspace # Switch to the workspace which we are loading. i3.command(f'workspace --no-auto-back-and-forth "{workspace_name}"') if target != 'programs_only': # Load workspace layout. layout.restore(workspace_name, workspace_layout) if target != 'layout_only': # Restore programs. saved_programs = programs.read(workspace, directory, profile) programs.restore(workspace_name, saved_programs)
def main(): i3 = i3ipc.Connection() p = 0 moddown = False for event in dev.read_loop(): if event.type == ecodes.EV_KEY: # left alt if event.code == 56: if event.value == 1: workspaces = i3.get_workspaces() p = startoverlay(workspaces) moddown = True elif event.value == 0 and p != 0: p.kill() p = 0 moddown = False # other than left alt (-> restart subprocess) else: if event.value == 1: if moddown: p.kill() # restart only if changing workspaces time.sleep(0.1) workspaces = i3.get_workspaces() p = startoverlay(workspaces)
def main(): args = build_parser().parse_args() i3 = i3ipc.Connection() event_filter = true_filter if args.run is not None: event_filter = combine_filters(event_filter, change_filter('run', not args.run)) if args.focus is not None: event_filter = combine_filters(event_filter, change_filter('focus', not args.focus)) if args.quiet: formatter = quiet_formatter else: formatter = json.dumps handler = Handler(formatter, event_filter) WORKSPACE = "workspace" types = set(("ipc_shutdown", WORKSPACE, "output", "mode", "window", "barconfig_update", "binding")) if args.workspace == True: types = set((WORKSPACE, )) elif args.workspace == False: types.remove(WORKSPACE) for name in types: i3.on(name, handler.handle) i3.main()
def main(): parser = argparse.ArgumentParser(__doc__) parser.add_argument("-config-path", help="Path to file that maps applications to icons in json format. Defaults to ~/.i3/app-icons.json or ~/.config/i3/app-icons.json or hard-coded list if they are not available.", required=False) parser.add_argument("-d", "--delimiter", help="The delimiter used to separate multiple window names in the same workspace.", required=False, default="|") parser.add_argument("-u", "--uniq", help="Remove duplicate icons in case the same application ", action="store_true", required=False, default=False) args = parser.parse_args() app_icons = _get_app_icons(args.config_path) # check for missing icons for app, icon_name in app_icons.items(): if not icon_name in icons: print("Specified icon '{}' for app '{}' does not exist!".format(icon_name, app)) # build i3-connection i3 = i3ipc.Connection() rename = build_rename(i3, app_icons, args.delimiter, args.uniq) for case in ['window::move', 'window::new', 'window::title', 'window::close']: i3.on(case, rename) i3.main()
def __init__( self, command, wm_class=None, wm_instance=None, wm_title=None, workspace=None, target_workspace=None, scratch=False, con_mark=None, ignore_case=False, event_time_limit=2, cycle=False, leave_fullscreen=False, ): self.command = command self.wm_class = wm_class self.wm_instance = wm_instance self.wm_title = wm_title self.workspace = workspace self.target_workspace = target_workspace or workspace self.scratch = scratch self.con_mark = con_mark self.ignore_case = ignore_case self.event_time_limit = event_time_limit self.cycle = cycle self.leave_fullscreen = leave_fullscreen self.regex_flags = [re.IGNORECASE] if self.ignore_case else [] self._check_args() self.i3 = i3ipc.Connection() self.tree = self.i3.get_tree() self.current_ws = self.get_current_workspace()
def move_container_to(id): print("move focused containter to workspace {}".format(id)) i3 = i3ipc.Connection() i3.command("move container to workspace {}".format(id)) if conf.getboolean('main', 'follow-container-on-move'): state['last_ws_id'] = state['current_ws_id'] display_workspace(id)
def generated_daemon(): workspace_policy = create_workspace_policy(disabled_during_pomodoro) i3 = i3ipc.Connection() i3_state = {"focused_workspace_name": get_focused_workspace(i3).name} i3.on('workspace::focus', handle_workspace_focus(i3, i3_state, workspace_policy, nagbar)) i3.main()
def i3_tracker_backend(): i3 = i3ipc.Connection() i3.on('workspace::focus', on_workspace_focus) i3.on("window::focus", on_window_focus) i3.on("window::title", on_window_title) i3.main()
def main(args): i3 = i3ipc.Connection() focused = i3.get_tree().find_focused() if focused.sticky and focused.floating.endswith('on'): focused.command('border normal, floating disable') else: focused.command('floating enable, sticky enable, border none') return 0