summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/sdl/window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/sdl/window.cpp')
-rw-r--r--src/osd/sdl/window.cpp792
1 files changed, 498 insertions, 294 deletions
diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
index 875e06a7b3d..59be82238d0 100644
--- a/src/osd/sdl/window.cpp
+++ b/src/osd/sdl/window.cpp
@@ -8,40 +8,38 @@
//
//============================================================
-#ifdef SDLMAME_WIN32
-#include <windows.h>
-#endif
-
-// standard SDL headers
-#include <SDL2/SDL.h>
-
-// standard C headers
-#include <math.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
-#include <list>
-#include <memory>
-
// MAME headers
-
#include "emu.h"
#include "emuopts.h"
#include "render.h"
+#include "screen.h"
+#include "uiinput.h"
#include "ui/uimain.h"
// OSD headers
-
-#include "window.h"
-#include "osdsdl.h"
-#include "modules/render/drawbgfx.h"
-#include "modules/render/drawsdl.h"
-#include "modules/render/draw13.h"
#include "modules/monitor/monitor_common.h"
-#if (USE_OPENGL)
-#include "modules/render/drawogl.h"
+#include "osdsdl.h"
+#include "window.h"
+
+// standard SDL headers
+#include <SDL2/SDL_syswm.h>
+
+// standard C headers
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <list>
+#include <memory>
+
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+
+#ifdef SDLMAME_WIN32
+#include <windows.h>
#endif
+
//============================================================
// PARAMETERS
//============================================================
@@ -66,19 +64,6 @@
#define SDL_VERSION_EQUALS(v1, vnum2) (SDL_VERSIONNUM(v1.major, v1.minor, v1.patch) == vnum2)
-class SDL_DM_Wrapper
-{
-public:
- SDL_DisplayMode mode;
-};
-
-// debugger
-//static int in_background;
-
-
-//============================================================
-// PROTOTYPES
-//============================================================
//============================================================
@@ -90,30 +75,10 @@ bool sdl_osd_interface::window_init()
{
osd_printf_verbose("Enter sdlwindow_init\n");
- // initialize the drawers
-
- switch (video_config.mode)
- {
- case VIDEO_MODE_BGFX:
- renderer_bgfx::init(machine());
- break;
-#if (USE_OPENGL)
- case VIDEO_MODE_OPENGL:
- renderer_ogl::init(machine());
- break;
-#endif
- case VIDEO_MODE_SDL2ACCEL:
- renderer_sdl2::init(machine());
- break;
- case VIDEO_MODE_SOFT:
- renderer_sdl1::init(machine());
- break;
- }
-
- /* We may want to set a number of the hints SDL2 provides.
- * The code below will document which hints were set.
- */
- const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION,
+ // We may want to set a number of the hints SDL2 provides.
+ // The code below will document which hints were set.
+ char const *const hints[] = {
+ SDL_HINT_FRAMEBUFFER_ACCELERATION,
SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS,
SDL_HINT_RENDER_SCALE_QUALITY,
SDL_HINT_RENDER_VSYNC,
@@ -124,23 +89,21 @@ bool sdl_osd_interface::window_init()
SDL_HINT_XINPUT_ENABLED, SDL_HINT_GAMECONTROLLERCONFIG,
SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_HINT_ALLOW_TOPMOST,
SDL_HINT_TIMER_RESOLUTION,
-#if SDL_VERSION_ATLEAST(2, 0, 2)
SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK,
SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT,
SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_MOUSE_RELATIVE_MODE_WARP,
-#endif
-#if SDL_VERSION_ATLEAST(2, 0, 3)
SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_HINT_VIDEO_HIGHDPI_DISABLED,
SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL,
SDL_HINT_WINRT_HANDLE_BACK_BUTTON,
-#endif
- nullptr
- };
+ };
osd_printf_verbose("\nHints:\n");
- for (int i = 0; hints[i] != nullptr; i++)
- osd_printf_verbose("\t%-40s %s\n", hints[i], SDL_GetHint(hints[i]));
+ for (auto const hintname : hints)
+ {
+ char const *const hintvalue(SDL_GetHint(hintname));
+ osd_printf_verbose("\t%-40s %s\n", hintname, hintvalue ? hintvalue : "(NULL)");
+ }
// set up the window list
osd_printf_verbose("Leave sdlwindow_init\n");
@@ -148,30 +111,6 @@ bool sdl_osd_interface::window_init()
}
-void sdl_osd_interface::update_slider_list()
-{
- for (auto window : osd_common_t::s_window_list)
- {
- // check if any window has dirty sliders
- if (window->renderer().sliders_dirty())
- {
- build_slider_list();
- return;
- }
- }
-}
-
-void sdl_osd_interface::build_slider_list()
-{
- m_sliders.clear();
-
- for (auto window : osd_common_t::s_window_list)
- {
- std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list();
- m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
- }
-}
-
//============================================================
// sdlwindow_exit
// (main thread)
@@ -182,33 +121,14 @@ void sdl_osd_interface::window_exit()
osd_printf_verbose("Enter sdlwindow_exit\n");
// free all the windows
+ m_focus_window = nullptr;
while (!osd_common_t::s_window_list.empty())
{
- auto window = osd_common_t::s_window_list.front();
-
- // Part of destroy removes the window from the list
+ auto window = std::move(osd_common_t::s_window_list.back());
+ s_window_list.pop_back();
window->destroy();
}
- switch(video_config.mode)
- {
- case VIDEO_MODE_SDL2ACCEL:
- renderer_sdl1::exit();
- break;
- case VIDEO_MODE_SOFT:
- renderer_sdl1::exit();
- break;
- case VIDEO_MODE_BGFX:
- renderer_bgfx::exit();
- break;
-#if (USE_OPENGL)
- case VIDEO_MODE_OPENGL:
- renderer_ogl::exit();
- break;
-#endif
- default:
- break;
- }
osd_printf_verbose("Leave sdlwindow_exit\n");
}
@@ -293,8 +213,6 @@ void sdl_window_info::toggle_full_screen()
m_windowed_dim = get_size();
}
- // reset UI to main menu
- machine().ui().menu_reset();
// kill off the drawers
renderer_reset();
bool is_osx = false;
@@ -304,17 +222,14 @@ void sdl_window_info::toggle_full_screen()
#endif
if (fullscreen() && (video_config.switchres || is_osx))
{
- SDL_SetWindowFullscreen(platform_window(), 0); // Try to set mode
- SDL_SetWindowDisplayMode(platform_window(), &m_original_mode->mode); // Try to set mode
- SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
+ SDL_SetWindowFullscreen(platform_window(), 0);
+ SDL_SetWindowDisplayMode(platform_window(), &m_original_mode);
+ SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN);
}
SDL_DestroyWindow(platform_window());
set_platform_window(nullptr);
-
downcast<sdl_osd_interface &>(machine().osd()).release_keys();
- set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this()));
-
// toggle the window mode
set_fullscreen(!fullscreen());
@@ -325,7 +240,7 @@ void sdl_window_info::modify_prescale(int dir)
{
int new_prescale = prescale();
- if (dir > 0 && prescale() < 3)
+ if (dir > 0 && prescale() < 20)
new_prescale = prescale() + 1;
if (dir < 0 && prescale() > 1)
new_prescale = prescale() - 1;
@@ -342,11 +257,11 @@ void sdl_window_info::modify_prescale(int dir)
}
else
{
- notify_changed();
m_prescale = new_prescale;
+ notify_changed();
}
- machine().ui().popup_time(1, "Prescale %d", prescale());
}
+ machine().ui().popup_time(1, "Prescale %d", prescale());
}
//============================================================
@@ -393,6 +308,291 @@ int sdl_window_info::xy_to_render_target(int x, int y, int *xt, int *yt)
return renderer().xy_to_render_target(x, y, xt, yt);
}
+void sdl_window_info::mouse_entered(unsigned device)
+{
+ m_mouse_inside = true;
+}
+
+void sdl_window_info::mouse_left(unsigned device)
+{
+ m_mouse_inside = false;
+
+ auto info(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), SDL_FingerID(-1), &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() == info) || (info->finger != SDL_FingerID(-1)))
+ return;
+
+ // leaving implicitly releases buttons, so check hold/drag if necessary
+ if (BIT(info->buttons, 0) && (0 < info->clickcnt))
+ {
+ auto const now(std::chrono::steady_clock::now());
+ auto const exp(std::chrono::milliseconds(250) + info->pressed);
+ int const dx(info->x - info->pressedx);
+ int const dy(info->y - info->pressedy);
+ int const distance((dx * dx) + (dy * dy));
+ if ((exp < now) || (CLICK_DISTANCE < distance))
+ info->clickcnt = -info->clickcnt;
+ }
+
+ // push to UI manager
+ machine().ui_input().push_pointer_leave(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ info->x, info->y,
+ info->buttons, info->clickcnt);
+
+ // dump pointer data
+ m_pointer_mask &= ~(decltype(m_pointer_mask)(1) << info->index);
+ if (info->index < m_next_pointer)
+ m_next_pointer = info->index;
+ m_active_pointers.erase(info);
+}
+
+void sdl_window_info::mouse_down(unsigned device, int x, int y, unsigned button)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ if ((x == info->x) && (y == info->y) && BIT(info->buttons, button))
+ return;
+
+ // detect multi-click actions
+ if (0 == button)
+ {
+ info->primary_down(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ CLICK_DISTANCE,
+ false,
+ m_ptrdev_info);
+ }
+
+ // update info and push to UI manager
+ auto const pressed(decltype(info->buttons)(1) << button);
+ info->x = x;
+ info->y = y;
+ info->buttons |= pressed;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ x, y,
+ info->buttons, pressed, 0, info->clickcnt);
+}
+
+void sdl_window_info::mouse_up(unsigned device, int x, int y, unsigned button)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ if ((x == info->x) && (y == info->y) && !BIT(info->buttons, button))
+ return;
+
+ // detect multi-click actions
+ if (0 == button)
+ {
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ CLICK_DISTANCE);
+ }
+
+ // update info and push to UI manager
+ auto const released(decltype(info->buttons)(1) << button);
+ info->x = x;
+ info->y = y;
+ info->buttons &= ~released;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ x, y,
+ info->buttons, 0, released, info->clickcnt);
+}
+
+void sdl_window_info::mouse_moved(unsigned device, int x, int y)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ // detect multi-click actions
+ if (BIT(info->buttons, 0))
+ {
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ CLICK_DISTANCE);
+ }
+
+ // update info and push to UI manager
+ info->x = x;
+ info->y = y;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::MOUSE,
+ info->index,
+ device,
+ x, y,
+ info->buttons, 0, 0, info->clickcnt);
+}
+
+void sdl_window_info::mouse_wheel(unsigned device, int y)
+{
+ if (!m_mouse_inside)
+ return;
+
+ auto const info(map_pointer(SDL_FingerID(-1), device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ // push to UI manager
+ machine().ui_input().push_mouse_wheel_event(target(), info->x, info->y, y, 3);
+}
+
+void sdl_window_info::finger_down(SDL_FingerID finger, unsigned device, int x, int y)
+{
+ auto const info(map_pointer(finger, device));
+ if (m_active_pointers.end() == info)
+ return;
+
+ assert(!info->buttons);
+
+ // detect multi-click actions
+ info->primary_down(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ TAP_DISTANCE,
+ true,
+ m_ptrdev_info);
+
+ // update info and push to UI manager
+ info->x = x;
+ info->y = y;
+ info->buttons = 1;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 1, 1, 0, info->clickcnt);
+}
+
+void sdl_window_info::finger_up(SDL_FingerID finger, unsigned device, int x, int y)
+{
+ auto info(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), finger, &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() == info) || (info->finger != finger))
+ return;
+
+ assert(1 == info->buttons);
+
+ // check for conversion to a (multi-)click-and-hold/drag
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ TAP_DISTANCE);
+
+ // need to remember touches to recognise multi-tap gestures
+ if (0 < info->clickcnt)
+ {
+ auto const now(std::chrono::steady_clock::now());
+ auto const time = std::chrono::milliseconds(250);
+ if ((time + info->pressed) >= now)
+ {
+ try
+ {
+ unsigned i(0);
+ if (m_ptrdev_info.size() > device)
+ i = m_ptrdev_info[device].clear_expired_touches(now, time);
+ else
+ m_ptrdev_info.resize(device + 1);
+
+ if (std::size(m_ptrdev_info[device].touches) > i)
+ {
+ m_ptrdev_info[device].touches[i].when = info->pressed;
+ m_ptrdev_info[device].touches[i].x = info->pressedx;
+ m_ptrdev_info[device].touches[i].y = info->pressedy;
+ m_ptrdev_info[device].touches[i].cnt = info->clickcnt;
+ }
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("win_window_info: error allocating pointer data\n");
+ }
+ }
+ }
+
+ // push to UI manager
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 0, 0, 1, info->clickcnt);
+ machine().ui_input().push_pointer_leave(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 0, info->clickcnt);
+
+ // dump pointer data
+ m_pointer_mask &= ~(decltype(m_pointer_mask)(1) << info->index);
+ if (info->index < m_next_pointer)
+ m_next_pointer = info->index;
+ m_active_pointers.erase(info);
+}
+
+void sdl_window_info::finger_moved(SDL_FingerID finger, unsigned device, int x, int y)
+{
+ auto info(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), finger, &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() == info) || (info->finger != finger))
+
+ assert(1 == info->buttons);
+
+ if ((x != info->x) || (y != info->y))
+ {
+ info->check_primary_hold_drag(
+ x,
+ y,
+ std::chrono::milliseconds(250),
+ TAP_DISTANCE);
+
+ // update info and push to UI manager
+ info->x = x;
+ info->y = y;
+ machine().ui_input().push_pointer_update(
+ target(),
+ osd::ui_event_handler::pointer::TOUCH,
+ info->index,
+ device,
+ x, y,
+ 1, 0, 0, info->clickcnt);
+ }
+}
+
//============================================================
// sdlwindow_video_window_create
// (main thread)
@@ -400,31 +600,13 @@ int sdl_window_info::xy_to_render_target(int x, int y, int *xt, int *yt)
int sdl_window_info::window_init()
{
- int result;
-
// set the initial maximized state
// FIXME: Does not belong here
- sdl_options &options = downcast<sdl_options &>(m_machine.options());
- m_startmaximized = options.maximize();
-
- // add us to the list
- osd_common_t::s_window_list.push_back(std::static_pointer_cast<sdl_window_info>(shared_from_this()));
+ m_startmaximized = downcast<sdl_options &>(machine().options()).maximize();
- set_renderer(osd_renderer::make_for_type(video_config.mode, static_cast<osd_window*>(this)->shared_from_this()));
-
- // load the layout
- m_target = m_machine.render().target_alloc();
-
- // set the specific view
- set_starting_view(m_index, options.view(), options.view(m_index));
-
- // make the window title
- if (video_config.numscreens == 1)
- sprintf(m_title, "%s: %s [%s]", emulator_info::get_appname(), m_machine.system().type.fullname(), m_machine.system().name);
- else
- sprintf(m_title, "%s: %s [%s] - Screen %d", emulator_info::get_appname(), m_machine.system().type.fullname(), m_machine.system().name, m_index);
+ create_target();
- result = complete_create();
+ int result = complete_create();
// handle error conditions
if (result == 1)
@@ -450,31 +632,17 @@ void sdl_window_info::complete_destroy()
if (fullscreen() && video_config.switchres)
{
- SDL_SetWindowFullscreen(platform_window(), 0); // Try to set mode
- SDL_SetWindowDisplayMode(platform_window(), &m_original_mode->mode); // Try to set mode
- SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
+ SDL_SetWindowFullscreen(platform_window(), 0);
+ SDL_SetWindowDisplayMode(platform_window(), &m_original_mode);
+ SDL_SetWindowFullscreen(platform_window(), SDL_WINDOW_FULLSCREEN);
}
+ renderer_reset();
SDL_DestroyWindow(platform_window());
- // release all keys ...
+ set_platform_window(nullptr);
downcast<sdl_osd_interface &>(machine().osd()).release_keys();
}
-void sdl_window_info::destroy()
-{
- //osd_event_wait(window->rendered_event, osd_ticks_per_second()*10);
-
- // remove us from the list
- osd_common_t::s_window_list.remove(std::static_pointer_cast<sdl_window_info>(shared_from_this()));
-
- // free the textures etc
- complete_destroy();
-
- // free the render target, after the textures!
- machine().render().target_free(m_target);
-
-}
-
//============================================================
// pick_best_mode
@@ -489,7 +657,7 @@ osd_dim sdl_window_info::pick_best_mode()
osd_dim ret(0,0);
// determine the minimum width/height for the selected target
- m_target->compute_minimum_size(minimum_width, minimum_height);
+ target()->compute_minimum_size(minimum_width, minimum_height);
// use those as the target for now
target_width = minimum_width * std::max(1, prescale());
@@ -502,7 +670,7 @@ osd_dim sdl_window_info::pick_best_mode()
}
// FIXME: this should be provided by monitor !
- num = SDL_GetNumDisplayModes(m_monitor->oshandle());
+ num = SDL_GetNumDisplayModes(monitor()->oshandle());
if (num == 0)
{
@@ -514,7 +682,7 @@ osd_dim sdl_window_info::pick_best_mode()
for (i = 0; i < num; ++i)
{
SDL_DisplayMode mode;
- SDL_GetDisplayMode(m_monitor->oshandle(), i, &mode);
+ SDL_GetDisplayMode(monitor()->oshandle(), i, &mode);
// compute initial score based on difference between target and current
size_score = 1.0f / (1.0f + abs((int32_t)mode.w - target_width) + abs((int32_t)mode.h - target_height));
@@ -556,20 +724,16 @@ osd_dim sdl_window_info::pick_best_mode()
void sdl_window_info::update()
{
- osd_ticks_t event_wait_ticks;
-
// adjust the cursor state
- //sdlwindow_update_cursor_state(machine, window);
-
update_cursor_state();
// if we're visible and running and not in the middle of a resize, draw
- if (m_target != nullptr)
+ if (target() != nullptr)
{
int tempwidth, tempheight;
// see if the games video mode has changed
- m_target->compute_minimum_size(tempwidth, tempheight);
+ target()->compute_minimum_size(tempwidth, tempheight);
if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
{
m_minimum_dim = osd_dim(tempwidth, tempheight);
@@ -586,6 +750,7 @@ void sdl_window_info::update()
}
}
+ osd_ticks_t event_wait_ticks;
if (video_config.waitvsync && video_config.syncrefresh)
event_wait_ticks = osd_ticks_per_second(); // block at most a second
else
@@ -601,13 +766,10 @@ void sdl_window_info::update()
// and redraw now
- // Some configurations require events to be polled in the worker thread
- downcast< sdl_osd_interface& >(machine().osd()).process_events_buf();
-
// Check whether window has vector screens
{
- const screen_device *screen = screen_device_iterator(machine().root_device()).byindex(m_index);
+ const screen_device *screen = screen_device_enumerator(machine().root_device()).byindex(index());
if ((screen != nullptr) && (screen->screen_type() == SCREEN_TYPE_VECTOR))
renderer().set_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
else
@@ -616,20 +778,20 @@ void sdl_window_info::update()
m_primlist = &primlist;
- // if no bitmap, just fill
if (m_primlist == nullptr)
{
+ // if no bitmap, just fill
}
- // otherwise, render with our drawing system
else
{
- if( video_config.perftest )
+ // otherwise, render with our drawing system
+ if (video_config.perftest)
measure_fps(update);
else
renderer().draw(update);
}
- /* all done, ready for next */
+ // all done, ready for next
m_rendered_event.set();
}
}
@@ -637,27 +799,6 @@ void sdl_window_info::update()
//============================================================
-// set_starting_view
-// (main thread)
-//============================================================
-
-void sdl_window_info::set_starting_view(int index, const char *defview, const char *view)
-{
- int viewindex;
-
- // choose non-auto over auto
- if (strcmp(view, "auto") == 0 && strcmp(defview, "auto") != 0)
- view = defview;
-
- // query the video system to help us pick a view
- viewindex = target()->configured_view(view, index, video_config.numscreens);
-
- // set the view
- target()->set_view(viewindex);
-}
-
-
-//============================================================
// complete_create
//============================================================
@@ -681,9 +822,13 @@ int sdl_window_info::complete_create()
temp = m_windowed_dim;
}
else if (m_startmaximized)
- temp = get_max_bounds(video_config.keepaspect );
+ {
+ temp = get_max_bounds(keepaspect());
+ }
else
- temp = get_min_bounds(video_config.keepaspect );
+ {
+ temp = get_min_bounds(keepaspect());
+ }
// create the window .....
@@ -694,50 +839,20 @@ int sdl_window_info::complete_create()
*
*/
osd_printf_verbose("Enter sdl_info::create\n");
- if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL) && !video_config.novideo)
+ if (renderer_sdl_needs_opengl())
{
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
-
- /* FIXME: A reminder that gamma is wrong throughout MAME. Currently, SDL2.0 doesn't seem to
- * support the following attribute although my hardware lists GL_ARB_framebuffer_sRGB as an extension.
- *
- * SDL_GL_SetAttribute( SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1 );
- *
- */
m_extra_flags = SDL_WINDOW_OPENGL;
}
else
- m_extra_flags = 0;
-
-#ifdef SDLMAME_MACOSX
- /* FIMXE: On OSX, SDL_WINDOW_FULLSCREEN_DESKTOP seems to be more reliable.
- * It however creates issues with white borders, i.e. the screen clear
- * does not work. This happens both with opengl and accel.
- */
-#endif
-
- // We need to workaround an issue in SDL 2.0.4 for OS X where setting the
- // relative mode on the mouse in fullscreen mode makes mouse events stop
- // It is fixed in the latest revisions so we'll assume it'll be fixed
- // in the next public SDL release as well
-#if defined(SDLMAME_MACOSX) && SDL_VERSION_ATLEAST(2, 0, 2) // SDL_HINT_MOUSE_RELATIVE_MODE_WARP is introduced in 2.0.2
- SDL_version linked;
- SDL_GetVersion(&linked);
- int revision = SDL_GetRevisionNumber();
-
- // If we're running the exact version of SDL 2.0.4 (revision 10001) from the
- // SDL web site, we need to work around this issue and send the warp mode hint
- if (SDL_VERSION_EQUALS(linked, SDL_VERSIONNUM(2, 0, 4)) && revision == 10001)
{
- osd_printf_verbose("Using warp mode for relative mouse in OS X SDL 2.0.4\n");
- SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
+ m_extra_flags = 0;
}
-#endif
// create the SDL window
// soft driver also used | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_MOUSE_FOCUS
m_extra_flags |= (fullscreen() ?
- SDL_WINDOW_BORDERLESS | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE);
+ SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE);
#if defined(SDLMAME_WIN32)
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
@@ -746,17 +861,74 @@ int sdl_window_info::complete_create()
// get monitor work area for centering
osd_rect work = monitor()->usuable_position_size();
- // create the SDL window
- auto sdlwindow = SDL_CreateWindow(m_title,
+ // create or attach to an existing window
+ SDL_Window *sdlwindow;
+#ifdef SDLMAME_X11
+ const char *attach_window = downcast<sdl_options &>(machine().options()).attach_window();
+#else
+ const char *attach_window = nullptr;
+#endif
+ if (attach_window && *attach_window)
+ {
+ // we're attaching to an existing window; parse the argument
+ unsigned long long attach_window_value;
+ try
+ {
+ attach_window_value = std::stoull(attach_window, nullptr, 0);
+ }
+ catch (std::invalid_argument &)
+ {
+ osd_printf_error("Invalid -attach_window value: %s\n", attach_window);
+ return 1;
+ }
+
+ // and attach to it
+ sdlwindow = SDL_CreateWindowFrom((void *)attach_window_value);
+ if (!sdlwindow)
+ {
+ osd_printf_error("Failed to attach to window \"%s\": %s\n", attach_window, SDL_GetError());
+ return 1;
+ }
+
+ // perform SDL subsystem-specific tasks
+ SDL_SysWMinfo swmi;
+ SDL_VERSION(&swmi.version);
+ if (SDL_GetWindowWMInfo(sdlwindow, &swmi))
+ {
+ switch (swmi.subsystem)
+ {
+#ifdef SDLMAME_X11
+ case SDL_SYSWM_X11:
+ // by default, SDL_CreateWindowFrom() doesn't ensure that we're getting the events that we
+ // expect
+ XSelectInput(swmi.info.x11.display, swmi.info.x11.window,
+ FocusChangeMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask | KeyPressMask | KeyReleaseMask |
+ PropertyChangeMask | StructureNotifyMask |
+ ExposureMask | KeymapStateMask);
+ break;
+#endif // SDLMAME_X11
+
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ // create the SDL window
+ sdlwindow = SDL_CreateWindow(title().c_str(),
work.left() + (work.width() - temp.width()) / 2,
work.top() + (work.height() - temp.height()) / 2,
temp.width(), temp.height(), m_extra_flags);
+ }
+
//window().sdl_window() = SDL_CreateWindow(window().m_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
// width, height, m_extra_flags);
if (sdlwindow == nullptr )
{
- if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL))
+ if (renderer_sdl_needs_opengl())
osd_printf_error("OpenGL not supported on this driver: %s\n", SDL_GetError());
else
osd_printf_error("Window creation failed: %s\n", SDL_GetError());
@@ -764,13 +936,14 @@ int sdl_window_info::complete_create()
}
set_platform_window(sdlwindow);
+ renderer_create();
if (fullscreen() && video_config.switchres)
{
SDL_DisplayMode mode;
//SDL_GetCurrentDisplayMode(window().monitor()->handle, &mode);
SDL_GetWindowDisplayMode(platform_window(), &mode);
- m_original_mode->mode = mode;
+ m_original_mode = mode;
mode.w = temp.width();
mode.h = temp.height();
if (m_win_config.refresh)
@@ -802,24 +975,6 @@ int sdl_window_info::complete_create()
SDL_SetWindowGrab(platform_window(), SDL_TRUE);
#endif
- // set main window
- if (m_index > 0)
- {
- for (auto w : osd_common_t::s_window_list)
- {
- if (w->m_index == 0)
- {
- set_main_window(std::dynamic_pointer_cast<osd_window>(w));
- break;
- }
- }
- }
- else
- {
- // We must be the main window
- set_main_window(shared_from_this());
- }
-
// update monitor resolution after mode change to ensure proper pixel aspect
monitor()->refresh();
if (fullscreen() && video_config.switchres)
@@ -830,8 +985,8 @@ int sdl_window_info::complete_create()
return 1;
// Make sure we have a consistent state
- SDL_ShowCursor(0);
- SDL_ShowCursor(1);
+ SDL_ShowCursor(SDL_DISABLE);
+ SDL_ShowCursor(SDL_ENABLE);
return 0;
}
@@ -910,14 +1065,9 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad
int32_t viswidth, visheight;
int32_t adjwidth, adjheight;
float pixel_aspect;
- std::shared_ptr<osd_monitor_info> monitor = m_monitor;
-
- // do not constrain aspect ratio for integer scaled views
- if (m_target->scale_mode() != SCALE_FRACTIONAL)
- return rect;
// get the pixel aspect ratio for the target monitor
- pixel_aspect = monitor->pixel_aspect();
+ pixel_aspect = monitor()->pixel_aspect();
// determine the proposed width/height
propwidth = rect.width() - extrawidth;
@@ -929,21 +1079,21 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad
{
case WMSZ_BOTTOM:
case WMSZ_TOP:
- m_target->compute_visible_area(10000, propheight, pixel_aspect, m_target->orientation(), propwidth, propheight);
+ target()->compute_visible_area(10000, propheight, pixel_aspect, target()->orientation(), propwidth, propheight);
break;
case WMSZ_LEFT:
case WMSZ_RIGHT:
- m_target->compute_visible_area(propwidth, 10000, pixel_aspect, m_target->orientation(), propwidth, propheight);
+ target()->compute_visible_area(propwidth, 10000, pixel_aspect, target()->orientation(), propwidth, propheight);
break;
default:
- m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), propwidth, propheight);
+ target()->compute_visible_area(propwidth, propheight, pixel_aspect, target()->orientation(), propwidth, propheight);
break;
}
// get the minimum width/height for the current layout
- m_target->compute_minimum_size(minwidth, minheight);
+ target()->compute_minimum_size(minwidth, minheight);
// clamp against the absolute minimum
propwidth = std::max(propwidth, MIN_WINDOW_DIM);
@@ -956,13 +1106,13 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad
// clamp against the maximum (fit on one screen for full screen mode)
if (m_fullscreen)
{
- maxwidth = monitor->position_size().width() - extrawidth;
- maxheight = monitor->position_size().height() - extraheight;
+ maxwidth = monitor()->position_size().width() - extrawidth;
+ maxheight = monitor()->position_size().height() - extraheight;
}
else
{
- maxwidth = monitor->usuable_position_size().width() - extrawidth;
- maxheight = monitor->usuable_position_size().height() - extraheight;
+ maxwidth = monitor()->usuable_position_size().width() - extrawidth;
+ maxheight = monitor()->usuable_position_size().height() - extraheight;
// further clamp to the maximum width/height in the window
if (m_win_config.width != 0)
@@ -976,7 +1126,11 @@ osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int ad
propheight = std::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);
+ target()->compute_visible_area(propwidth, propheight, pixel_aspect, target()->orientation(), viswidth, visheight);
+
+ // clamp visable area to the proposed rectangle
+ viswidth = std::min(viswidth, propwidth);
+ visheight = std::min(visheight, propheight);
// compute the adjustments we need to make
adjwidth = (viswidth + extrawidth) - rect.width();
@@ -1024,7 +1178,13 @@ osd_dim sdl_window_info::get_min_bounds(int constrain)
//assert(GetCurrentThreadId() == window_threadid);
// get the minimum target size
- m_target->compute_minimum_size(minwidth, minheight);
+ target()->compute_minimum_size(minwidth, minheight);
+
+ // check if visible area is bigger
+ int32_t viswidth, visheight;
+ target()->compute_visible_area(minwidth, minheight, monitor()->aspect(), target()->orientation(), viswidth, visheight);
+ minwidth = std::max(viswidth, minwidth);
+ minheight = std::max(visheight, minheight);
// expand to our minimum dimensions
if (minwidth < MIN_WINDOW_DIM)
@@ -1037,7 +1197,7 @@ osd_dim sdl_window_info::get_min_bounds(int constrain)
minheight += wnd_extra_height();
// if we want it constrained, figure out which one is larger
- if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL)
+ if (constrain)
{
// first constrain with no height limit
osd_rect test1(0,0,minwidth,10000);
@@ -1089,8 +1249,8 @@ osd_dim sdl_window_info::get_max_bounds(int constrain)
//assert(GetCurrentThreadId() == window_threadid);
// compute the maximum client area
- // m_monitor->refresh();
- osd_rect maximum = m_monitor->usuable_position_size();
+ // monitor()->refresh();
+ osd_rect maximum = monitor()->usuable_position_size();
// clamp to the window's max
int tempw = maximum.width();
@@ -1111,7 +1271,7 @@ osd_dim sdl_window_info::get_max_bounds(int constrain)
maximum = maximum.resize(tempw, temph);
// constrain to fit
- if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL)
+ if (constrain)
maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT);
// remove extra window stuff
@@ -1120,43 +1280,87 @@ osd_dim sdl_window_info::get_max_bounds(int constrain)
return maximum.dim();
}
+
+std::vector<sdl_window_info::sdl_pointer_info>::iterator sdl_window_info::map_pointer(SDL_FingerID finger, unsigned device)
+{
+ auto found(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), finger, &sdl_pointer_info::compare));
+ if ((m_active_pointers.end() != found) && (found->finger == finger))
+ return found;
+
+ if ((sizeof(m_next_pointer) * 8) <= m_next_pointer)
+ {
+ assert(~decltype(m_pointer_mask)(0) == m_pointer_mask);
+ osd_printf_warning("sdl_window_info: exceeded maximum number of active pointers\n");
+ return m_active_pointers.end();
+ }
+ assert(!BIT(m_pointer_mask, m_next_pointer));
+
+ try
+ {
+ found = m_active_pointers.emplace(
+ found,
+ sdl_pointer_info(finger, m_next_pointer, device));
+ m_pointer_mask |= decltype(m_pointer_mask)(1) << m_next_pointer;
+ do
+ {
+ ++m_next_pointer;
+ }
+ while (((sizeof(m_next_pointer) * 8) > m_next_pointer) && BIT(m_pointer_mask, m_next_pointer));
+
+ return found;
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_window_info: error allocating pointer data\n");
+ return m_active_pointers.end();
+ }
+}
+
+
+inline sdl_window_info::sdl_pointer_info::sdl_pointer_info(SDL_FingerID f, unsigned i, unsigned d)
+ : pointer_info(i, d)
+ , finger(f)
+{
+}
+
+
+
+
//============================================================
// construction and destruction
//============================================================
sdl_window_info::sdl_window_info(
running_machine &a_machine,
+ render_module &renderprovider,
int index,
- std::shared_ptr<osd_monitor_info> a_monitor,
+ const std::shared_ptr<osd_monitor_info> &a_monitor,
const osd_window_config *config)
- : osd_window_t(*config)
- , m_next(nullptr)
+ : osd_window_t(a_machine, renderprovider, index, std::move(a_monitor), *config)
, m_startmaximized(0)
// Following three are used by input code to defer resizes
, m_minimum_dim(0, 0)
, m_windowed_dim(0, 0)
, m_rendered_event(0, 1)
- , m_target(nullptr)
, m_extra_flags(0)
- , m_machine(a_machine)
- , m_monitor(a_monitor)
- , m_fullscreen(0)
, m_mouse_captured(false)
, m_mouse_hidden(false)
+ , m_pointer_mask(0)
+ , m_next_pointer(0)
+ , m_mouse_inside(false)
{
- m_index = index;
-
//FIXME: these should be per_window in config-> or even better a bit set
m_fullscreen = !video_config.windowed;
m_prescale = video_config.prescale;
m_windowed_dim = osd_dim(config->width, config->height);
- m_original_mode = global_alloc(SDL_DM_Wrapper);
+
+ m_ptrdev_info.reserve(1);
+ m_active_pointers.reserve(16);
}
sdl_window_info::~sdl_window_info()
{
- global_free(m_original_mode);
}