mirror of
https://github.com/gryf/tabbedalt.git
synced 2026-04-27 17:13:30 +02:00
Compare commits
6 Commits
7e76d39402
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 57f5423dc4 | |||
| b811ca58f6 | |||
| 2cede3b996 | |||
| 2ba623a811 | |||
| 8da342b9b0 | |||
| a9eb5cee5d |
+8
-32
@@ -121,6 +121,10 @@ You can change those values but bear in mind, that first group should have
|
||||
timeout in seconds set higher, than middle one. You can also change symbols for
|
||||
those groups.
|
||||
|
||||
Tab activity can be disabled by setting::
|
||||
|
||||
URxvt.tabbedalt.disable-activity: true
|
||||
|
||||
Flickering
|
||||
~~~~~~~~~~
|
||||
|
||||
@@ -179,7 +183,7 @@ several keysyms mapped to the actions:
|
||||
* ``Shift-Up``: ``rename_tab`` - for tab title renaming
|
||||
* ``Shift-Left``: ``prev_tab`` - for jumping to previous tab
|
||||
* ``Shift-Right``: ``next_tab`` - for jumping to next tab
|
||||
* ``Shift-Left``: ``move_tab_left`` - for moving tab to the left
|
||||
* ``Control-Left``: ``move_tab_left`` - for moving tab to the left
|
||||
* ``Control-Right``: ``move_tab_right`` - for moving tab to the right
|
||||
* ``Control-1..0``: ``jump_to_tab`` - for quickly jumping into first tenth tabs
|
||||
|
||||
@@ -196,9 +200,11 @@ It might be wise to define own shortcuts before disabling default keys.
|
||||
``tab-command``, for example::
|
||||
|
||||
URxvt.keysym.Control-t: tabbedalt:new_tab:htop:htop
|
||||
URxvt.keysym.Control-Shift-R: tabbedalt:new_tab:root:sudo su -
|
||||
|
||||
where pressing control+t it will run new tab with title ``htop`` and command
|
||||
``htop``.
|
||||
``htop``, while pressing control+shift+r will create tab with ``root``
|
||||
title and run ``sudo su -`` inside.
|
||||
|
||||
Both title and command may be omitted. If so, default title ``shell`` will
|
||||
be used in absence of title, and default shell will be run on missing
|
||||
@@ -292,36 +298,6 @@ or `kdialog`_::
|
||||
|
||||
or… any other dialog programs which fulfill the above criteria.
|
||||
|
||||
Creating specific commands/shells
|
||||
---------------------------------
|
||||
|
||||
Let's assume, that one want to add three kind of custom shells:
|
||||
|
||||
* simple one (default shell in the system),
|
||||
* midnight commander,
|
||||
* root (namely - su command)
|
||||
|
||||
A way to do this is to associate keystroke for it in ``.Xdefaults`` using
|
||||
urxvts ``keysym`` option, and the actions described above::
|
||||
|
||||
URxvt.keysym.Control-Shift-N: tabbedalt:new_tab:shell
|
||||
URxvt.keysym.Control-Shift-R: tabbedalt:new_tab:root:su -
|
||||
URxvt.keysym.Control-Shift-M: tabbedalt:new_tab:mc:mc
|
||||
|
||||
Resource values are colon separated values, which are in order:
|
||||
|
||||
* **plugin name:command**, which in this case of creating new tab will be
|
||||
``tabbedalt:new_tab``.
|
||||
* **title of the tab**, it could be anything but the colon.
|
||||
* **optional command**. If omitted, default shell will be launched.
|
||||
|
||||
Renaming tabs
|
||||
-------------
|
||||
|
||||
On runtime, tabs can be renamed using (by default) ``Shift+Up`` - now you can
|
||||
type name for the tab. ``Return`` accept change, ``ESC`` cancels it. This
|
||||
feature was taken from `stepb`_ tabbedx repository.
|
||||
|
||||
.. _urxvt-unicode: http://software.schmorp.de/pkg/rxvt-unicode.html
|
||||
.. _activity indicator: http://mina86.com/2009/05/16/tabbed-urxvt-extension/
|
||||
.. _stepb: http://github.com/stepb/urxvt-tabbedex
|
||||
|
||||
@@ -155,6 +155,23 @@
|
||||
#
|
||||
# 2023-10-28 16:30:32
|
||||
# - Added overlay based dialog to confirm closing urxvt window
|
||||
#
|
||||
# 2024-06-10 10:34:47
|
||||
# - Added option for disabling activity marks and colors
|
||||
#
|
||||
# 2024-12-10 18:30:22
|
||||
# - Fix an issue with requesting closing terminal, which appear to be a
|
||||
# single instance
|
||||
#
|
||||
# 2026-04-21 16:29:49
|
||||
# - Fix small but constant memory consumption, which over time eventually will
|
||||
# cause urxvt to consume huge amount of memory
|
||||
#
|
||||
# 2026-04-21 18:34:16
|
||||
# - Make some more optimization on memory usage - remove data from destroyed
|
||||
# tab and disable its hooks
|
||||
# - update tab property notifications, don't update it too often, clean up X
|
||||
# properties variables after use, update only changed X properties
|
||||
|
||||
use Scalar::Util;
|
||||
|
||||
@@ -228,6 +245,7 @@ package urxvt::ext::tabbedalt::main;
|
||||
sub tab_activity_mark ($$) {
|
||||
my ($self, $tab) = @_;
|
||||
return ' ' unless defined $tab->{lastActivity};
|
||||
return ' ' if $self->{disable_activity};
|
||||
return ' ' if $tab == $self->{cur};
|
||||
if (defined $self->{timeouts}) {
|
||||
my $diff = int urxvt::NOW - $tab->{lastActivity};
|
||||
@@ -258,14 +276,16 @@ sub refresh {
|
||||
my ($self) = @_;
|
||||
my $tabs_no = (@{$self->{tabs}});
|
||||
|
||||
my $old_tabheight = $self->{tabheight} // 0;
|
||||
|
||||
if ($self->{autohide} && $tabs_no == 1 &&
|
||||
! $self->{cur}->{is_being_renamed}) {
|
||||
$self->{tabheight} = 0;
|
||||
$self->configure;
|
||||
$self->copy_properties;
|
||||
return;
|
||||
} else {
|
||||
$self->{tabheight} = $self->{_tabheight};
|
||||
}
|
||||
|
||||
if ($old_tabheight != $self->{tabheight}) {
|
||||
$self->configure;
|
||||
$self->copy_properties;
|
||||
}
|
||||
@@ -275,6 +295,8 @@ sub refresh {
|
||||
my $text = " " x $ncol;
|
||||
my $rend = [($self->{rs_tabbar}) x $ncol];
|
||||
|
||||
undef $self->{tabofs};
|
||||
|
||||
my ($ofs, $idx, @ofs) = (0, 0);
|
||||
|
||||
if ($self->{new_button}) {
|
||||
@@ -306,6 +328,7 @@ sub refresh {
|
||||
if ($tab == $self->{cur}) {
|
||||
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab}) x $len;
|
||||
} else {
|
||||
if (!$self->{disable_activity}) {
|
||||
if ($act eq "*") {
|
||||
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_act}) x $len;
|
||||
} elsif ($act eq $self->{timeouts}[0][1]) {
|
||||
@@ -314,6 +337,7 @@ sub refresh {
|
||||
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_acs}) x $len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# sub with make current will activate events with mouse buttons
|
||||
push @ofs, [ $ofs, $ofs + $len, sub { $_[0]->make_current ($tab) } ];
|
||||
@@ -412,6 +436,9 @@ sub copy_properties {
|
||||
if $cur->[0] != $type or $cur->[1] != $format or $cur->[2] ne $items;
|
||||
|
||||
$self->{current_properties}{$atom} = [$type, $format, $items];
|
||||
undef $type;
|
||||
undef $format;
|
||||
undef $items;
|
||||
}
|
||||
|
||||
# pass 2, delete all extraneous properties
|
||||
@@ -566,6 +593,7 @@ sub init {
|
||||
$self->{stop_flickering} = $self->x_resource_boolean('stop-flickering');
|
||||
$self->{confirm_quit} = $self->x_resource_boolean('confirm-quit');
|
||||
$self->{confirm_program} = $self->x_resource('confirm-program');
|
||||
$self->{disable_activity} = $self->x_resource_boolean('disable-activity');
|
||||
|
||||
my $timeouts = $self->x_resource ("tabbar-timeouts");
|
||||
$timeouts = '16:.:8:::4:+' unless defined $timeouts;
|
||||
@@ -653,11 +681,12 @@ _on wm_delete_window => sub {
|
||||
my %process_to_skip = ( "bash"=>1, "zsh"=>1, "ps"=>1, "fish"=>1, "sh"=>1 );
|
||||
|
||||
foreach my $line (@subprocesses) {
|
||||
chomp $line;
|
||||
my @split_line = split(/ /, $line);
|
||||
$line =~ s/^\s+|\s+$//g;
|
||||
my @split_line = split(" ", $line);
|
||||
my $pid = @split_line[0];
|
||||
my $proc_name = @split_line[1];
|
||||
chomp $proc_name;
|
||||
my @line = split(" ", @split_line[1]);
|
||||
my $proc_name = @line[0];
|
||||
$proc_name =~ s/^\s+|\s+$//g;
|
||||
if (!exists $process_to_skip{$proc_name}) {
|
||||
$subp_count = $subp_count + 1;
|
||||
} else {
|
||||
@@ -691,10 +720,8 @@ _on wm_delete_window => sub {
|
||||
my $marginc = 0;
|
||||
$qst = "$qst (y/n)";
|
||||
if ((length $msg) > (length $qst)) {
|
||||
print("length $msg > length $qst\n");
|
||||
$marginc = int(($self->ncol - length $msg)/2);
|
||||
} elsif ((length $msg) <= (length $qst)) {
|
||||
print("length $msg <= length $qst\n");
|
||||
$marginc = int(($self->ncol - length $qst)/2);
|
||||
}
|
||||
my $marginr = int(($self->nrow - 4)/2);
|
||||
@@ -734,6 +761,18 @@ sub tab_start {
|
||||
sub tab_destroy {
|
||||
my ($self, $tab) = @_;
|
||||
|
||||
# Disable hooks and remove data from tab
|
||||
$tab->disable('line_update', 'key_press', 'property_notify', 'action', 'start', 'destroy');
|
||||
delete $tab->{lastActivity};
|
||||
delete $tab->{is_being_renamed};
|
||||
delete $tab->{old_name};
|
||||
delete $tab->{new_name};
|
||||
delete $tab->{overlay};
|
||||
delete $tab->{main};
|
||||
delete $tab->{parent};
|
||||
delete $tab->{'tabbedalt_main'};
|
||||
delete $tab->{name};
|
||||
|
||||
$self->{tabs} = [ grep $_ != $tab, @{ $self->{tabs} } ];
|
||||
|
||||
if (@{ $self->{tabs} }) {
|
||||
@@ -765,8 +804,37 @@ sub command {
|
||||
sub tab_property_notify {
|
||||
my ($self, $tab, $event) = @_;
|
||||
|
||||
$self->copy_properties
|
||||
if $event->{window} == $tab->parent;
|
||||
return () unless $event->{window} == $tab->parent;
|
||||
return () unless $tab == $self->{cur};
|
||||
|
||||
# skip if called too often (within 0.1s)
|
||||
my $now = urxvt::NOW;
|
||||
my $last = $self->{last_property_update} // 0;
|
||||
if ($now - $last < 0.1) {
|
||||
return ();
|
||||
}
|
||||
$self->{last_property_update} = $now;
|
||||
|
||||
# update only the changed property instead of all properties
|
||||
my $atom = $event->{atom};
|
||||
my ($type, $format, $items) = $self->XGetWindowProperty ($tab->parent, $atom);
|
||||
|
||||
my $wm_normal_hints = $self->XInternAtom ("WM_NORMAL_HINTS");
|
||||
|
||||
# fix up size hints
|
||||
if ($atom == $wm_normal_hints) {
|
||||
my (@hints) = unpack "l!*", $items;
|
||||
$hints[$_] += $self->{tabheight} for (4, 6, 16);
|
||||
$items = pack "l!*", @hints;
|
||||
}
|
||||
|
||||
$self->XChangeProperty ($self->parent, $atom, $type, $format, $items);
|
||||
$self->{current_properties}{$atom} = [$type, $format, $items];
|
||||
|
||||
# free memory from X properties
|
||||
undef $type;
|
||||
undef $format;
|
||||
undef $items;
|
||||
|
||||
()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user