diff options
author | 2016-03-02 21:49:49 +0100 | |
---|---|---|
committer | 2016-03-02 21:49:49 +0100 | |
commit | 9fe9f6d93e672bcd926f9e7461774bc9cc22e094 (patch) | |
tree | 3911b611dd010a4108b90fb8b8c82116eec21117 /src/osd/windows/window.cpp | |
parent | dbdf21ee465acadf3e643d62d6bedfcc297ada85 (diff) | |
parent | 1914702e6fae052668df5b068a502bca57c9a3b0 (diff) |
Merge remote-tracking branch 'refs/remotes/mamedev/master'
# Resolved Conflicts:
# src/osd/modules/render/d3d/d3dhlsl.cpp
# src/osd/windows/winmain.cpp
Diffstat (limited to 'src/osd/windows/window.cpp')
-rw-r--r-- | src/osd/windows/window.cpp | 189 |
1 files changed, 147 insertions, 42 deletions
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp index bb81f0b9de5..52d0a898df7 100644 --- a/src/osd/windows/window.cpp +++ b/src/osd/windows/window.cpp @@ -12,9 +12,12 @@ // Needed for RAW Input #define WM_INPUT 0x00FF +#include <stdio.h> // must be here otherwise issues with I64FMT in MINGW // standard C headers #include <process.h> +#include <atomic> + // MAME headers #include "emu.h" #include "uiinput.h" @@ -23,7 +26,6 @@ #include "winmain.h" #include "window.h" #include "video.h" -#include "input.h" #include "winutf8.h" #include "winutil.h" @@ -36,6 +38,12 @@ #include "modules/render/drawogl.h" #endif +#define NOT_ALREADY_DOWN(x) (x & 0x40000000) == 0 +#define SCAN_CODE(x) ((x >> 16) & 0xff) +#define IS_EXTENDED(x) (0x01000000 & x) +#define MAKE_DI_SCAN(scan, isextended) (scan & 0x7f) | (isextended ? 0x80 : 0x00) +#define WINOSD(machine) downcast<windows_osd_interface*>(&machine.osd()) + //============================================================ // PARAMETERS //============================================================ @@ -122,11 +130,11 @@ struct mtlog }; static mtlog mtlog[100000]; -static volatile INT32 mtlogindex; +static std::atomic<INT32> mtlogindex; void mtlog_add(const char *event) { - int index = atomic_increment32((INT32 *) &mtlogindex) - 1; + int index = mtlogindex++; if (index < ARRAY_LENGTH(mtlog)) { mtlog[index].timestamp = osd_ticks(); @@ -144,7 +152,7 @@ static void mtlog_dump(void) for (i = 0; i < mtlogindex; i++) { osd_ticks_t curr = mtlog[i].timestamp * 1000000 / cps; - fprintf(f, "%20I64d %10I64d %s\n", curr, curr - last, mtlog[i].event); + fprintf(f, "%20" I64FMT "d %10" I64FMT "d %s\n", (UINT64)curr, (UINT64)(curr - last), mtlog[i].event); last = curr; } fclose(f); @@ -188,7 +196,7 @@ bool windows_osd_interface::window_init() fatalerror("Failed to create window thread ready event\n"); // create a thread to run the windows from - temp = _beginthreadex(nullptr, 0, win_window_info::thread_entry, nullptr, 0, (unsigned *)&window_threadid); + temp = _beginthreadex(nullptr, 0, win_window_info::thread_entry, this, 0, (unsigned *)&window_threadid); window_thread = (HANDLE)temp; if (window_thread == nullptr) fatalerror("Failed to create window thread\n"); @@ -205,19 +213,19 @@ bool windows_osd_interface::window_init() } const int fallbacks[VIDEO_MODE_COUNT] = { - -1, // NONE -> no fallback - VIDEO_MODE_NONE, // GDI -> NONE - VIDEO_MODE_D3D, // BGFX -> D3D + -1, // NONE -> no fallback + VIDEO_MODE_NONE, // GDI -> NONE + VIDEO_MODE_D3D, // BGFX -> D3D #if (USE_OPENGL) - VIDEO_MODE_GDI, // OPENGL -> GDI + VIDEO_MODE_GDI, // OPENGL -> GDI #endif - -1, // No SDL2ACCEL on Windows OSD + -1, // No SDL2ACCEL on Windows OSD #if (USE_OPENGL) - VIDEO_MODE_OPENGL, // D3D -> OPENGL + VIDEO_MODE_OPENGL, // D3D -> OPENGL #else - VIDEO_MODE_GDI, // D3D -> GDI + VIDEO_MODE_GDI, // D3D -> GDI #endif - -1 // No SOFT on Windows OSD + -1 // No SOFT on Windows OSD }; int current_mode = video_config.mode; @@ -225,7 +233,7 @@ bool windows_osd_interface::window_init() { bool error = false; switch(current_mode) - { + { case VIDEO_MODE_NONE: error = renderer_none::init(machine()); break; @@ -401,7 +409,7 @@ win_window_info::~win_window_info() if (m_renderer != nullptr) { delete m_renderer; - } +} } @@ -437,7 +445,31 @@ static BOOL is_mame_window(HWND hwnd) return FALSE; } +inline static BOOL handle_mouse_button(windows_osd_interface *osd, int button, int down, int x, int y) +{ + MouseButtonEventArgs args; + args.button = button; + args.keydown = down; + args.xpos = x; + args.ypos = y; + + bool handled = osd->handle_input_event(INPUT_EVENT_MOUSE_BUTTON, &args); + + // When in lightgun mode or mouse mode, the mouse click may be routed to the input system + // because the mouse interactions in the UI are routed from the video_window_proc below + // we need to make sure they aren't suppressed in these cases. + return handled && !osd->options().lightgun() && !osd->options().mouse(); +} +inline static BOOL handle_keypress(windows_osd_interface *osd, int vkey, int down, int scancode, BOOL extended_key) +{ + KeyPressEventArgs args; + args.event_id = down ? INPUT_EVENT_KEYDOWN : INPUT_EVENT_KEYUP; + args.scancode = MAKE_DI_SCAN(scancode, extended_key); + args.vkey = vkey; + + return osd->handle_input_event(args.event_id, &args); +} //============================================================ // winwindow_process_events @@ -478,36 +510,45 @@ void winwindow_process_events(running_machine &machine, int ingame, bool nodispa // forward mouse button downs to the input system case WM_LBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_RBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_MBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_XBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; // forward mouse button ups to the input system case WM_LBUTTONUP: - dispatch = !wininput_handle_mouse_button(0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_RBUTTONUP: - dispatch = !wininput_handle_mouse_button(1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_MBUTTONUP: - dispatch = !wininput_handle_mouse_button(2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_XBUTTONUP: - dispatch = !wininput_handle_mouse_button(3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(WINOSD(machine), 3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + break; + + case WM_KEYDOWN: + if (NOT_ALREADY_DOWN(message.lParam)) + dispatch = !handle_keypress(WINOSD(machine), message.wParam, TRUE, SCAN_CODE(message.lParam), IS_EXTENDED(message.lParam)); + break; + + case WM_KEYUP: + dispatch = !handle_keypress(WINOSD(machine), message.wParam, FALSE, SCAN_CODE(message.lParam), IS_EXTENDED(message.lParam)); break; } } @@ -688,7 +729,7 @@ void winwindow_update_cursor_state(running_machine &machine) // 2. we also hide the cursor in full screen mode and when the window doesn't have a menu // 3. we also hide the cursor in windowed mode if we're not paused and // the input system requests it - if (winwindow_has_focus() && ((!video_config.windowed && !win_window_list->win_has_menu()) || (!machine.paused() && wininput_should_hide_mouse()))) + if (winwindow_has_focus() && ((!video_config.windowed && !win_window_list->win_has_menu()) || (!machine.paused() && downcast<windows_osd_interface&>(machine.osd()).should_hide_mouse()))) { win_window_info *window = win_window_list; RECT bounds; @@ -1152,6 +1193,7 @@ int win_window_info::wnd_extra_height() unsigned __stdcall win_window_info::thread_entry(void *param) { MSG message; + windows_osd_interface *osd = static_cast<windows_osd_interface*>(param); // make a bogus user call to make us a message thread PeekMessage(&message, nullptr, 0, 0, PM_NOREMOVE); @@ -1179,36 +1221,36 @@ unsigned __stdcall win_window_info::thread_entry(void *param) // forward mouse button downs to the input system case WM_LBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_RBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_MBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_XBUTTONDOWN: - dispatch = !wininput_handle_mouse_button(3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; // forward mouse button ups to the input system case WM_LBUTTONUP: - dispatch = !wininput_handle_mouse_button(0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_RBUTTONUP: - dispatch = !wininput_handle_mouse_button(1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_MBUTTONUP: - dispatch = !wininput_handle_mouse_button(2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; case WM_XBUTTONUP: - dispatch = !wininput_handle_mouse_button(3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); + dispatch = !handle_mouse_button(osd, 3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam)); break; // a terminate message to the thread posts a quit @@ -1369,7 +1411,7 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR // input: handle the raw input case WM_INPUT: - wininput_handle_raw((HRAWINPUT)lparam); + downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_RAWINPUT, &lparam); break; // syskeys - ignore @@ -1613,6 +1655,12 @@ void win_window_info::draw_video_contents(HDC dc, int update) } +static inline int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) +{ + float aspect0 = (float)width0 / (float)height0; + float aspect1 = (float)width1 / (float)height1; + return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; +} //============================================================ // constrain_to_aspect_ratio @@ -1626,15 +1674,19 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad INT32 propwidth, propheight; INT32 minwidth, minheight; INT32 maxwidth, maxheight; - INT32 viswidth, visheight; INT32 adjwidth, adjheight; - float pixel_aspect; + float desired_aspect = 1.0f; + osd_dim window_dim = get_size(); + INT32 target_width = window_dim.width(); + INT32 target_height = window_dim.height(); + INT32 xscale = 1, yscale = 1; + int newwidth, newheight; osd_monitor_info *monitor = winwindow_video_window_monitor(&rect); assert(GetCurrentThreadId() == window_threadid); // get the pixel aspect ratio for the target monitor - pixel_aspect = monitor->aspect(); + float pixel_aspect = monitor->aspect(); // determine the proposed width/height propwidth = rect.width() - extrawidth; @@ -1662,6 +1714,58 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad // get the minimum width/height for the current layout m_target->compute_minimum_size(minwidth, minheight); + // compute the appropriate visible area if we're trying to keepaspect + if (video_config.keepaspect) + { + // make sure the monitor is up-to-date + m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height); + desired_aspect = (float)target_width / (float)target_height; + } + + // non-integer scaling - often gives more pleasing results in full screen + newwidth = target_width; + newheight = target_height; + if (!video_config.fullstretch) + { + // compute maximum integral scaling to fit the window + xscale = (target_width + 2) / newwidth; + yscale = (target_height + 2) / newheight; + + // try a little harder to keep the aspect ratio if desired + if (video_config.keepaspect) + { + // if we could stretch more in the X direction, and that makes a better fit, bump the xscale + while (newwidth * (xscale + 1) <= window_dim.width() && + better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) + xscale++; + + // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale + while (newheight * (yscale + 1) <= window_dim.height() && + better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) + yscale++; + + // now that we've maxed out, see if backing off the maximally stretched one makes a better fit + if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale) + { + while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) + xscale--; + } + else + { + while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0)) + yscale--; + } + } + + // ensure at least a scale factor of 1 + if (xscale <= 0) xscale = 1; + if (yscale <= 0) yscale = 1; + + // apply the final scale + newwidth *= xscale; + newheight *= yscale; + } + // clamp against the absolute minimum propwidth = MAX(propwidth, MIN_WINDOW_DIM); propheight = MAX(propheight, MIN_WINDOW_DIM); @@ -1692,12 +1796,9 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad propwidth = MIN(propwidth, maxwidth); propheight = MIN(propheight, maxheight); - // compute the visible area based on the proposed rectangle - m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); - // compute the adjustments we need to make - adjwidth = (viswidth + extrawidth) - rect.width(); - adjheight = (visheight + extraheight) - rect.height(); + adjwidth = (propwidth + extrawidth) - rect.width(); + adjheight = (propheight + extraheight) - rect.height(); // based on which corner we're adjusting, constrain in different ways osd_rect ret(rect); @@ -1724,6 +1825,7 @@ osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height() + adjheight); break; } + return ret; } @@ -1815,10 +1917,13 @@ osd_dim win_window_info::get_max_bounds(int constrain) // constrain to fit if (constrain) + { maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); + } else { - maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); + // No - the maxima returned by usable_position_size are in window units, not usable units + //maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); } return maximum.dim(); } |