diff options
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r-- | platform/linuxbsd/joypad_linux.cpp | 25 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 65 | ||||
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.h | 5 |
3 files changed, 65 insertions, 30 deletions
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 342cff82e9..5d636240b7 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -56,6 +56,14 @@ static const char *ignore_str = "/dev/input/js"; #endif +// On Linux with Steam Input Xbox 360 devices have an index appended to their device name, this index is +// the Steam Input gamepad index +#define VALVE_GAMEPAD_NAME_PREFIX "Microsoft X-Box 360 pad " +// IDs used by Steam Input virtual controllers. +// See https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices +#define VALVE_GAMEPAD_VID 0x28DE +#define VALVE_GAMEPAD_PID 0x11FF + JoypadLinux::Joypad::~Joypad() { for (int i = 0; i < MAX_ABS; i++) { if (abs_info[i]) { @@ -411,8 +419,23 @@ void JoypadLinux::open_joypad(const char *p_path) { setup_joypad_properties(joypad); sprintf(uid, "%04x%04x", BSWAP16(inpid.bustype), 0); if (inpid.vendor && inpid.product && inpid.version) { + Dictionary joypad_info; + joypad_info["vendor_id"] = inpid.vendor; + joypad_info["product_id"] = inpid.product; + joypad_info["raw_name"] = name; + sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor, 0, product, 0, version, 0); - input->joy_connection_changed(joy_num, true, name, uid); + + if (inpid.vendor == VALVE_GAMEPAD_VID && inpid.product == VALVE_GAMEPAD_PID) { + if (name.begins_with(VALVE_GAMEPAD_NAME_PREFIX)) { + String idx_str = name.substr(strlen(VALVE_GAMEPAD_NAME_PREFIX)); + if (idx_str.is_valid_int()) { + joypad_info["steam_input_index"] = idx_str.to_int(); + } + } + } + + input->joy_connection_changed(joy_num, true, name, uid, joypad_info); } else { String uidname = uid; int uidlen = MIN(name.length(), 11); diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 2643cd3b1a..f0864f5134 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -379,7 +379,11 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { if (show_cursor && !previously_shown) { WindowID window_id = get_window_at_screen_position(mouse_get_position()); - if (window_id != INVALID_WINDOW_ID) { + if (window_id != INVALID_WINDOW_ID && window_mouseover_id != window_id) { + if (window_mouseover_id != INVALID_WINDOW_ID) { + _send_window_event(windows[window_mouseover_id], WINDOW_EVENT_MOUSE_EXIT); + } + window_mouseover_id = window_id; _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER); } } @@ -744,7 +748,7 @@ int DisplayServerX11::get_screen_count() const { // Using Xinerama Extension int event_base, error_base; - if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) { XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); XFree(xsi); } else { @@ -756,7 +760,7 @@ int DisplayServerX11::get_screen_count() const { int DisplayServerX11::get_primary_screen() const { int event_base, error_base; - if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) { return 0; } else { return XDefaultScreen(x11_display); @@ -809,7 +813,7 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const { // Using Xinerama Extension. int event_base, error_base; - if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) { int count; XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); @@ -1244,7 +1248,7 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const { XImage *image = nullptr; int event_base, error_base; - if (XineramaQueryExtension(x11_display, &event_base, &error_base)) { + if (xinerama_ext_ok && XineramaQueryExtension(x11_display, &event_base, &error_base)) { int xin_count; XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &xin_count); if (p_screen < xin_count) { @@ -1449,6 +1453,11 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { DEBUG_LOG_X11("delete_sub_window: %lu (%u) \n", wd.x11_window, p_id); + if (window_mouseover_id == p_id) { + window_mouseover_id = INVALID_WINDOW_ID; + _send_window_event(windows[p_id], WINDOW_EVENT_MOUSE_EXIT); + } + window_set_rect_changed_callback(Callable(), p_id); window_set_window_event_callback(Callable(), p_id); window_set_input_event_callback(Callable(), p_id); @@ -1586,6 +1595,7 @@ void DisplayServerX11::window_set_mouse_passthrough(const Vector<Vector2> &p_reg void DisplayServerX11::_update_window_mouse_passthrough(WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); + ERR_FAIL_COND(!xshaped_ext_ok); const Vector<Vector2> region_path = windows[p_window].mpath; @@ -3957,7 +3967,7 @@ bool DisplayServerX11::mouse_process_popups() { // Find top popup to close. while (E) { // Popup window area. - Rect2i win_rect = Rect2i(window_get_position(E->get()), window_get_size(E->get())); + Rect2i win_rect = Rect2i(window_get_position_with_decorations(E->get()), window_get_size_with_decorations(E->get())); // Area of the parent window, which responsible for opening sub-menu. Rect2i safe_rect = window_get_popup_safe_rect(E->get()); if (win_rect.has_point(pos)) { @@ -4291,7 +4301,8 @@ void DisplayServerX11::process_events() { break; } - if (!mouse_mode_grab) { + if (!mouse_mode_grab && window_mouseover_id == window_id) { + window_mouseover_id = INVALID_WINDOW_ID; _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT); } @@ -4303,7 +4314,11 @@ void DisplayServerX11::process_events() { break; } - if (!mouse_mode_grab) { + if (!mouse_mode_grab && window_mouseover_id != window_id) { + if (window_mouseover_id != INVALID_WINDOW_ID) { + _send_window_event(windows[window_mouseover_id], WINDOW_EVENT_MOUSE_EXIT); + } + window_mouseover_id = window_id; _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER); } } break; @@ -5461,13 +5476,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } if (initialize_xinerama(dylibloader_verbose) != 0) { - r_error = ERR_UNAVAILABLE; - ERR_FAIL_MSG("Can't load Xinerama dynamically."); + xinerama_ext_ok = false; } if (initialize_xrandr(dylibloader_verbose) != 0) { - r_error = ERR_UNAVAILABLE; - ERR_FAIL_MSG("Can't load Xrandr dynamically."); + xrandr_ext_ok = false; } if (initialize_xrender(dylibloader_verbose) != 0) { @@ -5537,42 +5550,36 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode return; } - { + if (xshaped_ext_ok) { int version_major = 0; int version_minor = 0; int rc = XShapeQueryVersion(x11_display, &version_major, &version_minor); print_verbose(vformat("Xshape %d.%d detected.", version_major, version_minor)); if (rc != 1 || version_major < 1) { - ERR_PRINT("Unsupported Xshape library version."); - r_error = ERR_UNAVAILABLE; - XCloseDisplay(x11_display); - return; + xshaped_ext_ok = false; + print_verbose("Unsupported Xshape library version."); } } - { + if (xinerama_ext_ok) { int version_major = 0; int version_minor = 0; int rc = XineramaQueryVersion(x11_display, &version_major, &version_minor); print_verbose(vformat("Xinerama %d.%d detected.", version_major, version_minor)); if (rc != 1 || version_major < 1) { - ERR_PRINT("Unsupported Xinerama library version."); - r_error = ERR_UNAVAILABLE; - XCloseDisplay(x11_display); - return; + xinerama_ext_ok = false; + print_verbose("Unsupported Xinerama library version."); } } - { + if (xrandr_ext_ok) { int version_major = 0; int version_minor = 0; int rc = XRRQueryVersion(x11_display, &version_major, &version_minor); print_verbose(vformat("Xrandr %d.%d detected.", version_major, version_minor)); if (rc != 1 || (version_major == 1 && version_minor < 3) || (version_major < 1)) { - ERR_PRINT("Unsupported Xrandr library version."); - r_error = ERR_UNAVAILABLE; - XCloseDisplay(x11_display); - return; + xrandr_ext_ok = false; + print_verbose("Unsupported Xrandr library version."); } } @@ -5638,7 +5645,9 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode if (!xrandr_handle) { fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err); } - } else { + } + + if (xrandr_handle) { XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor); if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) { xrr_get_monitors = (xrr_get_monitors_t)dlsym(xrandr_handle, "XRRGetMonitors"); diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 70703d42c3..cce44a92de 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -225,6 +225,7 @@ class DisplayServerX11 : public DisplayServer { List<WindowID> popup_list; + WindowID window_mouseover_id = INVALID_WINDOW_ID; WindowID last_focused_window = INVALID_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID; @@ -322,7 +323,9 @@ class DisplayServerX11 : public DisplayServer { xrr_get_monitors_t xrr_get_monitors = nullptr; xrr_free_monitors_t xrr_free_monitors = nullptr; void *xrandr_handle = nullptr; - Bool xrandr_ext_ok; + bool xrandr_ext_ok = true; + bool xinerama_ext_ok = true; + bool xshaped_ext_ok = true; struct Property { unsigned char *data; |