2014-01-04 12:33:02 +01:00
|
|
|
// Copyright (c) 2012- PPSSPP Project.
|
2013-07-29 05:23:27 -04:00
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
// Official git repository and contact information can be found at
|
|
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
2015-09-19 15:16:31 +02:00
|
|
|
// TODO: Get rid of the internal window.
|
|
|
|
// Tried before but Intel drivers screw up when minimizing, or something ?
|
|
|
|
|
2018-03-23 22:54:12 +01:00
|
|
|
#include "stdafx.h"
|
2023-04-28 21:04:05 +02:00
|
|
|
|
|
|
|
#include "ppsspp_config.h"
|
|
|
|
|
2013-07-28 21:01:49 -07:00
|
|
|
#include "Common/CommonWindows.h"
|
2017-02-23 10:40:55 +01:00
|
|
|
#include "Common/OSVersion.h"
|
|
|
|
|
2015-09-06 19:10:08 +02:00
|
|
|
#include <Windowsx.h>
|
2017-05-05 06:53:48 -07:00
|
|
|
#include <shellapi.h>
|
|
|
|
#include <commctrl.h>
|
2013-09-01 14:06:24 -07:00
|
|
|
#include <string>
|
2013-07-06 21:49:28 +02:00
|
|
|
|
2020-10-04 10:10:55 +02:00
|
|
|
#include "Common/System/Display.h"
|
2020-10-04 10:30:18 +02:00
|
|
|
#include "Common/System/NativeApp.h"
|
|
|
|
#include "Common/System/System.h"
|
2020-08-15 20:53:08 +02:00
|
|
|
#include "Common/TimeUtil.h"
|
2020-09-29 12:19:22 +02:00
|
|
|
#include "Common/StringUtils.h"
|
2020-10-01 13:05:04 +02:00
|
|
|
#include "Common/Data/Text/I18n.h"
|
2020-10-01 09:36:43 +02:00
|
|
|
#include "Common/Input/InputState.h"
|
|
|
|
#include "Common/Input/KeyCodes.h"
|
2020-10-01 09:27:25 +02:00
|
|
|
#include "Common/Thread/ThreadUtil.h"
|
2020-10-01 13:05:04 +02:00
|
|
|
#include "Common/Data/Encoding/Utf8.h"
|
2013-08-26 19:00:16 +02:00
|
|
|
|
2017-05-05 06:53:48 -07:00
|
|
|
#include "Core/Core.h"
|
2015-09-19 14:43:50 +02:00
|
|
|
#include "Core/Config.h"
|
2018-06-16 18:42:31 -07:00
|
|
|
#include "Core/ConfigValues.h"
|
2013-03-11 22:55:29 +01:00
|
|
|
#include "Core/Debugger/SymbolMap.h"
|
2020-08-18 01:07:12 -07:00
|
|
|
#include "Core/Instance.h"
|
2020-10-04 00:25:21 +02:00
|
|
|
#include "Core/KeyMap.h"
|
2017-05-05 06:53:48 -07:00
|
|
|
#include "Core/MIPS/JitCommon/JitCommon.h"
|
|
|
|
#include "Core/MIPS/JitCommon/JitBlockCache.h"
|
2022-07-30 18:21:32 -07:00
|
|
|
#include "Core/Reporting.h"
|
2014-01-01 16:45:37 -08:00
|
|
|
#include "Windows/InputBox.h"
|
2017-05-05 06:53:48 -07:00
|
|
|
#include "Windows/InputDevice.h"
|
2019-05-10 23:25:57 +02:00
|
|
|
#if PPSSPP_API(ANY_GL)
|
2015-11-03 23:22:09 +01:00
|
|
|
#include "Windows/GPU/WindowsGLContext.h"
|
2019-05-04 06:06:50 +08:00
|
|
|
#include "Windows/GEDebugger/GEDebugger.h"
|
|
|
|
#endif
|
2020-05-04 17:33:39 +02:00
|
|
|
#include "Windows/W32Util/DarkMode.h"
|
2023-01-02 18:23:33 +01:00
|
|
|
#include "Windows/W32Util/UAHMenuBar.h"
|
2013-03-11 22:55:29 +01:00
|
|
|
#include "Windows/Debugger/Debugger_Disasm.h"
|
|
|
|
#include "Windows/Debugger/Debugger_MemoryDlg.h"
|
2019-05-04 06:06:50 +08:00
|
|
|
|
|
|
|
#include "Common/GraphicsContext.h"
|
2015-09-19 14:43:50 +02:00
|
|
|
|
2017-05-05 06:53:48 -07:00
|
|
|
#include "Windows/main.h"
|
2019-05-04 06:06:50 +08:00
|
|
|
#ifndef _M_ARM
|
2018-11-01 21:42:12 -07:00
|
|
|
#include "Windows/DinputDevice.h"
|
2019-05-04 06:06:50 +08:00
|
|
|
#endif
|
2013-03-11 22:55:29 +01:00
|
|
|
#include "Windows/EmuThread.h"
|
2017-05-05 06:53:48 -07:00
|
|
|
#include "Windows/resource.h"
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2015-09-19 13:14:05 +02:00
|
|
|
#include "Windows/MainWindow.h"
|
2013-03-11 22:55:29 +01:00
|
|
|
#include "Common/LogManager.h"
|
|
|
|
#include "Common/ConsoleListener.h"
|
|
|
|
#include "Windows/W32Util/DialogManager.h"
|
|
|
|
#include "Windows/W32Util/ShellUtil.h"
|
|
|
|
#include "Windows/W32Util/Misc.h"
|
2014-01-19 11:59:11 -08:00
|
|
|
#include "Windows/RawInput.h"
|
2020-01-22 21:13:50 +08:00
|
|
|
#include "Windows/CaptureDevice.h"
|
2014-01-19 22:54:49 +01:00
|
|
|
#include "Windows/TouchInputHandler.h"
|
2017-05-05 06:53:48 -07:00
|
|
|
#include "Windows/MainWindowMenu.h"
|
2013-03-11 22:55:29 +01:00
|
|
|
#include "GPU/GPUInterface.h"
|
2013-05-22 18:00:06 +02:00
|
|
|
#include "UI/OnScreenDisplay.h"
|
2015-11-13 08:50:10 +01:00
|
|
|
#include "UI/GameSettingsScreen.h"
|
2013-11-27 21:57:17 +08:00
|
|
|
|
2014-02-24 13:28:20 +01:00
|
|
|
#define MOUSEEVENTF_FROMTOUCH_NOPEN 0xFF515780 //http://msdn.microsoft.com/en-us/library/windows/desktop/ms703320(v=vs.85).aspx
|
|
|
|
#define MOUSEEVENTF_MASK_PLUS_PENTOUCH 0xFFFFFF80
|
2014-01-23 18:05:42 +01:00
|
|
|
|
2023-06-04 10:09:20 +02:00
|
|
|
// See https://github.com/unknownbrackets/verysleepy/commit/fc1b1b3bd6081fae3566cdb542d896e413238b71
|
2013-11-30 18:21:47 -08:00
|
|
|
int verysleepy__useSendMessage = 1;
|
|
|
|
|
|
|
|
const UINT WM_VERYSLEEPY_MSG = WM_APP + 0x3117;
|
2022-07-29 15:49:19 +02:00
|
|
|
const UINT WM_USER_GET_BASE_POINTER = WM_APP + 0x3118; // 0xB118
|
2023-05-15 16:38:06 +03:00
|
|
|
const UINT WM_USER_GET_EMULATION_STATE = WM_APP + 0x3119; // 0xB119
|
2022-07-29 15:49:19 +02:00
|
|
|
|
2013-11-30 18:21:47 -08:00
|
|
|
// Respond TRUE to a message with this param value to indicate support.
|
|
|
|
const WPARAM VERYSLEEPY_WPARAM_SUPPORTED = 0;
|
|
|
|
// Respond TRUE to a message wit this param value after filling in the addr name.
|
|
|
|
const WPARAM VERYSLEEPY_WPARAM_GETADDRINFO = 1;
|
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
struct VerySleepy_AddrInfo {
|
2013-11-30 18:21:47 -08:00
|
|
|
// Always zero for now.
|
|
|
|
int flags;
|
|
|
|
// This is the pointer (always passed as 64 bits.)
|
|
|
|
unsigned long long addr;
|
|
|
|
// Write the name here.
|
|
|
|
wchar_t name[256];
|
|
|
|
};
|
|
|
|
|
2013-09-13 15:17:55 -04:00
|
|
|
static std::wstring windowTitle;
|
2013-07-07 10:42:39 +02:00
|
|
|
|
2013-05-04 23:21:06 +02:00
|
|
|
#define TIMER_CURSORUPDATE 1
|
2013-06-12 02:14:53 +08:00
|
|
|
#define TIMER_CURSORMOVEUPDATE 2
|
2019-06-17 00:57:06 +02:00
|
|
|
#define TIMER_WHEELRELEASE 3
|
2013-10-16 17:20:32 +02:00
|
|
|
#define CURSORUPDATE_INTERVAL_MS 1000
|
2013-06-12 02:14:53 +08:00
|
|
|
#define CURSORUPDATE_MOVE_TIMESPAN_MS 500
|
2019-06-17 00:57:06 +02:00
|
|
|
#define WHEELRELEASE_DELAY_MS 16
|
2013-04-18 17:13:00 +08:00
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
namespace MainWindow
|
|
|
|
{
|
2012-11-01 16:19:01 +01:00
|
|
|
HWND hwndMain;
|
2014-06-29 22:13:53 +02:00
|
|
|
HWND hwndDisplay;
|
|
|
|
HWND hwndGameList;
|
2014-01-19 22:54:49 +01:00
|
|
|
TouchInputHandler touchHandler;
|
2013-03-29 21:21:27 +01:00
|
|
|
static HMENU menu;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
HINSTANCE hInst;
|
2013-05-26 14:55:23 -07:00
|
|
|
static int cursorCounter = 0;
|
2013-06-12 02:14:53 +08:00
|
|
|
static int prevCursorX = -1;
|
|
|
|
static int prevCursorY = -1;
|
2015-09-19 15:16:31 +02:00
|
|
|
|
2013-06-12 02:14:53 +08:00
|
|
|
static bool mouseButtonDown = false;
|
|
|
|
static bool hideCursor = false;
|
2014-07-29 18:18:57 -04:00
|
|
|
static int g_WindowState;
|
2015-09-19 15:16:31 +02:00
|
|
|
static bool g_IgnoreWM_SIZE = false;
|
2017-07-30 08:33:02 -07:00
|
|
|
static bool inFullscreenResize = false;
|
2016-02-21 11:50:37 +01:00
|
|
|
static bool inResizeMove = false;
|
2017-12-24 18:03:28 -08:00
|
|
|
static bool hasFocus = true;
|
2021-01-09 14:17:41 -08:00
|
|
|
static bool g_isFullscreen = false;
|
2014-06-29 21:03:24 +02:00
|
|
|
|
2021-12-31 09:10:40 -08:00
|
|
|
static bool disasmMapLoadPending = false;
|
|
|
|
static bool memoryMapLoadPending = false;
|
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
// gross hack
|
|
|
|
bool noFocusPause = false; // TOGGLE_PAUSE state to override pause on lost focus
|
2017-05-05 00:21:57 +02:00
|
|
|
bool trapMouse = true; // Handles some special cases(alt+tab, win menu) when game is running and mouse is confined
|
2015-09-19 13:11:06 +02:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
#define MAX_LOADSTRING 100
|
2013-03-29 21:21:27 +01:00
|
|
|
const TCHAR *szWindowClass = TEXT("PPSSPPWnd");
|
|
|
|
const TCHAR *szDisplayClass = TEXT("PPSSPPDisplay");
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-03-17 14:46:39 +01:00
|
|
|
// Forward declarations of functions included in this code module:
|
2012-11-01 16:19:01 +01:00
|
|
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
2014-06-29 22:13:53 +02:00
|
|
|
LRESULT CALLBACK DisplayProc(HWND, UINT, WPARAM, LPARAM);
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-07-06 19:12:06 -07:00
|
|
|
HWND GetHWND() {
|
2012-11-01 16:19:01 +01:00
|
|
|
return hwndMain;
|
|
|
|
}
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
HWND GetDisplayHWND() {
|
|
|
|
return hwndDisplay;
|
|
|
|
}
|
|
|
|
|
2013-07-06 19:12:06 -07:00
|
|
|
void Init(HINSTANCE hInstance) {
|
2015-09-20 20:32:56 +02:00
|
|
|
// Register classes - Main Window
|
2012-11-01 16:19:01 +01:00
|
|
|
WNDCLASSEX wcex;
|
2015-09-20 20:32:56 +02:00
|
|
|
memset(&wcex, 0, sizeof(wcex));
|
2020-01-06 01:04:07 +08:00
|
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
2015-09-20 20:32:56 +02:00
|
|
|
wcex.style = 0; // Show in taskbar
|
|
|
|
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
|
|
|
wcex.hInstance = hInstance;
|
|
|
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
wcex.hbrBackground = NULL; // Always covered by display window
|
2013-08-26 19:00:16 +02:00
|
|
|
wcex.lpszMenuName = (LPCWSTR)IDR_MENU1;
|
2015-09-20 20:32:56 +02:00
|
|
|
wcex.lpszClassName = szWindowClass;
|
|
|
|
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_PPSSPP);
|
|
|
|
wcex.hIconSm = (HICON)LoadImage(hInstance, (LPCTSTR)IDI_PPSSPP, IMAGE_ICON, 16, 16, LR_SHARED);
|
2012-11-01 16:19:01 +01:00
|
|
|
RegisterClassEx(&wcex);
|
2014-06-29 22:13:53 +02:00
|
|
|
|
2015-09-20 20:32:56 +02:00
|
|
|
WNDCLASSEX wcdisp;
|
|
|
|
memset(&wcdisp, 0, sizeof(wcdisp));
|
2023-01-12 01:01:03 +01:00
|
|
|
// Display Window (contained in main window)
|
2015-09-20 20:32:56 +02:00
|
|
|
wcdisp.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
wcdisp.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
wcdisp.lpfnWndProc = (WNDPROC)DisplayProc;
|
|
|
|
wcdisp.hInstance = hInstance;
|
|
|
|
wcdisp.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
wcdisp.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
|
|
wcdisp.lpszMenuName = 0;
|
|
|
|
wcdisp.lpszClassName = szDisplayClass;
|
|
|
|
wcdisp.hIcon = 0;
|
|
|
|
wcdisp.hIconSm = 0;
|
|
|
|
RegisterClassEx(&wcdisp);
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2013-03-30 17:49:02 +01:00
|
|
|
void SavePosition() {
|
2022-05-28 15:47:12 -07:00
|
|
|
if (g_Config.UseFullScreen() || inFullscreenResize)
|
2014-06-23 20:04:31 +02:00
|
|
|
return;
|
2013-09-13 11:39:40 -04:00
|
|
|
|
2022-12-10 21:09:50 -08:00
|
|
|
WINDOWPLACEMENT placement{};
|
2013-03-30 17:49:02 +01:00
|
|
|
GetWindowPlacement(hwndMain, &placement);
|
|
|
|
if (placement.showCmd == SW_SHOWNORMAL) {
|
|
|
|
RECT rc;
|
|
|
|
GetWindowRect(hwndMain, &rc);
|
|
|
|
g_Config.iWindowX = rc.left;
|
|
|
|
g_Config.iWindowY = rc.top;
|
2013-09-11 00:19:34 +02:00
|
|
|
g_Config.iWindowWidth = rc.right - rc.left;
|
|
|
|
g_Config.iWindowHeight = rc.bottom - rc.top;
|
2013-03-30 17:49:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
static void GetWindowSizeAtResolution(int xres, int yres, int *windowWidth, int *windowHeight) {
|
|
|
|
RECT rc{};
|
|
|
|
rc.right = xres;
|
|
|
|
rc.bottom = yres;
|
|
|
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, TRUE);
|
|
|
|
*windowWidth = rc.right - rc.left;
|
|
|
|
*windowHeight = rc.bottom - rc.top;
|
2013-09-11 00:19:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetWindowSize(int zoom) {
|
2014-06-29 13:11:06 +02:00
|
|
|
AssertCurrentThreadName("Main");
|
2015-05-15 18:04:05 +02:00
|
|
|
// Actually, auto mode should be more granular...
|
2017-04-07 11:04:55 +02:00
|
|
|
int width, height;
|
2015-05-15 18:04:05 +02:00
|
|
|
if (g_Config.IsPortrait()) {
|
2017-04-07 11:04:55 +02:00
|
|
|
GetWindowSizeAtResolution(272 * (int)zoom, 480 * (int)zoom, &width, &height);
|
2015-05-15 18:04:05 +02:00
|
|
|
} else {
|
2017-04-07 11:04:55 +02:00
|
|
|
GetWindowSizeAtResolution(480 * (int)zoom, 272 * (int)zoom, &width, &height);
|
2015-05-15 18:04:05 +02:00
|
|
|
}
|
2017-04-07 11:04:55 +02:00
|
|
|
g_Config.iWindowWidth = width;
|
|
|
|
g_Config.iWindowHeight = height;
|
|
|
|
MoveWindow(hwndMain, g_Config.iWindowX, g_Config.iWindowY, width, height, TRUE);
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
void SetInternalResolution(int res) {
|
2013-09-19 21:18:26 -04:00
|
|
|
if (res >= 0 && res <= RESOLUTION_MAX)
|
2013-09-19 14:32:56 -04:00
|
|
|
g_Config.iInternalResolution = res;
|
|
|
|
else {
|
2013-09-19 21:18:26 -04:00
|
|
|
if (++g_Config.iInternalResolution > RESOLUTION_MAX)
|
2013-09-19 14:32:56 -04:00
|
|
|
g_Config.iInternalResolution = 0;
|
|
|
|
}
|
2020-01-06 01:04:07 +08:00
|
|
|
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED);
|
2013-09-11 00:19:34 +02:00
|
|
|
}
|
|
|
|
|
2013-05-26 14:55:23 -07:00
|
|
|
void CorrectCursor() {
|
2022-05-28 15:47:12 -07:00
|
|
|
bool autoHide = ((g_Config.UseFullScreen() && !mouseButtonDown) || (g_Config.bMouseControl && trapMouse)) && GetUIState() == UISTATE_INGAME;
|
2017-04-26 16:48:55 +02:00
|
|
|
if (autoHide && (hideCursor || g_Config.bMouseControl)) {
|
2013-05-26 14:55:23 -07:00
|
|
|
while (cursorCounter >= 0) {
|
|
|
|
cursorCounter = ShowCursor(FALSE);
|
|
|
|
}
|
2017-04-27 16:29:08 +02:00
|
|
|
if (g_Config.bMouseConfine) {
|
|
|
|
RECT rc;
|
|
|
|
GetClientRect(hwndDisplay, &rc);
|
|
|
|
ClientToScreen(hwndDisplay, reinterpret_cast<POINT*>(&rc.left));
|
|
|
|
ClientToScreen(hwndDisplay, reinterpret_cast<POINT*>(&rc.right));
|
|
|
|
ClipCursor(&rc);
|
|
|
|
}
|
2013-05-26 14:55:23 -07:00
|
|
|
} else {
|
2013-06-12 02:14:53 +08:00
|
|
|
hideCursor = !autoHide;
|
2013-05-26 14:55:23 -07:00
|
|
|
if (cursorCounter < 0) {
|
|
|
|
cursorCounter = ShowCursor(TRUE);
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
2017-05-05 00:21:57 +02:00
|
|
|
ClipCursor(NULL);
|
2013-05-26 14:55:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-03 00:01:37 +02:00
|
|
|
void ReleaseMouseWheel() {
|
2023-05-25 09:28:55 +02:00
|
|
|
// For simplicity release both wheel events
|
|
|
|
KeyInput key;
|
|
|
|
key.deviceId = DEVICE_ID_MOUSE;
|
|
|
|
key.flags = KEY_UP;
|
|
|
|
key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
|
|
|
|
NativeKey(key);
|
|
|
|
key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
|
|
|
|
NativeKey(key);
|
2019-06-17 00:57:06 +02:00
|
|
|
}
|
|
|
|
|
2015-09-20 21:54:27 -07:00
|
|
|
static void HandleSizeChange(int newSizingType) {
|
|
|
|
SavePosition();
|
|
|
|
Core_NotifyWindowHidden(false);
|
|
|
|
if (!g_Config.bPauseWhenMinimized) {
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::WINDOW_MINIMIZED, "false");
|
2015-09-20 21:54:27 -07:00
|
|
|
}
|
|
|
|
|
2023-08-10 10:28:25 +02:00
|
|
|
int width, height;
|
|
|
|
W32Util::GetWindowRes(hwndMain, &width, &height);
|
2015-09-20 21:54:27 -07:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2018-02-26 16:39:38 +01:00
|
|
|
DEBUG_LOG(SYSTEM, "Pixel width/height: %dx%d", PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
|
2017-03-06 13:50:22 +01:00
|
|
|
|
2017-01-17 17:21:00 +07:00
|
|
|
if (UpdateScreenScale(width, height)) {
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED);
|
|
|
|
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED);
|
2015-09-20 21:54:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Don't save the window state if fullscreen.
|
2022-05-28 15:47:12 -07:00
|
|
|
if (!g_Config.UseFullScreen()) {
|
2015-09-20 21:54:27 -07:00
|
|
|
g_WindowState = newSizingType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-15 23:07:24 +01:00
|
|
|
void ToggleFullscreen(HWND hWnd, bool goingFullscreen) {
|
2015-12-31 16:59:40 +01:00
|
|
|
GraphicsContext *graphicsContext = PSP_CoreParameter().graphicsContext;
|
2014-06-29 21:03:24 +02:00
|
|
|
// Make sure no rendering is happening during the switch.
|
2015-12-31 16:59:40 +01:00
|
|
|
if (graphicsContext) {
|
|
|
|
graphicsContext->Pause();
|
2015-09-20 19:45:36 +02:00
|
|
|
}
|
2015-09-19 15:16:31 +02:00
|
|
|
|
2017-07-30 08:33:02 -07:00
|
|
|
WINDOWPLACEMENT placement = { sizeof(WINDOWPLACEMENT) };
|
|
|
|
GetWindowPlacement(hwndMain, &placement);
|
|
|
|
|
2015-09-19 15:16:31 +02:00
|
|
|
int oldWindowState = g_WindowState;
|
2017-07-30 08:33:02 -07:00
|
|
|
inFullscreenResize = true;
|
2015-09-19 15:16:31 +02:00
|
|
|
g_IgnoreWM_SIZE = true;
|
2014-06-29 21:03:24 +02:00
|
|
|
|
2015-09-20 20:32:56 +02:00
|
|
|
DWORD dwStyle;
|
2013-09-11 00:19:34 +02:00
|
|
|
|
2014-07-16 23:50:46 -04:00
|
|
|
if (!goingFullscreen) {
|
2015-09-20 20:32:56 +02:00
|
|
|
dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
|
2014-07-20 17:28:25 +02:00
|
|
|
|
2015-09-20 20:32:56 +02:00
|
|
|
// Remove popup
|
|
|
|
dwStyle &= ~WS_POPUP;
|
|
|
|
// Re-add caption and border styles.
|
|
|
|
dwStyle |= WS_OVERLAPPEDWINDOW;
|
2014-07-16 23:50:46 -04:00
|
|
|
} else {
|
2014-07-29 18:18:57 -04:00
|
|
|
// If the window was maximized before going fullscreen, make sure to restore first
|
|
|
|
// in order not to have the taskbar show up on top of PPSSPP.
|
2017-07-30 08:33:02 -07:00
|
|
|
if (oldWindowState == SIZE_MAXIMIZED || placement.showCmd == SW_SHOWMAXIMIZED) {
|
2014-07-29 18:18:57 -04:00
|
|
|
ShowWindow(hwndMain, SW_RESTORE);
|
|
|
|
}
|
2013-09-27 15:34:13 -04:00
|
|
|
|
2014-07-16 23:50:46 -04:00
|
|
|
// Remove caption and border styles.
|
2015-09-20 20:32:56 +02:00
|
|
|
dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
|
|
|
|
dwStyle &= ~WS_OVERLAPPEDWINDOW;
|
|
|
|
// Add Popup
|
|
|
|
dwStyle |= WS_POPUP;
|
2014-02-12 10:36:40 +01:00
|
|
|
}
|
2014-06-29 21:03:24 +02:00
|
|
|
|
2015-09-20 20:32:56 +02:00
|
|
|
::SetWindowLong(hWnd, GWL_STYLE, dwStyle);
|
2013-09-11 00:19:34 +02:00
|
|
|
|
2022-09-29 18:51:21 +02:00
|
|
|
// Remove the menu bar. This can trigger WM_SIZE because the contents change size.
|
|
|
|
::SetMenu(hWnd, goingFullscreen || !g_Config.bShowMenuBar ? NULL : menu);
|
2013-09-11 00:19:34 +02:00
|
|
|
|
2022-05-28 15:47:12 -07:00
|
|
|
if (g_Config.UseFullScreen() != goingFullscreen) {
|
|
|
|
g_Config.bFullScreen = goingFullscreen;
|
|
|
|
g_Config.iForceFullScreen = -1;
|
|
|
|
}
|
2021-01-09 14:17:41 -08:00
|
|
|
g_isFullscreen = goingFullscreen;
|
2015-09-19 15:16:31 +02:00
|
|
|
|
|
|
|
g_IgnoreWM_SIZE = false;
|
|
|
|
|
2014-07-17 00:06:52 -04:00
|
|
|
// Resize to the appropriate view.
|
2014-07-29 18:18:57 -04:00
|
|
|
// If we're returning to window mode, re-apply the appropriate size setting.
|
|
|
|
if (goingFullscreen) {
|
2017-07-30 08:33:02 -07:00
|
|
|
if (g_Config.bFullScreenMulti) {
|
|
|
|
// Maximize isn't enough to display on all monitors.
|
|
|
|
// Remember that negative coordinates may be valid.
|
|
|
|
int totalX = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
|
|
|
int totalY = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
|
|
|
int totalWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
|
|
|
int totalHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
|
|
|
MoveWindow(hwndMain, totalX, totalY, totalWidth, totalHeight, TRUE);
|
|
|
|
HandleSizeChange(oldWindowState);
|
2023-05-06 08:56:34 -07:00
|
|
|
ShowWindow(hwndMain, SW_SHOW);
|
2017-07-30 08:33:02 -07:00
|
|
|
} else {
|
|
|
|
ShowWindow(hwndMain, SW_MAXIMIZE);
|
|
|
|
}
|
2014-07-29 18:18:57 -04:00
|
|
|
} else {
|
2015-09-19 15:16:31 +02:00
|
|
|
ShowWindow(hwndMain, oldWindowState == SIZE_MAXIMIZED ? SW_MAXIMIZE : SW_RESTORE);
|
2017-07-30 08:33:02 -07:00
|
|
|
if (g_Config.bFullScreenMulti && oldWindowState != SIZE_MAXIMIZED) {
|
|
|
|
// Return the screen to where it was.
|
|
|
|
MoveWindow(hwndMain, g_Config.iWindowX, g_Config.iWindowY, g_Config.iWindowWidth, g_Config.iWindowHeight, TRUE);
|
|
|
|
}
|
2015-09-20 21:54:27 -07:00
|
|
|
if (oldWindowState == SIZE_MAXIMIZED) {
|
|
|
|
// WM_SIZE wasn't sent, since the size didn't change (it was full screen before and after.)
|
|
|
|
HandleSizeChange(oldWindowState);
|
|
|
|
}
|
2014-07-29 18:18:57 -04:00
|
|
|
}
|
2013-09-11 00:19:34 +02:00
|
|
|
|
2017-07-30 08:33:02 -07:00
|
|
|
inFullscreenResize = false;
|
2013-09-11 00:19:34 +02:00
|
|
|
CorrectCursor();
|
2013-09-27 15:34:13 -04:00
|
|
|
|
2014-07-17 00:03:41 -04:00
|
|
|
ShowOwnedPopups(hwndMain, goingFullscreen ? FALSE : TRUE);
|
2014-07-16 23:50:46 -04:00
|
|
|
W32Util::MakeTopMost(hwndMain, g_Config.bTopMost);
|
2014-06-29 21:03:24 +02:00
|
|
|
|
2015-02-15 23:07:24 +01:00
|
|
|
WindowsRawInput::NotifyMenu();
|
2015-09-20 19:45:36 +02:00
|
|
|
|
2015-12-31 16:59:40 +01:00
|
|
|
if (graphicsContext) {
|
|
|
|
graphicsContext->Resume();
|
2015-09-20 19:45:36 +02:00
|
|
|
}
|
2013-09-11 00:19:34 +02:00
|
|
|
}
|
|
|
|
|
2015-12-25 19:18:32 -08:00
|
|
|
void Minimize() {
|
|
|
|
ShowWindow(hwndMain, SW_MINIMIZE);
|
2017-12-24 18:03:28 -08:00
|
|
|
InputDevice::LoseFocus();
|
2015-12-25 19:18:32 -08:00
|
|
|
}
|
|
|
|
|
2013-10-15 13:10:14 +02:00
|
|
|
RECT DetermineWindowRectangle() {
|
2017-04-08 11:36:05 +02:00
|
|
|
const int virtualScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
|
|
|
const int virtualScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
|
|
|
const int virtualScreenX = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
|
|
|
const int virtualScreenY = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
|
|
|
const int currentScreenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
|
|
const int currentScreenHeight = GetSystemMetrics(SM_CYSCREEN);
|
2013-10-15 13:10:14 +02:00
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
bool resetPositionX = true;
|
|
|
|
bool resetPositionY = true;
|
|
|
|
|
2022-05-28 15:47:12 -07:00
|
|
|
if (g_Config.iWindowWidth > 0 && g_Config.iWindowHeight > 0 && !g_Config.UseFullScreen()) {
|
2017-04-08 11:36:05 +02:00
|
|
|
bool visibleHorizontally = ((g_Config.iWindowX + g_Config.iWindowWidth) >= virtualScreenX) &&
|
|
|
|
((g_Config.iWindowX + g_Config.iWindowWidth) < (virtualScreenWidth + g_Config.iWindowWidth));
|
2013-10-15 13:10:14 +02:00
|
|
|
|
2017-04-08 11:36:05 +02:00
|
|
|
bool visibleVertically = ((g_Config.iWindowY + g_Config.iWindowHeight) >= virtualScreenY) &&
|
|
|
|
((g_Config.iWindowY + g_Config.iWindowHeight) < (virtualScreenHeight + g_Config.iWindowHeight));
|
2013-10-15 13:10:14 +02:00
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
if (visibleHorizontally)
|
|
|
|
resetPositionX = false;
|
2017-04-08 18:40:48 +02:00
|
|
|
if (visibleVertically)
|
2017-04-07 11:04:55 +02:00
|
|
|
resetPositionY = false;
|
2013-10-15 13:10:14 +02:00
|
|
|
}
|
|
|
|
|
2017-04-08 23:32:58 +02:00
|
|
|
// Try to workaround #9563.
|
|
|
|
if (!resetPositionY && g_Config.iWindowY < 0) {
|
|
|
|
g_Config.iWindowY = 0;
|
|
|
|
}
|
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
int windowWidth = g_Config.iWindowWidth;
|
|
|
|
int windowHeight = g_Config.iWindowHeight;
|
2013-10-15 13:10:14 +02:00
|
|
|
|
|
|
|
// First, get the w/h right.
|
2017-04-07 11:04:55 +02:00
|
|
|
if (windowWidth <= 0 || windowHeight <= 0) {
|
2015-05-15 18:04:05 +02:00
|
|
|
bool portrait = g_Config.IsPortrait();
|
2017-03-17 13:22:00 +01:00
|
|
|
|
|
|
|
// We want to adjust for DPI but still get an integer pixel scaling ratio.
|
2020-01-06 01:04:07 +08:00
|
|
|
double dpi_scale = 96.0 / System_GetPropertyFloat(SYSPROP_DISPLAY_DPI);
|
2017-03-17 13:22:00 +01:00
|
|
|
int scale = (int)ceil(2.0 / dpi_scale);
|
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
GetWindowSizeAtResolution(scale * (portrait ? 272 : 480), scale * (portrait ? 480 : 272), &windowWidth, &windowHeight);
|
2013-10-15 13:10:14 +02:00
|
|
|
}
|
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
// Then center if necessary. One dimension at a time.
|
2017-04-08 23:33:34 +02:00
|
|
|
// Max is to make sure that if we end up making the window bigger than the screen (which is not ideal), the top left
|
|
|
|
// corner, and thus the menu etc, will be visible. Also potential workaround for #9563.
|
2017-07-30 08:33:02 -07:00
|
|
|
int x = g_Config.iWindowX;
|
|
|
|
int y = g_Config.iWindowY;
|
2017-04-07 11:04:55 +02:00
|
|
|
if (resetPositionX) {
|
2017-07-30 08:33:02 -07:00
|
|
|
x = std::max(0, (currentScreenWidth - windowWidth) / 2);
|
2017-04-07 11:04:55 +02:00
|
|
|
}
|
|
|
|
if (resetPositionY) {
|
2017-07-30 08:33:02 -07:00
|
|
|
y = std::max(0, (currentScreenHeight - windowHeight) / 2);
|
2013-10-15 13:10:14 +02:00
|
|
|
}
|
|
|
|
|
2017-04-07 11:04:55 +02:00
|
|
|
RECT rc;
|
2017-07-30 08:33:02 -07:00
|
|
|
rc.left = x;
|
|
|
|
rc.right = rc.left + windowWidth;
|
|
|
|
rc.top = y;
|
|
|
|
rc.bottom = rc.top + windowHeight;
|
2013-10-15 13:10:14 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-09-13 15:17:55 -04:00
|
|
|
void UpdateWindowTitle() {
|
2020-08-18 01:07:12 -07:00
|
|
|
std::wstring title = windowTitle;
|
|
|
|
if (PPSSPP_ID >= 1 && GetInstancePeerCount() > 1) {
|
|
|
|
title.append(ConvertUTF8ToWString(StringFromFormat(" (instance: %d)", (int)PPSSPP_ID)));
|
|
|
|
}
|
|
|
|
SetWindowText(hwndMain, title.c_str());
|
2013-09-13 15:17:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetWindowTitle(const wchar_t *title) {
|
|
|
|
windowTitle = title;
|
|
|
|
}
|
|
|
|
|
2014-07-17 00:06:52 -04:00
|
|
|
BOOL Show(HINSTANCE hInstance) {
|
2013-09-22 14:44:35 -04:00
|
|
|
hInst = hInstance; // Store instance handle in our global variable.
|
|
|
|
RECT rc = DetermineWindowRectangle();
|
|
|
|
|
2013-03-29 21:21:27 +01:00
|
|
|
u32 style = WS_OVERLAPPEDWINDOW;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-08-26 19:00:16 +02:00
|
|
|
hwndMain = CreateWindowEx(0,szWindowClass, L"", style,
|
2013-06-08 08:32:07 +08:00
|
|
|
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
|
2012-11-01 16:19:01 +01:00
|
|
|
if (!hwndMain)
|
|
|
|
return FALSE;
|
|
|
|
|
2015-09-20 20:32:56 +02:00
|
|
|
SetWindowLong(hwndMain, GWL_EXSTYLE, WS_EX_APPWINDOW);
|
|
|
|
|
2013-09-11 00:19:34 +02:00
|
|
|
RECT rcClient;
|
|
|
|
GetClientRect(hwndMain, &rcClient);
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
hwndDisplay = CreateWindowEx(0, szDisplayClass, L"", WS_CHILD | WS_VISIBLE,
|
|
|
|
0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hwndMain, 0, hInstance, 0);
|
|
|
|
if (!hwndDisplay)
|
|
|
|
return FALSE;
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
menu = GetMenu(hwndMain);
|
2013-08-29 18:27:11 -04:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
MENUINFO info;
|
|
|
|
ZeroMemory(&info,sizeof(MENUINFO));
|
|
|
|
info.cbSize = sizeof(MENUINFO);
|
|
|
|
info.cyMax = 0;
|
|
|
|
info.dwStyle = MNS_CHECKORBMP;
|
|
|
|
info.fMask = MIM_STYLE;
|
2013-07-29 15:34:30 -04:00
|
|
|
for (int i = 0; i < GetMenuItemCount(menu); i++) {
|
2015-09-19 13:11:06 +02:00
|
|
|
SetMenuInfo(GetSubMenu(menu,i), &info);
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
2017-04-04 21:01:05 -07:00
|
|
|
|
|
|
|
// Always translate first: translating resets the menu.
|
|
|
|
TranslateMenus(hwndMain, menu);
|
2013-06-08 08:32:07 +08:00
|
|
|
UpdateMenus();
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-07-29 04:46:40 -04:00
|
|
|
// Accept dragged files.
|
2012-11-01 16:19:01 +01:00
|
|
|
DragAcceptFiles(hwndMain, TRUE);
|
|
|
|
|
2013-06-12 02:14:53 +08:00
|
|
|
hideCursor = true;
|
2013-06-08 08:32:07 +08:00
|
|
|
SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0);
|
2014-06-29 16:24:20 -04:00
|
|
|
|
2022-05-28 15:47:12 -07:00
|
|
|
ToggleFullscreen(hwndMain, g_Config.UseFullScreen());
|
2013-06-08 08:32:07 +08:00
|
|
|
|
2013-07-06 13:47:37 -04:00
|
|
|
W32Util::MakeTopMost(hwndMain, g_Config.bTopMost);
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
touchHandler.registerTouchWindow(hwndDisplay);
|
2013-04-16 21:12:55 +02:00
|
|
|
|
2014-01-19 11:59:11 -08:00
|
|
|
WindowsRawInput::Init();
|
2013-07-07 10:42:39 +02:00
|
|
|
|
2013-10-16 17:20:32 +02:00
|
|
|
SetFocus(hwndMain);
|
2014-03-24 20:13:35 -04:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-11-13 22:10:37 +01:00
|
|
|
void CreateDisasmWindow() {
|
|
|
|
if (!disasmWindow) {
|
|
|
|
disasmWindow = new CDisasm(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
|
|
|
|
DialogManager::AddDlg(disasmWindow);
|
|
|
|
}
|
2021-12-31 09:10:40 -08:00
|
|
|
if (disasmMapLoadPending)
|
|
|
|
disasmWindow->NotifyMapLoaded();
|
|
|
|
disasmMapLoadPending = false;
|
2021-11-13 22:10:37 +01:00
|
|
|
}
|
2013-08-26 14:19:46 +02:00
|
|
|
|
2021-11-13 22:10:37 +01:00
|
|
|
void CreateGeDebuggerWindow() {
|
2019-05-10 23:25:57 +02:00
|
|
|
#if PPSSPP_API(ANY_GL)
|
2021-11-13 22:47:29 +01:00
|
|
|
if (!geDebuggerWindow) {
|
2021-11-13 22:10:37 +01:00
|
|
|
geDebuggerWindow = new CGEDebugger(MainWindow::GetHInstance(), MainWindow::GetHWND());
|
|
|
|
DialogManager::AddDlg(geDebuggerWindow);
|
|
|
|
}
|
2021-11-13 22:47:29 +01:00
|
|
|
#endif
|
2021-11-13 22:10:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMemoryWindow() {
|
|
|
|
if (!memoryWindow) {
|
|
|
|
memoryWindow = new CMemoryDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
|
|
|
|
DialogManager::AddDlg(memoryWindow);
|
|
|
|
}
|
2021-12-31 09:10:40 -08:00
|
|
|
if (memoryMapLoadPending)
|
|
|
|
memoryWindow->NotifyMapLoaded();
|
|
|
|
memoryMapLoadPending = false;
|
2013-08-26 14:19:46 +02:00
|
|
|
}
|
|
|
|
|
2021-11-13 22:24:30 +01:00
|
|
|
void CreateVFPUWindow() {
|
|
|
|
if (!vfpudlg) {
|
|
|
|
vfpudlg = new CVFPUDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
|
|
|
|
DialogManager::AddDlg(vfpudlg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-31 09:10:40 -08:00
|
|
|
void NotifyDebuggerMapLoaded() {
|
|
|
|
disasmMapLoadPending = disasmWindow == nullptr;
|
|
|
|
memoryMapLoadPending = memoryWindow == nullptr;
|
|
|
|
if (!disasmMapLoadPending)
|
|
|
|
disasmWindow->NotifyMapLoaded();
|
|
|
|
if (!memoryMapLoadPending)
|
|
|
|
memoryWindow->NotifyMapLoaded();
|
|
|
|
}
|
|
|
|
|
2014-02-14 21:17:36 -08:00
|
|
|
void DestroyDebugWindows() {
|
2020-09-24 00:17:31 +02:00
|
|
|
DialogManager::RemoveDlg(disasmWindow);
|
|
|
|
if (disasmWindow)
|
|
|
|
delete disasmWindow;
|
2021-11-13 22:10:37 +01:00
|
|
|
disasmWindow = nullptr;
|
2020-01-06 01:04:07 +08:00
|
|
|
|
2019-05-10 23:25:57 +02:00
|
|
|
#if PPSSPP_API(ANY_GL)
|
2014-02-14 21:17:36 -08:00
|
|
|
DialogManager::RemoveDlg(geDebuggerWindow);
|
|
|
|
if (geDebuggerWindow)
|
|
|
|
delete geDebuggerWindow;
|
2021-11-13 22:10:37 +01:00
|
|
|
geDebuggerWindow = nullptr;
|
2019-05-04 06:06:50 +08:00
|
|
|
#endif
|
|
|
|
|
2020-09-24 00:17:31 +02:00
|
|
|
DialogManager::RemoveDlg(memoryWindow);
|
|
|
|
if (memoryWindow)
|
|
|
|
delete memoryWindow;
|
2021-11-13 22:10:37 +01:00
|
|
|
memoryWindow = nullptr;
|
2021-11-13 22:24:30 +01:00
|
|
|
|
|
|
|
DialogManager::RemoveDlg(vfpudlg);
|
|
|
|
if (vfpudlg)
|
|
|
|
delete vfpudlg;
|
|
|
|
vfpudlg = nullptr;
|
2014-02-14 21:17:36 -08:00
|
|
|
}
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
2014-06-23 20:04:31 +02:00
|
|
|
static bool firstErase = true;
|
2013-09-23 23:56:32 -04:00
|
|
|
|
2013-07-29 15:34:30 -04:00
|
|
|
switch (message) {
|
2014-06-29 22:13:53 +02:00
|
|
|
case WM_ACTIVATE:
|
|
|
|
if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
|
|
|
|
g_activeWindow = WINDOW_MAINWINDOW;
|
2014-06-29 13:11:06 +02:00
|
|
|
}
|
2012-11-01 16:19:01 +01:00
|
|
|
break;
|
2013-03-29 19:32:20 +01:00
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
case WM_SIZE:
|
|
|
|
break;
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
case WM_SETFOCUS:
|
|
|
|
break;
|
2014-06-23 20:23:11 +02:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
case WM_ERASEBKGND:
|
2014-06-23 20:04:31 +02:00
|
|
|
if (firstErase) {
|
|
|
|
firstErase = false;
|
|
|
|
// Paint black on first erase while OpenGL stuff is loading
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
// Then never erase, let the OpenGL drawing take care of everything.
|
|
|
|
return 1;
|
2013-03-29 19:32:20 +01:00
|
|
|
|
2023-04-02 10:41:26 +02:00
|
|
|
// Mouse input. We send asynchronous touch events for minimal latency.
|
2012-11-01 16:19:01 +01:00
|
|
|
case WM_LBUTTONDOWN:
|
2014-02-24 13:28:20 +01:00
|
|
|
if (!touchHandler.hasTouch() ||
|
|
|
|
(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
|
2014-01-23 18:05:42 +01:00
|
|
|
{
|
2013-07-09 22:51:02 +02:00
|
|
|
// Hack: Take the opportunity to show the cursor.
|
|
|
|
mouseButtonDown = true;
|
2013-03-31 19:15:59 -07:00
|
|
|
|
2023-02-25 13:09:44 +01:00
|
|
|
float x = GET_X_LPARAM(lParam) * g_display.dpi_scale_x;
|
|
|
|
float y = GET_Y_LPARAM(lParam) * g_display.dpi_scale_y;
|
2017-03-14 21:40:17 -07:00
|
|
|
WindowsRawInput::SetMousePos(x, y);
|
2013-06-01 23:34:50 +02:00
|
|
|
|
|
|
|
TouchInput touch;
|
|
|
|
touch.id = 0;
|
|
|
|
touch.flags = TOUCH_DOWN;
|
2017-03-14 21:40:17 -07:00
|
|
|
touch.x = x;
|
|
|
|
touch.y = y;
|
2013-06-01 23:34:50 +02:00
|
|
|
NativeTouch(touch);
|
2013-07-09 22:51:02 +02:00
|
|
|
SetCapture(hWnd);
|
2014-02-24 13:28:20 +01:00
|
|
|
|
2015-09-07 21:21:17 +02:00
|
|
|
// Simulate doubleclick, doesn't work with RawInput enabled
|
|
|
|
static double lastMouseDown;
|
2023-05-25 09:28:55 +02:00
|
|
|
static float lastMouseDownX = -1.0f;
|
|
|
|
static float lastMouseDownY = -1.0f;
|
2020-09-24 23:52:03 +02:00
|
|
|
double now = time_now_d();
|
2015-09-07 21:22:58 +02:00
|
|
|
if ((now - lastMouseDown) < 0.001 * GetDoubleClickTime()) {
|
2023-05-25 09:28:55 +02:00
|
|
|
float dx = lastMouseDownX - x;
|
|
|
|
float dy = lastMouseDownX - x;
|
|
|
|
float distSq = dx * dx + dy * dy;
|
|
|
|
if (distSq < 3.0f*3.0f && !g_Config.bShowTouchControls && !g_Config.bMouseControl && GetUIState() == UISTATE_INGAME && g_Config.bFullscreenOnDoubleclick) {
|
2022-05-28 15:47:12 -07:00
|
|
|
SendToggleFullscreen(!g_Config.UseFullScreen());
|
2015-09-07 21:21:17 +02:00
|
|
|
}
|
2015-09-07 22:25:38 +02:00
|
|
|
lastMouseDown = 0.0;
|
|
|
|
} else {
|
2020-10-10 19:01:40 +02:00
|
|
|
lastMouseDown = now;
|
2015-09-07 21:21:17 +02:00
|
|
|
}
|
2023-05-25 09:28:55 +02:00
|
|
|
lastMouseDownX = x;
|
|
|
|
lastMouseDownY = y;
|
2013-03-29 18:50:08 +01:00
|
|
|
}
|
2013-07-29 15:34:30 -04:00
|
|
|
break;
|
2013-03-29 18:50:08 +01:00
|
|
|
|
|
|
|
case WM_MOUSEMOVE:
|
2014-02-24 13:28:20 +01:00
|
|
|
if (!touchHandler.hasTouch() ||
|
|
|
|
(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
|
2013-03-29 18:50:08 +01:00
|
|
|
{
|
2013-06-12 02:14:53 +08:00
|
|
|
// Hack: Take the opportunity to show the cursor.
|
|
|
|
mouseButtonDown = (wParam & MK_LBUTTON) != 0;
|
|
|
|
int cursorX = GET_X_LPARAM(lParam);
|
|
|
|
int cursorY = GET_Y_LPARAM(lParam);
|
|
|
|
if (abs(cursorX - prevCursorX) > 1 || abs(cursorY - prevCursorY) > 1) {
|
|
|
|
hideCursor = false;
|
|
|
|
SetTimer(hwndMain, TIMER_CURSORMOVEUPDATE, CURSORUPDATE_MOVE_TIMESPAN_MS, 0);
|
|
|
|
}
|
|
|
|
prevCursorX = cursorX;
|
|
|
|
prevCursorY = cursorY;
|
|
|
|
|
2023-02-25 13:09:44 +01:00
|
|
|
float x = (float)cursorX * g_display.dpi_scale_x;
|
|
|
|
float y = (float)cursorY * g_display.dpi_scale_y;
|
2017-03-14 21:40:17 -07:00
|
|
|
WindowsRawInput::SetMousePos(x, y);
|
2013-06-01 23:34:50 +02:00
|
|
|
|
|
|
|
if (wParam & MK_LBUTTON) {
|
|
|
|
TouchInput touch;
|
|
|
|
touch.id = 0;
|
|
|
|
touch.flags = TOUCH_MOVE;
|
2017-03-14 21:40:17 -07:00
|
|
|
touch.x = x;
|
|
|
|
touch.y = y;
|
2013-06-01 23:34:50 +02:00
|
|
|
NativeTouch(touch);
|
2013-03-31 19:15:59 -07:00
|
|
|
}
|
2013-03-29 18:50:08 +01:00
|
|
|
}
|
2012-11-01 16:19:01 +01:00
|
|
|
break;
|
|
|
|
|
2013-03-29 18:50:08 +01:00
|
|
|
case WM_LBUTTONUP:
|
2014-02-24 13:28:20 +01:00
|
|
|
if (!touchHandler.hasTouch() ||
|
|
|
|
(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
|
2013-03-29 18:50:08 +01:00
|
|
|
{
|
2013-07-09 22:51:02 +02:00
|
|
|
// Hack: Take the opportunity to hide the cursor.
|
|
|
|
mouseButtonDown = false;
|
2017-03-14 21:40:17 -07:00
|
|
|
|
2023-02-25 13:09:44 +01:00
|
|
|
float x = (float)GET_X_LPARAM(lParam) * g_display.dpi_scale_x;
|
|
|
|
float y = (float)GET_Y_LPARAM(lParam) * g_display.dpi_scale_y;
|
2017-03-14 21:40:17 -07:00
|
|
|
WindowsRawInput::SetMousePos(x, y);
|
|
|
|
|
2013-06-01 23:34:50 +02:00
|
|
|
TouchInput touch;
|
|
|
|
touch.id = 0;
|
|
|
|
touch.flags = TOUCH_UP;
|
2017-03-14 21:40:17 -07:00
|
|
|
touch.x = x;
|
|
|
|
touch.y = y;
|
2013-06-01 23:34:50 +02:00
|
|
|
NativeTouch(touch);
|
2013-07-09 22:51:02 +02:00
|
|
|
ReleaseCapture();
|
2013-03-29 18:50:08 +01:00
|
|
|
}
|
2013-07-29 15:34:30 -04:00
|
|
|
break;
|
2013-03-29 18:50:08 +01:00
|
|
|
|
2013-04-16 21:12:55 +02:00
|
|
|
case WM_TOUCH:
|
2020-09-24 00:17:31 +02:00
|
|
|
touchHandler.handleTouchEvent(hWnd, message, wParam, lParam);
|
|
|
|
return 0;
|
2013-04-16 21:12:55 +02:00
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
default:
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2020-01-06 01:04:07 +08:00
|
|
|
|
2023-01-12 01:01:03 +01:00
|
|
|
RECT MapRectFromClientToWndCoords(HWND hwnd, const RECT & r)
|
|
|
|
{
|
|
|
|
RECT wnd_coords = r;
|
|
|
|
|
|
|
|
// map to screen
|
|
|
|
MapWindowPoints(hwnd, NULL, reinterpret_cast<POINT *>(&wnd_coords), 2);
|
|
|
|
|
|
|
|
RECT scr_coords;
|
|
|
|
GetWindowRect(hwnd, &scr_coords);
|
|
|
|
|
|
|
|
// map to window coords by substracting the window coord origin in
|
|
|
|
// screen coords.
|
|
|
|
OffsetRect(&wnd_coords, -scr_coords.left, -scr_coords.top);
|
|
|
|
|
|
|
|
return wnd_coords;
|
|
|
|
}
|
|
|
|
|
|
|
|
RECT GetNonclientMenuBorderRect(HWND hwnd)
|
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
GetClientRect(hwnd, &r);
|
|
|
|
r = MapRectFromClientToWndCoords(hwnd, r);
|
|
|
|
int y = r.top - 1;
|
|
|
|
return {
|
|
|
|
r.left,
|
|
|
|
y,
|
|
|
|
r.right,
|
|
|
|
y + 1
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
2023-01-02 18:23:33 +01:00
|
|
|
LRESULT darkResult = 0;
|
|
|
|
if (UAHDarkModeWndProc(hWnd, message, wParam, lParam, &darkResult)) {
|
|
|
|
return darkResult;
|
|
|
|
}
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
switch (message) {
|
|
|
|
case WM_CREATE:
|
2017-02-23 10:40:55 +01:00
|
|
|
if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) {
|
|
|
|
// Remove the D3D11 choice on versions below XP
|
|
|
|
RemoveMenu(GetMenu(hWnd), ID_OPTIONS_DIRECT3D11, MF_BYCOMMAND);
|
|
|
|
}
|
2020-05-04 17:33:39 +02:00
|
|
|
if (g_darkModeSupported) {
|
|
|
|
SendMessageW(hWnd, WM_THEMECHANGED, 0, 0);
|
|
|
|
}
|
2014-06-29 22:13:53 +02:00
|
|
|
break;
|
2020-01-06 01:04:07 +08:00
|
|
|
|
2022-07-29 15:49:19 +02:00
|
|
|
case WM_USER_GET_BASE_POINTER:
|
2022-07-30 18:21:32 -07:00
|
|
|
Reporting::NotifyDebugger();
|
2022-07-29 15:49:19 +02:00
|
|
|
switch (lParam) {
|
2023-02-05 13:45:29 +01:00
|
|
|
case 0: return (u32)(u64)Memory::base;
|
|
|
|
case 1: return (u32)((u64)Memory::base >> 32);
|
|
|
|
case 2: return (u32)(u64)(&Memory::base);
|
|
|
|
case 3: return (u32)((u64)(&Memory::base) >> 32);
|
2022-07-29 15:49:19 +02:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-05-15 16:38:06 +03:00
|
|
|
case WM_USER_GET_EMULATION_STATE:
|
|
|
|
return (u32)(Core_IsActive() && GetUIState() == UISTATE_INGAME);
|
|
|
|
|
2023-01-12 01:01:03 +01:00
|
|
|
// Hack to kill the white line underneath the menubar.
|
|
|
|
// From https://stackoverflow.com/questions/57177310/how-to-paint-over-white-line-between-menu-bar-and-client-area-of-window
|
|
|
|
case WM_NCPAINT:
|
|
|
|
case WM_NCACTIVATE:
|
|
|
|
{
|
|
|
|
if (!IsDarkModeEnabled() || IsIconic(hWnd)) {
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto result = DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
// Paint over the line with pure black. Could also try to figure out the dark theme color.
|
|
|
|
HDC hdc = GetWindowDC(hWnd);
|
|
|
|
RECT r = GetNonclientMenuBorderRect(hWnd);
|
|
|
|
HBRUSH red = CreateSolidBrush(RGB(0, 0, 0));
|
|
|
|
FillRect(hdc, &r, red);
|
|
|
|
DeleteObject(red);
|
|
|
|
ReleaseDC(hWnd, hdc);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
case WM_GETMINMAXINFO:
|
|
|
|
{
|
|
|
|
MINMAXINFO *minmax = reinterpret_cast<MINMAXINFO *>(lParam);
|
|
|
|
RECT rc = { 0 };
|
2015-05-15 18:04:05 +02:00
|
|
|
bool portrait = g_Config.IsPortrait();
|
|
|
|
rc.right = portrait ? 272 : 480;
|
|
|
|
rc.bottom = portrait ? 480 : 272;
|
2014-06-29 22:13:53 +02:00
|
|
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, TRUE);
|
|
|
|
minmax->ptMinTrackSize.x = rc.right - rc.left;
|
|
|
|
minmax->ptMinTrackSize.y = rc.bottom - rc.top;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
2013-09-28 14:34:08 +02:00
|
|
|
case WM_ACTIVATE:
|
2013-10-11 14:53:25 +03:00
|
|
|
{
|
2020-08-18 01:07:12 -07:00
|
|
|
UpdateWindowTitle();
|
2013-10-11 14:53:25 +03:00
|
|
|
bool pause = true;
|
|
|
|
if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
|
2015-02-28 16:01:41 -08:00
|
|
|
WindowsRawInput::GainFocus();
|
2017-12-24 18:03:28 -08:00
|
|
|
if (!IsIconic(GetHWND())) {
|
|
|
|
InputDevice::GainFocus();
|
|
|
|
}
|
2013-10-11 14:53:25 +03:00
|
|
|
g_activeWindow = WINDOW_MAINWINDOW;
|
|
|
|
pause = false;
|
|
|
|
}
|
2014-06-22 09:38:46 +02:00
|
|
|
if (!noFocusPause && g_Config.bPauseOnLostFocus && GetUIState() == UISTATE_INGAME) {
|
2013-10-11 14:53:25 +03:00
|
|
|
if (pause != Core_IsStepping()) { // != is xor for bools
|
2020-09-24 00:17:31 +02:00
|
|
|
if (disasmWindow)
|
|
|
|
SendMessage(disasmWindow->GetDlgHandle(), WM_COMMAND, IDC_STOPGO, 0);
|
2013-10-11 14:53:25 +03:00
|
|
|
else
|
2021-10-23 16:56:15 -07:00
|
|
|
Core_EnableStepping(pause, "ui.lost_focus", 0);
|
2013-10-11 14:53:25 +03:00
|
|
|
}
|
|
|
|
}
|
2013-10-31 00:34:09 +01:00
|
|
|
|
2017-12-24 18:03:28 -08:00
|
|
|
if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::GOT_FOCUS);
|
2017-12-24 18:03:28 -08:00
|
|
|
hasFocus = true;
|
2017-05-05 00:21:57 +02:00
|
|
|
trapMouse = true;
|
2015-05-21 10:49:47 +02:00
|
|
|
}
|
2013-10-31 00:34:09 +01:00
|
|
|
if (wParam == WA_INACTIVE) {
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::LOST_FOCUS);
|
2014-01-19 11:59:11 -08:00
|
|
|
WindowsRawInput::LoseFocus();
|
2015-02-28 14:02:03 -08:00
|
|
|
InputDevice::LoseFocus();
|
2017-12-24 18:03:28 -08:00
|
|
|
hasFocus = false;
|
2017-05-05 00:21:57 +02:00
|
|
|
trapMouse = false;
|
2013-10-31 00:34:09 +01:00
|
|
|
}
|
2013-09-28 14:34:08 +02:00
|
|
|
}
|
|
|
|
break;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2020-08-18 01:07:12 -07:00
|
|
|
case WM_SETFOCUS:
|
|
|
|
UpdateWindowTitle();
|
|
|
|
break;
|
|
|
|
|
2015-09-24 00:00:02 -07:00
|
|
|
case WM_ERASEBKGND:
|
|
|
|
// This window is always covered by DisplayWindow. No reason to erase.
|
2023-01-12 01:01:03 +01:00
|
|
|
return 0;
|
2014-06-29 22:13:53 +02:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
case WM_MOVE:
|
2013-03-30 17:49:02 +01:00
|
|
|
SavePosition();
|
2013-01-27 00:15:39 +01:00
|
|
|
break;
|
|
|
|
|
2016-02-21 11:50:37 +01:00
|
|
|
case WM_ENTERSIZEMOVE:
|
|
|
|
inResizeMove = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_EXITSIZEMOVE:
|
|
|
|
inResizeMove = false;
|
|
|
|
HandleSizeChange(SIZE_RESTORED);
|
|
|
|
break;
|
|
|
|
|
2014-06-29 22:13:53 +02:00
|
|
|
case WM_SIZE:
|
2015-09-19 15:16:31 +02:00
|
|
|
switch (wParam) {
|
|
|
|
case SIZE_RESTORED:
|
|
|
|
case SIZE_MAXIMIZED:
|
|
|
|
if (g_IgnoreWM_SIZE) {
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
2016-02-21 11:50:37 +01:00
|
|
|
} else if (!inResizeMove) {
|
2015-09-20 21:54:27 -07:00
|
|
|
HandleSizeChange(wParam);
|
2014-06-29 22:13:53 +02:00
|
|
|
}
|
2017-12-24 18:03:28 -08:00
|
|
|
if (hasFocus) {
|
|
|
|
InputDevice::GainFocus();
|
|
|
|
}
|
2015-09-19 15:16:31 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SIZE_MINIMIZED:
|
|
|
|
Core_NotifyWindowHidden(true);
|
|
|
|
if (!g_Config.bPauseWhenMinimized) {
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::WINDOW_MINIMIZED, "true");
|
2015-09-19 15:16:31 +02:00
|
|
|
}
|
2017-12-24 18:03:28 -08:00
|
|
|
InputDevice::LoseFocus();
|
2015-09-19 15:16:31 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-06-29 22:13:53 +02:00
|
|
|
}
|
2015-01-17 19:49:58 -08:00
|
|
|
break;
|
2014-06-29 22:13:53 +02:00
|
|
|
|
2019-07-22 04:42:07 +02:00
|
|
|
// Wheel events have to stay in WndProc for compatibility with older Windows(7). See #12156
|
|
|
|
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,
|
|
|
|
// so we release it with a slight delay.
|
|
|
|
key.flags = KEY_DOWN | KEY_HASWHEELDELTA | (wheelDelta << 16);
|
|
|
|
SetTimer(hwndMain, TIMER_WHEELRELEASE, WHEELRELEASE_DELAY_MS, 0);
|
|
|
|
NativeKey(key);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2019-06-17 00:57:06 +02:00
|
|
|
case WM_TIMER:
|
2013-05-04 23:21:06 +02:00
|
|
|
// Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode.
|
2013-07-29 04:46:40 -04:00
|
|
|
switch (wParam) {
|
2013-06-12 02:14:53 +08:00
|
|
|
case TIMER_CURSORUPDATE:
|
|
|
|
CorrectCursor();
|
|
|
|
return 0;
|
2013-07-29 15:34:30 -04:00
|
|
|
|
2013-06-12 02:14:53 +08:00
|
|
|
case TIMER_CURSORMOVEUPDATE:
|
|
|
|
hideCursor = true;
|
|
|
|
KillTimer(hWnd, TIMER_CURSORMOVEUPDATE);
|
|
|
|
return 0;
|
2019-07-22 04:42:07 +02:00
|
|
|
// Hack: need to release wheel event with a delay for games to register it was "pressed down".
|
2019-06-17 00:57:06 +02:00
|
|
|
case TIMER_WHEELRELEASE:
|
2019-09-03 00:01:37 +02:00
|
|
|
ReleaseMouseWheel();
|
|
|
|
KillTimer(hWnd, TIMER_WHEELRELEASE);
|
2019-06-17 00:57:06 +02:00
|
|
|
return 0;
|
2013-07-08 12:35:08 +02:00
|
|
|
}
|
2013-07-29 15:34:30 -04:00
|
|
|
break;
|
2013-07-08 12:35:08 +02:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
case WM_COMMAND:
|
2013-06-03 20:30:12 +08:00
|
|
|
{
|
2018-02-07 15:52:19 +01:00
|
|
|
if (!MainThread_Ready())
|
2013-07-29 04:46:40 -04:00
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
2014-01-07 16:08:11 -05:00
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
MainWindowMenu_Process(hWnd, wParam);
|
2013-06-03 20:30:12 +08:00
|
|
|
}
|
2012-11-01 16:19:01 +01:00
|
|
|
break;
|
2013-07-06 19:08:59 +02:00
|
|
|
|
2015-02-15 23:07:24 +01:00
|
|
|
case WM_USER_TOGGLE_FULLSCREEN:
|
2015-09-20 23:57:24 +02:00
|
|
|
ToggleFullscreen(hwndMain, wParam ? true : false);
|
2015-02-15 23:07:24 +01:00
|
|
|
break;
|
|
|
|
|
2013-07-07 10:42:39 +02:00
|
|
|
case WM_INPUT:
|
2014-01-19 12:11:08 -08:00
|
|
|
return WindowsRawInput::Process(hWnd, wParam, lParam);
|
|
|
|
|
|
|
|
// TODO: Could do something useful with WM_INPUT_DEVICE_CHANGE?
|
2013-05-13 17:13:49 +08:00
|
|
|
|
2014-06-29 23:29:49 +02:00
|
|
|
// 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);
|
|
|
|
|
2018-11-01 21:42:12 -07:00
|
|
|
case WM_DEVICECHANGE:
|
2019-05-04 06:06:50 +08:00
|
|
|
#ifndef _M_ARM
|
2018-11-01 21:42:12 -07:00
|
|
|
DinputDevice::CheckDevices();
|
2019-05-04 06:06:50 +08:00
|
|
|
#endif
|
2020-07-31 10:24:17 +08:00
|
|
|
if (winCamera)
|
|
|
|
winCamera->CheckDevices();
|
|
|
|
if (winMic)
|
|
|
|
winMic->CheckDevices();
|
2018-11-01 21:42:12 -07:00
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
|
2013-11-30 18:21:47 -08:00
|
|
|
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;
|
2013-12-18 23:57:39 -08:00
|
|
|
std::string name;
|
2013-11-30 18:21:47 -08:00
|
|
|
|
2021-11-27 16:11:51 -08:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(MIPSComp::jitLock);
|
2013-12-18 23:57:39 -08:00
|
|
|
if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr(ptr, name)) {
|
|
|
|
swprintf_s(info->name, L"Jit::%S", name.c_str());
|
|
|
|
return TRUE;
|
2013-11-30 18:21:47 -08:00
|
|
|
}
|
2013-12-18 23:57:39 -08:00
|
|
|
if (gpu && gpu->DescribeCodePtr(ptr, name)) {
|
|
|
|
swprintf_s(info->name, L"GPU::%S", name.c_str());
|
|
|
|
return TRUE;
|
2013-11-30 18:39:16 -08:00
|
|
|
}
|
2013-11-30 18:21:47 -08:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
case WM_DROPFILES:
|
|
|
|
{
|
2018-02-07 15:52:19 +01:00
|
|
|
if (!MainThread_Ready())
|
2013-06-08 08:32:07 +08:00
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
HDROP hdrop = (HDROP)wParam;
|
|
|
|
int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0);
|
2013-07-29 04:46:40 -04:00
|
|
|
if (count != 1) {
|
2013-08-26 19:00:16 +02:00
|
|
|
MessageBox(hwndMain,L"You can only load one file at a time",L"Error",MB_ICONINFORMATION);
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TCHAR filename[512];
|
2016-06-26 20:33:25 -07:00
|
|
|
if (DragQueryFile(hdrop, 0, filename, 512) != 0) {
|
|
|
|
const std::string utf8_filename = ReplaceAll(ConvertWStringToUTF8(filename), "\\", "/");
|
2023-09-30 11:21:22 +02:00
|
|
|
System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, utf8_filename);
|
2016-06-26 20:33:25 -07:00
|
|
|
Core_EnableStepping(false);
|
|
|
|
}
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
2014-03-23 22:18:54 -07:00
|
|
|
InputDevice::StopPolling();
|
2022-12-27 10:31:54 +01:00
|
|
|
MainThread_Stop();
|
2014-01-19 12:11:08 -08:00
|
|
|
WindowsRawInput::Shutdown();
|
2013-01-02 22:57:57 +01:00
|
|
|
return DefWindowProc(hWnd,message,wParam,lParam);
|
2013-01-05 19:57:06 +01:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
case WM_DESTROY:
|
2013-06-12 02:14:53 +08:00
|
|
|
KillTimer(hWnd, TIMER_CURSORUPDATE);
|
|
|
|
KillTimer(hWnd, TIMER_CURSORMOVEUPDATE);
|
2019-06-17 00:57:06 +02:00
|
|
|
KillTimer(hWnd, TIMER_WHEELRELEASE);
|
2022-12-11 10:02:21 +01:00
|
|
|
// Main window is gone, this tells the message loop to exit.
|
2012-11-01 16:19:01 +01:00
|
|
|
PostQuitMessage(0);
|
2022-12-11 10:02:21 +01:00
|
|
|
return 0;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-09-23 23:01:26 -04:00
|
|
|
case WM_USER + 1:
|
2021-12-31 09:10:40 -08:00
|
|
|
NotifyDebuggerMapLoaded();
|
2020-09-24 00:17:31 +02:00
|
|
|
if (disasmWindow)
|
|
|
|
disasmWindow->UpdateDialog();
|
2012-11-01 16:19:01 +01:00
|
|
|
break;
|
2013-03-29 19:52:32 +01:00
|
|
|
|
2013-07-21 02:21:50 -07:00
|
|
|
case WM_USER_SAVESTATE_FINISH:
|
|
|
|
SetCursor(LoadCursor(0, IDC_ARROW));
|
|
|
|
break;
|
2013-03-29 19:52:32 +01:00
|
|
|
|
2013-09-01 14:06:24 -07:00
|
|
|
case WM_USER_UPDATE_UI:
|
2015-09-19 13:11:06 +02:00
|
|
|
TranslateMenus(hwndMain, menu);
|
2017-04-04 20:33:22 -07:00
|
|
|
// Update checked status immediately for accelerators.
|
|
|
|
UpdateMenus();
|
2013-09-01 14:06:24 -07:00
|
|
|
break;
|
|
|
|
|
2013-09-13 15:17:55 -04:00
|
|
|
case WM_USER_WINDOW_TITLE_CHANGED:
|
|
|
|
UpdateWindowTitle();
|
|
|
|
break;
|
|
|
|
|
2017-04-15 16:33:30 -07:00
|
|
|
case WM_USER_RESTART_EMUTHREAD:
|
|
|
|
NativeSetRestarting();
|
2017-05-20 12:33:28 -07:00
|
|
|
InputDevice::StopPolling();
|
2018-02-07 15:52:19 +01:00
|
|
|
MainThread_Stop();
|
2017-04-15 16:33:30 -07:00
|
|
|
coreState = CORE_POWERUP;
|
2018-08-13 00:08:56 +02:00
|
|
|
UpdateUIState(UISTATE_MENU);
|
2018-02-10 16:24:36 -08:00
|
|
|
MainThread_Start(g_Config.iGPUBackend == (int)GPUBackend::OPENGL);
|
2017-05-20 12:33:28 -07:00
|
|
|
InputDevice::BeginPolling();
|
2017-04-15 16:33:30 -07:00
|
|
|
break;
|
|
|
|
|
2020-10-22 17:14:35 +08:00
|
|
|
case WM_USER_SWITCHUMD_UPDATED:
|
|
|
|
UpdateSwitchUMD();
|
|
|
|
break;
|
|
|
|
|
2013-03-29 19:32:20 +01:00
|
|
|
case WM_MENUSELECT:
|
2017-04-04 10:08:41 +02:00
|
|
|
// Called when a menu is opened. Also when an item is selected, but meh.
|
2017-04-04 20:33:22 -07:00
|
|
|
UpdateMenus(true);
|
2014-01-20 00:57:20 -08:00
|
|
|
WindowsRawInput::NotifyMenu();
|
2017-05-05 00:21:57 +02:00
|
|
|
trapMouse = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_EXITMENULOOP:
|
|
|
|
// Called when menu is closed.
|
|
|
|
trapMouse = true;
|
2013-03-29 19:32:20 +01:00
|
|
|
break;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-05-02 20:58:10 +02:00
|
|
|
// 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:
|
|
|
|
{
|
2013-07-29 04:46:40 -04:00
|
|
|
switch (wParam) {
|
2020-01-06 01:04:07 +08:00
|
|
|
case SC_SCREENSAVE:
|
2013-05-02 20:58:10 +02:00
|
|
|
return 0;
|
|
|
|
case SC_MONITORPOWER:
|
2020-01-06 01:04:07 +08:00
|
|
|
return 0;
|
2013-05-02 20:58:10 +02:00
|
|
|
}
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
2020-05-04 17:33:39 +02:00
|
|
|
break;
|
|
|
|
case WM_SETTINGCHANGE:
|
|
|
|
{
|
|
|
|
if (g_darkModeSupported && IsColorSchemeChangeMessage(lParam))
|
|
|
|
SendMessageW(hWnd, WM_THEMECHANGED, 0, 0);
|
|
|
|
}
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
|
|
|
|
case WM_THEMECHANGED:
|
|
|
|
{
|
|
|
|
if (g_darkModeSupported)
|
|
|
|
{
|
|
|
|
_AllowDarkModeForWindow(hWnd, g_darkModeEnabled);
|
|
|
|
RefreshTitleBarThemeColor(hWnd);
|
|
|
|
}
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
2013-05-02 20:58:10 +02:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
default:
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2020-01-06 01:04:07 +08:00
|
|
|
|
2013-07-29 04:46:40 -04:00
|
|
|
void Redraw() {
|
2014-06-29 22:13:53 +02:00
|
|
|
InvalidateRect(hwndDisplay,0,0);
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
2013-03-29 21:21:27 +01:00
|
|
|
|
2013-07-29 04:46:40 -04:00
|
|
|
HINSTANCE GetHInstance() {
|
2012-11-01 16:19:01 +01:00
|
|
|
return hInst;
|
|
|
|
}
|
2013-10-13 14:14:28 -04:00
|
|
|
|
2013-10-13 14:25:59 -04:00
|
|
|
void ToggleDebugConsoleVisibility() {
|
2013-10-13 14:14:28 -04:00
|
|
|
if (!g_Config.bEnableLogging) {
|
|
|
|
LogManager::GetInstance()->GetConsoleListener()->Show(false);
|
|
|
|
EnableMenuItem(menu, ID_DEBUG_LOG, MF_GRAYED);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LogManager::GetInstance()->GetConsoleListener()->Show(true);
|
|
|
|
EnableMenuItem(menu, ID_DEBUG_LOG, MF_ENABLED);
|
|
|
|
}
|
|
|
|
}
|
2015-09-19 13:11:06 +02:00
|
|
|
|
2015-09-20 23:57:24 +02:00
|
|
|
void SendToggleFullscreen(bool fullscreen) {
|
|
|
|
PostMessage(hwndMain, WM_USER_TOGGLE_FULLSCREEN, fullscreen, 0);
|
|
|
|
}
|
|
|
|
|
2021-01-09 14:17:41 -08:00
|
|
|
bool IsFullscreen() {
|
|
|
|
return g_isFullscreen;
|
|
|
|
}
|
|
|
|
|
2015-09-19 13:11:06 +02:00
|
|
|
} // namespace
|