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