summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/windows/window.cpp
diff options
context:
space:
mode:
author ImJezze <jezze@gmx.net>2016-03-02 21:49:49 +0100
committer ImJezze <jezze@gmx.net>2016-03-02 21:49:49 +0100
commit9fe9f6d93e672bcd926f9e7461774bc9cc22e094 (patch)
tree3911b611dd010a4108b90fb8b8c82116eec21117 /src/osd/windows/window.cpp
parentdbdf21ee465acadf3e643d62d6bedfcc297ada85 (diff)
parent1914702e6fae052668df5b068a502bca57c9a3b0 (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.cpp189
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();
}