| 1 |
root |
1.1 |
#!/usr/bin/perl |
| 2 |
|
|
|
| 3 |
|
|
# I tried to write this with Tk, as it uses elss memory and is |
| 4 |
|
|
# more widely available. Alas, Tk is rather broken with respect to embedding. |
| 5 |
|
|
|
| 6 |
|
|
# on debian, do: |
| 7 |
|
|
# apt-get install libgtk2-perl |
| 8 |
|
|
|
| 9 |
|
|
my $RXVT_BASENAME = "rxvt"; |
| 10 |
|
|
|
| 11 |
|
|
use Gtk2; |
| 12 |
|
|
use Encode; |
| 13 |
|
|
|
| 14 |
root |
1.2 |
$SIG{CHLD} = 'IGNORE'; |
| 15 |
|
|
|
| 16 |
root |
1.1 |
my $event_cb; # $wid => $cb |
| 17 |
|
|
|
| 18 |
|
|
init Gtk2; |
| 19 |
|
|
|
| 20 |
|
|
my $window = new Gtk2::Window 'toplevel'; |
| 21 |
|
|
|
| 22 |
|
|
my $vbox = new Gtk2::VBox; |
| 23 |
|
|
$window->add ($vbox); |
| 24 |
|
|
|
| 25 |
|
|
my $notebook = new Gtk2::Notebook; |
| 26 |
|
|
$vbox->pack_start ($notebook, 1, 1, 0); |
| 27 |
|
|
|
| 28 |
|
|
$notebook->can_focus (0); |
| 29 |
|
|
$notebook->set (scrollable => 1); |
| 30 |
|
|
|
| 31 |
|
|
sub new_terminal { |
| 32 |
|
|
my ($title, @args) = @_; |
| 33 |
|
|
|
| 34 |
|
|
my $label = new Gtk2::Label $title; |
| 35 |
|
|
|
| 36 |
|
|
my $rxvt = new Gtk2::Socket; |
| 37 |
|
|
$rxvt->can_focus (1); |
| 38 |
|
|
|
| 39 |
|
|
my $wm_normal_hints = sub { |
| 40 |
|
|
my ($window) = @_; |
| 41 |
|
|
my ($type, $format, @data) |
| 42 |
|
|
= $window->property_get ( |
| 43 |
|
|
Gtk2::Gdk::Atom->intern ("WM_NORMAL_HINTS", 0), |
| 44 |
|
|
Gtk2::Gdk::Atom->intern ("WM_SIZE_HINTS", 0), |
| 45 |
|
|
0, 70*4, 0 |
| 46 |
|
|
); |
| 47 |
|
|
my ($width_inc, $height_inc, $base_width, $base_height) = @data[9,10,15,16]; |
| 48 |
|
|
|
| 49 |
|
|
my $hints = new Gtk2::Gdk::Geometry; |
| 50 |
|
|
$hints->base_width ($base_width); $hints->base_height ($base_height); |
| 51 |
|
|
$hints->width_inc ($width_inc); $hints->height_inc ($height_inc); |
| 52 |
|
|
|
| 53 |
|
|
$rxvt->get_toplevel->set_geometry_hints ($rxvt, $hints, [qw(base-size resize-inc)]); |
| 54 |
|
|
}; |
| 55 |
|
|
|
| 56 |
|
|
$rxvt->signal_connect_after (realize => sub { |
| 57 |
|
|
my $win = $_[0]->window; |
| 58 |
|
|
|
| 59 |
|
|
if (fork == 0) { |
| 60 |
|
|
exec $RXVT_BASENAME, |
| 61 |
|
|
-embed => $win->get_xid, @args; |
| 62 |
|
|
exit (255); |
| 63 |
|
|
} |
| 64 |
|
|
|
| 65 |
|
|
0 |
| 66 |
|
|
}); |
| 67 |
|
|
|
| 68 |
|
|
$rxvt->signal_connect_after (plug_added => sub { |
| 69 |
|
|
my ($socket) = @_; |
| 70 |
|
|
my $plugged = ($socket->window->get_children)[0]; |
| 71 |
|
|
|
| 72 |
|
|
$plugged->set_events ($plugged->get_events + ["property-change-mask"]); |
| 73 |
|
|
|
| 74 |
|
|
$wm_normal_hints->($plugged); |
| 75 |
|
|
|
| 76 |
|
|
$event_cb{$plugged} = sub { |
| 77 |
|
|
my ($event) = @_; |
| 78 |
|
|
my $window = $event->window; |
| 79 |
|
|
|
| 80 |
|
|
if (Gtk2::Gdk::Event::Configure:: eq ref $event) { |
| 81 |
|
|
$wm_normal_hints->($window); |
| 82 |
|
|
} elsif (Gtk2::Gdk::Event::Property:: eq ref $event) { |
| 83 |
|
|
my $atom = $event->atom; |
| 84 |
|
|
my $name = $atom->name; |
| 85 |
|
|
|
| 86 |
|
|
return if $event->state; # GDK_PROPERTY_NEW_VALUE == 0 |
| 87 |
|
|
|
| 88 |
|
|
|
| 89 |
|
|
if ($name eq "_NET_WM_NAME") { |
| 90 |
|
|
my ($type, $format, $data) |
| 91 |
|
|
= $window->property_get ( |
| 92 |
|
|
$atom, |
| 93 |
|
|
Gtk2::Gdk::Atom->intern ("UTF8_STRING", 0), |
| 94 |
|
|
0, 128, 0 |
| 95 |
|
|
); |
| 96 |
|
|
|
| 97 |
|
|
$label->set_text (Encode::decode_utf8 $data); |
| 98 |
|
|
} |
| 99 |
|
|
} |
| 100 |
|
|
|
| 101 |
|
|
0; |
| 102 |
|
|
}; |
| 103 |
|
|
|
| 104 |
|
|
0; |
| 105 |
|
|
}); |
| 106 |
|
|
|
| 107 |
|
|
$rxvt->signal_connect_after (map_event => sub { |
| 108 |
|
|
$_[0]->grab_focus; |
| 109 |
|
|
0 |
| 110 |
|
|
}); |
| 111 |
|
|
|
| 112 |
|
|
$notebook->append_page ($rxvt, $label); |
| 113 |
|
|
|
| 114 |
|
|
$rxvt->show_all; |
| 115 |
|
|
|
| 116 |
|
|
$notebook->set_current_page ($notebook->page_num ($rxvt)); |
| 117 |
|
|
|
| 118 |
|
|
$rxvt; |
| 119 |
|
|
} |
| 120 |
|
|
|
| 121 |
|
|
my $new = new Gtk2::Frame; |
| 122 |
|
|
$notebook->prepend_page ($new, "New"); |
| 123 |
|
|
|
| 124 |
|
|
$notebook->signal_connect_after (switch_page => sub { |
| 125 |
|
|
if ($_[2] == 0) { |
| 126 |
|
|
new_terminal $RXVT_BASENAME; |
| 127 |
|
|
} |
| 128 |
|
|
}); |
| 129 |
|
|
|
| 130 |
|
|
$window->set_default_size (700, 400); |
| 131 |
|
|
$window->show_all; |
| 132 |
|
|
|
| 133 |
|
|
# ugly, but gdk_window_filters are ot available in perl |
| 134 |
|
|
|
| 135 |
|
|
Gtk2::Gdk::Event->handler_set (sub { |
| 136 |
|
|
my ($event) = @_; |
| 137 |
|
|
my $window = $event->window; |
| 138 |
|
|
|
| 139 |
|
|
($event_cb{$window} && $event_cb{$window}->($event)) |
| 140 |
|
|
or Gtk2->main_do_event ($event); |
| 141 |
|
|
}); |
| 142 |
|
|
|
| 143 |
|
|
main Gtk2; |
| 144 |
|
|
|