How can I make firefox run in the background like chromium?
A known feature in Chromium is the option to make it run in the background, which makes it easier to open .
Is it possible to do the same with firefox (and other applications)?
Running an application in the background
The solution below will allow you to run firefox (or any other application) in the background, meaning: without a visible window. Nor will the application show in Dash as a running application:
If you pick Toggle Firefox however, the application will pop up immediately:
How it works
-
If the panel icon (indicator) starts up, it launches a new
firefox
window, but immediately hides it (including possible existingfirefox
windows) from the face of the earth, usingxdotool
:xdotool windowunmap <window_id>
This will not only hide the window, but also will hide the fact that
firefox
is running at all, since the unity launcher acts on visibly existing windows. - The indicator stores the id of all unmapped windows in
~/.config/hidden_windows
, to be mapped on the next time you choose Toggle Firefox from the menu.
The script
#!/usr/bin/env python3
import subprocess
import os
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3
import time
app = "firefox"
winsdir = os.path.join(os.environ["HOME"], ".config/hidden_windows")
try:
os.mkdir(winsdir)
except FileExistsError:
pass
def checkruns(app):
try:
return subprocess.check_output(["pgrep", app]).decode("utf-8").strip()
except subprocess.CalledProcessError:
for w in os.listdir(winsdir):
if w.startswith(app):
os.remove(os.path.join(winsdir, w))
def get_currentwins(pid):
wins = subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8").splitlines()
return [l.split()[0] for l in wins if pid in l]
def hide_currentwins(matches):
# open(os.path.join(winsdir, "windowlist"), "wt").write("\n".join(matches))
for w in matches:
open(os.path.join(winsdir, app+"_"+w), "wt")
subprocess.Popen(["xdotool", "windowunmap", w])
def run_app(app):
subprocess.Popen(app)
while True:
time.sleep(1)
pid = checkruns(app)
matches = get_currentwins(pid) if pid else None
if matches:
hide_currentwins(matches)
break
def restore_wins():
for w in [w for w in os.listdir(winsdir) if w.startswith(app)]:
wid = w.split("_")[-1]
subprocess.Popen(["xdotool", "windowmap", wid])
os.remove(os.path.join(winsdir, w))
def toggle_app(*args):
pid = checkruns(app)
if pid:
matches = get_currentwins(pid)
if matches:
hide_currentwins(matches)
else:
restore_wins()
else:
subprocess.Popen(app)
run_app(app)
class Indicator():
def __init__(self):
self.app = 'toggle_app'
self.indicator = AppIndicator3.Indicator.new(
self.app, app,
AppIndicator3.IndicatorCategory.OTHER)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.create_menu())
def create_menu(self):
self.menu = Gtk.Menu()
item_toggle = Gtk.MenuItem('Toggle '+app)
item_toggle.connect("activate", toggle_app)
self.menu.append(item_toggle)
sep1 = Gtk.SeparatorMenuItem()
self.menu.append(sep1)
item_quit = Gtk.MenuItem('Quit')
item_quit.connect('activate', self.stop)
self.menu.append(item_quit)
self.menu.show_all()
return self.menu
def stop(self, source):
Gtk.main_quit()
Indicator()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
How to use
-
The script needs both
wmctrl
andxdotool
sudo apt-get install wmctrl xdotool
Copy the script into an empty file, save it as
firefox_bg.py
-
Test_run the script by the command:
python3 /path/to/firefox_bg.py
-
If all works fine, add it to Startup Applications: Dash > Startup Applications > Add. Add the command:
/bin/bash -c "sleep 10 && python3 /path/to/firefox_bg.py"
Alternatively, copy the code below into an empty file, save it as
firefox_bgrunner.desktop
in~/usr/share/applications
, log out and back in.[Desktop Entry] Type=Application Exec=python3 /path/to/firefox_bg.py Name=Firefox Webbrowser Background Runner Icon=firefox StartupWMClasss=nonsense
*The last line,
StartupWMClasss=nonsense
is to make sureFirefox windows will appear under their own icon, not the one of the indicator
.No need to mention that you have to edit the
Exec=
line to reflect the real (absolute) path to where you storedfirefox_bg.py
Then you will have the panel runner available from Dash:
Other applications?
I tested the same procedure with gnome-terminal
andThunderbird
(the latter usually not the quickest to startup), and it works perfectly:
To use with other applications, simply edit the line:
app = "firefox"
Note however that some applications seem to check if their attempt to create a window succeeded, and create a second one if the first one is unmapped. This happened to me with Inkscape
.
The script can even then perfectly be used though, but would need a small edit. If anyone ever might need to use it with Inkscape
, please leave a comment.