├── .gitignore ├── README ├── empathy.lua ├── fixwidthtextbox.lua ├── image ├── background.png ├── github_contributed.png ├── github_not_contributed.png ├── layout_empathy.png ├── squarefw.png └── squarew.png ├── menu.lua ├── myutil.lua ├── rc.lua ├── scripts └── update_github └── theme.lua /.gitignore: -------------------------------------------------------------------------------- 1 | local.lua 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | My Awesome configuration. 2 | 3 | Links: 4 | 5 | * https://bbs.archlinuxcn.org/viewtopic.php?id=2594 GTK 3 程序自绘窗口阴影造成的空白的解决方案 6 | -------------------------------------------------------------------------------- /empathy.lua: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------- 2 | -- Awesome layout suitable for windows which should be long and thin 3 | -- or short and wide 4 | -- Author: lilydjwg 5 | --------------------------------------------------------------------------- 6 | 7 | -- Grab environment we need 8 | local ipairs = ipairs 9 | local math = math 10 | local table = table 11 | -- “联系人列表”宽度 12 | -- local buddylist_width = 295 13 | local buddylist_width = 295 * 2 14 | -- local naughty = naughty 15 | 16 | local function do_empathy(p) 17 | if #p.clients > 0 then 18 | -- 每行最多窗口数 19 | local cols = 4 20 | local area = {} 21 | area.height = p.workarea.height 22 | area.width = p.workarea.width 23 | area.x = p.workarea.x 24 | area.y = p.workarea.y 25 | 26 | -- “联系人列表”窗口 27 | local cls = {} 28 | local buddylist_swap 29 | for k, c in ipairs(p.clients) do 30 | if c.name ~= '联系人列表' and c.name ~= 'Contact List' and c.name ~= '好友列表' then 31 | table.insert(cls, c) 32 | else 33 | if k ~= 1 then 34 | buddylist_swap = c 35 | end 36 | c:geometry({ 37 | width = buddylist_width - 2, 38 | height = area.height - 4, 39 | x = area.x, 40 | y = area.y, 41 | }) 42 | cols = cols - 1 43 | area.x = area.x + buddylist_width 44 | area.width = area.width - buddylist_width 45 | end 46 | end 47 | 48 | local rows = math.ceil(#cls / cols) 49 | local cols = math.ceil(#cls / rows) 50 | local aligned = (rows-1) * cols 51 | local col = 1 52 | local row = 1 53 | 54 | -- 计算其它窗口 55 | for k, c in ipairs(cls) do 56 | local g = {} 57 | g.height = area.height / rows 58 | if k <= aligned then 59 | g.width = area.width / cols 60 | else 61 | g.width = area.width / (#cls - (rows-1) * cols) 62 | end 63 | 64 | g.x = area.x + (col-1) * g.width 65 | g.y = area.y + (row-1) * g.height 66 | if row == rows then 67 | g.height = g.height - 4 68 | else 69 | g.height = g.height - 2 70 | end 71 | g.width = g.width - 2 72 | 73 | if col == cols then 74 | col = 1 75 | row = row + 1 76 | else 77 | col = col + 1 78 | end 79 | 80 | c:geometry(g) 81 | -- naughty.notify({ title=c.name, text= 'w: '.. g.width .. '\th: '.. g.height .. '\nx: '.. g.x .. '\ty: '.. g.y, 82 | -- timeout = 0 }) 83 | end 84 | if #cls > 0 and buddylist_swap then 85 | buddylist_swap:swap(cls[1]) 86 | end 87 | end 88 | end 89 | 90 | local empathy = {} 91 | empathy.name = "empathy" 92 | 93 | -- @param screen The screen to arrange. 94 | function empathy.arrange(p) 95 | return do_empathy(p) 96 | end 97 | 98 | return empathy 99 | -------------------------------------------------------------------------------- /fixwidthtextbox.lua: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------- 2 | -- @author Uli Schlachter 3 | -- @author dodo 4 | -- @author lilydjwg 5 | -- some code is borrowed from /usr/share/awesome/lib/wibox/widget/textbox.lua 6 | -- @copyright 2010, 2011 Uli Schlachter, dodo, lilydjwg 7 | -- @release v3.5 8 | --------------------------------------------------------------------------- 9 | 10 | local base = require("wibox.widget.textbox") 11 | local lgi = require("lgi") 12 | local Pango = lgi.Pango 13 | 14 | -- Setup a pango layout for the given textbox and cairo context 15 | local function setup_layout(box, width, height) 16 | local layout = box._layout 17 | layout.width = Pango.units_from_double(width) 18 | layout.height = Pango.units_from_double(height) 19 | end 20 | 21 | --- Fit the given textbox 22 | -- @return width and height needed in pixels 23 | local function fit(self, width, height) 24 | setup_layout(self, width, height) 25 | local ink, logical = self._layout:get_pixel_extents() 26 | return self.width or logical.width, logical.height 27 | end 28 | 29 | local function textbox(...) 30 | local box = base(...) 31 | box.fit = fit 32 | return box 33 | end 34 | 35 | return textbox 36 | 37 | -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 38 | -------------------------------------------------------------------------------- /image/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lilydjwg/myawesomerc/e61a7a36c545ca27f28cfcb8fcf08fbc0b8e716d/image/background.png -------------------------------------------------------------------------------- /image/github_contributed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lilydjwg/myawesomerc/e61a7a36c545ca27f28cfcb8fcf08fbc0b8e716d/image/github_contributed.png -------------------------------------------------------------------------------- /image/github_not_contributed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lilydjwg/myawesomerc/e61a7a36c545ca27f28cfcb8fcf08fbc0b8e716d/image/github_not_contributed.png -------------------------------------------------------------------------------- /image/layout_empathy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lilydjwg/myawesomerc/e61a7a36c545ca27f28cfcb8fcf08fbc0b8e716d/image/layout_empathy.png -------------------------------------------------------------------------------- /image/squarefw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lilydjwg/myawesomerc/e61a7a36c545ca27f28cfcb8fcf08fbc0b8e716d/image/squarefw.png -------------------------------------------------------------------------------- /image/squarew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lilydjwg/myawesomerc/e61a7a36c545ca27f28cfcb8fcf08fbc0b8e716d/image/squarew.png -------------------------------------------------------------------------------- /menu.lua: -------------------------------------------------------------------------------- 1 | xdgmenu = function(terminal) 2 | return { 3 | {'Internet', --[[/usr/share/desktop-directories/Arch-Internet.directory]] { 4 | {'Avahi SSH 服务器的浏览器', '/usr/bin/bssh', '/usr/share/icons/Adwaita/16x16/devices/network-wired.png' --[[/usr/share/applications/bssh.desktop]]}, 5 | {'Avahi VNC 服务器的浏览器', '/usr/bin/bvnc', '/usr/share/icons/Adwaita/16x16/devices/network-wired.png' --[[/usr/share/applications/bvnc.desktop]]}, 6 | {'Dropbox', 'dropbox', '/usr/share/pixmaps/dropbox.png' --[[/usr/share/applications/dropbox.desktop]]}, 7 | {'ELinks', (terminal or "xterm") .. " -e '/usr/bin/elinks'" --[[/usr/share/applications/elinks.desktop]]}, 8 | {'Firefox', '/usr/lib/firefox/firefox', '/usr/share/icons/hicolor/16x16/apps/firefox.png' --[[/usr/share/applications/firefox.desktop]]}, 9 | {'Google Chrome', '/usr/bin/google-chrome-stable', '/usr/share/icons/hicolor/16x16/apps/google-chrome.png' --[[/usr/share/applications/google-chrome.desktop]]}, 10 | {'MEGASync', 'megasync', '/usr/share/icons/hicolor/16x16/apps/mega.png' --[[/usr/share/applications/megasync.desktop]]}, 11 | {'Pidgin 互联网通讯程序', 'pidgin', '/usr/share/icons/hicolor/16x16/apps/pidgin.png' --[[/usr/share/applications/pidgin.desktop]]}, 12 | {'TigerVNC Viewer', '/usr/bin/vncviewer', '/usr/share/icons/hicolor/16x16/apps/tigervnc.png' --[[/usr/share/applications/vncviewer.desktop]]}, 13 | {'Transmission', 'transmission-gtk', '/usr/share/pixmaps/transmission.png' --[[/usr/share/applications/transmission-gtk.desktop]]}, 14 | {'Wine QQ 轻聊版', 'sudo mynetns_run WINEDEBUG=-all qq', '/home/lilydjwg/.local/share/icons/hicolor/256x256/apps/qq.png' --[[/home/lilydjwg/.local/share/applications/wine-qq.desktop]]}, 15 | {'Wireshark', 'wireshark', '/usr/share/icons/hicolor/16x16/apps/wireshark.png' --[[/usr/share/applications/wireshark.desktop]]}, 16 | {'X11VNC Server', 'x11vnc -gui tray=setpass -rfbport PROMPT -bg -o %HOME/.x11vnc.log.%VNCDISPLAY', '/usr/share/icons/Adwaita/16x16/devices/computer.png' --[[/usr/share/applications/x11vnc.desktop]]}, 17 | {'Zenmap', 'zenmap', '/usr/share/zenmap/pixmaps/zenmap.png' --[[/usr/share/applications/zenmap.desktop]]}, 18 | {'Zenmap (as root)', '/usr/share/zenmap/su-to-zenmap.sh', '/usr/share/zenmap/pixmaps/zenmap.png' --[[/usr/share/applications/zenmap-root.desktop]]}, 19 | {'aLinkCreator', 'alc', '/usr/share/pixmaps/alc.xpm' --[[/usr/share/applications/alc.desktop]]}, 20 | {'aMule', 'amule', '/usr/share/pixmaps/amule.xpm' --[[/usr/share/applications/amule.desktop]]}, 21 | {'aMuleGUI', 'amulegui', '/usr/share/pixmaps/amulegui.xpm' --[[/usr/share/applications/amulegui.desktop]]}, 22 | {'mutt', (terminal or "xterm") .. " -e 'mutt'" --[[/home/lilydjwg/.local/share/applications/mutt.desktop]]}, 23 | {'qTox', 'qtox', '/usr/share/icons/hicolor/16x16/apps/qtox.png' --[[/usr/share/applications/qtox.desktop]]}, 24 | {'wxCas', 'wxcas', '/usr/share/pixmaps/wxcas.xpm' --[[/usr/share/applications/wxcas.desktop]]}, 25 | {'网络浏览器', 'exo-open --launch WebBrowser', '/usr/share/icons/Adwaita/16x16/apps/web-browser.png' --[[/usr/share/applications/exo-web-browser.desktop]]}, 26 | {'邮件阅读器', 'exo-open --launch MailReader' --[[/usr/share/applications/exo-mail-reader.desktop]]}, 27 | } 28 | }, {'办公', --[[/usr/share/desktop-directories/Arch-Office.directory]] { 29 | {'FBReader', 'FBReader', '/usr/share/pixmaps/FBReader.png' --[[/usr/share/applications/FBReader.desktop]]}, 30 | {'LibreOffice', 'libreoffice', '/usr/share/icons/hicolor/16x16/apps/libreoffice-startcenter.png' --[[/usr/share/applications/libreoffice-startcenter.desktop]]}, 31 | {'LibreOffice Base', 'libreoffice --base', '/usr/share/icons/hicolor/16x16/apps/libreoffice-base.png' --[[/usr/share/applications/libreoffice-base.desktop]]}, 32 | {'LibreOffice Calc', 'libreoffice --calc', '/usr/share/icons/hicolor/16x16/apps/libreoffice-calc.png' --[[/usr/share/applications/libreoffice-calc.desktop]]}, 33 | {'LibreOffice Draw', 'libreoffice --draw', '/usr/share/icons/hicolor/16x16/apps/libreoffice-draw.png' --[[/usr/share/applications/libreoffice-draw.desktop]]}, 34 | {'LibreOffice Impress', 'libreoffice --impress', '/usr/share/icons/hicolor/16x16/apps/libreoffice-impress.png' --[[/usr/share/applications/libreoffice-impress.desktop]]}, 35 | {'LibreOffice Math', 'libreoffice --math', '/usr/share/icons/hicolor/16x16/apps/libreoffice-math.png' --[[/usr/share/applications/libreoffice-math.desktop]]}, 36 | {'LibreOffice Writer', 'libreoffice --writer', '/usr/share/icons/hicolor/16x16/apps/libreoffice-writer.png' --[[/usr/share/applications/libreoffice-writer.desktop]]}, 37 | {'WPS 文字', '/usr/bin/wps', '/usr/share/icons/hicolor/48x48/apps/wps-office-wpsmain.png' --[[/usr/share/applications/wps-office-wps.desktop]]}, 38 | {'WPS 演示', '/usr/bin/wpp', '/usr/share/icons/hicolor/48x48/apps/wps-office-wppmain.png' --[[/usr/share/applications/wps-office-wpp.desktop]]}, 39 | {'WPS 表格', '/usr/bin/et', '/usr/share/icons/hicolor/48x48/apps/wps-office-etmain.png' --[[/usr/share/applications/wps-office-et.desktop]]}, 40 | {'Xgnokii', 'xgnokii', '/usr/share/icons/Adwaita/16x16/devices/phone.png' --[[/usr/share/applications/xgnokii.desktop]]}, 41 | {'Zathura', 'zathura' --[[/usr/share/applications/zathura.desktop]]}, 42 | {'Zathura', 'zathura' --[[/usr/share/applications/zathura-pdf-poppler.desktop]]}, 43 | {'apvlv', 'apvlv' --[[/usr/share/applications/apvlv.desktop]]}, 44 | {'打印预览', 'evince-previewer', '/usr/share/icons/Adwaita/16x16/actions/document-print-preview.png' --[[/usr/share/applications/evince-previewer.desktop]]}, 45 | {'文档查看器', 'evince', '/usr/share/icons/hicolor/16x16/apps/evince.png' --[[/usr/share/applications/evince.desktop]]}, 46 | {'星际译王', 'stardict', '/usr/share/pixmaps/stardict.png' --[[/usr/share/applications/stardict.desktop]]}, 47 | } 48 | }, {'图像', --[[/usr/share/desktop-directories/Arch-Graphics.directory]] { 49 | {'Dia 图表编辑器', 'dia', '/usr/share/icons/hicolor/16x16/apps/dia.png' --[[/usr/share/applications/dia.desktop]]}, 50 | {'Feh', 'feh', '/usr/share/icons/hicolor/48x48/apps/feh.png' --[[/usr/share/applications/feh.desktop]]}, 51 | {'GNU 图像处理程序', 'gimp-2.8', '/usr/share/icons/hicolor/16x16/apps/gimp.png' --[[/usr/share/applications/gimp.desktop]]}, 52 | {'Geeqie', 'geeqie -r', '/usr/share/pixmaps/geeqie.png' --[[/usr/share/applications/geeqie.desktop]]}, 53 | {'Inkscape', 'inkscape', '/usr/share/icons/hicolor/16x16/apps/inkscape.png' --[[/usr/share/applications/inkscape.desktop]]}, 54 | {'LibreOffice Draw', 'libreoffice --draw', '/usr/share/icons/hicolor/16x16/apps/libreoffice-draw.png' --[[/usr/share/applications/libreoffice-draw.desktop]]}, 55 | {'MyPaint', 'mypaint', '/usr/share/icons/hicolor/16x16/apps/mypaint.png' --[[/usr/share/applications/mypaint.desktop]]}, 56 | {'XDot', 'xdot' --[[/usr/share/applications/xdot.desktop]]}, 57 | {'ida', 'ida', '/usr/share/pixmaps/ida.png' --[[/usr/share/applications/ida.desktop]]}, 58 | {'图像查看器', 'eog', '/usr/share/icons/hicolor/16x16/apps/eog.png' --[[/usr/share/applications/eog.desktop]]}, 59 | {'字型鍛造廠', 'fontforge', '/usr/share/icons/hicolor/16x16/apps/fontforge.png' --[[/usr/share/applications/fontforge.desktop]]}, 60 | {'打印预览', 'evince-previewer', '/usr/share/icons/Adwaita/16x16/actions/document-print-preview.png' --[[/usr/share/applications/evince-previewer.desktop]]}, 61 | {'文档查看器', 'evince', '/usr/share/icons/hicolor/16x16/apps/evince.png' --[[/usr/share/applications/evince.desktop]]}, 62 | } 63 | }, {'影音', --[[/usr/share/desktop-directories/Arch-Multimedia.directory]] { 64 | {'Audacity', 'env UBUNTU_MENUPROXY=0 audacity', '/usr/share/pixmaps/audacity.xpm' --[[/usr/share/applications/audacity.desktop]]}, 65 | {'Drumstick Drum Grid', 'drumstick-drumgrid', '/usr/share/icons/hicolor/16x16/apps/drumstick.png' --[[/usr/share/applications/drumstick-drumgrid.desktop]]}, 66 | {'Drumstick MIDI Player', 'drumstick-guiplayer', '/usr/share/icons/hicolor/16x16/apps/drumstick.png' --[[/usr/share/applications/drumstick-guiplayer.desktop]]}, 67 | {'Drumstick Virtual Piano', 'drumstick-vpiano', '/usr/share/icons/hicolor/16x16/apps/drumstick.png' --[[/usr/share/applications/drumstick-vpiano.desktop]]}, 68 | {'FlashPlayer', 'flashplayer', '/usr/share/pixmaps/gflashplayer.png' --[[/usr/share/applications/flashplayer.desktop]]}, 69 | {'MPlayer Media Player', 'mplayer', '/usr/share/pixmaps/mplayer.png' --[[/usr/share/applications/mplayer.desktop]]}, 70 | {'PulseAudio 音量控制', 'pavucontrol', '/usr/share/icons/Adwaita/16x16/apps/multimedia-volume-control.png' --[[/usr/share/applications/pavucontrol.desktop]]}, 71 | {'Qt V4L2 test Utility', 'qv4l2', '/usr/share/icons/hicolor/16x16/apps/qv4l2.png' --[[/usr/share/applications/qv4l2.desktop]]}, 72 | {'SimpleScreenRecorder', 'simplescreenrecorder --logfile', '/usr/share/icons/hicolor/16x16/apps/simplescreenrecorder.png' --[[/usr/share/applications/simplescreenrecorder.desktop]]}, 73 | {'VMPK', 'vmpk', '/usr/share/icons/hicolor/16x16/apps/vmpk.png' --[[/usr/share/applications/vmpk.desktop]]}, 74 | {'gtk-recordMyDesktop', 'gtk-recordMyDesktop', '/usr/share/pixmaps/gtk-recordmydesktop.png' --[[/usr/share/applications/gtk-recordmydesktop.desktop]]}, 75 | {'mpv 媒体播放器', 'mpv --player-operation-mode=pseudo-gui --', '/usr/share/icons/hicolor/16x16/apps/mpv.png' --[[/usr/share/applications/mpv.desktop]]}, 76 | {'qTox', 'qtox', '/usr/share/icons/hicolor/16x16/apps/qtox.png' --[[/usr/share/applications/qtox.desktop]]}, 77 | } 78 | }, {'教育', --[[/usr/share/desktop-directories/Arch-Education.directory]] { 79 | {'Drumstick Drum Grid', 'drumstick-drumgrid', '/usr/share/icons/hicolor/16x16/apps/drumstick.png' --[[/usr/share/applications/drumstick-drumgrid.desktop]]}, 80 | {'Drumstick MIDI Player', 'drumstick-guiplayer', '/usr/share/icons/hicolor/16x16/apps/drumstick.png' --[[/usr/share/applications/drumstick-guiplayer.desktop]]}, 81 | {'Drumstick Virtual Piano', 'drumstick-vpiano', '/usr/share/icons/hicolor/16x16/apps/drumstick.png' --[[/usr/share/applications/drumstick-vpiano.desktop]]}, 82 | {'GeoGebra', 'geogebra', '/usr/share/icons/hicolor/scalable/apps/geogebra.svg' --[[/usr/share/applications/geogebra.desktop]]}, 83 | {'LibreOffice Math', 'libreoffice --math', '/usr/share/icons/hicolor/16x16/apps/libreoffice-math.png' --[[/usr/share/applications/libreoffice-math.desktop]]}, 84 | {'Stellarium', 'stellarium', '/usr/share/pixmaps/stellarium.xpm' --[[/usr/share/applications/stellarium.desktop]]}, 85 | {'VMPK', 'vmpk', '/usr/share/icons/hicolor/16x16/apps/vmpk.png' --[[/usr/share/applications/vmpk.desktop]]}, 86 | } 87 | }, {'科学和数学', --[[/usr/share/desktop-directories/Arch-Science.directory]] { 88 | {'Qalculate!', 'qalculate-gtk', '/usr/share/pixmaps/qalculate.png' --[[/usr/share/applications/qalculate-gtk.desktop]]}, 89 | {'XDot', 'xdot' --[[/usr/share/applications/xdot.desktop]]}, 90 | } 91 | }, {'系统工具', --[[/usr/share/desktop-directories/Arch-System-Tools.directory]] { 92 | {'Avahi Zeroconf 浏览器', '/usr/bin/avahi-discover', '/usr/share/icons/Adwaita/16x16/devices/network-wired.png' --[[/usr/share/applications/avahi-discover.desktop]]}, 93 | {'Fcitx', 'fcitx', '/usr/share/icons/hicolor/16x16/apps/fcitx.png' --[[/usr/share/applications/fcitx.desktop]]}, 94 | {'GParted', '/usr/bin/gparted_polkit', '/usr/share/icons/hicolor/16x16/apps/gparted.png' --[[/usr/share/applications/gparted.desktop]]}, 95 | {'Htop', (terminal or "xterm") .. " -e 'htop'", '/usr/share/pixmaps/htop.png' --[[/usr/share/applications/htop.desktop]]}, 96 | {'Keyboard Layout', 'gkbd-keyboard-display', '/usr/share/icons/Adwaita/16x16/apps/preferences-desktop-keyboard.png' --[[/usr/share/applications/gkbd-keyboard-display.desktop]]}, 97 | {'LSHW', '/usr/sbin/gtk-lshw', '/usr/share/lshw/artwork/logo.svg' --[[/usr/share/applications/gtk-lshw.desktop]]}, 98 | {'MEGASync', 'megasync', '/usr/share/icons/hicolor/16x16/apps/mega.png' --[[/usr/share/applications/megasync.desktop]]}, 99 | {'Oracle VM VirtualBox', 'VirtualBox', '/usr/share/icons/hicolor/16x16/mimetypes/virtualbox.png' --[[/usr/share/applications/virtualbox.desktop]]}, 100 | {'Thunar 文件管理器', 'thunar', '/usr/share/icons/hicolor/16x16/apps/Thunar.png' --[[/usr/share/applications/Thunar.desktop]]}, 101 | {'UXTerm', 'uxterm', '/usr/share/pixmaps/xterm-color_48x48.xpm' --[[/usr/share/applications/uxterm.desktop]]}, 102 | {'XTerm', 'xterm', '/usr/share/pixmaps/xterm-color_48x48.xpm' --[[/usr/share/applications/xterm.desktop]]}, 103 | {'Xfce 终端', 'xfce4-terminal', '/usr/share/icons/Adwaita/16x16/apps/utilities-terminal.png' --[[/usr/share/applications/xfce4-terminal.desktop]]}, 104 | {'ranger', (terminal or "xterm") .. " -e 'ranger'", '/usr/share/icons/Adwaita/16x16/apps/utilities-terminal.png' --[[/usr/share/applications/ranger.desktop]]}, 105 | {'批量重命名', '/usr/lib/Thunar/ThunarBulkRename', '/usr/share/icons/hicolor/16x16/apps/Thunar.png' --[[/usr/share/applications/Thunar-bulk-rename.desktop]]}, 106 | {'用 Thunar 打开文件夹', 'thunar', '/usr/share/icons/hicolor/16x16/apps/Thunar.png' --[[/usr/share/applications/Thunar-folder-handler.desktop]]}, 107 | {'磁碟用量分析器', 'baobab', '/usr/share/icons/hicolor/16x16/apps/baobab.png' --[[/usr/share/applications/org.gnome.baobab.desktop]]}, 108 | } 109 | }, {'编程', --[[/usr/share/desktop-directories/Arch-Development.directory]] { 110 | {'CMake', 'cmake-gui', '/usr/share/icons/hicolor/32x32/apps/CMakeSetup.png' --[[/usr/share/applications/CMake.desktop]]}, 111 | {'D-Feet', 'd-feet', '/usr/share/icons/hicolor/16x16/apps/d-feet.png' --[[/usr/share/applications/d-feet.desktop]]}, 112 | {'FLUID', 'fluid', '/usr/share/icons/hicolor/16x16/apps/fluid.png' --[[/usr/share/applications/fluid.desktop]]}, 113 | {'GTK+ Demo', 'gtk3-demo', '/usr/share/icons/hicolor/16x16/apps/gtk3-demo.png' --[[/usr/share/applications/gtk3-demo.desktop]]}, 114 | {'Icon Browser', 'gtk3-icon-browser' --[[/usr/share/applications/gtk3-icon-browser.desktop]]}, 115 | {'Java Mission Control', '/usr/lib/jvm/java-8-jdk/bin/jmc', '/usr/share/icons/hicolor/16x16/apps/sun-java-jdk8.png' --[[/usr/share/applications/jmc-jdk8.desktop]]}, 116 | {'Java Monitoring and Management Console', '/usr/lib/jvm/java-8-jdk/bin/jconsole', '/usr/share/icons/hicolor/16x16/apps/sun-java-jdk8.png' --[[/usr/share/applications/jconsole-jdk8.desktop]]}, 117 | {'Java VisualVM', '/usr/lib/jvm/java-8-jdk/bin/jvisualvm', '/usr/share/icons/hicolor/16x16/apps/sun-java-jdk8.png' --[[/usr/share/applications/jvisualvm-jdk8.desktop]]}, 118 | {'Meld', 'meld', '/usr/share/icons/hicolor/16x16/apps/meld.png' --[[/usr/share/applications/meld.desktop]]}, 119 | {'Qt4 Assistant', 'assistant-qt4', '/usr/share/icons/hicolor/32x32/apps/assistant-qt4.png' --[[/usr/share/applications/assistant-qt4.desktop]]}, 120 | {'Qt4 Designer', 'designer-qt4', '/usr/share/icons/hicolor/128x128/apps/designer-qt4.png' --[[/usr/share/applications/designer-qt4.desktop]]}, 121 | {'Qt4 Linguist', 'linguist-qt4', '/usr/share/icons/hicolor/16x16/apps/linguist-qt4.png' --[[/usr/share/applications/linguist-qt4.desktop]]}, 122 | {'Qt4 QDbusViewer', 'qdbusviewer-qt4', '/usr/share/icons/hicolor/32x32/apps/qdbusviewer-qt4.png' --[[/usr/share/applications/qdbusviewer-qt4.desktop]]}, 123 | {'Widget Factory', 'gtk3-widget-factory', '/usr/share/icons/hicolor/16x16/apps/gtk3-widget-factory.png' --[[/usr/share/applications/gtk3-widget-factory.desktop]]}, 124 | {'ipython', (terminal or "xterm") .. " -e 'ipython'", '/usr/share/pixmaps/ipython.png' --[[/usr/share/applications/ipython.desktop]]}, 125 | {'sandbox', (terminal or "xterm") .. " -e 'sandbox'", '/usr/share/pixmaps/sandbox.svg' --[[/usr/share/applications/sandbox.desktop]]}, 126 | } 127 | }, {'附件', --[[/usr/share/desktop-directories/Arch-Accessories.directory]] { 128 | {'Fcitx 皮肤安装器', 'fcitx-skin-installer', '/usr/share/icons/hicolor/16x16/apps/fcitx.png' --[[/usr/share/applications/fcitx-skin-installer.desktop]]}, 129 | {'GVim', 'gvim -f', '/usr/share/pixmaps/gvim.png' --[[/usr/share/applications/gvim.desktop]]}, 130 | {'Leafpad', 'leafpad', '/usr/share/pixmaps/leafpad.png' --[[/usr/share/applications/leafpad.desktop]]}, 131 | {'Qalculate!', 'qalculate-gtk', '/usr/share/pixmaps/qalculate.png' --[[/usr/share/applications/qalculate-gtk.desktop]]}, 132 | {'Shutter', 'shutter', '/usr/share/pixmaps/shutter.png' --[[/usr/share/applications/shutter.desktop]]}, 133 | {'Vim', (terminal or "xterm") .. " -e 'vim'", '/usr/share/pixmaps/gvim.png' --[[/usr/share/applications/vim.desktop]]}, 134 | {'Winetricks', 'winetricks --gui', '/usr/share/icons/hicolor/scalable/apps/winetricks.svg' --[[/usr/share/applications/winetricks.desktop]]}, 135 | {'Xgnokii', 'xgnokii', '/usr/share/icons/Adwaita/16x16/devices/phone.png' --[[/usr/share/applications/xgnokii.desktop]]}, 136 | {'ipython', (terminal or "xterm") .. " -e 'ipython'", '/usr/share/pixmaps/ipython.png' --[[/usr/share/applications/ipython.desktop]]}, 137 | {'wxHexEditor', 'wxHexEditor', '/usr/share/pixmaps/wxHexEditor.png' --[[/usr/share/applications/wxHexEditor.desktop]]}, 138 | {'关于 Xfce', 'xfce4-about', '/usr/share/icons/Adwaita/16x16/actions/help-about.png' --[[/usr/share/applications/xfce4-about.desktop]]}, 139 | {'在已有的 GVIM 里打开', 'vv', '/usr/share/pixmaps/gvim.png' --[[/home/lilydjwg/.local/share/applications/vv.desktop]]}, 140 | {'字体查看器', 'gnome-font-viewer', '/usr/share/icons/Adwaita/16x16/apps/preferences-desktop-font.png' --[[/usr/share/applications/org.gnome.font-viewer.desktop]]}, 141 | {'字符映射表', 'gucharmap', '/usr/share/icons/Adwaita/16x16/apps/accessories-character-map.png' --[[/usr/share/applications/gucharmap.desktop]]}, 142 | {'应用程序查找器', 'xfce4-appfinder', '/usr/share/icons/Adwaita/16x16/actions/edit-find.png' --[[/usr/share/applications/xfce4-appfinder.desktop]]}, 143 | {'文件管理器', 'exo-open --launch FileManager', '/usr/share/icons/Adwaita/16x16/apps/system-file-manager.png' --[[/usr/share/applications/exo-file-manager.desktop]]}, 144 | {'星际译王', 'stardict', '/usr/share/pixmaps/stardict.png' --[[/usr/share/applications/stardict.desktop]]}, 145 | {'磁盘', 'gnome-disks', '/usr/share/icons/hicolor/16x16/apps/gnome-disks.png' --[[/usr/share/applications/org.gnome.DiskUtility.desktop]]}, 146 | {'终端模拟器', 'exo-open --launch TerminalEmulator', '/usr/share/icons/Adwaita/16x16/apps/utilities-terminal.png' --[[/usr/share/applications/exo-terminal-emulator.desktop]]}, 147 | {'运行程序...', 'xfce4-appfinder --collapsed', '/usr/share/icons/Adwaita/16x16/actions/system-run.png' --[[/usr/share/applications/xfce4-run.desktop]]}, 148 | } 149 | } 150 | } 151 | end 152 | -------------------------------------------------------------------------------- /myutil.lua: -------------------------------------------------------------------------------- 1 | local awful = require("awful") 2 | local client = client 3 | local pairs = pairs 4 | local table = table 5 | 6 | local myutil = {} 7 | 8 | -- Returns true if all pairs in table1 are present in table2 {{{1 9 | local function match (table1, table2) 10 | for k, v in pairs(table1) do 11 | -- not all clients have all properties so first test if it is nil 12 | if not table2[k] or (table2[k] ~= v and not table2[k]:find(v)) then 13 | return false 14 | end 15 | end 16 | return true 17 | end 18 | 19 | -- Get clients by condition {{{1 20 | local function getclients(properties) 21 | local clients = client.get() 22 | local focused = awful.client.next(0) 23 | local findex = 0 24 | local matched_clients = {} 25 | local n = 0 26 | for i, c in pairs(clients) do 27 | --make an array of matched clients 28 | if match(properties, c) then 29 | n = n + 1 30 | matched_clients[n] = c 31 | if c == focused then 32 | findex = n 33 | end 34 | end 35 | end 36 | return matched_clients, findex 37 | end 38 | 39 | -- {{{1 run_or_raise 40 | -- 来源: http://awesome.naquadah.org/wiki/Run_or_raise 41 | function myutil.run_or_raise(cmd, properties, beforemove) 42 | local findex, matched_clients 43 | matched_clients, findex = getclients(properties) 44 | local n = #matched_clients 45 | if n > 0 then 46 | local c = matched_clients[1] 47 | -- if the focused window matched switch focus to next in list 48 | if 0 < findex and findex < n then 49 | c = matched_clients[findex+1] 50 | end 51 | local ctags = c:tags() 52 | local curtag = awful.tag.selected() 53 | if beforemove then 54 | beforemove(c) 55 | end 56 | awful.client.movetotag(curtag, c) 57 | -- And then focus the client 58 | client.focus = c 59 | c:raise() 60 | -- if the client is maximized on another screen, re-maximize it if necessary 61 | if c.maximized_horizontal and c.maximized_vertical then 62 | local geo = c:geometry() 63 | local area = geo.width * geo.height 64 | local wa = screen[mouse.screen].workarea 65 | local area_t = wa.width * wa.height 66 | -- too large or small? 67 | if area < area_t * 0.9 or area > area_t then 68 | c.maximized_horizontal = false 69 | c.maximized_vertical = false 70 | c.maximized_horizontal = true 71 | c.maximized_vertical = true 72 | end 73 | end 74 | return c 75 | end 76 | awful.util.spawn(cmd) 77 | end 78 | 79 | return myutil 80 | 81 | -- {{{1 vim modeline 82 | -- vim: se fdm=marker: 83 | -------------------------------------------------------------------------------- /rc.lua: -------------------------------------------------------------------------------- 1 | -- Standard awesome library 2 | local gears = require("gears") 3 | local awful = require("awful") 4 | awful.rules = require("awful.rules") 5 | require("awful.autofocus") 6 | -- Widget and layout library 7 | local wibox = require("wibox") 8 | -- Theme handling library 9 | local beautiful = require("beautiful") 10 | -- Notification library 11 | local naughty = require("naughty") 12 | local menubar = require("menubar") 13 | -- for fcitx-chttrans 14 | table.insert(naughty.config.icon_dirs, '/usr/share/icons/hicolor/48x48/apps/') 15 | table.insert(naughty.config.icon_dirs, '/usr/share/icons/hicolor/48x48/status/') 16 | 17 | local empathy = require("empathy") 18 | local myutil = require("myutil") 19 | local fixwidthtextbox = require("fixwidthtextbox") 20 | local menu = require("menu") 21 | 22 | local ok, localconf = pcall(require, "local") 23 | if ok and localconf.scale then 24 | scale = localconf.scale 25 | else 26 | scale = 1 27 | end 28 | 29 | if scale ~= 1 then 30 | local dpi = 96 * scale 31 | require("lgi").PangoCairo.FontMap.get_default():set_resolution(dpi) 32 | end 33 | 34 | main_screen = 1 35 | eink_screen = 3 36 | 37 | os.setlocale("") 38 | last_bat_warning = 0 39 | 40 | notify = function(args) 41 | args.font = '12' 42 | args.screen = mouse.screen 43 | 44 | if mouse.screen == eink_screen then 45 | args.fg = '#000000' 46 | args.bg = '#ffffff' 47 | else 48 | args.fg = '#ffffff' 49 | end 50 | if args.critical then 51 | args.critical = nil 52 | args.preset = naughty.config.presets.critical 53 | end 54 | return naughty.notify(args) 55 | end 56 | 57 | -- A debugging func 58 | n = function(n) notify{title="消息", text=tostring(n)} end 59 | 60 | -- {{{ Error handling 61 | -- Check if awesome encountered an error during startup and fell back to 62 | -- another config (This code will only ever execute for the fallback config) 63 | if awesome.startup_errors then 64 | notify{ 65 | critical = true, 66 | title = "Oops, there were errors during startup!", 67 | text = awesome.startup_errors, 68 | } 69 | end 70 | 71 | -- Handle runtime errors after startup 72 | do 73 | local in_error = false 74 | awesome.connect_signal("debug::error", function (err) 75 | -- Make sure we don't go into an endless error loop 76 | if in_error then return end 77 | in_error = true 78 | 79 | notify{ 80 | critical = true, 81 | title = "Oops, an error happened!", 82 | text = err, 83 | } 84 | in_error = false 85 | end) 86 | end 87 | -- }}} 88 | 89 | -- {{{ Variable definitions 90 | -- Themes define colours, icons, and wallpapers 91 | beautiful.init(awful.util.getdir("config") .. "/theme.lua") 92 | 93 | -- This is used later as the default terminal and editor to run. 94 | terminal = "gnome-terminal" 95 | editor = "gvim" 96 | editor_cmd = editor 97 | 98 | -- Default modkey. 99 | -- Usually, Mod4 is the key with a logo between Control and Alt. 100 | -- If you do not like this or do not have such a key, 101 | -- I suggest you to remap Mod4 to another key using xmodmap or other tools. 102 | -- However, you can use another modifier like Mod1, but it may interact with others. 103 | modkey = "Mod4" 104 | 105 | -- Table of layouts to cover with awful.layout.inc, order matters. 106 | local layouts = 107 | { 108 | awful.layout.suit.floating, 109 | awful.layout.suit.tile, 110 | awful.layout.suit.tile.left, 111 | awful.layout.suit.tile.bottom, 112 | awful.layout.suit.tile.top, 113 | awful.layout.suit.fair, 114 | awful.layout.suit.fair.horizontal, 115 | -- awful.layout.suit.spiral, 116 | -- awful.layout.suit.spiral.dwindle, 117 | awful.layout.suit.max, 118 | awful.layout.suit.max.fullscreen, 119 | awful.layout.suit.magnifier, 120 | } 121 | -- }}} 122 | 123 | -- {{{ Functions 124 | function get_memory_usage() 125 | local ret = {} 126 | for l in io.lines('/proc/meminfo') do 127 | local k, v = l:match("([^:]+):%s+(%d+)") 128 | ret[k] = tonumber(v) 129 | end 130 | return ret 131 | end 132 | 133 | function string_split(string, pat, plain) 134 | local ret = {} 135 | local pos = 0 136 | local start, stop 137 | local t_insert = table.insert 138 | while true do 139 | start, stop = string:find(pat, pos, plain) 140 | if not start then 141 | t_insert(ret, string:sub(pos)) 142 | break 143 | end 144 | t_insert(ret, string:sub(pos, start-1)) 145 | pos = stop + 1 146 | end 147 | return ret 148 | end 149 | 150 | function parse_key(string) 151 | local t_insert = table.insert 152 | local parts = string_split(string, '[+-]') 153 | local last = table.remove(parts) 154 | local ret = {} 155 | for _, p in ipairs(parts) do 156 | p_ = p:lower() 157 | local m 158 | if p_ == 'ctrl' then 159 | m = 'Control' 160 | elseif p_ == 'alt' then 161 | m = 'Mod1' 162 | else 163 | m = p 164 | end 165 | t_insert(ret, m) 166 | end 167 | return ret, last 168 | end 169 | 170 | _key_map_cache = {} 171 | function map_client_key(client, key_map) 172 | local t_insert = table.insert 173 | local keys 174 | if _key_map_cache[key_map] then 175 | keys = awful.util.table.join(client:keys(), _key_map_cache[key_map]) 176 | else 177 | keys = {} 178 | for from, to in pairs(key_map) do 179 | local mod, key = parse_key(from) 180 | local key = awful.key(mod, key, function(c) 181 | awful.util.spawn( 182 | 'xdotool key --clearmodifiers --window ' 183 | .. c.window .. ' ' .. to) 184 | end) 185 | for _, k in ipairs(key) do 186 | t_insert(keys, k) 187 | end 188 | end 189 | _key_map_cache[key_map] = keys 190 | keys = awful.util.table.join(client:keys(), keys) 191 | end 192 | client:keys(keys) 193 | end 194 | -- }}} 195 | 196 | -- {{{ Wallpaper 197 | if beautiful.wallpaper then 198 | for s = 1, screen.count() do 199 | gears.wallpaper.maximized(beautiful.wallpaper, s, true) 200 | end 201 | end 202 | -- }}} 203 | 204 | -- {{{ Tags 205 | -- Define a tag table which hold all screen tags. 206 | tags_name = { "1聊天", "2火狐", "3", "4", "5", "6", "7", "8GVIM", "9", '0' } 207 | tags_layout = { 208 | awful.layout.suit.max, 209 | awful.layout.suit.max, 210 | awful.layout.suit.max, 211 | awful.layout.suit.max, 212 | awful.layout.suit.max, 213 | empathy, 214 | awful.layout.suit.max, 215 | awful.layout.suit.max, 216 | awful.layout.suit.max, 217 | awful.layout.suit.floating, 218 | } 219 | tags = {} 220 | revtags = {} 221 | for s = 1, screen.count() do 222 | -- Each screen has its own tag table. 223 | tags[s] = awful.tag(tags_name, s, tags_layout) 224 | revtags[s] = {} 225 | for i, t in ipairs(tags[s]) do 226 | revtags[s][t] = i 227 | end 228 | end 229 | -- }}} 230 | 231 | -- {{{ Menu 232 | -- Create a laucher widget and a main menu 233 | local myawesomemenu = { 234 | { "编辑配置 (&E)", editor_cmd .. " " .. awesome.conffile }, 235 | { "重新加载 (&R)", awesome.restart, '/usr/share/icons/gnome/16x16/actions/stock_refresh.png' }, 236 | { "注销 (&L)", awesome.quit }, 237 | } 238 | 239 | local mymenu = { 240 | { "&Nautilus", "nautilus --no-desktop /home/lilydjwg/tmpfs", '/usr/share/icons/gnome/32x32/apps/system-file-manager.png' }, 241 | { "&Wireshark", "wireshark", '/usr/share/icons/hicolor/32x32/apps/wireshark.png'}, 242 | { "&VirtualBox", "VirtualBox", '/usr/share/icons/hicolor/32x32/mimetypes/virtualbox.png' }, 243 | { "文档查看器 (&E)", "evince", '/usr/share/icons/hicolor/16x16/apps/evince.png' }, 244 | } 245 | 246 | mymainmenu = awful.menu({ items = { { "Awesome", myawesomemenu, beautiful.awesome_icon }, 247 | { "终端 (&T)", terminal, '/usr/share/icons/gnome/32x32/apps/utilities-terminal.png' }, 248 | { "G&VIM", "gvim", '/usr/share/pixmaps/gvim.png' }, 249 | { "火狐 (&F)", "firefox-nightly -P nightly", '/usr/share/icons/hicolor/32x32/apps/firefox.png' }, 250 | { "常用 (&U)", mymenu }, 251 | { "应用程序 (&A)", xdgmenu(terminal) }, 252 | { "挂起 (&S)", "systemctl suspend" }, 253 | { "关机 (&H)", "zenity --question --title '关机' --text '你确定关机吗?' --default-cancel && systemctl poweroff", '/usr/share/icons/gnome/16x16/actions/gtk-quit.png' }, 254 | } 255 | }) 256 | 257 | mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, 258 | menu = mymainmenu }) 259 | 260 | -- Menubar configuration 261 | menubar.utils.terminal = terminal -- Set the terminal for applications that require it 262 | -- }}} 263 | 264 | -- {{{ Wibox 265 | -- Create a textclock widget 266 | mytextclock = awful.widget.textclock(" %Y年%m月%d日 %H:%M:%S %A ", 1) 267 | 268 | -- {{{ my widgets 269 | -- {{{ Network speed indicator 270 | function update_netstat() 271 | local interval = netwidget_clock.timeout 272 | local netif, text 273 | local f = io.open('/proc/net/route') 274 | for line in f:lines() do 275 | netif = line:match('^(%w+)%s+00000000%s') 276 | if netif then 277 | break 278 | end 279 | end 280 | f:close() 281 | 282 | if netif then 283 | local down, up 284 | f = io.open('/proc/net/dev') 285 | for line in f:lines() do 286 | -- Match wmaster0 as well as rt0 (multiple leading spaces) 287 | local name, recv, send = string.match(line, "^%s*(%w+):%s+(%d+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)") 288 | if name == netif then 289 | if netdata[name] == nil then 290 | -- Default values on the first run 291 | netdata[name] = {} 292 | down, up = 0, 0 293 | else 294 | down = (recv - netdata[name][1]) / interval 295 | up = (send - netdata[name][2]) / interval 296 | end 297 | netdata[name][1] = recv 298 | netdata[name][2] = send 299 | break 300 | end 301 | end 302 | f:close() 303 | down = string.format('%.1f', down / 1024) 304 | up = string.format('%.1f', up / 1024) 305 | text = '↓'.. down ..''.. up ..'' 306 | else 307 | netdata = {} -- clear as the interface may have been reset 308 | text = '(No network)' 309 | end 310 | netwidget:set_markup(text) 311 | end 312 | netdata = {} 313 | netwidget = fixwidthtextbox('(net)') 314 | netwidget.width = 100 * scale 315 | netwidget:set_align('center') 316 | netwidget_clock = timer({ timeout = 2 }) 317 | netwidget_clock:connect_signal("timeout", update_netstat) 318 | netwidget_clock:start() 319 | update_netstat() 320 | -- }}} 321 | 322 | -- {{{ memory usage indicator 323 | function update_memwidget() 324 | local meminfo = get_memory_usage() 325 | local free 326 | if meminfo.MemAvailable then 327 | -- Linux 3.14+ 328 | free = meminfo.MemAvailable 329 | else 330 | free = meminfo.MemFree + meminfo.Buffers + meminfo.Cached 331 | end 332 | local total = meminfo.MemTotal 333 | local percent = 100 - math.floor(free / total * 100 + 0.5) 334 | memwidget:set_markup('Mem '.. percent ..'%') 335 | end 336 | memwidget = fixwidthtextbox('Mem ??') 337 | memwidget.width = 55 * scale 338 | update_memwidget() 339 | mem_clock = timer({ timeout = 5 }) 340 | mem_clock:connect_signal("timeout", update_memwidget) 341 | mem_clock:start() 342 | -- }}} 343 | 344 | -- {{{ CPU Temperature 345 | function update_cputemp() 346 | local pipe = io.popen('sensors coretemp-isa-0000') 347 | if not pipe then 348 | cputempwidget:set_markup('CPU ERR℃') 349 | return 350 | end 351 | local temp = 0 352 | for line in pipe:lines() do 353 | local newtemp = line:match('^Core [^:]+:%s+%+([0-9.]+)°C') 354 | if newtemp then 355 | newtemp = tonumber(newtemp) 356 | if temp < newtemp then 357 | temp = newtemp 358 | end 359 | end 360 | end 361 | pipe:close() 362 | cputempwidget:set_markup('CPU '..temp..'℃') 363 | end 364 | cputempwidget = fixwidthtextbox('CPU ??℃') 365 | cputempwidget.width = 60 * scale 366 | update_cputemp() 367 | cputemp_clock = timer({ timeout = 5 }) 368 | cputemp_clock:connect_signal("timeout", update_cputemp) 369 | cputemp_clock:start() 370 | -- }}} 371 | 372 | --{{{ battery indicator, using the acpi command 373 | local battery_state = { 374 | -- Unknown = '? ', 375 | Unknown = '↯', 376 | Idle = '↯', 377 | Charging = '+ ', 378 | Discharging = '– ', 379 | } 380 | function update_batwidget() 381 | local pipe = io.popen('batstatus') 382 | if not pipe then 383 | batwidget:set_markup('ERR') 384 | return 385 | end 386 | 387 | local bats = {} 388 | local max_percent = 0 389 | local max_percent_index = 0 390 | local index = 0 391 | for line in pipe:lines() do 392 | index = index + 1 393 | local state, percent, rest = line:match('^BAT%d+:%s+([^,]+), ([0-9.]+)%%(.*)') 394 | if state then 395 | local t 396 | if rest ~= '' then 397 | t = rest:match('[1-9]*%d:%d+') 398 | end 399 | if not t then t = '' end 400 | percent = tonumber(percent) 401 | if percent > max_percent then 402 | max_percent = percent 403 | max_percent_index = index 404 | end 405 | table.insert(bats, {state, percent, t}) 406 | end 407 | end 408 | pipe:close() 409 | 410 | if index == 0 then 411 | batwidget:set_markup('ERR') 412 | return 413 | end 414 | 415 | if max_percent <= 30 then 416 | if bats[max_percent_index][1] == 'Discharging' then 417 | local t = os.time() 418 | if t - last_bat_warning > 60 * 5 then 419 | notify{ 420 | critical = true, 421 | title = "电量警报", 422 | text = '电池电量只剩下 ' .. max_percent .. '% 了!', 423 | } 424 | last_bat_warning = t 425 | end 426 | if max_percent <= 10 and not dont_hibernate then 427 | awful.util.spawn("systemctl hibernate") 428 | end 429 | end 430 | end 431 | local text = ' ' 432 | for i, v in ipairs(bats) do 433 | local percent = v[2] 434 | if percent <= 30 then 435 | percent = '' .. percent .. '' 436 | end 437 | text = text .. (battery_state[v[1]] or battery_state.Unknown) .. percent .. '%' 438 | .. (v[3] ~= '' and (' ' .. v[3]) or '') .. '' 439 | if i ~= #bats then 440 | text = text .. ' ' 441 | end 442 | end 443 | batwidget:set_markup(text) 444 | end 445 | batwidget = wibox.widget.textbox('↯??%') 446 | update_batwidget() 447 | bat_clock = timer({ timeout = 5 }) 448 | bat_clock:connect_signal("timeout", update_batwidget) 449 | bat_clock:start() 450 | -- }}} 451 | 452 | -- {{{ Volume Controller 453 | function volumectl (mode, widget) 454 | if mode == "update" then 455 | local f = io.popen("pamixer --get-volume") 456 | local volume = f:read("*all") 457 | f:close() 458 | if not tonumber(volume) then 459 | widget:set_markup("ERR") 460 | do return end 461 | end 462 | volume = string.format("% 3d", volume) 463 | 464 | f = io.popen("pamixer --get-mute") 465 | local muted = f:read("*all") 466 | f:close() 467 | if muted:gsub('%s+', '') == "false" then 468 | volume = '♫' .. volume .. "%" 469 | else 470 | volume = '♫' .. volume .. "M" 471 | end 472 | widget:set_markup(volume) 473 | elseif mode == "up" then 474 | local f = io.popen("pamixer --allow-boost --increase 5") 475 | f:read("*all") 476 | f:close() 477 | volumectl("update", widget) 478 | elseif mode == "down" then 479 | local f = io.popen("pamixer --allow-boost --decrease 5") 480 | f:read("*all") 481 | f:close() 482 | volumectl("update", widget) 483 | else 484 | local f = io.popen("pamixer --toggle-mute") 485 | f:read("*all") 486 | f:close() 487 | volumectl("update", widget) 488 | end 489 | end 490 | volume_clock = timer({ timeout = 10 }) 491 | volume_clock:connect_signal("timeout", function () volumectl("update", volumewidget) end) 492 | volume_clock:start() 493 | 494 | volumewidget = fixwidthtextbox('(volume)') 495 | volumewidget.width = 48 * scale 496 | volumewidget:set_align('right') 497 | volumewidget:buttons(awful.util.table.join( 498 | awful.button({ }, 4, function () volumectl("up", volumewidget) end), 499 | awful.button({ }, 5, function () volumectl("down", volumewidget) end), 500 | awful.button({ }, 3, function () awful.util.spawn("pavucontrol") end), 501 | awful.button({ }, 1, function () volumectl("mute", volumewidget) end) 502 | )) 503 | volumectl("update", volumewidget) 504 | --}}} 505 | 506 | -- {{{ GitHub contribution indicator 507 | github_contributed = awful.util.getdir("config") .. "/image/github_contributed.png" 508 | github_not_contributed = awful.util.getdir("config") .. "/image/github_not_contributed.png" 509 | github_widget = wibox.widget.imagebox() 510 | function update_github(has_contributions) 511 | if has_contributions then 512 | github_widget:set_image(github_contributed) 513 | else 514 | github_widget:set_image(github_not_contributed) 515 | end 516 | end 517 | update_github(false) 518 | -- }}} 519 | -- }}} 520 | 521 | -- {{{ Create a wibox for each screen and add it 522 | mywibox = {} 523 | mypromptbox = {} 524 | mylayoutbox = {} 525 | mytaglist = {} 526 | mytaglist.buttons = awful.util.table.join( 527 | awful.button({ }, 1, awful.tag.viewonly), 528 | awful.button({ modkey }, 1, awful.client.movetotag), 529 | awful.button({ }, 3, awful.tag.viewtoggle), 530 | awful.button({ modkey }, 3, awful.client.toggletag), 531 | awful.button({ }, 4, function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end), 532 | awful.button({ }, 5, function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end) 533 | ) 534 | mytasklist = {} 535 | mytasklist.buttons = awful.util.table.join( 536 | awful.button({ }, 1, function (c) 537 | if c == client.focus and not c.minimized then 538 | c.minimized = true 539 | else 540 | -- Without this, the following 541 | -- :isvisible() makes no sense 542 | c.minimized = false 543 | if not c:isvisible() then 544 | awful.tag.viewonly(c:tags()[1]) 545 | end 546 | -- This will also un-minimize 547 | -- the client, if needed 548 | client.focus = c 549 | c:raise() 550 | end 551 | end), 552 | awful.button({ }, 2, function (c) 553 | c:kill() 554 | end), 555 | awful.button({ }, 3, function () 556 | if instance then 557 | instance:hide() 558 | instance = nil 559 | else 560 | instance = awful.menu.clients({ width=250 * scale }) 561 | end 562 | end), 563 | awful.button({ }, 4, function () 564 | awful.client.focus.byidx(1) 565 | if client.focus then client.focus:raise() end 566 | end), 567 | awful.button({ }, 5, function () 568 | awful.client.focus.byidx(-1) 569 | if client.focus then client.focus:raise() end 570 | end)) 571 | 572 | for s = 1, screen.count() do 573 | -- Create a promptbox for each screen 574 | mypromptbox[s] = awful.widget.prompt() 575 | -- Create an imagebox widget which will contains an icon indicating which layout we're using. 576 | -- We need one layoutbox per screen. 577 | mylayoutbox[s] = awful.widget.layoutbox(s) 578 | mylayoutbox[s]:buttons(awful.util.table.join( 579 | awful.button({ }, 1, function () awful.layout.inc(layouts, 1) end), 580 | awful.button({ }, 3, function () awful.layout.inc(layouts, -1) end), 581 | awful.button({ }, 4, function () awful.layout.inc(layouts, 1) end), 582 | awful.button({ }, 5, function () awful.layout.inc(layouts, -1) end))) 583 | -- Create a taglist widget 584 | mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons) 585 | 586 | -- Create a tasklist widget 587 | mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons) 588 | 589 | -- Create the wibox 590 | mywibox[s] = awful.wibox({ position = "top", screen = s, height = 18 * scale }) 591 | if s == eink_screen then 592 | mywibox[s]:set_fg('#ffffff') 593 | end 594 | 595 | -- Widgets that are aligned to the left 596 | local left_layout = wibox.layout.fixed.horizontal() 597 | left_layout:add(mylauncher) 598 | left_layout:add(mytaglist[s]) 599 | left_layout:add(mypromptbox[s]) 600 | 601 | -- Widgets that are aligned to the right 602 | local right_layout = wibox.layout.fixed.horizontal() 603 | if s ~= eink_screen then 604 | right_layout:add(memwidget) 605 | right_layout:add(cputempwidget) 606 | right_layout:add(batwidget) 607 | right_layout:add(netwidget) 608 | right_layout:add(volumewidget) 609 | end 610 | if s == main_screen then right_layout:add(wibox.widget.systray()) end 611 | if s == eink_screen then 612 | mytextclock2 = awful.widget.textclock(" %Y年%m月%d日 %H:%M %A ", 1) 613 | right_layout:add(mytextclock2) 614 | else 615 | right_layout:add(mytextclock) 616 | right_layout:add(github_widget) 617 | end 618 | right_layout:add(mylayoutbox[s]) 619 | 620 | -- Now bring it all together (with the tasklist in the middle) 621 | local layout = wibox.layout.align.horizontal() 622 | layout:set_left(left_layout) 623 | layout:set_middle(mytasklist[s]) 624 | layout:set_right(right_layout) 625 | 626 | mywibox[s]:set_widget(layout) 627 | end -- }}} 628 | -- }}} 629 | 630 | -- {{{ Mouse bindings 631 | root.buttons(awful.util.table.join( 632 | awful.button({ }, 3, function () mymainmenu:toggle() end), 633 | awful.button({ }, 4, awful.tag.viewprev), 634 | awful.button({ }, 5, awful.tag.viewnext) 635 | )) 636 | -- }}} 637 | 638 | -- {{{ Key bindings 639 | -- {{{ Functions 640 | local movebyrelidx = function (n, view) -- {{{ 641 | -- view: 要转到那个 tag 吗? 642 | local screen = mouse.screen 643 | local which = (revtags[screen][awful.tag.selected()]+n) % #tags[screen] 644 | if which == 0 then which = #tags[screen] end 645 | if client.focus and tags[client.focus.screen][which] then 646 | awful.client.movetotag(tags[client.focus.screen][which]) 647 | end 648 | if view and tags[screen][which] then 649 | awful.tag.viewonly(tags[screen][which]) 650 | end 651 | end -- }}} 652 | 653 | local keynumber_reg = function (i, which) -- {{{ 654 | if not which then 655 | which = i 656 | end 657 | globalkeys = awful.util.table.join(globalkeys, 658 | awful.key({ modkey }, i, 659 | function () 660 | local screen = mouse.screen 661 | if tags[screen][which] then 662 | awful.tag.viewonly(tags[screen][which]) 663 | end 664 | end), 665 | awful.key({ modkey, "Control" }, i, 666 | function () 667 | local screen = mouse.screen 668 | if tags[screen][which] then 669 | awful.tag.viewtoggle(tags[screen][which]) 670 | end 671 | end), 672 | awful.key({ modkey, "Shift" }, i, 673 | -- 移动窗口后跳转过去 674 | function () 675 | if client.focus and tags[client.focus.screen][which] then 676 | awful.client.movetotag(tags[client.focus.screen][which]) 677 | end 678 | local screen = mouse.screen 679 | if tags[screen][which] then 680 | awful.tag.viewonly(tags[screen][which]) 681 | end 682 | end), 683 | awful.key({ modkey, "Mod1" }, i, 684 | -- 只移动窗口,不跳转过去 685 | function () 686 | if client.focus and tags[client.focus.screen][which] then 687 | awful.client.movetotag(tags[client.focus.screen][which]) 688 | end 689 | end), 690 | awful.key({ modkey, "Control", "Shift" }, i, 691 | function () 692 | if client.focus and tags[client.focus.screen][which] then 693 | awful.client.toggletag(tags[client.focus.screen][which]) 694 | end 695 | end)) 696 | end -- }}} 697 | 698 | -- {{{ per client keys 699 | tm_keys = { 700 | ['alt+1'] = 'ctrl+1', 701 | ['alt+2'] = 'ctrl+2', 702 | ['alt+3'] = 'ctrl+3', 703 | ['alt+4'] = 'ctrl+4', 704 | ['alt+5'] = 'ctrl+5', 705 | ['alt+6'] = 'ctrl+6', 706 | ['alt+7'] = 'ctrl+7', 707 | ['alt+8'] = 'ctrl+8', 708 | ['alt+9'] = 'ctrl+9', 709 | -- 上/下一个标签页 710 | ['ctrl+Page_Up'] = 'ctrl+Left', 711 | ['ctrl+Page_Down'] = 'ctrl+Right', 712 | } 713 | -- not work, see https://bugs.launchpad.net/ubuntu/+source/xdotool/+bug/1011333 714 | evince_keys = { 715 | b = 'Page_Up', 716 | } 717 | emacs_keys = { 718 | ['ctrl+f'] = 'Right', 719 | ['ctrl+b'] = 'Left', 720 | ['ctrl+p'] = 'Up', 721 | ['ctrl+n'] = 'Down', 722 | ['ctrl+a'] = 'ctrl+Home', 723 | ['ctrl+e'] = 'ctrl+End', 724 | -- the following two doesn't work with Qt (4 & 5) programs 725 | ['alt+f'] = 'ctrl+Right', 726 | ['alt+b'] = 'ctrl+Left', 727 | } 728 | -- }}} 729 | -- }}} 730 | 731 | -- {{{ globalkeys 732 | globalkeys = awful.util.table.join( 733 | awful.key({ modkey, }, "Left", awful.tag.viewprev ), 734 | awful.key({ modkey, }, "Right", awful.tag.viewnext ), 735 | awful.key({ modkey, }, "Tab", awful.tag.history.restore), 736 | 737 | awful.key({ modkey, }, "j", 738 | function () 739 | awful.client.focus.byidx( 1) 740 | if client.focus then client.focus:raise() end 741 | end), 742 | awful.key({ modkey, }, "k", 743 | function () 744 | awful.client.focus.byidx(-1) 745 | if client.focus then client.focus:raise() end 746 | end), 747 | awful.key({ modkey, }, "w", function () mymainmenu:show() end), 748 | 749 | -- Layout manipulation 750 | awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end), 751 | awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end), 752 | awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end), 753 | awful.key({ modkey, }, "o", function () awful.screen.focus_relative( 1) end), 754 | awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end), 755 | awful.key({ modkey, }, "u", awful.client.urgent.jumpto), 756 | awful.key({ modkey, }, "Escape", 757 | function () 758 | awful.client.focus.history.previous() 759 | if client.focus then 760 | client.focus:raise() 761 | end 762 | end), 763 | 764 | -- Standard program 765 | awful.key({ modkey, }, "Return", 766 | function () 767 | -- Go and find a terminal for me 768 | myutil.run_or_raise("gnome-terminal --role=TempTerm --geometry=80x24+401+205", { role = "TempTerm" }) 769 | end), 770 | awful.key({ modkey, "Control" }, "r", awesome.restart), 771 | awful.key({ modkey, "Control" }, "q", awesome.quit), 772 | 773 | awful.key({ modkey, }, "l", awful.tag.viewnext), 774 | awful.key({ modkey, }, "h", awful.tag.viewprev), 775 | awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1) end), 776 | awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end), 777 | awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1) end), 778 | awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end), 779 | awful.key({ modkey, }, "space", function () awful.layout.inc(layouts, 1) end), 780 | awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end), 781 | awful.key({ modkey, "Shift" }, "s", 782 | function () 783 | -- because they may be not focusable 784 | local c = mouse.object_under_pointer() 785 | if c then 786 | c.sticky = not c.sticky 787 | end 788 | end), 789 | 790 | -- Prompt 791 | awful.key({ modkey, "Shift" }, "r", function () mypromptbox[mouse.screen]:run() end), 792 | awful.key({ "Mod1" }, "F2", function () awful.util.spawn('xfce4-appfinder', false) end), 793 | awful.key({ "Mod1" }, "space", function () awful.util.spawn('xfce4-appfinder', false) end), 794 | 795 | awful.key({ modkey, "Shift" }, "x", function () awful.util.spawn('openmsg_qq.py', false) end), 796 | -- Menubar 797 | awful.key({ modkey, "Mod1" }, "p", function() menubar.show() end), 798 | 799 | -- Switching tags 800 | awful.key({ modkey, }, "p", awful.tag.viewprev ), 801 | awful.key({ modkey, }, "n", awful.tag.viewnext ), 802 | awful.key({ modkey, "Shift" }, "p", 803 | function () 804 | movebyrelidx(-1, true) 805 | end), 806 | awful.key({ modkey, "Shift" }, "n", 807 | function () 808 | movebyrelidx(1, true) 809 | end), 810 | 811 | -- Screenshot 812 | awful.key({ }, "Print", 813 | function () 814 | awful.util.spawn_with_shell('flameshot gui') 815 | end), 816 | 817 | -- Alt-Tab 818 | awful.key({ "Mod1", }, "Tab", 819 | function () 820 | awful.client.focus.byidx( 1) 821 | if client.focus then client.focus:raise() end 822 | end), 823 | awful.key({ "Mod1", "Shift" }, "Tab", 824 | function () 825 | awful.client.focus.byidx(-1) 826 | if client.focus then client.focus:raise() end 827 | end), 828 | 829 | -- Unminimize clients 830 | awful.key({ modkey, "Control" }, "m", 831 | function () 832 | local allclients = client.get(mouse.screen) 833 | for _, c in ipairs(allclients) do 834 | if c.minimized and c:tags()[mouse.screen] == awful.tag.selected(mouse.screen) then 835 | c.minimized = false 836 | client.focus = c 837 | c:raise() 838 | return 839 | end 840 | end 841 | end), 842 | 843 | -- My programs 844 | awful.key({ modkey, }, "g", function () awful.util.spawn("gvim") end), 845 | awful.key({ "Control", "Mod1", "Shift" }, "x", function () awful.util.spawn("xkill") end), 846 | awful.key({ "Control", "Mod1" }, "l", function () awful.util.spawn("lockscreen") end), 847 | awful.key({ modkey, }, "x", function () awful.util.spawn("openmsg.py", false) end), 848 | awful.key({ modkey, }, "t", function () awful.util.spawn(terminal) end), 849 | awful.key({ modkey, "Shift" }, "Return", 850 | function () 851 | awful.util.spawn("gnome-terminal --role=TempTerm --geometry=80x24+343+180") 852 | end), 853 | 854 | -- htop 855 | awful.key({ modkey, }, "z", 856 | function () 857 | if client.focus and client.focus.role == 'FullScreenHtop' then 858 | awful.client.movetotag(tags[mouse.screen][10], client.focus) 859 | else 860 | myutil.run_or_raise("gnome-terminal --role=FullScreenHtop -- htop", { role = "FullScreenHtop" }) 861 | end 862 | end), 863 | 864 | -- My floating windows -> tag10 865 | awful.key({ modkey, }, "q", 866 | function () 867 | local c = client.focus 868 | if not c then return end 869 | if c.role == 'FullScreenHtop' or c.role == 'TempTerm' then 870 | awful.client.movetotag(tags[mouse.screen][10], c) 871 | end 872 | end), 873 | 874 | awful.key({ modkey }, "d", function () 875 | awful.util.spawn('sdcv-notify') 876 | end), 877 | awful.key({ modkey, "Shift" }, "d", function () 878 | awful.util.spawn('ydcv-notify') 879 | end), 880 | 881 | -- Volume 882 | awful.key({ }, 'XF86AudioRaiseVolume', function () volumectl("up", volumewidget) end), 883 | awful.key({ }, 'XF86AudioLowerVolume', function () volumectl("down", volumewidget) end), 884 | awful.key({ }, 'XF86AudioMute', function () volumectl("mute", volumewidget) end), 885 | 886 | -- awful.key({ }, 'XF86AudioPause', function () awful.util.spawn('playerctl pause', false) end), 887 | -- awful.key({ }, 'XF86AudioPlay', function () awful.util.spawn_with_shell('playerctl play || playmusic -q', false) end), 888 | -- awful.key({ }, 'XF86AudioNext', function () awful.util.spawn('playerctl next', false) end), 889 | -- awful.key({ }, 'XF86AudioPrev', function () awful.util.spawn('playerctl previous', false) end), 890 | 891 | awful.key({ }, 'XF86MonBrightnessUp', function () awful.util.spawn('monitor-brightness up', false) end), 892 | awful.key({ }, 'XF86MonBrightnessDown', function () awful.util.spawn('monitor-brightness down', false) end) 893 | ) -- }}} 894 | 895 | -- {{{ clientkeys 896 | clientkeys = awful.util.table.join( 897 | awful.key({ modkey, }, "f", function (c) c.fullscreen = not c.fullscreen end), 898 | awful.key({ modkey, }, "c", function (c) c:kill() end), 899 | awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ), 900 | awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end), 901 | awful.key({ modkey, "Shift" }, "o", awful.client.movetoscreen ), 902 | awful.key({ modkey, }, "a", function (c) c.above = not c.above end), 903 | awful.key({ modkey, }, "s", function (c) c.sticky = not c.sticky end), 904 | awful.key({ modkey, "Shift" }, "m", 905 | function (c) 906 | -- The client currently has the input focus, so it cannot be 907 | -- minimized, since minimized clients can't have the focus. 908 | c.minimized = true 909 | end), 910 | awful.key({ modkey, }, "m", 911 | function (c) 912 | c.maximized_horizontal = not c.maximized_horizontal 913 | c.maximized_vertical = not c.maximized_vertical 914 | end), 915 | awful.key({ modkey, "Shift" }, "c", 916 | function (c) 917 | if not awful.client.floating.get(c) then return end 918 | awful.placement.centered(c) 919 | end) 920 | ) -- }}} 921 | 922 | -- {{{ Switching to the numbered tag 923 | do 924 | local keynumber = math.min(9, #tags[1]); 925 | for i = 1, keynumber do 926 | keynumber_reg(i) 927 | end 928 | if #tags[1] >= 10 then 929 | keynumber_reg(0, 10) 930 | end 931 | end 932 | -- }}} 933 | 934 | -- {{{ clientbuttons 935 | clientbuttons = awful.util.table.join( 936 | awful.button({ }, 1, function (c) 937 | client.focus = c 938 | if c.class and (c.class == 'Gimp' or c.class == 'Gimp-2.8') then 939 | else 940 | c:raise() 941 | end 942 | end), 943 | awful.button({ modkey }, 1, awful.mouse.client.move), 944 | awful.button({ modkey }, 2, function (c) client.focus = c; c:kill() end), 945 | awful.button({ modkey }, 3, function (c) awful.mouse.client.resize(c, "bottom_right") end)) 946 | -- }}} 947 | 948 | -- Set keys 949 | root.keys(globalkeys) 950 | -- }}} 951 | 952 | -- {{{ Rules 953 | local old_filter = awful.client.focus.filter 954 | function myfocus_filter(c) 955 | if old_filter(c) then 956 | -- TM.exe completion pop-up windows 957 | if (c.instance == 'tm.exe' or c.instance == 'TIM.exe') 958 | and c.above and c.skip_taskbar 959 | and (c.type == 'normal' or c.type == 'dialog') -- dialog type is for tooltip windows 960 | and (c.class == 'qq.exe' or c.class == 'QQ.exe' or c.class == 'TIM.exe') then 961 | return nil 962 | -- This works with tooltips and some popup-menus 963 | elseif c.class == 'Wine' and c.above == true then 964 | return nil 965 | elseif c.class == 'WeChat.exe' and ( 966 | c.name == 'CMenuWnd' or not c.name 967 | or c.name == 'SessionChatRoomDetailWnd' 968 | ) then -- 微信菜单 969 | c.border_width = 0 970 | do return nil end 971 | elseif (c.class == 'Wine' or c.class == 'QQ.exe' or c.class == 'qq.exe') 972 | and c.type == 'dialog' 973 | and c.skip_taskbar == true 974 | and c.size_hints.max_width and c.size_hints.max_width < 160 975 | then 976 | -- for popup item menus of Photoshop CS5 977 | return nil 978 | elseif c.class == 'TelegramDesktop' and c.above == true and c.name == 'Media viewer' then 979 | -- Telegram media preview (https://t.me/archlinuxcn_group/1823691) 980 | c.fullscreen = true 981 | return c 982 | elseif c.class == 'TelegramDesktop' and c.above == true then 983 | -- Telegram picture-in-picture 984 | c.border_width = 0 985 | return c 986 | elseif c.skip_taskbar and c.instance == 'Popup' and c.class == 'Firefox' then 987 | -- popups for Settings page in Firefox 988 | return nil 989 | elseif c.class == 'Key-mon' then 990 | return nil 991 | else 992 | return c 993 | end 994 | end 995 | end 996 | awful.client.focus.filter = myfocus_filter 997 | awful.rules.rules = { 998 | -- All clients will match this rule. 999 | { 1000 | rule = { }, 1001 | properties = { 1002 | border_width = beautiful.border_width, 1003 | border_color = beautiful.border_normal, 1004 | focus = myfocus_filter, 1005 | keys = clientkeys, 1006 | buttons = clientbuttons, 1007 | } 1008 | }, { 1009 | rule = { class = "Screenruler" }, 1010 | properties = { 1011 | floating = true, 1012 | focus = false, 1013 | border_width = 0, 1014 | } 1015 | }, { 1016 | rule = { role = "FullScreenHtop" }, 1017 | properties = { 1018 | maximized_horizontal = true, 1019 | maximized_vertical = true, 1020 | } 1021 | }, { 1022 | rule = { class = "Firefox", instance = "firefox" }, 1023 | properties = { floating = true } 1024 | }, { 1025 | rule = { 1026 | class = "Firefox", 1027 | skip_taskbar = true, 1028 | role = 'Popup', 1029 | }, 1030 | properties = { 1031 | floating = true, 1032 | border_width = 0, 1033 | } 1034 | }, { 1035 | rule = { 1036 | class = "Nightly", 1037 | skip_taskbar = true, 1038 | role = 'Popup', 1039 | }, 1040 | properties = { 1041 | floating = true, 1042 | border_width = 0, 1043 | } 1044 | }, { 1045 | rule = { class = "Wireshark", name = "Wireshark" }, -- wireshark startup window 1046 | properties = { floating = true } 1047 | }, { 1048 | rule_any = { 1049 | instance = { 1050 | 'qq.exe', 'QQ.exe', 'TIM.exe', 'tim.exe', 1051 | 'QQExternal.exe', -- QQ 截图 1052 | 'deepin-music-player', 1053 | 'wechat.exe', 'wechatupdate.exe', 1054 | "megasync", "kruler", 1055 | }, 1056 | }, 1057 | properties = { 1058 | -- This, together with myfocus_filter, make the popup menus flicker taskbars less 1059 | -- Non-focusable menus may cause TM2013preview1 to not highlight menu 1060 | -- items on hover and crash. 1061 | -- Also for deepin-music, removing borders and floating pop-ups 1062 | focusable = true, 1063 | floating = true, 1064 | border_width = 0, 1065 | } 1066 | }, { 1067 | rule = { 1068 | -- mainly for picpick 1069 | class = "Wine", 1070 | above = true, 1071 | }, 1072 | properties = { 1073 | floating = true, 1074 | border_width = 0, 1075 | } 1076 | }, { 1077 | rule = { 1078 | -- for WinHex 1079 | class = "Wine", 1080 | instance = "WinHex.exe", 1081 | name = "数据解释器", 1082 | }, 1083 | properties = { 1084 | floating = true, 1085 | border_width = 0, 1086 | } 1087 | }, { 1088 | rule = { 1089 | class = "Wine", 1090 | skip_taskbar = true, 1091 | type = "dialog", 1092 | }, 1093 | callback = function (c) 1094 | if c.size_hints.max_width and c.size_hints.max_width < 160 then 1095 | -- for popup item menus of Photoshop CS5 1096 | c.border_width = 0 1097 | end 1098 | end, 1099 | }, { 1100 | rule = { 1101 | -- 白板的工具栏 1102 | name = 'frmPresentationTool', 1103 | instance = 'picpick.exe', 1104 | }, 1105 | properties = { 1106 | ontop = true, 1107 | } 1108 | }, { 1109 | rule_any = { 1110 | class = { 1111 | 'Flashplayer', 'Gnome-mplayer', 'Totem', 1112 | 'Eog', 'feh', 'Display', 'Gimp', 'Gimp-2.6', 1113 | 'Screenkey', 'TempTerm', 'AliWangWang', 1114 | 'Dia', 'Pavucontrol', 'Stardict', 'XEyes', 'Skype', 1115 | 'Xfce4-appfinder', 'Pinentry', 1116 | "/usr/lib/firefox/plugin-container", 1117 | "/opt/firefox-nightly/plugin-container", 1118 | 'WeChat.exe', 1119 | }, 1120 | name = { 1121 | '文件传输', 'Firefox 首选项', '暂存器', 'Keyboard', 1122 | }, 1123 | instance = { 1124 | 'Browser', -- 火狐的关于对话框 1125 | 'MATLAB', -- splash 1126 | }, 1127 | role = { 1128 | 'TempTerm', 1129 | }, 1130 | }, 1131 | properties = { 1132 | floating = true, 1133 | } 1134 | }, { 1135 | rule = { 1136 | instance = "xfce4-notifyd", 1137 | }, 1138 | properties = { 1139 | border_width = 0, 1140 | focus = false, 1141 | } 1142 | }, { 1143 | rule = { 1144 | class = "Key-mon", 1145 | }, 1146 | properties = { 1147 | border_width = 0, 1148 | focus = false, 1149 | focusable = false, 1150 | opacity = 0.65, 1151 | sticky = true, 1152 | } 1153 | }, 1154 | } 1155 | -- }}} 1156 | 1157 | -- {{{ Signals 1158 | -- Signal function to execute when a new client appears. 1159 | qqad_blocked = 0 1160 | client.connect_signal("manage", function (c, startup) 1161 | -- Enable sloppy focus 1162 | c:connect_signal("mouse::leave", function(c) 1163 | if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier 1164 | and myfocus_filter(c) then 1165 | client_unfocused = c.window 1166 | end 1167 | end) 1168 | 1169 | c:connect_signal("mouse::enter", function(c) 1170 | -- 如果离开后又进入同一窗口则忽略,这解决了由于输入条而造成的焦点移动 1171 | if client_unfocused ~= c.window 1172 | and awful.layout.get(c.screen) ~= awful.layout.suit.magnifier 1173 | and myfocus_filter(c) then 1174 | client.focus = c 1175 | end 1176 | end) 1177 | 1178 | if not startup then 1179 | -- Set the windows at the slave, 1180 | -- i.e. put it at the end of others instead of setting it master. 1181 | -- awful.client.setslave(c) 1182 | 1183 | -- Put windows in a smart way, only if they does not set an initial position. 1184 | if not c.size_hints.user_position and not c.size_hints.program_position then 1185 | awful.placement.no_overlap(c) 1186 | awful.placement.no_offscreen(c) 1187 | end 1188 | end 1189 | 1190 | if c.instance == 'empathy-chat' or (c.role == 'conversation' and c.class == 'Pidgin') then 1191 | local t 1192 | t = c:tags() 1193 | if #t == 1 and t[1] == tags[mouse.screen][6] then 1194 | awful.util.spawn_with_shell('sleep 0.1 && fcitx5-remote -T', false) 1195 | else 1196 | awful.client.movetotag(tags[mouse.screen][6], c) 1197 | end 1198 | elseif c.class == 'qTox' then 1199 | map_client_key(c, emacs_keys) 1200 | elseif c.class == 'Evince' then 1201 | map_client_key(c, evince_keys) 1202 | elseif c.name == '中文输入' then 1203 | awful.util.spawn_with_shell('sleep 0.05 && fcitx5-remote -T', false) 1204 | elseif c.instance == 'QQ.exe' or c.instance == 'qq.exe' then 1205 | if c.name and (c.name == '腾讯网迷你版' or c.name == '京东' or c.name:match('^腾讯.+新闻$')) then 1206 | qqad_blocked = qqad_blocked + 1 1207 | notify{ 1208 | title = "QQ广告屏蔽 " .. qqad_blocked, 1209 | text = "检测到一个符合条件的窗口,标题为".. c.name .."。", 1210 | } 1211 | c:kill() 1212 | else 1213 | map_client_key(c, tm_keys) 1214 | map_client_key(c, emacs_keys) 1215 | end 1216 | elseif c.class == 'MPlayer' or c.class == 'mpv' then 1217 | awful.client.floating.set(c, true) 1218 | awful.placement.centered(c) 1219 | elseif c.class == 'TelegramDesktop' then 1220 | awful.client.movetotag(tags[mouse.screen][1], c) 1221 | end 1222 | end) 1223 | 1224 | client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) 1225 | client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) 1226 | -- }}} 1227 | 1228 | -- {{{ other things 1229 | pcall(function() 1230 | package.cpath = package.cpath .. ';/home/lilydjwg/scripts/lua/cmod/?.so' 1231 | local clua = require('clua') 1232 | clua.setsubreap(true) 1233 | clua.ignore_SIGCHLD() 1234 | local pid = 1 1235 | while pid > 0 do 1236 | _, pid = clua.reap() 1237 | end 1238 | end) 1239 | dbus.release_name("session", "org.freedesktop.Notifications") 1240 | awful.util.spawn("awesomeup", false) 1241 | -- vim: set fdm=marker et sw=4: 1242 | -- }}} 1243 | -------------------------------------------------------------------------------- /scripts/update_github: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import os 4 | import time 5 | from subprocess import ( 6 | check_output, CalledProcessError, 7 | Popen, PIPE, 8 | ) 9 | import logging 10 | import logging.handlers 11 | 12 | import requests 13 | from lxml.html import fromstring 14 | 15 | try: 16 | import setproctitle 17 | setproctitle.setproctitle('update_github') 18 | except ImportError: 19 | pass 20 | 21 | logger = logging.getLogger(__name__) 22 | logger.addHandler(logging.handlers.SysLogHandler(address='/dev/log')) 23 | logger.setLevel(logging.INFO) 24 | 25 | def github_contributed(): 26 | user = os.environ['USER'] 27 | today = time.strftime('%Y-%m-%d') 28 | url = f'https://github.com/users/{user}/contributions' 29 | # url = f'https://github.com.cnpmjs.org/users/{user}/contributions' 30 | page = requests.get(url, timeout=30).text 31 | doc = fromstring(page) 32 | rect = doc.find('.//rect[@data-date="%s"]' % today) 33 | if rect is None: 34 | return False 35 | return int(rect.get('data-count')) > 0 36 | 37 | def get_dbus(): 38 | if 'DBUS_SESSION_BUS_ADDRESS' in os.environ: 39 | return True 40 | 41 | cmd = ['pgrep', '-U%d' % os.getuid(), '-x', 'awesome'] 42 | try: 43 | pid = check_output(cmd).strip().decode('ascii', errors='ignore') 44 | except CalledProcessError as e: 45 | if e.returncode == 1: 46 | # Awesome not running 47 | return False 48 | raise 49 | 50 | with open('/proc/%s/environ' % pid) as f: 51 | dbus = [x.split('=', 1)[1] for x in f.read().split('\0') if x.startswith('DBUS_SESSION_BUS_ADDRESS=')] 52 | if not dbus: 53 | logger.error("can't get DBUS_SESSION_BUS_ADDRESS of awesome (pid %s)", pid) 54 | return False 55 | dbus = dbus[0] 56 | 57 | os.environ['DBUS_SESSION_BUS_ADDRESS'] = dbus 58 | return True 59 | 60 | def main(): 61 | ok = get_dbus() 62 | if not ok: 63 | return 64 | 65 | try: 66 | s = str(github_contributed()).lower() 67 | except requests.exceptions.ConnectTimeout: 68 | logger.error('github timed out') 69 | return 70 | 71 | s = 'update_github(%s)' % s 72 | logger.info(s) 73 | 74 | client = Popen(['awesome-client'], stdin=PIPE) 75 | client.communicate(s.encode('ascii')) 76 | 77 | if __name__ == '__main__': 78 | main() 79 | -------------------------------------------------------------------------------- /theme.lua: -------------------------------------------------------------------------------- 1 | --------------------------- 2 | -- My awesome theme -- 3 | -- originally /usr/share/awesome/themes/default/theme.lua 4 | --------------------------- 5 | local awful = require("awful") 6 | local confdir = awful.util.getdir("config") 7 | 8 | theme = {} 9 | 10 | theme.font = "文泉驿正黑 8" 11 | 12 | theme.bg_normal = "#222222" 13 | theme.bg_focus = "#535d6c" 14 | theme.bg_urgent = "#222222" 15 | theme.bg_minimize = "#444444" 16 | theme.bg_systray = theme.bg_normal 17 | 18 | theme.fg_normal = "#aaaaaa" 19 | theme.fg_focus = "#ffffff" 20 | theme.fg_urgent = "#1e90ff" 21 | theme.fg_minimize = "#ffffff" 22 | 23 | theme.border_width = "2" 24 | theme.border_normal = "#000000" 25 | theme.border_focus = "#7f7fcc" 26 | theme.border_marked = "#91231c" 27 | 28 | -- There are other variable sets 29 | -- overriding the default one when 30 | -- defined, the sets are: 31 | -- [taglist|tasklist]_[bg|fg]_[focus|urgent] 32 | -- titlebar_[bg|fg]_[normal|focus] 33 | -- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color] 34 | -- mouse_finder_[color|timeout|animate_timeout|radius|factor] 35 | -- Example: 36 | --theme.taglist_bg_focus = "#ff0000" 37 | 38 | -- Display the taglist squares 39 | theme.taglist_squares_sel = confdir .. "/image/squarefw.png" 40 | theme.taglist_squares_unsel = confdir .. "/image/squarew.png" 41 | 42 | -- Variables set for theming the menu: 43 | -- menu_[bg|fg]_[normal|focus] 44 | -- menu_[border_color|border_width] 45 | theme.menu_submenu_icon = "/usr/share/awesome/themes/default/submenu.png" 46 | theme.menu_height = 15 47 | theme.menu_width = 100 48 | 49 | -- You can add as many variables as 50 | -- you wish and access them by using 51 | -- beautiful.variable in your rc.lua 52 | --theme.bg_widget = "#cc0000" 53 | 54 | -- Define the image to load 55 | theme.titlebar_close_button_normal = "/usr/share/awesome/themes/default/titlebar/close_normal.png" 56 | theme.titlebar_close_button_focus = "/usr/share/awesome/themes/default/titlebar/close_focus.png" 57 | 58 | theme.titlebar_ontop_button_normal_inactive = "/usr/share/awesome/themes/default/titlebar/ontop_normal_inactive.png" 59 | theme.titlebar_ontop_button_focus_inactive = "/usr/share/awesome/themes/default/titlebar/ontop_focus_inactive.png" 60 | theme.titlebar_ontop_button_normal_active = "/usr/share/awesome/themes/default/titlebar/ontop_normal_active.png" 61 | theme.titlebar_ontop_button_focus_active = "/usr/share/awesome/themes/default/titlebar/ontop_focus_active.png" 62 | 63 | theme.titlebar_sticky_button_normal_inactive = "/usr/share/awesome/themes/default/titlebar/sticky_normal_inactive.png" 64 | theme.titlebar_sticky_button_focus_inactive = "/usr/share/awesome/themes/default/titlebar/sticky_focus_inactive.png" 65 | theme.titlebar_sticky_button_normal_active = "/usr/share/awesome/themes/default/titlebar/sticky_normal_active.png" 66 | theme.titlebar_sticky_button_focus_active = "/usr/share/awesome/themes/default/titlebar/sticky_focus_active.png" 67 | 68 | theme.titlebar_floating_button_normal_inactive = "/usr/share/awesome/themes/default/titlebar/floating_normal_inactive.png" 69 | theme.titlebar_floating_button_focus_inactive = "/usr/share/awesome/themes/default/titlebar/floating_focus_inactive.png" 70 | theme.titlebar_floating_button_normal_active = "/usr/share/awesome/themes/default/titlebar/floating_normal_active.png" 71 | theme.titlebar_floating_button_focus_active = "/usr/share/awesome/themes/default/titlebar/floating_focus_active.png" 72 | 73 | theme.titlebar_maximized_button_normal_inactive = "/usr/share/awesome/themes/default/titlebar/maximized_normal_inactive.png" 74 | theme.titlebar_maximized_button_focus_inactive = "/usr/share/awesome/themes/default/titlebar/maximized_focus_inactive.png" 75 | theme.titlebar_maximized_button_normal_active = "/usr/share/awesome/themes/default/titlebar/maximized_normal_active.png" 76 | theme.titlebar_maximized_button_focus_active = "/usr/share/awesome/themes/default/titlebar/maximized_focus_active.png" 77 | 78 | theme.wallpaper = confdir .. "/image/background.png" 79 | 80 | -- You can use your own layout icons like this: 81 | theme.layout_fairh = "/usr/share/awesome/themes/default/layouts/fairhw.png" 82 | theme.layout_fairv = "/usr/share/awesome/themes/default/layouts/fairvw.png" 83 | theme.layout_floating = "/usr/share/awesome/themes/default/layouts/floatingw.png" 84 | theme.layout_magnifier = "/usr/share/awesome/themes/default/layouts/magnifierw.png" 85 | theme.layout_max = "/usr/share/awesome/themes/default/layouts/maxw.png" 86 | theme.layout_fullscreen = "/usr/share/awesome/themes/default/layouts/fullscreenw.png" 87 | theme.layout_tilebottom = "/usr/share/awesome/themes/default/layouts/tilebottomw.png" 88 | theme.layout_tileleft = "/usr/share/awesome/themes/default/layouts/tileleftw.png" 89 | theme.layout_tile = "/usr/share/awesome/themes/default/layouts/tilew.png" 90 | theme.layout_tiletop = "/usr/share/awesome/themes/default/layouts/tiletopw.png" 91 | theme.layout_spiral = "/usr/share/awesome/themes/default/layouts/spiralw.png" 92 | theme.layout_dwindle = "/usr/share/awesome/themes/default/layouts/dwindlew.png" 93 | theme.layout_empathy = confdir .. "/image/layout_empathy.png" 94 | 95 | theme.awesome_icon = "/usr/share/awesome/icons/awesome16.png" 96 | 97 | -- Define the icon theme for application icons. If not set then the icons 98 | -- from /usr/share/icons and /usr/share/icons/hicolor will be used. 99 | theme.icon_theme = nil 100 | 101 | return theme 102 | -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=80 103 | --------------------------------------------------------------------------------