michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "WidgetUtils.h" michael@0: michael@0: #include "mozilla/TextEvents.h" michael@0: michael@0: #include "nsIBaseWindow.h" michael@0: #include "nsIDocShellTreeItem.h" michael@0: #include "nsIDocShell.h" michael@0: #include "nsIInterfaceRequestorUtils.h" michael@0: michael@0: namespace mozilla { michael@0: namespace widget { michael@0: michael@0: //static michael@0: already_AddRefed michael@0: WidgetUtils::DOMWindowToWidget(nsIDOMWindow *aDOMWindow) michael@0: { michael@0: nsCOMPtr widget; michael@0: michael@0: nsCOMPtr window = do_QueryInterface(aDOMWindow); michael@0: if (window) { michael@0: nsCOMPtr baseWin(do_QueryInterface(window->GetDocShell())); michael@0: michael@0: while (!widget && baseWin) { michael@0: baseWin->GetParentWidget(getter_AddRefs(widget)); michael@0: if (!widget) { michael@0: nsCOMPtr docShellAsItem(do_QueryInterface(baseWin)); michael@0: if (!docShellAsItem) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr parent; michael@0: docShellAsItem->GetParent(getter_AddRefs(parent)); michael@0: michael@0: window = do_GetInterface(parent); michael@0: if (!window) michael@0: return nullptr; michael@0: michael@0: baseWin = do_QueryInterface(window->GetDocShell()); michael@0: } michael@0: } michael@0: } michael@0: michael@0: return widget.forget(); michael@0: } michael@0: michael@0: // static michael@0: uint32_t michael@0: WidgetUtils::ComputeKeyCodeFromChar(uint32_t aCharCode) michael@0: { michael@0: if (aCharCode >= 'A' && aCharCode <= 'Z') { michael@0: return aCharCode - 'A' + NS_VK_A; michael@0: } michael@0: if (aCharCode >= 'a' && aCharCode <= 'z') { michael@0: return aCharCode - 'a' + NS_VK_A; michael@0: } michael@0: if (aCharCode >= '0' && aCharCode <= '9') { michael@0: return aCharCode - '0' + NS_VK_0; michael@0: } michael@0: switch (aCharCode) { michael@0: case ' ': return NS_VK_SPACE; michael@0: case '\t': return NS_VK_TAB; michael@0: case ':': return NS_VK_COLON; michael@0: case ';': return NS_VK_SEMICOLON; michael@0: case '<': return NS_VK_LESS_THAN; michael@0: case '=': return NS_VK_EQUALS; michael@0: case '>': return NS_VK_GREATER_THAN; michael@0: case '?': return NS_VK_QUESTION_MARK; michael@0: case '@': return NS_VK_AT; michael@0: case '^': return NS_VK_CIRCUMFLEX; michael@0: case '!': return NS_VK_EXCLAMATION; michael@0: case '"': return NS_VK_DOUBLE_QUOTE; michael@0: case '#': return NS_VK_HASH; michael@0: case '$': return NS_VK_DOLLAR; michael@0: case '%': return NS_VK_PERCENT; michael@0: case '&': return NS_VK_AMPERSAND; michael@0: case '_': return NS_VK_UNDERSCORE; michael@0: case '(': return NS_VK_OPEN_PAREN; michael@0: case ')': return NS_VK_CLOSE_PAREN; michael@0: case '*': return NS_VK_ASTERISK; michael@0: case '+': return NS_VK_PLUS; michael@0: case '|': return NS_VK_PIPE; michael@0: case '-': return NS_VK_HYPHEN_MINUS; michael@0: case '{': return NS_VK_OPEN_CURLY_BRACKET; michael@0: case '}': return NS_VK_CLOSE_CURLY_BRACKET; michael@0: case '~': return NS_VK_TILDE; michael@0: case ',': return NS_VK_COMMA; michael@0: case '.': return NS_VK_PERIOD; michael@0: case '/': return NS_VK_SLASH; michael@0: case '`': return NS_VK_BACK_QUOTE; michael@0: case '[': return NS_VK_OPEN_BRACKET; michael@0: case '\\': return NS_VK_BACK_SLASH; michael@0: case ']': return NS_VK_CLOSE_BRACKET; michael@0: case '\'': return NS_VK_QUOTE; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: // static michael@0: void michael@0: WidgetUtils::GetLatinCharCodeForKeyCode(uint32_t aKeyCode, michael@0: bool aIsCapsLock, michael@0: uint32_t* aUnshiftedCharCode, michael@0: uint32_t* aShiftedCharCode) michael@0: { michael@0: MOZ_ASSERT(aUnshiftedCharCode && aShiftedCharCode, michael@0: "aUnshiftedCharCode and aShiftedCharCode must not be NULL"); michael@0: michael@0: if (aKeyCode >= NS_VK_A && aKeyCode <= NS_VK_Z) { michael@0: *aUnshiftedCharCode = *aShiftedCharCode = aKeyCode; michael@0: if (aIsCapsLock) { michael@0: *aShiftedCharCode += 0x20; michael@0: } else { michael@0: *aUnshiftedCharCode += 0x20; michael@0: } michael@0: return; michael@0: } michael@0: michael@0: // aShiftedCharCode must be zero for non-alphabet keys. michael@0: *aShiftedCharCode = 0; michael@0: michael@0: if (aKeyCode >= NS_VK_0 && aKeyCode <= NS_VK_9) { michael@0: *aUnshiftedCharCode = aKeyCode; michael@0: return; michael@0: } michael@0: michael@0: switch (aKeyCode) { michael@0: case NS_VK_SPACE: *aUnshiftedCharCode = ' '; break; michael@0: case NS_VK_COLON: *aUnshiftedCharCode = ':'; break; michael@0: case NS_VK_SEMICOLON: *aUnshiftedCharCode = ';'; break; michael@0: case NS_VK_LESS_THAN: *aUnshiftedCharCode = '<'; break; michael@0: case NS_VK_EQUALS: *aUnshiftedCharCode = '='; break; michael@0: case NS_VK_GREATER_THAN: *aUnshiftedCharCode = '>'; break; michael@0: case NS_VK_QUESTION_MARK: *aUnshiftedCharCode = '?'; break; michael@0: case NS_VK_AT: *aUnshiftedCharCode = '@'; break; michael@0: case NS_VK_CIRCUMFLEX: *aUnshiftedCharCode = '^'; break; michael@0: case NS_VK_EXCLAMATION: *aUnshiftedCharCode = '!'; break; michael@0: case NS_VK_DOUBLE_QUOTE: *aUnshiftedCharCode = '"'; break; michael@0: case NS_VK_HASH: *aUnshiftedCharCode = '#'; break; michael@0: case NS_VK_DOLLAR: *aUnshiftedCharCode = '$'; break; michael@0: case NS_VK_PERCENT: *aUnshiftedCharCode = '%'; break; michael@0: case NS_VK_AMPERSAND: *aUnshiftedCharCode = '&'; break; michael@0: case NS_VK_UNDERSCORE: *aUnshiftedCharCode = '_'; break; michael@0: case NS_VK_OPEN_PAREN: *aUnshiftedCharCode = '('; break; michael@0: case NS_VK_CLOSE_PAREN: *aUnshiftedCharCode = ')'; break; michael@0: case NS_VK_ASTERISK: *aUnshiftedCharCode = '*'; break; michael@0: case NS_VK_PLUS: *aUnshiftedCharCode = '+'; break; michael@0: case NS_VK_PIPE: *aUnshiftedCharCode = '|'; break; michael@0: case NS_VK_HYPHEN_MINUS: *aUnshiftedCharCode = '-'; break; michael@0: case NS_VK_OPEN_CURLY_BRACKET: *aUnshiftedCharCode = '{'; break; michael@0: case NS_VK_CLOSE_CURLY_BRACKET: *aUnshiftedCharCode = '}'; break; michael@0: case NS_VK_TILDE: *aUnshiftedCharCode = '~'; break; michael@0: case NS_VK_COMMA: *aUnshiftedCharCode = ','; break; michael@0: case NS_VK_PERIOD: *aUnshiftedCharCode = '.'; break; michael@0: case NS_VK_SLASH: *aUnshiftedCharCode = '/'; break; michael@0: case NS_VK_BACK_QUOTE: *aUnshiftedCharCode = '`'; break; michael@0: case NS_VK_OPEN_BRACKET: *aUnshiftedCharCode = '['; break; michael@0: case NS_VK_BACK_SLASH: *aUnshiftedCharCode = '\\'; break; michael@0: case NS_VK_CLOSE_BRACKET: *aUnshiftedCharCode = ']'; break; michael@0: case NS_VK_QUOTE: *aUnshiftedCharCode = '\''; break; michael@0: default: *aUnshiftedCharCode = 0; break; michael@0: } michael@0: } michael@0: michael@0: // static michael@0: KeyNameIndex michael@0: WidgetUtils::GetDeadKeyNameIndex(char16_t aChar) michael@0: { michael@0: switch (aChar) { michael@0: case '`': michael@0: case 0x02CB: // MODIFIER LETTER GRAVE ACCENT michael@0: case 0x0300: // COMBINING GRAVE ACCENT michael@0: return KEY_NAME_INDEX_DeadGrave; michael@0: case '\'': michael@0: case 0x00B4: // ACUTE ACCENT michael@0: case 0x02B9: // MODIFIER LETTER PRIME michael@0: case 0x02CA: // MODIFIER LETTER ACUTE ACCENT michael@0: case 0x0301: // COMBINING ACUTE ACCENT michael@0: case 0x0384: // GREEK TONOS michael@0: return KEY_NAME_INDEX_DeadAcute; michael@0: case '^': michael@0: case 0x02C6: // MODIFIER LETTER CIRCUMFLEX ACCENT michael@0: case 0x0302: // COMBINING CIRCUMFLEX ACCENT michael@0: return KEY_NAME_INDEX_DeadCircumflex; michael@0: case '~': michael@0: case 0x02DC: // SMALL TILDE michael@0: case 0x0303: // COMBINING TILDE michael@0: return KEY_NAME_INDEX_DeadTilde; michael@0: case 0x00AF: // MACRON michael@0: case 0x02C9: // MODIFIER LETTER MACRON michael@0: case 0x0304: // COMBINING MACRON michael@0: return KEY_NAME_INDEX_DeadMacron; michael@0: case 0x02D8: // BRAVE michael@0: case 0xA67C: // COMBINING CYRILLIC KAVYKA michael@0: case 0x0306: // COMBINING BRAVE michael@0: return KEY_NAME_INDEX_DeadBreve; michael@0: case 0x02D9: // DOT ABOVE michael@0: case 0x0307: // COMBINING DOT ABOVE michael@0: return KEY_NAME_INDEX_DeadAboveDot; michael@0: case 0x00A8: // DIAERESIS michael@0: case 0x0308: // COMBINING DIAERESIS michael@0: return KEY_NAME_INDEX_DeadUmlaut; michael@0: case 0x00B0: // DEGREE SIGN michael@0: case 0x02DA: // RING ABOVE michael@0: case 0x030A: // COMBINING RING ABOVE michael@0: return KEY_NAME_INDEX_DeadAboveRing; michael@0: case '"': michael@0: case 0x02BA: // MODIFIER LETTER DOUBLE PRIME michael@0: case 0x02DD: // DOUBLE ACUTE ACCENT michael@0: case 0x030B: // COMBINING DOUBLE ACUTE ACCENT michael@0: return KEY_NAME_INDEX_DeadDoubleacute; michael@0: case 0x02C7: // CARON michael@0: case 0x030C: // COMBINING CARON michael@0: return KEY_NAME_INDEX_DeadCaron; michael@0: case 0x00B8: // CEDILLA michael@0: case 0x0327: // COMBINING CEDILLA michael@0: return KEY_NAME_INDEX_DeadCedilla; michael@0: case 0x02DB: // OGONEK michael@0: case 0x0328: // COMBINING OGONEK michael@0: return KEY_NAME_INDEX_DeadOgonek; michael@0: case 0x0345: // COMBINING GREEK YPOGEGRAMMENI michael@0: case 0x037A: // GREEK YPOGEGRAMMENI michael@0: case 0x0399: // GREEK CAPITAL LETTER IOTA michael@0: return KEY_NAME_INDEX_DeadIota; michael@0: case 0x3099: // COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK michael@0: case 0x309B: // KATAKANA-HIRAGANA VOICED SOUND MARK michael@0: return KEY_NAME_INDEX_DeadVoicedSound; michael@0: case 0x309A: // COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK michael@0: case 0x309C: // KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK michael@0: return KEY_NAME_INDEX_DeadSemivoicedSound; michael@0: default: michael@0: return KEY_NAME_INDEX_Unidentified; michael@0: } michael@0: } michael@0: michael@0: } // namespace widget michael@0: } // namespace mozilla