For a long time my favorite Terminal program has been Guake. It is “a drop-down terminal for GNOME Desktop Environment.” It is always available and hidden when not in use. Simply press a button and it pops out from top of the screen, press again and it goes away.
To install Guake simply sudo apt-get install guake
The only problem I’ve had with it is on my desktop machine when two monitors are plugged in. Guake always defaults to the left monitor. It does a great job of determining the size of ‘monitor 1’, which in my case is a much smaller extra one to the side. To get Guake on my right-side monitor I had to tweak the source code. Here’s how you can do the same:
- Make a copy of theGuake program and put it in yourbin folder. I renamed mine toguake-dualmon but you can call it whatever you want.
1cp /usr/bin/guake ~/bin/guake-dualmon - Edit the copy in your preferred editor.
1nano ~/bin/guake-dualmon - Find the method definition def get_final_window_rect(self):
- First we will correctly position the terminal on the right monitor. Add one line at the end, between
window_rect.y = 0 and
return window_rect . The window_rect.x and window_rect.y variables tell theGuake window where to be located. Set window_rect.x to be the width of your left monitor and window_rect.y will depend on how offset the monitors are. I had to play with the ‘y’ setting to get it just right or the text starts off the top of the screen.
12window_rect.x = 1280window_rect.y = 24 - Now Guake will be positioned on your right monitor, but it will still be the size of the left one. In my case it was sized at 1280, and I needed it to be 1920. Divide your right monitor’s width by the left monitor’s width (ie. 1920/1280 = 150). Still within
get_final_window_rect(self): you will find the line
width = 100 . This setting is a percentage of your left monitor, so set it to the answer you got by dividing one width into the other. In my case it was:
1width = 150 - That’s it! Just make sure to always run your copy of the program, or better yet add it to your autostart so it runs automatically!
Here’s the new get_final_window_rect() method looks like with edited lines highlighted:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
def get_final_window_rect(self): """Gets the final size of the main window of guake. The height is the window_height property, width is window_width and the horizontal alignment is given by window_alignment. """ screen = self.window.get_screen() height = self.client.get_int(KEY('/general/window_height')) width = 150 halignment = self.client.get_int(KEY('/general/window_halignment')) # get the rectangle just from the first/default monitor in the # future we might create a field to select which monitor you # wanna use window_rect = screen.get_monitor_geometry(0) total_width = window_rect.width window_rect.height = window_rect.height * height / 100 window_rect.width = window_rect.width * width / 100 if width < total_width: if halignment == ALIGN_CENTER: window_rect.x = (total_width - window_rect.width) / 2 elif halignment == ALIGN_LEFT: window_rect.x = 0 elif halignment == ALIGN_RIGHT: window_rect.x = total_width - window_rect.width window_rect.y = 24 window_rect.x = 1280 return window_rect |
Have any questions? Feel free to ask in the comments below. Thanks for reading!
There are 4 comments on this post
Thank you! I modified the answer to make it always use my laptop screen by adding a method to the file and calling it in get_final_window_rect()
def find_builtin_monitor(self, screen):
"""
always try to position window on
small monitor
"""
monitors = screen.get_n_monitors()
if monitors < 2:
return (0, 0)
max_width = gtk.gdk.screen_width()
max_height = gtk.gdk.screen_height()
preffered = (1600, 900)
for mon in range(monitors):
tmp_rect = screen.get_monitor_geometry(mon)
if (tmp_rect.width, tmp_rect.height) == preffered:
return(mon, max_height - tmp_rect.height)
return (0, 0)
Then I use this function to :
monitor, yoffset = self.find_builtin_monitor(screen)
window_rect = screen.get_monitor_geometry(monitor)
...
window_rect.y = 0 + yoffset
I am using Y offset as my laptop screen is no 2 ( below ) big monitor.
Nice edits! Thanks for sharing!
When I first posted this I was new to Python, but now I've been learning Python Gtk. Your method inspires me to make more edits to Guake! If I come up with anything I will reply again and probably make a new post about it.
Just ran into this myself because my external monitor is above my laptop and has a smaller x dimension (not 16x9!) the display extends off the edge of my monitor.
This is actually a lot easier if your laptop monitor is your primary monitor. There is a combination of a subtle bug and an unnecessary assignment in the source code (both of which I will submit if I get around to it) that make it not work as intended.
In the get_final_window_rect func:
the line:
if width < total_width:
should really be:
if window_rect.width < total_width:
because width is hardcoded to 100 (%), in the code the alignment statements would ALWAYS be run (unless you had a very low resolution monitor!), but in reality they should NEVER be run (because it's hardcoded to never be < full width)!
Anyway, you can fix them up too, by making them adjust the x position returned from get_monitor_geometry rather than setting it absolutely. If at some point in the future you can configure the width % and alignment, it will work then.
The other thing you need to do is remove the window_rect.y = 0 statement. There is no reason I can think of to even have it. The .y is already correctly set to the monitor's 0 position relative to the screen size by the xxx_geometry() call.
The amended function works to always keep it on your primary display (as intended by the comments in the code):
def get_final_window_rect(self):
"""Gets the final size of the main window of guake. The height
is the window_height property, width is window_width and the
horizontal alignment is given by window_alignment.
"""
screen = self.window.get_screen()
height = self.client.get_int(KEY('/general/window_height'))
width = 100
halignment = self.client.get_int(KEY('/general/window_halignment'))
# get the rectangle just from the first/default monitor in the
# future we might create a field to select which monitor you
# wanna use
window_rect = screen.get_monitor_geometry(0)
total_width = window_rect.width
window_rect.height = window_rect.height * height / 100
window_rect.width = window_rect.width * width / 100
# This is never going to happen with hardcoded width=100(%) above
if window_rect.width < total_width:
if halignment == ALIGN_CENTER:
window_rect.x += (total_width - window_rect.width) / 2
elif halignment == ALIGN_LEFT:
window_rect.x += 0
elif halignment == ALIGN_RIGHT:
window_rect.x += total_width - window_rect.width
return window_rect
In re: to putting it on a non-primary display... If you have a desktop machine and want to hardcode that it should always be on a certain display you can just change the param to the get_monitory_geometry() to the # of the display. It seems like simply changing the param to (1) would work for the original article's intent.
That's not flexible enough for a laptop with frequent configuration changes, so maybe play around with which display to put it on based on the result of get_n_monitors(). For me, the default primary option works -- once the code does what was intended!
Well nevermind. The latest on github has a bunch of revisions that fix this bug and gives several options for multiple monitors. I recommend you update and you'll have it too!