Repository: pwr-Solaar/Solaar

Issue:
Enabling HID++ Scrolling toogle disables scrolling - is this expected behaviour?
**Information**
- Version: 1.02 (installed from PPA)
- Distribution: Ubuntu 18.04.3 LTS
- Kernel version (ex. `uname -srmo`): `Linux 5.3.0-7648-generic x86_64 GNU/Linux`
- Output of `solaar show`:
```
$ solaar show
Nano Receiver
  Device path  : /dev/hidraw1
  USB id       : 046d:c534
  Serial       : None
    Firmware   : 29.01.B0016
  Has 1 paired device(s) out of a maximum of 2.
  Has 19 successful pairing(s) remaining.
  Notifications: wireless, software present (0x000900)

  2: Wireless Mouse M185 new
     Codename     : M185n
     Kind         : mouse
     Wireless PID : 4054
     Protocol     : HID++ 4.5
     Polling rate : 8 ms (125Hz)
     Serial number: 00000000
          Firmware: RQM 64.00.B0008
     The power switch is located on the base.
     Supports 20 HID++ 2.0 features:
         0: ROOT                   {0000}   
         1: FEATURE SET            {0001}   
         2: DEVICE FW VERSION      {0003}   
         3: DEVICE NAME            {0005}   
         4: RESET                  {0020}   
         5: REPROG CONTROLS V4     {1B04}   
            Actions: {'80': 80, '81': 81, '82': 82}
         6: WIRELESS DEVICE STATUS {1D4B}   
         7: LOWRES WHEEL           {2130}   
            HID++ Scrolling: False
         8: POINTER SPEED          {2205}   
            Pointer Speed: 1.0
         9: DEVICE RESET           {1802}   internal, hidden
        10: unknown:1810           {1810}   internal, hidden
        11: unknown:1830           {1830}   internal, hidden
        12: unknown:1850           {1850}   internal, hidden
        13: unknown:1869           {1869}   internal, hidden
        14: unknown:1890           {1890}   internal, hidden
        15: unknown:18B1           {18B1}   internal, hidden
        16: unknown:1DF3           {1DF3}   internal, hidden
        17: unknown:1E00           {1E00}   hidden
        18: unknown:1F03           {1F03}   internal, hidden
        19: unknown:1E80           {1E80}   internal, hidden
     Has 3 reprogrammable keys:
         0: LEFT CLICK                , default: LeftClick                   => LEFT CLICK                
             mse, reprogrammable, pos:0, group:1, gmask:1
         1: RIGHT CLICK               , default: RightClick                  => RIGHT CLICK               
             mse, reprogrammable, pos:0, group:1, gmask:1
         2: Middle Button             , default: Mouse Middle Button         => Middle Button             
             mse, reprogrammable, divertable, pos:0, group:2, gmask:3
     Battery status unavailable.
```

**Describe the bug**
Choosing the HID++ Scrolling button (from OFF -> ON) disables all scrolling. Is this the expected bug?

**To Reproduce**
Steps to reproduce the behavior:
1. Go to 'SOLAAR GUI Dialogue'
2. Click on 'M185n>HID++ Scrolling (OFF->ON)'
3. Scrolling with the wheel becomes disabled. Switching HID++ Scrolling (ON->OFF) restores scrolling.

**Screenshots**
If applicable, add screenshots to help explain your problem.
![image](https://user-images.githubusercontent.com/1056700/85302255-eb987800-b476-11ea-8f51-fe9a5f47338e.png)



Discussion:
@cement-head Yes, it was expected. Linux mouse drivers not aware of HID++ scrolling events and this feature only useful to disable HID++ scrolling if it was enabled. 
It noted in documentation, in https://pwr-solaar.github.io/Solaar/devices 
"(note): Currently, smooth scrolling events are not processed in xfce and this setting is useful only to disable smooth scrolling."

Resolving patch:
diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py
--- a/lib/logitech_receiver/settings_templates.py
+++ b/lib/logitech_receiver/settings_templates.py
@@ -187,8 +187,8 @@ def feature_range(name, feature, min_value, max_value,
                                                       "instead of the standard side-scrolling events."))
 _HI_RES_SCROLL = ('hi-res-scroll', _("High Resolution Scrolling"),
 							_("High-sensitivity mode for vertical scroll with the wheel."))
-_LOW_RES_SCROLL = ('lowres-smooth-scroll', _("HID++ Scrolling"),
-							_("HID++ mode for vertical scroll with the wheel."))
+_LOW_RES_SCROLL = ('lowres-smooth-scroll', _("HID++ Scrolling"), _("HID++ mode for vertical scroll with the wheel.") + '\n' +
+							_("Effectively turns off wheel scrolling in Linux."))
 _HIRES_INV = ('hires-smooth-invert', _("High Resolution Wheel Invert"),
 							_("High-sensitivity wheel invert mode for vertical scroll."))
 _HIRES_RES = ('hires-smooth-resolution', _("Wheel Resolution"),
@@ -199,11 +199,12 @@ def feature_range(name, feature, min_value, max_value,
 						 	_("When unset, the F1..F12 keys will activate their standard function,\n"
 						 	"and you must hold the FN key to activate their special function."))
 _DPI = ('dpi', _("Sensitivity (DPI)"), None)
-_POINTER_SPEED = ('pointer_speed', _("Sensitivity (Pointer Speed)"), None)
+_POINTER_SPEED = ('pointer_speed', _("Sensitivity (Pointer Speed)"), _("Speed multiplier for mouse (256 is normal multiplier)."))
 _SMART_SHIFT = ('smart-shift', _("Smart Shift"), _("Automatically switch the mouse wheel between ratchet and freespin mode.\n"
 							"The mouse wheel is always free at 0, and always locked at 50"))
 _BACKLIGHT = ('backlight', _("Backlight"), _("Turn illumination on or off on keyboard."))
-_REPROGRAMMABLE_KEYS = ('reprogrammable-keys', _("Actions"), _("Change the action for the key"))
+_REPROGRAMMABLE_KEYS = ('reprogrammable-keys', _("Actions"), _("Change the action for the key or button.") + "\n" +
+						_("Changing important actions (such as for the left mouse button) can result in an unusable system."))
 _DISABLE_KEYS = ('disable-keyboard-keys', _("Disable keys"), _("Disable specific keyboard keys."))
 
 #
@@ -368,6 +369,7 @@ def _feature_pointer_speed():
 # the keys for the choice map are Logitech controls (from special_keys)
 # each choice value is a NamedInt with the string from a task (to be shown to the user)
 # and the integer being the control number for that task (to be written to the device)
+# Solaar only remaps keys (controlled by key gmask and group), not other key reprogramming
 def _feature_reprogrammable_keys_choices(device):
 	count = device.feature_request(_F.REPROG_CONTROLS_V4)
 	assert count, 'Oops, reprogrammable key count cannot be retrieved!'
@@ -382,9 +384,10 @@ def _feature_reprogrammable_keys_choices(device):
 		keys[i] = ( _special_keys.CONTROL[key], action, flags, gmask )
 		groups[group].append(action)
 	for k in keys:
-		if k[2] & _special_keys.KEY_FLAG.reprogrammable:
+		# if k[2] & _special_keys.KEY_FLAG.reprogrammable:  # this flag is only to show in UI, ignore in Solaar
+		if k[3]: # only keys with a non-zero gmask are remappable
 			key_choices = [ k[1] ] # it should always be possible to map the key to itself
-			for g in range(1,9): # group 0 and gmask 0 (k[3]) don't appear to work, don't consider group 0
+			for g in range(1,9): # group 0 and gmask 0 (k[3]) does not indicate remappability so don't consider group 0
 				if ( k[3]==0 if g==0 else k[3] & 2**(g-1) ):
 					for gm in groups[g]:
 						if int(gm) != int(k[0]): # don't put itself in twice
diff --git a/lib/logitech_receiver/special_keys.py b/lib/logitech_receiver/special_keys.py
--- a/lib/logitech_receiver/special_keys.py
+++ b/lib/logitech_receiver/special_keys.py
@@ -105,8 +105,8 @@
 	PAUSE_BREAK=0x004D,
 	SCROLL_LOCK=0x004E,
 	CONTEXTUAL_MENU=0x004F,
-	LEFT_CLICK=0x0050,
-	RIGHT_CLICK=0x0051,
+	Left_Button=0x0050,		# LEFT_CLICK
+	Right_Button=0x0051,		# RIGHT_CLICK
 	Middle_Button=0x0052,		# MIDDLE_BUTTON
 	Back_Button=0x0053,		# from M510v2 was BACK_AS_BUTTON_4
     	Back=0x0054,			# BACK_AS_HID
@@ -274,8 +274,8 @@
 	ZoomBtnOutSet2=0x0035,
 	ZoomBtnOutSet=0x0036,
 	ZoomBtnResetSet=0x0037,
-	LeftClick=0x0038,
-	RightClick=0x0039,
+	Left_Click=0x0038,		# LeftClick
+	Right_Click=0x0039,		# RightClick
 	Mouse_Middle_Button=0x003A,	# from M510v2 was MiddleMouseButton
 	Back=0x003B,
 	Mouse_Back_Button=0x003C,	# from M510v2 was BackEx


Test patch: