import os import time import json import psutil import subprocess from random import randint from threading import Thread import cusmodules.holiday #from cusmodules import holiday #from cusmodules.cuswidgets import fifo_ticker_gecko from cusmodules.cuswidgets import ticker_gecko from typing import List # noqa: F401 from libqtile import extension from libqtile.lazy import lazy from libqtile import layout, bar, widget, hook, qtile from libqtile.config import Key, KeyChord, Screen, Group, Drag, Click, DropDown, ScratchPad, Match from libqtile.utils import send_notification from libqtile.core.manager import Qtile from libqtile.backend.base import Window @hook.subscribe.startup_once def autostart(): home = os.path.expanduser('~') holiday = cusmodules.holiday.main() os.system(f'{home}/.config/qtile/cusmodules/wallpaper.py {holiday}') subprocess.Popen(f'{home}/.config/qtile/autostart.sh') @hook.subscribe.shutdown def shutdown(): home = os.path.expanduser('~') os.system(f"mpc -h {home}/.mpd/socket -p 6600 stop") mod = "mod4" home = os.path.expanduser('~') #term = 'st' term = 'alacritty' browser = 'librewolf' privatebrowser = f'{browser} --private-window' mpc = f"mpc -h {home}/.mpd/socket -p 6600" pythonlogo = '/tmp/python.png' terms = ['st', 'kitty', 'cool-retro-term', 'Alacritty'] terminal_windows = [] swallowed_wins = [] pinned_wins = [] fast_swallowed = None def pyimage(home): if os.path.isfile(pythonlogo): return pythonlogo else: return f'{home}/.config/qtile/pythonlogo.png' with open(f"{home}/.cache/wal/colors.json", 'r') as f: data = json.load(f) color = data["colors"] def isWhite(color): whites = [] h = color.strip('#') rgb = tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) for i in rgb: whites.append(i in range(235, 255)) if False in whites: return False else: return True def invColor(color): inv = () h = color.strip('#') rgb = tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) for i in rgb: g = 255 % i inv += (g,) invert = '%02x%02x%02x' % inv invcolor = f"#{invert}" return invcolor def highlight(ogcolor): h = color.get(ogcolor).strip('#') rgb = tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) rgb1, rgb2, rgb3 = rgb rgb1 = rgb1 +40 rgb2 = rgb2 +40 rgb3 = rgb3 +40 rgb4 = (rgb1, rgb2, rgb3) tohex = '%02x%02x%02x' % rgb4 return tohex def inactive(ogcolor): h = color.get(ogcolor).strip('#') rgb = tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) rgb1, rgb2, rgb3 = rgb rgb1 = rgb1 +64 rgb2 = rgb2 +64 rgb3 = rgb3 +64 rgb4 = (rgb1, rgb2, rgb3) tohex = '%02x%02x%02x' % rgb4 tohex = '#' + tohex return tohex layouts = [ layout.MonadTall(margin = 10, border_focus = color.get('color14'), border_normal = color.get('color0')), layout.Max(), layout.Stack(margin = 6, border_focus = color.get('color14'), border_normal = color.get('color0'), num_stacks=1), # Try more layouts by unleashing below layouts. # layout.Bsp(margin = 10, border_focus = '#00FFFF'), layout.Columns(margin = 6, border_focus = color.get('color14'), border_normal = color.get('color0')), layout.Matrix(margin = 6, border_focus = color.get('color14'), border_normal = color.get('color0')), layout.MonadWide(margin = 10, border_focus = color.get('color14'), border_normal = color.get('color0')), # layout.RatioTile(), # layout.Tile(), layout.TreeTab(sections = [''], active_bg = color.get('color14'), inactive_bg = color.get('color8'), bg_color = color.get('color6')), layout.Floating(border_focus = color.get('color14'), border_normal = color.get('color0')), # layout.VerticalTile(), # layout.Zoomy(), ] def reload_conf_cmd(qtile): qtile.reload_config() def pin_win(qtile): global pinned_wins if qtile.current_window in pinned_wins: pass else: pinned_wins.append(qtile.current_window) #with open('/tmp/wins.dict', 'w') as f: # f.write(str(qtile.current_window)) def unpin_win(qtile): global pinned_wins pinned_wins.remove(qtile.current_window) def move_floating(qtile, xMod, yMod): x = qtile.current_window.get_position()[0] + xMod y = qtile.current_window.get_position()[1] + yMod qtile.current_window.set_position_floating(x, y) with open('/tmp/wins.dict', 'w') as f: f.write(str(qtile.current_window.get_position())) def resize_floating(qtile, xMod, yMod): x = qtile.current_window.get_size()[0] + xMod y = qtile.current_window.get_size()[1] + yMod qtile.current_window.set_size_floating(x, y) #qtile.current_window.resize_floating(1, 1) def fast_swallow(qtile): #global fast_swallowed #qtile.current_window = fast_swallowed #with open('/tmp/test.txt', 'w') as f: #f.write(str(dir(qtile.groups))) #f.write(str(dir(qtile.groups[10].windows))) #f.write(str(qtile.groups[10].windows)) #f.write(str(qtile.groups().get('swallow'))) qtile.current_window.togroup('swallow') #qtile.current_window.hide() def fast_unswallow(qtile): for i in qtile.groups[10].windows: i.togroup(qtile.current_group.name) def cycle_float(qtile, direc): pass # floating_wins = [] # # for window in qtile.current_group.windows: # if window.floating: # floating_wins.append(window) # # if not floating_wins: # return # # try: # win = floating_wins[floating_wins.index(qtile.current_window) + direc] # win.focus() # # except: # pass #def debug_key(qtile): # #dic = dir(DropDown("vimpc", f"{term} -e vimpc -h {home}/.mpd/socket -p 6600", opacity=1).info) # dic = DropDown("vimpc", f"{term} -e vimpc -h {home}/.mpd/socket -p 6600", opacity=1).info() # # with open('/tmp/qtile_debug.py', 'w') as f: # f.write(str(dic)) @hook.subscribe.setgroup def move_pin(): global pinned_wins global qtile for i in pinned_wins: name = i.info()['name'] #if name in qtile.groups().get('swallow').get('windows'): # break i.togroup(str(qtile.current_group.name)) if 'mpv' in name: i.disable_floating() #with open('/tmp/wins.dict', 'w') as f: # f.write(str(qtile.groups().get('swallow').get('windows'))) @hook.subscribe.client_name_updated def defloat_mpv(c): name = c.info()['name'] if 'mpv' in name: c.disable_floating() @hook.subscribe.client_killed def un_swallow(c): global terms global pinned_wins global terminal_windows global swallowed_wins if c in pinned_wins: pinned_wins.remove(c) if name in terms: for i in terminal_windows: if c in i.values(): terminal_windows.remove(i) #with open('/tmp/wins.dict', 'w') as f: # f.write(str(terminal_windows)) else: for i in swallowed_wins: if c in i.values(): win_to_deswallow = i.get('swallowed') win_to_deswallow.togroup(c.info()['group']) swallowed_wins.remove(i) @hook.subscribe.client_managed def swallow(c): global term global terms global terminal_windows global swallowed_wins if str(c.get_wm_type()) == 'dialog': return 0 name = c.info()['name'] with open('/tmp/wins.dict', 'w') as f: f.write(name) #with open('/tmp/test.fifo', 'r') as f: # f.write(name) if 'mpv' in name: c.disable_floating() pid = c.window.get_net_wm_pid() if pid == None: pid = os.popen(f'pidof {name}').read().strip('\n').split(' ') pid = pid[0] term_pids = os.popen(f'pidof {term}').read().strip('\n').split(' ') pid = str(pid) ppid = str(psutil.Process(psutil.Process(int(pid)).ppid()).ppid()) try: if ppid in term_pids and ppid != 0: with open('/tmp/wins.dict', 'w') as f: f.write('skipping')#name))#.window.get_net_wm_pid())) else: ppid = str(psutil.Process(int(ppid)).ppid()) with open('/tmp/wins.dict', 'w') as f: f.write(str(ppid))#name))#.window.get_net_wm_pid())) except Exception as e: pass #with open('/tmp/wins.dict', 'w') as f: # f.write(str(ppid))#name))#.window.get_net_wm_pid())) if name in terms: terminal_windows.append({pid:c}) #os.system('kill -SIGKILL 84993') #with open('/tmp/wins.dict', 'w') as f: # f.write(str(terminal_windows))#name))#.window.get_net_wm_pid())) elif ppid == 1 or ppid == 0: return 0 else: for i in terminal_windows: if str(ppid) in i.keys(): swallowed_wins.append({'swallowed' : i.get(str(ppid)), 'swallowed_by': c}) win_to_swall = i.get(str(ppid)) win_to_swall.togroup('swallow') #f.write(str(swallowed_wins))#.window.get_net_wm_pid())) else: pass #with open('/tmp/wins.dict', 'w') as f: # f.write(f"{type(pid)}: {pid}\n{type(ppid)}: {ppid}\n{terminal_windows}\n{swallowed_wins}") keys = [ # Switch between windows Key([mod], "h", lazy.layout.left()), Key([mod], "l", lazy.layout.right()), Key([mod], "k", lazy.layout.up()), Key([mod], "j", lazy.layout.down()), # Move windows up or down in current stack Key([mod, "shift"], "h", lazy.layout.shuffle_left()), Key([mod, "shift"], "l", lazy.layout.shuffle_right()), Key([mod, "shift"], "k", lazy.layout.shuffle_up()), Key([mod, "shift"], "j", lazy.layout.shuffle_down()), Key([mod, "shift"], "space", lazy.layout.flip()), # Grow and shrink windows Key([mod, "control"], "k", lazy.layout.grow()), Key([mod, "control"], "j", lazy.layout.shrink()), # Move between Groups Key([mod, "mod1"], "k", lazy.screen.next_group()), Key([mod, "mod1"], "j", lazy.screen.prev_group()), # Sound Key([], "XF86AudioMute", lazy.spawn("amixer -q set Master toggle")), Key([], "XF86AudioLowerVolume", lazy.spawn("amixer -q sset 'Master' 2%- unmute")), Key([], "XF86AudioRaiseVolume", lazy.spawn("amixer -q sset 'Master' 2%+ unmute")), Key([], "XF86AudioPlay", lazy.spawn(f"{mpc} play")), Key([], "XF86AudioPause", lazy.spawn(f"{mpc} pause")), Key([], "XF86AudioPrev", lazy.spawn(f"{mpc} prev")), Key([], "XF86AudioNext", lazy.spawn(f"{mpc} next")), Key([mod], "m", lazy.spawn("amixer -q set Capture toggle"), lazy.spawn(f"{home}/.config/qtile/mic.sh")), Key([mod], "comma", lazy.spawn(f"{mpc} prev")), Key([mod, "shift"], "comma", lazy.spawn(f"{mpc} seek 0%")), Key([mod], "period", lazy.spawn(f"{mpc} next")), Key([mod, "shift"], "period", lazy.spawn(f"{mpc} repeat")), Key([mod, "shift"], "p", lazy.spawn(f"{mpc} toggle")), Key([mod], "bracketleft", lazy.spawn(f"{mpc} seek -10")), Key([mod], "bracketright", lazy.spawn(f"{mpc} seek +10")), Key([mod, "shift"], "bracketleft", lazy.spawn(f"{mpc} seek -60")), Key([mod, "shift"], "bracketright", lazy.spawn(f"{mpc} seek +60")), Key([mod, "control"], "bracketleft", lazy.spawn(f"{mpc} volume -5")), Key([mod, "control"], "bracketright", lazy.spawn(f"{mpc} volume +5")), Key([mod, "control"], "e", lazy.spawn(f"{home}/hammer.sh")), # Toggle between different layouts as defined below Key([mod], "Tab", lazy.next_layout()), Key([mod, "shift"], "f", lazy.window.toggle_floating()), Key([mod], "space", lazy.window.toggle_fullscreen()), # Close Windows Key([mod], "w", lazy.window.kill()), # Qtile Actions Key([mod, "control"], "r", lazy.restart()), Key([mod, "control"], "q", lazy.shutdown()), Key([mod], "b", lazy.hide_show_bar("top")), # Programs and misc actions Key([mod], "Return", lazy.spawn(term)), Key([mod], "c", lazy.spawn("xterm")), Key([mod], "p", lazy.spawn("dmenu_run -p 'Run:'")), Key([mod], "r", lazy.group['scratchpad'].dropdown_toggle('term')), Key([mod, "control"], "p", lazy.group['vimpc'].dropdown_toggle('vimpc')), Key([mod], "i", lazy.spawn(f"{home}/.config/qtile/cusmodules/appimg.py")), Key([mod], "f", lazy.spawn(browser)), Key([mod, "shift"], "s", lazy.spawn("flameshot gui")), Key([mod, "control"], "f", lazy.spawn(privatebrowser)), Key([mod, "control"], "c", lazy.spawn(f"{home}/.config/qtile/cusmodules/colors.py")), Key([mod, "control"], "l", lazy.spawn(f'xautolock -locknow')), Key([mod, "mod1"], "l", lazy.spawn(f'xautolock -toggle')), Key([mod, "control"], "n", lazy.spawn(home + "/.config/qtile/cusmodules/wallpaper.py")), Key([mod], "z", lazy.function(reload_conf_cmd)), Key([mod, 'control'], "z", lazy.function(fast_unswallow)), Key([mod, 'shift'], "z", lazy.function(fast_swallow)), Key([mod], "n", lazy.function(pin_win)), Key([mod, 'shift'], "n", lazy.function(unpin_win)), #KeyChord([mod], "x", [ # Key([], "h", lazy.function(move_floating, -8, 0)), # Key([], "j", lazy.function(move_floating, 0, 8)), # Key([], "k", lazy.function(move_floating, 0, -8)), # Key([], "l", lazy.function(move_floating, 8, 0)), # Key(['shift'], "h", lazy.function(resize_floating, -8, 0)), # Key(['shift'], "j", lazy.function(resize_floating, 0, 50)), # Key(['shift'], "k", lazy.function(resize_floating, 0, -8)), # Key(['shift'], "l", lazy.function(resize_floating, 50, 0)), # Key([], "f", lazy.window.toggle_floating()), # Key([], "period", lazy.function(cycle_float, 1)), # Key([], "w", lazy.window.kill()), #], # name='Floating' #) #Key([mod], "y", lazy.window.togroup('scratchpad')), #Key([mod], "u", lazy.group['scratchpad'].toscreen()), #Key([mod], "x", lazy.function(pinned.append, lazy.window)), #Write to debug file #Key([mod, "shift", "control"], "d", lazy.function(debug_key)), ] group_names = [("I", {'layout': 'monadtall'}), ("II", {'layout': 'monadtall'}), ("III", {'layout': 'monadtall'}), ("IV", {'layout': 'monadtall'}), ("V", {'layout': 'monadtall'}), ("VI", {'layout': 'monadtall'}), ("VII", {'layout': 'monadtall'}), ("VIII", {'layout': 'monadtall'}), ("IX", {'layout': 'monadtall'})] groups = [Group(name, **kwargs) for name, kwargs in group_names] groups.append(ScratchPad('swallow')) groups.append(ScratchPad('hidden')) groups.append(ScratchPad("scratchpad", [ DropDown("term", term, opacity=1) ])) #groups.append(ScratchPad("vimpc", [ DropDown("vimpc", f"{term} -e vimpc -h {home}/.mpd/socket -p 6600", opacity=1, height=0.55) ])) groups.append(ScratchPad("vimpc", [ DropDown("vimpc", "ario", opacity=1, height=0.55) ])) groups.append(Group("X")) for i, (name, kwargs) in enumerate(group_names, 1): keys.append(Key([mod], str(i), lazy.group[name].toscreen())) # Switch to another group keys.append(Key([mod, "shift"], str(i), lazy.window.togroup(name))) # Send current window to another group keys.append(Key([mod, "control"], str(i), lazy.window.togroup(name), lazy.group[name].toscreen())) # Send current window to another group keys.append(Key([mod], 'u', lazy.group['swallow'].toscreen())) keys.append(Key([mod, 'shift'], 'u', lazy.window.togroup('swallow'))) keys.append(Key([mod, "control"], 'u', lazy.window.togroup("swallow"), lazy.group["swallow"].toscreen())) # Send current window to another group keys.append(Key([mod], 'y', lazy.group['hidden'].toscreen())) keys.append(Key([mod, 'shift'], 'y', lazy.window.togroup('hidden'))) keys.append(Key([mod, "control"], 'y', lazy.window.togroup("hiddden"), lazy.group["hidden"].toscreen())) # Send current window to another group keys.append(Key([mod], '0', lazy.group['X'].toscreen())) keys.append(Key([mod, 'shift'], '0', lazy.window.togroup('X'))) keys.append(Key([mod, "control"], '0', lazy.window.togroup('X'), lazy.group['X'].toscreen())) # Send current window to another group widget_defaults = { 'font': 'Nimbus Sans', 'fontsize': 13, 'padding': 2, } extension_defaults = widget_defaults.copy() lar = u'\ue0b2' rar = u'\ue0b0' plf = "Powerline Symbols" screens = [ Screen( top=bar.Bar( [ widget.Image( filename = pyimage(home), background = color.get('color7'), margin = 2, ), widget.TextBox( text=rar, background = color.get('color0'), foreground = color.get('color7'), font = plf, padding = 0, fontsize = 23 ), widget.GroupBox( margin_y = 6, margin_x = 0, padding_y = 5, padding_x = 3, borderwidth = 3, active = '#ffffff', inactive = inactive('color0'), rounded = False, highlight_method = "line", highlight_color = [color.get('color0').strip('#'), highlight('color0')], background = color.get('color0'), this_current_screen_border = color.get('color6'), ), widget.TextBox( text=rar, foreground = color.get('color0'), font = plf, padding = 0, fontsize = 23 ), widget.Spacer( length=550 ), widget.TextBox( text=u'\ue0ba', foreground = color.get('color0'), padding = -0.5, fontsize = 26 ), widget.Mpd2( host=f"{home}/.mpd/socket", status_format='{play_status} {artist} - {title} [{elapsed}/{duration}] | {volume}%', background = color.get('color0') ), widget.TextBox( text=u'\ue0bc', foreground = color.get('color0'), padding = -0.5, fontsize = 26 ), widget.Spacer(), widget.TextBox( text=lar, foreground = color.get('color6'), font = plf, padding = -0.5, fontsize = 23, ), widget.Systray( background = color.get('color6'), icon_size = 15), widget.TextBox( text = lar, background = color.get('color6'), foreground = color.get('color8'), font = plf, padding = -0.5, fontsize = 23 ), widget.Volume( background= color.get('color8'), ), widget.Volume( emoji = True, background= color.get('color8'), ), widget.Volume( fmt= ' {} 🎙️', channel='Capture', background= color.get('color8'), ), widget.TextBox( text=lar, background= color.get('color8'), foreground = color.get('color6'), font = plf, padding = -0.5, fontsize = 23 ), widget.GenPollText( func=ticker_gecko.main, update_interval= 0.5, foreground = invColor(color.get('color6')) if isWhite(color.get('color6')) else '#FFFFFF', background = color.get('color6'), ), widget.TextBox( text = '🪙', background = color.get('color6'), ), widget.TextBox( text=lar, background = color.get('color6'), foreground = color.get('color8'), font = plf, padding = -0.5, fontsize = 23 ), widget.Memory( fmt = "{} 💾", background = color.get('color8'), ), widget.TextBox( text=lar, background= color.get('color8'), foreground = color.get('color6'), font = plf, padding = -0.5, fontsize = 23 ), widget.CPU( fmt = '{} 💻', foreground = invColor(color.get('color6')) if isWhite(color.get('color6')) else '#FFFFFF', background = color.get('color6'), ), widget.TextBox( text=lar, background = color.get('color6'), foreground = color.get('color8'), font = plf, padding = -0.5, fontsize = 23 ), widget.Net( format= '{down:6.2f}{down_suffix} ⬇️ {up:6.2f}{up_suffix} ⬆️ ', background = color.get('color8'), ), widget.TextBox( text=lar, background = color.get('color8'), foreground = color.get('color6'), font = plf, padding = -0.5, fontsize = 23 ), widget.Clock( background = color.get('color6'), foreground = invColor(color.get('color6')) if isWhite(color.get('color6')) else '#FFFFFF', format='%m-%d-%Y %a 📅 %I:%M:%S %p 🕒') ], 23, background = (0, 0, 0, 0), ), ), ] # Drag floating layouts. mouse = [ Drag([mod], "Button1", lazy.window.set_position_floating(), start=lazy.window.get_position()), Drag([mod], "Button3", lazy.window.set_size_floating(), start=lazy.window.get_size()), Click([mod], "Button2", lazy.window.bring_to_front()) ] main = None dgroups_key_binder = None dgroups_app_rules = [] # type: List follow_mouse_focus = True bring_front_click = False cursor_warp = False floating_layout = layout.Floating(float_rules=[ # Run the utility of `xprop` to see the wm class and name of an X client. *layout.Floating.default_float_rules, Match(wm_class='confirmreset'), Match(wm_class='makebranch'), Match(wm_class='maketag'), Match(wm_class='ssh-askpass'), Match(title='branchdialog'), Match(title='pinentry'), Match(title='xsnow'), #{'wmclass': 'confirm'}, #{'wmclass': 'dialog'}, #{'wmclass': 'main.py'}, #{'wmclass': 'download'}, #{'wmclass': 'error'}, #{'wmclass': 'file_progress'}, #{'wmclass': 'notification'}, #{'wmclass': 'splash'}, #{'wmclass': 'toolbar'}, #{'wmclass': 'confirmreset'}, # gitk #{'wmclass': 'makebranch'}, # gitk #{'wmclass': 'maketag'}, # gitk #{'wname': 'branchdialog'}, # gitk #{'wname': 'pinentry'}, # GPG key password entry #{'wname': 'dialog'}, #{'wmclass': 'ssh-askpass'}, # ssh-askpass ]) auto_fullscreen = True focus_on_window_activation = "smart" # XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this # string besides java UI toolkits; you can see several discussions on the # mailing lists, GitHub issues, and other WM documentation that suggest setting # this string if your java app doesn't work correctly. We may as well just lie # and say that we're a working one by default. # # We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in # java that happens to be on java's whitelist. wmname = "LG3D"