mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +03:00
Creating an -attach_window command line parameter on Windows to attach to an existing window (#5381)
* Creating an -attach_window command line parameter on Windows to attach to an existing window * Moved -attach_window option to Windows-specific code * Created an osd_set_aggressive_input_focus() function and exposed to LUA * Created a dummy implementation of osd_set_aggressive_input_focus() for SDL
This commit is contained in:
parent
16b1ed88f6
commit
fe3caae2a4
@ -2278,6 +2278,7 @@ void lua_engine::initialize()
|
||||
* ui:get_line_height() - current ui font height
|
||||
* ui:get_string_width(str, scale) - get str width with ui font at scale factor of current font size
|
||||
* ui:get_char_width(char) - get width of utf8 glyph char with ui font
|
||||
* ui:set_aggressive_input_focus(bool)
|
||||
*
|
||||
* ui.single_step
|
||||
* ui.show_fps - fps display enabled
|
||||
@ -2293,7 +2294,8 @@ void lua_engine::initialize()
|
||||
"get_line_height", &mame_ui_manager::get_line_height,
|
||||
"get_string_width", &mame_ui_manager::get_string_width,
|
||||
// sol converts char32_t to a string
|
||||
"get_char_width", [](mame_ui_manager &m, uint32_t utf8char) { return m.get_char_width(utf8char); });
|
||||
"get_char_width", [](mame_ui_manager &m, uint32_t utf8char) { return m.get_char_width(utf8char); },
|
||||
"set_aggressive_input_focus", [](mame_ui_manager &m, bool aggressive_focus) { osd_set_aggressive_input_focus(aggressive_focus); });
|
||||
|
||||
|
||||
/* device_state_entry library
|
||||
|
@ -300,7 +300,7 @@ public:
|
||||
int keynum;
|
||||
|
||||
// allocate and link in a new device
|
||||
devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(machine, *this, instance, &c_dfDIKeyboard, nullptr, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
|
||||
devinfo = m_dinput_helper->create_device<dinput_keyboard_device>(machine, *this, instance, &c_dfDIKeyboard, nullptr, dinput_cooperative_level::FOREGROUND);
|
||||
if (devinfo == nullptr)
|
||||
goto exit;
|
||||
|
||||
@ -372,7 +372,7 @@ public:
|
||||
HRESULT result;
|
||||
|
||||
// allocate and link in a new device
|
||||
devinfo = m_dinput_helper->create_device<dinput_mouse_device>(machine, *this, instance, &c_dfDIMouse2, &c_dfDIMouse, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
|
||||
devinfo = m_dinput_helper->create_device<dinput_mouse_device>(machine, *this, instance, &c_dfDIMouse2, &c_dfDIMouse, dinput_cooperative_level::FOREGROUND);
|
||||
if (devinfo == nullptr)
|
||||
goto exit;
|
||||
|
||||
@ -572,13 +572,13 @@ public:
|
||||
|
||||
BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
|
||||
{
|
||||
DWORD cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
|
||||
dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND;
|
||||
running_machine &machine = *static_cast<running_machine *>(ref);
|
||||
dinput_joystick_device *devinfo;
|
||||
int result = 0;
|
||||
|
||||
if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu())
|
||||
cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
|
||||
cooperative_level = dinput_cooperative_level::BACKGROUND;
|
||||
|
||||
// allocate and link in a new device
|
||||
devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level);
|
||||
|
@ -50,6 +50,12 @@ typedef HRESULT (WINAPI *dinput_create_fn)(HINSTANCE, DWORD, LPDIRECTINPUT8 *, L
|
||||
typedef HRESULT (WINAPI *dinput_create_fn)(HINSTANCE, DWORD, LPDIRECTINPUT *, LPUNKNOWN);
|
||||
#endif
|
||||
|
||||
enum class dinput_cooperative_level
|
||||
{
|
||||
FOREGROUND,
|
||||
BACKGROUND
|
||||
};
|
||||
|
||||
class dinput_api_helper
|
||||
{
|
||||
private:
|
||||
@ -74,9 +80,11 @@ public:
|
||||
LPCDIDEVICEINSTANCE instance,
|
||||
LPCDIDATAFORMAT format1,
|
||||
LPCDIDATAFORMAT format2,
|
||||
DWORD cooperative_level)
|
||||
dinput_cooperative_level cooperative_level)
|
||||
{
|
||||
HRESULT result;
|
||||
std::shared_ptr<win_window_info> window;
|
||||
HWND hwnd;
|
||||
|
||||
// convert instance name to utf8
|
||||
std::string utf8_instance_name = osd::text::from_tstring(instance->tszInstanceName);
|
||||
@ -120,8 +128,33 @@ public:
|
||||
goto error;
|
||||
}
|
||||
|
||||
// default window to the first window in the list
|
||||
window = std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front());
|
||||
DWORD di_cooperative_level;
|
||||
if (window->attached_mode())
|
||||
{
|
||||
// in attached mode we have to ignore the caller and hook up to the desktop window
|
||||
hwnd = GetDesktopWindow();
|
||||
di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hwnd = window->platform_window();
|
||||
switch (cooperative_level)
|
||||
{
|
||||
case dinput_cooperative_level::BACKGROUND:
|
||||
di_cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
|
||||
break;
|
||||
case dinput_cooperative_level::FOREGROUND:
|
||||
di_cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
|
||||
break;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
}
|
||||
|
||||
// set the cooperative level
|
||||
result = devinfo->dinput.device->SetCooperativeLevel(std::static_pointer_cast<win_window_info>(osd_common_t::s_window_list.front())->platform_window(), cooperative_level);
|
||||
result = devinfo->dinput.device->SetCooperativeLevel(hwnd, di_cooperative_level);
|
||||
if (result != DI_OK)
|
||||
goto error;
|
||||
|
||||
|
@ -186,7 +186,7 @@ public:
|
||||
|
||||
BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
|
||||
{
|
||||
DWORD cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
|
||||
dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND;
|
||||
running_machine &machine = *static_cast<running_machine *>(ref);
|
||||
dinput_joystick_device *devinfo;
|
||||
int result = 0;
|
||||
@ -200,7 +200,7 @@ public:
|
||||
}
|
||||
|
||||
if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu())
|
||||
cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
|
||||
cooperative_level = dinput_cooperative_level::BACKGROUND;
|
||||
|
||||
// allocate and link in a new device
|
||||
devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level);
|
||||
|
@ -1053,4 +1053,7 @@ std::vector<std::string> osd_get_command_line(int argc, char *argv[]);
|
||||
#define printf !MUST_USE_osd_printf_*_CALLS_WITHIN_THE_CORE!
|
||||
*/
|
||||
|
||||
// specifies "aggressive focus" - should MAME capture input for any windows co-habiting a MAME window?
|
||||
void osd_set_aggressive_input_focus(bool aggressive_focus);
|
||||
|
||||
#endif // MAME_OSD_OSDCORE_H
|
||||
|
@ -1158,3 +1158,13 @@ sdl_window_info::~sdl_window_info()
|
||||
{
|
||||
global_free(m_original_mode);
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// osd_set_aggressive_input_focus
|
||||
//============================================================
|
||||
|
||||
void osd_set_aggressive_input_focus(bool aggressive_focus)
|
||||
{
|
||||
// dummy implementation for now
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "winutf8.h"
|
||||
|
||||
#include "winutil.h"
|
||||
#include "strconv.h"
|
||||
|
||||
#include "modules/monitor/monitor_common.h"
|
||||
|
||||
@ -110,6 +111,8 @@ static DWORD last_update_time;
|
||||
|
||||
static HANDLE ui_pause_event;
|
||||
|
||||
static bool s_aggressive_focus;
|
||||
|
||||
|
||||
|
||||
//============================================================
|
||||
@ -315,7 +318,8 @@ win_window_info::win_window_info(
|
||||
m_lastclicktime(std::chrono::system_clock::time_point::min()),
|
||||
m_lastclickx(0),
|
||||
m_lastclicky(0),
|
||||
m_machine(machine)
|
||||
m_machine(machine),
|
||||
m_attached_mode(false)
|
||||
{
|
||||
memset(m_title,0,sizeof(m_title));
|
||||
m_non_fullscreen_bounds.left = 0;
|
||||
@ -660,17 +664,40 @@ void winwindow_toggle_full_screen(void)
|
||||
|
||||
bool winwindow_has_focus(void)
|
||||
{
|
||||
HWND focuswnd = GetFocus();
|
||||
|
||||
// see if one of the video windows has focus
|
||||
for (auto window : osd_common_t::s_window_list)
|
||||
if (focuswnd == std::static_pointer_cast<win_window_info>(window)->platform_window())
|
||||
{
|
||||
switch (std::static_pointer_cast<win_window_info>(window)->focus())
|
||||
{
|
||||
case win_window_focus::NONE:
|
||||
break;
|
||||
|
||||
case win_window_focus::THREAD:
|
||||
if (s_aggressive_focus)
|
||||
return true;
|
||||
break;
|
||||
|
||||
case win_window_focus::WINDOW:
|
||||
return true;
|
||||
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// osd_set_aggressive_input_focus
|
||||
//============================================================
|
||||
|
||||
void osd_set_aggressive_input_focus(bool aggressive_focus)
|
||||
{
|
||||
s_aggressive_focus = aggressive_focus;
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// winwindow_update_cursor_state
|
||||
// (main thread)
|
||||
@ -885,7 +912,19 @@ void win_window_info::update()
|
||||
// post a redraw request with the primitive list as a parameter
|
||||
last_update_time = timeGetTime();
|
||||
|
||||
SendMessage(platform_window(), WM_USER_REDRAW, 0, (LPARAM)primlist);
|
||||
if (attached_mode())
|
||||
{
|
||||
HDC hdc = GetDC(platform_window());
|
||||
|
||||
m_primlist = primlist;
|
||||
draw_video_contents(hdc, FALSE);
|
||||
|
||||
ReleaseDC(platform_window(), hdc);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(platform_window(), WM_USER_REDRAW, 0, (LPARAM)primlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1058,8 +1097,21 @@ int win_window_info::complete_create()
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create the window, but don't show it yet
|
||||
HWND hwnd = win_create_window_ex_utf8(
|
||||
// are we in worker UI mode?
|
||||
HWND hwnd;
|
||||
const char *attach_window_name = downcast<windows_options &>(machine().options()).attach_window();
|
||||
m_attached_mode = attach_window_name && *attach_window_name ? true : false;
|
||||
if (m_attached_mode)
|
||||
{
|
||||
// we are in worker UI mode; either this value is an HWND or a window name
|
||||
hwnd = (HWND)atoll(attach_window_name);
|
||||
if (!hwnd)
|
||||
hwnd = FindWindowEx(nullptr, nullptr, nullptr, osd::text::to_tstring(attach_window_name).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// create the window, but don't show it yet
|
||||
hwnd = win_create_window_ex_utf8(
|
||||
fullscreen() ? FULLSCREEN_STYLE_EX : WINDOW_STYLE_EX,
|
||||
"MAME",
|
||||
m_title,
|
||||
@ -1070,6 +1122,7 @@ int win_window_info::complete_create()
|
||||
menu,
|
||||
GetModuleHandleUni(),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
if (hwnd == nullptr)
|
||||
return 1;
|
||||
@ -1077,10 +1130,11 @@ int win_window_info::complete_create()
|
||||
set_platform_window(hwnd);
|
||||
|
||||
// set a pointer back to us
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
if (!attached_mode())
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
|
||||
// skip the positioning stuff for -video none */
|
||||
if (video_config.mode == VIDEO_MODE_NONE)
|
||||
// skip the positioning stuff for '-video none' or '-attach_window'
|
||||
if (video_config.mode == VIDEO_MODE_NONE || attached_mode())
|
||||
{
|
||||
set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this()));
|
||||
renderer().create();
|
||||
@ -1835,6 +1889,47 @@ void win_window_info::set_fullscreen(int fullscreen)
|
||||
adjust_window_position_after_major_change();
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// focus
|
||||
// (main or window thread)
|
||||
//============================================================
|
||||
|
||||
win_window_focus win_window_info::focus() const
|
||||
{
|
||||
HWND focuswnd = nullptr;
|
||||
if (attached_mode())
|
||||
{
|
||||
// if this window is in attached mode, we need to see if it has
|
||||
// focus in its context; first find out what thread owns it
|
||||
DWORD window_thread_id = GetWindowThreadProcessId(platform_window(), nullptr);
|
||||
|
||||
// and then identify which window has focus in that thread's context
|
||||
GUITHREADINFO gti;
|
||||
gti.cbSize = sizeof(gti);
|
||||
focuswnd = GetGUIThreadInfo(window_thread_id, >i)
|
||||
? gti.hwndFocus
|
||||
: nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// life is simpler in non-attached mode
|
||||
focuswnd = GetFocus();
|
||||
}
|
||||
|
||||
if (focuswnd == platform_window())
|
||||
return win_window_focus::WINDOW;
|
||||
else if (focuswnd)
|
||||
return win_window_focus::THREAD;
|
||||
else
|
||||
return win_window_focus::NONE;
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// winwindow_qt_filter
|
||||
//============================================================
|
||||
|
||||
#if (USE_QTDEBUG)
|
||||
bool winwindow_qt_filter(void *message)
|
||||
{
|
||||
|
@ -42,6 +42,14 @@
|
||||
// TYPE DEFINITIONS
|
||||
//============================================================
|
||||
|
||||
enum class win_window_focus
|
||||
{
|
||||
NONE, // neither this window nor this thread have focus
|
||||
THREAD, // a window in this thread has focus
|
||||
WINDOW // this window has focus directly
|
||||
};
|
||||
|
||||
|
||||
class win_window_info : public osd_window_t<HWND>
|
||||
{
|
||||
public:
|
||||
@ -51,6 +59,8 @@ public:
|
||||
|
||||
virtual render_target *target() override { return m_target; }
|
||||
int fullscreen() const override { return m_fullscreen; }
|
||||
bool attached_mode() const { return m_attached_mode; }
|
||||
win_window_focus focus() const;
|
||||
|
||||
void update() override;
|
||||
|
||||
@ -144,6 +154,7 @@ private:
|
||||
#endif
|
||||
|
||||
running_machine & m_machine;
|
||||
bool m_attached_mode;
|
||||
};
|
||||
|
||||
struct osd_draw_callbacks
|
||||
|
@ -165,6 +165,7 @@ const options_entry windows_options::s_option_entries[] =
|
||||
// video options
|
||||
{ nullptr, nullptr, OPTION_HEADER, "WINDOWS VIDEO OPTIONS" },
|
||||
{ WINOPTION_MENU, "0", OPTION_BOOLEAN, "enables menu bar if available by UI implementation" },
|
||||
{ WINOPTION_ATTACH_WINDOW, "", OPTION_STRING, "attach to arbitrary window" },
|
||||
|
||||
// post-processing options
|
||||
{ nullptr, nullptr, OPTION_HEADER, "DIRECT3D POST-PROCESSING OPTIONS" },
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
// video options
|
||||
#define WINOPTION_MENU "menu"
|
||||
#define WINOPTION_ATTACH_WINDOW "attach_window"
|
||||
|
||||
// core post-processing options
|
||||
#define WINOPTION_HLSLPATH "hlslpath"
|
||||
@ -135,6 +136,7 @@ public:
|
||||
|
||||
// video options
|
||||
bool menu() const { return bool_value(WINOPTION_MENU); }
|
||||
const char *attach_window() const { return value(WINOPTION_ATTACH_WINDOW); }
|
||||
|
||||
// core post-processing options
|
||||
const char *screen_post_fx_dir() const { return value(WINOPTION_HLSLPATH); }
|
||||
|
Loading…
Reference in New Issue
Block a user