00001 #include "application.h"
00002 #include "console.h"
00003 #include "event.h"
00004 #include "eventhandler.h"
00005 #include "hotspot.h"
00006 #include <string.h>
00007 #include <malloc.h>
00008 #include <gccore.h>
00009 #include <ogcsys.h>
00010 #include <wiiuse/wpad.h>
00011 #include <algorithm>
00012 #include <iterator>
00013 #include <vector>
00014
00015 namespace wit {
00016
00017
00018 struct Sans16_Registrar { Sans16_Registrar(); };
00019 struct Sans16_B_Registrar { Sans16_B_Registrar(); };
00020 struct Sans16_I_Registrar { Sans16_I_Registrar(); };
00021 struct Sans16_B_I_Registrar { Sans16_B_I_Registrar(); };
00022
00023
00078 struct EventHandlerNode {
00079 EventHandler* handler;
00080 int controllerID;
00081 EventHandlerNode* next;
00082 };
00083
00084 struct TimerNode {
00085 EventHandler* handler;
00086 int framesRemaining;
00087 void* data;
00088 TimerNode* next;
00089 };
00090
00091 class ApplicationPrivate {
00092 friend class Application;
00093 public:
00094 int features, screenWidth, powerControllerID;
00095 bool currentBuffer, doShutdown, doReset, doPower, abortGxOnReset;
00096 bool autoHomeMenu, homeMenuOpen;
00097 GXRModeObj videoMode;
00098 void* framebuffer[2];
00099 void* gxfifo;
00100 Console* console;
00101 EventHandlerNode* focus;
00102 EventHandlerNode* eventFilters;
00103 TimerNode* timers;
00104 TimerNode* addTimers;
00105 };
00106
00107 static Application* witInstance = 0;
00108 static ApplicationPrivate* witPrivate = 0;
00110 void wit_render_all();
00111
00112 static void wit_power_button_callback()
00113 {
00114 witPrivate->doPower = true;
00115 witPrivate->powerControllerID = -1;
00116 if(witPrivate->features & UseGX && witPrivate->abortGxOnReset) GX_AbortFrame();
00117 }
00118
00119 static void wit_reset_button_callback()
00120 {
00121 witPrivate->doReset = true;
00122 if(witPrivate->features & UseGX && witPrivate->abortGxOnReset) GX_AbortFrame();
00123 }
00124
00125 static void wit_remote_power_button_callback(int id)
00126 {
00127 witPrivate->doPower = true;
00128 witPrivate->powerControllerID = id;
00129 if(witPrivate->features & UseGX && witPrivate->abortGxOnReset) GX_AbortFrame();
00130 }
00131
00135 Application::Application(int features)
00136 {
00137
00138 witInstance = this;
00139 witPrivate = d = new ApplicationPrivate;
00140 memset(d, 0, sizeof(ApplicationPrivate));
00141 d->features = features;
00142 d->abortGxOnReset = true;
00143
00144
00145 VIDEO_Init();
00146 VIDEO_GetPreferredMode(&d->videoMode);
00147 if(CONF_GetAspectRatio() == CONF_ASPECT_16_9) {
00148 d->videoMode.viWidth = VI_MAX_WIDTH_PAL - 12;
00149 d->videoMode.viXOrigin = 8;
00150 }
00151 VIDEO_Configure(&d->videoMode);
00152 d->framebuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(&d->videoMode));
00153 VIDEO_ClearFrameBuffer(&d->videoMode, d->framebuffer[0], 0x800080);
00154 if(features & UseDoubleBuffer) {
00155 d->framebuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(&d->videoMode));
00156 VIDEO_ClearFrameBuffer(&d->videoMode, d->framebuffer[1], 0x800080);
00157 }
00158 d->currentBuffer = false;
00159 VIDEO_SetNextFramebuffer(d->framebuffer[0]);
00160 VIDEO_SetBlack(false);
00161 VIDEO_Flush();
00162
00163 if(features & UseWiiRemote) {
00164 WPAD_Init();
00165 for(int i = 0; i < WPAD_MAX_WIIMOTES; i++) {
00166 if(features & UsePointer) {
00167 WPAD_SetDataFormat(i, WPAD_FMT_BTNS_ACC_IR);
00168 WPAD_SetVRes(i, d->videoMode.fbWidth, d->videoMode.xfbHeight);
00169 } else if(features & UseMotion) {
00170 WPAD_SetDataFormat(i, WPAD_FMT_BTNS_ACC);
00171 }
00172 }
00173 }
00174
00175 if(features & UseGameCube) {
00176 PAD_Init();
00177 }
00178
00179 if(features & UseSound) {
00180
00181 }
00182
00183 if(features & UseFAT) {
00184
00185 }
00186
00187 VIDEO_WaitVSync();
00188 if(d->videoMode.viTVMode & VI_NON_INTERLACE)
00189 VIDEO_WaitVSync();
00190
00191 if(features & UseGX) {
00192 d->gxfifo = memalign(262144, 32);
00193 memset(d->gxfifo, 0, 262144);
00194 GX_Init(d->gxfifo, 262144);
00195 GX_SetBlendMode(GX_BM_BLEND,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
00196 GX_SetCopyClear((GXColor){ 0, 0, 0, 0xFF }, 0xFFFFFF);
00197 GX_SetViewport(0, 0, d->videoMode.fbWidth, d->videoMode.efbHeight, 0, 1);
00198 GX_SetScissor(0, 0, d->videoMode.fbWidth, d->videoMode.efbHeight);
00199 GX_SetDispCopyGamma(GX_GM_1_0);
00200 GX_SetCullMode(GX_CULL_NONE);
00201 GX_SetDispCopyDst(d->videoMode.fbWidth, GX_SetDispCopyYScale(GX_GetYScaleFactor(d->videoMode.efbHeight,d->videoMode.xfbHeight)));
00202 GX_SetCopyFilter(d->videoMode.aa, d->videoMode.sample_pattern, GX_TRUE, d->videoMode.vfilter);
00203 GX_SetVtxAttrFmt(GX_VTXFMT7, GX_VA_POS, GX_POS_XY, GX_F32, 0);
00204 GX_SetVtxAttrFmt(GX_VTXFMT7, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
00205 GX_SetVtxAttrFmt(GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
00206 if(d->videoMode.aa)
00207 GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR);
00208 else
00209 GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
00210
00211
00212 Sans16_Registrar s16r;
00213
00214
00215
00216 }
00217
00218 if(features & UseConsole) {
00219 d->console = new Console(&d->videoMode);
00220 } else {
00221 d->console = 0;
00222 }
00223
00224
00225 SYS_SetResetCallback(wit_reset_button_callback);
00226 SYS_SetPowerCallback(wit_power_button_callback);
00227 if(features & UseWiiRemote)
00228 WPAD_SetPowerButtonCallback(wit_remote_power_button_callback);
00229 }
00230
00234 Application::~Application()
00235 {
00236
00237 if(d->features & UseGX) {
00238 GX_AbortFrame();
00239 GX_Flush();
00240 }
00241 VIDEO_Flush();
00242
00243
00244 EventHandlerNode* next;
00245 while(d->focus) {
00246 next = d->focus->next;
00247 delete d->focus;
00248 d->focus = next;
00249 }
00250 while(d->eventFilters) {
00251 next = d->eventFilters->next;
00252 delete d->eventFilters;
00253 d->eventFilters = next;
00254 }
00255 TimerNode* nextTimer;
00256 while(d->timers) {
00257 nextTimer = d->timers->next;
00258 delete d->timers;
00259 d->timers = nextTimer;
00260 }
00261 while(d->addTimers) {
00262 nextTimer = d->addTimers->next;
00263 delete d->addTimers;
00264 d->addTimers = nextTimer;
00265 }
00266 delete d->console;
00267 free(d->gxfifo);
00268 delete d;
00269 }
00270
00276 Application* Application::instance()
00277 {
00278 return witInstance;
00279 }
00280
00285 Console* Application::console() const
00286 {
00287 return d->console;
00288 }
00289
00294 int Application::features() const
00295 {
00296 return d->features;
00297 }
00298
00302 void* Application::framebuffer() const
00303 {
00304 return d->framebuffer[d->currentBuffer ? 1 : 0];
00305 }
00306
00310 int Application::screenWidth() const
00311 {
00312 return d->videoMode.fbWidth;
00313 }
00314
00318 int Application::screenHeight() const
00319 {
00320 return d->videoMode.xfbHeight;
00321 }
00322
00332 void Application::setAutoHomeMenu(bool on)
00333 {
00334 d->autoHomeMenu = on;
00335 }
00336
00344 bool Application::autoHomeMenu() const
00345 {
00346 return d->autoHomeMenu;
00347 }
00348
00368 void Application::showHomeMenu()
00369 {
00370 setHomeMenuVisible(true);
00371 }
00372
00381 void Application::hideHomeMenu()
00382 {
00383 setHomeMenuVisible(false);
00384 }
00385
00394 void Application::homeMenuEvent(Event* event)
00395 {
00396
00397 }
00398
00406 void Application::setHomeMenuVisible(bool on)
00407 {
00408
00409 d->homeMenuVisible = on;
00410 }
00411
00418 bool Application::isHomeMenuVisible() const
00419 {
00420 return d->homeMenuVisible;
00421 }
00422
00426 void Application::reboot()
00427 {
00428 d->doShutdown = true;
00429 SYS_ResetSystem(SYS_RESTART, 0, 0);
00430 }
00431
00440 void Application::shutdown(ShutdownMode mode)
00441 {
00442 d->doShutdown = true;
00443 if(mode == Shutdown_Idle)
00444 SYS_ResetSystem(SYS_POWEROFF_IDLE, 0, 0);
00445 else if(mode == Shutdown_Standby)
00446 SYS_ResetSystem(SYS_POWEROFF_STANDBY, 0, 0);
00447 else
00448 SYS_ResetSystem(SYS_POWEROFF, 0, 0);
00449 }
00450
00454 void Application::returnToMenu()
00455 {
00456 d->doShutdown = true;
00457 SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
00458 }
00459
00463 void Application::quit()
00464 {
00465 d->doShutdown = true;
00466 }
00467
00468 static void wit_Application_wpad_cb(s32 chan, const WPADData* data)
00469 {
00470 static const unsigned int remoteMap[] = {
00471 0, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, WPAD_BUTTON_1, WPAD_BUTTON_2,
00472 WPAD_BUTTON_A, WPAD_BUTTON_B, 0, 0, 0, 0, 0, 0, 0, 0, WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS, WPAD_BUTTON_HOME, 0
00473 };
00474 static const unsigned int nunchukMap[] = {
00475 0, 0, 0, 0, 0, 0, 0, 0, 0, WPAD_NUNCHUK_BUTTON_C, 0, 0, WPAD_NUNCHUK_BUTTON_Z, 0, 0, 0, 0, 0, 0, 0, 0
00476 };
00477 static const unsigned int classicMap[] = {
00478 0, WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_DOWN, WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_RIGHT,
00479 0, 0, WPAD_CLASSIC_BUTTON_A, WPAD_CLASSIC_BUTTON_B, 0, WPAD_CLASSIC_BUTTON_X, WPAD_CLASSIC_BUTTON_Y, 0,
00480 WPAD_CLASSIC_BUTTON_ZL, WPAD_CLASSIC_BUTTON_ZR, WPAD_CLASSIC_BUTTON_FULL_L, WPAD_CLASSIC_BUTTON_FULL_R,
00481 WPAD_CLASSIC_BUTTON_MINUS, WPAD_CLASSIC_BUTTON_PLUS, WPAD_CLASSIC_BUTTON_HOME, 0
00482 };
00483 static const unsigned int guitarMap[] = {
00484 0, WPAD_GUITAR_HERO_3_BUTTON_STRUM_UP, WPAD_GUITAR_HERO_3_BUTTON_STRUM_DOWN, 0, 0,
00485 WPAD_GUITAR_HERO_3_BUTTON_YELLOW, WPAD_GUITAR_HERO_3_BUTTON_GREEN, WPAD_GUITAR_HERO_3_BUTTON_BLUE,
00486 WPAD_GUITAR_HERO_3_BUTTON_RED, WPAD_GUITAR_HERO_3_BUTTON_ORANGE, 0, 0, 0, 0, 0, 0, 0,
00487 WPAD_GUITAR_HERO_3_BUTTON_MINUS, WPAD_GUITAR_HERO_3_BUTTON_PLUS, 0, 0
00488 };
00489
00490 int features = witInstance->features();
00491
00492 if(data->btns_d ^ data->btns_u) {
00493 for(int i = 1; i < Button_Max; i++) {
00494 if(data->btns_d & remoteMap[i])
00495 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, WiiRemote, chan, i));
00496 else if(data->btns_u & remoteMap[i])
00497 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, WiiRemote, chan, i));
00498
00499 if(data->exp.type == WPAD_EXP_NUNCHUK && data->exp.nunchuk.btns & nunchukMap[i])
00500 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, Nunchuk, chan, i));
00501 else if(data->exp.type == WPAD_EXP_NUNCHUK && data->exp.nunchuk.btns_released & nunchukMap[i])
00502 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, Nunchuk, chan, i));
00503
00504 if(data->exp.type == WPAD_EXP_CLASSIC && data->exp.classic.btns & classicMap[i])
00505 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, Classic, chan, i));
00506 else if(data->exp.type == WPAD_EXP_CLASSIC && data->exp.classic.btns_released & classicMap[i])
00507 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, Classic, chan, i));
00508
00509 if(data->exp.type == WPAD_EXP_GUITARHERO3 && data->exp.gh3.btns & guitarMap[i])
00510 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, Guitar, chan, i));
00511 else if(data->exp.type == WPAD_EXP_GUITARHERO3 && data->exp.gh3.btns_released & guitarMap[i])
00512 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, Guitar, chan, i));
00513 }
00514 }
00515
00516 if(features & UseJoysticks) {
00517
00518 if(data->exp.type == WPAD_EXP_NUNCHUK) {
00519 JoystickEvent* stickEvent = new JoystickEvent(Nunchuk, chan);
00520 stickEvent->setByAngle(data->exp.nunchuk.js.ang, data->exp.nunchuk.js.mag);
00521 witInstance->postEvent(stickEvent);
00522 } else if(data->exp.type == WPAD_EXP_GUITARHERO3) {
00523 JoystickEvent* stickEvent = new JoystickEvent(Guitar, chan);
00524 stickEvent->setByAngle(data->exp.gh3.js.ang, data->exp.gh3.js.mag);
00525 witInstance->postEvent(stickEvent);
00526 witInstance->postEvent(new AnalogEvent(Guitar, chan, Analog_Whammy, data->exp.gh3.whammy_bar));
00527 } else if(data->exp.type == WPAD_EXP_CLASSIC) {
00528 JoystickEvent* stickEvent = new JoystickEvent(Classic, chan);
00529 stickEvent->setByAngle(data->exp.classic.ljs.ang, data->exp.classic.ljs.mag);
00530 witInstance->postEvent(stickEvent);
00531 stickEvent = new JoystickEvent(Classic, chan, true);
00532 stickEvent->setByAngle(data->exp.classic.rjs.ang, data->exp.classic.rjs.mag);
00533 witInstance->postEvent(stickEvent);
00534 witInstance->postEvent(new AnalogEvent(Classic, chan, Analog_Left, data->exp.classic.l_shoulder));
00535 witInstance->postEvent(new AnalogEvent(Classic, chan, Analog_Right, data->exp.classic.r_shoulder));
00536 }
00537 }
00538
00539 if(features & UsePointer) {
00540 if(data->ir.valid) {
00541 witInstance->postEvent(new PointerEvent(chan, data->ir.x, data->ir.y, data->ir.z));
00542 } else {
00543 witInstance->postEvent(new PointerEvent(chan, -1.0f, -1.0f, -1.0f));
00544 }
00545 }
00546
00547 if(features & UseMotion) {
00548 float x = data->accel.x / 1024.0;
00549 float y = data->accel.y / 1024.0;
00550 float z = data->accel.z / 1024.0;
00551 witInstance->postEvent(new MotionEvent(WiiRemote, chan, x, y, z, data->orient.pitch, data->orient.roll));
00552 if(data->exp.type == WPAD_EXP_NUNCHUK) {
00553 x = data->exp.nunchuk.accel.x / 1024.0;
00554 y = data->exp.nunchuk.accel.y / 1024.0;
00555 z = data->exp.nunchuk.accel.z / 1024.0;
00556 witInstance->postEvent(new MotionEvent(Nunchuk, chan, x, y, z, data->exp.nunchuk.orient.pitch, data->exp.nunchuk.orient.roll));
00557 }
00558
00559
00560
00561
00562
00563
00564
00565 }
00566 }
00567
00568 static void wit_Application_gcpad_cb(s32 chan, const PADStatus* data)
00569 {
00570 static const unsigned int gcMap[] = {
00571 0, PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT, 0, 0,
00572 PAD_BUTTON_A, PAD_BUTTON_B, 0, PAD_BUTTON_X, PAD_BUTTON_Y, PAD_TRIGGER_Z, 0, 0,
00573 PAD_TRIGGER_L, PAD_TRIGGER_R, 0, 0, 0, PAD_BUTTON_START
00574 };
00575
00576 static u16 oldbuttons[PAD_CHANMAX] = { 0, 0, 0, 0 };
00577
00578 if(data->err == PAD_ERR_NO_CONTROLLER) return;
00579
00580 int features = witInstance->features();
00581
00582 if(data->button != oldbuttons[chan]) {
00583 u16 changed = (data->button ^ oldbuttons[chan]);
00584 u16 press = changed & data->button;
00585 u16 release = changed & oldbuttons[chan];
00586 oldbuttons[chan] = data->button;
00587 for(int i = 0; i < Button_Max; i++) {
00588 if(press & gcMap[i]) {
00589 witInstance->postEvent(new ButtonEvent(Event::ButtonPress, GameCube, chan+4, i));
00590 } else if(release & gcMap[i]) {
00591 witInstance->postEvent(new ButtonEvent(Event::ButtonRelease, GameCube, chan+4, i));
00592 }
00593 }
00594 }
00595
00596 if(features & UseJoysticks) {
00597
00598 JoystickEvent* stickEvent = new JoystickEvent(GameCube, chan+4);
00599 stickEvent->setByPosition(data->stickX, data->stickY);
00600 witInstance->postEvent(stickEvent);
00601 stickEvent = new JoystickEvent(GameCube, chan+4, true);
00602 stickEvent->setByPosition(data->substickX, data->substickY);
00603 witInstance->postEvent(stickEvent);
00604 witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_Left, data->triggerL / 256.0f));
00605 witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_Right, data->triggerR / 256.0f));
00606 witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_A, data->analogA / 256.0f));
00607 witInstance->postEvent(new AnalogEvent(GameCube, chan+4, Analog_B, data->analogB / 256.0f));
00608 }
00609 }
00610
00611 static inline bool doStop() { return witPrivate->doShutdown || witPrivate->doPower || witPrivate->doReset; }
00612
00620 void Application::run()
00621 {
00622
00623
00624 PADStatus gcpad[PAD_CHANMAX];
00625 WPADData wpadData;
00626
00627 d->doShutdown = false;
00628 while(!d->doShutdown) {
00629
00630 if(!doStop() && d->features & UseWiiRemote) {
00631 for(int i = WPAD_CHAN_0; !doStop() && i < WPAD_MAX_WIIMOTES; i++) {
00632 while(!doStop() && WPAD_ReadEvent(i, &wpadData) >= WPAD_ERR_NONE)
00633 wit_Application_wpad_cb(i, &wpadData);
00634 }
00635 }
00636
00637
00638 if(!doStop() && d->features & UseGameCube) {
00639 PAD_Read(gcpad);
00640 for(int i = 0; !doStop() && i < PAD_CHANMAX; i++) {
00641 wit_Application_gcpad_cb(i, &gcpad[i]);
00642 }
00643 }
00644
00645
00646 if(d->doPower) {
00647 powerButtonPressed(d->powerControllerID);
00648 d->doPower = false;
00649 } else if(d->doReset) {
00650 resetButtonPressed();
00651 d->doReset = false;
00652 }
00653
00654
00655 wit_render_all();
00656 if(!d->doShutdown) {
00657 if(d->features & UseGX) {
00658 GX_DrawDone();
00659 GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
00660 GX_Flush();
00661 GX_CopyDisp(framebuffer(),GX_TRUE);
00662 }
00663 if(d->features & UseDoubleBuffer) {
00664 VIDEO_SetNextFramebuffer(framebuffer());
00665 VIDEO_Flush();
00666 d->currentBuffer = !d->currentBuffer;
00667 if(d->features & UseConsole)
00668 console()->setFramebuffer(framebuffer());
00669 } else {
00670 VIDEO_Flush();
00671 }
00672
00673
00674 if(!d->homeMenuVisible) {
00675
00676 if(d->addTimers) {
00677
00678 TimerNode* timer = d->addTimers;
00679 while(timer->next) timer = timer->next;
00680 timer->next = d->timers;
00681 d->timers = d->addTimers;
00682 d->addTimers = 0;
00683 }
00684
00685
00686 TimerNode* timer = d->timers;
00687 TimerNode* previousTimer = 0;
00688 TimerNode* nextTimer;
00689 while(timer) {
00690 if(--timer->framesRemaining < 0) {
00691 timer->handler->timerTriggered(timer->data);
00692 if(previousTimer) {
00693 previousTimer->next = timer->next;
00694 } else {
00695 d->timers = timer->next;
00696 }
00697 nextTimer = timer->next;
00698 delete timer;
00699 timer = nextTimer;
00700 } else {
00701 previousTimer = timer;
00702 timer = timer->next;
00703 }
00704 }
00705
00706
00707 if(previousTimer) {
00708 previousTimer->next = d->addTimers;
00709 } else {
00710 d->timers = d->addTimers;
00711 }
00712 d->addTimers = 0;
00713 }
00714
00715 VIDEO_WaitVSync();
00716 }
00717 }
00718 }
00719
00720 static bool wit_Application_distribute_event(Event* event, EventHandlerNode* node)
00721 {
00722 while(node) {
00723 bool cancel = node->handler->event(event);
00724 if(cancel) return true;
00725 node = node->next;
00726 }
00727 return false;
00728 }
00729
00730 static HotspotList lastHotspots[4];
00731
00761 void Application::postEvent(Event* event)
00762 {
00763 if(d->homeMenuVisible) {
00764 homeMenuEvent(event);
00765 delete event;
00766 return;
00767 }
00768
00769 if(wit_Application_distribute_event(event, d->eventFilters)) {
00770 delete event;
00771 return;
00772 }
00773
00774 if(event->type() == Event::Pointer) {
00775 PointerEvent* p = static_cast<PointerEvent*>(event);
00776 if(p->isValid()) {
00777 Hotspot* hs;
00778 std::auto_ptr<HotspotList> spots = Hotspot::findAtPoint(p->x, p->y);
00779 std::sort(spots->begin(), spots->end());
00780 HotspotList lostFocus;
00781 std::set_difference(lastHotspots[p->controllerNumber].begin(), lastHotspots[p->controllerNumber].end(), spots->begin(), spots->end(), std::back_inserter(lostFocus));
00782 lastHotspots[p->controllerNumber] = *spots;
00783 if(lostFocus.size() > 0) {
00784 Hotspot** end = &lostFocus.back();
00785 for(Hotspot** iter = &lostFocus.front(); iter <= end; iter++) {
00786 hs = *iter;
00787 PointerLeaveEvent leaveEvent(p->controllerNumber, hs);
00788 if(!wit_Application_distribute_event(&leaveEvent, d->eventFilters) && hs->eventHandler())
00789 hs->eventHandler()->event(&leaveEvent);
00790 }
00791 }
00792 if(spots->size() > 0) {
00793 Hotspot** end = &spots->back();
00794 Hotspot* receiver = 0;
00795 for(Hotspot** iter = &spots->front(); iter <= end; iter++) {
00796 hs = *iter;
00797 if(!hs->eventHandler()) continue;
00798 if(receiver && hs->zIndex() < receiver->zIndex()) continue;
00799 receiver = hs;
00800 }
00801 if(receiver)
00802 receiver->eventHandler()->event(event);
00803 }
00804 }
00805 } else {
00806 wit_Application_distribute_event(event, d->focus);
00807 }
00808 delete event;
00809 }
00810
00820 void Application::pushFocus(EventHandler* handler, int controllerID)
00821 {
00822 EventHandlerNode* node = new EventHandlerNode;
00823 node->controllerID = controllerID;
00824 node->handler = handler;
00825 node->next = d->focus;
00826 d->focus = node;
00827 }
00828
00837 EventHandler* Application::currentFocus(int controllerID) const
00838 {
00839 if(!d->focus) return 0;
00840 EventHandlerNode* node = d->focus;
00841 while(node) {
00842 if(node->controllerID == controllerID || node->controllerID == -1)
00843 return node->handler;
00844 node = node->next;
00845 }
00846 return 0;
00847 }
00848
00857 EventHandler* Application::popFocus(int controllerID)
00858 {
00859 if(!d->focus) return 0;
00860 EventHandlerNode* node = d->focus;
00861 EventHandlerNode* lastNode = 0;
00862 while(node) {
00863 if(node->controllerID == controllerID) {
00864 if(lastNode) {
00865 lastNode->next = node->next;
00866 } else {
00867 d->focus = node->next;
00868 }
00869 EventHandler* h = node->handler;
00870 delete node;
00871 return h;
00872 }
00873 lastNode = node;
00874 node = node->next;
00875 }
00876 return 0;
00877 }
00878
00886 void Application::removeFromFocusStack(EventHandler* handler, int controllerID)
00887 {
00888 EventHandlerNode* node = d->focus;
00889 EventHandlerNode* lastNode = 0;
00890 while(node) {
00891 if(node->handler == handler && (controllerID == -1 || controllerID == node->controllerID)) {
00892 if(lastNode) {
00893 lastNode->next = node->next;
00894 } else {
00895 d->focus = node->next;
00896 }
00897 EventHandlerNode* delNode = node;
00898 node = node->next;
00899 delete delNode;
00900 } else {
00901 lastNode = node;
00902 node = node->next;
00903 }
00904 }
00905 }
00906
00912 void Application::installEventFilter(EventHandler* handler)
00913 {
00914 EventHandlerNode* node = new EventHandlerNode;
00915 node->controllerID = -1;
00916 node->handler = handler;
00917 node->next = d->eventFilters;
00918 d->eventFilters = node;
00919 }
00920
00926 void Application::removeEventFilter(EventHandler* handler)
00927 {
00928 EventHandlerNode* node = d->eventFilters;
00929 EventHandlerNode* lastNode = 0;
00930 while(node) {
00931 if(node->handler == handler) {
00932 if(lastNode) {
00933 lastNode->next = node->next;
00934 } else {
00935 d->eventFilters = node->next;
00936 }
00937 delete node;
00938 return;
00939 }
00940 lastNode = node;
00941 node = node->next;
00942 }
00943 }
00944
00953 void Application::scheduleTimer(int frames, EventHandler* handler, void* data)
00954 {
00955 TimerNode* timer = new TimerNode;
00956 timer->handler = handler;
00957 timer->framesRemaining = frames;
00958 timer->data = data;
00959
00960
00961
00962 timer->next = d->addTimers;
00963 d->addTimers = timer;
00964 }
00965
00970 bool Application::abortGxOnReset() const
00971 {
00972 return d->abortGxOnReset;
00973 }
00974
00986 void Application::setAbortGxOnReset(bool on)
00987 {
00988 d->abortGxOnReset = on;
00989 }
00990
00999 void Application::resetButtonPressed()
01000 {
01001 reboot();
01002 }
01003
01015 void Application::powerButtonPressed(int controllerID)
01016 {
01017 shutdown();
01018 }
01019
01020 }