1 /*********************************************************** 2 * Copyright (C) 1997, Be Inc. Copyright (C) 1999, Jake Hamby. 3 * 4 * This program is freely distributable without licensing fees 5 * and is provided without guarantee or warrantee expressed or 6 * implied. This program is -not- in the public domain. 7 * 8 * 9 * FILE: glutEvent.cpp 10 * 11 * DESCRIPTION: here it is, the BeOS GLUT event loop 12 ***********************************************************/ 13 14 /*********************************************************** 15 * Headers 16 ***********************************************************/ 17 #include <GL/glut.h> 18 #include "glutint.h" 19 #include "glutState.h" 20 #include "glutBlocker.h" 21 #include <stdio.h> 22 #include <stdlib.h> 23 24 #define MOUSE_WHEEL_UP 3 25 #define MOUSE_WHEEL_DOWN 4 26 27 /*********************************************************** 28 * CLASS: GLUTtimer 29 * 30 * DESCRIPTION: list of timer callbacks 31 ***********************************************************/ 32 struct GLUTtimer { 33 GLUTtimer *next; // list of timers 34 bigtime_t timeout; // time to be called 35 GLUTtimerCB func; // function to call 36 int value; // value 37 }; 38 39 /*********************************************************** 40 * Private variables 41 ***********************************************************/ 42 static GLUTtimer *__glutTimerList = 0; // list of timer callbacks 43 static GLUTtimer *freeTimerList = 0; 44 45 /*********************************************************** 46 * FUNCTION: glutTimerFunc (7.19) 47 * 48 * DESCRIPTION: register a new timer callback 49 ***********************************************************/ 50 void APIENTRY 51 glutTimerFunc(unsigned int interval, GLUTtimerCB timerFunc, int value) 52 { 53 GLUTtimer *timer, *other; 54 GLUTtimer **prevptr; 55 56 if (!timerFunc) 57 return; 58 59 if (freeTimerList) { 60 timer = freeTimerList; 61 freeTimerList = timer->next; 62 } else { 63 timer = new GLUTtimer(); 64 if (!timer) 65 __glutFatalError("out of memory."); 66 } 67 68 timer->func = timerFunc; 69 timer->value = value; 70 timer->next = NULL; 71 timer->timeout = system_time() + (interval*1000); // 1000 ticks in a millisecond 72 prevptr = &__glutTimerList; 73 other = *prevptr; 74 while (other && (other->timeout < timer->timeout)) { 75 prevptr = &other->next; 76 other = *prevptr; 77 } 78 timer->next = other; 79 *prevptr = timer; 80 } 81 82 /*********************************************************** 83 * FUNCTION: handleTimeouts 84 * 85 * DESCRIPTION: private function to handle outstanding timeouts 86 ***********************************************************/ 87 static void 88 handleTimeouts(void) 89 { 90 bigtime_t now; 91 GLUTtimer *timer; 92 93 /* Assumption is that __glutTimerList is already determined 94 to be non-NULL. */ 95 now = system_time(); 96 while (__glutTimerList->timeout <= now) { 97 timer = __glutTimerList; 98 if(gState.currentWindow) 99 gState.currentWindow->LockGL(); 100 timer->func(timer->value); 101 if(gState.currentWindow) 102 gState.currentWindow->UnlockGL(); 103 __glutTimerList = timer->next; 104 timer->next = freeTimerList; 105 freeTimerList = timer; 106 if (!__glutTimerList) 107 break; 108 } 109 } 110 111 112 /*********************************************************** 113 * FUNCTION: processEventsAndTimeouts 114 * 115 * DESCRIPTION: clear gBlock, then check all windows for events 116 ***********************************************************/ 117 static void 118 processEventsAndTimeouts(void) 119 { 120 gBlock.WaitEvent(); // if there is already an event, returns 121 // immediately, otherwise wait forever 122 gBlock.ClearEvents(); 123 124 if(gState.quitAll) 125 exit(0); // exit handler cleans up windows and quits nicely 126 127 if (gState.currentWindow) 128 gState.currentWindow->LockGL(); 129 for(int i=0; i<gState.windowListSize; i++) { 130 if (gState.windowList[i]) { 131 GlutWindow *win = gState.windowList[i]; 132 // NOTE: we can use win as a shortcut for gState.windowList[i] 133 // in callbacks, EXCEPT we need to check the original variable 134 // after each callback to make sure the window hasn't been destroyed 135 if (win->anyevents) { 136 win->anyevents = false; 137 if (win->reshapeEvent) { 138 win->reshapeEvent = false; 139 __glutSetWindow(win); 140 win->reshape(win->m_width, win->m_height); 141 } 142 if (!gState.windowList[i]) 143 continue; // window was destroyed by callback! 144 145 if (win->displayEvent) { 146 win->displayEvent = false; 147 __glutSetWindow(win); 148 win->display(); 149 } 150 if (!gState.windowList[i]) 151 continue; // window was destroyed by callback! 152 153 if (win->mouseEvent) { 154 win->mouseEvent = false; 155 __glutSetWindow(win); 156 if (win->mouse) { 157 gState.modifierKeys = win->modifierKeys; 158 win->mouse(win->button, win->mouseState, win->mouseX, win->mouseY); 159 gState.modifierKeys = ~0; 160 } 161 } 162 if (!gState.windowList[i]) 163 continue; // window was destroyed by callback! 164 165 if (win->menuEvent) { 166 win->menuEvent = false; 167 __glutSetWindow(win); 168 GlutMenu *menu = __glutGetMenuByNum(win->menuNumber); 169 if (menu) { 170 gState.currentMenu = menu; 171 menu->select(win->menuValue); 172 } 173 } 174 if (!gState.windowList[i]) 175 continue; // window was destroyed by callback! 176 177 if (win->statusEvent) { 178 win->statusEvent = false; 179 __glutSetWindow(win); 180 if (gState.menuStatus) { 181 gState.currentMenu = __glutGetMenuByNum(win->menuNumber); 182 gState.menuStatus(win->menuStatus, win->statusX, win->statusY); 183 } 184 } 185 if (!gState.windowList[i]) 186 continue; // window was destroyed by callback! 187 188 if (win->motionEvent) { 189 win->motionEvent = false; 190 __glutSetWindow(win); 191 if (win->motion) 192 win->motion(win->motionX, win->motionY); 193 } 194 if (!gState.windowList[i]) 195 continue; // window was destroyed by callback! 196 197 if (win->passiveEvent) { 198 win->passiveEvent = false; 199 __glutSetWindow(win); 200 if (win->passive) 201 win->passive(win->passiveX, win->passiveY); 202 } 203 if (!gState.windowList[i]) 204 continue; // window was destroyed by callback! 205 206 if (win->keybEvent) { 207 win->keybEvent = false; 208 __glutSetWindow(win); 209 if (win->keyboard) { 210 gState.modifierKeys = win->modifierKeys; 211 win->keyboard(win->key, win->keyX, win->keyY); 212 gState.modifierKeys = ~0; 213 } 214 } 215 if (!gState.windowList[i]) 216 continue; // window was destroyed by callback! 217 218 if (win->specialEvent) { 219 win->specialEvent = false; 220 __glutSetWindow(win); 221 if (win->special) { 222 gState.modifierKeys = win->modifierKeys; 223 win->special(win->specialKey, win->specialX, win->specialY); 224 gState.modifierKeys = ~0; 225 } 226 } 227 if (!gState.windowList[i]) 228 continue; // window was destroyed by callback! 229 230 if (win->keybUpEvent) { 231 win->keybUpEvent = false; 232 __glutSetWindow(win); 233 if (win->keyboardUp) { 234 gState.modifierKeys = win->modifierKeys; 235 win->keyboardUp(win->key, win->keyX, win->keyY); 236 gState.modifierKeys = ~0; 237 } 238 } 239 if (!gState.windowList[i]) 240 continue; // window was destroyed by callback! 241 242 if (win->specialUpEvent) { 243 win->specialUpEvent = false; 244 __glutSetWindow(win); 245 if (win->specialUp) { 246 gState.modifierKeys = win->modifierKeys; 247 win->specialUp(win->specialKey, win->specialX, win->specialY); 248 gState.modifierKeys = ~0; 249 } 250 } 251 if (!gState.windowList[i]) 252 continue; // window was destroyed by callback! 253 254 255 if (win->entryEvent) { 256 win->entryEvent = false; 257 __glutSetWindow(win); 258 if (win->entry) 259 win->entry(win->entryState); 260 } 261 if (!gState.windowList[i]) 262 continue; // window was destroyed by callback! 263 264 if (win->windowStatusEvent) { 265 win->windowStatusEvent = false; 266 __glutSetWindow(win); 267 if (win->windowStatus) 268 win->windowStatus(win->visState); 269 } 270 if (!gState.windowList[i]) 271 continue; // window was destroyed by callback! 272 } 273 } 274 } 275 if (gState.currentWindow) 276 gState.currentWindow->UnlockGL(); 277 278 // This code isn't necessary since BGLView automatically traps errors 279 #if 0 280 if(gState.debug) { 281 for(int i=0; i<gState.windowListSize; i++) { 282 if (gState.windowList[i]) { 283 gState.windowList[i]->LockGL(); 284 glutReportErrors(); 285 gState.windowList[i]->UnlockGL(); 286 } 287 } 288 } 289 #endif 290 if (__glutTimerList) { 291 handleTimeouts(); 292 } 293 } 294 295 /*********************************************************** 296 * FUNCTION: waitForSomething 297 * 298 * DESCRIPTION: use gBlock to wait for a new event or timeout 299 ***********************************************************/ 300 static void 301 waitForSomething(void) 302 { 303 bigtime_t timeout = __glutTimerList->timeout; 304 bigtime_t now = system_time(); 305 306 if (gBlock.PendingEvent()) 307 goto immediatelyHandleEvent; 308 309 if(timeout>now) 310 gBlock.WaitEvent(timeout-now); 311 if (gBlock.PendingEvent()) { 312 immediatelyHandleEvent: 313 processEventsAndTimeouts(); 314 } else { 315 if (__glutTimerList) 316 handleTimeouts(); 317 } 318 } 319 320 /*********************************************************** 321 * FUNCTION: idleWait 322 * 323 * DESCRIPTION: check for events, then call idle function 324 ***********************************************************/ 325 static void 326 idleWait(void) 327 { 328 if (gBlock.PendingEvent()) { 329 processEventsAndTimeouts(); 330 } else { 331 if (__glutTimerList) 332 handleTimeouts(); 333 } 334 /* Make sure idle func still exists! */ 335 if(gState.currentWindow) 336 gState.currentWindow->LockGL(); 337 if (gState.idle) { 338 gState.idle(); 339 } 340 if(gState.currentWindow) 341 gState.currentWindow->UnlockGL(); 342 } 343 344 /*********************************************************** 345 * FUNCTION: glutMainLoop (3.1) 346 * 347 * DESCRIPTION: enter the event processing loop 348 ***********************************************************/ 349 void glutMainLoop() 350 { 351 if (!gState.windowListSize) 352 __glutFatalUsage("main loop entered with no windows created."); 353 354 if(gState.currentWindow) 355 gState.currentWindow->UnlockGL(); 356 357 for (;;) { 358 if (gState.idle) { 359 idleWait(); 360 } else { 361 if (__glutTimerList) { 362 waitForSomething(); 363 } else { 364 processEventsAndTimeouts(); 365 } 366 } 367 } 368 } 369 370 371 void glutSetKeyRepeat(int repeatMode) 372 { 373 switch(repeatMode) { 374 case GLUT_KEY_REPEAT_DEFAULT: 375 gState.keyRepeatMode = GLUT_KEY_REPEAT_ON; 376 break; 377 378 case GLUT_KEY_REPEAT_ON: 379 case GLUT_KEY_REPEAT_OFF: 380 gState.keyRepeatMode = repeatMode; 381 break; 382 383 default: 384 __glutWarning("invalid glutSetKeyRepeat mode: %d", repeatMode); 385 } 386 } 387 388 389 void glutIgnoreKeyRepeat(int ignore) 390 { 391 if (gState.currentWindow) 392 gState.currentWindow->ignoreKeyRepeat = (ignore != 0); 393 } 394 395 396 /*********************************************************** 397 * CLASS: GlutWindow 398 * 399 * FUNCTION: KeyDown 400 * 401 * DESCRIPTION: handles keyboard and special events 402 ***********************************************************/ 403 void GlutWindow::KeyDown(const char *s, int32 slen) 404 { 405 ulong aChar = s[0]; 406 BGLView::KeyDown(s,slen); 407 408 BPoint p; 409 410 if (ignoreKeyRepeat 411 && Window()->CurrentMessage()->FindInt32("be:key_repeat") > 0) 412 return; 413 414 switch (aChar) { 415 case B_FUNCTION_KEY: 416 switch(Window()->CurrentMessage()->FindInt32("key")) { 417 case B_F1_KEY: 418 aChar = GLUT_KEY_F1; 419 goto specialLabel; 420 case B_F2_KEY: 421 aChar = GLUT_KEY_F2; 422 goto specialLabel; 423 case B_F3_KEY: 424 aChar = GLUT_KEY_F3; 425 goto specialLabel; 426 case B_F4_KEY: 427 aChar = GLUT_KEY_F4; 428 goto specialLabel; 429 case B_F5_KEY: 430 aChar = GLUT_KEY_F5; 431 goto specialLabel; 432 case B_F6_KEY: 433 aChar = GLUT_KEY_F6; 434 goto specialLabel; 435 case B_F7_KEY: 436 aChar = GLUT_KEY_F7; 437 goto specialLabel; 438 case B_F8_KEY: 439 aChar = GLUT_KEY_F8; 440 goto specialLabel; 441 case B_F9_KEY: 442 aChar = GLUT_KEY_F9; 443 goto specialLabel; 444 case B_F10_KEY: 445 aChar = GLUT_KEY_F10; 446 goto specialLabel; 447 case B_F11_KEY: 448 aChar = GLUT_KEY_F11; 449 goto specialLabel; 450 case B_F12_KEY: 451 aChar = GLUT_KEY_F12; 452 goto specialLabel; 453 default: 454 return; 455 } 456 case B_LEFT_ARROW: 457 aChar = GLUT_KEY_LEFT; 458 goto specialLabel; 459 case B_UP_ARROW: 460 aChar = GLUT_KEY_UP; 461 goto specialLabel; 462 case B_RIGHT_ARROW: 463 aChar = GLUT_KEY_RIGHT; 464 goto specialLabel; 465 case B_DOWN_ARROW: 466 aChar = GLUT_KEY_DOWN; 467 goto specialLabel; 468 case B_PAGE_UP: 469 aChar = GLUT_KEY_PAGE_UP; 470 goto specialLabel; 471 case B_PAGE_DOWN: 472 aChar = GLUT_KEY_PAGE_DOWN; 473 goto specialLabel; 474 case B_HOME: 475 aChar = GLUT_KEY_HOME; 476 goto specialLabel; 477 case B_END: 478 aChar = GLUT_KEY_END; 479 goto specialLabel; 480 case B_INSERT: 481 aChar = GLUT_KEY_INSERT; 482 specialLabel: 483 if (special) { 484 anyevents = specialEvent = true; 485 GetMouse(&p,&m_buttons); 486 specialKey = aChar; 487 specialX = (int)p.x; 488 specialY = (int)p.y; 489 goto setModifiers; // set the modifier variable 490 } 491 return; 492 493 default: 494 break; 495 } 496 497 if (keyboard) { 498 anyevents = keybEvent = true; 499 GetMouse(&p,&m_buttons); 500 key = aChar; 501 keyX = (int)p.x; 502 keyY = (int)p.y; 503 setModifiers: 504 modifierKeys = 0; 505 uint32 beMod = Window()->CurrentMessage()->FindInt32("modifiers"); 506 if(beMod & B_SHIFT_KEY) 507 modifierKeys |= GLUT_ACTIVE_SHIFT; 508 if(beMod & B_CONTROL_KEY) 509 modifierKeys |= GLUT_ACTIVE_CTRL; 510 if(beMod & B_OPTION_KEY) { 511 // since the window traps B_COMMAND_KEY, we'll have to settle 512 // for the option key.. but we need to get the raw character, 513 // not the Unicode-enhanced version 514 key = Window()->CurrentMessage()->FindInt32("raw_char"); 515 modifierKeys |= GLUT_ACTIVE_ALT; 516 } 517 gBlock.NewEvent(); 518 } 519 } 520 521 /*********************************************************** 522 * CLASS: GlutWindow 523 * 524 * FUNCTION: KeyUp 525 * 526 * DESCRIPTION: handles keyboard and special events 527 ***********************************************************/ 528 void GlutWindow::KeyUp(const char *s, int32 slen) 529 { 530 ulong aChar = s[0]; 531 BGLView::KeyUp(s,slen); 532 533 BPoint p; 534 535 switch (aChar) { 536 case B_FUNCTION_KEY: 537 switch(Window()->CurrentMessage()->FindInt32("key")) { 538 case B_F1_KEY: 539 aChar = GLUT_KEY_F1; 540 goto specialLabel; 541 case B_F2_KEY: 542 aChar = GLUT_KEY_F2; 543 goto specialLabel; 544 case B_F3_KEY: 545 aChar = GLUT_KEY_F3; 546 goto specialLabel; 547 case B_F4_KEY: 548 aChar = GLUT_KEY_F4; 549 goto specialLabel; 550 case B_F5_KEY: 551 aChar = GLUT_KEY_F5; 552 goto specialLabel; 553 case B_F6_KEY: 554 aChar = GLUT_KEY_F6; 555 goto specialLabel; 556 case B_F7_KEY: 557 aChar = GLUT_KEY_F7; 558 goto specialLabel; 559 case B_F8_KEY: 560 aChar = GLUT_KEY_F8; 561 goto specialLabel; 562 case B_F9_KEY: 563 aChar = GLUT_KEY_F9; 564 goto specialLabel; 565 case B_F10_KEY: 566 aChar = GLUT_KEY_F10; 567 goto specialLabel; 568 case B_F11_KEY: 569 aChar = GLUT_KEY_F11; 570 goto specialLabel; 571 case B_F12_KEY: 572 aChar = GLUT_KEY_F12; 573 goto specialLabel; 574 default: 575 return; 576 } 577 case B_LEFT_ARROW: 578 aChar = GLUT_KEY_LEFT; 579 goto specialLabel; 580 case B_UP_ARROW: 581 aChar = GLUT_KEY_UP; 582 goto specialLabel; 583 case B_RIGHT_ARROW: 584 aChar = GLUT_KEY_RIGHT; 585 goto specialLabel; 586 case B_DOWN_ARROW: 587 aChar = GLUT_KEY_DOWN; 588 goto specialLabel; 589 case B_PAGE_UP: 590 aChar = GLUT_KEY_PAGE_UP; 591 goto specialLabel; 592 case B_PAGE_DOWN: 593 aChar = GLUT_KEY_PAGE_DOWN; 594 goto specialLabel; 595 case B_HOME: 596 aChar = GLUT_KEY_HOME; 597 goto specialLabel; 598 case B_END: 599 aChar = GLUT_KEY_END; 600 goto specialLabel; 601 case B_INSERT: 602 aChar = GLUT_KEY_INSERT; 603 specialLabel: 604 if (specialUp!=0) { 605 anyevents = specialUpEvent = true; 606 GetMouse(&p,&m_buttons); 607 specialKey = aChar; 608 specialX = (int)p.x; 609 specialY = (int)p.y; 610 goto setModifiers; // set the modifier variable 611 } 612 return; 613 614 default: 615 break; 616 } 617 618 if (keyboardUp!=0) { 619 anyevents = keybUpEvent = true; 620 GetMouse(&p,&m_buttons); 621 key = aChar; 622 keyX = (int)p.x; 623 keyY = (int)p.y; 624 setModifiers: 625 modifierKeys = 0; 626 uint32 beMod = Window()->CurrentMessage()->FindInt32("modifiers"); 627 if(beMod & B_SHIFT_KEY) 628 modifierKeys |= GLUT_ACTIVE_SHIFT; 629 if(beMod & B_CONTROL_KEY) 630 modifierKeys |= GLUT_ACTIVE_CTRL; 631 if(beMod & B_OPTION_KEY) { 632 // since the window traps B_COMMAND_KEY, we'll have to settle 633 // for the option key.. but we need to get the raw character, 634 // not the Unicode-enhanced version 635 key = Window()->CurrentMessage()->FindInt32("raw_char"); 636 modifierKeys |= GLUT_ACTIVE_ALT; 637 } 638 gBlock.NewEvent(); 639 } 640 } 641 642 /*********************************************************** 643 * CLASS: GlutWindow 644 * 645 * FUNCTION: MouseDown 646 * 647 * DESCRIPTION: handles mouse and menustatus events 648 ***********************************************************/ 649 void GlutWindow::MouseDown(BPoint point) 650 { 651 BGLView::MouseDown(point); 652 MouseCheck(); 653 } 654 655 /*********************************************************** 656 * CLASS: GlutWindow 657 * 658 * FUNCTION: MouseCheck 659 * 660 * DESCRIPTION: checks for button state changes 661 ***********************************************************/ 662 void GlutWindow::MouseCheck() 663 { 664 if (mouseEvent) 665 return; // we already have an outstanding mouse event 666 667 BPoint point; 668 uint32 newButtons; 669 GetMouse(&point, &newButtons); 670 if (m_buttons != newButtons) { 671 if (newButtons&B_PRIMARY_MOUSE_BUTTON && !(m_buttons&B_PRIMARY_MOUSE_BUTTON)) { 672 button = GLUT_LEFT_BUTTON; 673 mouseState = GLUT_DOWN; 674 } else if (m_buttons&B_PRIMARY_MOUSE_BUTTON && !(newButtons&B_PRIMARY_MOUSE_BUTTON)) { 675 button = GLUT_LEFT_BUTTON; 676 mouseState = GLUT_UP; 677 } else if (newButtons&B_SECONDARY_MOUSE_BUTTON && !(m_buttons&B_SECONDARY_MOUSE_BUTTON)) { 678 button = GLUT_RIGHT_BUTTON; 679 mouseState = GLUT_DOWN; 680 } else if (m_buttons&B_SECONDARY_MOUSE_BUTTON && !(newButtons&B_SECONDARY_MOUSE_BUTTON)) { 681 button = GLUT_RIGHT_BUTTON; 682 mouseState = GLUT_UP; 683 } else if (newButtons&B_TERTIARY_MOUSE_BUTTON && !(m_buttons&B_TERTIARY_MOUSE_BUTTON)) { 684 button = GLUT_MIDDLE_BUTTON; 685 mouseState = GLUT_DOWN; 686 } else if (m_buttons&B_TERTIARY_MOUSE_BUTTON && !(newButtons&B_TERTIARY_MOUSE_BUTTON)) { 687 button = GLUT_MIDDLE_BUTTON; 688 mouseState = GLUT_UP; 689 } 690 } else { 691 return; // no change, return 692 } 693 m_buttons = newButtons; 694 695 if (mouseState == GLUT_DOWN) { 696 BWindow *w = Window(); 697 GlutMenu *m = __glutGetMenuByNum(menu[button]); 698 if (m) { 699 if (gState.menuStatus) { 700 anyevents = statusEvent = true; 701 menuNumber = menu[button]; 702 menuStatus = GLUT_MENU_IN_USE; 703 statusX = (int)point.x; 704 statusY = (int)point.y; 705 gBlock.NewEvent(); 706 } 707 BRect bounds = w->Frame(); 708 point.x += bounds.left; 709 point.y += bounds.top; 710 GlutPopUp *bmenu = static_cast<GlutPopUp*>(m->CreateBMenu()); // start menu 711 bmenu->point = point; 712 bmenu->win = this; 713 thread_id menu_thread = spawn_thread(MenuThread, "menu thread", B_NORMAL_PRIORITY, bmenu); 714 resume_thread(menu_thread); 715 return; 716 } 717 } 718 719 if (mouse) { 720 anyevents = mouseEvent = true; 721 mouseX = (int)point.x; 722 mouseY = (int)point.y; 723 modifierKeys = 0; 724 uint32 beMod = modifiers(); 725 if(beMod & B_SHIFT_KEY) 726 modifierKeys |= GLUT_ACTIVE_SHIFT; 727 if(beMod & B_CONTROL_KEY) 728 modifierKeys |= GLUT_ACTIVE_CTRL; 729 if(beMod & B_OPTION_KEY) { 730 modifierKeys |= GLUT_ACTIVE_ALT; 731 } 732 gBlock.NewEvent(); 733 } 734 } 735 736 /*********************************************************** 737 * CLASS: GlutWindow 738 * 739 * FUNCTION: MouseMoved 740 * 741 * DESCRIPTION: handles entry, motion, and passive events 742 ***********************************************************/ 743 void GlutWindow::MouseMoved(BPoint point, 744 uint32 transit, const BMessage *msg) 745 { 746 BGLView::MouseMoved(point,transit,msg); 747 748 if(transit != B_INSIDE_VIEW) { 749 if (entry) { 750 anyevents = entryEvent = true; 751 gBlock.NewEvent(); 752 } 753 if (transit == B_ENTERED_VIEW) { 754 entryState = GLUT_ENTERED; 755 MakeFocus(); // make me the current focus 756 __glutSetCursor(cursor); 757 } else 758 entryState = GLUT_LEFT; 759 } 760 761 MouseCheck(); 762 if(m_buttons) { 763 if(motion) { 764 anyevents = motionEvent = true; 765 motionX = (int)point.x; 766 motionY = (int)point.y; 767 gBlock.NewEvent(); 768 } 769 } else { 770 if(passive) { 771 anyevents = passiveEvent = true; 772 passiveX = (int)point.x; 773 passiveY = (int)point.y; 774 gBlock.NewEvent(); 775 } 776 } 777 } 778 779 /*********************************************************** 780 * CLASS: GlutWindow 781 * 782 * FUNCTION: MessageReceived 783 * 784 * DESCRIPTION: handles mouse wheel events 785 ***********************************************************/ 786 787 void GlutWindow::MessageReceived(BMessage *message) 788 { 789 switch(message->what){ 790 case B_MOUSE_WHEEL_CHANGED: 791 { 792 float shift=0; 793 if(message->FindFloat("be:wheel_delta_y",&shift)==B_OK) { 794 if(shift>0)button = MOUSE_WHEEL_UP; 795 if(shift<0)button = MOUSE_WHEEL_DOWN; 796 if(shift!=0) { 797 anyevents = mouseEvent = true; 798 gBlock.NewEvent(); 799 } 800 } 801 break; 802 } 803 default: 804 BGLView::MessageReceived(message); 805 break; 806 } 807 } 808 809 /*********************************************************** 810 * CLASS: GlutWindow 811 * 812 * FUNCTION: FrameResized 813 * 814 * DESCRIPTION: handles reshape event 815 ***********************************************************/ 816 void GlutWindow::FrameResized(float width, float height) 817 { 818 BGLView::FrameResized(width, height); 819 if (visible) { 820 anyevents = reshapeEvent = true; 821 m_width = (int)(width)+1; 822 m_height = (int)(height)+1; 823 gBlock.NewEvent(); 824 } 825 } 826 827 /*********************************************************** 828 * CLASS: GlutWindow 829 * 830 * FUNCTION: Draw 831 * 832 * DESCRIPTION: handles reshape and display events 833 ***********************************************************/ 834 void GlutWindow::Draw(BRect updateRect) 835 { 836 BGLView::Draw(updateRect); 837 BRect frame = Frame(); 838 if (m_width != (frame.Width()+1) || m_height != (frame.Height()+1)) { 839 FrameResized(frame.Width(), frame.Height()); 840 } 841 Window()->Lock(); 842 if (visible) { 843 anyevents = displayEvent = true; 844 gBlock.NewEvent(); 845 } 846 Window()->Unlock(); 847 } 848 849 /*********************************************************** 850 * CLASS: GlutWindow 851 * 852 * FUNCTION: Pulse 853 * 854 * DESCRIPTION: handles mouse up event (MouseUp is broken) 855 ***********************************************************/ 856 void GlutWindow::Pulse() 857 { 858 BGLView::Pulse(); 859 if (m_buttons) { // if there are buttons pressed 860 MouseCheck(); 861 } 862 } 863 864 /*********************************************************** 865 * CLASS: GlutWindow 866 * 867 * FUNCTION: ErrorCallback 868 * 869 * DESCRIPTION: handles GL error messages 870 ***********************************************************/ 871 void GlutWindow::ErrorCallback(unsigned long errorCode) { 872 __glutWarning("GL error: %s", gluErrorString(errorCode)); 873 } 874 875 /*********************************************************** 876 * CLASS: GlutWindow 877 * 878 * FUNCTION: MenuThread 879 * 880 * DESCRIPTION: a new thread to launch popup menu, wait 881 * wait for response, then clean up afterwards and 882 * send appropriate messages 883 ***********************************************************/ 884 status_t GlutWindow::MenuThread(void *m) { 885 GlutPopUp *bmenu = static_cast<GlutPopUp*>(m); 886 GlutWindow *win = bmenu->win; // my window 887 GlutBMenuItem *result = (GlutBMenuItem*)bmenu->Go(bmenu->point); 888 win->Window()->Lock(); 889 win->anyevents = win->statusEvent = true; 890 win->menuStatus = GLUT_MENU_NOT_IN_USE; 891 win->menuNumber = bmenu->menu; 892 BPoint cursor; 893 uint32 buttons; 894 win->GetMouse(&cursor, &buttons); 895 win->statusX = (int)cursor.x; 896 win->statusY = (int)cursor.y; 897 if(result && result->menu) { 898 win->menuEvent = true; 899 win->menuNumber = result->menu; // in case it was a submenu 900 win->menuValue = result->value; 901 } 902 win->Window()->Unlock(); 903 gBlock.NewEvent(); 904 delete bmenu; 905 return B_OK; 906 } 907