void ProcessMouse(RAWINPUT *raw, bool foreground) { if (menuActive && UpdateMenuActive()) { // Ignore mouse input while a menu is active, it's probably interacting with the menu. return; } KeyInput key; key.deviceId = DEVICE_ID_MOUSE; mouseDeltaX += raw->data.mouse.lLastX; mouseDeltaY += raw->data.mouse.lLastY; if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) { key.flags = KEY_DOWN; key.keyCode = windowsTransTable[VK_RBUTTON]; NativeKey(key); } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) { key.flags = KEY_UP; key.keyCode = windowsTransTable[VK_RBUTTON]; NativeKey(key); } // TODO : Smooth and translate to an axis every frame. // NativeAxis() }
void XinputDevice::ApplyButtons(XINPUT_STATE &state, InputState &input_state) { u32 buttons = state.Gamepad.wButtons; if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) buttons |= XBOX_CODE_LEFTTRIGGER; if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) buttons |= XBOX_CODE_RIGHTTRIGGER; u32 downMask = buttons & (~prevButtons); u32 upMask = (~buttons) & prevButtons; prevButtons = buttons; for (int i = 0; i < xinput_ctrl_map_size; i++) { if (downMask & xinput_ctrl_map[i].from) { KeyInput key; key.deviceId = DEVICE_ID_X360_0; key.flags = KEY_DOWN; key.keyCode = xinput_ctrl_map[i].to; NativeKey(key); } if (upMask & xinput_ctrl_map[i].from) { KeyInput key; key.deviceId = DEVICE_ID_X360_0; key.flags = KEY_UP; key.keyCode = xinput_ctrl_map[i].to; NativeKey(key); } } }
void ProcessKeyboard(RAWINPUT *raw, bool foreground) { if (menuActive && UpdateMenuActive()) { // Ignore keyboard input while a menu is active, it's probably interacting with the menu. return; } KeyInput key; key.deviceId = DEVICE_ID_KEYBOARD; if (raw->data.keyboard.Message == WM_KEYDOWN || raw->data.keyboard.Message == WM_SYSKEYDOWN) { key.flags = KEY_DOWN; key.keyCode = windowsTransTable[GetTrueVKey(raw->data.keyboard)]; if (key.keyCode) { NativeKey(key); keyboardKeysDown.insert(key.keyCode); } } else if (raw->data.keyboard.Message == WM_KEYUP) { key.flags = KEY_UP; key.keyCode = windowsTransTable[GetTrueVKey(raw->data.keyboard)]; if (key.keyCode) { NativeKey(key); auto keyDown = std::find(keyboardKeysDown.begin(), keyboardKeysDown.end(), key.keyCode); if (keyDown != keyboardKeysDown.end()) keyboardKeysDown.erase(keyDown); } } }
void DinputDevice::ApplyButtons(DIJOYSTATE2 &state, InputState &input_state) { BYTE *buttons = state.rgbButtons; u32 downMask = 0x80; for (int i = 0; i < ARRAY_SIZE(dinput_buttons); ++i) { if (state.rgbButtons[i] == lastButtons_[i]) { continue; } bool down = (state.rgbButtons[i] & downMask) == downMask; KeyInput key; key.deviceId = DEVICE_ID_PAD_0; key.flags = down ? KEY_DOWN : KEY_UP; key.keyCode = dinput_buttons[i]; NativeKey(key); lastButtons_[i] = state.rgbButtons[i]; } // Now the POV hat, which can technically go in any degree but usually does not. if (LOWORD(state.rgdwPOV[0]) != lastPOV_[0]) { KeyInput dpad[4]; for (int i = 0; i < 4; ++i) { dpad[i].deviceId = DEVICE_ID_PAD_0; dpad[i].flags = KEY_UP; } dpad[0].keyCode = NKCODE_DPAD_UP; dpad[1].keyCode = NKCODE_DPAD_LEFT; dpad[2].keyCode = NKCODE_DPAD_DOWN; dpad[3].keyCode = NKCODE_DPAD_RIGHT; if (LOWORD(state.rgdwPOV[0]) != JOY_POVCENTERED) { // These are the edges, so we use or. if (state.rgdwPOV[0] >= JOY_POVLEFT_FORWARD || state.rgdwPOV[0] <= JOY_POVFORWARD_RIGHT) { dpad[0].flags = KEY_DOWN; } if (state.rgdwPOV[0] >= JOY_POVBACKWARD_LEFT && state.rgdwPOV[0] <= JOY_POVLEFT_FORWARD) { dpad[1].flags = KEY_DOWN; } if (state.rgdwPOV[0] >= JOY_POVRIGHT_BACKWARD && state.rgdwPOV[0] <= JOY_POVBACKWARD_LEFT) { dpad[2].flags = KEY_DOWN; } if (state.rgdwPOV[0] >= JOY_POVFORWARD_RIGHT && state.rgdwPOV[0] <= JOY_POVRIGHT_BACKWARD) { dpad[3].flags = KEY_DOWN; } } NativeKey(dpad[0]); NativeKey(dpad[1]); NativeKey(dpad[2]); NativeKey(dpad[3]); lastPOV_[0] = LOWORD(state.rgdwPOV[0]); } }
void ProcessMouse(HWND hWnd, RAWINPUT *raw, bool foreground) { if (menuActive && UpdateMenuActive()) { // Ignore mouse input while a menu is active, it's probably interacting with the menu. return; } TouchInput touch; touch.id = 0; touch.flags = TOUCH_MOVE; touch.x = input_state.pointer_x[0]; touch.y = input_state.pointer_y[0]; KeyInput key; key.deviceId = DEVICE_ID_MOUSE; mouseDeltaX += raw->data.mouse.lLastX; mouseDeltaY += raw->data.mouse.lLastY; if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) { key.flags = KEY_DOWN; key.keyCode = windowsTransTable[VK_RBUTTON]; NativeTouch(touch); if (MouseInWindow(hWnd)) { NativeKey(key); } mouseRightDown = true; } else if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) { key.flags = KEY_UP; key.keyCode = windowsTransTable[VK_RBUTTON]; NativeTouch(touch); if (MouseInWindow(hWnd)) { if (!mouseRightDown) { // This means they were focused outside, and right clicked inside. // Seems intentional, so send a down first. key.flags = KEY_DOWN; NativeKey(key); key.flags = KEY_UP; NativeKey(key); } else { NativeKey(key); } } mouseRightDown = false; } // TODO : Smooth and translate to an axis every frame. // NativeAxis() }
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_UP; NativeKey(keyInput); }
extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_UP; return NativeKey(keyInput); }
void QtEmuGL::wheelEvent(QWheelEvent *e) { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = e->delta()<0 ? NKCODE_EXT_MOUSEWHEEL_DOWN : NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); }
LRESULT ProcessChar(HWND hWnd, WPARAM wParam, LPARAM lParam) { KeyInput key; key.keyCode = wParam; // Note that this is NOT a NKCODE but a Unicode character! key.flags = KEY_CHAR; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); return 0; }
void LoseFocus() { // Force-release all held keys on the keyboard to prevent annoying stray inputs. KeyInput key; key.deviceId = DEVICE_ID_KEYBOARD; key.flags = KEY_UP; for (auto i = keyboardKeysDown.begin(); i != keyboardKeysDown.end(); ++i) { key.keyCode = *i; NativeKey(key); } }
extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key, jboolean isRepeat) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_DOWN; if (isRepeat) { keyInput.flags |= KEY_IS_REPEAT; } return NativeKey(keyInput); }
void MainWindow::keyPressEvent(QKeyEvent *e) { if(isFullScreen() && e->key() == Qt::Key_F11) { on_action_OptionsFullScreen_triggered(); return; } NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(e->key())->second, KEY_DOWN)); }
extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key, jboolean isRepeat) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_DOWN; if (isRepeat) { ILOG("Is repeat! %i", key); keyInput.flags |= KEY_IS_REPEAT; } return NativeKey(keyInput); }
void XinputDevice::ApplyButtons(XINPUT_STATE &state, InputState &input_state) { u32 buttons = state.Gamepad.wButtons; u32 downMask = buttons & (~prevButtons); u32 upMask = (~buttons) & prevButtons; prevButtons = buttons; for (int i = 0; i < xinput_ctrl_map_size; i++) { if (downMask & xinput_ctrl_map[i].from) { KeyInput key; key.deviceId = DEVICE_ID_X360_0; key.flags = KEY_DOWN; key.keyCode = xinput_ctrl_map[i].to; NativeKey(key); } if (upMask & xinput_ctrl_map[i].from) { KeyInput key; key.deviceId = DEVICE_ID_X360_0; key.flags = KEY_UP; key.keyCode = xinput_ctrl_map[i].to; NativeKey(key); } } }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: break; case WM_GETMINMAXINFO: { MINMAXINFO *minmax = reinterpret_cast<MINMAXINFO *>(lParam); RECT rc = { 0 }; bool portrait = g_Config.IsPortrait(); rc.right = portrait ? 272 : 480; rc.bottom = portrait ? 480 : 272; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, TRUE); minmax->ptMinTrackSize.x = rc.right - rc.left; minmax->ptMinTrackSize.y = rc.bottom - rc.top; } return 0; case WM_ACTIVATE: { bool pause = true; if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { WindowsRawInput::GainFocus(); InputDevice::GainFocus(); g_activeWindow = WINDOW_MAINWINDOW; pause = false; } if (!noFocusPause && g_Config.bPauseOnLostFocus && GetUIState() == UISTATE_INGAME) { if (pause != Core_IsStepping()) { // != is xor for bools if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_STOPGO, 0); else Core_EnableStepping(pause); } } if (wParam == WA_ACTIVE) { NativeMessageReceived("got_focus", ""); } if (wParam == WA_INACTIVE) { NativeMessageReceived("lost_focus", ""); WindowsRawInput::LoseFocus(); InputDevice::LoseFocus(); } } break; case WM_ERASEBKGND: // This window is always covered by DisplayWindow. No reason to erase. return 1; case WM_MOVE: SavePosition(); break; case WM_SIZE: switch (wParam) { case SIZE_RESTORED: case SIZE_MAXIMIZED: if (g_IgnoreWM_SIZE) { return DefWindowProc(hWnd, message, wParam, lParam); } else { SavePosition(); Core_NotifyWindowHidden(false); if (!g_Config.bPauseWhenMinimized) { NativeMessageReceived("window minimized", "false"); } int width = 0, height = 0; RECT rc; GetClientRect(hwndMain, &rc); width = rc.right - rc.left; height = rc.bottom - rc.top; // Moves the internal display window to match the inner size of the main window. MoveWindow(hwndDisplay, 0, 0, width, height, TRUE); // Setting pixelWidth to be too small could have odd consequences. if (width >= 4 && height >= 4) { // The framebuffer manager reads these once per frame, hopefully safe enough.. should really use a mutex or some // much better mechanism. PSP_CoreParameter().pixelWidth = width; PSP_CoreParameter().pixelHeight = height; } UpdateRenderResolution(); if (UpdateScreenScale(width, height, IsWindowSmall())) { NativeMessageReceived("gpu resized", ""); } // Don't save the window state if fullscreen. if (!g_Config.bFullScreen) { g_WindowState = wParam; } } break; case SIZE_MINIMIZED: Core_NotifyWindowHidden(true); if (!g_Config.bPauseWhenMinimized) { NativeMessageReceived("window minimized", "true"); } break; default: break; } break; case WM_TIMER: // Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode. switch (wParam) { case TIMER_CURSORUPDATE: CorrectCursor(); return 0; case TIMER_CURSORMOVEUPDATE: hideCursor = true; KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); return 0; } break; // For some reason, need to catch this here rather than in DisplayProc. case WM_MOUSEWHEEL: { int wheelDelta = (short)(wParam >> 16); KeyInput key; key.deviceId = DEVICE_ID_MOUSE; if (wheelDelta < 0) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; wheelDelta = -wheelDelta; } else { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; } // There's no separate keyup event for mousewheel events, let's pass them both together. // This also means it really won't work great for key mapping :( Need to build a 1 frame delay or something. key.flags = KEY_DOWN | KEY_UP | KEY_HASWHEELDELTA | (wheelDelta << 16); NativeKey(key); } break; case WM_COMMAND: { if (!EmuThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); MainWindowMenu_Process(hWnd, wParam); } break; case WM_USER_TOGGLE_FULLSCREEN: ToggleFullscreen(hwndMain, !g_Config.bFullScreen); break; case WM_INPUT: return WindowsRawInput::Process(hWnd, wParam, lParam); // TODO: Could do something useful with WM_INPUT_DEVICE_CHANGE? // Not sure why we are actually getting WM_CHAR even though we use RawInput, but alright.. case WM_CHAR: return WindowsRawInput::ProcessChar(hWnd, wParam, lParam); case WM_VERYSLEEPY_MSG: switch (wParam) { case VERYSLEEPY_WPARAM_SUPPORTED: return TRUE; case VERYSLEEPY_WPARAM_GETADDRINFO: { VerySleepy_AddrInfo *info = (VerySleepy_AddrInfo *)lParam; const u8 *ptr = (const u8 *)info->addr; std::string name; if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr(ptr, name)) { swprintf_s(info->name, L"Jit::%S", name.c_str()); return TRUE; } if (gpu && gpu->DescribeCodePtr(ptr, name)) { swprintf_s(info->name, L"GPU::%S", name.c_str()); return TRUE; } } return FALSE; default: return FALSE; } break; case WM_DROPFILES: { if (!EmuThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); HDROP hdrop = (HDROP)wParam; int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0); if (count != 1) { MessageBox(hwndMain,L"You can only load one file at a time",L"Error",MB_ICONINFORMATION); } else { TCHAR filename[512]; DragQueryFile(hdrop,0,filename,512); TCHAR *type = filename+_tcslen(filename)-3; NativeMessageReceived("boot", ConvertWStringToUTF8(filename).c_str()); Core_EnableStepping(false); } } break; case WM_CLOSE: EmuThread_Stop(); InputDevice::StopPolling(); WindowsRawInput::Shutdown(); return DefWindowProc(hWnd,message,wParam,lParam); case WM_DESTROY: KillTimer(hWnd, TIMER_CURSORUPDATE); KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); PostQuitMessage(0); break; case WM_USER + 1: if (disasmWindow[0]) disasmWindow[0]->NotifyMapLoaded(); if (memoryWindow[0]) memoryWindow[0]->NotifyMapLoaded(); if (disasmWindow[0]) disasmWindow[0]->UpdateDialog(); SetForegroundWindow(hwndMain); break; case WM_USER_SAVESTATE_FINISH: SetCursor(LoadCursor(0, IDC_ARROW)); break; case WM_USER_UPDATE_UI: TranslateMenus(hwndMain, menu); break; case WM_USER_UPDATE_SCREEN: ShowScreenResolution(); break; case WM_USER_WINDOW_TITLE_CHANGED: UpdateWindowTitle(); break; case WM_USER_BROWSE_BOOT_DONE: BrowseAndBootDone(); break; case WM_MENUSELECT: // Unfortunately, accelerate keys (hotkeys) shares the same enabled/disabled states // with corresponding menu items. UpdateMenus(); WindowsRawInput::NotifyMenu(); break; // Turn off the screensaver. // Note that if there's a screensaver password, this simple method // doesn't work on Vista or higher. case WM_SYSCOMMAND: { switch (wParam) { case SC_SCREENSAVE: return 0; case SC_MONITORPOWER: return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
bool MainUI::event(QEvent *e) { TouchInput input; QList<QTouchEvent::TouchPoint> touchPoints; switch(e->type()) { case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: touchPoints = static_cast<QTouchEvent *>(e)->touchPoints(); foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) { switch (touchPoint.state()) { case Qt::TouchPointStationary: break; case Qt::TouchPointPressed: case Qt::TouchPointReleased: input_state.pointer_down[touchPoint.id()] = (touchPoint.state() == Qt::TouchPointPressed); input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * g_dpi_scale * xscale; input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * g_dpi_scale * yscale; input.x = touchPoint.pos().x() * g_dpi_scale * xscale; input.y = touchPoint.pos().y() * g_dpi_scale * yscale; input.flags = (touchPoint.state() == Qt::TouchPointPressed) ? TOUCH_DOWN : TOUCH_UP; input.id = touchPoint.id(); NativeTouch(input); break; case Qt::TouchPointMoved: input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * g_dpi_scale * xscale; input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * g_dpi_scale * yscale; input.x = touchPoint.pos().x() * g_dpi_scale * xscale; input.y = touchPoint.pos().y() * g_dpi_scale * yscale; input.flags = TOUCH_MOVE; input.id = touchPoint.id(); NativeTouch(input); break; default: break; } } break; case QEvent::MouseButtonDblClick: if (!g_Config.bShowTouchControls || GetUIState() != UISTATE_INGAME) emit doubleClick(); break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale; input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale; input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale; input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale; input.flags = (e->type() == QEvent::MouseButtonPress) ? TOUCH_DOWN : TOUCH_UP; input.id = 0; NativeTouch(input); break; case QEvent::MouseMove: input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale; input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale; input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale; input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale; input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); break; case QEvent::Wheel: NativeKey(KeyInput(DEVICE_ID_MOUSE, ((QWheelEvent*)e)->delta()<0 ? NKCODE_EXT_MOUSEWHEEL_DOWN : NKCODE_EXT_MOUSEWHEEL_UP, KEY_DOWN)); break; case QEvent::KeyPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_DOWN)); break; case QEvent::KeyRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_UP)); break; default: return QWidget::event(e); } e->accept(); return true; }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; std::string fn; switch (message) { case WM_CREATE: break; case WM_MOVE: SavePosition(); ResizeDisplay(); break; case WM_SIZE: SavePosition(); ResizeDisplay(); break; case WM_TIMER: // Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode. switch (wParam) { case TIMER_CURSORUPDATE: CorrectCursor(); return 0; case TIMER_CURSORMOVEUPDATE: hideCursor = true; KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); return 0; } break; // For some reason, need to catch this here rather than in DisplayProc. case WM_MOUSEWHEEL: { int wheelDelta = (short)(wParam >> 16); KeyInput key; key.deviceId = DEVICE_ID_MOUSE; if (wheelDelta < 0) { key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; wheelDelta = -wheelDelta; } else { key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; } // There's no separate keyup event for mousewheel events, let's pass them both together. // This also means it really won't work great for key mapping :( Need to build a 1 frame delay or something. key.flags = KEY_DOWN | KEY_UP | KEY_HASWHEELDELTA | (wheelDelta << 16); NativeKey(key); break; } case WM_COMMAND: { if (!EmuThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); I18NCategory *g = GetI18NCategory("Graphics"); wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case ID_FILE_LOAD: BrowseAndBoot(""); break; case ID_FILE_LOAD_MEMSTICK: { std::string memStickDir, flash0dir; GetSysDirectories(memStickDir, flash0dir); memStickDir += "PSP\\GAME\\"; BrowseAndBoot(memStickDir); } break; case ID_FILE_REFRESHGAMELIST: break; case ID_FILE_MEMSTICK: { std::string memStickDir, flash0dir; GetSysDirectories(memStickDir, flash0dir); ShellExecuteA(NULL, "open", memStickDir.c_str(), 0, 0, SW_SHOW); } break; case ID_TOGGLE_PAUSE: if (globalUIState == UISTATE_PAUSEMENU) { NativeMessageReceived("run", ""); if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_GO, 0); } else if (Core_IsStepping()) //It is paused, then continue to run { if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_GO, 0); else Core_EnableStepping(false); } else { if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0); else Core_EnableStepping(true); } break; case ID_EMULATION_STOP: if (memoryWindow[0]) { SendMessage(memoryWindow[0]->GetDlgHandle(), WM_CLOSE, 0, 0); } if (disasmWindow[0]) { SendMessage(disasmWindow[0]->GetDlgHandle(), WM_CLOSE, 0, 0); } if (Core_IsStepping()) { Core_EnableStepping(false); } NativeMessageReceived("stop", ""); SetPlaying(0); Update(); break; case ID_EMULATION_RESET: if (globalUIState == UISTATE_PAUSEMENU) NativeMessageReceived("run", ""); NativeMessageReceived("reset", ""); break; case ID_EMULATION_SPEEDLIMIT: g_Config.bSpeedLimit = !g_Config.bSpeedLimit; break; case ID_FILE_LOADSTATEFILE: if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn)) { SetCursor(LoadCursor(0, IDC_WAIT)); SaveState::Load(fn, SaveStateActionFinished); } break; case ID_FILE_SAVESTATEFILE: if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn)) { SetCursor(LoadCursor(0, IDC_WAIT)); SaveState::Save(fn, SaveStateActionFinished); } break; // TODO: Improve UI for multiple slots case ID_FILE_SAVESTATE_NEXT_SLOT: { currentSavestateSlot = (currentSavestateSlot + 1)%5; char msg[30]; sprintf(msg, "Using save state slot %d.", currentSavestateSlot + 1); osm.Show(msg); break; } case ID_FILE_QUICKLOADSTATE: SetCursor(LoadCursor(0, IDC_WAIT)); SaveState::LoadSlot(currentSavestateSlot, SaveStateActionFinished); break; case ID_FILE_QUICKSAVESTATE: SetCursor(LoadCursor(0, IDC_WAIT)); SaveState::SaveSlot(currentSavestateSlot, SaveStateActionFinished); break; case ID_OPTIONS_SCREEN1X: SetZoom(1); break; case ID_OPTIONS_SCREEN2X: SetZoom(2); break; case ID_OPTIONS_SCREEN3X: SetZoom(3); break; case ID_OPTIONS_SCREEN4X: SetZoom(4); break; case ID_OPTIONS_MIPMAP: g_Config.bMipMap = !g_Config.bMipMap; break; case ID_OPTIONS_VSYNC: g_Config.iVSyncInterval = !g_Config.iVSyncInterval; break; case ID_TEXTURESCALING_OFF: setTexScalingLevel(1); break; case ID_TEXTURESCALING_2X: setTexScalingLevel(2); break; case ID_TEXTURESCALING_3X: setTexScalingLevel(3); break; case ID_TEXTURESCALING_4X: setTexScalingLevel(4); break; case ID_TEXTURESCALING_5X: setTexScalingLevel(5); break; case ID_TEXTURESCALING_XBRZ: setTexScalingType(TextureScaler::XBRZ); break; case ID_TEXTURESCALING_HYBRID: setTexScalingType(TextureScaler::HYBRID); break; case ID_TEXTURESCALING_BICUBIC: setTexScalingType(TextureScaler::BICUBIC); break; case ID_TEXTURESCALING_HYBRID_BICUBIC: setTexScalingType(TextureScaler::HYBRID_BICUBIC); break; case ID_TEXTURESCALING_DEPOSTERIZE: g_Config.bTexDeposterize = !g_Config.bTexDeposterize; if(gpu) gpu->ClearCacheNextFrame(); break; case ID_OPTIONS_BUFFEREDRENDERING: g_Config.bBufferedRendering = !g_Config.bBufferedRendering; osm.ShowOnOff(g->T("Buffered Rendering"), g_Config.bBufferedRendering); if (gpu) gpu->Resized(); // easy way to force a clear... break; case ID_OPTIONS_READFBOTOMEMORY: g_Config.bFramebuffersToMem = !g_Config.bFramebuffersToMem; osm.ShowOnOff(g->T("Read Framebuffers To Memory"), g_Config.bFramebuffersToMem); if (gpu) gpu->Resized(); // easy way to force a clear... break; case ID_OPTIONS_SHOWDEBUGSTATISTICS: g_Config.bShowDebugStats = !g_Config.bShowDebugStats; break; case ID_OPTIONS_HARDWARETRANSFORM: g_Config.bHardwareTransform = !g_Config.bHardwareTransform; osm.ShowOnOff(g->T("Hardware Transform"), g_Config.bHardwareTransform); break; case ID_OPTIONS_STRETCHDISPLAY: g_Config.bStretchToDisplay = !g_Config.bStretchToDisplay; if (gpu) gpu->Resized(); // easy way to force a clear... break; case ID_OPTIONS_FRAMESKIP: g_Config.iFrameSkip = g_Config.iFrameSkip == 0 ? 1 : 0; osm.ShowOnOff(g->T("Frame Skipping"), g_Config.iFrameSkip != 0); break; case ID_FILE_EXIT: DestroyWindow(hWnd); break; case ID_CPU_DYNAREC: g_Config.bJit = true; osm.ShowOnOff(g->T("Dynarec", "Dynarec (JIT)"), g_Config.bJit); break; case ID_CPU_INTERPRETER: g_Config.bJit = false; break; case ID_EMULATION_RUNONLOAD: g_Config.bAutoRun = !g_Config.bAutoRun; break; case ID_DEBUG_DUMPNEXTFRAME: if (gpu) gpu->DumpNextFrame(); break; case ID_DEBUG_LOADMAPFILE: if (W32Util::BrowseForFileName(true, hWnd, "Load .MAP",0,"Maps\0*.map\0All files\0*.*\0\0","map",fn)) { symbolMap.LoadSymbolMap(fn.c_str()); // HLE_PatchFunctions(); if (disasmWindow[0]) disasmWindow[0]->NotifyMapLoaded(); if (memoryWindow[0]) memoryWindow[0]->NotifyMapLoaded(); } break; case ID_DEBUG_SAVEMAPFILE: if (W32Util::BrowseForFileName(false, hWnd, "Save .MAP",0,"Maps\0*.map\0All files\0*.*\0\0","map",fn)) symbolMap.SaveSymbolMap(fn.c_str()); break; case ID_DEBUG_RESETSYMBOLTABLE: symbolMap.ResetSymbolMap(); for (int i=0; i<numCPUs; i++) if (disasmWindow[i]) disasmWindow[i]->NotifyMapLoaded(); for (int i=0; i<numCPUs; i++) if (memoryWindow[i]) memoryWindow[i]->NotifyMapLoaded(); break; case ID_DEBUG_DISASSEMBLY: if (disasmWindow[0]) disasmWindow[0]->Show(true); break; case ID_DEBUG_MEMORYVIEW: if (memoryWindow[0]) memoryWindow[0]->Show(true); break; case ID_DEBUG_LOG: LogManager::GetInstance()->GetConsoleListener()->Show(LogManager::GetInstance()->GetConsoleListener()->Hidden()); break; case ID_OPTIONS_IGNOREILLEGALREADS: g_Config.bIgnoreBadMemAccess = !g_Config.bIgnoreBadMemAccess; break; case ID_OPTIONS_FULLSCREEN: g_Config.bFullScreen = !g_Config.bFullScreen ; if(g_bFullScreen) { _ViewNormal(hWnd); } else { _ViewFullScreen(hWnd); } break; case ID_OPTIONS_VERTEXCACHE: g_Config.bVertexCache = !g_Config.bVertexCache; break; case ID_OPTIONS_SHOWFPS: g_Config.iShowFPSCounter = !g_Config.iShowFPSCounter; break; case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER: g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; break; case ID_OPTIONS_FASTMEMORY: g_Config.bFastMemory = !g_Config.bFastMemory; break; case ID_OPTIONS_USEVBO: g_Config.bUseVBO = !g_Config.bUseVBO; break; case ID_OPTIONS_TEXTUREFILTERING_AUTO: setTexFiltering(0); break; case ID_OPTIONS_NEARESTFILTERING: setTexFiltering(2) ; break; case ID_OPTIONS_LINEARFILTERING: setTexFiltering(3) ; break; case ID_OPTIONS_LINEARFILTERING_CG: setTexFiltering(4) ; break; case ID_OPTIONS_TOPMOST: g_Config.bTopMost = !g_Config.bTopMost; W32Util::MakeTopMost(hWnd, g_Config.bTopMost); break; case ID_OPTIONS_SIMPLE2XSSAA: g_Config.SSAntiAliasing = !g_Config.SSAntiAliasing; ResizeDisplay(true); break; case ID_OPTIONS_CONTROLS: MessageBox(hWnd, "Control mapping has been moved to the in-window Settings menu.\n", "Sorry", 0); break; case ID_EMULATION_SOUND: g_Config.bEnableSound = !g_Config.bEnableSound; break; case ID_HELP_OPENWEBSITE: ShellExecute(NULL, "open", "http://www.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL); break; case ID_HELP_OPENFORUM: ShellExecute(NULL, "open", "http://forums.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL); break; case ID_HELP_ABOUT: DialogManager::EnableAll(FALSE); DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); DialogManager::EnableAll(TRUE); break; case ID_DEBUG_TAKESCREENSHOT: g_TakeScreenshot = true; break; default: MessageBox(hwndMain,"Unimplemented","Sorry",0); break; } } break; case WM_INPUT: { UINT dwSize; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); if (!rawInputBuffer) { rawInputBuffer = malloc(dwSize); rawInputBufferSize = dwSize; } if (dwSize > rawInputBufferSize) { rawInputBuffer = realloc(rawInputBuffer, dwSize); } GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawInputBuffer, &dwSize, sizeof(RAWINPUTHEADER)); RAWINPUT* raw = (RAWINPUT*)rawInputBuffer; if (raw->header.dwType == RIM_TYPEKEYBOARD) { KeyInput key; key.deviceId = DEVICE_ID_KEYBOARD; if (raw->data.keyboard.Message == WM_KEYDOWN || raw->data.keyboard.Message == WM_SYSKEYDOWN) { key.flags = KEY_DOWN; key.keyCode = windowsTransTable[GetTrueVKey(raw->data.keyboard)]; if (key.keyCode) { NativeKey(key); } } else if (raw->data.keyboard.Message == WM_KEYUP) { key.flags = KEY_UP; key.keyCode = windowsTransTable[GetTrueVKey(raw->data.keyboard)]; if (key.keyCode) { NativeKey(key); } } } } return 0; case WM_DROPFILES: { if (!EmuThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); HDROP hdrop = (HDROP)wParam; int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0); if (count != 1) { MessageBox(hwndMain,"You can only load one file at a time","Error",MB_ICONINFORMATION); } else { TCHAR filename[512]; DragQueryFile(hdrop,0,filename,512); TCHAR *type = filename+_tcslen(filename)-3; SendMessage(hWnd, WM_COMMAND, ID_EMULATION_STOP, 0); // Ugly, need to wait for the stop message to process in the EmuThread. Sleep(20); MainWindow::SetPlaying(filename); MainWindow::Update(); NativeMessageReceived("boot", filename); } } break; case WM_CLOSE: /* if (g_Config.bConfirmOnQuit && __KernelIsRunning()) if (IDYES != MessageBox(hwndMain, "A game is in progress. Are you sure you want to exit?", "Are you sure?", MB_YESNO | MB_ICONQUESTION)) return 0; //*/ EmuThread_Stop(); return DefWindowProc(hWnd,message,wParam,lParam); case WM_DESTROY: KillTimer(hWnd, TIMER_CURSORUPDATE); KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); PostQuitMessage(0); break; case WM_USER+1: if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_CLOSE, 0, 0); if (memoryWindow[0]) SendMessage(memoryWindow[0]->GetDlgHandle(), WM_CLOSE, 0, 0); disasmWindow[0] = new CDisasm(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS); DialogManager::AddDlg(disasmWindow[0]); disasmWindow[0]->Show(g_Config.bShowDebuggerOnLoad); if (g_Config.bFullScreen) _ViewFullScreen(hWnd); memoryWindow[0] = new CMemoryDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS); DialogManager::AddDlg(memoryWindow[0]); if (disasmWindow[0]) disasmWindow[0]->NotifyMapLoaded(); if (memoryWindow[0]) memoryWindow[0]->NotifyMapLoaded(); SetForegroundWindow(hwndMain); break; case WM_MENUSELECT: // Unfortunately, accelerate keys (hotkeys) shares the same enabled/disabled states // with corresponding menu items. UpdateMenus(); break; // Turn off the screensaver. // Note that if there's a screensaver password, this simple method // doesn't work on Vista or higher. case WM_SYSCOMMAND: { switch (wParam) { case SC_SCREENSAVE: return 0; case SC_MONITORPOWER: return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
int main(int argc, char *argv[]) { std::string app_name; std::string app_name_nice; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 // We really should upgrade to SDL 2.0 soon. //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } #ifdef EGL if (EGL_Open()) return 1; #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); int mode; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else mode = SDL_OPENGL; for (int i = 1; i < argc; i++) if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; #endif if (mode & SDL_FULLSCREEN) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); pixel_xres = info->current_w; pixel_yres = info->current_h; g_Config.bFullScreen = true; } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2; pixel_yres = 272 * 2; g_Config.bFullScreen = false; } dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); } #ifdef EGL EGL_Init(); #endif SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); #ifdef MAEMO SDL_ShowCursor(SDL_DISABLE); #endif #ifndef USING_GLES2 if (GLEW_OK != glewInit()) { printf("Failed to initialize glew!\n"); return 1; } if (GLEW_VERSION_2_0) { printf("OpenGL 2.0 or higher.\n"); } else { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } #endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux char path[512]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); #endif #ifdef _WIN32 NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); #else NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif pixel_in_dps = (float)pixel_xres / dp_xres; float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; g_dpi_scale = dp_xres / (float)pixel_xres; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); NativeInitGraphics(); SDL_AudioSpec fmt; fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, NULL) < 0) ELOG("Failed to open audio: %s", SDL_GetError()); // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #ifdef PANDORA int numjoys = SDL_NumJoysticks(); // Joysticks init, we the nubs if setup as Joystick if (numjoys > 0) { ljoy = SDL_JoystickOpen(0); if (numjoys > 1) rjoy = SDL_JoystickOpen(1); } #else joystick = new SDLJoystick(); #endif EnableFZ(); int framecount = 0; float t = 0; float lastT = 0; while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; int quitRequested = 0; SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * dp_xscale; float my = event.motion.y * dp_yscale; switch (event.type) { case SDL_QUIT: quitRequested = 1; break; case SDL_KEYDOWN: { int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_KEYUP: { int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_UP; key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_DOWN; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_WHEELUP: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); } break; case SDL_BUTTON_WHEELDOWN: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_DOWN; NativeKey(key); } break; } break; case SDL_MOUSEMOTION: if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); } break; case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.pointer_down[0] = false; input_state.mouse_valid = true; //input_state.mouse_buttons_up = 1; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_UP; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_WHEELUP: { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_UP; NativeKey(key); } break; case SDL_BUTTON_WHEELDOWN: { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_UP; NativeKey(key); } break; } break; default: joystick->ProcessInput(event); break; } } if (quitRequested) break; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); SimulateGamepad(keys, &input_state); UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); #ifndef MAEMO if (lastUIState != globalUIState) { lastUIState = globalUIState; if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) SDL_ShowCursor(SDL_DISABLE); if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) SDL_ShowCursor(SDL_ENABLE); } #endif EndInputState(&input_state); if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } #ifdef EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { SDL_GL_SwapBuffers(); lastT = t; } #endif time_update(); t = time_now(); framecount++; } #ifndef PANDORA delete joystick; joystick = NULL; #endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifdef _WIN32 exit(0); #endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); #ifdef EGL EGL_Close(); #endif SDL_Quit(); net::Shutdown(); exit(0); return 0; }
/* * it seems that it takes about 600ms to get an update after buttonpress * */ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId,TRemConCoreApiButtonAction aButtonAct){ TRequestStatus status; switch( aOperationId ){ case ERemConCoreApiPausePlayFunction: { switch (aButtonAct){ case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_UP)); break; case ERemConCoreApiButtonClick: playtimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); break; default: // Play/Pause unknown action break; } break; } case ERemConCoreApiStop: { switch (aButtonAct){ case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); break; case ERemConCoreApiButtonClick: stoptimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); break; default: break; } break; } case ERemConCoreApiRewind: { switch (aButtonAct){ case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); break; case ERemConCoreApiButtonClick: backwardtimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); default: break; } break; } case ERemConCoreApiFastForward: { switch (aButtonAct){ case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); break; case ERemConCoreApiButtonClick: forwardtimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); default: break; } break; } case ERemConCoreApiVolumeUp: { switch (aButtonAct){ case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_UP)); break; case ERemConCoreApiButtonClick: voluptimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_DOWN)); default: break; } break; } case ERemConCoreApiVolumeDown: { switch (aButtonAct){ case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_UP)); break; case ERemConCoreApiButtonClick: voldowntimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); default: break; } break; } case ERemConCoreApiBackward: { switch (aButtonAct) { case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); break; case ERemConCoreApiButtonClick: backwardtimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); default: break; } break; } case ERemConCoreApiForward: { switch (aButtonAct) { case ERemConCoreApiButtonPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); break; case ERemConCoreApiButtonRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); break; case ERemConCoreApiButtonClick: forwardtimer->start(KTimeOut); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); default: break; } break; } default: break; } //complete key event CompleteMediaKeyEvent( aOperationId ); }
void SymbianMediaKeys::voldowntimerexpired(){ voldowntimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_UP)); }
void SymbianMediaKeys::backwardtimerexpired(){ backwardtimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); }
void SymbianMediaKeys::forwardtimerexpired(){ forwardtimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) { // Remove the D3D11 choice on versions below XP RemoveMenu(GetMenu(hWnd), ID_OPTIONS_DIRECT3D11, MF_BYCOMMAND); } break; case WM_GETMINMAXINFO: { MINMAXINFO *minmax = reinterpret_cast<MINMAXINFO *>(lParam); RECT rc = { 0 }; bool portrait = g_Config.IsPortrait(); rc.right = portrait ? 272 : 480; rc.bottom = portrait ? 480 : 272; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, TRUE); minmax->ptMinTrackSize.x = rc.right - rc.left; minmax->ptMinTrackSize.y = rc.bottom - rc.top; } return 0; case WM_ACTIVATE: { bool pause = true; if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { WindowsRawInput::GainFocus(); if (!IsIconic(GetHWND())) { InputDevice::GainFocus(); } g_activeWindow = WINDOW_MAINWINDOW; pause = false; } if (!noFocusPause && g_Config.bPauseOnLostFocus && GetUIState() == UISTATE_INGAME) { if (pause != Core_IsStepping()) { // != is xor for bools if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_STOPGO, 0); else Core_EnableStepping(pause); } } if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { NativeMessageReceived("got_focus", ""); hasFocus = true; trapMouse = true; } if (wParam == WA_INACTIVE) { NativeMessageReceived("lost_focus", ""); WindowsRawInput::LoseFocus(); InputDevice::LoseFocus(); hasFocus = false; trapMouse = false; } } break; case WM_ERASEBKGND: // This window is always covered by DisplayWindow. No reason to erase. return 1; case WM_MOVE: SavePosition(); break; case WM_ENTERSIZEMOVE: inResizeMove = true; break; case WM_EXITSIZEMOVE: inResizeMove = false; HandleSizeChange(SIZE_RESTORED); break; case WM_SIZE: switch (wParam) { case SIZE_RESTORED: case SIZE_MAXIMIZED: if (g_IgnoreWM_SIZE) { return DefWindowProc(hWnd, message, wParam, lParam); } else if (!inResizeMove) { HandleSizeChange(wParam); } if (hasFocus) { InputDevice::GainFocus(); } break; case SIZE_MINIMIZED: Core_NotifyWindowHidden(true); if (!g_Config.bPauseWhenMinimized) { NativeMessageReceived("window minimized", "true"); } InputDevice::LoseFocus(); break; default: break; } break; case WM_TIMER: // Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode. switch (wParam) { case TIMER_CURSORUPDATE: CorrectCursor(); return 0; case TIMER_CURSORMOVEUPDATE: hideCursor = true; KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); return 0; } break; // For some reason, need to catch this here rather than in DisplayProc. case WM_MOUSEWHEEL: { int wheelDelta = (short)(wParam >> 16); KeyInput key; key.deviceId = DEVICE_ID_MOUSE; if (wheelDelta < 0) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; wheelDelta = -wheelDelta; } else { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; } // There's no separate keyup event for mousewheel events, let's pass them both together. // This also means it really won't work great for key mapping :( Need to build a 1 frame delay or something. key.flags = KEY_DOWN | KEY_UP | KEY_HASWHEELDELTA | (wheelDelta << 16); NativeKey(key); } break; case WM_COMMAND: { if (!MainThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); MainWindowMenu_Process(hWnd, wParam); } break; case WM_USER_TOGGLE_FULLSCREEN: ToggleFullscreen(hwndMain, wParam ? true : false); break; case WM_INPUT: return WindowsRawInput::Process(hWnd, wParam, lParam); // TODO: Could do something useful with WM_INPUT_DEVICE_CHANGE? // Not sure why we are actually getting WM_CHAR even though we use RawInput, but alright.. case WM_CHAR: return WindowsRawInput::ProcessChar(hWnd, wParam, lParam); case WM_DEVICECHANGE: #ifndef _M_ARM DinputDevice::CheckDevices(); #endif return DefWindowProc(hWnd, message, wParam, lParam); case WM_VERYSLEEPY_MSG: switch (wParam) { case VERYSLEEPY_WPARAM_SUPPORTED: return TRUE; case VERYSLEEPY_WPARAM_GETADDRINFO: { VerySleepy_AddrInfo *info = (VerySleepy_AddrInfo *)lParam; const u8 *ptr = (const u8 *)info->addr; std::string name; if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr(ptr, name)) { swprintf_s(info->name, L"Jit::%S", name.c_str()); return TRUE; } if (gpu && gpu->DescribeCodePtr(ptr, name)) { swprintf_s(info->name, L"GPU::%S", name.c_str()); return TRUE; } } return FALSE; default: return FALSE; } break; case WM_DROPFILES: { if (!MainThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); HDROP hdrop = (HDROP)wParam; int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0); if (count != 1) { MessageBox(hwndMain,L"You can only load one file at a time",L"Error",MB_ICONINFORMATION); } else { TCHAR filename[512]; if (DragQueryFile(hdrop, 0, filename, 512) != 0) { const std::string utf8_filename = ReplaceAll(ConvertWStringToUTF8(filename), "\\", "/"); NativeMessageReceived("boot", utf8_filename.c_str()); Core_EnableStepping(false); } } } break; case WM_CLOSE: InputDevice::StopPolling(); WindowsRawInput::Shutdown(); return DefWindowProc(hWnd,message,wParam,lParam); case WM_DESTROY: KillTimer(hWnd, TIMER_CURSORUPDATE); KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); PostQuitMessage(0); break; case WM_USER + 1: if (disasmWindow[0]) disasmWindow[0]->NotifyMapLoaded(); if (memoryWindow[0]) memoryWindow[0]->NotifyMapLoaded(); if (disasmWindow[0]) disasmWindow[0]->UpdateDialog(); SetForegroundWindow(hwndMain); break; case WM_USER_SAVESTATE_FINISH: SetCursor(LoadCursor(0, IDC_ARROW)); break; case WM_USER_UPDATE_UI: TranslateMenus(hwndMain, menu); // Update checked status immediately for accelerators. UpdateMenus(); break; case WM_USER_WINDOW_TITLE_CHANGED: UpdateWindowTitle(); break; case WM_USER_BROWSE_BOOT_DONE: BrowseAndBootDone(); break; case WM_USER_BROWSE_BG_DONE: BrowseBackgroundDone(); break; case WM_USER_RESTART_EMUTHREAD: NativeSetRestarting(); InputDevice::StopPolling(); MainThread_Stop(); coreState = CORE_POWERUP; UpdateUIState(UISTATE_MENU); MainThread_Start(g_Config.iGPUBackend == (int)GPUBackend::OPENGL); InputDevice::BeginPolling(); break; case WM_MENUSELECT: // Called when a menu is opened. Also when an item is selected, but meh. UpdateMenus(true); WindowsRawInput::NotifyMenu(); trapMouse = false; break; case WM_EXITMENULOOP: // Called when menu is closed. trapMouse = true; break; // Turn off the screensaver. // Note that if there's a screensaver password, this simple method // doesn't work on Vista or higher. case WM_SYSCOMMAND: { switch (wParam) { case SC_SCREENSAVE: return 0; case SC_MONITORPOWER: return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
int main(int argc, char *argv[]) { glslang::InitializeProcess(); #if PPSSPP_PLATFORM(RPI) bcm_host_init(); #endif putenv((char*)"SDL_VIDEO_CENTERED=1"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); if (VulkanMayBeAvailable()) { printf("Vulkan might be available.\n"); } else { printf("Vulkan is not available.\n"); } int set_xres = -1; int set_yres = -1; bool portrait = false; bool set_ipad = false; float set_dpi = 1.0f; float set_scale = 1.0f; // Produce a new set of arguments with the ones we skip. int remain_argc = 1; const char *remain_argv[256] = { argv[0] }; Uint32 mode = 0; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; else if (set_xres == -2) set_xres = parseInt(argv[i]); else if (set_yres == -2) set_yres = parseInt(argv[i]); else if (set_dpi == -2) set_dpi = parseFloat(argv[i]); else if (set_scale == -2) set_scale = parseFloat(argv[i]); else if (!strcmp(argv[i],"--xres")) set_xres = -2; else if (!strcmp(argv[i],"--yres")) set_yres = -2; else if (!strcmp(argv[i],"--dpi")) set_dpi = -2; else if (!strcmp(argv[i],"--scale")) set_scale = -2; else if (!strcmp(argv[i],"--ipad")) set_ipad = true; else if (!strcmp(argv[i],"--portrait")) portrait = true; else { remain_argv[remain_argc++] = argv[i]; } } std::string app_name; std::string app_name_nice; std::string version; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version); bool joystick_enabled = true; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Failed to initialize SDL with joystick support. Retrying without.\n"); joystick_enabled = false; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } } // TODO: How do we get this into the GraphicsContext? #ifdef USING_EGL if (EGL_Open()) return 1; #endif // Get the video info before doing anything else, so we don't get skewed resolution results. // TODO: support multiple displays correctly SDL_DisplayMode displayMode; int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode); if (should_be_zero != 0) { fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError()); return 1; } g_DesktopWidth = displayMode.w; g_DesktopHeight = displayMode.h; SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetSwapInterval(1); // Is resolution is too low to run windowed if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) { mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; } if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { pixel_xres = g_DesktopWidth; pixel_yres = g_DesktopHeight; g_Config.bFullScreen = true; } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2 * set_scale; pixel_yres = 272 * 2 * set_scale; if (portrait) { std::swap(pixel_xres, pixel_yres); } g_Config.bFullScreen = false; } set_dpi = 1.0f / set_dpi; if (set_ipad) { pixel_xres = 1024; pixel_yres = 768; } if (!landscape) { std::swap(pixel_xres, pixel_yres); } if (set_xres > 0) { pixel_xres = set_xres; } if (set_yres > 0) { pixel_yres = set_yres; } float dpi_scale = 1.0f; if (set_dpi > 0) { dpi_scale = set_dpi; } dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; // Mac / Linux char path[2048]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } strcpy(path, the_path); if (path[strlen(path)-1] != '/') strcat(path, "/"); NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr); // Use the setting from the config when initing the window. if (g_Config.bFullScreen) mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; int x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()); int y = SDL_WINDOWPOS_UNDEFINED; pixel_in_dps_x = (float)pixel_xres / dp_xres; pixel_in_dps_y = (float)pixel_yres / dp_yres; g_dpi_scale_x = dp_xres / (float)pixel_xres; g_dpi_scale_y = dp_yres / (float)pixel_yres; g_dpi_scale_real_x = g_dpi_scale_x; g_dpi_scale_real_y = g_dpi_scale_y; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; std::string error_message; if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext(); if (ctx->Init(window, x, y, mode, &error_message) != 0) { printf("GL init error '%s'\n", error_message.c_str()); } graphicsContext = ctx; } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); if (!ctx->Init(window, x, y, mode, &error_message)) { printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); g_Config.iGPUBackend = (int)GPUBackend::OPENGL; SetGPUBackend((GPUBackend)g_Config.iGPUBackend); delete ctx; SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(); glctx->Init(window, x, y, mode, &error_message); graphicsContext = glctx; } else { graphicsContext = ctx; } } bool useEmuThread = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); // Since we render from the main thread, there's nothing done here, but we call it to avoid confusion. if (!graphicsContext->InitFromRenderThread(&error_message)) { printf("Init from thread error: '%s'\n", error_message.c_str()); } #ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif if (!useEmuThread) { NativeInitGraphics(graphicsContext); NativeResized(); } SDL_AudioSpec fmt, ret_fmt; memset(&fmt, 0, sizeof(fmt)); fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { if (ret_fmt.samples != fmt.samples) // Notify, but still use it ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples); if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) { ELOG("Sound buffer format does not match requested format."); ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq); ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format); ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels); ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudio(); } } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); if (joystick_enabled) { joystick = new SDLJoystick(); } else { joystick = nullptr; } EnableFZ(); int framecount = 0; bool mouseDown = false; if (useEmuThread) { EmuThreadStart(graphicsContext); } graphicsContext->ThreadStart(); while (true) { SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * g_dpi_scale_x; float my = event.motion.y * g_dpi_scale_y; switch (event.type) { case SDL_QUIT: g_QuitRequested = 1; break; #if !defined(MOBILE_DEVICE) case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: { Uint32 window_flags = SDL_GetWindowFlags(window); bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); pixel_xres = event.window.data1; pixel_yres = event.window.data2; dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; NativeResized(); // Set variable here in case fullscreen was toggled by hotkey g_Config.bFullScreen = fullscreen; // Hide/Show cursor correctly toggling fullscreen if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) { SDL_ShowCursor(SDL_DISABLE); } else if (lastUIState != UISTATE_INGAME || !fullscreen) { SDL_ShowCursor(SDL_ENABLE); } break; } default: break; } break; #endif case SDL_KEYDOWN: { if (event.key.repeat > 0) { break;} int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; auto mapped = KeyMapRawSDLtoNative.find(k); if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { break; } key.keyCode = mapped->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_KEYUP: { if (event.key.repeat > 0) { break;} int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_UP; auto mapped = KeyMapRawSDLtoNative.find(k); if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) { break; } key.keyCode = mapped->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_TEXTINPUT: { int pos = 0; int c = u8_nextchar(event.text.text, &pos); KeyInput key; key.flags = KEY_CHAR; key.keyCode = c; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); break; } case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { mouseDown = true; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_DOWN | TOUCH_MOUSE; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); NativeKey(key); } break; } break; case SDL_MOUSEWHEEL: { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; if (event.wheel.y > 0) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; } else { key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; } key.flags = KEY_DOWN; NativeKey(key); // SDL2 doesn't consider the mousewheel a button anymore // so let's send the KEY_UP right away. // Maybe KEY_UP alone will suffice? key.flags = KEY_UP; NativeKey(key); } case SDL_MOUSEMOTION: if (mouseDown) { TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_MOVE | TOUCH_MOUSE; input.id = 0; NativeTouch(input); } break; case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: { mouseDown = false; TouchInput input; input.x = mx; input.y = my; input.flags = TOUCH_UP | TOUCH_MOUSE; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); NativeKey(key); } break; } break; default: if (joystick) { joystick->ProcessInput(event); } break; } } if (g_QuitRequested) break; const uint8_t *keys = SDL_GetKeyboardState(NULL); if (emuThreadState == (int)EmuThreadState::DISABLED) { UpdateRunLoop(); } if (g_QuitRequested) break; #if !defined(MOBILE_DEVICE) if (lastUIState != GetUIState()) { lastUIState = GetUIState(); if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) SDL_ShowCursor(SDL_DISABLE); if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) SDL_ShowCursor(SDL_ENABLE); } #endif if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } if (emuThreadState != (int)EmuThreadState::DISABLED) { if (!graphicsContext->ThreadFrame()) break; } graphicsContext->SwapBuffers(); ToggleFullScreenIfFlagSet(window); time_update(); framecount++; } if (useEmuThread) { EmuThreadStop(); while (emuThreadState != (int)EmuThreadState::STOPPED) { // Need to keep eating frames to allow the EmuThread to exit correctly. graphicsContext->ThreadFrame(); } EmuThreadJoin(); } delete joystick; if (!useEmuThread) { NativeShutdownGraphics(); } graphicsContext->Shutdown(); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); NativeShutdown(); delete graphicsContext; SDL_PauseAudio(1); SDL_CloseAudio(); SDL_Quit(); #if PPSSPP_PLATFORM(RPI) bcm_host_deinit(); #endif glslang::FinalizeProcess(); ILOG("Leaving main"); return 0; }
void BlackberryMain::runMain() { bool running = true; while (running && !g_quitRequested) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; while (true) { // Handle Blackberry events bps_event_t *event = NULL; bps_get_event(&event, 0); if (event == NULL) break; // Ran out of events int domain = bps_event_get_domain(event); if (domain == screen_get_domain()) { handleInput(screen_event_get_event(event)); } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) { case NAVIGATOR_INVOKE_TARGET: { const navigator_invoke_invocation_t *invoke = navigator_invoke_event_get_invocation(event); if(invoke) { boot_filename = navigator_invoke_invocation_get_uri(invoke)+7; // Remove file:// } } break; case NAVIGATOR_ORIENTATION: sensor_remap_coordinates(navigator_event_get_orientation_angle(event)); break; case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); break; case NAVIGATOR_EXIT: return; } } else if (domain == sensor_get_domain()) { if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { sensor_event_get_xyz(event, &(input_state.acc.y), &(input_state.acc.x), &(input_state.acc.z)); AxisInput axis; axis.deviceId = DEVICE_ID_ACCELEROMETER; axis.flags = 0; axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; axis.value = input_state.acc.x; NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; axis.value = input_state.acc.y; NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; axis.value = input_state.acc.z; NativeAxis(axis); } } } UpdateInputState(&input_state); NativeUpdate(input_state); // Work in Progress // Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu. // Idea: Render to all displays. Controls go to internal, game goes to external(s). if (GetUIState() == UISTATE_INGAME && !emulating) { emulating = true; switchDisplay(screen_emu); if (g_Config.iShowFPSCounter == 4) { int options = SCREEN_DEBUG_STATISTICS; screen_set_window_property_iv(screen_win[0], SCREEN_PROPERTY_DEBUG, &options); } } else if (GetUIState() != UISTATE_INGAME && emulating) { emulating = false; switchDisplay(screen_ui); } NativeRender(); EndInputState(&input_state); time_update(); // This handles VSync if (emulating) eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]); else eglSwapBuffers(egl_disp[screen_ui], egl_surf[screen_ui]); } }
void BlackberryMain::handleInput(screen_event_t screen_event) { TouchInput input; KeyInput key; int val, buttons, pointerId; int pair[2]; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); input_state.mouse_valid = true; switch(val) { // Touchscreen case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH); input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; input.x = pair[0] * g_dpi_scale; input.y = pair[1] * g_dpi_scale; input.flags = (val == SCREEN_EVENT_MTOUCH_TOUCH) ? TOUCH_DOWN : TOUCH_UP; input.id = pointerId; NativeTouch(input); break; case SCREEN_EVENT_MTOUCH_MOVE: screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; input.x = pair[0] * g_dpi_scale; input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_MOVE; input.id = pointerId; NativeTouch(input); break; // Mouse, Simulator case SCREEN_EVENT_POINTER: screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down input_state.pointer_x[0] = pair[0] * g_dpi_scale; input_state.pointer_y[0] = pair[1] * g_dpi_scale; input_state.pointer_down[0] = true; input.x = pair[0] * g_dpi_scale; input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_DOWN; input.id = 0; NativeTouch(input); } else if (input_state.pointer_down[0]) { // Up input_state.pointer_x[0] = pair[0] * g_dpi_scale; input_state.pointer_y[0] = pair[1] * g_dpi_scale; input_state.pointer_down[0] = false; input.x = pair[0] * g_dpi_scale; input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_UP; input.id = 0; NativeTouch(input); } break; // Keyboard case SCREEN_EVENT_KEYBOARD: int flags, value; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawBlackberrytoNative.find(value)->second, (flags & KEY_DOWN) ? KEY_DOWN : KEY_UP)); break; // Gamepad case SCREEN_EVENT_GAMEPAD: case SCREEN_EVENT_JOYSTICK: int analog0[3]; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); for (int i = 0; i < 32; i++) { int mask = 1 << i; if ((old_buttons & mask) != (buttons & mask)) NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP)); } if (!screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG0, analog0)) { for (int i = 0; i < 2; i++) { AxisInput axis; axis.axisId = JOYSTICK_AXIS_X + i; // 1.2 to try to approximate the PSP's clamped rectangular range. axis.value = 1.2 * analog0[i] / 128.0f; if (axis.value > 1.0f) axis.value = 1.0f; if (axis.value < -1.0f) axis.value = -1.0f; axis.deviceId = DEVICE_ID_PAD_0; axis.flags = 0; NativeAxis(axis); } } old_buttons = buttons; break; case SCREEN_EVENT_DISPLAY: screen_display_t new_dpy = NULL; screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DISPLAY, (void **)&new_dpy); for (int i = 0; i < ndisplays; i++) { if (new_dpy != screen_dpy[i]) continue; int active = 0; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ATTACHED, &active); if (active) { int size[2]; screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_SIZE, size); if (size[0] == 0 || size[1] == 0) active = 0; } if (active && !displays[i].attached) realiseDisplay(i); else if (!active && displays[i].attached && displays[i].realised) unrealiseDisplay(i); displays[i].attached = active; } break; } }
void SDLJoystick::ProcessInput(SDL_Event &event){ switch (event.type) { case SDL_JOYAXISMOTION: { std::map<int, int>::const_iterator i = SDLJoyAxisMap.find(event.jaxis.axis); if (i != SDLJoyAxisMap.end()) { AxisInput axis; axis.axisId = i->second; // 1.2 to try to approximate the PSP's clamped rectangular range. axis.value = 1.2 * event.jaxis.value / 32767.0f; if (axis.value > 1.0f) axis.value = 1.0f; if (axis.value < -1.0f) axis.value = -1.0f; axis.deviceId = DEVICE_ID_PAD_0 + event.jaxis.which; axis.flags = 0; NativeAxis(axis); } break; } case SDL_JOYBUTTONDOWN: { std::map<int, int>::const_iterator i = SDLJoyButtonMap.find(event.jbutton.button); if (i != SDLJoyButtonMap.end()) { KeyInput key; key.flags = KEY_DOWN; key.keyCode = i->second; key.deviceId = DEVICE_ID_PAD_0 + event.jbutton.which; NativeKey(key); } break; } case SDL_JOYBUTTONUP: { std::map<int, int>::const_iterator i = SDLJoyButtonMap.find(event.jbutton.button); if (i != SDLJoyButtonMap.end()) { KeyInput key; key.flags = KEY_UP; key.keyCode = i->second; key.deviceId = DEVICE_ID_PAD_0 + event.jbutton.which; NativeKey(key); } break; } case SDL_JOYHATMOTION: { #ifdef _WIN32 KeyInput key; key.deviceId = DEVICE_ID_PAD_0 + event.jhat.which; key.flags = (event.jhat.value & SDL_HAT_UP)?KEY_DOWN:KEY_UP; key.keyCode = NKCODE_DPAD_UP; NativeKey(key); key.flags = (event.jhat.value & SDL_HAT_LEFT)?KEY_DOWN:KEY_UP; key.keyCode = NKCODE_DPAD_LEFT; NativeKey(key); key.flags = (event.jhat.value & SDL_HAT_DOWN)?KEY_DOWN:KEY_UP; key.keyCode = NKCODE_DPAD_DOWN; NativeKey(key); key.flags = (event.jhat.value & SDL_HAT_RIGHT)?KEY_DOWN:KEY_UP; key.keyCode = NKCODE_DPAD_RIGHT; NativeKey(key); #else AxisInput axisX; AxisInput axisY; axisX.axisId = JOYSTICK_AXIS_HAT_X; axisY.axisId = JOYSTICK_AXIS_HAT_Y; axisX.deviceId = DEVICE_ID_PAD_0 + event.jhat.which; axisY.deviceId = DEVICE_ID_PAD_0 + event.jhat.which; axisX.value = 0.0f; axisY.value = 0.0f; if (event.jhat.value & SDL_HAT_LEFT) axisX.value = -1.0f; if (event.jhat.value & SDL_HAT_RIGHT) axisX.value = 1.0f; if (event.jhat.value & SDL_HAT_DOWN) axisY.value = 1.0f; if (event.jhat.value & SDL_HAT_UP) axisY.value = -1.0f; NativeAxis(axisX); NativeAxis(axisY); #endif break; } } }
void SymbianMediaKeys::playtimerexpired(){ playtimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_UP)); }
void MainWindow::keyReleaseEvent(QKeyEvent *e) { NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(e->key())->second, KEY_UP)); }
void SymbianMediaKeys::stoptimerexpired(){ stoptimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); }