{"componentChunkName":"component---src-lekoarts-gatsby-theme-minimal-blog-core-templates-post-query-tsx","path":"/ubuntu-18-04-remap-mouse-buttons","result":{"data":{"post":{"slug":"/ubuntu-18-04-remap-mouse-buttons","title":"Ubuntu 18.04 Remap mouse buttons","date":"August 12, 2019","tags":[{"name":"Ubuntu","slug":"ubuntu"}],"description":null,"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Ubuntu 18.04 Remap mouse buttons\",\n  \"date\": \"2019-08-12T00:00:00.000Z\",\n  \"tags\": [\"Ubuntu\"],\n  \"excerpt\": \"Remap buttons on a *wireless* mouse\"\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"h2\", null, \"Goals:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Write a script to remap mouse buttons\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Run the script when the wireless mouse is connected\")), mdx(\"hr\", null), mdx(\"p\", null, \"This is my mouse:\"), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://cdn.jsdelivr.net/gh/Deerhound579/image-hosting/img/mouse.jpg\",\n    \"alt\": \"mouse\"\n  }))), mdx(\"p\", null, \"The default right-click is the bottom right button, but I would like to use the top right button instead.\"), mdx(\"h2\", null, \"Remap mouse buttons\"), mdx(\"p\", null, \"First, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"xinput\"), \" gives the id and name assigned to my mouse. Then, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"xinput list 18(device id)\"), \" gives information about all buttons on my mouse.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-shell\"\n  }), \"$ xinput\\n...\\n\\u239C   \\u21B3 Expert Wireless TB Mouse                  id=18   [slave  pointer  (2)]\\n\\n$ xinput list 18\\nExpert Wireless TB Mouse                    id=18   [slave  pointer  (2)]\\n    Reporting 7 classes:\\n        Class originated from: 18. Type: XIButtonClass\\n        Buttons supported: 9\\n        Button labels: \\\"Button Left\\\" \\\"Button Middle\\\" \\\"Button Right\\\" \\\"Button Wheel Up\\\" \\\"Button Wheel Down\\\" \\\"Button Horiz Wheel Left\\\" \\\"Button Horiz Wheel Right\\\" \\\"Button Side\\\" \\\"Button Extra\\\"\\n\")), mdx(\"p\", null, \"However, the labels are quite confusing. To find out which button is pressed, run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"xinput test 18(device id)\"), \" and press buttons you want to switch.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"$ xinput test 18\\nbutton press   8\\nbutton release 8\\nbutton press   3\\nbutton release 3\\n\")), mdx(\"p\", null, \"This is much clearer than the \\u201CButton Side\\u201D. To remap buttons, simply use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"xinput set-button-map $mouse_id 1 2 8 4 5 6 7 3 9\"), \" which switches \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"3\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"8\"), \".\"), mdx(\"hr\", null), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Problem:\"), \" When I restart the laptop, everything goes back to the default settings. With the help of \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://askubuntu.com/questions/492744/how-do-i-automatically-remap-buttons-on-my-mouse-at-startup\"\n  }), \"StackOverflow\"), \", I created a script called \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"remap_mouse_buttons.sh\"), \":\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"mouse_id=$(xinput list | grep \\\"Expert Wireless TB Mouse\\\" | sed 's/^.*id=\\\\([0-9]*\\\\)[ \\\\t].*/\\\\1/')\\nxinput set-button-map $mouse_id 1 2 8 4 5 6 7 3 9\\n\")), mdx(\"p\", null, \"I added this to the Start Up Applications. Unfortunately, this didn\\u2019t work because if I didn\\u2019t connect the mouse when the computer started, the system wouldn\\u2019t find the device let alone remap buttons.\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"NOTE:\"), \" I highly recommend you keep track of the error message by changing the second line to:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"xinput set-button-map $mouse_id  1 2 8 4 5 6 7 3 9 2>&1 | sudo tee /home/yourusername/error.txt\\n\")), mdx(\"p\", null, \"Additional resources:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean\"\n  }), \"Details on 2>&1\"))), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://stackoverflow.com/questions/82256/how-do-i-use-sudo-to-redirect-output-to-a-location-i-dont-have-permission-to-wr\"\n  }), \"How to avoid \\u201CPermission denied\\u201D when redirecting\")))), mdx(\"h2\", null, \"Run the script when the mouse is connected\"), mdx(\"p\", null, \"What I should do is executing the script when the mouse is connected via Bluetooth. \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://wiki.debian.org/udev\"\n  }), \"udev\"), \" rules are perfect for this job.\"), mdx(\"p\", null, \"This \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://linuxconfig.org/tutorial-on-how-to-write-basic-udev-rules-in-linux\"\n  }), \"tutorial\"), \" on how to write basic udev rules helped me a lot.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"# Where custom made rules are\\n$ cd /etc/udev/rules.d/\\n# The naming convention is xx-description.rules. \\\"xx\\\" is a number, and the larger it is, the later it will be executed\\n$ sudo touch 88-remapmouse.rules\\n\")), mdx(\"p\", null, \"Before writing rules, we need to gather information about the device. Run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"udevadm monitor\"), \" and reconnect the device to get its path. Then, run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"udevadm info\"), \" to get detailed information.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"$udevadm monitor\\nmonitor will print the received events for:\\nUDEV - the event which udev sends out after rule processing\\nKERNEL - the kernel uevent\\n\\nKERNEL[8572.460135] remove   /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:3585 (bluetooth)\\nKERNEL[8572.465756] add      /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:3585 (bluetooth)\\nUDEV  [8572.525910] remove   /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:3585 (bluetooth)\\nUDEV  [8572.582738] add      /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:3585 (bluetooth)\\n\\n# The output has been truncated\\n$ udevadm info -ap /devices/pci0000:00/00:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:3585\\n...\\nlooking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/bluetooth/hci0/hci0:3585':\\n    KERNEL==\\\"hci0:3585\\\"\\n    SUBSYSTEM==\\\"bluetooth\\\"\\n    DRIVER==\\\"\\\"\\n    ...\\nlooking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-7':\\n    KERNELS==\\\"1-7\\\"\\n    SUBSYSTEMS==\\\"usb\\\"\\n    DRIVERS==\\\"usb\\\"\\n    ...\\n    ATTRS{idProduct}==\\\"0a2b\\\"\\n    ATTRS{idVendor}==\\\"8087\\\"\\n    ...\\n\")), mdx(\"p\", null, \"Now we have enough info to write the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"88-remapmouse.rules\"), \":\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"ACTION==\\\"add\\\",\\\\\\nSUBSYSTEMS==\\\"usb\\\",\\\\\\nATTRS{idProduct}==\\\"0a2b\\\",\\\\\\nATTRS{idVendor}==\\\"8087\\\",\\\\\\nENV{DISPLAY}=\\\":0.0\\\",\\\\\\nENV{XAUTHORITY}=\\\"/run/user/1000/gdm/Xauthority\\\",\\\\\\nRUN+=\\\"/home/lisixian/remap_mouse.sh\\\"\\n\")), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"==\"), \" match the value\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"=\"), \" assign a value (overwrite)\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"+=\"), \" add another value\"), mdx(\"p\", null, \"The script seems daunting, but what it says is simply \\u201CWhen the device with matching values is detected(connected), run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"/home/lisixian/remap_mouse.sh\"), \" (the script in the first section)\\u201C.\"), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"NOTE:\"), \" \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ENV{DISPLAY}=\\\":0.0\\\"\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ENV{XAUTHORITY}=\\\"/run/user/1000/gdm/Xauthority\"), \" are important. From the tutorial:\"), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Those variables are essential when interacting with the X server programmatically, to setup some needed information: with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"DISPLAY\"), \" variable, we specify on what machine the server is running, what display and what screen we are referencing, and with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"XAUTHORITY\"), \" we provide the path to the file which contains Xorg authentication and authorization information.\")), mdx(\"p\", null, \"I got \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Cannot connect to X server\"), \" error without these two lines.\"), mdx(\"p\", null, \"Finally!\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"udevadm control --reload # reload all rules\\n\")), mdx(\"p\", null, \"Now, disconnect your device and connect again to see the results.\"));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"Remap buttons on a *wireless* mouse","banner":null}},"pageContext":{"slug":"/ubuntu-18-04-remap-mouse-buttons"}}}