git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16626 268f45cc-cd09-0410...
authoraliceli1 <aliceli1@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Sep 2006 21:39:47 +0000 (21:39 +0000)
committeraliceli1 <aliceli1@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Sep 2006 21:39:47 +0000 (21:39 +0000)
WebCore/ChangeLog
WebCore/editing/CommandByName.cpp [new file with mode: 0644]
WebCore/editing/CommandByName.h [new file with mode: 0644]
WebCore/page/Frame.cpp
WebCore/page/Frame.h
WebCore/page/FramePrivate.h
WebCore/platform/PlatformMouseEvent.h
WebCore/platform/StringImpl.cpp
WebCore/platform/StringImpl.h
WebCore/platform/win/MouseEventWin.cpp

index cb2772383099f94e436d9f7b2dec18725fa89fc4..723faaeaf0479e298568ead7bb5a6bc4bec75b6c 100644 (file)
@@ -1,3 +1,58 @@
+2006-09-28  Alice Liu  <alice.liu@apple.com>
+
+        Reviewed by Adam Roben.
+
+        This patch adds a command class that is attached to the frame so the frame can more easily execute commands such as copy, paste, select, etc. 
+        This patch also exposes some UBRK-related utilities so that they can be used elsewhere.
+        This patch also changes windows PlatformMouseEvent so that we can detect multiple-click mouse events
+
+        * editing/CommandByName.cpp: Added.
+        Added a command class that hangs off the frame so the frame can call commands more easily.  
+        (WebCore::Frame::commandImp):
+        (WebCore::Frame::execCopy):
+        (WebCore::Frame::execCut):
+        (WebCore::Frame::execDelete):
+        (WebCore::Frame::execForwardDelete):
+        (WebCore::Frame::execPaste):
+        (WebCore::Frame::execMoveLeft):
+        (WebCore::Frame::execMoveRight):
+        (WebCore::Frame::execMoveUp):
+        (WebCore::Frame::execMoveDown):
+        (WebCore::Frame::execSelectAll):
+        (WebCore::Frame::execSelectLeft):
+        (WebCore::Frame::execSelectRight):
+        (WebCore::Frame::execSelectUp):
+        (WebCore::Frame::execSelectDown):
+        (WebCore::Frame::enabled):
+        (WebCore::Frame::enabledAnySelection):
+        (WebCore::Frame::enabledAnyEditableSelection):
+        (WebCore::Frame::enabledPaste):
+        (WebCore::Frame::enabledAnyRangeSelection):
+        (WebCore::Frame::enabledAnyEditableRangeSelection):
+        (WebCore::Frame::createCommandDictionary):
+        (WebCore::Frame::Command::):
+        (WebCore:::m_frame):
+        (WebCore::CommandByName::execCommand):
+        * editing/CommandByName.h: Added.
+        * page/Frame.cpp:
+        Added implementation of accessor for CommandByName member
+        (WebCore::Frame::command):
+        * page/Frame.h:
+        Added accessor for CommandByName member
+        * page/FramePrivate.h:
+        Added a CommandByName member
+        (WebCore::FramePrivate::FramePrivate):
+        * platform/PlatformMouseEvent.h:
+        Changed constructor prototype
+        * platform/StringImpl.cpp:
+        Exposing getWordBreakIterator to be used elsewhere
+        (WebCore::getWordBreakIterator):
+        * platform/StringImpl.h:
+        Exposing getWordBreakIterator to be used elsewhere
+        * platform/win/MouseEventWin.cpp:
+        Changed the PlatformMouseEvent on windows so that we "roll our own" multi-click mouse events instead of relying on the system to tell us, enabling us to detect triple-clicks
+        (WebCore::PlatformMouseEvent::PlatformMouseEvent):
+
 2006-09-28  Adam Roben  <aroben@apple.com>
 
         Reviewed by Adele.
diff --git a/WebCore/editing/CommandByName.cpp b/WebCore/editing/CommandByName.cpp
new file mode 100644 (file)
index 0000000..4496d3c
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+#include "config.h"
+#include "CommandByName.h"
+
+#include <wtf/HashMap.h>
+#include "Document.h"
+#include "Frame.h"
+#include "PlatformString.h"
+#include "SelectionController.h"
+#include "StringHash.h"
+#include "TypingCommand.h"
+
+namespace WebCore {
+
+class Frame;
+
+namespace {
+//FIXME: there's a setter for this. Bring it in later when we need it
+bool supportsPasteCommand = false;
+
+struct CommandImp {
+    bool (*execFn)(Frame* frame);
+    bool (*enabledFn)(Frame* frame);
+};
+
+typedef HashMap<StringImpl*, const CommandImp*, CaseInsensitiveHash> CommandMap;
+
+CommandMap* createCommandDictionary();
+
+const CommandImp* commandImp(const String& command)
+{
+    static CommandMap* commandDictionary = createCommandDictionary();
+    return commandDictionary->get(command.impl());
+}
+
+// ============================================================================
+// 
+// execCommand function implementations
+// 
+
+bool execCopy(Frame* frame)
+{
+    frame->copyToPasteboard();
+    return true;
+}
+
+bool execCut(Frame* frame)
+{
+    frame->cutToPasteboard();
+    return true;
+}
+
+bool execDelete(Frame* frame)
+{
+    TypingCommand::deleteKeyPressed(frame->document(), frame->selectionGranularity() == WordGranularity);
+    return true;
+}
+
+bool execForwardDelete(Frame* frame)
+{
+    TypingCommand::forwardDeleteKeyPressed(frame->document());
+    return true;
+}
+
+bool execPaste(Frame* frame)
+{
+    frame->pasteFromPasteboard();
+    return true;
+}
+
+bool execMoveLeft(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::MOVE, SelectionController::LEFT, CharacterGranularity, true);
+    return true;
+}
+
+bool execMoveRight(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::MOVE, SelectionController::RIGHT, CharacterGranularity, true);
+    return true;
+}
+
+bool execMoveUp(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, LineGranularity, true);
+    return true;
+}
+
+bool execMoveDown(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, LineGranularity, true);
+    return true;
+}
+
+bool execSelectAll(Frame* frame)
+{
+    frame->selectAll();
+    return true;
+}
+
+bool execSelectLeft(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::LEFT, CharacterGranularity, true);
+    return true;
+}
+
+bool execSelectRight(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::RIGHT, CharacterGranularity, true);
+    return true;
+}
+
+bool execSelectUp(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::BACKWARD, LineGranularity, true);
+    return true;
+}
+
+bool execSelectDown(Frame* frame)
+{
+    frame->selectionController()->modify(SelectionController::EXTEND, SelectionController::FORWARD, LineGranularity, true);
+    return true;
+}
+
+// ============================================================================
+// 
+// enabled functions implementations
+// 
+
+bool enabled(Frame*)
+{
+    return true;
+}
+
+bool enabledAnySelection(Frame* frame)
+{
+    return frame->selectionController()->isCaretOrRange();
+}
+
+bool enabledAnyEditableSelection(Frame* frame)
+{
+    return frame->selectionController()->isCaretOrRange() && frame->selectionController()->isContentEditable();
+}
+
+bool enabledPaste(Frame* frame)
+{
+    return supportsPasteCommand && frame->canPaste();
+}
+
+bool enabledAnyRangeSelection(Frame* frame)
+{
+    return frame->selectionController()->isRange();
+}
+
+bool enabledAnyEditableRangeSelection(Frame* frame)
+{
+    return frame->selectionController()->isRange() && frame->selectionController()->isContentEditable();
+}
+
+CommandMap* createCommandDictionary()
+{
+    struct Command { const char* name; CommandImp imp; };
+
+    static const Command commands[] = {
+        { "Copy", { execCopy, enabledAnyRangeSelection } },
+        { "Cut", { execCut, enabledAnyEditableRangeSelection } },
+        { "Delete", { execDelete, enabledAnyEditableSelection } },
+        { "ForwardDelete", { execForwardDelete, enabledAnyEditableSelection } },
+        { "Paste", { execPaste, enabledPaste } },
+        { "SelectAll", { execSelectAll, enabled } },
+        // FIXME: not sure if the following 8 should be enabledAnyRangeSelection or enabledAnySelection
+        { "MoveLeft", { execMoveLeft, enabledAnyRangeSelection } },
+        { "MoveRight", { execMoveRight, enabledAnyRangeSelection } },
+        { "MoveUp", { execMoveUp, enabledAnyRangeSelection } },
+        { "MoveDown", { execMoveDown, enabledAnyRangeSelection } },
+        { "SelectLeft", { execSelectLeft, enabledAnyRangeSelection } },
+        { "SelectRight", { execSelectRight, enabledAnyRangeSelection } },
+        { "SelectUp", { execSelectUp, enabledAnyRangeSelection } },
+        { "SelectDown", { execSelectDown, enabledAnyRangeSelection } }
+    };
+
+    CommandMap* commandMap = new CommandMap;
+
+    const int numCommands = sizeof(commands) / sizeof(commands[0]);
+    for (int i = 0; i < numCommands; ++i) {
+        StringImpl *name = new StringImpl(commands[i].name);
+        name->ref();
+        commandMap->set(name, &commands[i].imp);
+    }
+
+    return commandMap;
+}
+
+} // anonymous namespace
+
+CommandByName::CommandByName(Frame* frame)
+    : m_frame(frame)
+{
+}
+
+const bool CommandByName::execCommand(const String& command)
+{
+    bool handled = false;
+    const CommandImp* cmd = commandImp(command);
+    if (!cmd)
+        return false;
+    if (!m_frame)
+        return false;
+    if (cmd->enabledFn(m_frame)) {
+        m_frame->document()->updateLayoutIgnorePendingStylesheets();
+        handled = cmd->execFn(m_frame);
+    }
+    return handled;
+}
+
+} // namespace WebCore
diff --git a/WebCore/editing/CommandByName.h b/WebCore/editing/CommandByName.h
new file mode 100644 (file)
index 0000000..d223b23
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef command_by_name_h__
+#define command_by_name_h__
+
+namespace WebCore {
+
+class Frame;
+class String;
+
+class CommandByName {
+public: 
+    CommandByName(Frame* frame);
+    const bool execCommand(const String& command);
+    
+private:
+    Frame* m_frame;
+};
+
+} // namespace WebCore
+
+#endif // command_by_name_h__
index 16273d24ef44586a3cf6e4f6e42198cce3abed6c..1dc7f08cd7311ae1156844386a3f48b3a2ff2342 100644 (file)
@@ -1233,6 +1233,11 @@ SelectionController* Frame::selectionController() const
     return &(d->m_selectionController);
 }
 
+CommandByName* Frame::command() const
+{
+    return &(d->m_command);
+}
+
 TextGranularity Frame::selectionGranularity() const
 {
     return d->m_selectionGranularity;
index 6507021b90d628b7a5e8332a168dc81b7d3b472b..5f39b520424c4a8333df7df11815606b5284d97b 100644 (file)
@@ -55,6 +55,7 @@ namespace KJS {
 
 namespace WebCore {
 
+class CommandByName;
 class CSSComputedStyleDeclaration;
 class CSSMutableStyleDeclaration;
 class CSSStyleDeclaration;
@@ -821,6 +822,7 @@ public:
   SelectionController* dragCaretController() const;
   DOMWindow* domWindow() const;
 
+  CommandByName* command() const;
  private:
   friend class FramePrivate;
   FramePrivate* d;
index 0b74c50d91d1d529db9ff3b342edfaf9be861611..219fd2b215c9f47c10c67e1eb1c500483511bdaa 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "CSSMutableStyleDeclaration.h"
 #include "CachePolicy.h"
+#include "CommandByName.h"
 #include "DOMWindow.h"
 #include "Decoder.h"
 #include "EditCommand.h"
@@ -85,6 +86,7 @@ namespace WebCore {
             , m_bMousePressed(false)
             , m_selectionController(thisFrame)
             , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
+            , m_command(thisFrame)
             , m_caretVisible(false)
             , m_caretBlinks(true)
             , m_caretPaint(true)
@@ -193,6 +195,8 @@ namespace WebCore {
         Selection m_mark;
         Timer<Frame> m_caretBlinkTimer;
 
+        CommandByName m_command;
+
         bool m_caretVisible : 1;
         bool m_caretBlinks : 1;
         bool m_caretPaint : 1;
index bb9ff50e43f4808fbce3a823201343003f38ee28..ca249736976635c24952a3d604edbea241c040bc 100644 (file)
@@ -99,7 +99,7 @@ namespace WebCore {
         PlatformMouseEvent(NSEvent*);
 #endif
 #if PLATFORM(WIN)
-        PlatformMouseEvent(HWND, WPARAM, LPARAM, int clickCount);
+        PlatformMouseEvent(HWND, WPARAM, LPARAM);
 #endif
 #if PLATFORM(GDK) 
         PlatformMouseEvent(GdkEvent*);
index 7a954dcce0a824196aa100fb97a34905eb0d3c3c..70f43d4594b59cfcfedd1585ebd6ed0e52632a0f 100644 (file)
@@ -547,7 +547,8 @@ StringImpl* StringImpl::simplifyWhiteSpace() const
     return c;
 }
 
-static UBreakIterator* getWordBreakIterator(const UChar* string, int length)
+// FIXME: this implementation should move to its own file now that StringImpl is not the only class that uses it
+UBreakIterator* getWordBreakIterator(const UChar* string, int length)
 {
     // The locale is currently ignored when determining character cluster breaks.
     // This may change in the future, according to Deborah Goldsmith.
index 4e86d8d6824cc13485ac9eb7f312dfe6f8bfaea7..354d6859f1204f9fea20e0fdb050744a731f8ff8 100644 (file)
@@ -32,6 +32,8 @@
 #include <wtf/Vector.h>
 #include <limits.h>
 
+typedef void UBreakIterator;
+
 #if PLATFORM(CF)
 typedef const struct __CFString * CFStringRef;
 #endif
@@ -158,6 +160,8 @@ bool equalIgnoringCase(const StringImpl*, const StringImpl*);
 bool equalIgnoringCase(const StringImpl*, const char*);
 inline bool equalIgnoringCase(const char* a, const StringImpl* b) { return equalIgnoringCase(b, a); }
 
+UBreakIterator* getWordBreakIterator(const UChar* string, int length);
+
 }
 
 namespace WTF {
index 92454290aff6b4869d35c08f9b610f1ac77f90ce..dd521bd1f0039ce8d7dabf20b486cbe29b3a870f 100644 (file)
@@ -33,6 +33,10 @@ const PlatformMouseEvent::CurrentEventTag PlatformMouseEvent::currentEvent = {};
 
 #define HIGH_BIT_MASK_SHORT 0x8000
 
+static int globalClickCount = 0;
+static DWORD globalPrevClickTime = 0;
+static IntPoint globalPrevClickPosition = IntPoint();
+
 static IntPoint positionForEvent(HWND hWnd, LPARAM lParam)
 {
     POINT point = {LOWORD(lParam), HIWORD(lParam)};
@@ -46,10 +50,10 @@ static IntPoint globalPositionForEvent(HWND hWnd, LPARAM lParam)
     return point;
 }
 
-PlatformMouseEvent::PlatformMouseEvent(HWND hWnd, WPARAM wParam, LPARAM lParam, int clkCount)
+PlatformMouseEvent::PlatformMouseEvent(HWND hWnd, WPARAM wParam, LPARAM lParam)
     : m_position(positionForEvent(hWnd, lParam))
     , m_globalPosition(globalPositionForEvent(hWnd, lParam))
-    , m_clickCount(clkCount)
+    , m_clickCount(0)
     , m_shiftKey(wParam & MK_SHIFT)
     , m_ctrlKey(wParam & MK_CONTROL)
     , m_altKey(GetAsyncKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT)
@@ -61,6 +65,19 @@ PlatformMouseEvent::PlatformMouseEvent(HWND hWnd, WPARAM wParam, LPARAM lParam,
         m_button = RightButton;
     else if (wParam & MK_MBUTTON)
         m_button = MiddleButton;
-}
 
+    if (m_button == LeftButton) {
+        DWORD curTime = GetTickCount();
+        if (curTime - globalPrevClickTime > GetDoubleClickTime() 
+            || globalPrevClickPosition != m_position)
+            globalClickCount = 1;
+        else 
+            globalClickCount++;
+
+        globalPrevClickTime = curTime;
+        globalPrevClickPosition = m_position;
+        m_clickCount = globalClickCount;
+    }
 }
+
+} // namespace WebCore