void KeymapWrapper::InitBySystemSettings() { PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitBySystemSettings, mGdkKeymap=%p", this, mGdkKeymap)); Display* display = gdk_x11_display_get_xdisplay(gdk_display_get_default()); int min_keycode = 0; int max_keycode = 0; XDisplayKeycodes(display, &min_keycode, &max_keycode); int keysyms_per_keycode = 0; KeySym* xkeymap = XGetKeyboardMapping(display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode); if (!xkeymap) { PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitBySystemSettings, " "Failed due to null xkeymap", this)); return; } XModifierKeymap* xmodmap = XGetModifierMapping(display); if (!xmodmap) { PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitBySystemSettings, " "Failed due to null xmodmap", this)); XFree(xkeymap); return; } PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitBySystemSettings, min_keycode=%d, " "max_keycode=%d, keysyms_per_keycode=%d, max_keypermod=%d", this, min_keycode, max_keycode, keysyms_per_keycode, xmodmap->max_keypermod)); // The modifiermap member of the XModifierKeymap structure contains 8 sets // of max_keypermod KeyCodes, one for each modifier in the order Shift, // Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5. // Only nonzero KeyCodes have meaning in each set, and zero KeyCodes are // ignored. // Note that two or more modifiers may use one modifier flag. E.g., // on Ubuntu 10.10, Alt and Meta share the Mod1 in default settings. // And also Super and Hyper share the Mod4. In such cases, we need to // decide which modifier flag means one of DOM modifiers. // mod[0] is Modifier introduced by Mod1. Modifier mod[5]; int32_t foundLevel[5]; for (uint32_t i = 0; i < ArrayLength(mod); i++) { mod[i] = NOT_MODIFIER; foundLevel[i] = INT32_MAX; } const uint32_t map_size = 8 * xmodmap->max_keypermod; for (uint32_t i = 0; i < map_size; i++) { KeyCode keycode = xmodmap->modifiermap[i]; PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitBySystemSettings, " " i=%d, keycode=0x%08X", this, i, keycode)); if (!keycode || keycode < min_keycode || keycode > max_keycode) { continue; } ModifierKey* modifierKey = GetModifierKey(keycode); if (!modifierKey) { modifierKey = mModifierKeys.AppendElement(ModifierKey(keycode)); } const KeySym* syms = xkeymap + (keycode - min_keycode) * keysyms_per_keycode; const uint32_t bit = i / xmodmap->max_keypermod; modifierKey->mMask |= 1 << bit; // We need to know the meaning of Mod1, Mod2, Mod3, Mod4 and Mod5. // Let's skip if current map is for others. if (bit < 3) { continue; } const int32_t modIndex = bit - 3; for (int32_t j = 0; j < keysyms_per_keycode; j++) { Modifier modifier = GetModifierForGDKKeyval(syms[j]); PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS, ("KeymapWrapper(%p): InitBySystemSettings, " " Mod%d, j=%d, syms[j]=%s(0x%X), modifier=%s", this, modIndex + 1, j, gdk_keyval_name(syms[j]), syms[j], GetModifierName(modifier))); switch (modifier) { case NOT_MODIFIER: // Don't overwrite the stored information with // NOT_MODIFIER. break; case CAPS_LOCK: case SHIFT: case CTRL: // Ignore the modifiers defined in GDK spec. They shouldn't // be mapped to Mod1-5 because they must not work on native // GTK applications. break; default: // If new modifier is found in higher level than stored // value, we don't need to overwrite it. if (j > foundLevel[modIndex]) { break; } // If new modifier is more important than stored value, // we should overwrite it with new modifier. if (j == foundLevel[modIndex]) { mod[modIndex] = std::min(modifier, mod[modIndex]); break; } foundLevel[modIndex] = j; mod[modIndex] = modifier; break; } } } for (uint32_t i = 0; i < COUNT_OF_MODIFIER_INDEX; i++) { Modifier modifier; switch (i) { case INDEX_NUM_LOCK: modifier = NUM_LOCK; break; case INDEX_SCROLL_LOCK: modifier = SCROLL_LOCK; break; case INDEX_ALT: modifier = ALT; break; case INDEX_META: modifier = META; break; case INDEX_SUPER: modifier = SUPER; break; case INDEX_HYPER: modifier = HYPER; break; case INDEX_LEVEL3: modifier = LEVEL3; break; case INDEX_LEVEL5: modifier = LEVEL5; break; default: MOZ_CRASH("All indexes must be handled here"); } for (uint32_t j = 0; j < ArrayLength(mod); j++) { if (modifier == mod[j]) { mModifierMasks[i] |= 1 << (j + 3); } } } XFreeModifiermap(xmodmap); XFree(xkeymap); }
void EditPointTool::updateStatusText() { QString text; if (text_editor) { text = tr("<b>%1</b>: Finish editing. ").arg(ModifierKey::escape()); } else if (editingInProgress()) { MapCoordF drag_vector = constrained_pos_map - click_pos_map; text = EditTool::tr("<b>Coordinate offset:</b> %1, %2 mm <b>Distance:</b> %3 m "). arg(QLocale().toString(drag_vector.x(), 'f', 1)). arg(QLocale().toString(-drag_vector.y(), 'f', 1)). arg(QLocale().toString(0.001 * map()->getScaleDenominator() * drag_vector.length(), 'f', 1)) + QLatin1String("| "); if (!angle_helper->isActive()) text += EditTool::tr("<b>%1</b>: Fixed angles. ").arg(ModifierKey::control()); if (!(active_modifiers & Qt::ShiftModifier)) { if (hover_state == OverObjectNode && hover_object->getType() == Object::Path && hover_object->asPath()->isCurveHandle(hover_point)) { text += tr("<b>%1</b>: Keep opposite handle positions. ").arg(ModifierKey::shift()); } else { text += EditTool::tr("<b>%1</b>: Snap to existing objects. ").arg(ModifierKey::shift()); } } } else { text = EditTool::tr("<b>Click</b>: Select a single object. <b>Drag</b>: Select multiple objects. <b>%1+Click</b>: Toggle selection. ").arg(ModifierKey::shift()); if (map()->getNumSelectedObjects() > 0) { text += EditTool::tr("<b>%1</b>: Delete selected objects. ").arg(ModifierKey(delete_object_key)); if (map()->selectedObjects().size() <= max_objects_for_handle_display) { // TODO: maybe show this only if at least one PathObject among the selected objects? if (active_modifiers & Qt::ControlModifier) { if (addDashPointDefault()) text = tr("<b>%1+Click</b> on point: Delete it; on path: Add a new dash point; with <b>%2</b>: Add a normal point. "). arg(ModifierKey::control(), ModifierKey::space()); else text = tr("<b>%1+Click</b> on point: Delete it; on path: Add a new point; with <b>%2</b>: Add a dash point. "). arg(ModifierKey::control(), ModifierKey::space()); } else if (space_pressed) text = tr("<b>%1+Click</b> on point to switch between dash and normal point. ").arg(ModifierKey::space()); else text += QLatin1String("| ") + MapEditorTool::tr("More: %1, %2").arg(ModifierKey::control(), ModifierKey::space()); } } } setStatusBarText(text); }
namespace dom { /* static */ void FuzzingFunctions::GarbageCollect(const GlobalObject&) { nsJSContext::GarbageCollectNow(JS::gcreason::COMPONENT_UTILS, nsJSContext::NonIncrementalGC, nsJSContext::NonShrinkingGC); } /* static */ void FuzzingFunctions::CycleCollect(const GlobalObject&) { nsJSContext::CycleCollectNow(); } /* static */ void FuzzingFunctions::EnableAccessibility(const GlobalObject&, ErrorResult& aRv) { RefPtr<nsIAccessibilityService> a11y; nsresult rv; rv = NS_GetAccessibilityService(getter_AddRefs(a11y)); if (NS_FAILED(rv)) { aRv.Throw(rv); } } struct ModifierKey final { Modifier mModifier; KeyNameIndex mKeyNameIndex; bool mLockable; ModifierKey(Modifier aModifier, KeyNameIndex aKeyNameIndex, bool aLockable) : mModifier(aModifier) , mKeyNameIndex(aKeyNameIndex) , mLockable(aLockable) { } }; static const ModifierKey kModifierKeys[] = { ModifierKey(MODIFIER_ALT, KEY_NAME_INDEX_Alt, false), ModifierKey(MODIFIER_ALTGRAPH, KEY_NAME_INDEX_AltGraph, false), ModifierKey(MODIFIER_CONTROL, KEY_NAME_INDEX_Control, false), ModifierKey(MODIFIER_FN, KEY_NAME_INDEX_Fn, false), ModifierKey(MODIFIER_META, KEY_NAME_INDEX_Meta, false), ModifierKey(MODIFIER_OS, KEY_NAME_INDEX_OS, false), ModifierKey(MODIFIER_SHIFT, KEY_NAME_INDEX_Shift, false), ModifierKey(MODIFIER_SYMBOL, KEY_NAME_INDEX_Symbol, false), ModifierKey(MODIFIER_CAPSLOCK, KEY_NAME_INDEX_CapsLock, true), ModifierKey(MODIFIER_FNLOCK, KEY_NAME_INDEX_FnLock, true), ModifierKey(MODIFIER_NUMLOCK, KEY_NAME_INDEX_NumLock, true), ModifierKey(MODIFIER_SCROLLLOCK, KEY_NAME_INDEX_ScrollLock, true), ModifierKey(MODIFIER_SYMBOLLOCK, KEY_NAME_INDEX_SymbolLock, true), }; /* static */ Modifiers FuzzingFunctions::ActivateModifiers(TextInputProcessor* aTextInputProcessor, Modifiers aModifiers, nsIWidget* aWidget, ErrorResult& aRv) { MOZ_ASSERT(aTextInputProcessor); if (aModifiers == MODIFIER_NONE) { return MODIFIER_NONE; } // We don't want to dispatch modifier key event from here. In strictly // speaking, all necessary modifiers should be activated with dispatching // each modifier key event. However, we cannot keep storing // TextInputProcessor instance for multiple SynthesizeKeyboardEvents() calls. // So, if some callers need to emulate modifier key events, they should do // it by themselves. uint32_t flags = nsITextInputProcessor::KEY_NON_PRINTABLE_KEY | nsITextInputProcessor::KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT; Modifiers activatedModifiers = MODIFIER_NONE; Modifiers activeModifiers = aTextInputProcessor->GetActiveModifiers(); for (const ModifierKey& kModifierKey : kModifierKeys) { if (!(kModifierKey.mModifier & aModifiers)) { continue; // Not requested modifier. } if (kModifierKey.mModifier & activeModifiers) { continue; // Already active, do nothing. } WidgetKeyboardEvent event(true, eVoidEvent, aWidget); // mKeyCode will be computed by TextInputProcessor automatically. event.mKeyNameIndex = kModifierKey.mKeyNameIndex; aRv = aTextInputProcessor->Keydown(event, flags); if (NS_WARN_IF(aRv.Failed())) { return activatedModifiers; } if (kModifierKey.mLockable) { aRv = aTextInputProcessor->Keyup(event, flags); if (NS_WARN_IF(aRv.Failed())) { return activatedModifiers; } } activatedModifiers |= kModifierKey.mModifier; } return activatedModifiers; } /* static */ Modifiers FuzzingFunctions::InactivateModifiers(TextInputProcessor* aTextInputProcessor, Modifiers aModifiers, nsIWidget* aWidget, ErrorResult& aRv) { MOZ_ASSERT(aTextInputProcessor); if (aModifiers == MODIFIER_NONE) { return MODIFIER_NONE; } // We don't want to dispatch modifier key event from here. In strictly // speaking, all necessary modifiers should be activated with dispatching // each modifier key event. However, we cannot keep storing // TextInputProcessor instance for multiple SynthesizeKeyboardEvents() calls. // So, if some callers need to emulate modifier key events, they should do // it by themselves. uint32_t flags = nsITextInputProcessor::KEY_NON_PRINTABLE_KEY | nsITextInputProcessor::KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT; Modifiers inactivatedModifiers = MODIFIER_NONE; Modifiers activeModifiers = aTextInputProcessor->GetActiveModifiers(); for (const ModifierKey& kModifierKey : kModifierKeys) { if (!(kModifierKey.mModifier & aModifiers)) { continue; // Not requested modifier. } if (kModifierKey.mModifier & activeModifiers) { continue; // Already active, do nothing. } WidgetKeyboardEvent event(true, eVoidEvent, aWidget); // mKeyCode will be computed by TextInputProcessor automatically. event.mKeyNameIndex = kModifierKey.mKeyNameIndex; if (kModifierKey.mLockable) { aRv = aTextInputProcessor->Keydown(event, flags); if (NS_WARN_IF(aRv.Failed())) { return inactivatedModifiers; } } aRv = aTextInputProcessor->Keyup(event, flags); if (NS_WARN_IF(aRv.Failed())) { return inactivatedModifiers; } inactivatedModifiers |= kModifierKey.mModifier; } return inactivatedModifiers; } /* static */ void FuzzingFunctions::SynthesizeKeyboardEvents(const GlobalObject&, const nsAString& aKeyValue, const KeyboardEventInit& aDict, ErrorResult& aRv) { // Prepare keyboard event to synthesize first. uint32_t flags = 0; // Don't modify the given dictionary since caller may want to modify // a part of it and call this with it again. WidgetKeyboardEvent event(true, eVoidEvent, nullptr); event.mKeyCode = aDict.mKeyCode; event.mCharCode = 0; // Ignore. event.mKeyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aKeyValue); if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { event.mKeyValue = aKeyValue; } // code value should be empty string or one of valid code value. event.mCodeNameIndex = aDict.mCode.IsEmpty() ? CODE_NAME_INDEX_UNKNOWN : WidgetKeyboardEvent::GetCodeNameIndex(aDict.mCode); if (NS_WARN_IF(event.mCodeNameIndex == CODE_NAME_INDEX_USE_STRING)) { // Meaning that the code value is specified but it's not a known code // value. TextInputProcessor does not support synthesizing keyboard // events with unknown code value. So, returns error now. aRv.Throw(NS_ERROR_INVALID_ARG); return; } event.mLocation = aDict.mLocation; event.mIsRepeat = aDict.mRepeat; #define SET_MODIFIER(aName, aValue) \ if (aDict.m##aName) { \ event.mModifiers |= aValue; \ } \ SET_MODIFIER(CtrlKey, MODIFIER_CONTROL) SET_MODIFIER(ShiftKey, MODIFIER_SHIFT) SET_MODIFIER(AltKey, MODIFIER_ALT) SET_MODIFIER(MetaKey, MODIFIER_META) SET_MODIFIER(ModifierAltGraph, MODIFIER_ALTGRAPH) SET_MODIFIER(ModifierCapsLock, MODIFIER_CAPSLOCK) SET_MODIFIER(ModifierFn, MODIFIER_FN) SET_MODIFIER(ModifierFnLock, MODIFIER_FNLOCK) SET_MODIFIER(ModifierNumLock, MODIFIER_NUMLOCK) SET_MODIFIER(ModifierOS, MODIFIER_OS) SET_MODIFIER(ModifierScrollLock, MODIFIER_SCROLLLOCK) SET_MODIFIER(ModifierSymbol, MODIFIER_SYMBOL) SET_MODIFIER(ModifierSymbolLock, MODIFIER_SYMBOLLOCK) #undef SET_MODIFIER // If we could distinguish whether the caller specified 0 explicitly or // not, we would skip computing the key location when it's specified // explicitly. However, this caller probably won't test tricky keyboard // events, so, it must be enough even though caller cannot set location // to 0. Maybe<uint32_t> maybeNonStandardLocation; if (!event.mLocation) { maybeNonStandardLocation = mozilla::Some(event.mLocation); } // If the key is a printable key and |.code| and/or |.keyCode| value is // not specified as non-zero explicitly, let's assume that the caller // emulates US-English keyboard's behavior (because otherwise, caller // should set both values. if (event.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) { if (event.mCodeNameIndex == CODE_NAME_INDEX_UNKNOWN) { event.mCodeNameIndex = TextInputProcessor::GuessCodeNameIndexOfPrintableKeyInUSEnglishLayout( event.mKeyValue, maybeNonStandardLocation); MOZ_ASSERT(event.mCodeNameIndex != CODE_NAME_INDEX_USE_STRING); } if (!event.mKeyCode) { event.mKeyCode = TextInputProcessor::GuessKeyCodeOfPrintableKeyInUSEnglishLayout( event.mKeyValue, maybeNonStandardLocation); if (!event.mKeyCode) { // Prevent to recompute keyCode in TextInputProcessor. flags |= nsITextInputProcessor::KEY_KEEP_KEYCODE_ZERO; } } } // If the key is a non-printable key, we can compute |.code| value of // usual keyboard of the platform. Note that |.keyCode| value for // non-printable key will be computed by TextInputProcessor. So, we need // to take care only |.code| value here. else if (event.mCodeNameIndex == CODE_NAME_INDEX_UNKNOWN) { event.mCodeNameIndex = WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex( event.mKeyNameIndex, maybeNonStandardLocation); } // Synthesize keyboard events on focused widget. nsFocusManager* focusManager = nsFocusManager::GetFocusManager(); if (NS_WARN_IF(!focusManager)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return; } nsPIDOMWindowOuter* activeWindow = focusManager->GetActiveWindow(); if (NS_WARN_IF(!activeWindow)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return; } nsIDocShell* docShell = activeWindow->GetDocShell(); if (NS_WARN_IF(!docShell)) { aRv.Throw(NS_ERROR_FAILURE); return; } RefPtr<nsPresContext> presContext; docShell->GetPresContext(getter_AddRefs(presContext)); if (NS_WARN_IF(!presContext)) { aRv.Throw(NS_ERROR_FAILURE); return; } event.mWidget = presContext->GetRootWidget(); if (NS_WARN_IF(!event.mWidget)) { aRv.Throw(NS_ERROR_FAILURE); return; } nsCOMPtr<nsPIDOMWindowInner> activeWindowInner = activeWindow->EnsureInnerWindow(); if (NS_WARN_IF(!activeWindowInner)) { aRv.Throw(NS_ERROR_FAILURE); return; } RefPtr<TextInputProcessor> textInputProcessor = new TextInputProcessor(); bool beganInputTransaction = false; aRv = textInputProcessor->BeginInputTransactionForFuzzing( activeWindowInner, nullptr, &beganInputTransaction); if (NS_WARN_IF(aRv.Failed())) { return; } if (NS_WARN_IF(!beganInputTransaction)) { // This is possible if a keyboard event listener or something tries to // dispatch next keyboard events during dispatching a keyboard event via // TextInputProcessor. aRv.Throw(NS_ERROR_FAILURE); return; } // First, activate necessary modifiers. Modifiers activatedModifiers = ActivateModifiers(textInputProcessor, event.mModifiers, event.mWidget, aRv); if (NS_WARN_IF(aRv.Failed())) { return; } // Then, dispatch keydown and keypress. aRv = textInputProcessor->Keydown(event, flags); if (NS_WARN_IF(aRv.Failed())) { return; } // Then, dispatch keyup. aRv = textInputProcessor->Keyup(event, flags); if (NS_WARN_IF(aRv.Failed())) { return; } // Finally, inactivate some modifiers which are activated by this call. InactivateModifiers(textInputProcessor, activatedModifiers, event.mWidget, aRv); if (NS_WARN_IF(aRv.Failed())) { return; } // Unfortunately, we cannot keep storing modifier state in the // TextInputProcessor since if we store it into a static variable, // we need to take care of resetting it when the caller wants. // However, that makes API more complicated. So, until they need // to want } } // namespace dom