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