~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit2/WebProcess/WebCoreSupport/gtk/WebEditorClientGtk.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2011 Igalia S.L.
 
3
 *
 
4
 *  This library is free software; you can redistribute it and/or
 
5
 *  modify it under the terms of the GNU Lesser General Public License
 
6
 *  as published by the Free Software Foundation; either version 2 of
 
7
 *  the License, or (at your option) any later version.
 
8
 *
 
9
 *  This library is distributed in the hope that it will be useful,
 
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 *  Lesser General Public License for more details.
 
13
 *
 
14
 *  You should have received a copy of the GNU Lesser General Public
 
15
 *  License along with this library; if not, write to the Free
 
16
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
17
 *  Boston, MA 02110-1301 USA
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
#include "WebEditorClient.h"
 
22
 
 
23
#include "Frame.h"
 
24
#include "FrameDestructionObserver.h"
 
25
#include "PlatformKeyboardEvent.h"
 
26
#include "WebPage.h"
 
27
#include "WebPageProxyMessages.h"
 
28
#include "WebProcess.h"
 
29
#include <WebCore/DataObjectGtk.h>
 
30
#include <WebCore/KeyboardEvent.h>
 
31
#include <WebCore/PasteboardHelper.h>
 
32
#include <WebCore/NotImplemented.h>
 
33
 
 
34
using namespace WebCore;
 
35
 
 
36
namespace WebKit {
 
37
 
 
38
void WebEditorClient::getEditorCommandsForKeyEvent(const KeyboardEvent* event, Vector<WTF::String>& pendingEditorCommands)
 
39
{
 
40
    ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
 
41
 
 
42
    /* First try to interpret the command in the UI and get the commands.
 
43
       UI needs to receive event type because only knows current NativeWebKeyboardEvent.*/
 
44
    WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::GetEditorCommandsForKeyEvent(event->type()),
 
45
                                                Messages::WebPageProxy::GetEditorCommandsForKeyEvent::Reply(pendingEditorCommands),
 
46
                                                m_page->pageID(), CoreIPC::Connection::NoTimeout);
 
47
}
 
48
 
 
49
bool WebEditorClient::executePendingEditorCommands(Frame* frame, Vector<WTF::String> pendingEditorCommands, bool allowTextInsertion)
 
50
{
 
51
    Vector<Editor::Command> commands;
 
52
    for (size_t i = 0; i < pendingEditorCommands.size(); i++) {
 
53
        Editor::Command command = frame->editor()->command(pendingEditorCommands.at(i).utf8().data());
 
54
        if (command.isTextInsertion() && !allowTextInsertion)
 
55
            return false;
 
56
 
 
57
        commands.append(command);
 
58
    }
 
59
 
 
60
    for (size_t i = 0; i < commands.size(); i++) {
 
61
        if (!commands.at(i).execute())
 
62
            return false;
 
63
    }
 
64
 
 
65
    return true;
 
66
}
 
67
 
 
68
void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
 
69
{
 
70
    Node* node = event->target()->toNode();
 
71
    ASSERT(node);
 
72
    Frame* frame = node->document()->frame();
 
73
    ASSERT(frame);
 
74
 
 
75
    const PlatformKeyboardEvent* platformEvent = event->keyEvent();
 
76
    if (!platformEvent)
 
77
        return;
 
78
 
 
79
    Vector<WTF::String> pendingEditorCommands;
 
80
    getEditorCommandsForKeyEvent(event, pendingEditorCommands);
 
81
    if (!pendingEditorCommands.isEmpty()) {
 
82
 
 
83
        // During RawKeyDown events if an editor command will insert text, defer
 
84
        // the insertion until the keypress event. We want keydown to bubble up
 
85
        // through the DOM first.
 
86
        if (platformEvent->type() == PlatformEvent::RawKeyDown) {
 
87
            if (executePendingEditorCommands(frame, pendingEditorCommands, false))
 
88
                event->setDefaultHandled();
 
89
 
 
90
            return;
 
91
        }
 
92
 
 
93
        // Only allow text insertion commands if the current node is editable.
 
94
        if (executePendingEditorCommands(frame, pendingEditorCommands, frame->editor()->canEdit())) {
 
95
            event->setDefaultHandled();
 
96
            return;
 
97
        }
 
98
    }
 
99
 
 
100
    // Don't allow text insertion for nodes that cannot edit.
 
101
    if (!frame->editor()->canEdit())
 
102
        return;
 
103
 
 
104
    // This is just a normal text insertion, so wait to execute the insertion
 
105
    // until a keypress event happens. This will ensure that the insertion will not
 
106
    // be reflected in the contents of the field until the keyup DOM event.
 
107
    if (event->type() == eventNames().keypressEvent) {
 
108
 
 
109
        // FIXME: Add IM support
 
110
        // https://bugs.webkit.org/show_bug.cgi?id=55946
 
111
        frame->editor()->insertText(platformEvent->text(), event);
 
112
        event->setDefaultHandled();
 
113
 
 
114
    } else {
 
115
        // Don't insert null or control characters as they can result in unexpected behaviour
 
116
        if (event->charCode() < ' ')
 
117
            return;
 
118
 
 
119
        // Don't insert anything if a modifier is pressed
 
120
        if (platformEvent->ctrlKey() || platformEvent->altKey())
 
121
            return;
 
122
 
 
123
        if (frame->editor()->insertText(platformEvent->text(), event))
 
124
            event->setDefaultHandled();
 
125
    }
 
126
}
 
127
 
 
128
void WebEditorClient::handleInputMethodKeydown(KeyboardEvent*)
 
129
{
 
130
    notImplemented();
 
131
}
 
132
 
 
133
#if PLATFORM(X11)
 
134
class EditorClientFrameDestructionObserver : FrameDestructionObserver {
 
135
public:
 
136
    EditorClientFrameDestructionObserver(Frame* frame, GClosure* closure)
 
137
        : FrameDestructionObserver(frame)
 
138
        , m_closure(closure)
 
139
    {
 
140
        g_closure_add_finalize_notifier(m_closure, this, destroyOnClosureFinalization);
 
141
    }
 
142
 
 
143
    void frameDestroyed()
 
144
    {
 
145
        g_closure_invalidate(m_closure);
 
146
        FrameDestructionObserver::frameDestroyed();
 
147
    }
 
148
private:
 
149
    GClosure* m_closure;
 
150
 
 
151
    static void destroyOnClosureFinalization(gpointer data, GClosure* closure)
 
152
    {
 
153
        // Calling delete void* will free the memory but won't invoke
 
154
        // the destructor, something that is a must for us.
 
155
        EditorClientFrameDestructionObserver* observer = static_cast<EditorClientFrameDestructionObserver*>(data);
 
156
        delete observer;
 
157
    }
 
158
};
 
159
 
 
160
static Frame* frameSettingClipboard;
 
161
 
 
162
static void collapseSelection(GtkClipboard* clipboard, Frame* frame)
 
163
{
 
164
    if (frameSettingClipboard && frameSettingClipboard == frame)
 
165
        return;
 
166
 
 
167
    // Collapse the selection without clearing it.
 
168
    ASSERT(frame);
 
169
    frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity());
 
170
}
 
171
#endif
 
172
 
 
173
void WebEditorClient::updateGlobalSelection(Frame* frame)
 
174
{
 
175
#if PLATFORM(X11)
 
176
    GtkClipboard* clipboard = PasteboardHelper::defaultPasteboardHelper()->getPrimarySelectionClipboard(frame);
 
177
    DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard);
 
178
 
 
179
    if (!frame->selection()->isRange())
 
180
        return;
 
181
 
 
182
    dataObject->clearAll();
 
183
    dataObject->setRange(frame->selection()->toNormalizedRange());
 
184
 
 
185
    frameSettingClipboard = frame;
 
186
    GClosure* callback = g_cclosure_new(G_CALLBACK(collapseSelection), frame, 0);
 
187
    // This observer will be self-destroyed on closure finalization,
 
188
    // that will happen either after closure execution or after
 
189
    // closure invalidation.
 
190
    new EditorClientFrameDestructionObserver(frame, callback);
 
191
    g_closure_set_marshal(callback, g_cclosure_marshal_VOID__VOID);
 
192
    PasteboardHelper::defaultPasteboardHelper()->writeClipboardContents(clipboard, PasteboardHelper::DoNotIncludeSmartPaste, callback);
 
193
    frameSettingClipboard = 0;
 
194
#endif
 
195
}
 
196
 
 
197
bool WebEditorClient::shouldShowUnicodeMenu()
 
198
{
 
199
    return true;
 
200
}
 
201
 
 
202
}