bsnes/hiro/windows/application.cpp

220 lines
7.1 KiB
C++
Raw Normal View History

namespace phoenix {
static bool Application_keyboardProc(HWND, UINT, WPARAM, LPARAM);
static void Application_processDialogMessage(MSG&);
static LRESULT CALLBACK Application_windowProc(HWND, UINT, WPARAM, LPARAM);
void pApplication::run() {
MSG msg;
if(Application::main) {
while(applicationState.quit == false) {
Application::main();
processEvents();
}
} else {
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
Application_processDialogMessage(msg);
}
}
}
bool pApplication::pendingEvents() {
MSG msg;
return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
}
void pApplication::processEvents() {
while(pendingEvents()) {
MSG msg;
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
Application_processDialogMessage(msg);
}
}
}
void Application_processDialogMessage(MSG& msg) {
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP
|| msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) {
if(Application_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam)) {
DispatchMessage(&msg);
Update to v094 release. byuu says: This release adds support for game libraries, and substantially improves Game Boy and Game Boy Color emulation with cycle-based renderers. Many other changes are also present. It's very important to note that this release now defaults to optimal drivers rather than safe drivers. This is particularly important if you do not have strong OpenGL 3.2 drivers. If performance is bad, go to Settings -> Configuration -> Advanced, change the video driver, and restart higan. In the rare case that you have trouble opening higan, you can edit settings.bml directly and change the setting there. The Windows safe driver is Direct3D, and the Linux safe driver is XShm. Also note that although display emulation shaders are now supported, they have not been included in this release as they are not ready yet. The support has been built-in anyway, so that they can be tested by everyone. Once refined, future releases of higan will come with built-in shaders for each emulated system that simulates the unique display characteristics of each. Changelog (since v093): - sfc: added SA-1 MDR support (fixes SD Gundam G-Next bug) - sfc: remove random/ and config/, merge to system/ with better randomization - gb: improved color emulation palette contrast - gbc: do not sort sprites by X-priority - gbc: allow transparency on BG priority pixels - gbc: VRAM DMA timing and register fixes - gbc: block invalid VRAM DMA transfer source and target addresses - gba: added LCD color emulation (without it, colors are grossly over-saturated) - gba: removed internal frame blending (use shaders to simulate motion blur if desired) - gba: added Game Boy Player support (adds joypad rumble support to supported games) - gba: SOUND_CTL_H is readable - gb/gbc: PPU renderer is now cycle-based (major accuracy improvement) - gb/gbc: OAM DMA runs in parallel with the CPU - gb/gbc: only HRAM can be accessed during OAM DMA - gb/gbc: fixed serialization of games with SRAM - gb/gbc: disallow up+down or left+right at the same time - gb/gbc: added weak hipass filter to remove DC bias - gb/gbc: STAT OAM+Hblank IRQs only trigger during active display - gb/gbc: fixed underflow in window clamping - gb/gbc/gba: audio mixes internally at 2MHz now instead of 4MHz (does not affect accuracy) - gb/gbc/gba: audio volume reduced for consistency with other systems - fc/sfc/gb/gbc/gba: cheat codes are now stored in universal, decrypted format - ethos: replaced file loader with a proper game library - ethos: added display emulation shader support - ethos: added color emulation option to video settings - ethos: program icon upgraded from 48x48 to 512x512 - ethos: settings and tools windows now use tab frames (less wasted screen space) - ethos: default to optimal (video, audio, input) drivers instead of safest drivers - ethos: input mapping system completely rewritten to support hotplugging and unique device mappings - ruby: added fixes for OpenGL 3.2 on AMD graphics cards - ruby: quark shaders now support user settings inside of manifest - ruby: quark shaders can use integral textures (allows display emulation shaders to work with raw colors) - ruby: add joypad rumble support - ruby: XInput (Xbox 360) controllers now support hotplugging - ruby: added Linux udev joypad driver with hotplug support - phoenix: fixed a rare null pointer dereference issue on Windows - port: target -std=c++11 instead of -std=gnu++11 (do not rely on GNU C++ extensions) - port: added out-of-the-box compilation support for BSD/Clang 3.3+ - port: applied a few Debian upstream patches - cheats: updated to mightymo's 2014-01-02 release; decrypted all Game Genie codes
2014-01-20 08:55:17 +00:00
return;
}
}
if(!IsDialogMessage(GetForegroundWindow(), &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void pApplication::quit() {
PostQuitMessage(0);
}
void pApplication::initialize() {
CoInitialize(0);
InitCommonControls();
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Application_windowProc;
wc.lpszClassName = L"phoenix_window";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Canvas_windowProc;
wc.lpszClassName = L"phoenix_canvas";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Label_windowProc;
wc.lpszClassName = L"phoenix_label";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = Viewport_windowProc;
wc.lpszClassName = L"phoenix_viewport";
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
settings = new Settings;
pKeyboard::initialize();
}
static bool Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false;
GUITHREADINFO info;
memset(&info, 0, sizeof(GUITHREADINFO));
info.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(GetCurrentThreadId(), &info);
Object* object = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
if(object == nullptr) return false;
if(dynamic_cast<Window*>(object)) {
Window& window = (Window&)*object;
if(pWindow::modal.size() > 0 && !pWindow::modal.find(&window.p)) return false;
Keyboard::Keycode keysym = Keysym(wparam, lparam);
if(keysym != Keyboard::Keycode::None) {
if((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && window.onKeyPress) window.onKeyPress(keysym);
if((msg == WM_KEYUP || msg == WM_SYSKEYUP) && window.onKeyRelease) window.onKeyRelease(keysym);
}
return false;
}
if(msg == WM_KEYDOWN) {
if(dynamic_cast<ListView*>(object)) {
ListView& listView = (ListView&)*object;
if(wparam == VK_RETURN) {
if(listView.selected()) return true; //returning true generates LVN_ITEMACTIVATE message
}
} else if(dynamic_cast<LineEdit*>(object)) {
LineEdit& lineEdit = (LineEdit&)*object;
if(wparam == VK_RETURN) {
if(lineEdit.onActivate) lineEdit.onActivate();
}
} else if(dynamic_cast<TextEdit*>(object)) {
TextEdit& textEdit = (TextEdit&)*object;
if(wparam == 'A' && GetKeyState(VK_CONTROL) < 0) {
//Ctrl+A = select all text
//note: this is not a standard accelerator on Windows
Edit_SetSel(textEdit.p.hwnd, 0, ~0);
return true;
} else if(wparam == 'V' && GetKeyState(VK_CONTROL) < 0) {
//Ctrl+V = paste text
//note: this formats Unix (LF) and OS9 (CR) line-endings to Windows (CR+LF) line-endings
//this is necessary as the EDIT control only supports Windows line-endings
OpenClipboard(hwnd);
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
if(handle) {
wchar_t* text = (wchar_t*)GlobalLock(handle);
if(text) {
string data = (const char*)utf8_t(text);
data.replace("\r\n", "\n");
data.replace("\r", "\n");
data.replace("\n", "\r\n");
GlobalUnlock(handle);
utf16_t output(data);
HGLOBAL resource = GlobalAlloc(GMEM_MOVEABLE, (wcslen(output) + 1) * sizeof(wchar_t));
if(resource) {
wchar_t* write = (wchar_t*)GlobalLock(resource);
if(write) {
wcscpy(write, output);
GlobalUnlock(write);
if(SetClipboardData(CF_UNICODETEXT, resource) == FALSE) {
GlobalFree(resource);
}
}
}
}
}
CloseClipboard();
return false;
}
}
}
return false;
}
/*case WM_GETMINMAXINFO: {
MINMAXINFO* mmi = (MINMAXINFO*)lparam;
mmi->ptMinTrackSize.x = 256 + window.p.frameMargin().width;
mmi->ptMinTrackSize.y = 256 + window.p.frameMargin().height;
return TRUE;
break;
}*/
static LRESULT CALLBACK Application_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
Object* object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(object == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam);
Window& window = dynamic_cast<Window*>(object) ? (Window&)*object : *((Widget*)object)->Sizable::state.window;
bool process = true;
if(!pWindow::modal.empty() && !pWindow::modal.find(&window.p)) process = false;
if(applicationState.quit) process = false;
if(process == false) return DefWindowProc(hwnd, msg, wparam, lparam);
switch(msg) {
case WM_CLOSE: window.p.onClose(); return TRUE;
case WM_MOVE: window.p.onMove(); break;
case WM_SIZE: window.p.onSize(); break;
case WM_DROPFILES: window.p.onDrop(wparam); return FALSE;
case WM_ERASEBKGND: if(window.p.onEraseBackground()) return true; break;
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: window.p.onModalBegin(); return FALSE;
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: window.p.onModalEnd(); return FALSE;
}
return Shared_windowProc(DefWindowProc, hwnd, msg, wparam, lparam);
}
}