Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions doc/terminator.1
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,30 @@ Specify the preferred size and position of Terminator\(cqs window;
see \fBX\fP(7).
.RE
.sp
\fB\-\-guake\-key\fP=\fIGUAKE_KEY\fP
.RS 4
A Guake like terminal mode where terminal can be toggled by a key.
Usage Example: terminator \-\-guake\-key="F8" \-\-guake\-side left \-\-guake\-width 700 \-\-guake\-height 800
.RE
.sp
\fB\-\-guake\-side\fP=\fIGUAKE_SIDE\fP
.RS 4
Set the preferred screen edge position of a terminal in Guake like mode.
Options: top, bottom, left, right
Default: top
.RE
.sp
\fB\-\-guake\-width\fP=\fIGUAKE_WIDTH\fP
.RS 4
Set the preferred width when using Guake like mode.
Default: 800
.RE
.sp
\fB\-\-guake\-height\fP=\fIGUAKE_HEIGHT\fP
.RS 4
Set the preferred height when using Guake like mode.
Default: 600
.sp
\fB\-e\fP \fICOMMAND\fP, \fB\-\-command\fP=\fICOMMAND\fP
.RS 4
Run the specified command instead of the default shell or profile
Expand Down
13 changes: 12 additions & 1 deletion terminatorlib/optionparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"""Terminator.optionparse - Parse commandline options"""

import argparse
from argparse import RawTextHelpFormatter
import sys
import os

Expand All @@ -37,7 +38,7 @@ def parse_options():
"""Parse the command line options"""
is_x_terminal_emulator = os.path.basename(sys.argv[0]) == 'x-terminal-emulator'

parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter)

parser.add_argument('-R', '--reload', action='store_true', dest='reload',
help=_('Reload terminator configuration'))
Expand All @@ -59,6 +60,16 @@ def parse_options():
parser.add_argument('--geometry', dest='geometry', type=str,
help=_('Set the preferred size and position of the window'
'(see X man page)'))
parser.add_argument('--guake-key', dest='guake_key', type=str,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, while I appreciate the command line args, the usual way of adding options to Terminator is to add them to the config file. That way they can also be easily added to the preferences dialog, so that one doesn't have to worry about command-line args

help=_('A Guake like terminal mode where terminal can be toggled by a key.\nUsage Example: terminator --guake-key="F8" --guake-side left --guake-width 700 --guake-height 800'))
parser.add_argument('--guake-side', dest='guake_side', default="top", type=str,
help=_('Set the preferred screen edge position of a terminal in Guake like mode.\nOptions: top, bottom, left, right\nDefault: top'))
parser.add_argument('--guake-width', dest='guake_width', default="800", type=str,
help=_('Set the preferred width when using Guake like mode. Default: 800'
'(see X man page)'))
parser.add_argument('--guake-height', dest='guake_height', default="600", type=str,
help=_('Set the preferred height when using Guake like mode. Default: 600'
'(see X man page)'))
if not is_x_terminal_emulator:
parser.add_argument('-e', '--command', dest='command',
help=_('Specify a command to execute inside the terminal'))
Expand Down
125 changes: 97 additions & 28 deletions terminatorlib/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,17 @@ def __init__(self):
# self.set_property('allow-shrink', True) # FIXME FOR GTK3, or do we need this actually?
icon_to_apply=''

self.register_callbacks()

self.apply_config()

self.title = WindowTitle(self)
self.title.update()

self.preventHide = False

self.preventHide = False

self.display = Gdk.Display().get_default()
self.mouse = self.display.get_default_seat().get_pointer()
self.guake_key = None

options = self.config.options_get()
if options:
Expand All @@ -92,15 +96,44 @@ def __init__(self):

if options.role:
self.set_role(options.role)

if options.forcedicon is not None:
icon_to_apply = options.forcedicon

if options.geometry:
if not self.parse_geometry(options.geometry):
err('Window::__init__: Unable to parse geometry: %s' %
err('Window::__init__: Unable to parse geometry: %s' %
options.geometry)

if options.guake_key:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move these command-line options to config file variables? We can still leave them as command-line options, but merge them into the config file variables with self.config.options_get()

self.guake_key = options.guake_key

if options.guake_side and options.guake_width and options.guake_height:
proceed_undecorated = True

if options.guake_side in ["top", "bottom", "left", "right"]:
self.guake_side = options.guake_side
else:
proceed_undecorated = False
err('Window::__init__: Unable to parse guake_side: %s' %
options.guake_side)

try:
self.guake_width = int(options.guake_width)
self.guake_height = int(options.guake_height)
except Exception as e:
proceed_undecorated = False
err('Window::__init__: Unable to parse guake_width: %s and/or guake_height: %s' %
options.guake_width, options.guake_height)

if proceed_undecorated:
self.set_decorated(False)
self.set_default_size(self.guake_width, self.guake_height)
else:
self.guake_key = None

self.register_callbacks()

self.apply_icon(icon_to_apply)
self.pending_set_rough_geometry_hint = False
self.hidefunc = self.hide
Expand All @@ -119,6 +152,35 @@ def do_set_property(self, prop, value):
else:
raise AttributeError('unknown property %s' % prop.name)

# NOTE: Gdk.VisibilityState.UNOBSCURED presumably isn't reliable due to transparency in moddern wms.
# Seems to work okay for our needs but should be kept in mind for future changes....
def _bind_window_to_position(self, widget, eve):
if eve.state == Gdk.VisibilityState.UNOBSCURED:
screen, mouse_x, mouse_y = self.mouse.get_position()
monitor = self.display.get_monitor_at_point(mouse_x, mouse_y)
window_w, window_h = self.guake_width, self.guake_height
geom_rect = monitor.get_geometry()
x, y, w, h = geom_rect.x, geom_rect.y, geom_rect.width, geom_rect.height

if not self.is_maximized() and not self.isfullscreen:
if self.guake_side == "top":
new_x = (w - (window_w + ((w - window_w)/2) )) + x
new_y = y
if self.guake_side == "bottom":
new_x = (w - (window_w + ((w - window_w)/2) )) + x
new_y = (h - window_h) + y
if self.guake_side == "left":
new_x = x
new_y = (h - (window_h + ((h - window_h)/2) )) + y
if self.guake_side == "right":
new_x = (w - window_w) + x
new_y = (h - (window_h + ((h - window_h)/2) )) + y
else:
new_x = x
new_y = y

self.move(new_x, new_y)

def register_callbacks(self):
"""Connect the GTK+ signals we care about"""
self.connect('key-press-event', self.on_key_press)
Expand All @@ -129,22 +191,29 @@ def register_callbacks(self):
self.connect('focus-out-event', self.on_focus_out)
self.connect('focus-in-event', self.on_focus_in)

if self.guake_key not in ('', None):
guake_unload_id = self.connect('visibility-notify-event', self._bind_window_to_position)

_hide_key = self.config['keybindings']['hide_window']
toggle_key = self.guake_key if self.guake_key not in ('', None) else _hide_key if _hide_key not in ('', None) else None

# Attempt to grab a global hotkey for hiding the window.
# If we fail, we'll never hide the window, iconifying instead.
if self.config['keybindings']['hide_window'] not in ('', None):
if display_manager() == 'X11':
try:
self.hidebound = Keybinder.bind(
self.config['keybindings']['hide_window'],
self.on_hide_window)
except (KeyError, NameError):
pass

if not self.hidebound:
err('Unable to bind hide_window key, another instance/window has it.')
self.hidefunc = self.iconify
else:
self.hidefunc = self.hide
if toggle_key and display_manager() == 'X11':
try:
self.hidebound = Keybinder.bind(toggle_key, self.on_hide_window)
except (KeyError, NameError):
...

if not self.hidebound:
err('Unable to bind hide_window key, another instance/window has it.')
self.hidefunc = self.iconify

if self.guake_key not in ('', None):
GObject.signal_handler_disconnect(self, guake_unload_id)
self.set_decorated(True)
else:
self.hidefunc = self.hide

def apply_config(self):
"""Apply various configuration options"""
Expand Down Expand Up @@ -335,7 +404,7 @@ def on_hide_window(self, data=None):
# pylint: disable-msg=W0613
def on_window_state_changed(self, window, event):
"""Handle the state of the window changing"""
self.isfullscreen = bool(event.new_window_state &
self.isfullscreen = bool(event.new_window_state &
Gdk.WindowState.FULLSCREEN)
self.ismaximised = bool(event.new_window_state &
Gdk.WindowState.MAXIMIZED)
Expand Down Expand Up @@ -394,7 +463,7 @@ def set_real_transparency(self, value=True):
visual = screen.get_rgba_visual()
if visual:
self.set_visual(visual)

def show(self, startup=False):
"""Undo the startup show request if started in hidden mode"""
#Present is necessary to grab focus when window is hidden from taskbar.
Expand Down Expand Up @@ -484,7 +553,7 @@ def split_axis(self, widget, vertical=True, cwd=None, sibling=None, widgetfirst=
container = maker.make('VPaned')
else:
container = maker.make('HPaned')

self.set_pos_by_ratio = True

if not sibling:
Expand All @@ -508,7 +577,7 @@ def split_axis(self, widget, vertical=True, cwd=None, sibling=None, widgetfirst=
for term in order:
container.add(term)
container.show_all()

while Gtk.events_pending():
Gtk.main_iteration_do(False)
sibling.grab_focus()
Expand Down Expand Up @@ -556,7 +625,7 @@ def zoom(self, widget, font_scale=True):
self.set_property('term_zoomed', True)

if font_scale:
widget.cnxids.new(widget, 'size-allocate',
widget.cnxids.new(widget, 'size-allocate',
widget.zoom_scale, self.zoom_data)

widget.grab_focus()
Expand Down Expand Up @@ -629,7 +698,7 @@ def rotate(self, widget, clockwise):

def get_terminals(self):
return(util.enumerate_descendants(self)[1])

def get_visible_terminals(self):
"""Walk down the widget tree to find all of the visible terminals.
Mostly using Container::get_visible_terminals()"""
Expand Down Expand Up @@ -719,7 +788,7 @@ def set_rough_geometry_hints(self):
extra_height = win_height - total_font_height

dbg('setting geometry hints: (ewidth:%s)(eheight:%s),\
(fwidth:%s)(fheight:%s)' % (extra_width, extra_height,
(fwidth:%s)(fheight:%s)' % (extra_width, extra_height,
font_width, font_height))
geometry = Gdk.Geometry()
geometry.base_width = extra_width
Expand Down Expand Up @@ -843,7 +912,7 @@ def ungroup_tab(self, widget):
if not maker.isinstance(notebook, 'Notebook'):
dbg('note in a notebook, refusing to ungroup tab')
return

self.set_groups(None, self.get_visible_terminals())

def move_tab(self, widget, direction):
Expand Down Expand Up @@ -876,7 +945,7 @@ def move_tab(self, widget, direction):
else:
err('unknown direction: %s' % direction)
return

notebook.reorder_child(child, page)

def navigate_terminal(self, terminal, direction):
Expand Down