Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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