зеркало из https://github.com/mozilla/pjs.git
Add support for native keybindings for input and textarea for gtk2. This allows us to respect the GTK keybinding preferences. Bug 257405, r=blizzard, sr=roc.
This commit is contained in:
Родитель
b89a09b444
Коммит
d342e8f7b4
|
@ -299,6 +299,7 @@ content/xbl/Makefile
|
||||||
content/xbl/public/Makefile
|
content/xbl/public/Makefile
|
||||||
content/xbl/src/Makefile
|
content/xbl/src/Makefile
|
||||||
content/xbl/builtin/Makefile
|
content/xbl/builtin/Makefile
|
||||||
|
content/xbl/builtin/gtk2/Makefile
|
||||||
content/xbl/builtin/unix/Makefile
|
content/xbl/builtin/unix/Makefile
|
||||||
content/xbl/builtin/win/Makefile
|
content/xbl/builtin/win/Makefile
|
||||||
content/xsl/Makefile
|
content/xsl/Makefile
|
||||||
|
|
|
@ -48,9 +48,13 @@ else
|
||||||
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
||||||
DIRS = mac
|
DIRS = mac
|
||||||
else
|
else
|
||||||
|
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||||
|
DIRS = gtk2
|
||||||
|
else
|
||||||
DIRS = unix
|
DIRS = unix
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Makefile
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<bindings id="htmlBindings"
|
||||||
|
xmlns="http://www.mozilla.org/xbl"
|
||||||
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
|
||||||
|
<binding id="inputFields">
|
||||||
|
<handlers>
|
||||||
|
<handler event="keypress" key="a" modifiers="alt"
|
||||||
|
command="cmd_selectAll"/>
|
||||||
|
<handler event="keypress" key="y" modifiers="accel"
|
||||||
|
command="cmd_redo"/>
|
||||||
|
<handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
|
||||||
|
<handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
|
||||||
|
<handler event="keypress" keycode="VK_F14" command="cmd_undo" />
|
||||||
|
</handlers>
|
||||||
|
</binding>
|
||||||
|
|
||||||
|
<binding id="textAreas">
|
||||||
|
<handlers>
|
||||||
|
<handler event="keypress" key="a" modifiers="alt"
|
||||||
|
command="cmd_selectAll"/>
|
||||||
|
<handler event="keypress" key="y" modifiers="accel"
|
||||||
|
command="cmd_redo"/>
|
||||||
|
<handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
|
||||||
|
<handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
|
||||||
|
<handler event="keypress" keycode="VK_F20" command="cmd_cut" />
|
||||||
|
<handler event="keypress" keycode="VK_F16" command="cmd_copy" />
|
||||||
|
<handler event="keypress" keycode="VK_F18" command="cmd_paste" />
|
||||||
|
<handler event="keypress" keycode="VK_F14" command="cmd_undo" />
|
||||||
|
</handlers>
|
||||||
|
</binding>
|
||||||
|
|
||||||
|
<binding id="browser">
|
||||||
|
<handlers>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
|
||||||
|
|
||||||
|
<handler event="keypress" keycode="VK_DELETE" modifiers="shift" command="cmd_cut" />
|
||||||
|
<handler event="keypress" keycode="VK_DELETE" modifiers="control" command="cmd_copy" />
|
||||||
|
<handler event="keypress" keycode="VK_INSERT" modifiers="control" command="cmd_copy" />
|
||||||
|
<handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
|
||||||
|
<handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
|
||||||
|
<handler event="keypress" keycode="VK_F20" command="cmd_cut" />
|
||||||
|
<handler event="keypress" keycode="VK_F16" command="cmd_copy" />
|
||||||
|
<handler event="keypress" keycode="VK_F18" command="cmd_paste" />
|
||||||
|
<handler event="keypress" keycode="VK_F14" command="cmd_undo" />
|
||||||
|
<handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious" />
|
||||||
|
<handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext" />
|
||||||
|
<handler event="keypress" keycode="VK_LEFT" modifiers="control,shift" command="cmd_selectWordPrevious" />
|
||||||
|
<handler event="keypress" keycode="VK_RIGHT" modifiers="control,shift" command="cmd_selectWordNext" />
|
||||||
|
<handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectCharPrevious" />
|
||||||
|
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectCharNext" />
|
||||||
|
<handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
|
||||||
|
<handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
|
||||||
|
<handler event="keypress" keycode="VK_UP" modifiers="shift" command="cmd_selectLinePrevious" />
|
||||||
|
<handler event="keypress" keycode="VK_DOWN" modifiers="shift" command="cmd_selectLineNext" />
|
||||||
|
<handler event="keypress" key="a" modifiers="alt" command="cmd_selectAll"/>
|
||||||
|
</handlers>
|
||||||
|
</binding>
|
||||||
|
|
||||||
|
<binding id="editor">
|
||||||
|
<handlers>
|
||||||
|
<handler event="keypress" key="h" modifiers="control" command="cmd_deleteCharBackward"/>
|
||||||
|
<handler event="keypress" key="d" modifiers="control" command="cmd_deleteCharForward"/>
|
||||||
|
<handler event="keypress" key="k" modifiers="control" command="cmd_deleteToEndOfLine"/>
|
||||||
|
<handler event="keypress" key="u" modifiers="control" command="cmd_deleteToBeginningOfLine"/>
|
||||||
|
<handler event="keypress" key="a" modifiers="control" command="cmd_beginLine"/>
|
||||||
|
<handler event="keypress" key="e" modifiers="control" command="cmd_endLine"/>
|
||||||
|
<handler event="keypress" key="b" modifiers="control" command="cmd_charPrevious"/>
|
||||||
|
<handler event="keypress" key="f" modifiers="control" command="cmd_charNext"/>
|
||||||
|
<handler event="keypress" key="p" modifiers="control" command="cmd_linePrevious"/>
|
||||||
|
<handler event="keypress" key="n" modifiers="control" command="cmd_lineNext"/>
|
||||||
|
<handler event="keypress" key="x" modifiers="control" command="cmd_cut"/>
|
||||||
|
<handler event="keypress" key="c" modifiers="control" command="cmd_copy"/>
|
||||||
|
<handler event="keypress" key="v" modifiers="control" command="cmd_paste"/>
|
||||||
|
<handler event="keypress" key="z" modifiers="control" command="cmd_undo"/>
|
||||||
|
<handler event="keypress" key="r" modifiers="accel" command="cmd_redo"/>
|
||||||
|
<handler event="keypress" key="y" modifiers="accel" command="cmd_redo"/>
|
||||||
|
<handler event="keypress" key="a" modifiers="alt" command="cmd_selectAll"/>
|
||||||
|
<handler event="keypress" keycode="VK_DELETE" modifiers="shift" command="cmd_cutOrDelete"/>
|
||||||
|
<handler event="keypress" keycode="VK_DELETE" modifiers="control" command="cmd_copyOrDelete"/>
|
||||||
|
<handler event="keypress" keycode="VK_INSERT" modifiers="control" command="cmd_copy"/>
|
||||||
|
<handler event="keypress" keycode="VK_INSERT" modifiers="shift" command="cmd_paste"/>
|
||||||
|
<handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious"/>
|
||||||
|
<handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext"/>
|
||||||
|
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,control" command="cmd_selectWordPrevious"/>
|
||||||
|
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,control" command="cmd_selectWordNext"/>
|
||||||
|
<handler event="keypress" keycode="VK_BACK" modifiers="control" command="cmd_deleteWordBackward"/>
|
||||||
|
<handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
|
||||||
|
<handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
|
||||||
|
<handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine"/>
|
||||||
|
<handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine"/>
|
||||||
|
<handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop"/>
|
||||||
|
<handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom"/>
|
||||||
|
<handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
|
||||||
|
<handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
|
||||||
|
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
|
||||||
|
<handler event="keypress" keycode="VK_F20" command="cmd_cut" />
|
||||||
|
<handler event="keypress" keycode="VK_F16" command="cmd_copy" />
|
||||||
|
<handler event="keypress" keycode="VK_F18" command="cmd_paste" />
|
||||||
|
<handler event="keypress" keycode="VK_F14" command="cmd_undo" />
|
||||||
|
</handlers>
|
||||||
|
</binding>
|
||||||
|
</bindings>
|
|
@ -128,6 +128,7 @@
|
||||||
#include "nsStyleSet.h"
|
#include "nsStyleSet.h"
|
||||||
#include "nsImageFrame.h"
|
#include "nsImageFrame.h"
|
||||||
#include "nsILanguageAtomService.h"
|
#include "nsILanguageAtomService.h"
|
||||||
|
#include "nsTextControlFrame.h"
|
||||||
|
|
||||||
// view stuff
|
// view stuff
|
||||||
#include "nsViewsCID.h"
|
#include "nsViewsCID.h"
|
||||||
|
@ -417,6 +418,7 @@ Shutdown()
|
||||||
|
|
||||||
GlobalWindowImpl::ShutDown();
|
GlobalWindowImpl::ShutDown();
|
||||||
nsDOMClassInfo::ShutDown();
|
nsDOMClassInfo::ShutDown();
|
||||||
|
nsTextControlFrame::ShutDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
|
|
|
@ -120,6 +120,10 @@
|
||||||
#include "nsIDOMText.h" //for multiline getselection
|
#include "nsIDOMText.h" //for multiline getselection
|
||||||
#include "nsNodeInfoManager.h"
|
#include "nsNodeInfoManager.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
|
#include "nsIDOMKeyListener.h"
|
||||||
|
#include "nsIDOMEventGroup.h"
|
||||||
|
#include "nsIDOM3EventTarget.h"
|
||||||
|
#include "nsINativeKeyBindings.h"
|
||||||
|
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
#include "nsIBidiKeyboard.h"
|
#include "nsIBidiKeyboard.h"
|
||||||
|
@ -138,8 +142,12 @@ static const PRInt32 DEFAULT_COLS = 20;
|
||||||
static const PRInt32 DEFAULT_ROWS = 1;
|
static const PRInt32 DEFAULT_ROWS = 1;
|
||||||
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;
|
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;
|
||||||
|
|
||||||
|
static nsINativeKeyBindings *sNativeInputBindings = nsnull;
|
||||||
|
static nsINativeKeyBindings *sNativeTextAreaBindings = nsnull;
|
||||||
|
|
||||||
class nsTextInputListener : public nsISelectionListener,
|
class nsTextInputListener : public nsISelectionListener,
|
||||||
public nsIDOMFocusListener,
|
public nsIDOMFocusListener,
|
||||||
|
public nsIDOMKeyListener,
|
||||||
public nsIEditorObserver,
|
public nsIEditorObserver,
|
||||||
public nsSupportsWeakReference
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
|
@ -169,12 +177,19 @@ public:
|
||||||
NS_IMETHOD Blur (nsIDOMEvent* aEvent);
|
NS_IMETHOD Blur (nsIDOMEvent* aEvent);
|
||||||
/* END interfaces from nsIDOMFocusListener*/
|
/* END interfaces from nsIDOMFocusListener*/
|
||||||
|
|
||||||
|
// nsIDOMKeyListener
|
||||||
|
NS_IMETHOD KeyDown(nsIDOMEvent *aKeyEvent);
|
||||||
|
NS_IMETHOD KeyPress(nsIDOMEvent *aKeyEvent);
|
||||||
|
NS_IMETHOD KeyUp(nsIDOMEvent *aKeyEvent);
|
||||||
|
|
||||||
NS_DECL_NSIEDITOROBSERVER
|
NS_DECL_NSIEDITOROBSERVER
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsresult UpdateTextInputCommands(const nsAString& commandsToUpdate);
|
nsresult UpdateTextInputCommands(const nsAString& commandsToUpdate);
|
||||||
|
|
||||||
|
NS_HIDDEN_(nsINativeKeyBindings*) GetKeyBindings();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsTextControlFrame* mFrame; // weak reference
|
nsTextControlFrame* mFrame; // weak reference
|
||||||
|
@ -211,9 +226,18 @@ nsTextInputListener::~nsTextInputListener()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS5(nsTextInputListener, nsISelectionListener,
|
NS_IMPL_ADDREF(nsTextInputListener)
|
||||||
nsIDOMEventListener, nsIDOMFocusListener,
|
NS_IMPL_RELEASE(nsTextInputListener)
|
||||||
nsIEditorObserver, nsISupportsWeakReference)
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsTextInputListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIEditorObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFocusListener)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
// BEGIN nsIDOMSelectionListener
|
// BEGIN nsIDOMSelectionListener
|
||||||
|
|
||||||
|
@ -313,6 +337,103 @@ nsTextInputListener::Blur(nsIDOMEvent* aEvent)
|
||||||
|
|
||||||
// END nsIFocusListener
|
// END nsIFocusListener
|
||||||
|
|
||||||
|
// BEGIN nsIDOMKeyListener
|
||||||
|
|
||||||
|
static void
|
||||||
|
DoCommandCallback(const char *aCommand, void *aData)
|
||||||
|
{
|
||||||
|
nsTextControlFrame *frame = NS_STATIC_CAST(nsTextControlFrame*, aData);
|
||||||
|
nsIContent *content = frame->GetContent();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIControllers> controllers;
|
||||||
|
nsCOMPtr<nsIDOMNSHTMLInputElement> input = do_QueryInterface(content);
|
||||||
|
if (input) {
|
||||||
|
input->GetControllers(getter_AddRefs(controllers));
|
||||||
|
} else {
|
||||||
|
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textArea =
|
||||||
|
do_QueryInterface(content);
|
||||||
|
|
||||||
|
if (textArea) {
|
||||||
|
textArea->GetControllers(getter_AddRefs(controllers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!controllers) {
|
||||||
|
NS_WARNING("Could not get controllers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIController> controller;
|
||||||
|
controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
|
||||||
|
if (controller) {
|
||||||
|
controller->DoCommand(aCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRBool
|
||||||
|
DOMEventToNativeKeyEvent(nsIDOMEvent *aDOMEvent,
|
||||||
|
nsNativeKeyEvent *aNativeEvent)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNSUIEvent> nsevent = do_QueryInterface(aDOMEvent);
|
||||||
|
PRBool defaultPrevented;
|
||||||
|
nsevent->GetPreventDefault(&defaultPrevented);
|
||||||
|
if (defaultPrevented)
|
||||||
|
return PR_FALSE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aDOMEvent);
|
||||||
|
|
||||||
|
keyEvent->GetCharCode(&aNativeEvent->charCode);
|
||||||
|
keyEvent->GetKeyCode(&aNativeEvent->keyCode);
|
||||||
|
keyEvent->GetAltKey(&aNativeEvent->altKey);
|
||||||
|
keyEvent->GetCtrlKey(&aNativeEvent->ctrlKey);
|
||||||
|
keyEvent->GetShiftKey(&aNativeEvent->shiftKey);
|
||||||
|
keyEvent->GetMetaKey(&aNativeEvent->metaKey);
|
||||||
|
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTextInputListener::KeyDown(nsIDOMEvent *aKeyEvent)
|
||||||
|
{
|
||||||
|
nsNativeKeyEvent nativeEvent;
|
||||||
|
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||||
|
if (bindings && DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent)) {
|
||||||
|
if (bindings->KeyDown(nativeEvent, DoCommandCallback, mFrame)) {
|
||||||
|
aKeyEvent->PreventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTextInputListener::KeyPress(nsIDOMEvent *aKeyEvent)
|
||||||
|
{
|
||||||
|
nsNativeKeyEvent nativeEvent;
|
||||||
|
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||||
|
if (bindings && DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent)) {
|
||||||
|
if (bindings->KeyPress(nativeEvent, DoCommandCallback, mFrame)) {
|
||||||
|
aKeyEvent->PreventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTextInputListener::KeyUp(nsIDOMEvent *aKeyEvent)
|
||||||
|
{
|
||||||
|
nsNativeKeyEvent nativeEvent;
|
||||||
|
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||||
|
if (bindings && DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent)) {
|
||||||
|
if (bindings->KeyUp(nativeEvent, DoCommandCallback, mFrame)) {
|
||||||
|
aKeyEvent->PreventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// END nsIDOMKeyListener
|
||||||
|
|
||||||
// BEGIN nsIEditorObserver
|
// BEGIN nsIEditorObserver
|
||||||
|
|
||||||
|
@ -371,6 +492,36 @@ nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
|
||||||
return domWindow->UpdateCommands(commandsToUpdate);
|
return domWindow->UpdateCommands(commandsToUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsINativeKeyBindings*
|
||||||
|
nsTextInputListener::GetKeyBindings()
|
||||||
|
{
|
||||||
|
if (mFrame->IsTextArea()) {
|
||||||
|
static PRBool sNoTextAreaBindings = PR_FALSE;
|
||||||
|
|
||||||
|
if (!sNativeTextAreaBindings && !sNoTextAreaBindings) {
|
||||||
|
CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "textarea",
|
||||||
|
&sNativeTextAreaBindings);
|
||||||
|
|
||||||
|
if (!sNativeTextAreaBindings) {
|
||||||
|
sNoTextAreaBindings = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sNativeTextAreaBindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRBool sNoInputBindings = PR_FALSE;
|
||||||
|
if (!sNativeInputBindings && !sNoInputBindings) {
|
||||||
|
CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "input",
|
||||||
|
&sNativeInputBindings);
|
||||||
|
|
||||||
|
if (!sNativeInputBindings) {
|
||||||
|
sNoInputBindings = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sNativeInputBindings;
|
||||||
|
}
|
||||||
|
|
||||||
// END nsTextInputListener
|
// END nsTextInputListener
|
||||||
|
|
||||||
|
@ -1255,6 +1406,22 @@ nsTextControlFrame::PreDestroy(nsPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
erP->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
erP->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||||
|
erP->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||||
|
nsCOMPtr<nsIDOM3EventTarget> dom3Targ = do_QueryInterface(mContent);
|
||||||
|
if (dom3Targ) {
|
||||||
|
// cast because of ambiguous base
|
||||||
|
nsIDOMEventListener *listener = NS_STATIC_CAST(nsIDOMKeyListener*,
|
||||||
|
mTextListener);
|
||||||
|
|
||||||
|
dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keydown"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keyup"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mDidPreDestroy = PR_TRUE;
|
mDidPreDestroy = PR_TRUE;
|
||||||
|
@ -3005,11 +3172,10 @@ nsTextControlFrame::SetInitialChildList(nsPresContext* aPresContext,
|
||||||
scrollableFrame->SetScrollbarVisibility(PR_FALSE, PR_FALSE);
|
scrollableFrame->SetScrollbarVisibility(PR_FALSE, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//register keylistener
|
//register focus and key listeners
|
||||||
nsCOMPtr<nsIDOMEventReceiver> erP;
|
nsCOMPtr<nsIDOMEventReceiver> erP = do_QueryInterface(mContent);
|
||||||
if (NS_SUCCEEDED(mContent->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP))) && erP)
|
if (erP) {
|
||||||
{
|
// register the event listeners with the DOM event receiver
|
||||||
// register the event listeners with the DOM event reveiver
|
|
||||||
rv = erP->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
rv = erP->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register focus listener");
|
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register focus listener");
|
||||||
// XXXbryner do we need to check for a null presshell here?
|
// XXXbryner do we need to check for a null presshell here?
|
||||||
|
@ -3017,6 +3183,22 @@ nsTextControlFrame::SetInitialChildList(nsPresContext* aPresContext,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||||
|
erP->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||||
|
nsCOMPtr<nsIDOM3EventTarget> dom3Targ = do_QueryInterface(mContent);
|
||||||
|
if (dom3Targ) {
|
||||||
|
// cast because of ambiguous base
|
||||||
|
nsIDOMEventListener *listener = NS_STATIC_CAST(nsIDOMKeyListener*,
|
||||||
|
mTextListener);
|
||||||
|
|
||||||
|
dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keydown"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keypress"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keyup"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
}
|
||||||
|
|
||||||
while(first)
|
while(first)
|
||||||
{
|
{
|
||||||
nsIView *view = first->GetView();
|
nsIView *view = first->GetView();
|
||||||
|
@ -3105,3 +3287,10 @@ nsTextControlFrame::HandleEvent(nsPresContext* aPresContext,
|
||||||
return nsStackFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
return nsStackFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
nsTextControlFrame::ShutDown()
|
||||||
|
{
|
||||||
|
NS_IF_RELEASE(sNativeTextAreaBindings);
|
||||||
|
NS_IF_RELEASE(sNativeInputBindings);
|
||||||
|
}
|
||||||
|
|
|
@ -212,6 +212,9 @@ public: //for methods who access nsTextControlFrame directly
|
||||||
nsresult DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
|
nsresult DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
|
||||||
nsresult OffsetToDOMPoint(PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
|
nsresult OffsetToDOMPoint(PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
|
||||||
|
|
||||||
|
/* called to free up native keybinding services */
|
||||||
|
static NS_HIDDEN_(void) ShutDown();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -120,6 +120,10 @@
|
||||||
#include "nsIDOMText.h" //for multiline getselection
|
#include "nsIDOMText.h" //for multiline getselection
|
||||||
#include "nsNodeInfoManager.h"
|
#include "nsNodeInfoManager.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
|
#include "nsIDOMKeyListener.h"
|
||||||
|
#include "nsIDOMEventGroup.h"
|
||||||
|
#include "nsIDOM3EventTarget.h"
|
||||||
|
#include "nsINativeKeyBindings.h"
|
||||||
|
|
||||||
#ifdef IBMBIDI
|
#ifdef IBMBIDI
|
||||||
#include "nsIBidiKeyboard.h"
|
#include "nsIBidiKeyboard.h"
|
||||||
|
@ -138,8 +142,12 @@ static const PRInt32 DEFAULT_COLS = 20;
|
||||||
static const PRInt32 DEFAULT_ROWS = 1;
|
static const PRInt32 DEFAULT_ROWS = 1;
|
||||||
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;
|
static const PRInt32 DEFAULT_ROWS_TEXTAREA = 2;
|
||||||
|
|
||||||
|
static nsINativeKeyBindings *sNativeInputBindings = nsnull;
|
||||||
|
static nsINativeKeyBindings *sNativeTextAreaBindings = nsnull;
|
||||||
|
|
||||||
class nsTextInputListener : public nsISelectionListener,
|
class nsTextInputListener : public nsISelectionListener,
|
||||||
public nsIDOMFocusListener,
|
public nsIDOMFocusListener,
|
||||||
|
public nsIDOMKeyListener,
|
||||||
public nsIEditorObserver,
|
public nsIEditorObserver,
|
||||||
public nsSupportsWeakReference
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
|
@ -169,12 +177,19 @@ public:
|
||||||
NS_IMETHOD Blur (nsIDOMEvent* aEvent);
|
NS_IMETHOD Blur (nsIDOMEvent* aEvent);
|
||||||
/* END interfaces from nsIDOMFocusListener*/
|
/* END interfaces from nsIDOMFocusListener*/
|
||||||
|
|
||||||
|
// nsIDOMKeyListener
|
||||||
|
NS_IMETHOD KeyDown(nsIDOMEvent *aKeyEvent);
|
||||||
|
NS_IMETHOD KeyPress(nsIDOMEvent *aKeyEvent);
|
||||||
|
NS_IMETHOD KeyUp(nsIDOMEvent *aKeyEvent);
|
||||||
|
|
||||||
NS_DECL_NSIEDITOROBSERVER
|
NS_DECL_NSIEDITOROBSERVER
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsresult UpdateTextInputCommands(const nsAString& commandsToUpdate);
|
nsresult UpdateTextInputCommands(const nsAString& commandsToUpdate);
|
||||||
|
|
||||||
|
NS_HIDDEN_(nsINativeKeyBindings*) GetKeyBindings();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
nsTextControlFrame* mFrame; // weak reference
|
nsTextControlFrame* mFrame; // weak reference
|
||||||
|
@ -211,9 +226,18 @@ nsTextInputListener::~nsTextInputListener()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS5(nsTextInputListener, nsISelectionListener,
|
NS_IMPL_ADDREF(nsTextInputListener)
|
||||||
nsIDOMEventListener, nsIDOMFocusListener,
|
NS_IMPL_RELEASE(nsTextInputListener)
|
||||||
nsIEditorObserver, nsISupportsWeakReference)
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsTextInputListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIEditorObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFocusListener)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
// BEGIN nsIDOMSelectionListener
|
// BEGIN nsIDOMSelectionListener
|
||||||
|
|
||||||
|
@ -313,6 +337,103 @@ nsTextInputListener::Blur(nsIDOMEvent* aEvent)
|
||||||
|
|
||||||
// END nsIFocusListener
|
// END nsIFocusListener
|
||||||
|
|
||||||
|
// BEGIN nsIDOMKeyListener
|
||||||
|
|
||||||
|
static void
|
||||||
|
DoCommandCallback(const char *aCommand, void *aData)
|
||||||
|
{
|
||||||
|
nsTextControlFrame *frame = NS_STATIC_CAST(nsTextControlFrame*, aData);
|
||||||
|
nsIContent *content = frame->GetContent();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIControllers> controllers;
|
||||||
|
nsCOMPtr<nsIDOMNSHTMLInputElement> input = do_QueryInterface(content);
|
||||||
|
if (input) {
|
||||||
|
input->GetControllers(getter_AddRefs(controllers));
|
||||||
|
} else {
|
||||||
|
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textArea =
|
||||||
|
do_QueryInterface(content);
|
||||||
|
|
||||||
|
if (textArea) {
|
||||||
|
textArea->GetControllers(getter_AddRefs(controllers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!controllers) {
|
||||||
|
NS_WARNING("Could not get controllers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIController> controller;
|
||||||
|
controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
|
||||||
|
if (controller) {
|
||||||
|
controller->DoCommand(aCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRBool
|
||||||
|
DOMEventToNativeKeyEvent(nsIDOMEvent *aDOMEvent,
|
||||||
|
nsNativeKeyEvent *aNativeEvent)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNSUIEvent> nsevent = do_QueryInterface(aDOMEvent);
|
||||||
|
PRBool defaultPrevented;
|
||||||
|
nsevent->GetPreventDefault(&defaultPrevented);
|
||||||
|
if (defaultPrevented)
|
||||||
|
return PR_FALSE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aDOMEvent);
|
||||||
|
|
||||||
|
keyEvent->GetCharCode(&aNativeEvent->charCode);
|
||||||
|
keyEvent->GetKeyCode(&aNativeEvent->keyCode);
|
||||||
|
keyEvent->GetAltKey(&aNativeEvent->altKey);
|
||||||
|
keyEvent->GetCtrlKey(&aNativeEvent->ctrlKey);
|
||||||
|
keyEvent->GetShiftKey(&aNativeEvent->shiftKey);
|
||||||
|
keyEvent->GetMetaKey(&aNativeEvent->metaKey);
|
||||||
|
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTextInputListener::KeyDown(nsIDOMEvent *aKeyEvent)
|
||||||
|
{
|
||||||
|
nsNativeKeyEvent nativeEvent;
|
||||||
|
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||||
|
if (bindings && DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent)) {
|
||||||
|
if (bindings->KeyDown(nativeEvent, DoCommandCallback, mFrame)) {
|
||||||
|
aKeyEvent->PreventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTextInputListener::KeyPress(nsIDOMEvent *aKeyEvent)
|
||||||
|
{
|
||||||
|
nsNativeKeyEvent nativeEvent;
|
||||||
|
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||||
|
if (bindings && DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent)) {
|
||||||
|
if (bindings->KeyPress(nativeEvent, DoCommandCallback, mFrame)) {
|
||||||
|
aKeyEvent->PreventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsTextInputListener::KeyUp(nsIDOMEvent *aKeyEvent)
|
||||||
|
{
|
||||||
|
nsNativeKeyEvent nativeEvent;
|
||||||
|
nsINativeKeyBindings *bindings = GetKeyBindings();
|
||||||
|
if (bindings && DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent)) {
|
||||||
|
if (bindings->KeyUp(nativeEvent, DoCommandCallback, mFrame)) {
|
||||||
|
aKeyEvent->PreventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// END nsIDOMKeyListener
|
||||||
|
|
||||||
// BEGIN nsIEditorObserver
|
// BEGIN nsIEditorObserver
|
||||||
|
|
||||||
|
@ -371,6 +492,36 @@ nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
|
||||||
return domWindow->UpdateCommands(commandsToUpdate);
|
return domWindow->UpdateCommands(commandsToUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsINativeKeyBindings*
|
||||||
|
nsTextInputListener::GetKeyBindings()
|
||||||
|
{
|
||||||
|
if (mFrame->IsTextArea()) {
|
||||||
|
static PRBool sNoTextAreaBindings = PR_FALSE;
|
||||||
|
|
||||||
|
if (!sNativeTextAreaBindings && !sNoTextAreaBindings) {
|
||||||
|
CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "textarea",
|
||||||
|
&sNativeTextAreaBindings);
|
||||||
|
|
||||||
|
if (!sNativeTextAreaBindings) {
|
||||||
|
sNoTextAreaBindings = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sNativeTextAreaBindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRBool sNoInputBindings = PR_FALSE;
|
||||||
|
if (!sNativeInputBindings && !sNoInputBindings) {
|
||||||
|
CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "input",
|
||||||
|
&sNativeInputBindings);
|
||||||
|
|
||||||
|
if (!sNativeInputBindings) {
|
||||||
|
sNoInputBindings = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sNativeInputBindings;
|
||||||
|
}
|
||||||
|
|
||||||
// END nsTextInputListener
|
// END nsTextInputListener
|
||||||
|
|
||||||
|
@ -1255,6 +1406,22 @@ nsTextControlFrame::PreDestroy(nsPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
erP->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
erP->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||||
|
erP->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||||
|
nsCOMPtr<nsIDOM3EventTarget> dom3Targ = do_QueryInterface(mContent);
|
||||||
|
if (dom3Targ) {
|
||||||
|
// cast because of ambiguous base
|
||||||
|
nsIDOMEventListener *listener = NS_STATIC_CAST(nsIDOMKeyListener*,
|
||||||
|
mTextListener);
|
||||||
|
|
||||||
|
dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keydown"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keyup"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mDidPreDestroy = PR_TRUE;
|
mDidPreDestroy = PR_TRUE;
|
||||||
|
@ -3005,11 +3172,10 @@ nsTextControlFrame::SetInitialChildList(nsPresContext* aPresContext,
|
||||||
scrollableFrame->SetScrollbarVisibility(PR_FALSE, PR_FALSE);
|
scrollableFrame->SetScrollbarVisibility(PR_FALSE, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//register keylistener
|
//register focus and key listeners
|
||||||
nsCOMPtr<nsIDOMEventReceiver> erP;
|
nsCOMPtr<nsIDOMEventReceiver> erP = do_QueryInterface(mContent);
|
||||||
if (NS_SUCCEEDED(mContent->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP))) && erP)
|
if (erP) {
|
||||||
{
|
// register the event listeners with the DOM event receiver
|
||||||
// register the event listeners with the DOM event reveiver
|
|
||||||
rv = erP->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
rv = erP->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *,mTextListener), NS_GET_IID(nsIDOMFocusListener));
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register focus listener");
|
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register focus listener");
|
||||||
// XXXbryner do we need to check for a null presshell here?
|
// XXXbryner do we need to check for a null presshell here?
|
||||||
|
@ -3017,6 +3183,22 @@ nsTextControlFrame::SetInitialChildList(nsPresContext* aPresContext,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||||
|
erP->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||||
|
nsCOMPtr<nsIDOM3EventTarget> dom3Targ = do_QueryInterface(mContent);
|
||||||
|
if (dom3Targ) {
|
||||||
|
// cast because of ambiguous base
|
||||||
|
nsIDOMEventListener *listener = NS_STATIC_CAST(nsIDOMKeyListener*,
|
||||||
|
mTextListener);
|
||||||
|
|
||||||
|
dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keydown"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keypress"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keyup"),
|
||||||
|
listener, PR_FALSE, systemGroup);
|
||||||
|
}
|
||||||
|
|
||||||
while(first)
|
while(first)
|
||||||
{
|
{
|
||||||
nsIView *view = first->GetView();
|
nsIView *view = first->GetView();
|
||||||
|
@ -3105,3 +3287,10 @@ nsTextControlFrame::HandleEvent(nsPresContext* aPresContext,
|
||||||
return nsStackFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
return nsStackFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
nsTextControlFrame::ShutDown()
|
||||||
|
{
|
||||||
|
NS_IF_RELEASE(sNativeTextAreaBindings);
|
||||||
|
NS_IF_RELEASE(sNativeInputBindings);
|
||||||
|
}
|
||||||
|
|
|
@ -212,6 +212,9 @@ public: //for methods who access nsTextControlFrame directly
|
||||||
nsresult DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
|
nsresult DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
|
||||||
nsresult OffsetToDOMPoint(PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
|
nsresult OffsetToDOMPoint(PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
|
||||||
|
|
||||||
|
/* called to free up native keybinding services */
|
||||||
|
static NS_HIDDEN_(void) ShutDown();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,6 +71,7 @@ EXPORTS = \
|
||||||
nsIDragSessionOS2.h \
|
nsIDragSessionOS2.h \
|
||||||
nsIXRemoteWidgetHelper.h \
|
nsIXRemoteWidgetHelper.h \
|
||||||
nsIPluginWidget.h \
|
nsIPluginWidget.h \
|
||||||
|
nsINativeKeyBindings.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* IBM Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Brian Ryner <bryner@brianryner.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsINativeKeyBindings_h_
|
||||||
|
#define nsINativeKeyBindings_h_
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
#define NS_INATIVEKEYBINDINGS_IID \
|
||||||
|
{0x606c54e7, 0x0593, 0x4750, {0x99, 0xd9, 0x4e, 0x1b, 0xcc, 0xec, 0x98, 0xd9}}
|
||||||
|
|
||||||
|
#define NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX \
|
||||||
|
"@mozilla.org/widget/native-key-bindings;1?type="
|
||||||
|
|
||||||
|
struct nsNativeKeyEvent
|
||||||
|
{
|
||||||
|
PRUint32 keyCode;
|
||||||
|
PRUint32 charCode;
|
||||||
|
PRBool altKey;
|
||||||
|
PRBool ctrlKey;
|
||||||
|
PRBool shiftKey;
|
||||||
|
PRBool metaKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
class nsINativeKeyBindings : public nsISupports
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef void (*DoCommandCallback)(const char *, void*);
|
||||||
|
|
||||||
|
NS_DEFINE_STATIC_IID_ACCESSOR(NS_INATIVEKEYBINDINGS_IID)
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(PRBool) KeyDown(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback,
|
||||||
|
void *aCallbackData) = 0;
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(PRBool) KeyPress(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback,
|
||||||
|
void *aCallbackData) = 0;
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(PRBool) KeyUp(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback,
|
||||||
|
void *aCallbackData) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -81,6 +81,7 @@ CPPSRCS = \
|
||||||
nsDragService.cpp \
|
nsDragService.cpp \
|
||||||
nsFilePicker.cpp \
|
nsFilePicker.cpp \
|
||||||
nsSound.cpp \
|
nsSound.cpp \
|
||||||
|
nsNativeKeyBindings.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# build our subdirs, too
|
# build our subdirs, too
|
||||||
|
|
|
@ -215,6 +215,53 @@ GdkKeyCodeToDOMKeyCode(int aKeysym)
|
||||||
return((int)0);
|
return((int)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
DOMKeyCodeToGdkKeyCode(PRUint32 aKeysym)
|
||||||
|
{
|
||||||
|
int i, length = 0;
|
||||||
|
|
||||||
|
// First, try to handle alphanumeric input, not listed in nsKeycodes:
|
||||||
|
// most likely, more letters will be getting typed in than things in
|
||||||
|
// the key list, so we will look through these first.
|
||||||
|
|
||||||
|
if (aKeysym >= NS_VK_A && aKeysym <= NS_VK_Z)
|
||||||
|
// gdk and DOM both use the ASCII codes for these keys.
|
||||||
|
return aKeysym;
|
||||||
|
|
||||||
|
// numbers
|
||||||
|
if (aKeysym >= NS_VK_0 && aKeysym <= NS_VK_9)
|
||||||
|
// gdk and DOM both use the ASCII codes for these keys.
|
||||||
|
return aKeysym - GDK_0 + NS_VK_0;
|
||||||
|
|
||||||
|
// keypad numbers
|
||||||
|
if (aKeysym >= NS_VK_NUMPAD0 && aKeysym <= NS_VK_NUMPAD9)
|
||||||
|
return aKeysym - NS_VK_NUMPAD0 + GDK_KP_0;
|
||||||
|
|
||||||
|
// map Sun Keyboard special keysyms
|
||||||
|
if (IS_XSUN_XSERVER(GDK_DISPLAY())) {
|
||||||
|
length = NS_ARRAY_LENGTH(nsSunKeycodes);
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
if (nsSunKeycodes[i].vkCode == aKeysym) {
|
||||||
|
return nsSunKeycodes[i].keysym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// misc other things
|
||||||
|
length = NS_ARRAY_LENGTH(nsKeycodes);
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
if (nsKeycodes[i].vkCode == aKeysym) {
|
||||||
|
return nsKeycodes[i].keysym;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function keys
|
||||||
|
if (aKeysym >= NS_VK_F1 && aKeysym <= NS_VK_F9)
|
||||||
|
return aKeysym - NS_VK_F1 + GDK_F1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert gdk key event keyvals to char codes if printable, 0 otherwise
|
// Convert gdk key event keyvals to char codes if printable, 0 otherwise
|
||||||
PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aEvent)
|
PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aEvent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#define __nsGdkKeyUtils_h__
|
#define __nsGdkKeyUtils_h__
|
||||||
|
|
||||||
int GdkKeyCodeToDOMKeyCode (int aKeysym);
|
int GdkKeyCodeToDOMKeyCode (int aKeysym);
|
||||||
|
int DOMKeyCodeToGdkKeyCode (PRUint32 aKeysym);
|
||||||
PRUint32 nsConvertCharCodeToUnicode (GdkEventKey* aEvent);
|
PRUint32 nsConvertCharCodeToUnicode (GdkEventKey* aEvent);
|
||||||
|
|
||||||
#endif /* __nsGdkKeyUtils_h__ */
|
#endif /* __nsGdkKeyUtils_h__ */
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* IBM Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Brian Ryner <bryner@brianryner.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsNativeKeyBindings.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsMemory.h"
|
||||||
|
#include "nsGtkKeyUtils.h"
|
||||||
|
|
||||||
|
#include <gtk/gtkentry.h>
|
||||||
|
#include <gtk/gtktextview.h>
|
||||||
|
#include <gtk/gtkbindings.h>
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
|
||||||
|
static nsINativeKeyBindings::DoCommandCallback gCurrentCallback;
|
||||||
|
static void *gCurrentCallbackData;
|
||||||
|
|
||||||
|
// Common GtkEntry and GtkTextView signals
|
||||||
|
static void
|
||||||
|
copy_clipboard_cb(GtkWidget *w, gpointer user_data)
|
||||||
|
{
|
||||||
|
gCurrentCallback("cmd_copy", gCurrentCallbackData);
|
||||||
|
g_signal_stop_emission_by_name(w, "copy_clipboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cut_clipboard_cb(GtkWidget *w, gpointer user_data)
|
||||||
|
{
|
||||||
|
gCurrentCallback("cmd_cut", gCurrentCallbackData);
|
||||||
|
g_signal_stop_emission_by_name(w, "cut_clipboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
// GTK distinguishes between display lines (wrapped, as they appear on the
|
||||||
|
// screen) and paragraphs, which are runs of text terminated by a newline.
|
||||||
|
// We don't have this distinction, so we always use editor's notion of
|
||||||
|
// lines, which are newline-terminated.
|
||||||
|
|
||||||
|
static const char *const sDeleteCommands[][2] = {
|
||||||
|
// backward, forward
|
||||||
|
{ "cmd_deleteCharBackward", "cmd_deleteCharForward" }, // CHARS
|
||||||
|
{ "cmd_deleteWordBackward", "cmd_deleteWordForward" }, // WORD_ENDS
|
||||||
|
{ "cmd_deleteWordBackward", "cmd_deleteWordForward" }, // WORDS
|
||||||
|
{ "cmd_deleteToBeginningOfLine", "cmd_deleteToEndOfLine" }, // LINES
|
||||||
|
{ "cmd_deleteToBeginningOfLine", "cmd_deleteToEndOfLine" }, // LINE_ENDS
|
||||||
|
{ "cmd_deleteToBeginningOfLine", "cmd_deleteToEndOfLine" }, // PARAGRAPH_ENDS
|
||||||
|
{ "cmd_deleteToBeginningOfLine", "cmd_deleteToEndOfLine" }, // PARAGRAPHS
|
||||||
|
// This deletes from the end of the previous word to the beginning of the
|
||||||
|
// next word, but only if the caret is not in a word.
|
||||||
|
// XXX need to implement in editor
|
||||||
|
{ nsnull, nsnull } // WHITESPACE
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
delete_from_cursor_cb(GtkWidget *w, GtkDeleteType del_type,
|
||||||
|
gint count, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_signal_stop_emission_by_name(w, "delete_from_cursor");
|
||||||
|
|
||||||
|
PRBool forward = count > 0;
|
||||||
|
if (PRUint32(del_type) >= NS_ARRAY_LENGTH(sDeleteCommands)) {
|
||||||
|
// unsupported deletion type
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (del_type == GTK_DELETE_WORDS) {
|
||||||
|
// This works like word_ends, except we first move the caret to the
|
||||||
|
// beginning/end of the current word.
|
||||||
|
if (forward) {
|
||||||
|
gCurrentCallback("cmd_wordNext", gCurrentCallbackData);
|
||||||
|
gCurrentCallback("cmd_wordPrevious", gCurrentCallbackData);
|
||||||
|
} else {
|
||||||
|
gCurrentCallback("cmd_wordPrevious", gCurrentCallbackData);
|
||||||
|
gCurrentCallback("cmd_wordNext", gCurrentCallbackData);
|
||||||
|
}
|
||||||
|
} else if (del_type == GTK_DELETE_DISPLAY_LINES ||
|
||||||
|
del_type == GTK_DELETE_PARAGRAPHS) {
|
||||||
|
|
||||||
|
// This works like display_line_ends, except we first move the caret to the
|
||||||
|
// beginning/end of the current line.
|
||||||
|
if (forward) {
|
||||||
|
gCurrentCallback("cmd_beginLine", gCurrentCallbackData);
|
||||||
|
} else {
|
||||||
|
gCurrentCallback("cmd_endLine", gCurrentCallbackData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cmd = sDeleteCommands[del_type][forward];
|
||||||
|
if (!cmd)
|
||||||
|
return; // unsupported command
|
||||||
|
|
||||||
|
count = PR_ABS(count);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
gCurrentCallback(cmd, gCurrentCallbackData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *const sMoveCommands[][2][2] = {
|
||||||
|
// non-extend { backward, forward }, extend { backward, forward }
|
||||||
|
// GTK differentiates between logical position, which is prev/next,
|
||||||
|
// and visual position, which is always left/right.
|
||||||
|
// We should fix this to work the same way for RTL text input.
|
||||||
|
{ // LOGICAL_POSITIONS
|
||||||
|
{ "cmd_charPrevious", "cmd_charNext" },
|
||||||
|
{ "cmd_selectCharPrevious", "cmd_selectCharNext" }
|
||||||
|
},
|
||||||
|
{ // VISUAL_POSITIONS
|
||||||
|
{ "cmd_charPrevious", "cmd_charNext" },
|
||||||
|
{ "cmd_selectCharPrevious", "cmd_selectCharNext" }
|
||||||
|
},
|
||||||
|
{ // WORDS
|
||||||
|
{ "cmd_wordPrevious", "cmd_wordNext" },
|
||||||
|
{ "cmd_selectWordPrevious", "cmd_selectWordNext" }
|
||||||
|
},
|
||||||
|
{ // DISPLAY_LINES
|
||||||
|
{ "cmd_linePrevious", "cmd_lineNext" },
|
||||||
|
{ "cmd_selectLinePrevious", "cmd_selectLineNext" }
|
||||||
|
},
|
||||||
|
{ // DISPLAY_LINE_ENDS
|
||||||
|
{ "cmd_beginLine", "cmd_endLine" },
|
||||||
|
{ "cmd_selectBeginLine", "cmd_selectEndLine" }
|
||||||
|
},
|
||||||
|
{ // PARAGRAPHS
|
||||||
|
{ "cmd_linePrevious", "cmd_lineNext" },
|
||||||
|
{ "cmd_selectLinePrevious", "cmd_selectLineNext" }
|
||||||
|
},
|
||||||
|
{ // PARAGRAPH_ENDS
|
||||||
|
{ "cmd_beginLine", "cmd_endLine" },
|
||||||
|
{ "cmd_selectBeginLine", "cmd_selectEndLine" }
|
||||||
|
},
|
||||||
|
{ // PAGES
|
||||||
|
{ "cmd_movePageUp", "cmd_movePageDown" },
|
||||||
|
{ "cmd_selectPageUp", "cmd_selectPageDown" }
|
||||||
|
},
|
||||||
|
{ // BUFFER_ENDS
|
||||||
|
{ "cmd_moveTop", "cmd_moveBottom" },
|
||||||
|
{ "cmd_selectTop", "cmd_selectBottom" }
|
||||||
|
},
|
||||||
|
{ // HORIZONTAL_PAGES (unsupported)
|
||||||
|
{ nsnull, nsnull },
|
||||||
|
{ nsnull, nsnull }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
move_cursor_cb(GtkWidget *w, GtkMovementStep step, gint count,
|
||||||
|
gboolean extend_selection, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_signal_stop_emission_by_name(w, "move_cursor");
|
||||||
|
PRBool forward = count > 0;
|
||||||
|
if (PRUint32(step) >= NS_ARRAY_LENGTH(sMoveCommands)) {
|
||||||
|
// unsupported movement type
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cmd = sMoveCommands[step][extend_selection][forward];
|
||||||
|
if (!cmd)
|
||||||
|
return; // unsupported command
|
||||||
|
|
||||||
|
|
||||||
|
count = PR_ABS(count);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
gCurrentCallback(cmd, gCurrentCallbackData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paste_clipboard_cb(GtkWidget *w, gpointer user_data)
|
||||||
|
{
|
||||||
|
gCurrentCallback("cmd_paste", gCurrentCallbackData);
|
||||||
|
g_signal_stop_emission_by_name(w, "paste_clipboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
// GtkTextView-only signals
|
||||||
|
static void
|
||||||
|
select_all_cb(GtkWidget *w, gboolean select, gpointer user_data)
|
||||||
|
{
|
||||||
|
gCurrentCallback("cmd_selectAll", gCurrentCallbackData);
|
||||||
|
g_signal_stop_emission_by_name(w, "select_all");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsNativeKeyBindings::Init(NativeKeyBindingsType aType)
|
||||||
|
{
|
||||||
|
switch (aType) {
|
||||||
|
case eKeyBindings_Input:
|
||||||
|
mNativeTarget = gtk_entry_new();
|
||||||
|
break;
|
||||||
|
case eKeyBindings_TextArea:
|
||||||
|
mNativeTarget = gtk_text_view_new();
|
||||||
|
g_signal_connect(G_OBJECT(mNativeTarget), "select_all",
|
||||||
|
G_CALLBACK(select_all_cb), this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect(G_OBJECT(mNativeTarget), "copy_clipboard",
|
||||||
|
G_CALLBACK(copy_clipboard_cb), this);
|
||||||
|
g_signal_connect(G_OBJECT(mNativeTarget), "cut_clipboard",
|
||||||
|
G_CALLBACK(cut_clipboard_cb), this);
|
||||||
|
g_signal_connect(G_OBJECT(mNativeTarget), "delete_from_cursor",
|
||||||
|
G_CALLBACK(delete_from_cursor_cb), this);
|
||||||
|
g_signal_connect(G_OBJECT(mNativeTarget), "move_cursor",
|
||||||
|
G_CALLBACK(move_cursor_cb), this);
|
||||||
|
g_signal_connect(G_OBJECT(mNativeTarget), "paste_clipboard",
|
||||||
|
G_CALLBACK(paste_clipboard_cb), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsNativeKeyBindings::~nsNativeKeyBindings()
|
||||||
|
{
|
||||||
|
gtk_widget_destroy(mNativeTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(nsNativeKeyBindings, nsINativeKeyBindings)
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsNativeKeyBindings::KeyDown(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback, void *aCallbackData)
|
||||||
|
{
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsNativeKeyBindings::KeyPress(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback, void *aCallbackData)
|
||||||
|
{
|
||||||
|
PRUint32 keyCode;
|
||||||
|
|
||||||
|
if (aEvent.charCode != 0)
|
||||||
|
keyCode = gdk_unicode_to_keyval(aEvent.charCode);
|
||||||
|
else
|
||||||
|
keyCode = DOMKeyCodeToGdkKeyCode(aEvent.keyCode);
|
||||||
|
|
||||||
|
int modifiers = 0;
|
||||||
|
if (aEvent.altKey)
|
||||||
|
modifiers |= GDK_MOD1_MASK;
|
||||||
|
if (aEvent.ctrlKey)
|
||||||
|
modifiers |= GDK_CONTROL_MASK;
|
||||||
|
if (aEvent.shiftKey)
|
||||||
|
modifiers |= GDK_SHIFT_MASK;
|
||||||
|
// we don't support meta
|
||||||
|
|
||||||
|
gCurrentCallback = aCallback;
|
||||||
|
gCurrentCallbackData = aCallbackData;
|
||||||
|
|
||||||
|
PRBool handled = PR_FALSE;
|
||||||
|
|
||||||
|
if (gtk_bindings_activate(GTK_OBJECT(mNativeTarget),
|
||||||
|
keyCode, GdkModifierType(modifiers))) {
|
||||||
|
handled = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gCurrentCallback = nsnull;
|
||||||
|
gCurrentCallbackData = nsnull;
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsNativeKeyBindings::KeyUp(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback, void *aCallbackData)
|
||||||
|
{
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* IBM Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Brian Ryner <bryner@brianryner.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsNativeKeyBindings_h_
|
||||||
|
#define nsNativeKeyBindings_h_
|
||||||
|
|
||||||
|
// X.h defines KeyPress
|
||||||
|
#ifdef KeyPress
|
||||||
|
#undef KeyPress
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "nsINativeKeyBindings.h"
|
||||||
|
#include <gtk/gtkwidget.h>
|
||||||
|
|
||||||
|
enum NativeKeyBindingsType {
|
||||||
|
eKeyBindings_Input,
|
||||||
|
eKeyBindings_TextArea
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NS_NATIVEKEYBINDINGSINPUT_CID \
|
||||||
|
{0x5c337258, 0xa580, 0x472e, {0x86, 0x15, 0xf2, 0x77, 0xdd, 0xc5, 0xbb, 0x06}}
|
||||||
|
|
||||||
|
#define NS_NATIVEKEYBINDINGSINPUT_CONTRACTID \
|
||||||
|
NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "input"
|
||||||
|
|
||||||
|
#define NS_NATIVEKEYBINDINGSTEXTAREA_CID \
|
||||||
|
{0x2a898043, 0x180f, 0x4c8b, {0x8e, 0x54, 0x41, 0x0c, 0x7a, 0x54, 0x0f, 0x27}}
|
||||||
|
|
||||||
|
#define NS_NATIVEKEYBINDINGSTEXTAREA_CONTRACTID \
|
||||||
|
NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "textarea"
|
||||||
|
|
||||||
|
class nsNativeKeyBindings : public nsINativeKeyBindings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_HIDDEN_(void) Init(NativeKeyBindingsType aType);
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
// nsINativeKeyBindings
|
||||||
|
virtual NS_HIDDEN_(PRBool) KeyDown(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback,
|
||||||
|
void *aCallbackData);
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(PRBool) KeyPress(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback,
|
||||||
|
void *aCallbackData);
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(PRBool) KeyUp(const nsNativeKeyEvent& aEvent,
|
||||||
|
DoCommandCallback aCallback,
|
||||||
|
void *aCallbackData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
~nsNativeKeyBindings() NS_HIDDEN;
|
||||||
|
|
||||||
|
GtkWidget *mNativeTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -51,6 +51,7 @@
|
||||||
#include "nsFilePicker.h"
|
#include "nsFilePicker.h"
|
||||||
#include "nsSound.h"
|
#include "nsSound.h"
|
||||||
#include "nsBidiKeyboard.h"
|
#include "nsBidiKeyboard.h"
|
||||||
|
#include "nsNativeKeyBindings.h"
|
||||||
|
|
||||||
#include "nsIComponentRegistrar.h"
|
#include "nsIComponentRegistrar.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
|
@ -147,6 +148,49 @@ nsFilePickerUnregisterSelf(nsIComponentManager *aCompMgr,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NS_IMETHODIMP
|
||||||
|
nsNativeKeyBindingsConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||||
|
void **aResult,
|
||||||
|
NativeKeyBindingsType aKeyBindingsType)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
nsNativeKeyBindings *inst;
|
||||||
|
|
||||||
|
*aResult = NULL;
|
||||||
|
if (NULL != aOuter) {
|
||||||
|
rv = NS_ERROR_NO_AGGREGATION;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_NEWXPCOM(inst, nsNativeKeyBindings);
|
||||||
|
if (NULL == inst) {
|
||||||
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
NS_ADDREF(inst);
|
||||||
|
inst->Init(aKeyBindingsType);
|
||||||
|
rv = inst->QueryInterface(aIID, aResult);
|
||||||
|
NS_RELEASE(inst);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NS_IMETHODIMP
|
||||||
|
nsNativeKeyBindingsInputConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||||
|
void **aResult)
|
||||||
|
{
|
||||||
|
return nsNativeKeyBindingsConstructor(aOuter, aIID, aResult,
|
||||||
|
eKeyBindings_Input);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NS_IMETHODIMP
|
||||||
|
nsNativeKeyBindingsTextAreaConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||||
|
void **aResult)
|
||||||
|
{
|
||||||
|
return nsNativeKeyBindingsConstructor(aOuter, aIID, aResult,
|
||||||
|
eKeyBindings_TextArea);
|
||||||
|
}
|
||||||
|
|
||||||
static const nsModuleComponentInfo components[] =
|
static const nsModuleComponentInfo components[] =
|
||||||
{
|
{
|
||||||
|
@ -204,6 +248,14 @@ static const nsModuleComponentInfo components[] =
|
||||||
NS_BIDIKEYBOARD_CID,
|
NS_BIDIKEYBOARD_CID,
|
||||||
"@mozilla.org/widget/bidikeyboard;1",
|
"@mozilla.org/widget/bidikeyboard;1",
|
||||||
nsBidiKeyboardConstructor },
|
nsBidiKeyboardConstructor },
|
||||||
|
{ "Input Native Keybindings",
|
||||||
|
NS_NATIVEKEYBINDINGSINPUT_CID,
|
||||||
|
NS_NATIVEKEYBINDINGSINPUT_CONTRACTID,
|
||||||
|
nsNativeKeyBindingsInputConstructor },
|
||||||
|
{ "TextArea Native Keybindings",
|
||||||
|
NS_NATIVEKEYBINDINGSTEXTAREA_CID,
|
||||||
|
NS_NATIVEKEYBINDINGSTEXTAREA_CONTRACTID,
|
||||||
|
nsNativeKeyBindingsTextAreaConstructor }
|
||||||
};
|
};
|
||||||
|
|
||||||
PR_STATIC_CALLBACK(void)
|
PR_STATIC_CALLBACK(void)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче