def rotate_workspaces_to_right_and_keep_ws_names(): # Get all visible workspace(s) - the workspace(s) currently visible on output(s) workspaces = i3.filter(i3.get_workspaces(), visible=True) # Get list containing num of the visible workspaces ws_names = [ ws['num'] for ws in workspaces ] # Get focused workspace id/name ws_focused = i3.filter(workspaces, focused=True)[0]['num'] # Get index of focused node in ws_names idx = ws_names.index(ws_focused) # Create a range that starts from the index of the focused node so the # focused output is the last to be rotated to the right. This results in # the focus to stay on the same output ws_range = [ index%len(ws_names) for index in range(idx-1,idx+len(ws_names)-1) ] # For each visible workspace for i in ws_range: # Set focus to workspace by id/name i3.workspace( str(ws_names[i]) ) # Move focused workspace to output on the right i3.command('move workspace to output right')
def _resize(self, pct, orientation): self.enable_focus() w = workspaces.get_current_workspace() w_orientation_size = w["rect"][orientation] expected_orientation_size = pct * w_orientation_size id, child = self.get_current_i3_container() child = child["raw"] c_orientation_size = child["rect"][orientation] px = expected_orientation_size - c_orientation_size action = "grow" if px < 0: px = -px action = "shrink" ppt = int(100 * (px / w_orientation_size)) px = int(px) i3.command("resize", action, orientation, "{}".format(px), "px", "or", "{}".format(ppt), "ppt")
def cycle(window_exe, window_title, window_class): current = i3.filter(nodes=[], focused=True) try: current_title = current[0]["window_properties"]["title"] current_class = current[0]["window_properties"]["class"] # There are not this parameters in current # That happens when trying to run a program in a empty workspace except: i3.command('exec', window_exe) return if current_class == window_class or current_title == window_title: return else: other = i3.filter(nodes=[], focused=False) for window in other: try: this_window_title = window['window_properties']['title'] this_window_class = window['window_properties']['class'] if this_window_class == window_class or this_window_title == window_title: i3.focus(con_id=window['id']) return except: pass i3.command('exec', window_exe)
def create_next_workspace_on_output(): # Get all workspace(s) workspaces = i3.get_workspaces() # Current workspace current = [ws for ws in workspaces if ws['focused']][0] output = current['output'] # Get list containing num of the workspaces on current output ws_names = [ ws['num'] for ws in workspaces if ws['output'] == output ] # Set start and end 'num' for workspaces depending on setup of one or two # monitors if ( len(ws_names) == len(workspaces) ): # One monitor start = 1 end = 10 else: # Two monitors start = 1 if current['num'] < 6 else 6 end = start+5 # Create workspace on output with lowest available 'num' for k in range(start,end): if not k in ws_names: i3.command('workspace {}'.format(k)) break;
def migrate(src, dst, exclude=[]): workspaces = i3.get_workspaces() for w in workspaces: if w['name'] in exclude: continue if w['output'] != dst['name']: i3.workspace(w['name']) i3.command('move', 'workspace to output right')
def activate(*_): model, treeiter = tree.get_selection().get_selected() conid = model.get_value(treeiter, 1) if conid > -1: i3.command("[con_id={conid}] focus".format(conid=conid)) else: app_id = model.get_value(treeiter, 2) apps[app_id].launch() Gtk.main_quit()
def main(): ws = i3.get_workspaces() trpl = ws + ws + ws # three times, because if we're on workspace "10" then we need to be able to go two times forward for i, ws in enumerate(trpl): if not ws['focused']: continue next_ws = i + 1 if "10" in trpl[next_ws]['name']: next_ws += 1 i3.command('workspace', trpl[next_ws]['name'])
def activate(*_): model, treeiter = tree.get_selection().get_selected() conid = model.get_value(treeiter, 1) if conid > -1: i3.command("[con_id={conid}] focus".format(conid=conid)) elif model.get_value(treeiter, 2) == "EXIT": Gtk.main_quit() else: app_id = model.get_value(treeiter, 2) i3.command("exec %s" % apps[app_id].get_executable()) win.hide()
def launch_terminal(): """Launches terminal on output that has focus with profile""" focused_workspace = get_focused_workspace() focused_output = focused_workspace['output'] LOG.debug('Focused output: ' + focused_output) # Launch 'External' profile if not focused on main monitor profileArgs = [] if not focused_output.startswith('eDP'): profileArgs = ['--profile=External'] i3.command(*(['exec', 'terminator'] + profileArgs))
def insert_new_workspace(workspaces, name): new_index = 1 for workspace in workspaces: (w_index, w_name) = int(workspace[0]), workspace[3:] if w_name < name: new_index = w_index + 1 else: new_name = "%i: %s" % (w_index+1, w_name) i3.command('rename workspace "%s" to "%s"' % (workspace, new_name)) new_name = "%i: %s" % (new_index, name) return new_name
def i3exec(cmd, sleep=0.1, root=None): print "Execute: {}".format(cmd) with tempfile.NamedTemporaryFile("w") as temp: if root: temp.file.write("cd {}\n".format(root)) temp.file.write(cmd + "\n") temp.file.close() current_stats = os.stat(temp.name) os.chmod(temp.name, current_stats.st_mode | stat.S_IEXEC) i3.command("exec", temp.name) time.sleep(sleep)
def dock(): #check for pickle if os.path.exists(PATH): with open(PATH, 'rb') as savefile: workspace_mapping = pickle.load(savefile) #restore pickled active workspaces for workspace in workspace_mapping: i3.command('[workspace={}] move workspace to output {}'.format( workspace['name'], workspace['output'])) else: #TODO: use default workspace mapping pass
def undock(): workspaces = i3.get_workspaces() # check path if not os.path.exists(os.path.dirname(PATH)): os.mkdir(os.path.dirname(PATH)) # pickle workspaces with open(PATH, 'wb') as savefile: pickle.dump(workspaces, savefile) #move all workspaces to laptop for workspace in workspaces: i3.command('[workspace={}] move workspace to output {}'.format( workspace['name'], LAPTOP))
def main(): outputs = i3.get_outputs() workspaces = i3.get_workspaces() active_workspaces = [o['current_workspace'] for o in outputs if o['active'] is True] if len(active_workspaces) != 2: return focused_workspace = [w['num'] for w in workspaces if w['focused'] is True] active_workspaces.remove(str(focused_workspace[0])) i3.command('workspace', active_workspaces[0])
def sort_workspaces(): names = get_workspace_names() names = names.sort(key=lambda x: x[3:]) for i, name in enumerate(get_workspace_names()): if name[0].isdigit(): w_name = name[3:] new_name = "%i: %s" % (i+1, w_name) else: new_name = "%i: %s" % (i+1, name); print 'rename workspace "%s" to "%s"' % (name, new_name) if new_name != name: cmd = 'rename workspace "%s" to "%s"' % (name, new_name) i3.command(cmd)
def switch_workspace(opr, lower, upper): #increment or decrement the workspace new_ws=ops[opr](focused_ws_num(),1) #wrap around if necessary if new_ws > upper: new_ws = lower elif new_ws < lower: new_ws = upper cmd="workspace number %s" % new_ws i3.command(cmd)
def go_last_mode(self): # Current mode needs to be removed # Don't want it added on the stack again self.current_mode = None # Exit if no stack if self.mode_stack == []: self.log.debug( "No modes found to go back to entering default mode") i3.command('mode', "default") # Jump to the last mode on the stack else: last_mode = self.mode_stack.pop() self.log.debug("Going back to {0}".format(last_mode)) i3.command('mode', last_mode)
def positionWindow(): i3.scratchpad("show", instance="metask") workspace = [ws for ws in i3.get_workspaces() if ws['focused']][0] screen_w =str(workspace['rect']['width']) screen_h =str(workspace['rect']['height']) targetheight = str(workspace['rect']['height']/3) current = i3.filter(nodes=[], focused=True) i3.command("move","absolute","position","0",str(barHeight)) i3.command("resize","shrink","width",screen_w); i3.command("resize","shrink","height",screen_h); i3.command("resize","grow","width",screen_w); i3.command("resize","grow","height",targetheight);
def xmonify(): # get currently focused windows current = i3.filter(nodes=[], focused=True) # get unfocused windows other = i3.filter(nodes=[], focused=False) # focus each previously unfocused window for 0.5 seconds # The following is done in a hackish way as there is no way to wait for a # successfull ending of previous command for window in other: status = i3.focus(con_id=window['id']) status = i3.move('workspace temp') for window in current: status = i3.focus(con_id=window['id']) status = i3.move('workspace 1') counter = 0 for window in other: status = i3.focus(con_id=window['id']) status = i3.move('workspace 1') if counter == 0: status = i3.command("split", "v") counter += 1 for window in current: i3.focus(con_id=window['id'])
def xmonify(): # get currently focused windows current = i3.filter(nodes=[], focused=True) # get unfocused windows other = i3.filter(nodes=[], focused=False) # focus each previously unfocused window for 0.5 seconds # The following is done in a hackish way as there is no way to wait for a # successfull ending of previous command for window in other: status = i3.focus(con_id=window['id']) status = i3.move('workspace temp') for window in current: status = i3.focus(con_id=window['id']) status = i3.move('workspace 1') counter = 0 for window in other: status = i3.focus(con_id=window['id']) status = i3.move('workspace 1') if counter==0: status = i3.command("split", "v") counter += 1 for window in current: i3.focus(con_id=window['id'])
def change_workspace_000(num): LOG.debug('change_workspace_000') #LOG.debug('Want workspace:\n' + pformat(want_workspace)) # Get workspace we want to switch to want_workspace = get_workspace(num) if want_workspace is None: LOG.debug('Switching to workspace because it does not exist') #switch_workspace(num) return # Save workspace originally showing on want_workspace's output other_output = [outp for outp in get_active_outputs() if outp['name'] == want_workspace['output']][0] LOG.debug('Other_output=%s', other_output) other_workspace = [wk for wk in i3.get_workspaces() if wk['name'] == other_output['current_workspace']][0] LOG.debug('Other workspace:\n' + pformat(other_workspace)) # Check if wanted workspace is on focused output if focused_workspace['output'] == want_workspace['output']: LOG.debug('Wanted workspace already on focused output, ' 'switching as normal') switch_workspace(num) return # Check if wanted workspace is on other output if not want_workspace['visible']: LOG.debug('Workspace to switch to is on other output, not showing') # Switch to workspace on other output switch_workspace(num) LOG.debug('Wanted workspace is on other output') # Wanted workspace is visible, so swap workspaces swap_visible_workspaces(want_workspace, focused_workspace) # Focus other_workspace switch_workspace(other_workspace['num']) # Focus on wanted workspace i3.command('focus', 'output', original_output)
def shift_workspaces(count, right): """ Shift the workspaces. count : maximum shift allowed (typically between 0 and 9) right : reverse shift direction if True return : 0 on success, 1 on error """ # initial workspace setup workspaces = [None] * 10 for name in [w['name'] for w in get_workspaces()]: if name in ALLOWED : workspaces[int(name)-1] = name info('Initial workspaces={}' .format(workspaces)) # optimal workspace setup changes = [ws for ws in workspaces if ws!= None] info('Optimal workspaces={}' .format(changes)) # deduce swaps to make (considering count parameter) commits= [] offset = 10-len(changes) if right else 0 for index, ws in enumerate(changes): src, target = int(ws), index + 1 + offset if src != target: if right : final = src +(min(count,target - src)) else : final = src - (min(count,src - target)) commits.append( (src,final) ) # apply changes in right order if right: commits.reverse() try : for (src,final) in commits: info('Moving workspace {}->{}'.format(src, final)) command('rename workspace {} to {}'.format(src, final)) except i3Exception: critical('Communication with i3 failed') return 1 info('{} swaps were made.'.format(len(commits))) return 0
def i3_menu(self, event, data, subscription): if data[1] is True: # controls workspaces if 200 <= data[0] <= 207: i3.command('workspace {}'.format(data[0] - 199)) # menu for a to h buttons elif LETTER_BUTTONS.get(data[0]) is not None: self.mode = LETTER_BUTTONS.get(data[0]) if (self.mode == 'h'): self.quit() self.refresh_letter_buttons() self.refresh_grid() # menu for the normal buttons: behavior changes depending on menu and config file else: coord = [int(data[0] / 16), data[0] % 16] i3.command(self.json[self.mode][coord[0]][coord[1]])
def flip(single_column=False): focused_workspace = get_focused_workspace() focused_output = xinerama_number(focused_workspace) queue = [] for workspace in workspaces: workspace_output = xinerama_number(workspace) should_flip = (not single_column or focused_output % 2 == workspace_output % 2) if (should_flip): add_to_queue(workspace, queue) for command in queue: i3.command(command) # Restore focus to originally focused workspace # Race conditions apply where focus is lost on movement, so sleep! time.sleep(0.25) i3.focus("output " + get_target_output(focused_workspace))
def float_with_storage(workspaces): focused_window = my_filter(i3.get_tree()['nodes'])[0] window_class = focused_window['window_properties']['class'] if window_class != None and len(window_class) > 1: window_class += "\n" found = False lines = [] with open(floating_windows,'r+') as f: lines = f.readlines() print(repr(lines)) print(repr(window_class)) try: lines.remove(window_class) except ValueError: # couldn't remove since it wasn't there lines.append(window_class) print(repr(lines)) with open(floating_windows,'w') as f: f.writelines(lines) i3.command('floating', 'toggle') return
def float_with_storage(workspaces): focused_window = my_filter(i3.get_tree()['nodes'])[0] window_class = focused_window['window_properties']['class'] if window_class != None and len(window_class) > 1: window_class += "\n" found = False lines = [] with open(floating_windows, 'r+') as f: lines = f.readlines() print(repr(lines)) print(repr(window_class)) try: lines.remove(window_class) except ValueError: # couldn't remove since it wasn't there lines.append(window_class) print(repr(lines)) with open(floating_windows, 'w') as f: f.writelines(lines) i3.command('floating', 'toggle') return
def main(): parser = argparse.ArgumentParser( description='Utility for switching to unnumbered i3 workspaces ' 'using their relative position.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument( 'number', metavar='NUMBER', type=int, help='Number of the workspace to focus. Starting with 1.') parser.add_argument('-m', '--move', action='store_true', default=False, help='move') args = parser.parse_args() available_workspaces = get_available_workspaces() focused_output = i3.filter(focused=True)[0]['output'] command = get_command(args) i3.command(command, available_workspaces[focused_output][args.number])
def change_workspace(name): """ Switches to workspace num like xmonad. Always sets focused output to workspace num. If the workspace is on another output, then the workspaces are "shifted" among the outputs. """ # Allow for string or int type for argument #num = int(num) #LOG.debug('Switching to workspace %d', num) focused_workspace = get_focused_workspace() LOG.debug('Focused workspace:\n' + pformat(focused_workspace)) original_output = focused_workspace['output'] LOG.debug('Current output: %s', original_output) LOG.debug('Current ws: %s', focused_workspace['name']) # Check if already on workspace if ( focused_workspace['name'] == name ): LOG.debug('Already on correct workspace') return # Get workspace we want to switch to want_workspace = get_workspace_name(name) if want_workspace is None: LOG.debug('Workspace does not exist') return if ( focused_workspace['name'] == name ): LOG.debug('Already on correct workspace') return # Focus on wanted workspace i3.command('focus', 'output', original_output)
def cmd_behave_screen_edge(delay, quiesce, verbose): delay = delay / 1000 if delay > 0 else delay quiesce = quiesce / 1000 if quiesce > 0 else delay workspace_curr = get_workspace_curr() x_max, y_max = get_workspace_rects(workspace_curr) while True: edges = get_edge_or_corner(x_max, y_max) if not edges is None: workspaces = get_workspaces() workspaces_len = len(workspaces) logging.debug('workspaces length: %i' % workspaces_len) # Just only workspace, do nothing if workspaces_len <= 1: time.sleep(delay + quiesce) continue workspace_curr = get_workspace_curr(workspaces) x_max, y_max = get_workspace_rects(workspace_curr) logging.debug('edges: %s, workspace_curr: %s, workspaces_len: %s' % \ (edges, workspace_curr, workspaces_len)) next_for = workspace_switch_for(edges) logging.info('exec workspace %s' % next_for) if next_for: i3.command('workspace', next_for) x_new, y_new = new_mouse_location(edges, x_max, y_max) logging.debug('exec xdotool mousemove %i %i' % (x_new, y_new)) if x_new != -1 and y_new != -1: set_mouse_location(x_new, y_new) time.sleep(quiesce) continue time.sleep(delay)
def cmd_behave_screen_edge(delay, quiesce, verbose): delay = delay / 1000 if delay > 0 else delay quiesce = quiesce / 1000 if quiesce > 0 else delay while True: workspaces = i3.get_workspaces() workspaces_len = len(workspaces) logging.debug('workspaces length: %i' % workspaces_len) # Just only workspace, do nothing if workspaces_len <= 1: time.sleep(delay + quiesce) continue workspace_root = sorted(workspaces, key=lambda ws: ws['num'])[0] workspace_curr = [ws for ws in workspaces if ws['focused'] == True][0] x_max = workspace_root['rect']['width'] - 1 y_max = workspace_root['rect']['height'] - 1 edges = get_edge_or_corner(x_max, y_max) if not edges is None: logging.info('[OK] edges: %s, workspace_curr: %s, workspaces_len: %s' % \ (edges, workspace_curr, workspaces_len)) next = workspace_nth_next(edges, workspace_curr, workspaces_len) logging.debug('exec workspace %i' % next) if next != -1: i3.command('workspace', str(next)) x_new, y_new = new_mouse_location(edges, x_max, y_max) logging.debug('exec xdotool mousemove %i %i' % (x_new, y_new)) if x_new != -1 and y_new != -1: set_mouse_location(x_new, y_new) time.sleep(quiesce) continue time.sleep(delay)
def main(): outputs = i3.get_outputs() workspaces = i3.get_workspaces() # Only include outputs with active: True workspaces = [ o['current_workspace'] for o in outputs if o['active'] is True ] if len(workspaces) == 2: i3.command('workspace', workspaces[0]) i3.command('move', 'workspace to output down') # Hacky fix for race condition time.sleep(0.01) i3.command('workspace', workspaces[1]) i3.command('move', 'workspace to output up') elif len(outputs) < 2: print('Not enough outputs') else: print('Too many outputs')
def rotate_workspaces_to_right(): # Get all visible workspace(s) - the workspace(s) currently visible on output(s) workspaces = i3.filter(i3.get_workspaces(), visible=True) # Get list containing num of the visible workspaces ws_names = [ ws['num'] for ws in workspaces ] # Get focused workspace id/name ws_focused = i3.filter(workspaces, focused=True)[0]['num'] # Get index of focused node in ws_names idx = ws_names.index(ws_focused) # Create a range that starts from the index of the focused node so the # focused output is the last to be rotated to the right. This results in # the focus to stay on the same output ws_range = [ index%len(ws_names) for index in range(idx-1,idx+len(ws_names)-1) ] # Rename the first workspace to the temporary name i3.command('rename workspace {0} to {1}'.format(ws_names[idx],WS_TMP_NAME)) # For each visible workspace for i in ws_range: # Get name of workspace to be in focus ws_name = WS_TMP_NAME if i==idx else ws_names[i] # Set focus to workspace by id/name i3.workspace( str(ws_name) ) # Rename focused workspace to id/name of workspace to the right i3.command('rename workspace {0} to {1}'.format( ws_name, ws_names[(i+1) % len(ws_names)] ) ) # Move focused workspace to output on the right i3.command('move workspace to output right')
#!/usr/bin/env python import i3 outputs = i3.get_outputs() workspaces = i3.get_workspaces() # figure out what is on, and what is currently on your screen. workspace = list(filter(lambda s: s['focused']==True, workspaces)) output = list(filter(lambda s: s['active']==True, outputs)) # figure out the other workspace name other_workspace = list(filter(lambda s: s['name']!=workspace[0]['output'], output)) # send current to the no-active one i3.command('move', 'workspace to output '+other_workspace[0]['name'])
dmenu = subprocess.Popen(['/usr/bin/dmenu','-i','-l', str(l)], stdin=subprocess.PIPE, stdout=subprocess.PIPE) menu_str = '\n'.join(sorted(clients.keys())) # Popen.communicate returns a tuple stdout, stderr win_str = dmenu.communicate(menu_str.encode('utf-8'))[0].decode('utf-8').rstrip() return clients.get(win_str, None) def get_current_ws(): for o in i3.get_outputs(): if o['active']: return o['current_workspace'] if __name__ == '__main__': ws = get_current_ws() just_ws = None if len(sys.argv) != 2 else sys.argv[1] if just_ws == 'current': just_ws = int(ws) else: just_ws = int(just_ws) clients = i3clients(just_ws) win_id = win_menu(clients) if win_id: i3.focus(con_id=win_id) if win_id and just_ws: i3.command('move window to workspace ' + str(ws)) i3.command('workspace ' + str(ws))
def move_workspace(workspace, output): i3.command('workspace', workspace['name']) i3.command('move', 'workspace to output ' + output['name']) i3.command('workspace', workspace['name'])
import subprocess def get_workspace(): workspaces = i3.get_workspaces() for workspace in workspaces: if workspace['focused']: return workspace return None def dmenu_prompt(num): dmenu = subprocess.Popen([ '/usr/bin/dmenu', '-i', '-p', 'Type new workspace name: {0}:'.format(num) ], stdin=subprocess.PIPE, stdout=subprocess.PIPE) name = dmenu.communicate("")[0].decode().rstrip() return name if __name__ == '__main__': ws = get_workspace() name = dmenu_prompt(ws['num']) if not len(name): exit(0) print ws['name'] i3.command("rename workspace \"{0}\" to \"{1}: {2}\"".format( ws['name'], ws['num'], name))
def main(): parser = argparse.ArgumentParser(description='''quickswitch for i3''') parser.add_argument('-m', '--move', default=False, action="store_true", help="move window to the current workspace") mutgrp = parser.add_mutually_exclusive_group() mutgrp.add_argument('-s', '--scratchpad', default=False, action="store_true", help="list scratchpad windows instead of regular ones") mutgrp.add_argument('-w', '--workspaces', default=False, action="store_true", help="list workspaces instead of windows") mutgrp.add_argument('-e', '--empty', default=False, action='store_true', help='go to the next empty, numbered workspace') mutgrp.add_argument( '-r', '--regex', help='find the first window matching the regex and focus/move it') mutgrp.add_argument( '-g', '--degap', action='store_true', help='make numbered workspaces consecutive (remove gaps)') mutgrp.add_argument('-n', '--next', default=False, action='store_true', help='go to the next (numbered) workspace') mutgrp.add_argument('-p', '--previous', default=False, action='store_true', help='go to the previous (numbered) workspace') parser.add_argument('-d', '--dmenu', default='dmenu -b -i -l 20', help='dmenu command, executed within a shell') args = parser.parse_args() if not check_dmenu(): print("quickswitch requires dmenu.") print("Please install it using your distribution's package manager.") exit(1) # jumping to the next empty workspaces doesn't require going through all # the stuff below, as we don't need to call dmenu etc, so we just call it # here and exit if the appropriate flag was given. if args.empty: exit(*goto_workspace(next_empty())) # likewise for degapping... if args.degap: degap() exit(0) # ...and regex search... if args.regex: exit(0 if find_window_by_regex(args.regex, args.move) else 1) # ...as well as workspace cycling if args.next or args.previous: if not get_current_workspace().isdecimal: print("--next and --previous only work on numbered workspaces") exit(1) target_ws = cycle_numbered_workspaces(args.previous) if not args.move: exit(*goto_workspace(target_ws)) else: exit(*i3.command("move container to workspace {}".format( target_ws))) lookup_func = get_windows if args.scratchpad: lookup_func = get_scratchpad if args.workspaces: lookup_func = get_workspaces action_func = focus if args.move: action_func = move_window_here else: if args.scratchpad: action_func = get_scratchpad_window if args.workspaces: action_func = goto_workspace lookup = lookup_func() target = dmenu(lookup.keys(), args.dmenu) id_ = lookup.get(target) success = action_func(lookup.get(target)) if id_ is not None else False exit(0 if success else 1)
def move_window_to_workspace(target, follow=False): i3.command('move', 'container to workspace "%s"' % (str(target))) if follow: switch_to_workspace(target)
channel.setLevel(level) formatter = logging.Formatter('[%(levelname)s] %(message)s') channel.setFormatter(formatter) LOG.addHandler(channel) def get_focused_workspace(): """Get workspace that is currently focused""" actives = [wk for wk in i3.get_workspaces() if wk['focused']] assert len(actives) == 1 return actives[0] def launch_terminal(): """Launches terminal on output that has focus with profile""" focused_workspace = get_focused_workspace() focused_output = focused_workspace['output'] LOG.debug('Focused output: ' + focused_output) # Launch 'External' profile if not focused on main monitor profileArgs = [] if not focused_output.startswith('eDP'): profileArgs = ['--profile=External'] i3.command(*(['exec', 'terminator'] + profileArgs)) if __name__ == '__main__': i3.command('exec', 'terminator') #setup_logger(logging.DEBUG) #launch_terminal()
def main(): parser = argparse.ArgumentParser(description="""quickswitch for i3""") mutgrp_1 = parser.add_mutually_exclusive_group() mutgrp_1.add_argument("-m", "--move", default=False, action="store_true", help="move a chosen window to the current " "workspace or moves the current container " "to the selected workspace") mutgrp_1.add_argument("-j", "--journey", default=False, action="store_true", help="moves the current container to a " "chosen workspace or moves it to a new empty " "workspace with -e") mutgrp_2 = parser.add_mutually_exclusive_group() mutgrp_2.add_argument("-f", "--follow", default=False, action="store_true", help="Follow a moved container to the workspace it is moved to") mutgrp_2.add_argument("-F", "--followifempty", default=False, action="store_true", help="Follow a moved container to the workspace it is moved to " "if the current workspace is empty after moving") mutgrp_3 = parser.add_mutually_exclusive_group() mutgrp_3.add_argument("-s", "--scratchpad", default=False, action="store_true", help="list scratchpad windows instead of " "regular ones") mutgrp_3.add_argument("-w", "--workspaces", default=False, action="store_true", help="list workspaces instead of windows") mutgrp_3.add_argument("-e", "--empty", default=False, action="store_true", help="go to the first empty, numbered " "workspace. Use with -j to send current " "window to a new empty workspace") mutgrp_3.add_argument("-E", "--nextempty", default=False, action="store_true", help="go to the next empty, numbered " "workspace after the current one. Use " "with -j to send current window to a new " "empty workspace") mutgrp_3.add_argument("-r", "--regex", help="find the first window matching the " "regex and focus/move it. Finds the first " "matching workspace when used with -j") mutgrp_3.add_argument("-g", "--degap", action="store_true", help="make numbered workspaces consecutive " "(remove gaps), does not work with other arguments") mutgrp_3.add_argument("-n", "--next", default=False, action="store_true", help="go to the next (numbered) workspace") mutgrp_3.add_argument("-p", "--previous", default=False, action="store_true", help="go to the previous (numbered) workspace") mutgrp_3.add_argument("-u", "--urgent", default=False, action="store_true", help="go to the first window with the " "urgency hint set") mutgrp_3.add_argument("-l", "--launch", default=False, action="store_true", help="if input to dmenu doesn't match any " "given option, send the input to shell for " "interpretation") parser.add_argument("-C", "--ignore-classes", default="", help="comma separated list of window classes " "to ignore") parser.add_argument("-d", "--dmenu", default=default_dmenu_command, help="dmenu command, executed within a shell") parser.add_argument("-i", "--insensitive", default=False, action="store_true", help="make regexps case insensitive") parser.add_argument("-o", "--prompt", default=False, action="store_true", help="show a prompt in dmenu describing the " "action to perform") args = parser.parse_args() global follow follow = args.follow global follow_if_empty follow_if_empty = args.followifempty # jumping to the next empty workspaces doesn't require going through all # the stuff below, as we don't need to call dmenu etc, so we just call it # here and exit if the appropriate flag was given. if args.empty or args.nextempty: target_ws = first_empty() if args.empty else next_empty() if args.journey: sys.exit(*move_container_to_workspace(target_ws)) else: sys.exit(*goto_workspace(target_ws)) # likewise for degapping... if args.degap: degap() sys.exit(os.EX_OK) # initialize window_class_ignore_list if args.ignore_classes: set_ignore_class_list(args.ignore_classes) # ...and regex search... if args.regex: if args.journey: if find_workspace_by_regex(args.regex, args.insensitive): sys.exit(os.EX_OK) else: sys.exit(os.EX_NOTFOUND) else: if find_window_by_regex(args.regex, args.insensitive, args.move): sys.exit(os.EX_OK) else: sys.exit(os.EX_NOTFOUND) # ...as well as workspace cycling if args.next or args.previous: if not workspace_is_numbered(get_current_workspace()): print("--next and --previous only work on numbered workspaces") sys.exit(1) target_ws = cycle_numbered_workspaces(args.previous) if not args.move: sys.exit(*goto_workspace(target_ws)) else: sys.exit(*i3.command( "move container to workspace {}".format(target_ws))) if args.urgent: urgent_windows = i3.filter(urgent=True, nodes=[]) try: win_id = urgent_windows[0]["window"] focus(win_id) except IndexError: sys.exit(os.EX_SOFTWARE) sys.exit(os.EX_OK) if args.dmenu == default_dmenu_command and not check_dmenu(): print("quickswitch requires dmenu.") print("Please install it using your distribution's package manager.") sys.exit(os.EX_UNAVAILABLE) lookup_func = get_windows unit = "window" if args.scratchpad: lookup_func = get_scratchpad unit = "scratchpad" if args.workspaces: lookup_func = get_workspaces unit = "workspace" action_func = focus dmenu_prompt = "focus {}".format(unit) if args.move: action_func = move_window_here dmenu_prompt = "move container to this {}".format(unit) elif args.journey: lookup_func = get_workspaces action_func = move_container_to_workspace dmenu_prompt = "move container to workspace" else: if args.scratchpad: action_func = get_scratchpad_window dmenu_prompt = "focus {}".format(unit) if args.workspaces: action_func = goto_workspace dmenu_prompt = "focus {}".format(unit) lookup = lookup_func() dmenu_prompt_args = args.dmenu if args.prompt: dmenu_prompt_args += " -p '{}'".format(dmenu_prompt) target = dmenu(lookup.keys(), dmenu_prompt_args) ws_id = lookup.get(target) if not ws_id and args.workspaces: # For workspace actions, we want to enable users to create new # workspaces. Easily done by discarding the lookup result # and just use what dmenu handed us to begin with. ws_id = target if ws_id: action_func(ws_id) elif target and args.launch: subprocess.call(target, shell=True) sys.exit(os.EX_OK)
#!/usr/bin/python2.7 import i3 import sys # This replaces `workspace` in many cases in config. If the target workspace # already exists (read: has a client) it does nothing. Otherwise it spawns an # application defined by a CLI arg. target_workspace_name = sys.argv[1] run_if_empty = sys.argv[2] target_workspace_exists = False workspaces = i3.get_workspaces() for workspace in workspaces: if target_workspace_name == workspace['name']: target_workspace_exists = True break i3.command('workspace', target_workspace_name) if not (target_workspace_exists): i3.command('exec', run_if_empty)
#!/usr/bin/env python import i3 from utils.dmenu import dmenu workspaces = i3.get_workspaces() urgents = [] others = [] for workspace in workspaces: if workspace["urgent"]: urgents.append(workspace["name"]) else: others.append(workspace["name"]) urgents.sort() others.sort() workspace = dmenu(urgents + others).strip() i3.command("workspace", workspace)
#!/usr/bin/env python # https://gist.github.com/97-109-107/b70356670ae8309ffb4f import i3 outputs = i3.get_outputs() workspaces = i3.get_workspaces() # figure out what is on, and what is currently on your screen. workspace = list(filter(lambda s: s['focused']==True, workspaces)) output = list(filter(lambda s: s['active']==True, outputs)) # figure out the other workspace name other_workspace = list(filter(lambda s: s['name']!=workspace[0]['output'], output)) # send current to the no-active one i3.command('move', 'workspace to output '+other_workspace[0]['name'])
#!/usr/bin/python3 import i3 # retrieve only active outputs outputs = list(filter(lambda output: output["active"], i3.get_outputs())) current_ws = i3.filter(i3.get_workspaces(), focused=True)[0]["name"] for output in outputs: # set current workspace to the one active on that output i3.workspace(output["current_workspace"]) # ..and move it to the output to the right. # outputs wrap, so the right of the right is left ;) i3.command("move", "workspace to output right") i3.workspace(current_ws)
parser = argparse.ArgumentParser(description='switch to or move container to next or prev free workspace') parser.add_argument('action', nargs=1, choices=['switch', 'move']) parser.add_argument('direction', nargs=1, choices=['prev', 'next']) args = parser.parse_args() def focused(workspace): if workspace['focused']: return workspace workspaces = i3.get_workspaces() current_ws = filter(focused, workspaces)[0]['num'] ws_list = range(current_ws + 1, 11) + range(1, current_ws) if args.direction[0] == 'prev': ws_list.reverse() used_ws = [ws['num'] for ws in i3.get_workspaces()] try: ws = next(ws for ws in ws_list if ws not in used_ws) except StopIteration: sys.exit(3) if args.action[0] == 'switch': i3.command('workspace', str(ws)) else: i3.command('move container to workspace', str(ws))
def main(): parser = argparse.ArgumentParser(description="""quickswitch for i3""") mutgrp_1 = parser.add_mutually_exclusive_group() mutgrp_1.add_argument( "-m", "--move", default=False, action="store_true", help="move a chosen window to the current workspace. moves the current container to the selected workspace", ) mutgrp_1.add_argument( "-j", "--journey", default=False, action="store_true", help="moves the current container to a chosen workspace. Moves it to a new empty workspace with -e", ) mutgrp_2 = parser.add_mutually_exclusive_group() mutgrp_2.add_argument( "-s", "--scratchpad", default=False, action="store_true", help="list scratchpad windows instead of regular ones" ) mutgrp_2.add_argument( "-w", "--workspaces", default=False, action="store_true", help="list workspaces instead of windows" ) mutgrp_2.add_argument( "-e", "--empty", default=False, action="store_true", help="go to the first empty, numbered workspace. Use with -j to send current window to a new empty workspace", ) mutgrp_2.add_argument( "-E", "--nextempty", default=False, action="store_true", help="go to the next empty, numbered workspace after the current one. Use with -j to send current window to a new empty workspace", ) mutgrp_2.add_argument( "-r", "--regex", help="find the first window matching the regex and focus/move it. Finds the first matching workspace when used with -j", ) mutgrp_2.add_argument( "-g", "--degap", action="store_true", help="make numbered workspaces consecutive (remove gaps), does not work with other arguments", ) mutgrp_2.add_argument( "-n", "--next", default=False, action="store_true", help="go to the next (numbered) workspace" ) mutgrp_2.add_argument( "-p", "--previous", default=False, action="store_true", help="go to the previous (numbered) workspace" ) mutgrp_2.add_argument( "-N", "--next-any", type=int, metavar=("FIRST_WORKSPACE", "LAST_WORKSPACE"), nargs=2, help="go to the next (numbered) workspace, whether it's exists or not", ) mutgrp_2.add_argument( "-P", "--previous-any", type=int, metavar=("FIRST_WORKSPACE", "LAST_WORKSPACE"), nargs=2, help="go to the previous (numbered) workspace, whether it's exists or not", ) mutgrp_2.add_argument( "-u", "--urgent", default=False, action="store_true", help="go to the first window with the urgency hint set" ) parser.add_argument("-d", "--dmenu", default=default_dmenu_command, help="dmenu command, executed within a shell") parser.add_argument("-i", "--insensitive", default=False, action="store_true", help="make regexps case insensitive") args = parser.parse_args() # jumping to the next empty workspaces doesn't require going through all # the stuff below, as we don't need to call dmenu etc, so we just call it # here and exit if the appropriate flag was given. if args.empty: if args.journey: exit(*move_container_to_workspace(first_empty())) else: exit(*goto_workspace(first_empty())) if args.nextempty: if args.journey: exit(*move_container_to_workspace(next_empty())) else: exit(*goto_workspace(next_empty())) # likewise for degapping... if args.degap: degap() exit(os.EX_OK) # ...and regex search... if args.regex: if args.journey: exit(os.EX_OK if find_workspace_by_regex(args.regex, args.insensitive) else os.EX_NOTFOUND) else: exit(os.EX_OK if find_window_by_regex(args.regex, args.insensitive, args.move) else os.EX_NOTFOUND) # ...as well as workspace cycling if args.next or args.previous: if not workspace_is_numbered(get_current_workspace()): print("--next and --previous only work on numbered workspaces") exit(1) target_ws = cycle_numbered_workspaces(args.previous) if not args.move: exit(*goto_workspace(target_ws)) else: exit(*i3.command("move container to workspace {}".format(target_ws))) if args.next_any or args.previous_any: if not workspace_is_numbered(get_current_workspace()): print("--next and --previous only work on numbered workspaces") exit(1) previous = args.next_any is None target_ws = cycle_all_numbered_workspaces(previous, args.previous_any if previous else args.next_any) if not args.move: exit(*goto_workspace(target_ws)) else: exit(*i3.command("move container to workspace {}".format(target_ws))) if args.urgent: urgent_windows = i3.filter(urgent=True, nodes=[]) try: window_id = urgent_windows[0]["window"] focus(window_id) except IndexError: exit(os.EX_SOFTWARE) exit(os.EX_OK) if args.dmenu == default_dmenu_command and not check_dmenu(): print("quickswitch requires dmenu.") print("Please install it using your distribution's package manager.") exit(os.EX_UNAVAILABLE) lookup_func = get_windows if args.scratchpad: lookup_func = get_scratchpad if args.workspaces: lookup_func = get_workspaces action_func = focus if args.move: action_func = move_window_here elif args.journey: lookup_func = get_workspaces action_func = move_container_to_workspace else: if args.scratchpad: action_func = get_scratchpad_window if args.workspaces: action_func = goto_workspace lookup = lookup_func() target = dmenu(lookup.keys(), args.dmenu) id_ = lookup.get(target) if not id_ and args.workspaces: # For workspace actions, we want to enable users to create new # workspaces. Easily done by discarding the lookup result # and just use what dmenu handed us to begin with. id_ = target action_func(id_) if id_ else False exit(os.EX_OK)
#!/usr/bin/python2.7 import i3 outputs = i3.get_outputs() # set current workspace to output 0 i3.workspace(outputs[0]['current_workspace']) # ..and move it to the other output. # outputs wrap, so the right of the right is left ;) i3.command('move', 'workspace to output right') # rinse and repeat i3.workspace(outputs[1]['current_workspace']) i3.command('move', 'workspace to output right')
if workspace['focused']: return workspace return None def dmenu_prompt(num): script = expanduser('~/.config/i3/bin/make-menu') dmenu = subprocess.Popen([ script, '-m', '-h', '50', '-p', 'Type new workspace name: {0}: '.format(num), # prompt '-f', 'Ubuntu 12' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE ) name = dmenu.communicate("")[0].decode().rstrip() return name if __name__ == '__main__': ws = get_workspace() name = dmenu_prompt(ws['num']) if not len(name): exit(0) print(ws['name']) i3.command("rename workspace \"{0}\" to \"{1}: {2}\"".format( ws['name'], ws['num'], name ))
args = parser.parse_args() def focused(workspace): if workspace['focused']: return workspace workspaces = i3.get_workspaces() current_ws = filter(focused, workspaces)[0]['num'] ws_list = range(current_ws + 1, 11) + range(1, current_ws) if args.direction[0] == 'prev': ws_list.reverse() used_ws = [ws['num'] for ws in i3.get_workspaces()] try: ws = next(ws for ws in ws_list if ws not in used_ws) except StopIteration: sys.exit(3) if args.action[0] == 'switch': i3.command('workspace', str(ws)) else: i3.command('move container to workspace', str(ws)) # Switch to the new workspace. i3.command('workspace', str(ws))
import i3 import pprint # spaces = i3.get_workspaces() def outputs(): puts = i3.get_outputs() act = [item for item in puts if item['active']] s = sorted(act, key=lambda x: x['rect']['x']) return s outs = outputs() # pprint.pprint(outs) c = outs[0]['current_workspace'] pprint.pprint(c) many = len(outs) spaces = 10/many current = 1 for output in outs: for i in xrange(spaces): print output['name'] print current i3.workspace(str(current)) i3.command('move', 'workspace to output ' + output['name']) current += 1 i3.workspace(c)
def goto_next_workspace(): current_workspace = get_current_workspace() i3.command('workspace number {0}'.format( get_next_workspace(current_workspace)))
logging.info("current task: %s" % task) ws = task['workspace'] layout = task['layout'] progs = task['progs'] x = layout2arr(layout) r = step(x, horizontal, vertical) logging.info("path: %s", r) if r[0]: #print r op = [("exec", progs[x[0,0]-1])] op.extend(i3conv(r[1],x.shape[1], x.shape[0], progs)) logging.info("result: %s", op) if not simulate: i3.command("workspace", ws) time.sleep(0.1) for i in op: logging.debug("next op: %s", i) if not simulate: i3.command(i[0],i[1]) if i[0] == "exec": time.sleep(0.5) else: time.sleep(0.1) else: print "ERROR: No path found for layout!" print layout if __name__ == "__main__":
#!/usr/bin/python2.7 import i3 outputs = i3.get_outputs() # Move all workspace to the right, if output is active for i in range(len(outputs)): if (outputs[i]['active'] == True): i3.workspace(outputs[i]['current_workspace']) i3.command('move workspace to output right')
def main(): parser = argparse.ArgumentParser(description='''quickswitch for i3''') parser.add_argument('-m', '--move', default=False, action="store_true", help="move window to the current workspace") mutgrp = parser.add_mutually_exclusive_group() mutgrp.add_argument('-s', '--scratchpad', default=False, action="store_true", help="list scratchpad windows instead of regular ones") mutgrp.add_argument('-w', '--workspaces', default=False, action="store_true", help="list workspaces instead of windows") mutgrp.add_argument('-e', '--empty', default=False, action='store_true', help='go to the next empty, numbered workspace') mutgrp.add_argument('-r', '--regex', help='find the first window matching the regex and focus/move it') mutgrp.add_argument('-g', '--degap', action='store_true', help='make numbered workspaces consecutive (remove gaps)') mutgrp.add_argument('-n', '--next', default=False, action='store_true', help='go to the next (numbered) workspace') mutgrp.add_argument('-p', '--previous', default=False, action='store_true', help='go to the previous (numbered) workspace') parser.add_argument('-d', '--dmenu', default='dmenu -b -i -l 20', help='dmenu command, executed within a shell') args = parser.parse_args() if not check_dmenu(): print("quickswitch requires dmenu.") print("Please install it using your distribution's package manager.") exit(1) # jumping to the next empty workspaces doesn't require going through all # the stuff below, as we don't need to call dmenu etc, so we just call it # here and exit if the appropriate flag was given. if args.empty: target_ws=next_empty() if not args.move: exit(*goto_workspace(target_ws)) else: exit(*i3.command("move container to workspace {}".format(target_ws))) # likewise for degapping... if args.degap: degap() exit(0) # ...and regex search... if args.regex: exit(0 if find_window_by_regex(args.regex, args.move) else 1) # ...as well as workspace cycling if args.next or args.previous: if not get_current_workspace().isdecimal: print("--next and --previous only work on numbered workspaces") exit(1) target_ws = cycle_numbered_workspaces(args.previous) if not args.move: exit(*goto_workspace(target_ws)) else: exit(*i3.command("move container to workspace {}".format(target_ws))) lookup_func = get_windows if args.scratchpad: lookup_func = get_scratchpad if args.workspaces: lookup_func = get_workspaces action_func = focus if args.move: action_func = move_window_here else: if args.scratchpad: action_func = get_scratchpad_window if args.workspaces: action_func = goto_workspace lookup = lookup_func() target = dmenu(lookup.keys(), args.dmenu) id_ = lookup.get(target) success = action_func(lookup.get(target)) if id_ is not None else False exit(0 if success else 1)
def move_workspace(source, dest): i3.command('rename', 'workspace "%s" to "%s"' % (str(source), str(dest)))
def swap_visible_workspaces(wk_a, wk_b): """Swaps two workspaces that are visible""" switch_workspace(wk_a['num']) i3.command('move', 'workspace to output ' + wk_b['output']) switch_workspace(wk_b['num']) i3.command('move', 'workspace to output ' + wk_a['output'])
def switch_to_workspace(target): i3.command('workspace "%s"' % (str(target)))
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import i3 from generate_bash import generate_bash from generate_i3 import generate_i3 from generate_i3bar import generate_i3bar from wallpaper import set_wallpaper if __name__ == "__main__": generate_bash() generate_i3bar() generate_i3() set_wallpaper() i3.command("reload")
def move_window_to_output(target): i3.command('move', 'window to output "%s"' % (str(target)))
#!/usr/bin/python3 import i3 from subprocess import call for w in i3.get_workspaces(): if w['focused']: cur_wks = w['name'] for w in i3.get_workspaces(): i3.workspace(w['name']) i3.command('move', 'workspace to output right') i3.command('workspace', cur_wks) for w in i3.get_workspaces(): if w['focused']: cur_output = w['output'] break call("xrandr --output {} --primary".format(cur_output), shell=True)