ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/RCU/RCU/Event.pm
Revision: 1.1
Committed: Sun Nov 6 17:17:37 2005 UTC (19 years, 1 month ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 RCU::Event - Event-based RCU operation
4
5 =head1 SYNOPSIS
6
7 use RCU::Event;
8
9 $rcu = connect RCU::Event "interfac-spec", [initial-context]
10
11 =head1 DESCRIPTION
12
13 This module provides a superset of the standard C<RCU> interface by adding
14 an event-based interface. Basically, you create one or more I<contexts>
15 (See C<RCU::Context>) and bind it to a RCU::Event object. All key events
16 will then be directed to the current context.
17
18 =over 4
19
20 =cut
21
22 package RCU::Event;
23
24 $VERSION = 0.01;
25
26 use Carp;
27 use Event;
28
29 use RCU;
30 use RCU::Context;
31 use base RCU;
32
33 =item $ctx = connect RCU::Event "interface-desc";
34
35 Create a new RCU interface. The functionality is the same as L<RCU|RCU>,
36 with the functions added below.
37
38 =cut
39
40 sub new {
41 my $class = shift;
42 my $if = shift;
43 my $self = $class->SUPER::new($if);
44
45 my $last_key;
46
47 $self->{w} = Event->io(
48 fd => $self->{if}->fd,
49 desc => "$if key event",
50 poll => 'r',
51 hard => 1,
52 nice => -1,
53 cb => sub {
54 while (my ($time, $raw, $cooked) = $self->{if}->poll) {
55 my $key = $RCU::Key::db{$raw}
56 || ($RCU::Key::db{$cooked} ||= new RCU::Key
57 $RCU::some_key->[0] || $RCU::Key::db{""}{"<default>"}[0] || {},
58 $cooked);
59
60 my $repeat_freq = $key->[0]{repeat_freq} || 0.1;
61 if ($RCU::last_key != $key || $time > $RCU::next_time) {
62 if ($RCU::last_key) {
63 $self->inject("~" . ($RCU::last_key->[2] || $RCU::last_key->[1]), $time);
64 undef $RCU::last_key;
65 }
66 $self->inject("=" . ($key->[2] || $key->[1]), $time);
67 }
68 $RCU::some_key = $RCU::last_key = $key;
69 $RCU::next_time = $time + $repeat_freq;
70 $self->{tow}->stop;
71 $self->{tow}->at($RCU::next_time);
72 $self->{tow}->start;
73 }
74 },
75 );
76 $self->{tow} = Event->timer(
77 parked => 1,
78 cb => sub {
79 if ($RCU::last_key) {
80 $self->inject("~" . ($RCU::last_key->[2] || $RCU::last_key->[1]), $self->{tow}->at);
81 undef $RCU::last_key;
82 }
83 },
84 );
85
86 $self;
87 }
88
89 =item $rcu->inject(key)
90
91 Act as if key C<key> was pressed (C<key> starts with "=") or released
92 (when C<key> starts with C<~>). This is rarely used but is useful to
93 "simulate" key presses.
94
95 =cut
96
97 sub inject {
98 my $self = shift;
99 my ($event, $time) = @_;
100 $self->{ctx}->inject((join ":", @{$self->{history}}, $event), $time, $self) if $self->{ctx};
101 if ("~" eq substr $event, 0, 1) {
102 push @{$self->{history}}, substr $event, 1;
103 shift @{$self->{history}} if @{$self->{history}} > $RCU::Context::histsize;
104 }
105 }
106
107 =item $rcu->set_context(new_context)
108
109 Leave the current context (if any) and enter the C<new_context>, to which
110 all new events are directed to.
111
112 =cut
113
114 sub set_context {
115 my $self = shift;
116 my $ctx = shift;
117 if ($self->{ctx} != $ctx) {
118 $self->{ctx}->leave($self) if $self->{ctx};
119 $self->{ctx} = $ctx;
120 $ctx->enter($self);
121 }
122 }
123
124 =item $rcu->push_context(new_context)
125
126 Enter the given C<new_context> without leaving the current one.
127
128 =cut
129
130 sub push_context {
131 my $self = shift;
132 my $ctx = shift;
133 push @{$self->{ctx_stack}}, $self->{ctx};
134 $self->{ctx} = $ctx;
135 $ctx->enter($self);
136 }
137
138 =item $rcu->pop_context
139
140 Leave the current context and restore the previous context that was saved
141 in C<push_context>.
142
143 =cut
144
145 sub pop_context {
146 my $self = shift;
147 $self->{ctx}->leave($self);
148 $self->{ctx} = pop @{$self->{ctx_stack}};
149 }
150
151 1;
152
153 =back
154
155 =head1 SEE ALSO
156
157 L<RCU>.
158
159 =head1 AUTHOR
160
161 This perl extension was written by Marc Lehmann <schmorp@schmorp.de>.
162
163 =cut
164
165
166
167
168