Skip to content

Commit 36b4e17

Browse files
committed
bug fix: allow compositor to choose output for full screen. Cleaner keyboard handling and an ugly fix for FlightGear state handling.
1 parent 6debadd commit 36b4e17

File tree

1 file changed

+32
-12
lines changed

1 file changed

+32
-12
lines changed

src/osgViewer/GraphicsWindowWayland.cpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ struct gc_client_state {
5656
struct wl_surface* keyboard_surface;
5757
struct wl_surface* pointer_surface;
5858
uint32_t keyboard_serial;
59-
// custom Ctrl modifier
60-
bool keyboard_ctrl;
6159
// repeat state
6260
int32_t keyboard_repeat;
6361
int32_t keyboard_delay;
@@ -212,7 +210,7 @@ class WLGraphicsWindow : public osgViewer::GraphicsWindow {
212210
if (_traits->windowDecoration)
213211
xdg_toplevel_unset_fullscreen(_gw.xdg_toplevel);
214212
else
215-
xdg_toplevel_set_fullscreen(_gw.xdg_toplevel, _gw.gc->output[_traits->screenNum]);
213+
xdg_toplevel_set_fullscreen(_gw.xdg_toplevel, NULL); // allow compositor to select screen
216214
WLGWlog(0) << _logname << "full=" << !_traits->windowDecoration << "/screen=" << _traits->screenNum << std::endl;
217215
// bool supportsResize yes, we do, no action.
218216
// bool pbuffer (see above)
@@ -316,7 +314,7 @@ class WLGraphicsWindow : public osgViewer::GraphicsWindow {
316314
if (windowDecoration)
317315
xdg_toplevel_unset_fullscreen(_gw.xdg_toplevel);
318316
else
319-
xdg_toplevel_set_fullscreen(_gw.xdg_toplevel, _gw.gc->output[_traits->screenNum]);
317+
xdg_toplevel_set_fullscreen(_gw.xdg_toplevel, NULL); // allow compositor to select screen
320318
return true;
321319
}
322320
virtual void grabFocus() {
@@ -498,7 +496,6 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
498496
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
499497
obj->_gc.keyboard_surface = surface;
500498
obj->_gc.keyboard_serial = serial;
501-
obj->_gc.keyboard_ctrl = false;
502499
WLGWlog(1) << "<keyboard enter: " << surface << ">" << std::endl;
503500
// dump pressed keys
504501
uint32_t* pkey = (uint32_t*)keys->data;
@@ -544,29 +541,52 @@ class WLWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemI
544541
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
545542
// update XKB with modifier state: https://wayland-book.com/seat/keyboard.html
546543
xkb_state_update_mask(obj->_gc.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
544+
if (auto win = obj->get_window(obj->_gc.keyboard_surface)) {
545+
// adjust currently effective modifiers
546+
auto es = win->getEventQueue()->getCurrentEventState();
547+
int emods = es->getModKeyMask();
548+
if (xkb_state_mod_name_is_active(obj->_gc.xkb_state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE))
549+
emods |= osgGA::GUIEventAdapter::ModKeyMask::MODKEY_SHIFT;
550+
else
551+
emods &= ~osgGA::GUIEventAdapter::ModKeyMask::MODKEY_SHIFT;
552+
if (xkb_state_mod_name_is_active(obj->_gc.xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE))
553+
emods |= osgGA::GUIEventAdapter::ModKeyMask::MODKEY_CTRL;
554+
else
555+
emods &= ~osgGA::GUIEventAdapter::ModKeyMask::MODKEY_CTRL;
556+
if (xkb_state_mod_name_is_active(obj->_gc.xkb_state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE))
557+
emods |= osgGA::GUIEventAdapter::ModKeyMask::MODKEY_ALT;
558+
else
559+
emods &= ~osgGA::GUIEventAdapter::ModKeyMask::MODKEY_ALT;
560+
es->setModKeyMask(emods);
561+
// push through a harmless key to update modifier state in event system, otherwise the joystick b0rks.. (arrrrgh!!)
562+
win->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KeySymbol::KEY_Shift_L);
563+
}
547564
WLGWlog(0) << "<keymods: " << mods_depressed << ',' << mods_latched << ',' << mods_locked << ',' << group << ">" << std::endl;
548565
}
549566
static void keyboard_key(void* data, wl_keyboard* wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
550567
WLWindowingSystemInterface* obj = (WLWindowingSystemInterface*) data;
551568
// NB: from: https://wayland-book.com/seat/keyboard.html
552569
// "Important: the scancode from this event is the Linux evdev scancode. To translate this to an XKB scancode, you must add 8 to the evdev scancode."
570+
key += 8;
571+
// ignore modifier keys..
572+
if (!xkb_key_repeats(obj->_gc.xkb_keymap, key))
573+
return;
553574
// We also rely on the fact that OSG have used the /same UTF32 symbol codes/ as XKB (or so it appears)
554-
xkb_keysym_t sym = xkb_state_key_get_one_sym(obj->_gc.xkb_state, key+8);
555-
// independantly of XKB, we maintain a flag for Ctrl modifier, since the above function ignores it..
556-
if (XKB_KEY_Control_L==sym || XKB_KEY_Control_R==sym)
557-
obj->_gc.keyboard_ctrl = state ? true : false;
558-
// if Ctrl is in play and we have A-Z, synthesize old ASCII values
559-
if (obj->_gc.keyboard_ctrl && sym>=XKB_KEY_a && sym<=XKB_KEY_z) {
575+
xkb_keysym_t sym = xkb_state_key_get_one_sym(obj->_gc.xkb_state, key);
576+
// if Ctrl is in play and we have A-Z, synthesize old ASCII values, as 'get_one_sym' above does not translate Ctrl codes..
577+
if (xkb_state_mod_name_is_active(obj->_gc.xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE)
578+
&& sym>=XKB_KEY_a && sym<=XKB_KEY_z) {
560579
sym = 1 + (sym - XKB_KEY_a);
561580
}
581+
// find the target window..
562582
if (auto win = obj->get_window(obj->_gc.keyboard_surface)) {
563583
if (state)
564584
win->getEventQueue()->keyPress((int)sym);
565585
else
566586
win->getEventQueue()->keyRelease((int)sym);
567587
WLGWlog(0) << (state?"<keypress: ":"<keyrelease: ") << key << "=>" << sym << ">" << std::endl;
568588
}
569-
// any new keypress always puts us in DELAY state for repeats, releasing any key stops repeats
589+
// any keypress always puts us in DELAY state for repeats, any release and we stop repeating
570590
obj->_gc.keyboard_state = state ? KEYBOARD_DELAY : KEYBOARD_IDLE;
571591
obj->_gc.keyboard_last = (int)sym;
572592
}

0 commit comments

Comments
 (0)