From: Toni Wilen Date: Sat, 7 Oct 2023 16:21:54 +0000 (+0300) Subject: Pad GUI control X-Git-Tag: 5.1.0~90 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=1e83b4e96211818f3a4233c1c871bdce52836a7f;p=francis%2Fwinuae.git Pad GUI control --- diff --git a/include/options.h b/include/options.h index 6e82c899..4a903ed4 100644 --- a/include/options.h +++ b/include/options.h @@ -907,6 +907,7 @@ struct uae_prefs { bool win32_filesystem_mangle_reserved_names; bool win32_shutdown_notification; bool win32_warn_exit; + bool win32_gui_control; bool right_control_is_right_win_key; #ifdef WITH_SLIRP struct slirp_redir slirp_redirs[MAX_SLIRP_REDIRS]; diff --git a/od-win32/hardfile_win32.cpp b/od-win32/hardfile_win32.cpp index be998fd4..c2e0ad0a 100644 --- a/od-win32/hardfile_win32.cpp +++ b/od-win32/hardfile_win32.cpp @@ -897,7 +897,8 @@ static bool hd_get_meta_hack_realtek(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 * progressdialogreturn = -1; progressdialogactive = 1; - HWND hwnd = CustomCreateDialog(IDD_PROGRESSBAR, hDlg, ProgressDialogProc); + struct newresource *res; + HWND hwnd = CustomCreateDialog(&res, IDD_PROGRESSBAR, hDlg, ProgressDialogProc); if (hwnd == NULL) return false; HWND hwndprogress = GetDlgItem (hwnd, IDC_PROGRESSBAR); @@ -934,6 +935,7 @@ static bool hd_get_meta_hack_realtek(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 * tcnt = 0; } } + freescaleresource(res); if (progressdialogactive) { DestroyWindow (hwnd); @@ -1400,6 +1402,7 @@ static int gethdfchs(HWND hDlg, struct uae_driveinfo *udi, HANDLE h, int *cylsp, DWORD err = 0; HFONT font; HWND hwnd; + struct newresource *res; memset(data, 0, 512); memset(cmd, 0, sizeof(cmd)); @@ -1427,7 +1430,7 @@ static int gethdfchs(HWND hDlg, struct uae_driveinfo *udi, HANDLE h, int *cylsp, } chsdialogactive = 1; - hwnd = CustomCreateDialog(IDD_CHSQUERY, hDlg, CHSDialogProc); + hwnd = CustomCreateDialog(&res, IDD_CHSQUERY, hDlg, CHSDialogProc); if (hwnd == NULL) { err = -15; goto end; @@ -1448,6 +1451,7 @@ static int gethdfchs(HWND hDlg, struct uae_driveinfo *udi, HANDLE h, int *cylsp, } } } + freescaleresource(res); DeleteObject(font); if (chsdialogactive == 0) { err = -100; @@ -1533,6 +1537,7 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile) bool atapi = false; HWND hwnd; bool empty = true; + struct newresource *res; geometryfile[0] = 0; text = xcalloc(TCHAR, 100000); @@ -1660,7 +1665,7 @@ doout: stringboxdialogactive = 1; hdini = ini; - hwnd = CustomCreateDialog (IDD_DISKINFO, hDlg, StringBoxDialogProc); + hwnd = CustomCreateDialog(&res, IDD_DISKINFO, hDlg, StringBoxDialogProc); if (hwnd != NULL) { HFONT font = CreateFont (getscaledfontsize(-1), 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T("Lucida Console")); if (font) @@ -1682,6 +1687,7 @@ doout: break; } DeleteObject (font); + freescaleresource(res); } end: @@ -3635,6 +3641,7 @@ int harddrive_to_hdf (HWND hDlg, struct uae_prefs *p, int idx) TCHAR path[MAX_DPATH], tmp[MAX_DPATH], tmp2[MAX_DPATH]; DWORD retcode = 0; HWND hwnd, hwndprogress, hwndprogresstxt; + struct newresource *res; MSG msg; int pct, cnt; DWORD r; @@ -3710,7 +3717,7 @@ int harddrive_to_hdf (HWND hDlg, struct uae_prefs *p, int idx) SetFilePointer (h, 0, &li.HighPart, FILE_BEGIN); progressdialogreturn = -1; progressdialogactive = 1; - hwnd = CustomCreateDialog(IDD_PROGRESSBAR, hDlg, ProgressDialogProc); + hwnd = CustomCreateDialog(&res, IDD_PROGRESSBAR, hDlg, ProgressDialogProc); if (hwnd == NULL) goto err; hwndprogress = GetDlgItem (hwnd, IDC_PROGRESSBAR); @@ -3806,6 +3813,7 @@ int harddrive_to_hdf (HWND hDlg, struct uae_prefs *p, int idx) sizecnt += got; pct = (int)(sizecnt * 100 / size); } + freescaleresource(res); if (progressdialogactive) { DestroyWindow (hwnd); while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) { diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index 5ed71a6c..58b3e17a 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -2189,7 +2189,7 @@ END STRINGTABLE BEGIN - IDS_MISCLISTITEMS4 "Windows shutdown/logoff notification\nWarn when attempting to close window\nPower led dims when audio filter is disabled\nAutomatically capture mouse when window is activated\nDebug memory space\nForce hard reset if CPU halted\nA600/A1200/A4000 IDE scsi.device disable\nWarp mode reset\n" + IDS_MISCLISTITEMS4 "Windows shutdown/logoff notification\nWarn when attempting to close window\nPower led dims when audio filter is disabled\nAutomatically capture mouse when window is activated\nDebug memory space\nForce hard reset if CPU halted\nA600/A1200/A4000 IDE scsi.device disable\nWarp mode reset\nGUI gamepad control\n" IDS_SHUTDOWN_NOTIFICATION "Emulation session active" IDS_QUIT_WARNING "Are you sure you want to quit WinUAE?" IDS_UNMAPPED_ADDRESS "Floating\nAll zeros\nAll ones\n" diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 718b4743..43daf330 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -2059,6 +2059,11 @@ static void EndCustomResize(HWND hWindow, BOOL bCanceled) #define MSGDEBUG 1 +static int externaldialogguicontrol; +static void CALLBACK gui_control_cb(HWND h, UINT v, UINT_PTR v3, DWORD v4) +{ +} + static LRESULT CALLBACK AmigaWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { struct AmigaMonitor *mon = NULL; @@ -2082,6 +2087,18 @@ static LRESULT CALLBACK AmigaWindowProc(HWND hWnd, UINT message, WPARAM wParam, mon = &AMonitors[0]; } + if (externaldialogactive && gui_control) { + if (!externaldialogguicontrol) { + externaldialogguicontrol = 1; + SetTimer(hWnd, 8, 20, gui_control_cb); + } + } else { + if (externaldialogguicontrol) { + externaldialogguicontrol = 0; + KillTimer(hWnd, 8); + } + } + #if MSGDEBUG > 1 write_log (_T("AWP: %p %08x %08x %08x\n"), hWnd, message, wParam, lParam); #endif @@ -4460,6 +4477,7 @@ void target_default_options (struct uae_prefs *p, int type) p->win32_borderless = 0; p->win32_blankmonitors = false; p->win32_powersavedisabled = true; + p->win32_gui_control = false; p->sana2 = 0; p->win32_rtgmatchdepth = 1; p->gf[GF_RTG].gfx_filter_autoscale = RTG_MODE_SCALE; @@ -4552,6 +4570,7 @@ void target_save_options (struct zfile *f, struct uae_prefs *p) cfgfile_target_dwrite_bool(f, _T("active_capture_automatically"), p->win32_capture_always); cfgfile_target_dwrite_bool(f, _T("start_iconified"), p->win32_start_minimized); cfgfile_target_dwrite_bool(f, _T("start_not_captured"), p->win32_start_uncaptured); + cfgfile_target_dwrite_bool(f, _T("gui_control"), p->win32_gui_control); cfgfile_target_dwrite_bool (f, _T("ctrl_f11_is_quit"), p->win32_ctrl_F11_is_quit); @@ -4955,6 +4974,9 @@ static int target_parse_option_host(struct uae_prefs *p, const TCHAR *option, co if (cfgfile_yesno(option, value, _T("start_not_captured"), &p->win32_start_uncaptured)) return 1; + if (cfgfile_yesno(option, value, _T("gui_control"), &p->win32_gui_control)) + return 1; + if (cfgfile_string_escape(option, value, _T("serial_port"), &p->sername[0], 256)) { sernametodev(p->sername); if (p->sername[0]) @@ -6922,6 +6944,10 @@ static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2) key_swap_hack2 = 1; return 1; } + if (!_tcscmp(arg, _T("gui_control"))) { + gui_control = 1; + return 1; + } if (!np) return 0; diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 9526a9cc..9e69592a 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -2549,6 +2549,7 @@ int check_prefs_changed_gfx(void) currprefs.win32_ctrl_F11_is_quit != changed_prefs.win32_ctrl_F11_is_quit || currprefs.win32_shutdown_notification != changed_prefs.win32_shutdown_notification || currprefs.win32_warn_exit != changed_prefs.win32_warn_exit || + currprefs.win32_gui_control != changed_prefs.win32_gui_control || currprefs.right_control_is_right_win_key != changed_prefs.right_control_is_right_win_key) { currprefs.win32_minimize_inactive = changed_prefs.win32_minimize_inactive; @@ -2572,6 +2573,7 @@ int check_prefs_changed_gfx(void) currprefs.win32_ctrl_F11_is_quit = changed_prefs.win32_ctrl_F11_is_quit; currprefs.win32_shutdown_notification = changed_prefs.win32_shutdown_notification; currprefs.win32_warn_exit = changed_prefs.win32_warn_exit; + currprefs.win32_gui_control = changed_prefs.win32_gui_control; currprefs.right_control_is_right_win_key = changed_prefs.right_control_is_right_win_key; inputdevice_unacquire (); currprefs.keyboard_leds_in_use = changed_prefs.keyboard_leds_in_use = (currprefs.keyboard_leds[0] | currprefs.keyboard_leds[1] | currprefs.keyboard_leds[2]) != 0; diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 58754fb3..b0e95b88 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -141,8 +141,11 @@ int dialog_inhibit; static HMODULE hHtmlHelp; pathtype path_type; +int externaldialogactive; static int stringboxdialogactive; static int customdialogactive; +static struct newresource *customdialogres; +static HWND customdialoghwnd; void HtmlHelp(const TCHAR *panel) { @@ -310,6 +313,28 @@ struct GUIPAGE { }; static struct GUIPAGE ppage[MAX_C_PAGES]; +static void CALLBACK gui_control_cb(HWND h, UINT v, UINT_PTR v3, DWORD v4) +{ + HWND ha = GetActiveWindow(); + if (externaldialogactive) { + if (ha) { + HWND p = GetParent(ha); + HWND mainhwnd = AMonitors[0].hAmigaWnd; + if (p && (p == customdialoghwnd || p == guiDlg || p == mainhwnd)) { + process_gui_control(ha, NULL); + } + } + } else if (customdialogactive > 0 && customdialogres && customdialoghwnd) { + if (ha == customdialoghwnd) { + process_gui_control(customdialoghwnd, customdialogres); + } + } else { + if (ha == h) { + process_gui_control(h, panelresource); + } + } +} + static bool ischecked(HWND hDlg, DWORD id) { return IsDlgButtonChecked(hDlg, id) == BST_CHECKED; @@ -631,7 +656,25 @@ static BOOL GetFileDialog (OPENFILENAME *opn, const GUID *guid, int mode) pfd->SetFolder (shellitem); } - hr = pfd->Show (opn->hwndOwner); + externaldialogactive = 1; + // GUI control without GUI + if (gui_control && hGUIWnd == NULL) { + HWND h = AMonitors[0].hAmigaWnd; + if (h) { + SetTimer(h, 8, 20, gui_control_cb); + } + } + + hr = pfd->Show(opn->hwndOwner); + + externaldialogactive = 0; + if (gui_control && hGUIWnd == NULL) { + HWND h = AMonitors[0].hAmigaWnd; + if (h) { + KillTimer(h, 8); + } + } + if (SUCCEEDED (hr)) { UINT idx; IShellItemArray *pitema; @@ -2066,6 +2109,7 @@ int scan_roms (HWND hDlg, int show) UAEREG *fkey, *fkey2; TCHAR *paths[MAX_ROM_PATHS]; MSG msg; + struct newresource *res = NULL; if (recursive) return 0; @@ -2081,7 +2125,7 @@ int scan_roms (HWND hDlg, int show) infoboxdialogstate = true; infoboxhwnd = NULL; if (!rp_isactive ()) { - HWND hwnd = CustomCreateDialog(IDD_INFOBOX, hDlg, InfoBoxDialogProc); + HWND hwnd = CustomCreateDialog(&res, IDD_INFOBOX, hDlg, InfoBoxDialogProc); if (!hwnd) goto end; infoboxhwnd = hwnd; @@ -2143,6 +2187,7 @@ end: TranslateMessage (&msg); DispatchMessage (&msg); } + FreeResource(res); } read_rom_list(false); if (show) @@ -2577,7 +2622,8 @@ static void eject_cd (void) void gui_infotextbox(HWND hDlg, const TCHAR *text) { stringboxdialogactive = 1; - HWND hwnd = CustomCreateDialog(IDD_DISKINFO, hDlg ? hDlg : hGUIWnd, StringBoxDialogProc); + struct newresource *res; + HWND hwnd = CustomCreateDialog(&res, IDD_DISKINFO, hDlg ? hDlg : hGUIWnd, StringBoxDialogProc); if (hwnd == NULL) return; @@ -2600,6 +2646,7 @@ void gui_infotextbox(HWND hDlg, const TCHAR *text) break; } } + freescaleresource(res); if (font) { DeleteObject(font); } @@ -2610,6 +2657,7 @@ static void infofloppy (HWND hDlg, int n) struct diskinfo di; TCHAR tmp2[MAX_DPATH], tmp1[MAX_DPATH], tmp3[MAX_DPATH]; TCHAR text[20000]; + struct newresource *res; DISK_examine_image (&workprefs, n, &di, true, tmp3); DISK_validate_filename(&workprefs, workprefs.floppyslots[n].df, n, tmp1, 0, NULL, NULL, NULL); @@ -2673,7 +2721,7 @@ static void infofloppy (HWND hDlg, int n) } stringboxdialogactive = 1; - HWND hwnd = CustomCreateDialog(IDD_DISKINFO, hDlg, StringBoxDialogProc); + HWND hwnd = CustomCreateDialog(&res, IDD_DISKINFO, hDlg, StringBoxDialogProc); if (hwnd == NULL) return; @@ -2696,6 +2744,7 @@ static void infofloppy (HWND hDlg, int n) break; } } + freescaleresource(res); DeleteObject (font); } @@ -4756,6 +4805,7 @@ static const struct miscentry misclist[] = { { 0, 1, _T("Force hard reset if CPU halted"), &workprefs.crash_auto_reset }, { 0, 0, _T("A600/A1200/A4000 IDE scsi.device disable"), &workprefs.scsidevicedisable }, { 0, 1, _T("Warp mode reset"), &workprefs.turbo_boot }, + { 0, 1, _T("GUI game pad control"), &workprefs.win32_gui_control }, { 0, 0, NULL } }; @@ -5782,8 +5832,7 @@ static INT_PTR CALLBACK InfoSettingsProc(HWND hDlg, UINT msg, WPARAM wParam, LPA PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_INITDIALOG: { @@ -5837,13 +5886,11 @@ static INT_PTR CALLBACK InfoSettingsProc(HWND hDlg, UINT msg, WPARAM wParam, LPA DiskSelection(hDlg, IDC_PATH_NAME, 8, &workprefs, NULL, NULL); break; case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDC_CONFIGAUTO: @@ -6481,13 +6528,11 @@ static INT_PTR CALLBACK ErrorLogProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM switch (msg) { case WM_COMMAND: if (wParam == IDOK) { - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; } else if (wParam == IDC_ERRORLOGCLEAR) { error_log (NULL); - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; } break; @@ -6554,13 +6599,11 @@ static INT_PTR CALLBACK ContributorsProc (HWND hDlg, UINT msg, WPARAM wParam, LP PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_COMMAND: if (wParam == ID_OK) { - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; } break; @@ -14537,8 +14580,7 @@ static INT_PTR CALLBACK VolumeSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_INITDIALOG: { @@ -14623,13 +14665,11 @@ static INT_PTR CALLBACK VolumeSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, volumeselectdir (hDlg, 0, 1); break; case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; } @@ -15146,8 +15186,7 @@ static INT_PTR CALLBACK TapeDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_INITDIALOG: recursive++; @@ -15235,13 +15274,11 @@ static INT_PTR CALLBACK TapeDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara break; } case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; } @@ -15268,8 +15305,7 @@ static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_INITDIALOG: @@ -15289,8 +15325,7 @@ static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, if (((LPNMHDR) lParam)->idFrom == IDC_CDLIST) { NM_LISTVIEW *nmlistview = (NM_LISTVIEW *)lParam; if (nmlistview->hdr.code == NM_DBLCLK) { - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; } } @@ -15302,13 +15337,11 @@ static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, switch (LOWORD (wParam)) { case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDC_HDF_CONTROLLER: @@ -15382,8 +15415,7 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_DROPFILES: dragdrop (hDlg, (HDROP)wParam, &changed_prefs, -2); @@ -15544,13 +15576,11 @@ static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam DISK_history_add(current_hfdlg.ci.filesys, -1, HISTORY_FS, 1); break; case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDC_HDF_PHYSGEOMETRY: @@ -15677,8 +15707,7 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara PostQuitMessage(0); return TRUE; case WM_CLOSE: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; case WM_INITDIALOG: { @@ -15735,13 +15764,11 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara if (HIWORD (wParam) == BN_CLICKED) { switch (LOWORD (wParam)) { case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDC_HDF_PHYSGEOMETRY: @@ -18536,10 +18563,11 @@ static void values_to_inputdlg (HWND hDlg) static int askinputcustom (HWND hDlg, TCHAR *custom, int maxlen, DWORD titleid) { HWND hwnd; + struct newresource *res; TCHAR txt[MAX_DPATH]; stringboxdialogactive = 1; - hwnd = CustomCreateDialog (IDD_STRINGBOX, hDlg, StringBoxDialogProc); + hwnd = CustomCreateDialog(&res, IDD_STRINGBOX, hDlg, StringBoxDialogProc); if (hwnd == NULL) return 0; if (titleid != 0) { @@ -18563,9 +18591,11 @@ static int askinputcustom (HWND hDlg, TCHAR *custom, int maxlen, DWORD titleid) } if (stringboxdialogactive == -1) { _tcscpy (custom, txt); + freescaleresource(res); return 1; } } + freescaleresource(res); return 0; } @@ -19491,8 +19521,7 @@ static INT_PTR CALLBACK RemapSpecialsProc(HWND hDlg, UINT msg, WPARAM wParam, LP if (inputmap_handle(NULL, -1, -1, NULL, NULL, -1, NULL, inputmap_selected, remapcustoms[entry].flags, IDEV_MAPPED_AUTOFIRE_SET | IDEV_MAPPED_TOGGLE | IDEV_MAPPED_INVERTTOGGLE | IDEV_MAPPED_INVERT, NULL)) { inputdevice_generate_jport_custom(&workprefs, inputmap_port); - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); return TRUE; } } @@ -19513,13 +19542,11 @@ static INT_PTR CALLBACK RemapSpecialsProc(HWND hDlg, UINT msg, WPARAM wParam, LP break; } case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; } @@ -19531,7 +19558,9 @@ static INT_PTR CALLBACK RemapSpecialsProc(HWND hDlg, UINT msg, WPARAM wParam, LP static void input_remapspecials(HWND hDlg) { - CustomCreateDialog(IDD_LIST, hDlg, RemapSpecialsProc); + struct newresource *res; + CustomCreateDialog(&res, IDD_LIST, hDlg, RemapSpecialsProc); + freescaleresource(res); } static INT_PTR CALLBACK InputMapDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -19697,12 +19726,13 @@ static INT_PTR CALLBACK InputMapDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA static void ports_remap (HWND hDlg, int port, int sub) { + struct newresource *res; inputmap_port = port; if (sub < 0) { sub = 0; } inputmap_port_sub = sub; - HWND dlg = CustomCreateDialog (IDD_INPUTMAP, hDlg, InputMapDlgProc); + HWND dlg = CustomCreateDialog(&res, IDD_INPUTMAP, hDlg, InputMapDlgProc); if (dlg == NULL) return; MSG msg; @@ -19726,6 +19756,7 @@ static void ports_remap (HWND hDlg, int port, int sub) TranslateMessage (&msg); DispatchMessage (&msg); } + freescaleresource(res); } static void input_togglesetmode (void) @@ -19949,13 +19980,11 @@ static INT_PTR CALLBACK QualifierProc (HWND hDlg, UINT msg, WPARAM wParam, LPARA break; } case IDOK: - customdialogactive = -1; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; case IDCANCEL: - customdialogactive = 0; - DestroyWindow(hDlg); + CustomDialogClose(hDlg); recursive = 0; return TRUE; } @@ -19971,6 +20000,7 @@ static void input_qualifiers (HWND hDlg) int evt; TCHAR name[256]; TCHAR custom[MAX_DPATH]; + struct newresource *res; if (input_selected_device < 0 || input_selected_widget < 0) return; @@ -19979,7 +20009,8 @@ static void input_qualifiers (HWND hDlg) if (evt <= 0) name[0] = 0; - CustomCreateDialog(IDD_LIST, hDlg, QualifierProc); + CustomCreateDialog(&res, IDD_LIST, hDlg, QualifierProc); + freescaleresource(res); #if 0 int item = genericpopupmenu (hDlg, names, mflags, MAX_INPUT_QUALIFIERS * 2); if (item >= 0) @@ -21959,6 +21990,7 @@ static HWND updatePanel (int id, UINT action) static HWND hwndTT; static bool first = true; int fullpanel; + HWND focus = GetFocus(); SaveListView(panelDlg, false); listview_id = 0; @@ -22056,9 +22088,15 @@ static HWND updatePanel (int id, UINT action) hAccelTable = ppage[currentpage].accel; +#if 0 if (ppage[id].focusid > 0 && action != TVC_BYKEYBOARD) { setfocus (panelDlg, ppage[id].focusid); } +#endif + + if (focus) { + SetFocus(focus); + } return panelDlg; } @@ -23000,6 +23038,7 @@ static INT_PTR CALLBACK DialogProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM l gui_size_changed = 1; return 0; } + handlerawinput (hDlg, msg, wParam, lParam); return FALSE; } @@ -23051,7 +23090,16 @@ struct newresource *getresource (int tmpl) return nr; } -INT_PTR CustomDialogBox (int templ, HWND hDlg, DLGPROC proc) +void CustomDialogClose(HWND hDlg) +{ + customdialogactive = 0; + customdialoghwnd = NULL; + freescaleresource(customdialogres); + customdialogres = NULL; + DestroyWindow(hDlg); +} + +INT_PTR CustomDialogBox(int templ, HWND hDlg, DLGPROC proc) { struct newresource *res; struct dlgcontext dctx; @@ -23070,12 +23118,13 @@ INT_PTR CustomDialogBox (int templ, HWND hDlg, DLGPROC proc) return h; } -HWND CustomCreateDialog(int templ, HWND hDlg, DLGPROC proc) +HWND CustomCreateDialog(struct newresource **resp, int templ, HWND hDlg, DLGPROC proc) { struct newresource *res; struct dlgcontext dctx; HWND h = NULL; + *resp = NULL; res = getresource (templ); if (!res) return h; @@ -23083,17 +23132,20 @@ HWND CustomCreateDialog(int templ, HWND hDlg, DLGPROC proc) res->parent = panelresource; h = x_CreateDialogIndirectParam(res->inst, res->resource, hDlg, proc, NULL, res); } - freescaleresource (res); + *resp = res; return h; } int CustomCreateDialogBox(int templ, HWND hDlg, DLGPROC proc) { + struct newresource *res; customdialogactive = 1; - HWND hwnd = CustomCreateDialog(templ, hDlg, proc); + HWND hwnd = CustomCreateDialog(&res, templ, hDlg, proc); if (!hwnd) { return 0; } + customdialogres = res; + customdialoghwnd = hwnd; while (customdialogactive == 1) { MSG msg; int ret; @@ -23300,6 +23352,7 @@ static int GetSettings (int all_options, HWND hwnd) int fmultx = 0, fmulty = 0; int resetcount = 0; bool boxart_reopen = false; + int use_gui_control = gui_control > 0 ? 2 : -1; setdefaultguisize(0); getstoredguisize(); scaleresource_setsize(-1, -1, -1); @@ -23473,8 +23526,12 @@ static int GetSettings (int all_options, HWND hwnd) reset_box_art_window(); boxart_reopen = false; } - if (devicechangetimer < 0) + if (devicechangetimer < 0) { SetTimer(dhwnd, 4, 2000, NULL); + } + if (use_gui_control > 1) { + SetTimer(dhwnd, 8, 20, gui_control_cb); + } for (;;) { HANDLE IPChandle; @@ -23540,6 +23597,14 @@ static int GetSettings (int all_options, HWND hwnd) // reset after IDCANCEL which would save coordinates gui_fullscreen = 0; } + if ((workprefs.win32_gui_control ? 1 : 0) != use_gui_control && use_gui_control < 2) { + use_gui_control = workprefs.win32_gui_control; + if (use_gui_control) { + SetTimer(dhwnd, 8, 30, gui_control_cb); + } else { + KillTimer(dhwnd, 8); + } + } } psresult = dialogreturn; } else { @@ -23560,6 +23625,10 @@ gui_exit: quit_program = 0; } + if (use_gui_control > 0) { + KillTimer(dhwnd, 8); + } + hGUIWnd = NULL; if (quit_program) { psresult = -2; diff --git a/od-win32/win32gui.h b/od-win32/win32gui.h index 5ca49cae..a855590f 100644 --- a/od-win32/win32gui.h +++ b/od-win32/win32gui.h @@ -72,8 +72,12 @@ typedef struct struct newreswnd { - HWND hwnd; + HWND hwnd, hwndx[5]; LONG x, y, w, h; + int style; + int region; + bool selectable; + bool list, listn; }; struct newresource @@ -114,6 +118,8 @@ struct newresource extern struct uae_prefs workprefs; extern int dialog_inhibit; +extern int gui_control; +extern int externaldialogactive; HWND x_CreateDialogIndirectParam(HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit, struct newresource*); void x_DestroyWindow(HWND, struct newresource*); @@ -122,8 +128,9 @@ extern int scaleresource(struct newresource*, struct dlgcontext *dctx, HWND, int extern void rescaleresource(struct newresource*, bool); extern void freescaleresource (struct newresource*); extern void scaleresource_setsize (int w, int h, int fs); -extern HWND CustomCreateDialog (int templ, HWND hDlg, DLGPROC proc); +extern HWND CustomCreateDialog (struct newresource **, int templ, HWND hDlg, DLGPROC proc); extern int CustomCreateDialogBox(int templ, HWND hDlg, DLGPROC proc); +extern void CustomDialogClose(HWND); extern INT_PTR CustomDialogBox (int templ, HWND hDlg, DLGPROC proc); extern struct newresource *getresource (int tmpl); extern void scaleresource_init(const TCHAR*, int); @@ -143,6 +150,9 @@ extern int calculated_boxart_window_width; void getextendedframebounds(HWND hwnd, RECT *r); void reset_box_art_window(void); +void gui_cursor(HWND, struct newresource*, int, int, int); +void process_gui_control(HWND h, struct newresource *nres); + void darkmode_initdialog(HWND hDlg); void darkmode_themechanged(HWND hDlg); INT_PTR darkmode_ctlcolor(WPARAM wParam, bool *handled); diff --git a/od-win32/win32gui_extra.cpp b/od-win32/win32gui_extra.cpp index e628bfef..5fb753bc 100644 --- a/od-win32/win32gui_extra.cpp +++ b/od-win32/win32gui_extra.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include "Xinput.h" #include "sysconfig.h" #include "sysdeps.h" @@ -41,6 +43,8 @@ static int fontweight_list = FW_REGULAR; static TEXTMETRIC listview_tm; static const TCHAR *fontprefix; +static IUIAutomation *Automation; + #include typedef struct { WORD dlgVer; @@ -259,7 +263,6 @@ static const WORD *DIALOG_GetControl32(const WORD *p, DLG_CONTROL_INFO *info, return (const WORD *)(((UINT_PTR)p + 3) & ~3); } - static BOOL DIALOG_CreateControls32(HWND hwnd, LPCSTR tmpl, const DLG_TEMPLATE *dlgTemplate, HINSTANCE hInst, struct newresource *res) { @@ -314,6 +317,75 @@ static BOOL DIALOG_CreateControls32(HWND hwnd, LPCSTR tmpl, const DLG_TEMPLATE * nrw->y = y; nrw->w = w; nrw->h = h; + if (info.id != IDC_STATIC) { + int style = info.style & BS_TYPEMASK; + if (!_tcsicmp(info.className, _T("Button")) || + !_tcsicmp(info.className, _T("ComboBox")) || + !_tcsicmp(info.className, _T("SysTreeView32")) || + !_tcsicmp(info.className, _T("SysListView32")) || + !_tcsicmp(info.className, _T("msctls_trackbar32")) || + !_tcsicmp(info.className, _T("Edit"))) { + if (style == BS_GROUPBOX) { + nrw->selectable = false; + } else { + nrw->selectable = true; + } + if (!_tcsicmp(info.className, _T("Edit"))) { + if (info.style & ES_READONLY) { + nrw->selectable = false; + } + } + if (!_tcsicmp(info.className, _T("ComboBox"))) { + style |= 0x100; + } + if (!_tcsicmp(info.className, _T("msctls_trackbar32"))) { + style |= 0x200; + } + if (!_tcsicmp(info.className, _T("SysTreeView32"))) { + nrw->list = true; + nrw->region = 3; + style |= 0x400; + } + if (!_tcsicmp(info.className, _T("SysListView32"))) { + nrw->listn = true; + nrw->region = 3; + style |= 0x400; + } + nrw->style = style; + int i = 0; + nrw->hwndx[i++] = nrw->hwnd; + if (!_tcsicmp(info.className, _T("ComboBox"))) { + COMBOBOXINFO pcbi = {}; + pcbi.cbSize = sizeof(COMBOBOXINFO); + GetComboBoxInfo(nrw->hwnd, &pcbi); + if (pcbi.hwndItem && pcbi.hwndItem != nrw->hwnd) { + nrw->hwndx[i++] = pcbi.hwndItem; + } + if (pcbi.hwndCombo && pcbi.hwndCombo != nrw->hwnd) { + nrw->hwndx[i++] = pcbi.hwndCombo; + } + if (pcbi.hwndList && pcbi.hwndList != nrw->hwnd) { + nrw->hwndx[i++] = pcbi.hwndList; + } + } + switch(info.id) + { + case IDC_PANELTREE: + nrw->region = 2; + break; + case IDC_RESETAMIGA: + case IDC_QUITEMU: + case IDC_RESTARTEMU: + case IDC_ERRORLOG: + case IDOK: + case IDCANCEL: + case IDHELP: + nrw->region = 1; + break; + } + } + //write_log(_T("%p %s %d %08x\n"), hwndCtrl, info.className, info.id, info.style); + } /* Send initialisation messages to the control */ if (dlgInfo->hUserFont) SendMessage(hwndCtrl, WM_SETFONT, @@ -2002,3 +2074,646 @@ LRESULT CALLBACK BoxArtWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM } return DefWindowProc(hWnd, message, wParam, lParam); } + + +static HRESULT InitializeUIAutomation(IUIAutomation **ppAutomation) +{ + return CoCreateInstance(CLSID_CUIAutomation, NULL, + CLSCTX_INPROC_SERVER, IID_IUIAutomation, + reinterpret_cast(ppAutomation)); +} + +struct elxy +{ + int sx, sy; + int ex, ey; + int region; + bool selectable; + struct newreswnd *nres; +}; + +static struct elxy *findclosestelement(struct elxy *xy, int total, struct elxy *curxy, int x, int y, int region, int newdist, int xydist) +{ + struct elxy *closest = NULL; + int olddist = 10000; + + int cx = curxy->sx; + int cy = curxy->sy; + int cxe = curxy->ex; + int cye = curxy->ey; + + if (x > 0) { + cxe = cx = curxy->ex + 1; + } else if (x < 0) { + cxe = cx = curxy->sx - 1; + } + if (y > 0) { + cye = cy = curxy->ey + 1; + } else if (y < 0) { + cye = cy = curxy->sy - 1; + } + + cx += x * newdist; + cy += y * newdist; + cxe += x * newdist; + cye += y * newdist; + + int cxs = cx + (cxe - cx) / 2; + int cys = cy + (cye - cy) / 2; + + for (int i = 0; i < total; i++) { + struct elxy *txy = &xy[i]; + int dist = -1; + int sx = txy->sx; + int sy = txy->sy; + int ex = txy->ex; + int ey = txy->ey; + + if (!txy->selectable) { + continue; + } + + if (txy->region != region) { + continue; + } + + if (x) { + ey += xydist; + sy -= xydist; + } + if (y) { + ex += xydist; + sx -= xydist; + } + + if ((sx <= cxs && ex >= cxs) && y) { + if ((y < 0 && txy->ey < curxy->sy) || (y > 0 && txy->sy > curxy->ey)) { + dist = abs(txy->sy + (txy->ey - txy->sy) / 2 - cys); + } + } else if ((sy <= cys && ey >= cys) && x) { + if ((x < 0 && txy->ex < curxy->sx) || (x > 0 && txy->sx > curxy->ex)) { + dist = abs(txy->sx + (txy->ex - txy->sx) / 2 - cxs); + } + } + if (dist > 0 && dist < olddist) { + closest = txy; + olddist = dist; + } + } + return closest; +} + +static void UIA_Invoke(HWND hwnd) +{ + IUIAutomationElement *el; + HRESULT hr = Automation->GetFocusedElement(&el); + if (SUCCEEDED(hr)) { + IUIAutomationInvokePattern *InvokePattern; + hr = el->GetCurrentPattern(UIA_InvokePatternId, (IUnknown **)&InvokePattern); + if (SUCCEEDED(hr) && InvokePattern) { + InvokePattern->Invoke(); + InvokePattern->Release(); + } + el->Release(); + } +} + +static void treeview_cursor(HWND h, HTREEITEM next) +{ + TreeView_SelectItem(h, next); + RECT r; + r.left = -1; + r.top = -1; + TreeView_GetItemRect(h, next, &r, TRUE); + if (r.left != -1 && r.top != -1) { + RECT r2; + GetWindowRect(h, &r2); + r.left += r2.left; + r.right += r2.left; + r.top += r2.top; + r.bottom += r2.top; + SetCursorPos(r.left + (r.right - r.left) / 2, r.top + (r.bottom - r.top) / 2); + } +} + +void gui_cursor(HWND hwnd, struct newresource *ns, int x, int y, int click) +{ + struct elxy *found = NULL; + struct elxy *currres; + struct elxy xy[MAX_DLGID]; + int total = 0; + int maxdist = 0; + int mindist = 32000; + + if (!Automation) { + InitializeUIAutomation(&Automation); + } + if (!Automation) { + return; + } + + for (int i = 0; ns->hwnds[i].hwnd; i++) { + struct newreswnd *nrw = &ns->hwnds[i]; + if (nrw->selectable && IsWindowVisible(nrw->hwnd) && IsWindowEnabled(nrw->hwnd)) { + RECT r; + GetWindowRect(nrw->hwnd, &r); + struct elxy *txy = &xy[total]; + txy->sx = r.left; + txy->sy = r.top; + txy->ex = r.right; + txy->ey = r.bottom; + txy->region = nrw->region; + txy->selectable = nrw->selectable; + txy->nres = nrw; + total++; + } + } + ns = ns->child; + if (ns) { + for (int i = 0; ns->hwnds[i].hwnd; i++) { + struct newreswnd *nrw = &ns->hwnds[i]; + if (IsWindowVisible(nrw->hwnd) && IsWindowEnabled(nrw->hwnd)) { + RECT r; + GetWindowRect(nrw->hwnd, &r); + struct elxy *txy = &xy[total]; + txy->sx = r.left; + txy->sy = r.top; + txy->ex = r.right; + txy->ey = r.bottom; + txy->region = nrw->region; + txy->selectable = nrw->selectable; + txy->nres = nrw; + total++; + } + } + } + + for (int i = 0; i < total; i++) { + struct elxy *txy = &xy[i]; + struct newreswnd *nrw = txy->nres; + if (nrw->x + nrw->w > maxdist) { + maxdist = nrw->x + nrw->x; + } + if (nrw->y + nrw->h > maxdist) { + maxdist = nrw->y + nrw->h; + } + if (nrw->x < mindist) { + mindist = nrw->x; + } + if (nrw->y < mindist) { + mindist = nrw->y; + } + } + + currres = NULL; + HWND focus = GetFocus(); + for (int i = 0; i < total; i++) { + struct elxy *txy = &xy[i]; + for (int j = 0; txy->nres->hwndx[j]; j++) { + HWND h = txy->nres->hwndx[j]; + if (h == focus && txy->selectable) { + RECT r; + GetWindowRect(h, &r); + currres = txy; + write_log("%p %d\n", currres->nres->hwnd, currres->region); + break; + } + } + } + + if (click == 8) { + bool regfound = false; + int region = 0; + if (currres) { + region = currres->region; + } + while (!regfound) { + region++; + if (region >= 4) { + region = 0; + } + for (int i = 0; i < total; i++) { + struct elxy *txy = &xy[i]; + if (txy->region == region) { + if (txy->selectable) { + found = txy; + goto end; + } + regfound = true; + } + } + } + return; + } + + + if (currres && click == 1 && x && !y) { + int style = currres->nres->style; + // msctls_trackbar32 + if (style & 0x200) { + HWND h = currres->nres->hwnd; + LRESULT v = SendMessage(h, TBM_GETPOS, 0, 0); + LRESULT min = SendMessage(h, TBM_GETRANGEMIN, 0, 0); + LRESULT max = SendMessage(h, TBM_GETRANGEMAX, 0, 0); + LRESULT change = SendMessage(h, TBM_GETLINESIZE, 0, 0); + v += change * x; + if (v < min) { + v = min; + } + if (v > max) { + v = max; + } + SendMessage(h, TBM_SETPOSNOTIFY, 0, v); + } + return; + } + + if (currres && click == 1 && !x && !y) { + HWND h = currres->nres->hwnd; + int style = currres->nres->style; + int style2 = style & BS_TYPEMASK; + // ComboBox expand/collapse + if (style & 0x100) { + IUIAutomationElement *el; + HRESULT hr = Automation->ElementFromHandle(currres->nres->hwndx[0], &el); + if (SUCCEEDED(hr)) { + IUIAutomationExpandCollapsePattern *ExpandCollapsePattern; + hr = el->GetCurrentPattern(UIA_ExpandCollapsePatternId, (IUnknown **)&ExpandCollapsePattern); + if (SUCCEEDED(hr) && ExpandCollapsePattern) { + ExpandCollapseState ecs; + hr = ExpandCollapsePattern->get_CurrentExpandCollapseState(&ecs); + if (SUCCEEDED(hr)) { + if (ecs == ExpandCollapseState_Collapsed) { + ExpandCollapsePattern->Expand(); + } else { + ExpandCollapsePattern->Collapse(); + } + } + ExpandCollapsePattern->Release(); + } + el->Release(); + } + } else if (currres->nres->listn) { + // ListView + int c = ListView_GetHotItem(h); + UINT state = ListView_GetItemState(h, c, LVIS_STATEIMAGEMASK); + // checkbox toggle + if (state & 0x3000) { + if ((state & 0x3000) == 0x1000) { + state &= ~0x1000; + state |= 0x2000; + } else { + state &= ~0x2000; + state |= 0x1000; + } + ListView_SetItemState(h, c, state, LVIS_STATEIMAGEMASK); + } + return; + } else if (style2 == BS_PUSHBUTTON || + style2 == BS_DEFPUSHBUTTON || + style2 == BS_CHECKBOX || + style2 == BS_AUTOCHECKBOX || + style2 == BS_RADIOBUTTON || + style2 == BS_AUTORADIOBUTTON || + style2 == BS_3STATE || + style2 == BS_AUTO3STATE) + { + // button, checkbox etc click + UIA_Invoke(h); + return; + } + return; + } + + if (currres) { + int style = currres->nres->style; + HWND h = currres->nres->hwnd; + // TreeView up/down + if (currres->nres->list) { + if (x || y) { + HTREEITEM c = TreeView_GetSelection(h); + HTREEITEM next; + if (x < 0) { + next = TreeView_GetNextItem(h, c, TVGN_PARENT); + } else if (x > 0) { + next = TreeView_GetNextItem(h, c, TVGN_CHILD); + if (!next) { + HTREEITEM next2 = c; + for (;;) { + next2 = TreeView_GetNextItem(h, next2, TVGN_NEXT); + if (!next2) { + break; + } + next = TreeView_GetNextItem(h, next2, TVGN_CHILD); + if (next) { + break; + } + } + } + } else if (y < 0) { + next = TreeView_GetNextItem(h, c, TVGN_PREVIOUS); + if (!next) { + next = c; + for (;;) { + HTREEITEM next2 = TreeView_GetNextItem(h, next, TVGN_NEXT); + if (!next2) { + break; + } + next = next2; + } + } + } else if (y > 0) { + next = TreeView_GetNextItem(h, c, TVGN_NEXT); + if (!next) { + next = TreeView_GetNextItem(h, c, TVGN_PARENT); + if (next) { + next = TreeView_GetNextItem(h, next, TVGN_CHILD); + } else { + next = TreeView_GetNextItem(h, c, TVGN_CHILD); + } + } + } + if (!next) { + next = TreeView_GetNextItem(h, next, TVGN_ROOT); + } + if (next) { + treeview_cursor(h, next); + } + return; + } + } else if (currres->nres->listn) { + // ListView + if (!x && y) { + int c = ListView_GetHotItem(h); + int total = ListView_GetItemCount(h); + c += y; + if (c < 0) { + c = total - 1; + if (c < 0) { + c = 0; + } + } + if (c >= total) { + c = 0; + } + ListView_SetHotItem(h, c); + ListView_EnsureVisible(h, c, FALSE); + RECT r; + r.left = -1; + r.top = -1; + ListView_GetItemRect(h, c, &r, LVIR_BOUNDS); + if (r.left != -1 && r.top != -1) { + RECT r2; + GetWindowRect(h, &r2); + r.left += r2.left; + r.right += r2.left; + r.top += r2.top; + r.bottom += r2.top; + SetCursorPos(r.left + (r.right - r.left) / 3, r.top + (r.bottom - r.top) / 2); + } + } + return; + } else if (style & 0x100) { + // ComboBox expanded up/down + IUIAutomationElement *el; + //HRESULT hr = Automation->GetFocusedElement(&el); + HRESULT hr = Automation->ElementFromHandle(currres->nres->hwndx[0], &el); + if (SUCCEEDED(hr)) { + IUIAutomationExpandCollapsePattern *ExpandCollapsePattern; + hr = el->GetCurrentPattern(UIA_ExpandCollapsePatternId, (IUnknown **)&ExpandCollapsePattern); + if (SUCCEEDED(hr) && ExpandCollapsePattern) { + ExpandCollapseState ecs; + hr = ExpandCollapsePattern->get_CurrentExpandCollapseState(&ecs); + if (SUCCEEDED(hr)) { + if (ecs != ExpandCollapseState_Collapsed) { + ExpandCollapsePattern->Release(); + el->Release(); + INPUT inp[2] = {}; + inp[0].type = INPUT_KEYBOARD; + inp[0].ki.wVk = y < 0 ? VK_UP : VK_DOWN; + inp[1].type = INPUT_KEYBOARD; + inp[1].ki.wVk = inp[0].ki.wVk; + inp[1].ki.dwFlags = KEYEVENTF_KEYUP; + SendInput(ARRAYSIZE(inp), inp, sizeof(INPUT)); + return; + } + } + ExpandCollapsePattern->Release(); + } + el->Release(); + } + } + } + + if (currres && (x || y)) { + int dist_min = 10; + int dist_max = maxdist - mindist; + int dist_step = 10; + + int region = currres->region; + for(int j = 0; j < 5 && !found; j++) { + for (int i = dist_min; i < dist_max && !found; i += dist_step) { + struct elxy *n = findclosestelement(xy, total, currres, x, y, region, i, dist_max * j / 10); + if (n && n != currres) { + found = n; + } + } + } + } +end: + if (found) { + HWND h = found->nres->hwnd; + if (found->nres->list) { + HTREEITEM c = TreeView_GetSelection(h); + treeview_cursor(h, c); + } else { + RECT r; + GetWindowRect(h, &r); + SetCursorPos(r.left + (r.right - r.left) / 3, r.top + (r.bottom - r.top) / 2); + //SetCursorPos(r.left, r.top); + } + HWND parent = GetParent(h); + SetFocus(parent); + SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)h, TRUE); + + //write_log("%p -> %p\n", focus, h); + } + +} + +#define MAX_PADS 4 + +int gui_control = 1; + +void process_gui_control(HWND h, struct newresource *nres) +{ + static int clicked[MAX_PADS]; + static int lastbuttons[MAX_PADS]; + static int mousemove; + + if (h == NULL || nres == NULL) { + mousemove = 1; + } + + for (int i = 0; i < MAX_PADS; i++) { + XINPUT_STATE xstate; + DWORD state = XInputGetState(i, &xstate); + if (state == ERROR_SUCCESS) { + int buttons = xstate.Gamepad.wButtons; + int oldclick = clicked[i]; + bool clickchanged = false; + if (buttons & XINPUT_GAMEPAD_A) { + clicked[i] |= 1; + } else { + clicked[i] &= ~1; + } + if (buttons & XINPUT_GAMEPAD_B) { + clicked[i] |= 2; + } else { + clicked[i] &= ~2; + } + if (buttons & XINPUT_GAMEPAD_X) { + clicked[i] |= 4; + } else { + clicked[i] &= ~4; + } + if (buttons & XINPUT_GAMEPAD_Y) { + clicked[i] |= 8; + } else { + clicked[i] &= ~8; + } + if (clicked[i] != oldclick) { + clickchanged = true; + } + + int newbuttons = buttons; + if (lastbuttons[i] & (XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_RIGHT)) { + if (buttons & (XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_RIGHT)) { + buttons &= ~(XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_RIGHT); + } + } + + int x = 0, y = 0; + if (buttons & XINPUT_GAMEPAD_DPAD_UP) { + y = -1; + mousemove = 0; + } + if (buttons & XINPUT_GAMEPAD_DPAD_DOWN) { + y = 1; + mousemove = 0; + } + if (buttons & XINPUT_GAMEPAD_DPAD_LEFT) { + x = -1; + mousemove = 0; + } + if (buttons & XINPUT_GAMEPAD_DPAD_RIGHT) { + x = 1; + mousemove = 0; + } + + if (mousemove && clicked[i] == 1 && clickchanged) { + + INPUT inputs[2] = { 0 }; + inputs[0].type = INPUT_MOUSE; + inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; + inputs[1].type = INPUT_MOUSE; + inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP; + SendInput(sizeof(inputs) / sizeof(INPUT), inputs, sizeof(INPUT)); + + lastbuttons[i] = newbuttons; + + } else if (mousemove && clicked[i] == 2 && clickchanged) { + + INPUT inputs[2] = { 0 }; + inputs[0].type = INPUT_MOUSE; + inputs[0].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN; + inputs[1].type = INPUT_MOUSE; + inputs[1].mi.dwFlags = MOUSEEVENTF_RIGHTUP; + SendInput(sizeof(inputs) / sizeof(INPUT), inputs, sizeof(INPUT)); + + lastbuttons[i] = newbuttons; + + } else if (mousemove && clicked[i] == 8 && clickchanged) { + + INPUT inputs[2] = { 0 }; + inputs[0].type = INPUT_KEYBOARD; + inputs[0].ki.wVk = VK_TAB; + inputs[1].type = INPUT_KEYBOARD; + inputs[1].ki.wVk = VK_TAB; + inputs[1].ki.dwFlags = KEYEVENTF_KEYUP; + SendInput(sizeof(inputs) / sizeof(INPUT), inputs, sizeof(INPUT)); + + lastbuttons[i] = newbuttons; + + } else { + + if (nres && h && (x || y || (clickchanged && clicked[i]))) { + gui_cursor(h, nres, x, y, clicked[i]); + } + lastbuttons[i] = newbuttons; + + int min = 4096; + int max = 30; + int xdiff = 0, ydiff = 0; + if (xstate.Gamepad.sThumbLX < -min || xstate.Gamepad.sThumbLX > min) { + xdiff = abs(xstate.Gamepad.sThumbLX) - min; + if (xstate.Gamepad.sThumbLX < 0) { + xdiff = -xdiff; + } + } + if (xstate.Gamepad.sThumbLY < -min || xstate.Gamepad.sThumbLY > min) { + ydiff = abs(xstate.Gamepad.sThumbLY) - min; + if (xstate.Gamepad.sThumbLY < 0) { + ydiff = -ydiff; + } + } + if (xdiff || ydiff) { + xdiff /= 1024; + ydiff /= 1024; + if (xdiff < -max) { + xdiff = -max; + } + if (xdiff > max) { + xdiff = max; + } + if (ydiff < -max) { + ydiff = -max; + } + if (ydiff > max) { + ydiff = max; + } + POINT pt; + if ((xdiff || ydiff) && GetCursorPos(&pt)) { + POINT ptx = pt; + pt.x += xdiff; + pt.y += -ydiff; + if (h) { + RECT r; + WINDOWINFO wi = { 0 }; + wi.cbSize = sizeof(wi); + GetWindowInfo(h, &wi); + r = wi.rcClient; + if (pt.x < r.left) { + pt.x = r.left; + } + if (pt.x > r.right) { + pt.x = r.right; + } + if (pt.y < r.top) { + pt.y = r.top; + } + if (pt.y > r.bottom) { + pt.y = r.bottom; + } + } + if (ptx.x != pt.x || ptx.y != pt.y) { + mousemove = 1; + SetCursorPos(pt.x, pt.y); + } + } + } + } + + } + } +} diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj b/od-win32/winuae_msvc15/winuae_msvc.vcxproj index c2a8abe1..5a7ae28f 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj @@ -371,7 +371,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true %(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\ @@ -452,7 +452,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true %(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\ @@ -534,7 +534,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true %(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\ @@ -615,7 +615,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) NotSet $(OutDir)$(TargetName)$(TargetExt) true @@ -766,7 +766,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) NotSet $(OutDir)$(TargetName)$(TargetExt) true @@ -918,7 +918,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) NotSet $(OutDir)$(TargetName)$(TargetExt) true @@ -1072,7 +1072,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;winio.lib;setupapi.lib;wininet.lib;shlwapi.lib;libpng16.lib;lglcd.lib;openal32.lib;portaudio_x86.lib;vfw32.lib;wtsapi32.lib;enet.lib;lzmalib.lib;prowizard.lib;libFLAC_static.lib;hid.lib;zlibstat.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true %(AdditionalLibraryDirectories);$(SolutionDir)\..\lib\ @@ -1154,7 +1154,7 @@ 0x0409 - ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;%(AdditionalDependencies) + ws2_32.lib;winmm.lib;comctl32.lib;version.lib;vfw32.lib;msacm32.lib;dsound.lib;dinput8.lib;d3d9.lib;d3dx9.lib;setupapi.lib;wininet.lib;shlwapi.lib;zlibstat.lib;portaudio_x64.lib;openal32.lib;libpng16.lib;lglcd.lib;wtsapi32.lib;enet_x64.lib;prowizard_x64.lib;lzmalib.lib;libFLAC_static.lib;hid.lib;Iphlpapi.lib;luastatic.lib;libmpeg2_ff.lib;softfloat.lib;gdiplus.lib;effects11.lib;Msimg32.lib;Dwmapi.lib;mt32emu.lib;XINPUT9_1_0.lib;%(AdditionalDependencies) NotSet $(OutDir)$(TargetName)$(TargetExt) true