summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author npwoods <npwoods@mess.org>2019-08-04 15:49:31 -0400
committer R. Belmont <rb6502@users.noreply.github.com>2019-08-04 15:49:31 -0400
commitfe3caae2a44c5534353e513563aebcd2dd79e8c2 (patch)
tree4ab957977dfe2625a029296b4e3ee7512381d7c0
parent16b1ed88f69c1b61b947584ccf113fedb298b721 (diff)
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
-rw-r--r--src/frontend/mame/luaengine.cpp4
-rw-r--r--src/osd/modules/input/input_dinput.cpp8
-rw-r--r--src/osd/modules/input/input_dinput.h37
-rw-r--r--src/osd/modules/input/input_winhybrid.cpp4
-rw-r--r--src/osd/osdcore.h3
-rw-r--r--src/osd/sdl/window.cpp10
-rw-r--r--src/osd/windows/window.cpp115
-rw-r--r--src/osd/windows/window.h11
-rw-r--r--src/osd/windows/winmain.cpp1
-rw-r--r--src/osd/windows/winmain.h2
10 files changed, 176 insertions, 19 deletions
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index f5ebec7190d..bb4c585516a 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -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
diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp
index 4d434ce3b4c..0b5eb348dc0 100644
--- a/src/osd/modules/input/input_dinput.cpp
+++ b/src/osd/modules/input/input_dinput.cpp
@@ -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);
diff --git a/src/osd/modules/input/input_dinput.h b/src/osd/modules/input/input_dinput.h
index 2f8331f5e5f..a2b6c2edcbb 100644
--- a/src/osd/modules/input/input_dinput.h
+++ b/src/osd/modules/input/input_dinput.h
@@ -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;
diff --git a/src/osd/modules/input/input_winhybrid.cpp b/src/osd/modules/input/input_winhybrid.cpp
index 6b945710e3b..1436ae009d6 100644
--- a/src/osd/modules/input/input_winhybrid.cpp
+++ b/src/osd/modules/input/input_winhybrid.cpp
@@ -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);
diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h
index aababe47a19..d64ca04c578 100644
--- a/src/osd/osdcore.h
+++ b/src/osd/osdcore.h
@@ -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
diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
index 18899cf1b69..875e06a7b3d 100644
--- a/src/osd/sdl/window.cpp
+++ b/src/osd/sdl/window.cpp
@@ -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
+}
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
index 7b574d121cf..dff970eb1fe 100644
--- a/src/osd/windows/window.cpp
+++ b/src/osd/windows/window.cpp
@@ -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,18 +664,41 @@ 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, &gti)
+ ? 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)
{
diff --git a/src/osd/windows/window.h b/src/osd/windows/window.h
index 7d82888bc47..3e9838ba396 100644
--- a/src/osd/windows/window.h
+++ b/src/osd/windows/window.h
@@ -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
diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp
index 5146bfae31e..721407a777a 100644
--- a/src/osd/windows/winmain.cpp
+++ b/src/osd/windows/winmain.cpp
@@ -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" },
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index 5fb71fa9286..21e1b9d2044 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -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); }