Bug 966395 - Correctly propagate the input language's direction on OSX. r=masayuki/mrbkap

Gtk patch written by mrbkap@mozilla.com, with r=roc
This commit is contained in:
Alexandru Tifrea 2015-04-10 15:18:05 -07:00
parent 4717b36921
commit 750f1d8d1c
15 changed files with 163 additions and 8 deletions

View File

@ -179,6 +179,7 @@
#include "mozilla/dom/time/DateCacheCleaner.h"
#include "mozilla/dom/voicemail/VoicemailIPCService.h"
#include "mozilla/net/NeckoMessageUtils.h"
#include "mozilla/widget/PuppetBidiKeyboard.h"
#include "mozilla/RemoteSpellCheckEngineChild.h"
#include "GMPServiceChild.h"
@ -200,6 +201,7 @@ using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
using namespace mozilla::jsipc;
using namespace mozilla::widget;
#if defined(MOZ_WIDGET_GONK)
using namespace mozilla::system;
#endif
@ -793,12 +795,14 @@ ContentChild::InitXPCOM()
if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
NS_WARNING("Couldn't register console listener for child process");
bool isOffline;
bool isOffline, isLangRTL;
ClipboardCapabilities clipboardCaps;
DomainPolicyClone domainPolicy;
SendGetXPCOMProcessAttributes(&isOffline, &mAvailableDictionaries, &clipboardCaps, &domainPolicy);
SendGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &mAvailableDictionaries,
&clipboardCaps, &domainPolicy);
RecvSetOffline(isOffline);
RecvBidiKeyboardNotify(isLangRTL);
if (domainPolicy.active()) {
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
@ -1222,6 +1226,18 @@ ContentChild::RecvSpeakerManagerNotify()
return false;
}
bool
ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL)
{
// bidi is always of type PuppetBidiKeyboard* (because in the child, the only
// possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard).
PuppetBidiKeyboard* bidi = static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard());
if (bidi) {
bidi->SetIsLangRTL(aIsLangRTL);
}
return true;
}
static CancelableTask* sFirstIdleTask;
static void FirstIdle(void)

View File

@ -299,6 +299,8 @@ public:
virtual bool RecvSpeakerManagerNotify() override;
virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) override;
virtual bool RecvNotifyVisited(const URIParams& aURI) override;
// auto remove when alertfinished is received.
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);

View File

@ -151,6 +151,8 @@
#include "private/pprio.h"
#include "ContentProcessManager.h"
#include "nsIBidiKeyboard.h"
#if defined(ANDROID) || defined(LINUX)
#include "nsSystemInfo.h"
#endif
@ -2817,11 +2819,11 @@ ContentParent::RecvAddNewProcess(const uint32_t& aPid,
}
// Update offline settings.
bool isOffline;
bool isOffline, isLangRTL;
InfallibleTArray<nsString> unusedDictionaries;
ClipboardCapabilities clipboardCaps;
DomainPolicyClone domainPolicy;
RecvGetXPCOMProcessAttributes(&isOffline, &unusedDictionaries,
RecvGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &unusedDictionaries,
&clipboardCaps, &domainPolicy);
mozilla::unused << content->SendSetOffline(isOffline);
MOZ_ASSERT(!clipboardCaps.supportsSelectionClipboard() &&
@ -3164,6 +3166,7 @@ ContentParent::RecvGetProcessAttributes(ContentParentId* aCpId,
bool
ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
bool* aIsLangRTL,
InfallibleTArray<nsString>* dictionaries,
ClipboardCapabilities* clipboardCaps,
DomainPolicyClone* domainPolicy)
@ -3173,6 +3176,13 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed getting offline?");
nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard();
*aIsLangRTL = false;
if (bidi) {
bidi->IsLangRTL(aIsLangRTL);
}
nsCOMPtr<nsISpellChecker> spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID));
MOZ_ASSERT(spellChecker, "No spell checker?");

View File

@ -535,6 +535,7 @@ private:
bool* aIsForApp,
bool* aIsForBrowser) override;
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline,
bool* aIsLangRTL,
InfallibleTArray<nsString>* dictionaries,
ClipboardCapabilities* clipboardCaps,
DomainPolicyClone* domainPolicy)

View File

@ -456,6 +456,12 @@ child:
async SpeakerManagerNotify();
/**
* Communication between the PuppetBidiKeyboard and the actual
* BidiKeyboard hosted by the parent
*/
async BidiKeyboardNotify(bool isLangRTL);
async DataStoreNotify(uint32_t aAppId, nsString aName,
nsString aManifestURL);
@ -616,7 +622,7 @@ parent:
sync GetProcessAttributes()
returns (ContentParentId cpId, bool isForApp, bool isForBrowser);
sync GetXPCOMProcessAttributes()
returns (bool isOffline, nsString[] dictionaries,
returns (bool isOffline, bool isLangRTL, nsString[] dictionaries,
ClipboardCapabilities clipboardCaps,
DomainPolicyClone domainPolicy);

View File

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PuppetBidiKeyboard.h"
using namespace mozilla::widget;
NS_IMPL_ISUPPORTS(PuppetBidiKeyboard, nsIBidiKeyboard)
PuppetBidiKeyboard::PuppetBidiKeyboard() : nsIBidiKeyboard()
{
}
PuppetBidiKeyboard::~PuppetBidiKeyboard()
{
}
NS_IMETHODIMP
PuppetBidiKeyboard::Reset()
{
return NS_OK;
}
NS_IMETHODIMP
PuppetBidiKeyboard::IsLangRTL(bool* aIsRTL)
{
*aIsRTL = mIsLangRTL;
return NS_OK;
}
void
PuppetBidiKeyboard::SetIsLangRTL(bool aIsLangRTL)
{
mIsLangRTL = aIsLangRTL;
}
NS_IMETHODIMP
PuppetBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
{
// not implemented yet
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_widget_PuppetBidiKeyboard_h_
#define mozilla_widget_PuppetBidiKeyboard_h_
#include "nsIBidiKeyboard.h"
namespace mozilla {
namespace widget {
class PuppetBidiKeyboard final : public nsIBidiKeyboard
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIBIDIKEYBOARD
PuppetBidiKeyboard();
void SetIsLangRTL(bool aIsLangRTL);
private:
~PuppetBidiKeyboard();
bool mIsLangRTL;
};
} // namespace widget
} // namespace mozilla
#endif // mozilla_widget_PuppetBidiKeyboard_h_

View File

@ -1004,6 +1004,8 @@ private:
// We cannot access to the NSInputManager during we aren't active, so, the
// focused handler can have an IME transaction even if we are deactive.
static IMEInputHandler* sFocusedIMEHandler;
static bool sCachedIsForRTLLangage;
};
/**

View File

@ -21,6 +21,8 @@
#include "nsCocoaUtils.h"
#include "WidgetUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/unused.h"
#include "mozilla/dom/ContentParent.h"
#include "ComplexTextInputPanel.h"
using namespace mozilla;
@ -2227,6 +2229,7 @@ TextInputHandler::DoCommandBySelector(const char* aSelector)
******************************************************************************/
bool IMEInputHandler::sStaticMembersInitialized = false;
bool IMEInputHandler::sCachedIsForRTLLangage = false;
CFStringRef IMEInputHandler::sLatestIMEOpenedModeInputSourceID = nullptr;
IMEInputHandler* IMEInputHandler::sFocusedIMEHandler = nullptr;
@ -2315,6 +2318,20 @@ IMEInputHandler::OnCurrentTextInputSourceChange(CFNotificationCenterRef aCenter,
sLastTIS = newTIS;
}
#endif // #ifdef PR_LOGGING
/**
* When the direction is changed, all the children are notified.
* No need to treat the initial case separately because it is covered
* by the general case (sCachedIsForRTLLangage is initially false)
*/
if (sCachedIsForRTLLangage != tis.IsForRTLLanguage()) {
nsTArray<dom::ContentParent*> children;
dom::ContentParent::GetAll(children);
for (uint32_t i = 0; i < children.Length(); i++) {
unused << children[i]->SendBidiKeyboardNotify(tis.IsForRTLLanguage());
}
sCachedIsForRTLLangage = tis.IsForRTLLanguage();
}
}
// static

View File

@ -12,6 +12,7 @@ XPIDL_MODULE = 'widget_cocoa'
EXPORTS += [
'mozView.h',
'nsBidiKeyboard.h',
'nsChangeObserver.h',
'nsCocoaFeatures.h',
'nsCocoaUtils.h',

View File

@ -135,7 +135,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor },
{ &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor },
{ &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor },
{ &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
@ -172,7 +173,8 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
{ "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID },
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
mozilla::Module::MAIN_PROCESS_ONLY },

View File

@ -20,7 +20,10 @@ nsBidiKeyboard::nsBidiKeyboard()
NS_IMETHODIMP
nsBidiKeyboard::Reset()
{
mHaveBidiKeyboards = gdk_keymap_have_bidi_layouts(gdk_keymap_get_default());
// NB: The default keymap can be null (e.g. in xpcshell). In that case,
// simply assume that we don't have bidi keyboards.
GdkKeymap *keymap = gdk_keymap_get_default();
mHaveBidiKeyboards = keymap && gdk_keymap_have_bidi_layouts(keymap);
return NS_OK;
}

View File

@ -131,6 +131,10 @@ EXPORTS.mozilla += [
'WidgetUtils.h',
]
EXPORTS.mozilla.widget += [
'PuppetBidiKeyboard.h',
]
UNIFIED_SOURCES += [
'ContentHelper.cpp',
'GfxDriverInfo.cpp',
@ -158,6 +162,7 @@ UNIFIED_SOURCES += [
'nsTransferable.cpp',
'nsXPLookAndFeel.cpp',
'PluginWidgetProxy.cpp',
'PuppetBidiKeyboard.cpp',
'PuppetWidget.cpp',
'ScreenProxy.cpp',
'SharedWidgetUtils.cpp',

View File

@ -12,8 +12,10 @@
#include "nsDragServiceProxy.h"
#include "nsFilePickerProxy.h"
#include "nsScreenManagerProxy.h"
#include "mozilla/widget/PuppetBidiKeyboard.h"
using namespace mozilla;
using namespace mozilla::widget;
#ifndef MOZ_B2G
@ -22,11 +24,13 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragServiceProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard)
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
NS_DEFINE_NAMED_CID(PUPPETBIDIKEYBOARD_CID);
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
@ -40,6 +44,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
Module::CONTENT_PROCESS_ONLY },
{ &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerProxyConstructor,
Module::CONTENT_PROCESS_ONLY },
{ &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor,
mozilla::Module::CONTENT_PROCESS_ONLY },
{ nullptr }
};

View File

@ -109,6 +109,9 @@
#define NS_BIDIKEYBOARD_CID \
{ 0x9f1800ab, 0xf428, 0x4207, { 0xb4, 0x0c, 0xe8, 0x32, 0xe7, 0x7b, 0x01, 0xfc } }
#define PUPPETBIDIKEYBOARD_CID \
{ 0x689e2586, 0x0344, 0x40b2, {0x83, 0x75, 0x13, 0x67, 0x2d, 0x3b, 0x71, 0x9a } }
#define NS_SCREENMANAGER_CID \
{ 0xc401eb80, 0xf9ea, 0x11d3, { 0xbb, 0x6f, 0xe7, 0x32, 0xb7, 0x3e, 0xbe, 0x7c } }