1
0
mirror of https://github.com/gryf/tabbedalt.git synced 2026-04-27 17:13:30 +02:00

Compare commits

...

6 Commits

Author SHA1 Message Date
gryf 57f5423dc4 Added more memory optimizations 2026-04-24 19:54:29 +02:00
gryf b811ca58f6 Removed redundant sections 2026-04-21 18:44:08 +02:00
gryf 2cede3b996 Fix memory leaks caused by not freed resources from X properites 2026-04-21 16:35:27 +02:00
gryf 2ba623a811 Fix wrong shortcut in README 2026-04-21 16:28:46 +02:00
gryf 8da342b9b0 Fix an issue with confirmation to close terminal.
Sometimes, it happens that closing terminal with mouse/keyboard
confirmation dialog appears (no matter if it was graphical or the one
build on top of urxvt overlay).

The culprit was with lines origin from `ps` command, which wasn't
correctly split, but, what is more important, wasn't properly trimmed.
This commit fixing the issue by removing whitespace from both ends of
the string and splitting using space character rather, than regexp, and
second, be sure to chop off all the whitespace characters before
splitting line and after splitting process name and its arguments.
2024-12-10 19:02:41 +01:00
gryf a9eb5cee5d Added ability to disable tab activity indicator. 2024-06-10 10:42:27 +02:00
2 changed files with 97 additions and 53 deletions
+8 -32
View File
@@ -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
+79 -11
View File
@@ -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;
()
}