diff --git a/BrowserRefresh.py b/BrowserRefresh.py index 9fee847..aa44df2 100644 --- a/BrowserRefresh.py +++ b/BrowserRefresh.py @@ -50,6 +50,21 @@ def run(self, args, activate=True, if 'chrome' in browsers: refresher.chrome() + if 'chromium' in browsers and _os == 'Linux': + refresher.chromium() + + if 'konqueror' in browsers and _os == 'Linux': + refresher.konqueror() + + if 'midori' in browsers and _os == 'Linux': + refresher.midori() + + if 'qupzilla' in browsers and _os == 'Linux': + refresher.qupzilla() + + if 'vivaldi' in browsers and _os == 'Linux': + refresher.vivaldi() + if 'canary' in browsers and _os == 'Darwin': refresher.canary() @@ -65,6 +80,9 @@ def run(self, args, activate=True, if 'firefox' in browsers: refresher.firefox() + if 'nightly' in browsers and _os == 'Linux': + refresher.nightly() + if 'firefoxdev' in browsers and _os == 'Darwin': refresher.firefox_dev() @@ -77,5 +95,13 @@ def run(self, args, activate=True, if 'iron' in browsers and _os == 'Windows': refresher.iron() - if 'palemoon' in browsers and _os == 'Windows': + if 'palemoon' in browsers and _os in ['Windows', 'Linux']: refresher.palemoon() + + if _os == 'Linux': + for browser in browsers: + customWindow = browser.split(':')[1] if 'custom:' in browser else False + customCommand = customWindow.split(',')[1] if ',' in customWindow else False + customWindow = customWindow.split(',')[0] if ',' in customWindow else False + if customWindow: + refresher.custom(customWindow, customCommand) diff --git a/README.md b/README.md index da48739..ac349fc 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ git clone https://github.com/gcollazo/BrowserRefresh-Sublime.git "Browser Refres Install xdotool: ``` -sudo apt-get install xdotool +sudo apt-get install xdotool wmctrl ``` ### 2. Configure Key Bindings @@ -64,15 +64,28 @@ Specify which browsers to refresh on command. The default is `chrome` which will |---------------------------|--------------|-----------------| | Google Chrome | `chrome` | Mac, Win, Linux | | Google Chrome Canary | `canary` | Mac, Win | +| Chromium | `chromium | Linux | | Safari | `safari` | Mac, Win | | WebKit | `webkit` | Mac | | Firefox | `firefox` | Mac, Win, Linux | | Firefox Developer Edition | `firefoxdev` | Mac | -| Opera | `opera` | Mac, Win | +| Firefox Nightly | `nightly` | Linux | +| Opera | `opera` | Mac, Win, Linux | | Internet Explorer | `ie` | Win | | SRWare Iron | `iron` | Win | | Yandex | `yandex` | Mac | -| Pale Moon | `palemoon` | Win | +| Pale Moon | `palemoon` | Win,Linux | +| Konqueror | `konqueror` | Linux | +| Midori | `midori` | Linux | +| Qupzilla | `qupzilla` | Linux | +| Vivaldi | `vivaldi` | Linux | + +**Linux special** + +You can optionnally try to send any key on any window with a special browser argument +**"browsers" : ["custom:opera,ctrl+F5"]** + +Keep in mind this is only for convenience purpose, it is absolutely not garranteed this method actually works ## Contributions If you have the time to make this plugin better feel free to fork and submit a pull request. diff --git a/linux/__init__.py b/linux/__init__.py index eaf4908..f15f10a 100644 --- a/linux/__init__.py +++ b/linux/__init__.py @@ -1,15 +1,32 @@ import sublime -from subprocess import call - +from subprocess import call, Popen, PIPE, STDOUT class LinuxBrowserRefresh: def __init__(self, activate_browser): - # activate_browser is always true on Windows since you can't - # send keys to an inactive window programmatically. We ignore it. self.activate_browser = activate_browser def chrome(self): - self.SendKeysToAllWindows('google-chrome', 'F5') + # need to force ctrl+F5 here + self.SendKeyToAllWebkitBasedNavigators('google-chrome', 'ctrl+F5') + + def chromium(self): + # need to force ctrl+F5 here + self.SendKeyToAllWebkitBasedNavigators('chromium-browser', 'ctrl+F5') + + def konqueror(self): + # need to force ctrl+F5 here + self.SendKeyToAllWebkitBasedNavigators('konqueror', 'ctrl+F5') + + def midori(self): + self.SendKeyToAllWindows('midori', 'F5') + + def palemoon(self): + # need to force ctrl+F5 here + self.SendKeyToAllWindows('pale moon', 'F5') + + def qupzilla(self): + # need to force ctrl+F5 here + self.SendKeyToAllWebkitBasedNavigators('qupzilla', 'ctrl+F5') def iron(self): pass @@ -24,30 +41,119 @@ def safari64(self): # except NotImplemented("Safari64 support not implemented yet.") def firefox(self): - self.SendKeysToAllWindows('firefox', 'F5') + self.SendKeysToAllNamedWindows('firefox', 'F5') + + def nightly(self): + self.SendKeysToAllNamedWindows('nightly', 'F5') + + def vivaldi(self): + # need to force ctrl+F5 here + self.SendKeyToAllWebkitBasedNavigators('vivaldi', 'ctrl+F5') def opera(self): - pass - # except NotImplemented("Opera support not implemented yet.") + # need to force ctrl+F5 here + self.SendKeyToAllWebkitBasedNavigators('opera', 'ctrl+F5') def ie(self): pass # except NotImplemented("IE support not implemented yet.") - def SendKeysToAllWindows(self, cls, key): - "Sends the keystroke to all windows whose title matches the regex" + def custom(self, customWindow, customCommand): + customCommand = customCommand if customCommand else 'ctrl+R' + # Use the safer method + self.SendKeyToAllWebkitBasedNavigators(customWindow, customCommand) + + def getDesktop(self): + '''This method is here for compatibilty purpose + because sometime xdotool would throw + XGetWindowProperty[_NET_WM_DESKTOP] failed (code=1)''' + cmd = ['xdotool', 'get_desktop'] + try: + process = Popen(cmd, stdout=PIPE) + out, err = process.communicate() + return out.decode(encoding='UTF-8') + except Exception: + self.print_error(cmd) + return False + + def SendKeyToAllWebkitBasedNavigators(self, cls, key): + cmd = ['xdotool', 'search', + '--desktop', self.getDesktop(), + '--onlyvisible', + '--class', cls, + 'windowactivate', 'key', key] - cmd = ['xdotool', 'search', '--sync', '--onlyvisible', '--class', cls, 'windowfocus', 'key', key] + if self.activate_browser: + cmd += ['windowactivate'] + else: + # trick to bring sublime text back to front + # this avoids the webkit bug where you have + # to activatewindow before inputing key + call(['subl']) + + try: + call(cmd) + except Exception: + self.print_error(cmd) + + def SendKeyToAllWindows(self, cls, key): + cmd = ['xdotool', 'search', + '--desktop', self.getDesktop(), + '--onlyvisible', + '--class', cls, + 'key', key] if self.activate_browser: cmd += ['windowactivate'] - status_code = call(cmd) + try: + call(cmd) + except Exception: + self.print_error(cmd) + + def SendKeysToAllNamedWindows(self, cls, key): + "Sends the keystroke to all windows whose title matches the regex" + + cmd = ['wmctrl', '-l'] + try: + process = Popen(cmd, stdout=PIPE) + out, err = process.communicate() + except Exception: + self.print_error(cmd) + return + + process = Popen(['grep', '-ie', + '[-]\?[a-z0-9 ]*%s[a-z0-9 ]*$' % cls], + stdout=PIPE, stdin=PIPE) + process.stdin.write(out) + out, err = process.communicate() + + wID = "" + try: + wID = out.split()[0].decode(encoding='UTF-8') + except Exception: + # no window found + return + + cmd = ['xdotool', 'key', '--window', wID, key] + try: + call(cmd) + except Exception: + self.print_error(cmd) + return + + if self.activate_browser: + cmd = ['xdotool', 'windowactivate', wID] + try: + call(cmd) + except Exception: + self.print_error(cmd) + return - if status_code != 0: - sublime.error_message( - 'Browser Refresh cannot execute the specified program.\n\n' - '%s\n\n' - 'If program \'xdotool\' is currently not installed ' - 'you can install it by typing:\n\n' - 'sudo apt-get install xdotool' % " ".join(cmd)) + def print_error(prog, cmd): + sublime.error_message( + 'Browser Refresh cannot execute the specified program.\n\n' + '%s\n\n' + 'If program \'%s\' is currently not installed ' + 'you can install it by typing:\n\n' + 'sudo apt-get install %s' % (' '.join(cmd), cmd[0], cmd[0]))