Re-adding guake like functionality comit after bungled merge

This commit is contained in:
itdominator 2023-09-18 21:27:32 -05:00
parent 6d225c7aee
commit 9248fc9340
3 changed files with 132 additions and 29 deletions

View File

@ -90,6 +90,30 @@ Specify the preferred size and position of Terminator\(cqs window;
see \fBX\fP(7). see \fBX\fP(7).
.RE .RE
.sp .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 \fB\-e\fP \fICOMMAND\fP, \fB\-\-command\fP=\fICOMMAND\fP
.RS 4 .RS 4
Run the specified command instead of the default shell or profile Run the specified command instead of the default shell or profile

View File

@ -16,6 +16,7 @@
"""Terminator.optionparse - Parse commandline options""" """Terminator.optionparse - Parse commandline options"""
import argparse import argparse
from argparse import RawTextHelpFormatter
import sys import sys
import os import os
@ -37,7 +38,7 @@ def parse_options():
"""Parse the command line options""" """Parse the command line options"""
is_x_terminal_emulator = os.path.basename(sys.argv[0]) == 'x-terminal-emulator' 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', parser.add_argument('-R', '--reload', action='store_true', dest='reload',
help=_('Reload terminator configuration')) help=_('Reload terminator configuration'))
@ -59,6 +60,16 @@ def parse_options():
parser.add_argument('--geometry', dest='geometry', type=str, parser.add_argument('--geometry', dest='geometry', type=str,
help=_('Set the preferred size and position of the window' help=_('Set the preferred size and position of the window'
'(see X man page)')) '(see X man page)'))
parser.add_argument('--guake-key', dest='guake_key', type=str,
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: if not is_x_terminal_emulator:
parser.add_argument('-e', '--command', dest='command', parser.add_argument('-e', '--command', dest='command',
help=_('Specify a command to execute inside the terminal')) help=_('Specify a command to execute inside the terminal'))

View File

@ -77,13 +77,16 @@ class Window(Container, Gtk.Window):
# self.set_property('allow-shrink', True) # FIXME FOR GTK3, or do we need this actually? # self.set_property('allow-shrink', True) # FIXME FOR GTK3, or do we need this actually?
icon_to_apply='' icon_to_apply=''
self.register_callbacks()
self.apply_config() self.apply_config()
self.title = WindowTitle(self) self.title = WindowTitle(self)
self.title.update() 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() options = self.config.options_get()
if options: if options:
@ -101,6 +104,35 @@ class Window(Container, Gtk.Window):
err('Window::__init__: Unable to parse geometry: %s' % err('Window::__init__: Unable to parse geometry: %s' %
options.geometry) options.geometry)
if options.guake_key:
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.apply_icon(icon_to_apply)
self.pending_set_rough_geometry_hint = False self.pending_set_rough_geometry_hint = False
self.hidefunc = self.hide self.hidefunc = self.hide
@ -119,6 +151,35 @@ class Window(Container, Gtk.Window):
else: else:
raise AttributeError('unknown property %s' % prop.name) 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): def register_callbacks(self):
"""Connect the GTK+ signals we care about""" """Connect the GTK+ signals we care about"""
self.connect('key-press-event', self.on_key_press) self.connect('key-press-event', self.on_key_press)
@ -129,22 +190,29 @@ class Window(Container, Gtk.Window):
self.connect('focus-out-event', self.on_focus_out) self.connect('focus-out-event', self.on_focus_out)
self.connect('focus-in-event', self.on_focus_in) 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. # Attempt to grab a global hotkey for hiding the window.
# If we fail, we'll never hide the window, iconifying instead. # If we fail, we'll never hide the window, iconifying instead.
if self.config['keybindings']['hide_window'] not in ('', None): if toggle_key and display_manager() == 'X11':
if display_manager() == 'X11': try:
try: self.hidebound = Keybinder.bind(toggle_key, self.on_hide_window)
self.hidebound = Keybinder.bind( except (KeyError, NameError):
self.config['keybindings']['hide_window'], ...
self.on_hide_window)
except (KeyError, NameError):
pass
if not self.hidebound: if not self.hidebound:
err('Unable to bind hide_window key, another instance/window has it.') err('Unable to bind hide_window key, another instance/window has it.')
self.hidefunc = self.iconify self.hidefunc = self.iconify
else:
self.hidefunc = self.hide 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): def apply_config(self):
"""Apply various configuration options""" """Apply various configuration options"""