Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package sc-controller for openSUSE:Factory checked in at 2022-05-07 23:54:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/sc-controller (Old) and /work/SRC/openSUSE:Factory/.sc-controller.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "sc-controller" Sat May 7 23:54:17 2022 rev:12 rq:975474 version:0.4.8.7 Changes: -------- --- /work/SRC/openSUSE:Factory/sc-controller/sc-controller.changes 2021-09-12 20:09:36.948088884 +0200 +++ /work/SRC/openSUSE:Factory/.sc-controller.new.1538/sc-controller.changes 2022-05-07 23:54:18.568909609 +0200 @@ -1,0 +2,35 @@ +Fri May 6 18:11:50 UTC 2022 - Jannik Seiler <se...@mosad.xyz> + +- Update to 0.4.8.7 + * AppImage tested on Ubuntu 22.04 LTS, Fedora 35, Fedora 33, + Manjaro, and PopOS 21.10 + * Updated AppImage scripts for setuptools behavior changes and + library path changes + * Migrate setup.py script to use setuptools rather than distutils. + Try to comply with PEP 632 regarding the deprecation of distutils + * Fixed Turn Off Controller option for BLE connected controller. + Contribution by labsin + * Changed feel of rumble emulation support. Period and amplitude of + haptics change depending on data in ff_rumble event struct. + I find that it feels better + * Fixed long packet support for BLE reader. 3 input packet payloads + now work in BLE reader + * Fixed hotplug detection for BT connected Steam Controller + * Added report ID 3 to feature report packets to allow BLE support to + work again. Needed to make BLE support work with later versions of BlueZ (5.64) + * Fixes to allow Bluetooth evdev and HID controllers to appear in + controller registration list. Contribution by chewi + * Fixed some HID driver and evdev driver crashes. Contribution by Alastor27 + * Fixed popup positioning and layering (somewhat) on Wayland. + Contribution by Supreeeme + * Allow deadzone calculations for analog trigger output. + Full usable analog trigger range + * Fixed Mouse Region output + * Small fixes for HID report parsing + * Added lowercase VDF button aliases to button dictionary + * Properly clamp rotated touchpad coordinates to s16 range + * Use proper limits for output 360 axes + * Add DS4 v.1 detection to ds4drv driver + * Fix display names for mapped X and Y buttons due to busted Linux aliases + +------------------------------------------------------------------- Old: ---- sc-controller-0.4.8.6.tar.gz New: ---- sc-controller-0.4.8.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ sc-controller.spec ++++++ --- /var/tmp/diff_new_pack.l390cq/_old 2022-05-07 23:54:19.352910590 +0200 +++ /var/tmp/diff_new_pack.l390cq/_new 2022-05-07 23:54:19.356910595 +0200 @@ -1,7 +1,7 @@ # # spec file for package sc-controller # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: sc-controller -Version: 0.4.8.6 +Version: 0.4.8.7 Release: 0 Summary: User-mode driver and GTK3-based GUI for the Steam Controller License: GPL-2.0-only @@ -29,6 +29,7 @@ BuildRequires: gobject-introspection BuildRequires: hicolor-icon-theme BuildRequires: pkgconfig +BuildRequires: python3-setuptools BuildRequires: shared-mime-info BuildRequires: zlib-devel BuildRequires: pkgconfig(python3) ++++++ sc-controller-0.4.8.6.tar.gz -> sc-controller-0.4.8.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/README.md new/sc-controller-0.4.8.7/README.md --- old/sc-controller-0.4.8.6/README.md 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/README.md 2022-05-06 18:39:50.000000000 +0200 @@ -43,6 +43,7 @@ - [python-pylibacl](http://pylibacl.k1024.org/) is recommended - [python-evdev](https://python-evdev.readthedocs.io/en/latest/) is strongly recommended - [python-vdf](https://pypi.org/project/vdf/) + - [gtk-layer-shell](https://github.com/wmww/gtk-layer-shell) (Wayland only) ### Installing - Download and extract [latest release](https://github.com/kozec/sc-controller/releases/latest) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/appimage-build.sh new/sc-controller-0.4.8.7/appimage-build.sh --- old/sc-controller-0.4.8.6/appimage-build.sh 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/appimage-build.sh 2022-05-06 18:39:50.000000000 +0200 @@ -105,7 +105,9 @@ # Build important part python3 setup.py build -python3 setup.py install --prefix ${BUILD_APPDIR}/usr + +# Need to use single-version-externally-managed due to setuptools behavior +python3 setup.py install --single-version-externally-managed --prefix ${BUILD_APPDIR}/usr --record /dev/null # Move udev stuff mv ${BUILD_APPDIR}/usr/lib/udev/rules.d/69-${APP}.rules ${BUILD_APPDIR}/ @@ -127,12 +129,12 @@ cp scripts/${APP}.appdata.xml ${BUILD_APPDIR}/usr/share/metainfo/${APP}.appdata.xml # Make symlinks -ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libcemuhook.cpython-39-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libcemuhook.so -ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libhiddrv.cpython-39-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libhiddrv.so -ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libremotepad.cpython-39-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libremotepad.so -ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libsc_by_bt.cpython-39-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libsc_by_bt.so -ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libuinput.cpython-39-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libuinput.so -ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/posix1e.cpython-39-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/posix1e.so +ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libcemuhook.cpython-310-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libcemuhook.so +ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libhiddrv.cpython-310-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libhiddrv.so +ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libremotepad.cpython-310-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libremotepad.so +ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libsc_by_bt.cpython-310-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libsc_by_bt.so +ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libuinput.cpython-310-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/libuinput.so +ln -sfr ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/posix1e.cpython-310-x86_64-linux-gnu.so ${BUILD_APPDIR}/usr/lib64/python${PYTHON_VERSION}/site-packages/posix1e.so # Copy AppRun script cp scripts/appimage-AppRun.sh ${BUILD_APPDIR}/AppRun diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/actions.py new/sc-controller-0.4.8.7/scc/actions.py --- old/sc-controller-0.4.8.6/scc/actions.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/actions.py 2022-05-06 18:39:50.000000000 +0200 @@ -13,7 +13,8 @@ from scc.tools import circle_to_square, clamp, nameof from scc.uinput import Keys, Axes, Rels from scc.lib import xwrappers as X -from scc.constants import STICK_PAD_MIN, STICK_PAD_MAX, STICK_PAD_MIN_HALF +from scc.constants import (STICK_PAD_MIN, STICK_PAD_MAX, STICK_PAD_MIN_HALF, +OUTPUT_360_STICK_MIN, OUTPUT_360_STICK_MAX) from scc.constants import STICK_PAD_MAX_HALF, TRIGGER_MIN, TRIGGER_HALF from scc.constants import HIPFIRE_NORMAL, HIPFIRE_SENSIBLE, HIPFIRE_EXCLUSIVE from scc.constants import LEFT, RIGHT, CPAD, STICK, PITCH, YAW, ROLL @@ -682,7 +683,7 @@ # DPAD return int(max(-1, min(1, value))) # Everything else - return int(max(STICK_PAD_MIN, min(STICK_PAD_MAX, value))) + return int(max(OUTPUT_360_STICK_MIN, min(OUTPUT_360_STICK_MAX, value))) def axis(self, mapper, position, what): @@ -1456,8 +1457,9 @@ Keys.BTN_SELECT : "< Select", Keys.BTN_A : "A Button", Keys.BTN_B : "B Button", - Keys.BTN_X : "X Button", - Keys.BTN_Y : "Y Button", + # Work around busted Linux btn aliases + Keys.BTN_NORTH : "X Button", + Keys.BTN_WEST : "Y Button", Keys.KEY_PREVIOUSSONG : "<< Song", Keys.KEY_STOP : "Stop", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/constants.py new/sc-controller-0.4.8.7/scc/constants.py --- old/sc-controller-0.4.8.6/scc/constants.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/constants.py 2022-05-06 18:39:50.000000000 +0200 @@ -28,7 +28,7 @@ If SC-Controller is updated while daemon is running, DAEMON_VERSION send by daemon will differ one one expected by UI and daemon will be forcefully restarted. """ -DAEMON_VERSION = "0.4.8.6" +DAEMON_VERSION = "0.4.8.7" HPERIOD = 0.02 LPERIOD = 0.5 @@ -126,10 +126,14 @@ STICK_PAD_MIN = -32768 -STICK_PAD_MAX = 32768 +STICK_PAD_MAX = 32767 STICK_PAD_MIN_HALF = STICK_PAD_MIN / 3 STICK_PAD_MAX_HALF = STICK_PAD_MAX / 3 +# Take async 360 stick axes into account +OUTPUT_360_STICK_MAX = 32767 +OUTPUT_360_STICK_MIN = -32768 + CPAD_MIN = 0 CPAD_X_MAX = 1916 CPAD_Y_MAX = 930 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/device_monitor.py new/sc-controller-0.4.8.7/scc/device_monitor.py --- old/sc-controller-0.4.8.6/scc/device_monitor.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/device_monitor.py 2022-05-06 18:39:50.000000000 +0200 @@ -8,7 +8,7 @@ from scc.lib.eudevmonitor import Eudev, Monitor from scc.lib.ioctl_opt import IOR from ctypes.util import find_library -import os, ctypes, fcntl, re, logging +import os, ctypes, fcntl, re, logging, time log = logging.getLogger("DevMon") @@ -195,6 +195,9 @@ return vendor, product # Above method works for anything _but_ SteamController # For that one, following desperate mess is needed + + # Sleep for 1 second to make sure info is available on system + time.sleep(1) node = self._dev_for_hci(syspath) if node: name = node.split("/")[-1] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/ds4drv.py new/sc-controller-0.4.8.7/scc/drivers/ds4drv.py --- old/sc-controller-0.4.8.6/scc/drivers/ds4drv.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/ds4drv.py 2022-05-06 18:39:50.000000000 +0200 @@ -21,6 +21,7 @@ VENDOR_ID = 0x054c PRODUCT_ID = 0x09cc +DS4_V1_PRODUCT_ID = 0x5C4 class DS4Controller(HIDController): @@ -411,10 +412,17 @@ # daemon.add_error("ds4", "No access to DS4 device") if config["drivers"].get("hiddrv") or (HAVE_EVDEV and config["drivers"].get("evdevdrv")): + # DS4 v.2 register_hotplug_device(hid_callback, VENDOR_ID, PRODUCT_ID, on_failure=fail_cb) + # DS4 v.1 + register_hotplug_device(hid_callback, VENDOR_ID, DS4_V1_PRODUCT_ID, on_failure=fail_cb) if HAVE_EVDEV and config["drivers"].get("evdevdrv"): + # DS4 v.2 daemon.get_device_monitor().add_callback("bluetooth", VENDOR_ID, PRODUCT_ID, make_evdev_device, None) + # DS4 v.1 + daemon.get_device_monitor().add_callback("bluetooth", + VENDOR_ID, DS4_V1_PRODUCT_ID, make_evdev_device, None) return True else: log.warning("Neither HID nor Evdev driver is enabled, DS4 support cannot be enabled.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/evdevdrv.py new/sc-controller-0.4.8.7/scc/drivers/evdevdrv.py --- old/sc-controller-0.4.8.6/scc/drivers/evdevdrv.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/evdevdrv.py 2022-05-06 18:39:50.000000000 +0200 @@ -34,6 +34,7 @@ EvdevControllerInput = namedtuple('EvdevControllerInput', 'buttons ltrig rtrig stick_x stick_y lpad_x lpad_y rpad_x rpad_y ' + 'accel_x accel_y accel_z ' 'gpitch groll gyaw q1 q2 q3 q4 ' 'cpad_x cpad_y' ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/hiddrv.c new/sc-controller-0.4.8.7/scc/drivers/hiddrv.c --- old/sc-controller-0.4.8.6/scc/drivers/hiddrv.c 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/hiddrv.c 2022-05-06 18:39:50.000000000 +0200 @@ -8,7 +8,7 @@ #define HIDDRV_MODULE_VERSION 5 PyObject* module; -#define AXIS_COUNT 17 +#define AXIS_COUNT 20 #define BUTTON_COUNT 32 struct HIDControllerInput { @@ -26,15 +26,18 @@ AXIS_STICK_Y = 5, AXIS_LTRIG = 6, AXIS_RTRIG = 7, - AXIS_GPITCH = 8, - AXIS_GROLL = 9, - AXIS_GYAW = 10, - AXIS_Q1 = 11, - AXIS_Q2 = 12, - AXIS_Q3 = 13, - AXIS_Q4 = 14, - AXIS_CPAD_X = 15, - AXIS_CPAD_Y = 16, + AXIS_ACCEL_X = 8, + AXIS_ACCEL_Y = 9, + AXIS_ACCEL_Z = 10, + AXIS_GPITCH = 11, + AXIS_GROLL = 12, + AXIS_GYAW = 13, + AXIS_Q1 = 14, + AXIS_Q2 = 15, + AXIS_Q3 = 16, + AXIS_Q4 = 17, + AXIS_CPAD_X = 18, + AXIS_CPAD_Y = 19, _AxisType_force_int = INT_MAX }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/hiddrv.py new/sc-controller-0.4.8.7/scc/drivers/hiddrv.py --- old/sc-controller-0.4.8.6/scc/drivers/hiddrv.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/hiddrv.py 2022-05-06 18:39:50.000000000 +0200 @@ -23,7 +23,7 @@ DEV_CLASS_HID = 3 TRANSFER_TYPE_INTERRUPT = 3 LIBUSB_DT_REPORT = 0x22 -AXIS_COUNT = 17 # Must match number of axis fields in HIDControllerInput and values in AxisType +AXIS_COUNT = 20 # Must match number of axis fields in HIDControllerInput and values in AxisType BUTTON_COUNT = 32 # Must match (or be less than) number of bits in HIDControllerInput.buttons ALLOWED_SIZES = [1, 2, 4, 8, 16, 32] SYS_DEVICES = "/sys/devices" @@ -54,6 +54,9 @@ ('stick_y', ctypes.c_int32), ('ltrig', ctypes.c_int32), ('rtrig', ctypes.c_int32), + ('accel_x', ctypes.c_int32), + ('accel_y', ctypes.c_int32), + ('accel_z', ctypes.c_int32), ('gpitch', ctypes.c_int32), ('groll', ctypes.c_int32), ('gyaw', ctypes.c_int32), @@ -75,15 +78,18 @@ AXIS_STICK_Y = 5 AXIS_LTRIG = 6 AXIS_RTRIG = 7 - AXIS_GPITCH = 8 - AXIS_GROLL = 9 - AXIS_GYAW = 10 - AXIS_Q1 = 11 - AXIS_Q2 = 12 - AXIS_Q3 = 13 - AXIS_Q4 = 14 - AXIS_CPAD_X = 15 - AXIS_CPAD_Y = 16 + AXIS_ACCEL_X = 8 + AXIS_ACCEL_Y = 9 + AXIS_ACCEL_Z = 10 + AXIS_GPITCH = 11 + AXIS_GROLL = 12 + AXIS_GYAW = 13 + AXIS_Q1 = 14 + AXIS_Q2 = 15 + AXIS_Q3 = 16 + AXIS_Q4 = 17 + AXIS_CPAD_X = 18 + AXIS_CPAD_Y = 19 class AxisMode(IntEnum): @@ -234,7 +240,7 @@ if hid_descriptor is None: hid_descriptor = self.handle.getRawDescriptor( LIBUSB_DT_REPORT, 0, 512) - open("report", "wb").write(b"".join([ chr(x) for x in hid_descriptor ])) + open("report", "wb").write(bytes([x for x in hid_descriptor ])) self._build_hid_decoder(hid_descriptor, config, max_size) self._packet_size = self._decoder.packet_size @@ -346,13 +352,13 @@ if config: target, axis_data = self._build_axis_maping(next_axis, config) if axis_data: - axis_data.byte_offset = total / 8 + axis_data.byte_offset = total // 8 axis_data.bit_offset = total % 8 axis_data.size = size self._decoder.axes[target] = axis_data else: self._decoder.axes[next_axis] = AxisData(mode = AxisMode.AXIS_NO_SCALE) - self._decoder.axes[next_axis].byte_offset = total / 8 + self._decoder.axes[next_axis].byte_offset = total // 8 self._decoder.axes[next_axis].bit_offset = total % 8 self._decoder.axes[next_axis].size = size next_axis = next_axis + 1 @@ -367,12 +373,12 @@ if config: target, axis_data = self._build_axis_maping(next_axis, config, AxisMode.HATSWITCH) if axis_data: - axis_data.byte_offset = total / 8 + axis_data.byte_offset = total // 8 axis_data.bit_offset = total % 8 self._decoder.axes[target] = axis_data else: self._decoder.axes[next_axis] = AxisData(mode = AxisMode.HATSWITCH) - self._decoder.axes[next_axis].byte_offset = total / 8 + self._decoder.axes[next_axis].byte_offset = total // 8 self._decoder.axes[next_axis].bit_offset = total % 8 self._decoder.axes[next_axis].data.hatswitch.min = STICK_PAD_MIN self._decoder.axes[next_axis].data.hatswitch.max = STICK_PAD_MAX @@ -393,7 +399,7 @@ log.debug("Found %s buttons at bit %s", count, total) self._decoder.buttons = ButtonData( enabled = True, - byte_offset = total / 8, + byte_offset = total // 8, bit_offset = total % 8, size = buttons_size, button_count = count, @@ -404,7 +410,7 @@ log.debug("Skipped over %s bits for %s at bit %s", count * size, kind, total) total += count * size - self._decoder.packet_size = total / 8 + self._decoder.packet_size = total // 8 if total % 8 > 0: self._decoder.packet_size += 1 if self._decoder.packet_size > max_size: @@ -449,7 +455,8 @@ log.debug("Loading descriptor from '%s'", full_path) temp_list = None with open(full_path, "rb") as read_file: - temp_list = [ ord(x) for x in read_file.read(1024) ] + temp_list = [ x for x in read_file.read(1024)] + return temp_list except Exception as e: log.exception(e) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/sc_by_bt.c new/sc-controller-0.4.8.7/scc/drivers/sc_by_bt.c --- old/sc-controller-0.4.8.6/scc/drivers/sc_by_bt.c 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/sc_by_bt.c 2022-05-06 18:39:50.000000000 +0200 @@ -17,6 +17,7 @@ }; #define LONG_PACKET 0x80 +#define SINGLE_PACKET_PAYLOAD_PREFIX 0x40 #define PACKET_SIZE 20 enum SCButtons { @@ -116,24 +117,53 @@ /** Returns 1 if state has changed, 2 on read error */ int read_input(SCByBtCPtr ptr) { - if (ptr->long_packet) { - // Previous packet had long flag set and this is its 2nd part - if (read(ptr->fileno, tmp_buffer, PACKET_SIZE) < PACKET_SIZE) - return 2; - memcpy(ptr->buffer + PACKET_SIZE, tmp_buffer + 1, PACKET_SIZE - 1); - ptr->long_packet = 0; - //debug_packet(ptr->buffer, PACKET_SIZE * 2); - } else { - if (read(ptr->fileno, ptr->buffer, PACKET_SIZE) < PACKET_SIZE) - return 2; - ptr->long_packet = *((uint8_t*)(ptr->buffer + 1)) == LONG_PACKET; - if (ptr->long_packet) { - // This is 1st part of long packet + if (read(ptr->fileno, tmp_buffer, PACKET_SIZE) < PACKET_SIZE) + { + return 2; + } + + bool inLongPacket = false; + bool endPayload = false; + bool resetBufferData = false; + { + char checkPayloadByte = tmp_buffer[1]; + int currentPacketNum = (int)(checkPayloadByte & 0x0F); + //printf("%i\n", currentPacketNum); + //bool processPayload = false; + + inLongPacket = ptr->long_packet; + if (ptr->long_packet) + { + // Will grab 18 bytes from each partial input. Start idx + // offset from 20. + int offset = ((PACKET_SIZE - 2) * currentPacketNum) + 2; + // Skip copying first two bytes in partial input + // (report ID and packet payload byte) + memcpy(ptr->buffer + offset, tmp_buffer + 2, PACKET_SIZE - 2); + } + else + { + memcpy(ptr->buffer, tmp_buffer, PACKET_SIZE); + } + + endPayload = (checkPayloadByte & SINGLE_PACKET_PAYLOAD_PREFIX) == SINGLE_PACKET_PAYLOAD_PREFIX; + ptr->long_packet = !endPayload; + + if (!endPayload) + { return 0; } - //debug_packet(ptr->buffer, PACKET_SIZE); + else if (inLongPacket && endPayload) + { + resetBufferData = true; + } + + //if (endPayload) + //{ + // debug_packet(ptr->buffer, PACKET_SIZE * (currentPacketNum+1)); + //} } - + struct SCByBtControllerInput* state = &(ptr->state); struct SCByBtControllerInput* old_state = &(ptr->old_state); @@ -143,6 +173,12 @@ char* data = &ptr->buffer[4]; if ((type & PING) == PING) { // PING packet does nothing + + if (resetBufferData) + { + memset(ptr->buffer, 0, 256); + } + return 0; } if ((type & BUTTON) == BUTTON) { @@ -205,6 +241,11 @@ data += 14; */ } + + if (resetBufferData) + { + memset(ptr->buffer, 0, 256); + } return rv; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/sc_by_bt.py new/sc-controller-0.4.8.7/scc/drivers/sc_by_bt.py --- old/sc-controller-0.4.8.6/scc/drivers/sc_by_bt.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/sc_by_bt.py 2022-05-06 18:39:50.000000000 +0200 @@ -8,7 +8,7 @@ """ from scc.lib.hidraw import HIDRaw -from scc.constants import ControllerFlags +from scc.constants import ControllerFlags, STICK_PAD_MIN, STICK_PAD_MAX from scc.tools import find_library from .sc_dongle import SCPacketType, SCPacketLength, SCConfigType from .sc_dongle import SCController @@ -92,12 +92,13 @@ self.daemon.get_scheduler().schedule(1.0, reconnect) - def _retry_cancel(self, syspath): + def _retry_cancel(self, syspath, vendor, product): """ Cancels reconnection scheduled by 'retry'. Called when device monitor reports controller (as in BT device) being disconencted. """ - self.reconnecting.remove(syspath) + if syspath in self.reconnecting: + self.reconnecting.remove(syspath) def new_device_callback(self, syspath, *whatever): @@ -243,11 +244,20 @@ """ Flushes all prepared control messages to the device """ while len(self._cmsg): msg = self._cmsg.pop() - self._hidrawdev.sendFeatureReport(msg) + # Feature report data must be sent with report ID 3 + # or Input/output error will occur with later BlueZ versions (5.64) + # Does not affect older BlueZ versions + self._hidrawdev.sendFeatureReport(msg, 3) def input(self, idata): raise RuntimeError("This shouldn't be called, ever") + + def turnoff(self): + super().turnoff() + # Need to call flush to make sure packet + # is sent to controller + self.flush() def close(self, *a): @@ -269,13 +279,25 @@ if self._input_rotation_l and (self._state.type & 0x0100) != 0: lx, ly = self._state.lpad_x, self._state.lpad_y s, c = sin(self._input_rotation_l), cos(self._input_rotation_l) - self._state.lpad_x = int(lx * c - ly * s) - self._state.lpad_y = int(lx * s + ly * c) + + # Adjust LX for rotation and clamp + value = int(lx * c - ly * s) + self._state.lpad_x = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) + + # Adjust LY for rotation and clamp + value = int(lx * s + ly * c) + self._state.lpad_y = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) if self._input_rotation_r and (self._state.type & 0x0200) != 0: rx, ry = self._state.rpad_x, self._state.rpad_y s, c = sin(self._input_rotation_r), cos(self._input_rotation_r) - self._state.rpad_x = int(rx * c - ry * s) - self._state.rpad_y = int(rx * s + ry * c) + + # Adjust RX for rotation and clamp + value = int(rx * c - ry * s) + self._state.rpad_x = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) + + # Adjust RY for rotation and clamp + value = int(rx * s + ry * c) + self._state.rpad_y = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) self.mapper.input(self, self._old_state, self._state) self.flush() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/drivers/sc_dongle.py new/sc-controller-0.4.8.7/scc/drivers/sc_dongle.py --- old/sc-controller-0.4.8.6/scc/drivers/sc_dongle.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/drivers/sc_dongle.py 2022-05-06 18:39:50.000000000 +0200 @@ -8,7 +8,7 @@ from scc.lib import IntEnum from scc.drivers.usb import USBDevice, register_hotplug_device -from scc.constants import SCButtons, STICKTILT +from scc.constants import SCButtons, STICKTILT, STICK_PAD_MIN, STICK_PAD_MAX from scc.controller import Controller from scc.config import Config from collections import namedtuple @@ -195,16 +195,31 @@ # if (idata.buttons & STICKPRESS) and not (idata.buttons & STICKTILT): # idata = ControllerInput.replace(buttons=idata.buttons & ~SCButtons.LPAD) - if self._input_rotation_l: + if self._input_rotation_l or self._input_rotation_r: lx, ly = idata.lpad_x, idata.lpad_y - if idata.buttons & SCButtons.LPADTOUCH: + rx, ry = idata.rpad_x, idata.rpad_y + + if self._input_rotation_l and idata.buttons & SCButtons.LPADTOUCH: s, c = sin(self._input_rotation_l), cos(self._input_rotation_l) - lx = int(idata.lpad_x * c - idata.lpad_y * s) - ly = int(idata.lpad_x * s + idata.lpad_y * c) - s, c = sin(self._input_rotation_r), cos(self._input_rotation_r) - rx = int(idata.rpad_x * c - idata.rpad_y * s) - ry = int(idata.rpad_x * s + idata.rpad_y * c) - + # Adjust LX for rotation and clamp + value = int(idata.lpad_x * c - idata.lpad_y * s) + lx = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) + + # Adjust LY for rotation and clamp + value = int(idata.lpad_x * s + idata.lpad_y * c) + ly = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) + + if self._input_rotation_r and idata.buttons & SCButtons.RPADTOUCH: + s, c = sin(self._input_rotation_r), cos(self._input_rotation_r) + + # Adjust RX for rotation and clamp + value = int(idata.rpad_x * c - idata.rpad_y * s) + rx = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) + + # Adjust RY for rotation and clamp + value = int(idata.rpad_x * s + idata.rpad_y * c) + ry = max(STICK_PAD_MIN, min(STICK_PAD_MAX, value)) + # TODO: This is awfull :( idata = ControllerInput( idata.type, idata.status, idata.seq, idata.buttons, @@ -214,7 +229,7 @@ idata.gpitch, idata.groll, idata.gyaw, idata.q1, idata.q2, idata.q3, idata.q4 ) - + self.mapper.input(self, old_state, idata) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/foreign/vdf.py new/sc-controller-0.4.8.7/scc/foreign/vdf.py --- old/sc-controller-0.4.8.6/scc/foreign/vdf.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/foreign/vdf.py 2022-05-06 18:39:50.000000000 +0200 @@ -23,9 +23,14 @@ class VDFProfile(Profile): BUTTON_TO_BUTTON = { # maps button keys from vdf file to SCButtons constants + # It looks like uppercase button and lowercase button aliases are needed + 'button_a' : SCButtons.A, 'button_A' : SCButtons.A, + 'button_b' : SCButtons.B, 'button_B' : SCButtons.B, + 'button_x' : SCButtons.X, 'button_X' : SCButtons.X, + 'button_y' : SCButtons.Y, 'button_Y' : SCButtons.Y, 'button_back_left' : SCButtons.LGRIP, 'button_back_right' : SCButtons.RGRIP, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/gui/action_editor.py new/sc-controller-0.4.8.7/scc/gui/action_editor.py --- old/sc-controller-0.4.8.6/scc/gui/action_editor.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/gui/action_editor.py 2022-05-06 18:39:50.000000000 +0200 @@ -70,7 +70,7 @@ # That way, stuff like Rotation settings is not shown when editor # is used to edit menu actions. Action.AC_BUTTON : Action.MOD_OSD | Action.MOD_FEEDBACK, - Action.AC_TRIGGER : Action.MOD_OSD | Action.MOD_SENSITIVITY | Action.MOD_FEEDBACK, + Action.AC_TRIGGER : Action.MOD_OSD | Action.MOD_SENSITIVITY | Action.MOD_FEEDBACK | Action.MOD_DEADZONE, Action.AC_STICK : Action.MOD_OSD | Action.MOD_CLICK | Action.MOD_DEADZONE | Action.MOD_ROTATE | Action.MOD_SENSITIVITY | Action.MOD_FEEDBACK | Action.MOD_SMOOTH, Action.AC_PAD : Action.MOD_OSD | Action.MOD_CLICK | Action.MOD_DEADZONE | Action.MOD_ROTATE | Action.MOD_SENSITIVITY | Action.MOD_FEEDBACK | Action.MOD_SMOOTH | Action.MOD_BALL, Action.AC_GYRO : Action.MOD_OSD | Action.MOD_SENSITIVITY | Action.MOD_SENS_Z | Action.MOD_DEADZONE | Action.MOD_FEEDBACK, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/gui/ae/__init__.py new/sc-controller-0.4.8.7/scc/gui/ae/__init__.py --- old/sc-controller-0.4.8.6/scc/gui/ae/__init__.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/gui/ae/__init__.py 2022-05-06 18:39:50.000000000 +0200 @@ -105,7 +105,11 @@ if v is None or type(v) in (int, float, str,): return _('(not set)') elif isinstance(v, Action): - dsc = v.describe(Action.AC_STICK if cls == XYAction else Action.AC_BUTTON) + if not mode: + dsc = v.describe(Action.AC_STICK if cls == XYAction else Action.AC_BUTTON) + else: + dsc = v.describe(mode) + if "\n" in dsc: dsc = "<small>" + "\n".join(dsc.split("\n")[0:2]) + "</small>" return dsc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/gui/ae/trigger.py new/sc-controller-0.4.8.7/scc/gui/ae/trigger.py --- old/sc-controller-0.4.8.6/scc/gui/ae/trigger.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/gui/ae/trigger.py 2022-05-06 18:39:50.000000000 +0200 @@ -156,9 +156,10 @@ self.set_cb(cb, trigger_style, 1) if full: self.builder.get_object("sclFullLevel").set_value(full.press_level) - if isinstance(analog, TriggerAction): - self.builder.get_object("sclARangeStart").set_value(analog.press_level) - self.builder.get_object("sclARangeEnd").set_value(analog.release_level) + + if isinstance(analog, AxisAction): + self.builder.get_object("sclARangeStart").set_value(analog.min) + self.builder.get_object("sclARangeEnd").set_value(analog.max) self._recursing = False self.update() @@ -167,7 +168,7 @@ def update(self): self.builder.get_object("lblPartPressed").set_label(describe_action(Action.AC_BUTTON, ButtonAction, self.half)) self.builder.get_object("lblFullPressed").set_label(describe_action(Action.AC_BUTTON, ButtonAction, self.full)) - self.builder.get_object("lblAnalog").set_label(describe_action(Action.AC_BUTTON, AxisAction, self.analog)) + self.builder.get_object("lblAnalog").set_label(describe_action(Action.AC_TRIGGER, AxisAction, self.analog)) def send(self): @@ -197,9 +198,9 @@ analog_start = int(self.builder.get_object("sclARangeStart").get_value()) analog_end = int(self.builder.get_object("sclARangeEnd").get_value()) if analog_start == TRIGGER_MIN and analog_end == TRIGGER_MAX: - actions.append(self.analog) + actions.append(AxisAction(self.analog.id)) else: - actions.append(TriggerAction(analog_start, analog_end, self.analog)) + actions.append(AxisAction(self.analog.id, analog_start, analog_end)) self.editor.set_action(MultiAction.make(*actions)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/gui/creg/dialog.py new/sc-controller-0.4.8.7/scc/gui/creg/dialog.py --- old/sc-controller-0.4.8.6/scc/gui/creg/dialog.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/gui/creg/dialog.py 2022-05-06 18:39:50.000000000 +0200 @@ -460,7 +460,9 @@ ] self._tester.start() - if dev.info.vendor == 0 and dev.info.product == 0: + # Check VID+PID info and whether HID driver support is enabled + if (dev.info.vendor == 0 and dev.info.product == 0 or + not self.app.config["drivers"].get("hiddrv")): # Not an USB device, skip HID test altogether retry_with_evdev(None, 0) else: @@ -740,7 +742,9 @@ for fname in evdev.list_devices(): dev = evdev.InputDevice(fname) is_gamepad = ControllerRegistration.does_he_looks_like_a_gamepad(dev) - if not dev.phys: + # bustype 3 is BUS_USB, which is the type used for emulated + # gamepads. phys is blank for BUS_BLUETOOTH devices. + if dev.info.bustype == 3 and not dev.phys: # Skipping over virtual devices so list doesn't show # gamepads emulated by SCC continue diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/gui/menu_editor.py new/sc-controller-0.4.8.7/scc/gui/menu_editor.py --- old/sc-controller-0.4.8.6/scc/gui/menu_editor.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/gui/menu_editor.py 2022-05-06 18:39:50.000000000 +0200 @@ -235,7 +235,7 @@ def on_entName_changed(self, *a): - id = self.builder.get_object("entName").get_text().decode("utf-8") + id = self.builder.get_object("entName").get_text() if len(id.strip()) == 0: self._bad_id_no_id() return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/lib/hidparse.py new/sc-controller-0.4.8.7/scc/lib/hidparse.py --- old/sc-controller-0.4.8.6/scc/lib/hidparse.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/lib/hidparse.py 2022-05-06 18:39:50.000000000 +0200 @@ -70,7 +70,7 @@ def __new__(cls, value): if value not in cls._CACHE: - cls._CACHE[value] = object.__new__(cls, value) + cls._CACHE[value] = object.__new__(cls) return cls._CACHE[value] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/lib/xwrappers.py new/sc-controller-0.4.8.7/scc/lib/xwrappers.py --- old/sc-controller-0.4.8.6/scc/lib/xwrappers.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/lib/xwrappers.py 2022-05-06 18:39:50.000000000 +0200 @@ -331,7 +331,7 @@ Returns (nitems, property) of specified window or (-1, None) if anything fails. Returned 'property' is POINTER(c_void_p) and has to be freed using X.free(). """ - prop_atom = intern_atom(dpy, bytes(prop_name, "utf-8"), False) + prop_atom = intern_atom(dpy, prop_name, False) type_return, format_return = Atom(), Atom() nitems, bytes_after = c_ulong(), c_ulong() prop = c_void_p() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/mapper.py new/sc-controller-0.4.8.7/scc/mapper.py --- old/sc-controller-0.4.8.6/scc/mapper.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/mapper.py 2022-05-06 18:39:50.000000000 +0200 @@ -104,13 +104,34 @@ def _rumble_ready(self, fd, event): + # Taken from Steam Controller Singer project + # https://gitlab.com/Pilatomic/SteamControllerSinger + STEAM_CONTROLLER_MAGIC_PERIOD_RATIO = 495483.0 ef = self.gamepad.ff_read() if ef: # tale of... + period_command = 0 + amplitude = 0 + if ef.level != 0: + tempRatio = ef.level / 32767.5 + period_command = ((6000 - 25000) * tempRatio + 25000) + amplitude = ((900 - 600) * tempRatio + 600); + + raw_period = period_command / STEAM_CONTROLLER_MAGIC_PERIOD_RATIO + #duration_seconds = 1 + duration_seconds = ef.duration / 1000.0 * ef.repetitions + count = 0 + if raw_period != 0: + count = min(int(duration_seconds * 1.5 / raw_period), 0x7FFF) + + #log.debug(f"{ef.level} {ef.duration} {ef.repetitions} {count}") self.send_feedback(HapticData( HapticPos.BOTH, - period = 32760, - amplitude = max(0, ef.level), - count = min(0x7FFF, ef.duration * ef.repetitions / 30) + period = period_command, + amplitude = amplitude, + count = count, + #period = 20000, + #amplitude = max(0, ef.level), + #count = min(0x7FFF, ef.duration * ef.repetitions / 30) )) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/modifiers.py new/sc-controller-0.4.8.7/scc/modifiers.py --- old/sc-controller-0.4.8.6/scc/modifiers.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/modifiers.py 2022-05-06 18:39:50.000000000 +0200 @@ -423,6 +423,10 @@ def set_speed(self, x, y, *a): self.speed = (x, y) + if self.action and (isinstance(self.action, CircularModifier) + and hasattr(self.action, "set_speed")): + self.action.set_speed(x, y, *a) + # Reset calculated x and y velocities self._xvel = 0.0 self._yvel = 0.0 @@ -710,7 +714,20 @@ angle = atan2(x, y) return distance * sin(angle), distance * cos(angle) - + + def _convert_trigger_stick_range(self, position, trigger_range): + result = clamp(0, + (position / trigger_range) * STICK_PAD_MAX, + STICK_PAD_MAX) + + return result + + def _convert_stick_trigger_range(self, position): + result = clamp(0, + (position / STICK_PAD_MAX) * TRIGGER_MAX, + TRIGGER_MAX) + + return result @staticmethod def decode(data, a, *b): @@ -769,9 +786,19 @@ def trigger(self, mapper, position, old_position): - position = self._convert(position, 0, TRIGGER_MAX) + # Need to convert trigger value to stick range for deadzone modifier + # calcs to work as intended + position = self._convert_trigger_stick_range(position, TRIGGER_MAX) + + # Perform dead zone calculations + position = self._convert(position, 0, STICK_PAD_MAX) + + # Convert calculated stick position value back to applicable + # position in trigger range + position = self._convert_stick_trigger_range(position[0]) + # Invoke trigger action with new value return self.action.trigger(mapper, position, old_position) - + def axis(self, mapper, position, what): position = self._convert(position, 0, STICK_PAD_MAX) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/osd/__init__.py new/sc-controller-0.4.8.7/scc/osd/__init__.py --- old/sc-controller-0.4.8.6/scc/osd/__init__.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/osd/__init__.py 2022-05-06 18:39:50.000000000 +0200 @@ -37,7 +37,7 @@ EPILOG = "" css_provider = None # Used by staticmethods - def __init__(self, wmclass): + def __init__(self, wmclass, layer = None): Gtk.Window.__init__(self) OSDWindow._apply_css(Config()) @@ -56,10 +56,13 @@ from gi.repository import GtkLayerShell if GtkLayerShell.is_supported(): self.using_wlroots=True + self.x_layer_anchor = GtkLayerShell.Edge.LEFT + self.y_layer_anchor = GtkLayerShell.Edge.BOTTOM GtkLayerShell.init_for_window(self) - GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP) - GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True) - GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True) + GtkLayerShell.set_layer(self, layer if layer is not None else GtkLayerShell.Layer.TOP) + GtkLayerShell.set_anchor(self, self.x_layer_anchor, True) + GtkLayerShell.set_anchor(self, self.y_layer_anchor, True) + self.layer_shell = GtkLayerShell except (ImportError): pass if not self.using_wlroots: @@ -210,12 +213,26 @@ self.get_window().set_override_redirect(True) x, y = self.compute_position() - if x < 0: # Negative X position is counted from right border - x = Gdk.Screen.width() - self.get_allocated_width() + x + 1 - if y < 0: # Negative Y position is counted from bottom border - y = Gdk.Screen.height() - self.get_allocated_height() + y + 1 - - self.move(x, y) + if self.using_wlroots: + if x < 0: + self.layer_shell.set_anchor(self, self.x_layer_anchor, False) + self.x_layer_anchor = self.layer_shell.Edge.RIGHT + self.layer_shell.set_anchor(self, self.x_layer_anchor, True) + x = -x + if y < 0: + self.layer_shell.set_anchor(self, self.y_layer_anchor, False) + self.y_layer_anchor = self.layer_shell.Edge.BOTTOM + self.layer_shell.set_anchor(self, self.y_layer_anchor, True) + y = -y + self.layer_shell.set_margin(self, self.x_layer_anchor, x) + self.layer_shell.set_margin(self, self.y_layer_anchor, y) + else: # X11 + if x < 0: # Negative X position is counted from right border + x = Gdk.Screen.width() - self.get_allocated_width() + x + 1 + if y < 0: # Negative Y position is counted from bottom border + y = Gdk.Screen.height() - self.get_allocated_height() + y + 1 + self.move(x, y) + Gtk.Window.show(self) self.make_window_clicktrough() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/osd/menu.py new/sc-controller-0.4.8.7/scc/osd/menu.py --- old/sc-controller-0.4.8.6/scc/osd/menu.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/osd/menu.py 2022-05-06 18:39:50.000000000 +0200 @@ -41,8 +41,8 @@ PREFER_BW_ICONS = True - def __init__(self, cls="osd-menu"): - OSDWindow.__init__(self, cls) + def __init__(self, cls="osd-menu", layer = None): + OSDWindow.__init__(self, cls, layer) self.daemon = None self.config = None self.feedback = None @@ -71,7 +71,6 @@ self._confirm_with = 'A' self._cancel_with = 'B' - def set_is_submenu(self): """ Marks menu as submenu. This changes behaviour of some methods, @@ -468,13 +467,20 @@ self._selected = self._submenu._selected self.quit(self._submenu.get_exit_code()) self._submenu = None + if self.using_wlroots: + self.layer_shell.set_layer(self, self.layer_shell.Layer.OVERLAY) def show_submenu(self, trash, trash2, trash3, menuitem): """ Called when user chooses menu item pointing to submenu """ filename = find_menu(menuitem.filename) if filename: - self._submenu = self.__class__() + layer = None + if self.using_wlroots: + if self.layer_shell.is_supported(): + layer = self.layer_shell.Layer.OVERLAY + self.layer_shell.set_layer(self, self.layer_shell.Layer.TOP) + self._submenu = self.__class__(layer = layer) sub_pos = list(self.position) for i in (0, 1): sub_pos[i] = (sub_pos[i] - self.SUBMENU_OFFSET diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/sccdaemon.py new/sc-controller-0.4.8.7/scc/sccdaemon.py --- old/sc-controller-0.4.8.6/scc/sccdaemon.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/sccdaemon.py 2022-05-06 18:39:50.000000000 +0200 @@ -328,7 +328,7 @@ def on_sa_area(self, mapper, action, x1, y1, x2, y2): """ Called when *AreaAction has OSD enabled """ with self.lock: - self._osd('area', '-x', x1, '-y', y1, '--width', x2-x1, '--height', y2-y1) + self._osd('area', '-x', str(x1), '-y', str(y1), '--width', str(x2-x1), '--height', str(y2-y1)) def on_sa_clear_osd(self, *a): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scc/uinput.c new/sc-controller-0.4.8.7/scc/uinput.c --- old/sc-controller-0.4.8.6/scc/uinput.c 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scc/uinput.c 2022-05-06 18:39:50.000000000 +0200 @@ -401,11 +401,13 @@ // supposed to play, effect properties are updated on the fly. if (!ff_effects[rv]->continuous_rumble) { ff_effects[rv]->continuous_rumble = true; + ff_effects[rv]->repetitions = 1; RUMBLE_DEBUG("CONTINUOUS RUMBLE enabled on %i\n", rv); } } else if (ff_effects[rv]->continuous_rumble) { RUMBLE_DEBUG("CONTINUOUS RUMBLE disabled on %i\n", rv); ff_effects[rv]->continuous_rumble = false; + ff_effects[rv]->repetitions = 0; } RUMBLE_DEBUG("FF_PLAY -> %i (type %i, lvl %i, dur. %i, reps. %i)\n", event.code, ff_effects[rv]->type, ff_effects[rv]->level, ff_effects[rv]->duration, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/scripts/appimage-AppRun.sh new/sc-controller-0.4.8.7/scripts/appimage-AppRun.sh --- old/sc-controller-0.4.8.6/scripts/appimage-AppRun.sh 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/scripts/appimage-AppRun.sh 2022-05-06 18:39:50.000000000 +0200 @@ -4,8 +4,8 @@ export LD_LIBRARY_PATH=${APPDIR}/usr/lib64:$LD_LIBRARY_PATH export GI_TYPELIB_PATH=${APPDIR}/usr/lib/girepository-1.0 export GDK_PIXBUF_MODULEDIR=${APPDIR}/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders -export PYTHONPATH=${APPDIR}/usr/lib/python3.9/site-packages:$PYTHONPATH -export PYTHONPATH=${APPDIR}/usr/lib64/python3.9/site-packages:$PYTHONPATH +export PYTHONPATH=${APPDIR}/usr/lib/python3.10/site-packages:$PYTHONPATH +export PYTHONPATH=${APPDIR}/usr/lib64/python3.10/site-packages:$PYTHONPATH export SCC_SHARED=${APPDIR}/usr/share/scc function dependency_check_failed() { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sc-controller-0.4.8.6/setup.py new/sc-controller-0.4.8.7/setup.py --- old/sc-controller-0.4.8.6/setup.py 2021-09-09 20:00:13.000000000 +0200 +++ new/sc-controller-0.4.8.7/setup.py 2022-05-06 18:39:50.000000000 +0200 @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 -from distutils.core import setup, Extension +#!/usr/bin/env python3 +from setuptools import setup, Extension from scc.constants import DAEMON_VERSION import glob