On 04.07.2016 19:29, Stefan Ram wrote:
>
r...@zedat.fu-berlin.de (Stefan Ram) writes:
>> void check_incoming2
>> ( winapi::Input_record & event_data,
>> winapi::Double_word n_items )
>> { const auto kind = event_data.EventType;
>> if( kind == winapi::Event_kind::key )
>> { if( check_incoming3( event_data, n_items, kind ) )return; }
>> winapi::ReadConsoleInputW( keyboard_, &event_data, 1, &n_items ); }
>
> There is an early return left above, so:
>
> void check_incoming2
> ( winapi::Input_record & event_data,
> winapi::Double_word n_items )
> { const auto kind = event_data.EventType;
> if
> ( kind == winapi::Event_kind::key &&
> check_incoming3( event_data, n_items, kind ) ); else
> winapi::ReadConsoleInputW( keyboard_, &event_data, 1, &n_items ); }
I used a slightly more course-grained functional decomposition, leaving
one early return and transforming the other returns to more meaningful
value returns, so that now the abstract event stream class is like
class Event_stream
: public Non_copyable
, public Non_movable
{
private:
class Impl;
protected:
Boxed_event buffer_;
struct Check_result{ enum Enum{
event_ignored, event_accepted, no_available_event
}; };
virtual auto accept_or_ignore_incoming_if_any()
-> Check_result::Enum
= 0;
void check_incoming()
{
if( buffer_.pointer_to<Event>() != nullptr )
{
return; // Already buffered an event.
}
while( accept_or_ignore_incoming_if_any() ==
Check_result::event_ignored )
{;}
}
virtual ~Event_stream() {}
Event_stream() {}
public:
template< class Event_kind >
auto has()
-> bool
{
check_incoming();
return (buffer_.pointer_to<Event_kind>() != nullptr);
}
auto next_event()
-> Boxed_event
{
Boxed_event result{ buffer_ };
buffer_ = Boxed_event{}; // Very empty.
return result;
}
static auto singleton() // An `Impl` defined by the
system's impl.
-> Ref_<Event_stream>;
};
… and then in the Windows implementation class there is
auto accept_or_ignore_incoming_if_any()
-> Check_result::Enum
override
try
{
winapi::Input_record event_data = {};
winapi::Double_word n_items = 0;
winapi::PeekConsoleInputW( keyboard_, &event_data, 1,
&n_items )
|| fail( "PeekConsoleInputW failed" );
if( n_items == 0 )
{
return Check_result::no_available_event;
}
const auto kind = event_data.EventType;
if( kind == winapi::Event_kind::key )
{
const auto& ev = event_data.Event.KeyEvent;
const auto key_code = static_cast<Keycodes::Enum>(
ev.wVirtualKeyCode );
const bool is_autorepeat = (ev.bKeyDown and is_in(
pressed_keys_, key_code ));
if( not is_autorepeat )
{
if( ev.bKeyDown )
{
pressed_keys_.insert( key_code );
}
else
{
pressed_keys_.erase( key_code );
}
Base::buffer_ = Boxed_event{ Key_event{
Key{ key_code, ev.uChar.UnicodeChar },
(ev.bKeyDown? Key_event::Action::pressed :
Key_event::Action::released)
} };
winapi::ReadConsoleInputW( keyboard_, &event_data,
1, &n_items );
return Check_result::event_accepted;
}
}
// Best effort to consume the ignored event, to help reduce the
// chance of Windows' event buffer becoming full.
winapi::ReadConsoleInputW( keyboard_, &event_data, 1,
&n_items );
return Check_result::event_ignored;
} CPPX_RETHROW_X // Prepends the qualified function name
to the message.
… which doesn't yet deal with mouse events, but's like in the old days
one bought FM receivers “ready for stereo”: they could more or less
easily be upgraded to stereo, or at least that was intended and hoped.
I think the names of the functions are now awkward, though. :)
Cheers!, and thanks,
- Alf (ungood at naming non-simple functions)