1 /* _______ __ __ __ ______ __ __ _______ __ __ 2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 8 * 9 * Copyright (c) 2004 - 2008 Olof Naess�n and Per Larsson 10 * 11 * 12 * Per Larsson a.k.a finalman 13 * Olof Naess�n a.k.a jansem/yakslem 14 * 15 * Visit: http://guichan.sourceforge.net 16 * 17 * License: (BSD) 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in 25 * the documentation and/or other materials provided with the 26 * distribution. 27 * 3. Neither the name of Guichan nor the names of its contributors may 28 * be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 /* 45 * For comments regarding functions please see the header file. 46 */ 47 48 #include "guichan/gui.hpp" 49 50 #include "guichan/basiccontainer.hpp" 51 #include "guichan/exception.hpp" 52 #include "guichan/focushandler.hpp" 53 #include "guichan/graphics.hpp" 54 #include "guichan/input.hpp" 55 #include "guichan/keyinput.hpp" 56 #include "guichan/keylistener.hpp" 57 #include "guichan/mouseinput.hpp" 58 #include "guichan/mouselistener.hpp" 59 #include "guichan/widget.hpp" 60 61 namespace gcn 62 { Gui()63 Gui::Gui() 64 :mTop(NULL), 65 mGraphics(NULL), 66 mInput(NULL), 67 mTabbing(true), 68 mShiftPressed(false), 69 mMetaPressed(false), 70 mControlPressed(false), 71 mAltPressed(false), 72 mLastMousePressButton(0), 73 mLastMousePressTimeStamp(0), 74 mLastMouseX(0), 75 mLastMouseY(0), 76 mClickCount(1), 77 mLastMouseDragButton(0) 78 { 79 mFocusHandler = new FocusHandler(); 80 } 81 ~Gui()82 Gui::~Gui() 83 { 84 if (Widget::widgetExists(mTop)) 85 { 86 setTop(NULL); 87 } 88 89 delete mFocusHandler; 90 } 91 setTop(Widget * top)92 void Gui::setTop(Widget* top) 93 { 94 if (mTop != NULL) 95 { 96 mTop->_setFocusHandler(NULL); 97 } 98 if (top != NULL) 99 { 100 top->_setFocusHandler(mFocusHandler); 101 } 102 103 mTop = top; 104 } 105 getTop() const106 Widget* Gui::getTop() const 107 { 108 return mTop; 109 } 110 setGraphics(Graphics * graphics)111 void Gui::setGraphics(Graphics* graphics) 112 { 113 mGraphics = graphics; 114 } 115 getGraphics() const116 Graphics* Gui::getGraphics() const 117 { 118 return mGraphics; 119 } 120 setInput(Input * input)121 void Gui::setInput(Input* input) 122 { 123 mInput = input; 124 } 125 getInput() const126 Input* Gui::getInput() const 127 { 128 return mInput; 129 } 130 logic()131 void Gui::logic() 132 { 133 if (mTop == NULL) 134 { 135 throw GCN_EXCEPTION("No top widget set"); 136 } 137 138 handleModalFocus(); 139 handleModalMouseInputFocus(); 140 141 if (mInput != NULL) 142 { 143 mInput->_pollInput(); 144 145 handleKeyInput(); 146 handleMouseInput(); 147 148 } // end if 149 150 mTop->logic(); 151 } 152 draw()153 void Gui::draw() 154 { 155 if (mTop == NULL) 156 { 157 throw GCN_EXCEPTION("No top widget set"); 158 } 159 if (mGraphics == NULL) 160 { 161 throw GCN_EXCEPTION("No graphics set"); 162 } 163 164 if (!mTop->isVisible()) 165 { 166 return; 167 } 168 169 mGraphics->_beginDraw(); 170 171 // If top has a frame, 172 // draw it before drawing top 173 if (mTop->getFrameSize() > 0) 174 { 175 Rectangle rec = mTop->getDimension(); 176 rec.x -= mTop->getFrameSize(); 177 rec.y -= mTop->getFrameSize(); 178 rec.width += 2 * mTop->getFrameSize(); 179 rec.height += 2 * mTop->getFrameSize(); 180 mGraphics->pushClipArea(rec); 181 mTop->drawFrame(mGraphics); 182 mGraphics->popClipArea(); 183 } 184 185 mGraphics->pushClipArea(mTop->getDimension()); 186 mTop->draw(mGraphics); 187 mGraphics->popClipArea(); 188 189 mGraphics->_endDraw(); 190 } 191 focusNone()192 void Gui::focusNone() 193 { 194 mFocusHandler->focusNone(); 195 } 196 setTabbingEnabled(bool tabbing)197 void Gui::setTabbingEnabled(bool tabbing) 198 { 199 mTabbing = tabbing; 200 } 201 isTabbingEnabled()202 bool Gui::isTabbingEnabled() 203 { 204 return mTabbing; 205 } 206 addGlobalKeyListener(KeyListener * keyListener)207 void Gui::addGlobalKeyListener(KeyListener* keyListener) 208 { 209 mKeyListeners.push_back(keyListener); 210 } 211 removeGlobalKeyListener(KeyListener * keyListener)212 void Gui::removeGlobalKeyListener(KeyListener* keyListener) 213 { 214 mKeyListeners.remove(keyListener); 215 } 216 handleMouseInput()217 void Gui::handleMouseInput() 218 { 219 while (!mInput->isMouseQueueEmpty()) 220 { 221 MouseInput mouseInput = mInput->dequeueMouseInput(); 222 223 // Save the current mouse state. It will be needed if modal focus 224 // changes or modal mouse input focus changes. 225 mLastMouseX = mouseInput.getX(); 226 mLastMouseY = mouseInput.getY(); 227 228 switch (mouseInput.getType()) 229 { 230 case MouseInput::PRESSED: 231 handleMousePressed(mouseInput); 232 break; 233 case MouseInput::RELEASED: 234 handleMouseReleased(mouseInput); 235 break; 236 case MouseInput::MOVED: 237 handleMouseMoved(mouseInput); 238 break; 239 case MouseInput::WHEEL_MOVED_DOWN: 240 handleMouseWheelMovedDown(mouseInput); 241 break; 242 case MouseInput::WHEEL_MOVED_UP: 243 handleMouseWheelMovedUp(mouseInput); 244 break; 245 default: 246 throw GCN_EXCEPTION("Unknown mouse input type."); 247 break; 248 } 249 } 250 } 251 handleKeyInput()252 void Gui::handleKeyInput() 253 { 254 while (!mInput->isKeyQueueEmpty()) 255 { 256 KeyInput keyInput = mInput->dequeueKeyInput(); 257 258 // Save modifiers state 259 mShiftPressed = keyInput.isShiftPressed(); 260 mMetaPressed = keyInput.isMetaPressed(); 261 mControlPressed = keyInput.isControlPressed(); 262 mAltPressed = keyInput.isAltPressed(); 263 264 KeyEvent keyEventToGlobalKeyListeners(NULL, 265 mShiftPressed, 266 mControlPressed, 267 mAltPressed, 268 mMetaPressed, 269 keyInput.getType(), 270 keyInput.isNumericPad(), 271 keyInput.getKey()); 272 273 distributeKeyEventToGlobalKeyListeners(keyEventToGlobalKeyListeners); 274 275 // If a global key listener consumes the event it will not be 276 // sent further to the source of the event. 277 if (keyEventToGlobalKeyListeners.isConsumed()) 278 { 279 continue; 280 } 281 282 bool keyEventConsumed = false; 283 284 // Send key inputs to the focused widgets 285 if (mFocusHandler->getFocused() != NULL) 286 { 287 KeyEvent keyEvent(getKeyEventSource(), 288 mShiftPressed, 289 mControlPressed, 290 mAltPressed, 291 mMetaPressed, 292 keyInput.getType(), 293 keyInput.isNumericPad(), 294 keyInput.getKey()); 295 296 297 if (!mFocusHandler->getFocused()->isFocusable()) 298 { 299 mFocusHandler->focusNone(); 300 } 301 else 302 { 303 distributeKeyEvent(keyEvent); 304 } 305 306 keyEventConsumed = keyEvent.isConsumed(); 307 } 308 309 // If the key event hasn't been consumed and 310 // tabbing is enable check for tab press and 311 // change focus. 312 if (!keyEventConsumed 313 && mTabbing 314 && keyInput.getKey().getValue() == Key::TAB 315 && keyInput.getType() == KeyInput::PRESSED) 316 { 317 if (keyInput.isShiftPressed()) 318 { 319 mFocusHandler->tabPrevious(); 320 } 321 else 322 { 323 mFocusHandler->tabNext(); 324 } 325 } 326 327 } // end while 328 } 329 handleMouseMoved(const MouseInput & mouseInput)330 void Gui::handleMouseMoved(const MouseInput& mouseInput) 331 { 332 // Check if the mouse leaves the application window. 333 if (!mWidgetWithMouseQueue.empty() 334 && (mouseInput.getX() < 0 335 || mouseInput.getY() < 0 336 || !mTop->getDimension().isPointInRect(mouseInput.getX(), mouseInput.getY())) 337 ) 338 { 339 // Distribute an event to all widgets in the "widget with mouse" queue. 340 while (!mWidgetWithMouseQueue.empty()) 341 { 342 Widget* widget = mWidgetWithMouseQueue.front(); 343 344 if (Widget::widgetExists(widget)) 345 { 346 distributeMouseEvent(widget, 347 MouseEvent::EXITED, 348 mouseInput.getButton(), 349 mouseInput.getX(), 350 mouseInput.getY(), 351 true, 352 true); 353 } 354 355 mWidgetWithMouseQueue.pop_front(); 356 } 357 358 return; 359 } 360 361 // Check if there is a need to send mouse exited events by 362 // traversing the "widget with mouse" queue. 363 bool widgetWithMouseQueueCheckDone = mWidgetWithMouseQueue.empty(); 364 while (!widgetWithMouseQueueCheckDone) 365 { 366 unsigned int iterations = 0; 367 std::deque<Widget*>::iterator iter; 368 for (iter = mWidgetWithMouseQueue.begin(); 369 iter != mWidgetWithMouseQueue.end(); 370 iter++) 371 { 372 Widget* widget = *iter; 373 374 // If a widget in the "widget with mouse queue" doesn't 375 // exists anymore it should be removed from the queue. 376 if (!Widget::widgetExists(widget)) 377 { 378 mWidgetWithMouseQueue.erase(iter); 379 break; 380 } 381 else 382 { 383 int x, y; 384 widget->getAbsolutePosition(x, y); 385 386 if (x > mouseInput.getX() 387 || y > mouseInput.getY() 388 || x + widget->getWidth() <= mouseInput.getX() 389 || y + widget->getHeight() <= mouseInput.getY() 390 || !widget->isVisible()) 391 { 392 distributeMouseEvent(widget, 393 MouseEvent::EXITED, 394 mouseInput.getButton(), 395 mouseInput.getX(), 396 mouseInput.getY(), 397 true, 398 true); 399 mClickCount = 1; 400 mLastMousePressTimeStamp = 0; 401 mWidgetWithMouseQueue.erase(iter); 402 break; 403 } 404 } 405 406 iterations++; 407 } 408 409 widgetWithMouseQueueCheckDone = iterations == mWidgetWithMouseQueue.size(); 410 } 411 412 // Check all widgets below the mouse to see if they are 413 // present in the "widget with mouse" queue. If a widget 414 // is not then it should be added and an entered event should 415 // be sent to it. 416 Widget* parent = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); 417 Widget* widget = parent; 418 419 // If a widget has modal mouse input focus then it will 420 // always be returned from getMouseEventSource, but we only wan't to send 421 // mouse entered events if the mouse has actually entered the widget with 422 // modal mouse input focus, hence we need to check if that's the case. If 423 // it's not we should simply ignore to send any mouse entered events. 424 if (mFocusHandler->getModalMouseInputFocused() != NULL 425 && widget == mFocusHandler->getModalMouseInputFocused() 426 && Widget::widgetExists(widget)) 427 { 428 int x, y; 429 widget->getAbsolutePosition(x, y); 430 431 if (x > mouseInput.getX() 432 || y > mouseInput.getY() 433 || x + widget->getWidth() <= mouseInput.getX() 434 || y + widget->getHeight() <= mouseInput.getY()) 435 { 436 parent = NULL; 437 } 438 } 439 440 while (parent != NULL) 441 { 442 parent = (Widget*)widget->getParent(); 443 444 // Check if the widget is present in the "widget with mouse" queue. 445 bool widgetIsPresentInQueue = false; 446 std::deque<Widget*>::iterator iter; 447 for (iter = mWidgetWithMouseQueue.begin(); 448 iter != mWidgetWithMouseQueue.end(); 449 iter++) 450 { 451 if (*iter == widget) 452 { 453 widgetIsPresentInQueue = true; 454 break; 455 } 456 } 457 458 // Widget is not present, send an entered event and add 459 // it to the "widget with mouse" queue. 460 if (!widgetIsPresentInQueue 461 && Widget::widgetExists(widget)) 462 { 463 distributeMouseEvent(widget, 464 MouseEvent::ENTERED, 465 mouseInput.getButton(), 466 mouseInput.getX(), 467 mouseInput.getY(), 468 true, 469 true); 470 mWidgetWithMouseQueue.push_front(widget); 471 } 472 473 Widget* swap = widget; 474 widget = parent; 475 parent = (Widget*)swap->getParent(); 476 } 477 478 if (mFocusHandler->getDraggedWidget() != NULL) 479 { 480 distributeMouseEvent(mFocusHandler->getDraggedWidget(), 481 MouseEvent::DRAGGED, 482 mLastMouseDragButton, 483 mouseInput.getX(), 484 mouseInput.getY()); 485 } 486 else 487 { 488 Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); 489 distributeMouseEvent(sourceWidget, 490 MouseEvent::MOVED, 491 mouseInput.getButton(), 492 mouseInput.getX(), 493 mouseInput.getY()); 494 } 495 } 496 handleMousePressed(const MouseInput & mouseInput)497 void Gui::handleMousePressed(const MouseInput& mouseInput) 498 { 499 Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); 500 501 if (mFocusHandler->getDraggedWidget() != NULL) 502 { 503 sourceWidget = mFocusHandler->getDraggedWidget(); 504 } 505 506 int sourceWidgetX, sourceWidgetY; 507 sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); 508 509 if ((mFocusHandler->getModalFocused() != NULL 510 && sourceWidget->isModalFocused()) 511 || mFocusHandler->getModalFocused() == NULL) 512 { 513 sourceWidget->requestFocus(); 514 } 515 516 if (mouseInput.getTimeStamp() - mLastMousePressTimeStamp < 250 517 && mLastMousePressButton == mouseInput.getButton()) 518 { 519 mClickCount++; 520 } 521 else 522 { 523 mClickCount = 1; 524 } 525 526 distributeMouseEvent(sourceWidget, 527 MouseEvent::PRESSED, 528 mouseInput.getButton(), 529 mouseInput.getX(), 530 mouseInput.getY()); 531 532 mFocusHandler->setLastWidgetPressed(sourceWidget); 533 534 mFocusHandler->setDraggedWidget(sourceWidget); 535 mLastMouseDragButton = mouseInput.getButton(); 536 537 mLastMousePressButton = mouseInput.getButton(); 538 mLastMousePressTimeStamp = mouseInput.getTimeStamp(); 539 } 540 handleMouseWheelMovedDown(const MouseInput & mouseInput)541 void Gui::handleMouseWheelMovedDown(const MouseInput& mouseInput) 542 { 543 Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); 544 545 if (mFocusHandler->getDraggedWidget() != NULL) 546 { 547 sourceWidget = mFocusHandler->getDraggedWidget(); 548 } 549 550 int sourceWidgetX, sourceWidgetY; 551 sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); 552 553 distributeMouseEvent(sourceWidget, 554 MouseEvent::WHEEL_MOVED_DOWN, 555 mouseInput.getButton(), 556 mouseInput.getX(), 557 mouseInput.getY()); 558 } 559 handleMouseWheelMovedUp(const MouseInput & mouseInput)560 void Gui::handleMouseWheelMovedUp(const MouseInput& mouseInput) 561 { 562 Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); 563 564 if (mFocusHandler->getDraggedWidget() != NULL) 565 { 566 sourceWidget = mFocusHandler->getDraggedWidget(); 567 } 568 569 int sourceWidgetX, sourceWidgetY; 570 sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); 571 572 distributeMouseEvent(sourceWidget, 573 MouseEvent::WHEEL_MOVED_UP, 574 mouseInput.getButton(), 575 mouseInput.getX(), 576 mouseInput.getY()); 577 } 578 handleMouseReleased(const MouseInput & mouseInput)579 void Gui::handleMouseReleased(const MouseInput& mouseInput) 580 { 581 Widget* sourceWidget = getMouseEventSource(mouseInput.getX(), mouseInput.getY()); 582 583 if (mFocusHandler->getDraggedWidget() != NULL) 584 { 585 if (sourceWidget != mFocusHandler->getLastWidgetPressed()) 586 { 587 mFocusHandler->setLastWidgetPressed(NULL); 588 } 589 590 sourceWidget = mFocusHandler->getDraggedWidget(); 591 } 592 593 int sourceWidgetX, sourceWidgetY; 594 sourceWidget->getAbsolutePosition(sourceWidgetX, sourceWidgetY); 595 596 distributeMouseEvent(sourceWidget, 597 MouseEvent::RELEASED, 598 mouseInput.getButton(), 599 mouseInput.getX(), 600 mouseInput.getY()); 601 602 if (mouseInput.getButton() == mLastMousePressButton 603 && mFocusHandler->getLastWidgetPressed() == sourceWidget) 604 { 605 distributeMouseEvent(sourceWidget, 606 MouseEvent::CLICKED, 607 mouseInput.getButton(), 608 mouseInput.getX(), 609 mouseInput.getY()); 610 611 mFocusHandler->setLastWidgetPressed(NULL); 612 } 613 else 614 { 615 mLastMousePressButton = 0; 616 mClickCount = 0; 617 } 618 619 if (mFocusHandler->getDraggedWidget() != NULL) 620 { 621 mFocusHandler->setDraggedWidget(NULL); 622 } 623 } 624 getWidgetAt(int x,int y)625 Widget* Gui::getWidgetAt(int x, int y) 626 { 627 // If the widget's parent has no child then we have found the widget.. 628 Widget* parent = mTop; 629 Widget* child = mTop; 630 631 while (child != NULL) 632 { 633 Widget* swap = child; 634 int parentX, parentY; 635 parent->getAbsolutePosition(parentX, parentY); 636 child = parent->getWidgetAt(x - parentX, y - parentY); 637 parent = swap; 638 } 639 640 return parent; 641 } 642 getMouseEventSource(int x,int y)643 Widget* Gui::getMouseEventSource(int x, int y) 644 { 645 Widget* widget = getWidgetAt(x, y); 646 647 if (mFocusHandler->getModalMouseInputFocused() != NULL 648 && !widget->isModalMouseInputFocused()) 649 { 650 return mFocusHandler->getModalMouseInputFocused(); 651 } 652 653 return widget; 654 } 655 getKeyEventSource()656 Widget* Gui::getKeyEventSource() 657 { 658 Widget* widget = mFocusHandler->getFocused(); 659 660 while (widget->_getInternalFocusHandler() != NULL 661 && widget->_getInternalFocusHandler()->getFocused() != NULL) 662 { 663 widget = widget->_getInternalFocusHandler()->getFocused(); 664 } 665 666 return widget; 667 } 668 distributeMouseEvent(Widget * source,int type,int button,int x,int y,bool force,bool toSourceOnly)669 void Gui::distributeMouseEvent(Widget* source, 670 int type, 671 int button, 672 int x, 673 int y, 674 bool force, 675 bool toSourceOnly) 676 { 677 Widget* parent = source; 678 Widget* widget = source; 679 680 if (mFocusHandler->getModalFocused() != NULL 681 && !widget->isModalFocused() 682 && !force) 683 { 684 return; 685 } 686 687 if (mFocusHandler->getModalMouseInputFocused() != NULL 688 && !widget->isModalMouseInputFocused() 689 && !force) 690 { 691 return; 692 } 693 694 MouseEvent mouseEvent(source, 695 mShiftPressed, 696 mControlPressed, 697 mAltPressed, 698 mMetaPressed, 699 type, 700 button, 701 x, 702 y, 703 mClickCount); 704 705 while (parent != NULL) 706 { 707 // If the widget has been removed due to input 708 // cancel the distribution. 709 if (!Widget::widgetExists(widget)) 710 { 711 break; 712 } 713 714 parent = (Widget*)widget->getParent(); 715 716 if (widget->isEnabled() || force) 717 { 718 int widgetX, widgetY; 719 widget->getAbsolutePosition(widgetX, widgetY); 720 721 mouseEvent.mX = x - widgetX; 722 mouseEvent.mY = y - widgetY; 723 724 std::list<MouseListener*> mouseListeners = widget->_getMouseListeners(); 725 726 // Send the event to all mouse listeners of the widget. 727 for (std::list<MouseListener*>::iterator it = mouseListeners.begin(); 728 it != mouseListeners.end(); 729 ++it) 730 { 731 switch (mouseEvent.getType()) 732 { 733 case MouseEvent::ENTERED: 734 (*it)->mouseEntered(mouseEvent); 735 break; 736 case MouseEvent::EXITED: 737 (*it)->mouseExited(mouseEvent); 738 break; 739 case MouseEvent::MOVED: 740 (*it)->mouseMoved(mouseEvent); 741 break; 742 case MouseEvent::PRESSED: 743 (*it)->mousePressed(mouseEvent); 744 break; 745 case MouseEvent::RELEASED: 746 (*it)->mouseReleased(mouseEvent); 747 break; 748 case MouseEvent::WHEEL_MOVED_UP: 749 (*it)->mouseWheelMovedUp(mouseEvent); 750 break; 751 case MouseEvent::WHEEL_MOVED_DOWN: 752 (*it)->mouseWheelMovedDown(mouseEvent); 753 break; 754 case MouseEvent::DRAGGED: 755 (*it)->mouseDragged(mouseEvent); 756 break; 757 case MouseEvent::CLICKED: 758 (*it)->mouseClicked(mouseEvent); 759 break; 760 default: 761 throw GCN_EXCEPTION("Unknown mouse event type."); 762 } 763 } 764 765 if (toSourceOnly) 766 { 767 break; 768 } 769 770 } 771 772 Widget* swap = widget; 773 widget = parent; 774 parent = (Widget*)swap->getParent(); 775 776 // If a non modal focused widget has been reach 777 // and we have modal focus cancel the distribution. 778 if (mFocusHandler->getModalFocused() != NULL 779 && !widget->isModalFocused()) 780 { 781 break; 782 } 783 784 // If a non modal mouse input focused widget has been reach 785 // and we have modal mouse input focus cancel the distribution. 786 if (mFocusHandler->getModalMouseInputFocused() != NULL 787 && !widget->isModalMouseInputFocused()) 788 { 789 break; 790 } 791 } 792 } 793 distributeKeyEvent(KeyEvent & keyEvent)794 void Gui::distributeKeyEvent(KeyEvent& keyEvent) 795 { 796 Widget* parent = keyEvent.getSource(); 797 Widget* widget = keyEvent.getSource(); 798 799 if (mFocusHandler->getModalFocused() != NULL 800 && !widget->isModalFocused()) 801 { 802 return; 803 } 804 805 if (mFocusHandler->getModalMouseInputFocused() != NULL 806 && !widget->isModalMouseInputFocused()) 807 { 808 return; 809 } 810 811 while (parent != NULL) 812 { 813 // If the widget has been removed due to input 814 // cancel the distribution. 815 if (!Widget::widgetExists(widget)) 816 { 817 break; 818 } 819 820 parent = (Widget*)widget->getParent(); 821 822 if (widget->isEnabled()) 823 { 824 std::list<KeyListener*> keyListeners = widget->_getKeyListeners(); 825 826 // Send the event to all key listeners of the source widget. 827 for (std::list<KeyListener*>::iterator it = keyListeners.begin(); 828 it != keyListeners.end(); 829 ++it) 830 { 831 switch (keyEvent.getType()) 832 { 833 case KeyEvent::PRESSED: 834 (*it)->keyPressed(keyEvent); 835 break; 836 case KeyEvent::RELEASED: 837 (*it)->keyReleased(keyEvent); 838 break; 839 default: 840 throw GCN_EXCEPTION("Unknown key event type."); 841 } 842 } 843 } 844 845 Widget* swap = widget; 846 widget = parent; 847 parent = (Widget*)swap->getParent(); 848 849 // If a non modal focused widget has been reach 850 // and we have modal focus cancel the distribution. 851 if (mFocusHandler->getModalFocused() != NULL 852 && !widget->isModalFocused()) 853 { 854 break; 855 } 856 } 857 } 858 distributeKeyEventToGlobalKeyListeners(KeyEvent & keyEvent)859 void Gui::distributeKeyEventToGlobalKeyListeners(KeyEvent& keyEvent) 860 { 861 KeyListenerListIterator it; 862 863 for (it = mKeyListeners.begin(); it != mKeyListeners.end(); it++) 864 { 865 switch (keyEvent.getType()) 866 { 867 case KeyEvent::PRESSED: 868 (*it)->keyPressed(keyEvent); 869 break; 870 case KeyEvent::RELEASED: 871 (*it)->keyReleased(keyEvent); 872 break; 873 default: 874 throw GCN_EXCEPTION("Unknown key event type."); 875 } 876 877 if (keyEvent.isConsumed()) 878 { 879 break; 880 } 881 } 882 } 883 handleModalMouseInputFocus()884 void Gui::handleModalMouseInputFocus() 885 { 886 // Check if modal mouse input focus has been gained by a widget. 887 if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus() 888 != mFocusHandler->getModalMouseInputFocused()) 889 && (mFocusHandler->getLastWidgetWithModalMouseInputFocus() == NULL)) 890 { 891 handleModalFocusGained(); 892 mFocusHandler->setLastWidgetWithModalMouseInputFocus(mFocusHandler->getModalMouseInputFocused()); 893 } 894 // Check if modal mouse input focus has been released. 895 else if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus() 896 != mFocusHandler->getModalMouseInputFocused()) 897 && (mFocusHandler->getLastWidgetWithModalMouseInputFocus() != NULL)) 898 { 899 handleModalFocusReleased(); 900 mFocusHandler->setLastWidgetWithModalMouseInputFocus(NULL); 901 } 902 } 903 handleModalFocus()904 void Gui::handleModalFocus() 905 { 906 // Check if modal focus has been gained by a widget. 907 if ((mFocusHandler->getLastWidgetWithModalFocus() 908 != mFocusHandler->getModalFocused()) 909 && (mFocusHandler->getLastWidgetWithModalFocus() == NULL)) 910 { 911 handleModalFocusGained(); 912 mFocusHandler->setLastWidgetWithModalFocus(mFocusHandler->getModalFocused()); 913 } 914 // Check if modal focus has been released. 915 else if ((mFocusHandler->getLastWidgetWithModalFocus() 916 != mFocusHandler->getModalFocused()) 917 && (mFocusHandler->getLastWidgetWithModalFocus() != NULL)) 918 { 919 handleModalFocusReleased(); 920 mFocusHandler->setLastWidgetWithModalFocus(NULL); 921 } 922 } 923 handleModalFocusGained()924 void Gui::handleModalFocusGained() 925 { 926 // Distribute an event to all widgets in the "widget with mouse" queue. 927 while (!mWidgetWithMouseQueue.empty()) 928 { 929 Widget* widget = mWidgetWithMouseQueue.front(); 930 931 if (Widget::widgetExists(widget)) 932 { 933 distributeMouseEvent(widget, 934 MouseEvent::EXITED, 935 mLastMousePressButton, 936 mLastMouseX, 937 mLastMouseY, 938 true, 939 true); 940 } 941 942 mWidgetWithMouseQueue.pop_front(); 943 } 944 945 mFocusHandler->setLastWidgetWithModalMouseInputFocus(mFocusHandler->getModalMouseInputFocused()); 946 } 947 handleModalFocusReleased()948 void Gui::handleModalFocusReleased() 949 { 950 // Check all widgets below the mouse to see if they are 951 // present in the "widget with mouse" queue. If a widget 952 // is not then it should be added and an entered event should 953 // be sent to it. 954 Widget* widget = getMouseEventSource(mLastMouseX, mLastMouseY); 955 Widget* parent = widget; 956 957 while (parent != NULL) 958 { 959 parent = (Widget*)widget->getParent(); 960 961 // Check if the widget is present in the "widget with mouse" queue. 962 bool widgetIsPresentInQueue = false; 963 std::deque<Widget*>::iterator iter; 964 for (iter = mWidgetWithMouseQueue.begin(); 965 iter != mWidgetWithMouseQueue.end(); 966 iter++) 967 { 968 if (*iter == widget) 969 { 970 widgetIsPresentInQueue = true; 971 break; 972 } 973 } 974 975 // Widget is not present, send an entered event and add 976 // it to the "widget with mouse" queue. 977 if (!widgetIsPresentInQueue 978 && Widget::widgetExists(widget)) 979 { 980 distributeMouseEvent(widget, 981 MouseEvent::ENTERED, 982 mLastMousePressButton, 983 mLastMouseX, 984 mLastMouseY, 985 false, 986 true); 987 mWidgetWithMouseQueue.push_front(widget); 988 } 989 990 Widget* swap = widget; 991 widget = parent; 992 parent = (Widget*)swap->getParent(); 993 } 994 } 995 } 996