diff options
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r-- | platform/linuxbsd/crash_handler_linuxbsd.cpp | 22 | ||||
-rw-r--r-- | platform/linuxbsd/detect_prime_x11.cpp | 2 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 64 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.h | 56 | ||||
-rw-r--r-- | platform/linuxbsd/export/export_plugin.h | 2 | ||||
-rw-r--r-- | platform/linuxbsd/joypad_linux.cpp | 336 | ||||
-rw-r--r-- | platform/linuxbsd/joypad_linux.h | 41 | ||||
-rw-r--r-- | platform/linuxbsd/tts_linux.h | 4 |
8 files changed, 265 insertions, 262 deletions
diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp index b4ec7924f6..33da094860 100644 --- a/platform/linuxbsd/crash_handler_linuxbsd.cpp +++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/os/os.h" +#include "core/string/print_string.h" #include "core/version.h" #include "main/main.h" @@ -61,21 +62,22 @@ static void handle_crash(int sig) { msg = proj_settings->get("debug/settings/crash_handler/message"); } - // Dump the backtrace to stderr with a message to the user - fprintf(stderr, "\n================================================================\n"); - fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); - + // Tell MainLoop about the crash. This can be handled by users too in Node. if (OS::get_singleton()->get_main_loop()) { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH); } + // Dump the backtrace to stderr with a message to the user + print_error("\n================================================================"); + print_error(vformat("%s: Program crashed with signal %d", __FUNCTION__, sig)); + // Print the engine version just before, so that people are reminded to include the version in backtrace reports. if (String(VERSION_HASH).is_empty()) { - fprintf(stderr, "Engine version: %s\n", VERSION_FULL_NAME); + print_error(vformat("Engine version: %s", VERSION_FULL_NAME)); } else { - fprintf(stderr, "Engine version: %s (%s)\n", VERSION_FULL_NAME, VERSION_HASH); + print_error(vformat("Engine version: %s (%s)", VERSION_FULL_NAME, VERSION_HASH)); } - fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data()); + print_error(vformat("Dumping the backtrace. %s", msg)); char **strings = backtrace_symbols(bt_buffer, size); if (strings) { for (size_t i = 1; i < size; i++) { @@ -117,13 +119,13 @@ static void handle_crash(int sig) { output = output.substr(0, output.length() - 1); } - fprintf(stderr, "[%ld] %s (%s)\n", (long int)i, fname, output.utf8().get_data()); + print_error(vformat("[%d] %s (%s)", (int64_t)i, fname, output)); } free(strings); } - fprintf(stderr, "-- END OF BACKTRACE --\n"); - fprintf(stderr, "================================================================\n"); + print_error("-- END OF BACKTRACE --"); + print_error("================================================================"); // Abort to pass the error to the OS abort(); diff --git a/platform/linuxbsd/detect_prime_x11.cpp b/platform/linuxbsd/detect_prime_x11.cpp index 63531d33fa..42b7f68a5e 100644 --- a/platform/linuxbsd/detect_prime_x11.cpp +++ b/platform/linuxbsd/detect_prime_x11.cpp @@ -55,7 +55,7 @@ typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *); struct vendor { - const char *glxvendor; + const char *glxvendor = nullptr; int priority = 0; }; diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 027f8562eb..5829711698 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -2356,14 +2356,14 @@ DisplayServerX11::CursorShape DisplayServerX11::cursor_get_shape() const { return current_cursor; } -void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { _THREAD_SAFE_METHOD_ if (p_cursor.is_valid()) { - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape); if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + if (cursor_c->value[0] == p_cursor && cursor_c->value[1] == p_hotspot) { cursor_set_shape(p_shape); return; } @@ -3456,9 +3456,9 @@ void DisplayServerX11::process_events() { } if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_PRESSURE)) { - Map<int, Vector2>::Element *pen_pressure = xi.pen_pressure_range.find(device_id); + HashMap<int, Vector2>::Iterator pen_pressure = xi.pen_pressure_range.find(device_id); if (pen_pressure) { - Vector2 pen_pressure_range = pen_pressure->value(); + Vector2 pen_pressure_range = pen_pressure->value; if (pen_pressure_range != Vector2()) { xi.pressure_supported = true; xi.pressure = (*values - pen_pressure_range[0]) / @@ -3470,9 +3470,9 @@ void DisplayServerX11::process_events() { } if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTX)) { - Map<int, Vector2>::Element *pen_tilt_x = xi.pen_tilt_x_range.find(device_id); + HashMap<int, Vector2>::Iterator pen_tilt_x = xi.pen_tilt_x_range.find(device_id); if (pen_tilt_x) { - Vector2 pen_tilt_x_range = pen_tilt_x->value(); + Vector2 pen_tilt_x_range = pen_tilt_x->value; if (pen_tilt_x_range[0] != 0 && *values < 0) { xi.tilt.x = *values / -pen_tilt_x_range[0]; } else if (pen_tilt_x_range[1] != 0) { @@ -3484,9 +3484,9 @@ void DisplayServerX11::process_events() { } if (XIMaskIsSet(raw_event->valuators.mask, VALUATOR_TILTY)) { - Map<int, Vector2>::Element *pen_tilt_y = xi.pen_tilt_y_range.find(device_id); + HashMap<int, Vector2>::Iterator pen_tilt_y = xi.pen_tilt_y_range.find(device_id); if (pen_tilt_y) { - Vector2 pen_tilt_y_range = pen_tilt_y->value(); + Vector2 pen_tilt_y_range = pen_tilt_y->value; if (pen_tilt_y_range[0] != 0 && *values < 0) { xi.tilt.y = *values / -pen_tilt_y_range[0]; } else if (pen_tilt_y_range[1] != 0) { @@ -3508,11 +3508,11 @@ void DisplayServerX11::process_events() { xi.raw_pos.x = rel_x; xi.raw_pos.y = rel_y; - Map<int, Vector2>::Element *abs_info = xi.absolute_devices.find(device_id); + HashMap<int, Vector2>::Iterator abs_info = xi.absolute_devices.find(device_id); if (abs_info) { // Absolute mode device - Vector2 mult = abs_info->value(); + Vector2 mult = abs_info->value; xi.relative_motion.x += (xi.raw_pos.x - xi.old_raw_pos.x) * mult.x; xi.relative_motion.y += (xi.raw_pos.y - xi.old_raw_pos.y) * mult.y; @@ -3557,21 +3557,21 @@ void DisplayServerX11::process_events() { } break; case XI_TouchUpdate: { - Map<int, Vector2>::Element *curr_pos_elem = xi.state.find(index); + HashMap<int, Vector2>::Iterator curr_pos_elem = xi.state.find(index); if (!curr_pos_elem) { // Defensive break; } - if (curr_pos_elem->value() != pos) { + if (curr_pos_elem->value != pos) { Ref<InputEventScreenDrag> sd; sd.instantiate(); sd->set_window_id(window_id); sd->set_index(index); sd->set_position(pos); - sd->set_relative(pos - curr_pos_elem->value()); + sd->set_relative(pos - curr_pos_elem->value); Input::get_singleton()->parse_input_event(sd); - curr_pos_elem->value() = pos; + curr_pos_elem->value = pos; } } break; #endif @@ -4112,13 +4112,13 @@ void DisplayServerX11::process_events() { void DisplayServerX11::release_rendering_thread() { #if defined(GLES3_ENABLED) -// gl_manager->release_current(); + gl_manager->release_current(); #endif } void DisplayServerX11::make_rendering_thread() { #if defined(GLES3_ENABLED) -// gl_manager->make_current(); + gl_manager->make_current(); #endif } @@ -4531,24 +4531,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode r_error = OK; - current_cursor = CURSOR_ARROW; - mouse_mode = MOUSE_MODE_VISIBLE; - for (int i = 0; i < CURSOR_MAX; i++) { cursors[i] = None; img[i] = nullptr; } - xmbstring = nullptr; - - last_click_ms = 0; - last_click_button_index = MouseButton::NONE; - last_click_pos = Point2i(-100, -100); - - last_timestamp = 0; - last_mouse_pos_valid = false; - last_keyrelease_time = 0; - XInitThreads(); //always use threads /** XLIB INITIALIZATION **/ @@ -4583,8 +4570,6 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } const char *err; - xrr_get_monitors = nullptr; - xrr_free_monitors = nullptr; int xrandr_major = 0; int xrandr_minor = 0; int event_base, error_base; @@ -4660,11 +4645,10 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode XFree(imvalret); } - /* Atorm internment */ + /* Atom internment */ wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); - //Set Xdnd (drag & drop) support + // Set Xdnd (drag & drop) support. xdnd_aware = XInternAtom(x11_display, "XdndAware", False); - xdnd_version = 5; xdnd_enter = XInternAtom(x11_display, "XdndEnter", False); xdnd_position = XInternAtom(x11_display, "XdndPosition", False); xdnd_status = XInternAtom(x11_display, "XdndStatus", False); @@ -4751,11 +4735,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } driver_found = true; - // gl_manager->set_use_vsync(current_videomode.use_vsync); - if (true) { - // if (RasterizerGLES3::is_viable() == OK) { - // RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); } else { memdelete(gl_manager); @@ -4930,12 +4910,6 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } cursor_set_shape(CURSOR_BUSY); - requested = None; - - /*if (p_desired.layered) { - set_window_per_pixel_transparency_enabled(true); - }*/ - XEvent xevent; while (XPending(x11_display) > 0) { XNextEvent(x11_display, &xevent); diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 3d49886b94..66941fbe29 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -100,8 +100,8 @@ class DisplayServerX11 : public DisplayServer { Atom xdnd_finished; Atom xdnd_selection; Atom xdnd_aware; - Atom requested; - int xdnd_version; + Atom requested = None; + int xdnd_version = 5; #if defined(GLES3_ENABLED) GLManager_X11 *gl_manager = nullptr; @@ -137,7 +137,7 @@ class DisplayServerX11 : public DisplayServer { Callable drop_files_callback; WindowID transient_parent = INVALID_WINDOW_ID; - Set<WindowID> transient_children; + RBSet<WindowID> transient_children; ObjectID instance_id; @@ -159,7 +159,7 @@ class DisplayServerX11 : public DisplayServer { unsigned int focus_order = 0; }; - Map<WindowID, WindowData> windows; + HashMap<WindowID, WindowData> windows; unsigned int last_mouse_monitor_mask = 0; Vector2i last_mouse_monitor_pos; @@ -174,21 +174,21 @@ class DisplayServerX11 : public DisplayServer { String internal_clipboard; String internal_clipboard_primary; - Window xdnd_source_window; + Window xdnd_source_window = 0; ::Display *x11_display; char *xmbstring = nullptr; - int xmblen; - unsigned long last_timestamp; - ::Time last_keyrelease_time; + int xmblen = 0; + unsigned long last_timestamp = 0; + ::Time last_keyrelease_time = 0; ::XIM xim; ::XIMStyle xim_style; static void _xim_destroy_callback(::XIM im, ::XPointer client_data, ::XPointer call_data); Point2i last_mouse_pos; - bool last_mouse_pos_valid; - Point2i last_click_pos; - uint64_t last_click_ms; + bool last_mouse_pos_valid = false; + Point2i last_click_pos = Point2i(-100, -100); + uint64_t last_click_ms = 0; MouseButton last_click_button_index = MouseButton::NONE; MouseButton last_button_state = MouseButton::NONE; bool app_focused = false; @@ -197,12 +197,12 @@ class DisplayServerX11 : public DisplayServer { struct { int opcode; Vector<int> touch_devices; - Map<int, Vector2> absolute_devices; - Map<int, Vector2> pen_pressure_range; - Map<int, Vector2> pen_tilt_x_range; - Map<int, Vector2> pen_tilt_y_range; + HashMap<int, Vector2> absolute_devices; + HashMap<int, Vector2> pen_pressure_range; + HashMap<int, Vector2> pen_tilt_x_range; + HashMap<int, Vector2> pen_tilt_y_range; XIEventMask all_event_mask; - Map<int, Vector2> state; + HashMap<int, Vector2> state; double pressure; bool pressure_supported; Vector2 tilt; @@ -221,7 +221,7 @@ class DisplayServerX11 : public DisplayServer { void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state); void _flush_mouse_motion(); - MouseMode mouse_mode; + MouseMode mouse_mode = MOUSE_MODE_VISIBLE; Point2i center; void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo = false); @@ -233,30 +233,26 @@ class DisplayServerX11 : public DisplayServer { String _clipboard_get(Atom p_source, Window x11_window) const; void _clipboard_transfer_ownership(Atom p_source, Window x11_window) const; - //bool minimized; - //bool window_has_focus; - bool do_mouse_warp; + bool do_mouse_warp = false; - const char *cursor_theme; - int cursor_size; + const char *cursor_theme = nullptr; + int cursor_size = 0; XcursorImage *img[CURSOR_MAX]; Cursor cursors[CURSOR_MAX]; Cursor null_cursor; - CursorShape current_cursor; - Map<CursorShape, Vector<Variant>> cursors_cache; + CursorShape current_cursor = CURSOR_ARROW; + HashMap<CursorShape, Vector<Variant>> cursors_cache; - bool layered_window; + bool layered_window = false; String rendering_driver; - //bool window_focused; - //void set_wm_border(bool p_enabled); void set_wm_fullscreen(bool p_enabled); void set_wm_above(bool p_enabled); typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors); typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors); - xrr_get_monitors_t xrr_get_monitors; - xrr_free_monitors_t xrr_free_monitors; + xrr_get_monitors_t xrr_get_monitors = nullptr; + xrr_free_monitors_t xrr_free_monitors = nullptr; void *xrandr_handle = nullptr; Bool xrandr_ext_ok; @@ -411,7 +407,7 @@ public: virtual void cursor_set_shape(CursorShape p_shape) override; virtual CursorShape cursor_get_shape() const override; - virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override; + virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override; virtual int keyboard_get_layout_count() const override; virtual int keyboard_get_current_layout() const override; diff --git a/platform/linuxbsd/export/export_plugin.h b/platform/linuxbsd/export/export_plugin.h index f46fc68e1d..9ae5cf827a 100644 --- a/platform/linuxbsd/export/export_plugin.h +++ b/platform/linuxbsd/export/export_plugin.h @@ -38,7 +38,7 @@ #include "scene/resources/texture.h" class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC { - Map<String, String> extensions; + HashMap<String, String> extensions; Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); public: diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 22a9518a25..bc018e366b 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -65,6 +65,7 @@ void JoypadLinux::Joypad::reset() { abs_map[i] = -1; curr_axis[i] = 0; } + events.clear(); } JoypadLinux::JoypadLinux(Input *in) { @@ -84,23 +85,26 @@ JoypadLinux::JoypadLinux(Input *in) { print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads."); #endif input = in; - joy_thread.start(joy_thread_func, this); + monitor_joypads_thread.start(monitor_joypads_thread_func, this); + joypad_events_thread.start(joypad_events_thread_func, this); } JoypadLinux::~JoypadLinux() { - exit_monitor.set(); - joy_thread.wait_to_finish(); - close_joypad(); + monitor_joypads_exit.set(); + joypad_events_exit.set(); + monitor_joypads_thread.wait_to_finish(); + joypad_events_thread.wait_to_finish(); + close_joypads(); } -void JoypadLinux::joy_thread_func(void *p_user) { +void JoypadLinux::monitor_joypads_thread_func(void *p_user) { if (p_user) { JoypadLinux *joy = static_cast<JoypadLinux *>(p_user); - joy->run_joypad_thread(); + joy->monitor_joypads_thread_run(); } } -void JoypadLinux::run_joypad_thread() { +void JoypadLinux::monitor_joypads_thread_run() { #ifdef UDEV_ENABLED if (use_udev) { udev *_udev = udev_new(); @@ -140,7 +144,6 @@ void JoypadLinux::enumerate_joypads(udev *p_udev) { if (devnode) { String devnode_str = devnode; if (devnode_str.find(ignore_str) == -1) { - MutexLock lock(joy_mutex); open_joypad(devnode); } } @@ -156,7 +159,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { udev_monitor_enable_receiving(mon); int fd = udev_monitor_get_fd(mon); - while (!exit_monitor.is_set()) { + while (!monitor_joypads_exit.is_set()) { fd_set fds; struct timeval tv; int ret; @@ -175,7 +178,6 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { dev = udev_monitor_receive_device(mon); if (dev && udev_device_get_devnode(dev) != nullptr) { - MutexLock lock(joy_mutex); String action = udev_device_get_action(dev); const char *devnode = udev_device_get_devnode(dev); if (devnode) { @@ -184,11 +186,10 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { if (action == "add") { open_joypad(devnode); } else if (String(action) == "remove") { - close_joypad(get_joy_from_path(devnode)); + close_joypad(devnode); } } } - udev_device_unref(dev); } } @@ -199,59 +200,54 @@ void JoypadLinux::monitor_joypads(udev *p_udev) { #endif void JoypadLinux::monitor_joypads() { - while (!exit_monitor.is_set()) { - { - MutexLock lock(joy_mutex); - - DIR *input_directory; - input_directory = opendir("/dev/input"); - if (input_directory) { - struct dirent *current; - char fname[64]; - - while ((current = readdir(input_directory)) != nullptr) { - if (strncmp(current->d_name, "event", 5) != 0) { - continue; - } - sprintf(fname, "/dev/input/%.*s", 16, current->d_name); - if (attached_devices.find(fname) == -1) { - open_joypad(fname); - } + while (!monitor_joypads_exit.is_set()) { + DIR *input_directory; + input_directory = opendir("/dev/input"); + if (input_directory) { + struct dirent *current; + char fname[64]; + + while ((current = readdir(input_directory)) != nullptr) { + if (strncmp(current->d_name, "event", 5) != 0) { + continue; + } + sprintf(fname, "/dev/input/%.*s", 16, current->d_name); + if (attached_devices.find(fname) == -1) { + open_joypad(fname); } } - closedir(input_directory); } - usleep(1000000); // 1s + closedir(input_directory); } + usleep(1000000); // 1s } -int JoypadLinux::get_joy_from_path(String p_path) const { +void JoypadLinux::close_joypads() { for (int i = 0; i < JOYPADS_MAX; i++) { - if (joypads[i].devpath == p_path) { - return i; - } + MutexLock lock(joypads_mutex[i]); + Joypad &joypad = joypads[i]; + close_joypad(joypad, i); } - return -2; } -void JoypadLinux::close_joypad(int p_id) { - if (p_id == -1) { - for (int i = 0; i < JOYPADS_MAX; i++) { - close_joypad(i); +void JoypadLinux::close_joypad(const char *p_devpath) { + for (int i = 0; i < JOYPADS_MAX; i++) { + MutexLock lock(joypads_mutex[i]); + Joypad &joypad = joypads[i]; + if (joypads[i].devpath == p_devpath) { + close_joypad(joypad, i); } - return; - } else if (p_id < 0) { - return; } +} - Joypad &joy = joypads[p_id]; - - if (joy.fd != -1) { - close(joy.fd); - joy.fd = -1; - attached_devices.remove_at(attached_devices.find(joy.devpath)); +void JoypadLinux::close_joypad(Joypad &p_joypad, int p_id) { + if (p_joypad.fd != -1) { + close(p_joypad.fd); + p_joypad.fd = -1; + attached_devices.erase(p_joypad.devpath); input->joy_connection_changed(p_id, false, ""); } + p_joypad.events.clear(); } static String _hex_str(uint8_t p_byte) { @@ -265,27 +261,25 @@ static String _hex_str(uint8_t p_byte) { return ret; } -void JoypadLinux::setup_joypad_properties(int p_id) { - Joypad *joy = &joypads[p_id]; - +void JoypadLinux::setup_joypad_properties(Joypad &p_joypad) { unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; int num_buttons = 0; int num_axes = 0; - if ((ioctl(joy->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || - (ioctl(joy->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) { + if ((ioctl(p_joypad.fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || + (ioctl(p_joypad.fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) { return; } for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) { if (test_bit(i, keybit)) { - joy->key_map[i] = num_buttons++; + p_joypad.key_map[i] = num_buttons++; } } for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) { if (test_bit(i, keybit)) { - joy->key_map[i] = num_buttons++; + p_joypad.key_map[i] = num_buttons++; } } for (int i = 0; i < ABS_MISC; ++i) { @@ -295,21 +289,21 @@ void JoypadLinux::setup_joypad_properties(int p_id) { continue; } if (test_bit(i, absbit)) { - joy->abs_map[i] = num_axes++; - joy->abs_info[i] = memnew(input_absinfo); - if (ioctl(joy->fd, EVIOCGABS(i), joy->abs_info[i]) < 0) { - memdelete(joy->abs_info[i]); - joy->abs_info[i] = nullptr; + p_joypad.abs_map[i] = num_axes++; + p_joypad.abs_info[i] = memnew(input_absinfo); + if (ioctl(p_joypad.fd, EVIOCGABS(i), p_joypad.abs_info[i]) < 0) { + memdelete(p_joypad.abs_info[i]); + p_joypad.abs_info[i] = nullptr; } } } - joy->force_feedback = false; - joy->ff_effect_timestamp = 0; + p_joypad.force_feedback = false; + p_joypad.ff_effect_timestamp = 0; unsigned long ffbit[NBITS(FF_CNT)]; - if (ioctl(joy->fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) != -1) { + if (ioctl(p_joypad.fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) != -1) { if (test_bit(FF_RUMBLE, ffbit)) { - joy->force_feedback = true; + p_joypad.force_feedback = true; } } } @@ -353,12 +347,12 @@ void JoypadLinux::open_joypad(const char *p_path) { return; } - joypads[joy_num].reset(); - - Joypad &joy = joypads[joy_num]; - joy.fd = fd; - joy.devpath = String(p_path); - setup_joypad_properties(joy_num); + MutexLock lock(joypads_mutex[joy_num]); + Joypad &joypad = joypads[joy_num]; + joypad.reset(); + joypad.fd = fd; + joypad.devpath = String(p_path); + setup_joypad_properties(joypad); sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0); if (inpid.vendor && inpid.product && inpid.version) { uint16_t vendor = BSWAP16(inpid.vendor); @@ -379,13 +373,12 @@ void JoypadLinux::open_joypad(const char *p_path) { } } -void JoypadLinux::joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) { - Joypad &joy = joypads[p_id]; - if (!joy.force_feedback || joy.fd == -1 || p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { +void JoypadLinux::joypad_vibration_start(Joypad &p_joypad, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) { + if (!p_joypad.force_feedback || p_joypad.fd == -1 || p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { return; } - if (joy.ff_effect_id != -1) { - joypad_vibration_stop(p_id, p_timestamp); + if (p_joypad.ff_effect_id != -1) { + joypad_vibration_stop(p_joypad, p_timestamp); } struct ff_effect effect; @@ -396,7 +389,7 @@ void JoypadLinux::joypad_vibration_start(int p_id, float p_weak_magnitude, float effect.replay.length = floor(p_duration * 1000); effect.replay.delay = 0; - if (ioctl(joy.fd, EVIOCSFF, &effect) < 0) { + if (ioctl(p_joypad.fd, EVIOCSFF, &effect) < 0) { return; } @@ -404,26 +397,25 @@ void JoypadLinux::joypad_vibration_start(int p_id, float p_weak_magnitude, float play.type = EV_FF; play.code = effect.id; play.value = 1; - if (write(joy.fd, (const void *)&play, sizeof(play)) == -1) { + if (write(p_joypad.fd, (const void *)&play, sizeof(play)) == -1) { print_verbose("Couldn't write to Joypad device."); } - joy.ff_effect_id = effect.id; - joy.ff_effect_timestamp = p_timestamp; + p_joypad.ff_effect_id = effect.id; + p_joypad.ff_effect_timestamp = p_timestamp; } -void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) { - Joypad &joy = joypads[p_id]; - if (!joy.force_feedback || joy.fd == -1 || joy.ff_effect_id == -1) { +void JoypadLinux::joypad_vibration_stop(Joypad &p_joypad, uint64_t p_timestamp) { + if (!p_joypad.force_feedback || p_joypad.fd == -1 || p_joypad.ff_effect_id == -1) { return; } - if (ioctl(joy.fd, EVIOCRMFF, joy.ff_effect_id) < 0) { + if (ioctl(p_joypad.fd, EVIOCRMFF, p_joypad.ff_effect_id) < 0) { return; } - joy.ff_effect_id = -1; - joy.ff_effect_timestamp = p_timestamp; + p_joypad.ff_effect_id = -1; + p_joypad.ff_effect_timestamp = p_timestamp; } float JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { @@ -433,104 +425,124 @@ float JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { return 2.0f * (p_value - min) / (max - min) - 1.0f; } -void JoypadLinux::process_joypads() { - if (joy_mutex.try_lock() != OK) { - return; +void JoypadLinux::joypad_events_thread_func(void *p_user) { + if (p_user) { + JoypadLinux *joy = (JoypadLinux *)p_user; + joy->joypad_events_thread_run(); } +} + +void JoypadLinux::joypad_events_thread_run() { + while (!joypad_events_exit.is_set()) { + bool no_events = true; + for (int i = 0; i < JOYPADS_MAX; i++) { + MutexLock lock(joypads_mutex[i]); + Joypad &joypad = joypads[i]; + if (joypad.fd == -1) { + continue; + } + input_event event; + while (read(joypad.fd, &event, sizeof(event)) > 0) { + no_events = false; + JoypadEvent joypad_event; + joypad_event.type = event.type; + joypad_event.code = event.code; + joypad_event.value = event.value; + joypad.events.push_back(joypad_event); + } + if (errno != EAGAIN) { + close_joypad(joypad, i); + } + } + if (no_events) { + usleep(10000); // 10ms + } + } +} + +void JoypadLinux::process_joypads() { for (int i = 0; i < JOYPADS_MAX; i++) { - if (joypads[i].fd == -1) { + MutexLock lock(joypads_mutex[i]); + Joypad &joypad = joypads[i]; + if (joypad.fd == -1) { continue; } + for (uint32_t j = 0; j < joypad.events.size(); j++) { + const JoypadEvent &joypad_event = joypad.events[j]; + // joypad_event may be tainted and out of MAX_KEY range, which will cause + // joypad.key_map[joypad_event.code] to crash + if (joypad_event.code >= MAX_KEY) { + return; + } - input_event events[32]; - Joypad *joy = &joypads[i]; - - int len; - - while ((len = read(joy->fd, events, (sizeof events))) > 0) { - len /= sizeof(events[0]); - for (int j = 0; j < len; j++) { - input_event &ev = events[j]; - - // ev may be tainted and out of MAX_KEY range, which will cause - // joy->key_map[ev.code] to crash - if (ev.code >= MAX_KEY) { - return; - } - - switch (ev.type) { - case EV_KEY: - input->joy_button(i, (JoyButton)joy->key_map[ev.code], ev.value); - break; - - case EV_ABS: - - switch (ev.code) { - case ABS_HAT0X: - if (ev.value != 0) { - if (ev.value < 0) { - joy->dpad = (HatMask)((joy->dpad | HatMask::LEFT) & ~HatMask::RIGHT); - } else { - joy->dpad = (HatMask)((joy->dpad | HatMask::RIGHT) & ~HatMask::LEFT); - } + switch (joypad_event.type) { + case EV_KEY: + input->joy_button(i, (JoyButton)joypad.key_map[joypad_event.code], joypad_event.value); + break; + + case EV_ABS: + switch (joypad_event.code) { + case ABS_HAT0X: + if (joypad_event.value != 0) { + if (joypad_event.value < 0) { + joypad.dpad = (HatMask)((joypad.dpad | HatMask::LEFT) & ~HatMask::RIGHT); } else { - joy->dpad &= ~(HatMask::LEFT | HatMask::RIGHT); + joypad.dpad = (HatMask)((joypad.dpad | HatMask::RIGHT) & ~HatMask::LEFT); } - - input->joy_hat(i, (HatMask)joy->dpad); - break; - - case ABS_HAT0Y: - if (ev.value != 0) { - if (ev.value < 0) { - joy->dpad = (HatMask)((joy->dpad | HatMask::UP) & ~HatMask::DOWN); - } else { - joy->dpad = (HatMask)((joy->dpad | HatMask::DOWN) & ~HatMask::UP); - } + } else { + joypad.dpad &= ~(HatMask::LEFT | HatMask::RIGHT); + } + input->joy_hat(i, (HatMask)joypad.dpad); + break; + + case ABS_HAT0Y: + if (joypad_event.value != 0) { + if (joypad_event.value < 0) { + joypad.dpad = (HatMask)((joypad.dpad | HatMask::UP) & ~HatMask::DOWN); } else { - joy->dpad &= ~(HatMask::UP | HatMask::DOWN); + joypad.dpad = (HatMask)((joypad.dpad | HatMask::DOWN) & ~HatMask::UP); } - - input->joy_hat(i, (HatMask)joy->dpad); - break; - - default: - if (ev.code >= MAX_ABS) { - return; - } - if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) { - float value = axis_correct(joy->abs_info[ev.code], ev.value); - joy->curr_axis[joy->abs_map[ev.code]] = value; - } - break; - } - break; - } + } else { + joypad.dpad &= ~(HatMask::UP | HatMask::DOWN); + } + input->joy_hat(i, (HatMask)joypad.dpad); + break; + + default: + if (joypad_event.code >= MAX_ABS) { + return; + } + if (joypad.abs_map[joypad_event.code] != -1 && joypad.abs_info[joypad_event.code]) { + float value = axis_correct(joypad.abs_info[joypad_event.code], joypad_event.value); + joypad.curr_axis[joypad.abs_map[joypad_event.code]] = value; + } + break; + } + break; } } + joypad.events.clear(); + for (int j = 0; j < MAX_ABS; j++) { - int index = joy->abs_map[j]; + int index = joypad.abs_map[j]; if (index != -1) { - input->joy_axis(i, (JoyAxis)index, joy->curr_axis[index]); + input->joy_axis(i, (JoyAxis)index, joypad.curr_axis[index]); } } - if (len == 0 || (len < 0 && errno != EAGAIN)) { - close_joypad(i); - } - if (joy->force_feedback) { + if (joypad.force_feedback) { uint64_t timestamp = input->get_joy_vibration_timestamp(i); - if (timestamp > joy->ff_effect_timestamp) { + if (timestamp > joypad.ff_effect_timestamp) { Vector2 strength = input->get_joy_vibration_strength(i); float duration = input->get_joy_vibration_duration(i); if (strength.x == 0 && strength.y == 0) { - joypad_vibration_stop(i, timestamp); + joypad_vibration_stop(joypad, timestamp); } else { - joypad_vibration_start(i, strength.x, strength.y, duration, timestamp); + joypad_vibration_start(joypad, strength.x, strength.y, duration, timestamp); } } } } - joy_mutex.unlock(); } -#endif + +#endif // JOYDEV_ENABLED diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h index 9177465547..4afc261ce7 100644 --- a/platform/linuxbsd/joypad_linux.h +++ b/platform/linuxbsd/joypad_linux.h @@ -35,6 +35,7 @@ #include "core/input/input.h" #include "core/os/mutex.h" #include "core/os/thread.h" +#include "core/templates/local_vector.h" struct input_absinfo; @@ -51,6 +52,12 @@ private: MAX_KEY = 767, // Hack because <linux/input.h> can't be included here }; + struct JoypadEvent { + uint16_t type; + uint16_t code; + int32_t value; + }; + struct Joypad { float curr_axis[MAX_ABS]; int key_map[MAX_KEY]; @@ -65,6 +72,8 @@ private: int ff_effect_id = 0; uint64_t ff_effect_timestamp = 0; + LocalVector<JoypadEvent> events; + ~Joypad(); void reset(); }; @@ -72,29 +81,39 @@ private: #ifdef UDEV_ENABLED bool use_udev = false; #endif - SafeFlag exit_monitor; - Mutex joy_mutex; - Thread joy_thread; Input *input = nullptr; + + SafeFlag monitor_joypads_exit; + SafeFlag joypad_events_exit; + Thread monitor_joypads_thread; + Thread joypad_events_thread; + Joypad joypads[JOYPADS_MAX]; + Mutex joypads_mutex[JOYPADS_MAX]; + Vector<String> attached_devices; - static void joy_thread_func(void *p_user); + static void monitor_joypads_thread_func(void *p_user); + void monitor_joypads_thread_run(); + + void open_joypad(const char *p_path); + void setup_joypad_properties(Joypad &p_joypad); - int get_joy_from_path(String p_path) const; + void close_joypads(); + void close_joypad(const char *p_devpath); + void close_joypad(Joypad &p_joypad, int p_id); - void setup_joypad_properties(int p_id); - void close_joypad(int p_id = -1); #ifdef UDEV_ENABLED void enumerate_joypads(struct udev *p_udev); void monitor_joypads(struct udev *p_udev); #endif void monitor_joypads(); - void run_joypad_thread(); - void open_joypad(const char *p_path); - void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); - void joypad_vibration_stop(int p_id, uint64_t p_timestamp); + void joypad_vibration_start(Joypad &p_joypad, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); + void joypad_vibration_stop(Joypad &p_joypad, uint64_t p_timestamp); + + static void joypad_events_thread_func(void *p_user); + void joypad_events_thread_run(); float axis_correct(const input_absinfo *p_abs, int p_value) const; }; diff --git a/platform/linuxbsd/tts_linux.h b/platform/linuxbsd/tts_linux.h index 4d39af8970..4e3f348ae4 100644 --- a/platform/linuxbsd/tts_linux.h +++ b/platform/linuxbsd/tts_linux.h @@ -35,7 +35,7 @@ #include "core/os/thread_safe.h" #include "core/string/ustring.h" #include "core/templates/list.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/variant/array.h" #include "servers/display_server.h" @@ -49,7 +49,7 @@ class TTS_Linux { bool speaking = false; bool paused = false; int last_msg_id = -1; - Map<int, int> ids; + HashMap<int, int> ids; Thread init_thread; |