mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
parent
b22f3c67f0
commit
a801976727
@ -133,21 +133,21 @@ void GenodeConsole::update_video_mode()
|
||||
d->SetVideoModeHint(0 /*=display*/,
|
||||
true /*=enabled*/, false /*=changeOrigin*/,
|
||||
0 /*=originX*/, 0 /*=originY*/,
|
||||
fb->w(), fb->h(), fb->depth());
|
||||
fb->w(), fb->h(),
|
||||
/* Windows 8 only accepts 32-bpp modes */
|
||||
32);
|
||||
}
|
||||
|
||||
void GenodeConsole::eventWait(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
void GenodeConsole::handle_input(unsigned)
|
||||
{
|
||||
static LONG64 mt_events [64];
|
||||
unsigned mt_number = 0;
|
||||
|
||||
_receiver.wait_for_signal();
|
||||
|
||||
/* read out input capabilities of guest */
|
||||
bool guest_abs = false, guest_rel = false, guest_multi = false;
|
||||
gMouse->COMGETTER(AbsoluteSupported)(&guest_abs);
|
||||
gMouse->COMGETTER(RelativeSupported)(&guest_rel);
|
||||
gMouse->COMGETTER(MultiTouchSupported)(&guest_multi);
|
||||
_vbox_mouse->COMGETTER(AbsoluteSupported)(&guest_abs);
|
||||
_vbox_mouse->COMGETTER(RelativeSupported)(&guest_rel);
|
||||
_vbox_mouse->COMGETTER(MultiTouchSupported)(&guest_multi);
|
||||
|
||||
for (int i = 0, num_ev = _input.flush(); i < num_ev; ++i) {
|
||||
Input::Event &ev = _ev_buf[i];
|
||||
@ -166,11 +166,11 @@ void GenodeConsole::eventWait(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
(ev.type() == Input::Event::RELEASE) ? 0x80 : 0;
|
||||
|
||||
if (scan_code.is_normal())
|
||||
gKeyboard->PutScancode(scan_code.code() | release_bit);
|
||||
_vbox_keyboard->PutScancode(scan_code.code() | release_bit);
|
||||
|
||||
if (scan_code.is_ext()) {
|
||||
gKeyboard->PutScancode(0xe0);
|
||||
gKeyboard->PutScancode(scan_code.ext() | release_bit);
|
||||
_vbox_keyboard->PutScancode(0xe0);
|
||||
_vbox_keyboard->PutScancode(scan_code.ext() | release_bit);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,10 +204,10 @@ void GenodeConsole::eventWait(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
int ry = ev.ay() - _ay;
|
||||
rx = Genode::min(boundary, Genode::max(-boundary, rx));
|
||||
ry = Genode::min(boundary, Genode::max(-boundary, ry));
|
||||
gMouse->PutMouseEvent(rx, ry, 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEvent(rx, ry, 0, 0, buttons);
|
||||
} else
|
||||
gMouse->PutMouseEventAbsolute(ev.ax(), ev.ay(), 0,
|
||||
0, buttons);
|
||||
_vbox_mouse->PutMouseEventAbsolute(ev.ax(), ev.ay(), 0,
|
||||
0, buttons);
|
||||
|
||||
_ax = ev.ax();
|
||||
_ay = ev.ay();
|
||||
@ -218,11 +218,11 @@ void GenodeConsole::eventWait(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
|
||||
/* prefer relative motion event */
|
||||
if (guest_rel)
|
||||
gMouse->PutMouseEvent(ev.rx(), ev.ry(), 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEvent(ev.rx(), ev.ry(), 0, 0, buttons);
|
||||
else if (guest_abs) {
|
||||
_ax += ev.rx();
|
||||
_ay += ev.ry();
|
||||
gMouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
|
||||
}
|
||||
}
|
||||
/* only the buttons changed */
|
||||
@ -231,28 +231,28 @@ void GenodeConsole::eventWait(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
if (_last_received_motion_event_was_absolute) {
|
||||
/* prefer absolute button event */
|
||||
if (guest_abs)
|
||||
gMouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
|
||||
else if (guest_rel)
|
||||
gMouse->PutMouseEvent(0, 0, 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons);
|
||||
} else {
|
||||
/* prefer relative button event */
|
||||
if (guest_rel)
|
||||
gMouse->PutMouseEvent(0, 0, 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons);
|
||||
else if (guest_abs)
|
||||
gMouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
|
||||
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (is_wheel)
|
||||
gMouse->PutMouseEvent(0, 0, ev.rx(), ev.ry(), 0);
|
||||
_vbox_mouse->PutMouseEvent(0, 0, ev.rx(), ev.ry(), 0);
|
||||
|
||||
if (is_touch) {
|
||||
/* if multitouch queue is full - send it */
|
||||
if (mt_number >= sizeof(mt_events) / sizeof(mt_events[0])) {
|
||||
gMouse->PutEventMultiTouch(mt_number, mt_number,
|
||||
mt_events, RTTimeMilliTS());
|
||||
_vbox_mouse->PutEventMultiTouch(mt_number, mt_number,
|
||||
mt_events, RTTimeMilliTS());
|
||||
mt_number = 0;
|
||||
}
|
||||
|
||||
@ -282,8 +282,39 @@ void GenodeConsole::eventWait(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
|
||||
/* if there are elements - send it */
|
||||
if (mt_number)
|
||||
gMouse->PutEventMultiTouch(mt_number, mt_number, mt_events,
|
||||
RTTimeMilliTS());
|
||||
_vbox_mouse->PutEventMultiTouch(mt_number, mt_number, mt_events,
|
||||
RTTimeMilliTS());
|
||||
}
|
||||
|
||||
void GenodeConsole::handle_mode_change(unsigned)
|
||||
{
|
||||
Display *d = getDisplay();
|
||||
Genodefb *fb = dynamic_cast<Genodefb *>(d->getFramebuffer());
|
||||
|
||||
fb->update_mode();
|
||||
update_video_mode();
|
||||
}
|
||||
|
||||
void GenodeConsole::event_loop(IKeyboard * gKeyboard, IMouse * gMouse)
|
||||
{
|
||||
_vbox_keyboard = gKeyboard;
|
||||
_vbox_mouse = gMouse;
|
||||
|
||||
/* register the mode change signal dispatcher at the framebuffer */
|
||||
Display *d = getDisplay();
|
||||
Genodefb *fb = dynamic_cast<Genodefb *>(d->getFramebuffer());
|
||||
fb->mode_sigh(_mode_change_signal_dispatcher);
|
||||
|
||||
for (;;) {
|
||||
|
||||
Genode::Signal sig = _receiver.wait_for_signal();
|
||||
Genode::Signal_dispatcher_base *dispatcher =
|
||||
dynamic_cast<Genode::Signal_dispatcher_base *>(sig.context());
|
||||
|
||||
if (dispatcher)
|
||||
dispatcher->dispatch(sig.num());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GenodeConsole::onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative,
|
||||
|
@ -107,15 +107,18 @@ class GenodeConsole : public Console {
|
||||
|
||||
private:
|
||||
|
||||
Input::Connection _input;
|
||||
Genode::Signal_receiver _receiver;
|
||||
Genode::Signal_context _context;
|
||||
Input::Event *_ev_buf;
|
||||
unsigned _ax, _ay;
|
||||
bool _last_received_motion_event_was_absolute;
|
||||
Report::Connection _shape_report_connection;
|
||||
Genode::Attached_dataspace _shape_report_ds;
|
||||
Vbox_pointer::Shape_report *_shape_report;
|
||||
Input::Connection _input;
|
||||
Genode::Signal_receiver _receiver;
|
||||
Input::Event *_ev_buf;
|
||||
unsigned _ax, _ay;
|
||||
bool _last_received_motion_event_was_absolute;
|
||||
Report::Connection _shape_report_connection;
|
||||
Genode::Attached_dataspace _shape_report_ds;
|
||||
Vbox_pointer::Shape_report *_shape_report;
|
||||
IKeyboard *_vbox_keyboard;
|
||||
IMouse *_vbox_mouse;
|
||||
Genode::Signal_dispatcher<GenodeConsole> _input_signal_dispatcher;
|
||||
Genode::Signal_dispatcher<GenodeConsole> _mode_change_signal_dispatcher;
|
||||
|
||||
bool _key_status[Input::KEY_MAX + 1];
|
||||
|
||||
@ -136,15 +139,19 @@ class GenodeConsole : public Console {
|
||||
_last_received_motion_event_was_absolute(false),
|
||||
_shape_report_connection("shape", sizeof(Vbox_pointer::Shape_report)),
|
||||
_shape_report_ds(_shape_report_connection.dataspace()),
|
||||
_shape_report(_shape_report_ds.local_addr<Vbox_pointer::Shape_report>())
|
||||
_shape_report(_shape_report_ds.local_addr<Vbox_pointer::Shape_report>()),
|
||||
_vbox_keyboard(0),
|
||||
_vbox_mouse(0),
|
||||
_input_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_input),
|
||||
_mode_change_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_mode_change)
|
||||
{
|
||||
for (unsigned i = 0; i <= Input::KEY_MAX; i++)
|
||||
_key_status[i] = 0;
|
||||
|
||||
_input.sigh(_receiver.manage(&_context));
|
||||
_input.sigh(_input_signal_dispatcher);
|
||||
}
|
||||
|
||||
void eventWait(IKeyboard * gKeyboard, IMouse * gMouse);
|
||||
void event_loop(IKeyboard * gKeyboard, IMouse * gMouse);
|
||||
|
||||
void onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative,
|
||||
BOOL supportsMT, BOOL needsHostCursor);
|
||||
@ -209,4 +216,7 @@ class GenodeConsole : public Console {
|
||||
}
|
||||
|
||||
void update_video_mode();
|
||||
|
||||
void handle_input(unsigned);
|
||||
void handle_mode_change(unsigned);
|
||||
};
|
||||
|
@ -26,46 +26,76 @@ class Genodefb :
|
||||
{
|
||||
private:
|
||||
|
||||
Fb_Genode::Connection _fb;
|
||||
Fb_Genode::Mode const _fb_mode;
|
||||
void * _fb_base;
|
||||
RTCRITSECT _fb_lock;
|
||||
Fb_Genode::Connection _fb;
|
||||
|
||||
unsigned long _width;
|
||||
unsigned long _height;
|
||||
/* The mode matching the currently attached dataspace */
|
||||
Fb_Genode::Mode _fb_mode;
|
||||
|
||||
/* The mode at the time when the mode change signal was received */
|
||||
Fb_Genode::Mode _next_fb_mode;
|
||||
|
||||
/*
|
||||
* The mode currently used by the VM. Can be smaller than the
|
||||
* framebuffer mode.
|
||||
*/
|
||||
Fb_Genode::Mode _virtual_fb_mode;
|
||||
|
||||
void *_fb_base;
|
||||
RTCRITSECT _fb_lock;
|
||||
|
||||
void _clear_screen()
|
||||
{
|
||||
size_t const num_pixels = _fb_mode.width() * _virtual_fb_mode.height();
|
||||
memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel());
|
||||
_fb.refresh(0, 0, _virtual_fb_mode.width(), _virtual_fb_mode.height());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Genodefb ()
|
||||
:
|
||||
_fb_mode(_fb.mode()),
|
||||
_fb_base(Genode::env()->rm_session()->attach(_fb.dataspace())),
|
||||
_width(_fb_mode.width()),
|
||||
_height(_fb_mode.height())
|
||||
_next_fb_mode(_fb_mode),
|
||||
_virtual_fb_mode(_fb_mode),
|
||||
_fb_base(Genode::env()->rm_session()->attach(_fb.dataspace()))
|
||||
{
|
||||
int rc = RTCritSectInit(&_fb_lock);
|
||||
Assert(rc == VINF_SUCCESS);
|
||||
}
|
||||
|
||||
int w() const { return _fb_mode.width(); }
|
||||
int h() const { return _fb_mode.height(); }
|
||||
int depth() const { return 16; /* XXX */ }
|
||||
/* Return the next mode of the framebuffer */
|
||||
int w() const { return _next_fb_mode.width(); }
|
||||
int h() const { return _next_fb_mode.height(); }
|
||||
|
||||
void mode_sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
_fb.mode_sigh(sigh);
|
||||
}
|
||||
|
||||
void update_mode()
|
||||
{
|
||||
Lock();
|
||||
_next_fb_mode = _fb.mode();
|
||||
Unlock();
|
||||
}
|
||||
|
||||
STDMETHODIMP COMGETTER(Width)(ULONG *width)
|
||||
{
|
||||
if (!width)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*width = (int)_width > _fb_mode.width() ? _fb_mode.width() : _width;
|
||||
*width = _virtual_fb_mode.width();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP COMGETTER(Height)(ULONG *height)
|
||||
{
|
||||
if (!height)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*height = (int)_height > _fb_mode.height() ? _fb_mode.height() : _height;
|
||||
*height = _virtual_fb_mode.height();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -90,7 +120,8 @@ class Genodefb :
|
||||
if (!bits)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*bits = _fb_mode.bytes_per_pixel() * 8;
|
||||
*bits = _virtual_fb_mode.bytes_per_pixel() * 8;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -111,29 +142,44 @@ class Genodefb :
|
||||
ULONG bytesPerLine, ULONG w, ULONG h,
|
||||
BOOL *finished)
|
||||
{
|
||||
/* clear screen to avoid artefacts during resize */
|
||||
size_t const num_pixels = _fb_mode.width() * _fb_mode.height();
|
||||
memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel());
|
||||
HRESULT result = E_FAIL;
|
||||
|
||||
_fb.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
|
||||
Lock();
|
||||
|
||||
/* bitsPerPixel == 0 is set by DevVGA when in text mode */
|
||||
bool ok = ((bitsPerPixel == 16) || (bitsPerPixel == 0)) &&
|
||||
(w <= (ULONG)_fb_mode.width()) &&
|
||||
(h <= (ULONG)_fb_mode.height());
|
||||
if (ok)
|
||||
PINF("fb resize : %lux%lu@%zu -> %ux%u@%u", _width, _height,
|
||||
_fb_mode.bytes_per_pixel() * 8, w, h, bitsPerPixel);
|
||||
else
|
||||
PWRN("fb resize : %lux%lu@%zu -> %ux%u@%u ignored", _width, _height,
|
||||
_fb_mode.bytes_per_pixel() * 8, w, h, bitsPerPixel);
|
||||
bool ok = (w <= (ULONG)_next_fb_mode.width()) &&
|
||||
(h <= (ULONG)_next_fb_mode.height());
|
||||
|
||||
_width = w;
|
||||
_height = h;
|
||||
if (ok) {
|
||||
PINF("fb resize : %dx%d@%zu -> %ux%u@%u",
|
||||
_virtual_fb_mode.width(), _virtual_fb_mode.height(),
|
||||
_virtual_fb_mode.bytes_per_pixel() * 8, w, h, bitsPerPixel);
|
||||
|
||||
if ((w < (ULONG)_next_fb_mode.width()) ||
|
||||
(h < (ULONG)_next_fb_mode.height())) {
|
||||
/* clear the old content around the new, smaller area. */
|
||||
_clear_screen();
|
||||
}
|
||||
|
||||
_fb_mode = _next_fb_mode;
|
||||
|
||||
_virtual_fb_mode = Fb_Genode::Mode(w, h, Fb_Genode::Mode::RGB565);
|
||||
|
||||
Genode::env()->rm_session()->detach(_fb_base);
|
||||
|
||||
_fb_base = Genode::env()->rm_session()->attach(_fb.dataspace());
|
||||
|
||||
result = S_OK;
|
||||
|
||||
} else
|
||||
PWRN("fb resize : %dx%d@%zu -> %ux%u@%u ignored",
|
||||
_virtual_fb_mode.width(), _virtual_fb_mode.height(),
|
||||
_virtual_fb_mode.bytes_per_pixel() * 8, w, h, bitsPerPixel);
|
||||
|
||||
*finished = true;
|
||||
|
||||
return S_OK;
|
||||
Unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COMGETTER(PixelFormat) (ULONG *format)
|
||||
@ -177,9 +223,8 @@ class Genodefb :
|
||||
if (!supported)
|
||||
return E_POINTER;
|
||||
|
||||
*supported = ((width <= (ULONG)_fb_mode.width()) &&
|
||||
(height <= (ULONG)_fb_mode.height()) &&
|
||||
(bpp == _fb_mode.bytes_per_pixel() * 8));
|
||||
*supported = ((width <= (ULONG)_next_fb_mode.width()) &&
|
||||
(height <= (ULONG)_next_fb_mode.height()));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -198,9 +198,8 @@ HRESULT setupmachine()
|
||||
/* handle input of Genode and forward it to VMM layer */
|
||||
ComPtr<GenodeConsole> genodeConsole = gConsole;
|
||||
RTLogPrintf("genodeConsole = %p\n", genodeConsole);
|
||||
while (true) {
|
||||
genodeConsole->eventWait(gKeyboard, gMouse);
|
||||
}
|
||||
|
||||
genodeConsole->event_loop(gKeyboard, gMouse);
|
||||
|
||||
Assert(!"return not expected");
|
||||
return E_FAIL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user