diff ext/guichan-0.8.2/src/gui.cpp @ 378:64738befdf3b

bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 11 Jan 2010 23:34:52 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ext/guichan-0.8.2/src/gui.cpp	Mon Jan 11 23:34:52 2010 +0000
@@ -0,0 +1,995 @@
+/*      _______   __   __   __   ______   __   __   _______   __   __
+ *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
+ *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
+ *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
+ *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
+ * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
+ * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
+ *
+ * Copyright (c) 2004 - 2008 Olof Naessén and Per Larsson
+ *
+ *
+ * Per Larsson a.k.a finalman
+ * Olof Naessén a.k.a jansem/yakslem
+ *
+ * Visit: http://guichan.sourceforge.net
+ *
+ * License: (BSD)
+ * 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.
+ * 3. Neither the name of Guichan nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+/*
+ * For comments regarding functions please see the header file.
+ */
+
+#include "guichan/gui.hpp"
+
+#include "guichan/basiccontainer.hpp"
+#include "guichan/exception.hpp"
+#include "guichan/focushandler.hpp"
+#include "guichan/graphics.hpp"
+#include "guichan/input.hpp"
+#include "guichan/keyinput.hpp"
+#include "guichan/keylistener.hpp"
+#include "guichan/mouseinput.hpp"
+#include "guichan/mouselistener.hpp"
+#include "guichan/widget.hpp"
+
+namespace gcn
+{
+    Gui::Gui()
+            :mTop(NULL),
+             mGraphics(NULL),
+             mInput(NULL),
+             mTabbing(true),
+             mShiftPressed(false),
+             mMetaPressed(false),
+             mControlPressed(false),
+             mAltPressed(false),
+             mLastMousePressButton(0),
+             mLastMousePressTimeStamp(0),
+             mLastMouseX(0),
+             mLastMouseY(0),
+             mClickCount(1),
+             mLastMouseDragButton(0)
+    {
+        mFocusHandler = new FocusHandler();
+    }
+
+    Gui::~Gui()
+    {
+        if (Widget::widgetExists(mTop))
+        {
+            setTop(NULL);
+        }
+
+        delete mFocusHandler;
+    }
+
+    void Gui::setTop(Widget* top)
+    {
+        if (mTop != NULL)
+        {
+            mTop->_setFocusHandler(NULL);
+        }
+        if (top != NULL)
+        {
+            top->_setFocusHandler(mFocusHandler);
+        }
+
+        mTop = top;
+    }
+
+    Widget* Gui::getTop() const
+    {
+        return mTop;
+    }
+
+    void Gui::setGraphics(Graphics* graphics)
+    {
+        mGraphics = graphics;
+    }
+
+    Graphics* Gui::getGraphics() const
+    {
+        return mGraphics;
+    }
+
+    void Gui::setInput(Input* input)
+    {
+        mInput = input;
+    }
+
+    Input* Gui::getInput() const
+    {
+        return mInput;
+    }
+
+    void Gui::logic()
+    {
+        if (mTop == NULL)
+        {
+            throw GCN_EXCEPTION("No top widget set");
+        }
+
+        handleModalFocus();
+        handleModalMouseInputFocus();
+
+        if (mInput != NULL)
+        {
+            mInput->_pollInput();
+
+            handleKeyInput();
+            handleMouseInput();
+ 
+        } // end if
+
+        mTop->logic();
+    }
+
+    void Gui::draw()
+    {
+        if (mTop == NULL)
+        {
+            throw GCN_EXCEPTION("No top widget set");
+        }
+        if (mGraphics == NULL)
+        {
+            throw GCN_EXCEPTION("No graphics set");
+        }
+
+        if (!mTop->isVisible())
+        {
+            return;
+        }
+
+        mGraphics->_beginDraw();
+
+        // If top has a frame,
+        // draw it before drawing top
+        if (mTop->getFrameSize() > 0)
+        {
+            Rectangle rec = mTop->getDimension();
+            rec.x -= mTop->getFrameSize();
+            rec.y -= mTop->getFrameSize();
+            rec.width += 2 * mTop->getFrameSize();
+            rec.height += 2 * mTop->getFrameSize();
+            mGraphics->pushClipArea(rec);
+            mTop->drawFrame(mGraphics);
+            mGraphics->popClipArea();
+        }
+
+        mGraphics->pushClipArea(mTop->getDimension());
+        mTop->draw(mGraphics);
+        mGraphics->popClipArea();
+
+        mGraphics->_endDraw();
+    }
+
+    void Gui::focusNone()
+    {
+        mFocusHandler->focusNone();
+    }
+
+    void Gui::setTabbingEnabled(bool tabbing)
+    {
+        mTabbing = tabbing;
+    }
+
+    bool Gui::isTabbingEnabled()
+    {
+        return mTabbing;
+    }
+
+    void Gui::addGlobalKeyListener(KeyListener* keyListener)
+    {
+        mKeyListeners.push_back(keyListener);
+    }
+
+    void Gui::removeGlobalKeyListener(KeyListener* keyListener)
+    {
+        mKeyListeners.remove(keyListener);
+    }
+
+    void Gui::handleMouseInput()
+    {
+        while (!mInput->isMouseQueueEmpty())
+         {
+             MouseInput mouseInput = mInput->dequeueMouseInput();
+
+             // Save the current mouse state. It will be needed if modal focus
+             // changes or modal mouse input focus changes.
+             mLastMouseX = mouseInput.getX();
+             mLastMouseY = mouseInput.getY();
+
+             switch (mouseInput.getType())
+             {
+               case MouseInput::PRESSED:
+                   handleMousePressed(mouseInput);
+                   break;
+               case MouseInput::RELEASED:
+                   handleMouseReleased(mouseInput);
+                   break;
+               case MouseInput::MOVED:
+                   handleMouseMoved(mouseInput);
+                   break;
+               case MouseInput::WHEEL_MOVED_DOWN:
+                   handleMouseWheelMovedDown(mouseInput);
+                   break;
+               case MouseInput::WHEEL_MOVED_UP:
+                   handleMouseWheelMovedUp(mouseInput);
+                   break;
+               default:
+                   throw GCN_EXCEPTION("Unknown mouse input type.");
+                   break;
+             }
+         }
+    }
+
+    void Gui::handleKeyInput()
+    {
+        while (!mInput->isKeyQueueEmpty())
+        {
+            KeyInput keyInput = mInput->dequeueKeyInput();
+
+            // Save modifiers state
+            mShiftPressed = keyInput.isShiftPressed();
+            mMetaPressed = keyInput.isMetaPressed();
+            mControlPressed = keyInput.isControlPressed();
+            mAltPressed = keyInput.isAltPressed();
+
+            KeyEvent keyEventToGlobalKeyListeners(NULL,
+                                                  mShiftPressed,
+                                                  mControlPressed,
+                                                  mAltPressed,
+                                                  mMetaPressed,
+                                                  keyInput.getType(),
+                                                  keyInput.isNumericPad(),
+                                                  keyInput.getKey());
+
+            distributeKeyEventToGlobalKeyListeners(keyEventToGlobalKeyListeners);
+
+            // If a global key listener consumes the event it will not be
+            // sent further to the source of the event.
+            if (keyEventToGlobalKeyListeners.isConsumed())
+            {
+                continue;
+            }
+
+            bool keyEventConsumed = false;
+            
+            // Send key inputs to the focused widgets
+            if (mFocusHandler->getFocused() != NULL)
+            {
+                KeyEvent keyEvent(getKeyEventSource(),
+                                  mShiftPressed,
+                                  mControlPressed,
+                                  mAltPressed,
+                                  mMetaPressed,
+                                  keyInput.getType(),
+                                  keyInput.isNumericPad(),
+                                  keyInput.getKey());
+                
+
+                if (!mFocusHandler->getFocused()->isFocusable())
+                {
+                    mFocusHandler->focusNone();
+                }
+                else
+                {                    
+                    distributeKeyEvent(keyEvent);                    
+                }
+
+                keyEventConsumed = keyEvent.isConsumed();
+            }
+
+            // If the key event hasn't been consumed and
+            // tabbing is enable check for tab press and
+            // change focus.
+            if (!keyEventConsumed
+                && mTabbing
+                && keyInput.getKey().getValue() == Key::TAB
+                && keyInput.getType() == KeyInput::PRESSED)
+            {
+                if (keyInput.isShiftPressed())
+                {
+                    mFocusHandler->tabPrevious();
+                }
+                else
+                {
+                    mFocusHandler->tabNext();
+                }
+            }                           
+                
+        } // end while
+    }
+
+    void Gui::handleMouseMoved(const MouseInput& mouseInput)
+    {
+        // Check if the mouse leaves the application window.
+        if (!mWidgetWithMouseQueue.empty()
+            && (mouseInput.getX() < 0
+                || mouseInput.getY() < 0
+                || !mTop->getDimension().isPointInRect(mouseInput.getX(), mouseInput.getY()))
+            )
+        {
+            // Distribute an event to all widgets in the "widget with mouse" queue.
+            while (!mWidgetWithMouseQueue.empty())
+            {
+                Widget* widget = mWidgetWithMouseQueue.front();
+
+                if (Widget::widgetExists(widget))
+                {
+                    distributeMouseEvent(widget,
+                                         MouseEvent::EXITED,
+                                         mouseInput.getButton(),
+                                         mouseInput.getX(),
+                                         mouseInput.getY(),
+                                         true,
+                                         true);
+                }
+
+                mWidgetWithMouseQueue.pop_front();
+            }
+
+            return;
+        }
+
+        // Check if there is a need to send mouse exited events by
+        // traversing the "widget with mouse" queue.
+        bool widgetWithMouseQueueCheckDone = mWidgetWithMouseQueue.empty();
+        while (!widgetWithMouseQueueCheckDone)
+        {
+            unsigned int iterations = 0;
+            std::deque<Widget*>::iterator iter;
+            for (iter = mWidgetWithMouseQueue.begin();
+                 iter != mWidgetWithMouseQueue.end();
+                 iter++)
+            {
+                Widget* widget = *iter;
+                            
+                // If a widget in the "widget with mouse queue" doesn't
+                // exists anymore it should be removed from the queue.
+                if (!Widget::widgetExists(widget))
+                {
+                    mWidgetWithMouseQueue.erase(iter);
+                    break;
+                }
+                else
+                {
+                    int x, y;
+                    widget->getAbsolutePosition(x, y);
+
+                    if (x > mouseInput.getX()
+                        || y > mouseInput.getY()
+                        || x + widget->getWidth() <= mouseInput.getX()
+                        || y + widget->getHeight() <= mouseInput.getY()
+                        || !widget->isVisible())
+                    {
+                        distributeMouseEvent(widget,
+                                             MouseEvent::EXITED,
+                                             mouseInput.getButton(),
+                                             mouseInput.getX(),
+                                             mouseInput.getY(),
+                                             true,
+                                             true);                                       
+                        mClickCount = 1;
+                        mLastMousePressTimeStamp = 0;
+                        mWidgetWithMouseQueue.erase(iter);
+                        break;
+                    }
+                }
+
+                iterations++;
+            }
+
+            widgetWithMouseQueueCheckDone = iterations == mWidgetWithMouseQueue.size();
+        }
+
+        // Check all widgets below the mouse to see if they are
+        // present in the "widget with mouse" queue. If a widget
+        // is not then it should be added and an entered event should
+        // be sent to it.
+        Widget* parent = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
+        Widget* widget = parent;
+
+        // If a widget has modal mouse input focus then it will
+        // always be returned from getMouseEventSource, but we only wan't to send
+        // mouse entered events if the mouse has actually entered the widget with
+        // modal mouse input focus, hence we need to check if that's the case. If
+        // it's not we should simply ignore to send any mouse entered events.
+        if (mFocusHandler->getModalMouseInputFocused() != NULL
+            && widget == mFocusHandler->getModalMouseInputFocused()
+            && Widget::widgetExists(widget))
+        {
+            int x, y;
+            widget->getAbsolutePosition(x, y);
+
+            if (x > mouseInput.getX()
+                || y > mouseInput.getY()
+                || x + widget->getWidth() <= mouseInput.getX() 
+                || y + widget->getHeight() <= mouseInput.getY())
+            {
+                parent = NULL;
+            }
+        }
+
+        while (parent != NULL)
+        {
+            parent = (Widget*)widget->getParent();
+
+            // Check if the widget is present in the "widget with mouse" queue.
+            bool widgetIsPresentInQueue = false;
+            std::deque<Widget*>::iterator iter;
+            for (iter = mWidgetWithMouseQueue.begin();
+                 iter != mWidgetWithMouseQueue.end();
+                 iter++)
+            {
+                if (*iter == widget)
+                {
+                    widgetIsPresentInQueue = true;
+                    break;
+                }
+            }
+
+            // Widget is not present, send an entered event and add
+            // it to the "widget with mouse" queue.
+            if (!widgetIsPresentInQueue
+                && Widget::widgetExists(widget))
+            {
+                distributeMouseEvent(widget,
+                                     MouseEvent::ENTERED,
+                                     mouseInput.getButton(),
+                                     mouseInput.getX(),
+                                     mouseInput.getY(),
+                                     true,
+                                     true);
+                mWidgetWithMouseQueue.push_front(widget);
+            }
+
+            Widget* swap = widget;
+            widget = parent;
+            parent = (Widget*)swap->getParent();
+        }
+
+        if (mFocusHandler->getDraggedWidget() != NULL)
+        {
+            distributeMouseEvent(mFocusHandler->getDraggedWidget(),
+                                 MouseEvent::DRAGGED,
+                                 mLastMouseDragButton,
+                                 mouseInput.getX(),
+                                 mouseInput.getY());
+        }
+        else
+        {
+            Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
+            distributeMouseEvent(sourceWidget,
+                                 MouseEvent::MOVED,
+                                 mouseInput.getButton(),
+                                 mouseInput.getX(),
+                                 mouseInput.getY());
+        }
+    }
+
+    void Gui::handleMousePressed(const MouseInput& mouseInput)
+    {
+        Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
+
+        if (mFocusHandler->getDraggedWidget() != NULL)
+        {
+            sourceWidget = mFocusHandler->getDraggedWidget();
+        }
+
+        int sourceWidgetX, sourceWidgetY;
+        sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
+
+        if ((mFocusHandler->getModalFocused() != NULL
+            && sourceWidget->isModalFocused())
+            || mFocusHandler->getModalFocused() == NULL)
+        {
+            sourceWidget->requestFocus();
+        }
+
+        if (mouseInput.getTimeStamp() - mLastMousePressTimeStamp < 250
+            && mLastMousePressButton == mouseInput.getButton())
+        {
+            mClickCount++;
+        }
+        else
+        {
+            mClickCount = 1;
+        }
+
+        distributeMouseEvent(sourceWidget,
+                             MouseEvent::PRESSED,
+                             mouseInput.getButton(),
+                             mouseInput.getX(),
+                             mouseInput.getY());
+
+        mFocusHandler->setLastWidgetPressed(sourceWidget);
+
+        mFocusHandler->setDraggedWidget(sourceWidget);
+        mLastMouseDragButton = mouseInput.getButton();
+
+        mLastMousePressButton = mouseInput.getButton();
+        mLastMousePressTimeStamp = mouseInput.getTimeStamp();
+    }
+
+    void Gui::handleMouseWheelMovedDown(const MouseInput& mouseInput)
+    {
+        Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
+
+        if (mFocusHandler->getDraggedWidget() != NULL)
+        {
+            sourceWidget = mFocusHandler->getDraggedWidget();
+        }
+
+        int sourceWidgetX, sourceWidgetY;
+        sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
+
+        distributeMouseEvent(sourceWidget,
+                             MouseEvent::WHEEL_MOVED_DOWN,
+                             mouseInput.getButton(),
+                             mouseInput.getX(),
+                             mouseInput.getY());
+    }
+
+    void Gui::handleMouseWheelMovedUp(const MouseInput& mouseInput)
+    {
+        Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
+
+        if (mFocusHandler->getDraggedWidget() != NULL)
+        {
+            sourceWidget = mFocusHandler->getDraggedWidget();
+        }
+
+        int sourceWidgetX, sourceWidgetY;
+        sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
+
+        distributeMouseEvent(sourceWidget,
+                             MouseEvent::WHEEL_MOVED_UP,
+                             mouseInput.getButton(),
+                             mouseInput.getX(),
+                             mouseInput.getY());
+    }
+
+    void Gui::handleMouseReleased(const MouseInput& mouseInput)
+    {
+        Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY());
+
+        if (mFocusHandler->getDraggedWidget() != NULL)
+        {
+            if (sourceWidget != mFocusHandler->getLastWidgetPressed())
+            {
+                mFocusHandler->setLastWidgetPressed(NULL);
+            }
+            
+            sourceWidget = mFocusHandler->getDraggedWidget();
+        }
+
+        int sourceWidgetX, sourceWidgetY;
+        sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY);
+        
+        distributeMouseEvent(sourceWidget,
+                             MouseEvent::RELEASED,
+                             mouseInput.getButton(),
+                             mouseInput.getX(),
+                             mouseInput.getY());
+
+        if (mouseInput.getButton() == mLastMousePressButton            
+            && mFocusHandler->getLastWidgetPressed() == sourceWidget)
+        {
+            distributeMouseEvent(sourceWidget,
+                                 MouseEvent::CLICKED,
+                                 mouseInput.getButton(),
+                                 mouseInput.getX(),
+                                 mouseInput.getY());
+            
+            mFocusHandler->setLastWidgetPressed(NULL);
+        }
+        else
+        {
+            mLastMousePressButton = 0;
+            mClickCount = 0;
+        }
+
+        if (mFocusHandler->getDraggedWidget() != NULL)
+        {
+            mFocusHandler->setDraggedWidget(NULL);
+        }
+    }
+
+    Widget* Gui::getWidgetAt(int x, int y)
+    {
+        // If the widget's parent has no child then we have found the widget..
+        Widget* parent = mTop;
+        Widget* child = mTop;
+
+        while (child != NULL)
+        {
+            Widget* swap = child;
+            int parentX, parentY;
+            parent->getAbsolutePosition(parentX, parentY);
+            child = parent->getWidgetAt(x - parentX, y - parentY);
+            parent = swap;
+        }
+
+        return parent;
+    }
+
+    Widget* Gui::getMouseEventSource(int x, int y)
+    {
+        Widget* widget = getWidgetAt(x, y);
+
+        if (mFocusHandler->getModalMouseInputFocused() != NULL
+            && !widget->isModalMouseInputFocused())
+        {
+            return mFocusHandler->getModalMouseInputFocused();
+        }
+
+        return widget;
+    }
+
+    Widget* Gui::getKeyEventSource()
+    {
+        Widget* widget = mFocusHandler->getFocused();
+
+        while (widget->_getInternalFocusHandler() != NULL
+               && widget->_getInternalFocusHandler()->getFocused() != NULL)
+        {
+            widget = widget->_getInternalFocusHandler()->getFocused();
+        }
+
+        return widget;
+    }
+
+    void Gui::distributeMouseEvent(Widget* source,
+                                   int type,
+                                   int button,
+                                   int x,
+                                   int y,
+                                   bool force,
+                                   bool toSourceOnly)
+    {
+        Widget* parent = source;
+        Widget* widget = source;
+
+        if (mFocusHandler->getModalFocused() != NULL
+            && !widget->isModalFocused()
+            && !force)
+        {
+            return;
+        }
+
+        if (mFocusHandler->getModalMouseInputFocused() != NULL
+            && !widget->isModalMouseInputFocused()
+            && !force)
+        {
+            return;
+        }
+
+        MouseEvent mouseEvent(source,
+                              mShiftPressed,
+                              mControlPressed,
+                              mAltPressed,
+                              mMetaPressed,
+                              type,
+                              button,
+                              x,
+                              y,
+                              mClickCount);
+
+        while (parent != NULL)
+        {
+            // If the widget has been removed due to input
+            // cancel the distribution.
+            if (!Widget::widgetExists(widget))
+            {
+                break;
+            }
+
+            parent = (Widget*)widget->getParent();
+
+            if (widget->isEnabled() || force)
+            {
+                int widgetX, widgetY;
+                widget->getAbsolutePosition(widgetX, widgetY);
+
+                mouseEvent.mX = x - widgetX;
+                mouseEvent.mY = y - widgetY;
+                                      
+                std::list<MouseListener*> mouseListeners = widget->_getMouseListeners();
+
+                // Send the event to all mouse listeners of the widget.
+                for (std::list<MouseListener*>::iterator it = mouseListeners.begin();
+                     it != mouseListeners.end();
+                     ++it)
+                {
+                    switch (mouseEvent.getType())
+                    {
+                      case MouseEvent::ENTERED:
+                          (*it)->mouseEntered(mouseEvent);
+                          break;
+                      case MouseEvent::EXITED:
+                          (*it)->mouseExited(mouseEvent);
+                          break;
+                      case MouseEvent::MOVED:
+                          (*it)->mouseMoved(mouseEvent);
+                          break;
+                      case MouseEvent::PRESSED:
+                          (*it)->mousePressed(mouseEvent);
+                          break;
+                      case MouseEvent::RELEASED:
+                          (*it)->mouseReleased(mouseEvent);
+                          break;
+                      case MouseEvent::WHEEL_MOVED_UP:
+                          (*it)->mouseWheelMovedUp(mouseEvent);
+                          break;
+                      case MouseEvent::WHEEL_MOVED_DOWN:
+                          (*it)->mouseWheelMovedDown(mouseEvent);
+                          break;
+                      case MouseEvent::DRAGGED:
+                          (*it)->mouseDragged(mouseEvent);
+                          break;
+                      case MouseEvent::CLICKED:
+                          (*it)->mouseClicked(mouseEvent);
+                          break;
+                      default:
+                          throw GCN_EXCEPTION("Unknown mouse event type.");
+                    }                    
+                }
+                
+                if (toSourceOnly)
+                {
+                    break;
+                }
+
+            }
+
+            Widget* swap = widget;
+            widget = parent;
+            parent = (Widget*)swap->getParent();
+
+            // If a non modal focused widget has been reach
+            // and we have modal focus cancel the distribution.
+            if (mFocusHandler->getModalFocused() != NULL
+                && !widget->isModalFocused())
+            {
+                break;
+            }
+
+            // If a non modal mouse input focused widget has been reach
+            // and we have modal mouse input focus cancel the distribution.
+            if (mFocusHandler->getModalMouseInputFocused() != NULL
+                && !widget->isModalMouseInputFocused())
+            {
+                break;
+            }
+        }
+    }
+
+    void Gui::distributeKeyEvent(KeyEvent& keyEvent)
+    {
+        Widget* parent = keyEvent.getSource();
+        Widget* widget = keyEvent.getSource();
+
+        if (mFocusHandler->getModalFocused() != NULL
+            && !widget->isModalFocused())
+        {
+            return;
+        }
+
+        if (mFocusHandler->getModalMouseInputFocused() != NULL
+            && !widget->isModalMouseInputFocused())
+        {
+            return;
+        }
+
+        while (parent != NULL)
+        {
+            // If the widget has been removed due to input
+            // cancel the distribution.
+            if (!Widget::widgetExists(widget))
+            {
+                break;
+            }
+
+            parent = (Widget*)widget->getParent();
+
+            if (widget->isEnabled())
+            {
+                std::list<KeyListener*> keyListeners = widget->_getKeyListeners();
+            
+                // Send the event to all key listeners of the source widget.
+                for (std::list<KeyListener*>::iterator it = keyListeners.begin();
+                     it != keyListeners.end();
+                     ++it)
+                {
+                    switch (keyEvent.getType())
+                    {
+                      case KeyEvent::PRESSED:
+                          (*it)->keyPressed(keyEvent);
+                          break;
+                      case KeyEvent::RELEASED:
+                          (*it)->keyReleased(keyEvent);
+                          break;
+                      default:
+                          throw GCN_EXCEPTION("Unknown key event type.");
+                    }                
+                }
+            }
+
+            Widget* swap = widget;
+            widget = parent;
+            parent = (Widget*)swap->getParent();
+
+            // If a non modal focused widget has been reach
+            // and we have modal focus cancel the distribution.
+            if (mFocusHandler->getModalFocused() != NULL
+                && !widget->isModalFocused())
+            {
+                break;
+            }
+        }
+    }
+
+    void Gui::distributeKeyEventToGlobalKeyListeners(KeyEvent& keyEvent)
+    {
+        KeyListenerListIterator it;
+
+        for (it = mKeyListeners.begin(); it != mKeyListeners.end(); it++)
+        {
+            switch (keyEvent.getType())
+            {
+              case KeyEvent::PRESSED:
+                  (*it)->keyPressed(keyEvent);
+                  break;
+              case KeyEvent::RELEASED:
+                  (*it)->keyReleased(keyEvent);
+                  break;
+              default:
+                  throw GCN_EXCEPTION("Unknown key event type.");
+            }
+
+            if (keyEvent.isConsumed())
+            {
+                break;
+            }
+        }
+    }
+
+    void Gui::handleModalMouseInputFocus()
+    {
+        // Check if modal mouse input focus has been gained by a widget.
+        if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus() 
+                != mFocusHandler->getModalMouseInputFocused())
+             && (mFocusHandler->getLastWidgetWithModalMouseInputFocus() == NULL))
+        {
+            handleModalFocusGained();
+            mFocusHandler->setLastWidgetWithModalMouseInputFocus(mFocusHandler->getModalMouseInputFocused());
+        }
+        // Check if modal mouse input focus has been released.
+        else if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
+                    != mFocusHandler->getModalMouseInputFocused())
+                    && (mFocusHandler->getLastWidgetWithModalMouseInputFocus() != NULL))
+        {
+            handleModalFocusReleased();
+            mFocusHandler->setLastWidgetWithModalMouseInputFocus(NULL);
+        }
+    }
+
+     void Gui::handleModalFocus()
+    {
+        // Check if modal focus has been gained by a widget.
+        if ((mFocusHandler->getLastWidgetWithModalFocus() 
+                != mFocusHandler->getModalFocused())
+             && (mFocusHandler->getLastWidgetWithModalFocus() == NULL))
+        {
+            handleModalFocusGained();
+            mFocusHandler->setLastWidgetWithModalFocus(mFocusHandler->getModalFocused());
+        }
+        // Check if modal focus has been released.
+        else if ((mFocusHandler->getLastWidgetWithModalFocus()
+                    != mFocusHandler->getModalFocused())
+                    && (mFocusHandler->getLastWidgetWithModalFocus() != NULL))
+        {
+            handleModalFocusReleased();
+            mFocusHandler->setLastWidgetWithModalFocus(NULL);
+        }
+    }
+
+    void Gui::handleModalFocusGained()
+    {
+         // Distribute an event to all widgets in the "widget with mouse" queue.
+        while (!mWidgetWithMouseQueue.empty())
+        {
+            Widget* widget = mWidgetWithMouseQueue.front();
+
+            if (Widget::widgetExists(widget))
+            {
+                distributeMouseEvent(widget,
+                                     MouseEvent::EXITED,
+                                     mLastMousePressButton,
+                                     mLastMouseX,
+                                     mLastMouseY,
+                                     true,
+                                     true);
+            }
+
+            mWidgetWithMouseQueue.pop_front();
+        }
+
+        mFocusHandler->setLastWidgetWithModalMouseInputFocus(mFocusHandler->getModalMouseInputFocused());
+    }
+
+    void Gui::handleModalFocusReleased()
+    {
+         // Check all widgets below the mouse to see if they are
+        // present in the "widget with mouse" queue. If a widget
+        // is not then it should be added and an entered event should
+        // be sent to it.
+        Widget* widget = getMouseEventSource(mLastMouseX, mLastMouseY);
+        Widget* parent = widget;
+
+        while (parent != NULL)
+        {
+            parent = (Widget*)widget->getParent();
+
+            // Check if the widget is present in the "widget with mouse" queue.
+            bool widgetIsPresentInQueue = false;
+            std::deque<Widget*>::iterator iter;
+            for (iter = mWidgetWithMouseQueue.begin();
+                 iter != mWidgetWithMouseQueue.end();
+                 iter++)
+            {
+                if (*iter == widget)
+                {
+                    widgetIsPresentInQueue = true;
+                    break;
+                }
+            }
+
+            // Widget is not present, send an entered event and add
+            // it to the "widget with mouse" queue.
+            if (!widgetIsPresentInQueue
+                && Widget::widgetExists(widget))
+            {
+                distributeMouseEvent(widget,
+                                     MouseEvent::ENTERED,
+                                     mLastMousePressButton,
+                                     mLastMouseX,
+                                     mLastMouseY,
+                                     false,
+                                     true);
+                mWidgetWithMouseQueue.push_front(widget);
+            }
+
+            Widget* swap = widget;
+            widget = parent;
+            parent = (Widget*)swap->getParent();
+        }
+    }
+}