{"id":79737,"date":"2020-04-30T07:41:58","date_gmt":"2020-04-30T05:41:58","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/novyj-analog-punto-switcher-dlya-linux-xswitcher"},"modified":"2020-04-30T07:41:58","modified_gmt":"2020-04-30T05:41:58","slug":"novyj-analog-punto-switcher-dlya-linux-xswitcher","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/novyj-analog-punto-switcher-dlya-linux-xswitcher","title":{"rendered":"A new alternative to Punto Switcher for Linux: xswitcher","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>The discontinuation of support for xneur has caused me some distress over the past six months. <i>(with the introduction of OpenSUSE 15.1 on my desktops: when xneur is enabled, windows lose focus and amusingly flicker in sync with keyboard input)<\/i>.<\/p>\n<p>\"Ah, damn, I started typing in the wrong layout again\" \u2014 this happens to me alarmingly often at work. It doesn't add any positivity.<\/p>\n<p><img decoding=\"async\" alt=\"A new alternative to Punto Switcher for Linux: xswitcher\" src=\"\/wp-content\/uploads\/2020\/04\/d296936e3aedb8e94ba4c26522ffe72b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nAt the same time, I (as a design engineer) can clearly articulate what I want. And what I wanted (first from Punto Switcher, and then, thanks to Windows Vista, finally switching to Linux, from xneur) was just one thing. Realizing that the screen is filled with nonsense in the wrong layout (this usually occurs at the end of typing a new word), I want to hit 'Pause\/Break'. And get what I was typing.<\/p>\n<p>Currently, the product has an optimal (from my perspective) functionality\/complexity ratio. It's time to share.<\/p>\n<h2>TL;DR<\/h2>\n<p>\nNext will be some technical details, so first \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ds-voix\/VX-PBX\/blob\/master\/x%20switcher\/bin\/xswitcher\">a link 'to touch'<\/a><\/noindex> for the impatient.<\/p>\n<p>At the moment, the following behavior is hardcoded:<\/p>\n<ul>\n<li>\"Pause\/Break\": deletes (Backspace) the last word, switches the layout in the active window (between 0 and 1) and types again.<\/li>\n<li>\"Left Ctrl without anything\": switches the layout in the active window (between 0 and 1).<\/li>\n<li>\"Left Shift without anything\": enables layout #0 in the active window.<\/li>\n<li>\"Right Shift without anything\": enables layout #1 in the active window.<\/li>\n<\/ul>\n<p>\nFrom this moment, I plan to customize the behavior. Without feedback \u2014 it's not interesting (I'm already satisfied). I believe there will be a sufficient percentage of the audience on Habr with similar problems.<\/p>\n<p><b>N.B.<\/b> Since the current version of the keylogger is attached to \"\/dev\/input\/\", xswitcher must be run with root privileges:<\/p>\n<pre><code class=\"bash\">chown root:root xswitcher\nchmod +xs xswitcher<\/code><\/pre>\n<p>\n<b>Please note:<\/b> the file with suid must be owned by root, as whoever is the owner will turn it into suid upon execution.<\/p>\n<p>Paranoids (I am no exception) can clone from <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ds-voix\/VX-PBX\">GIT<\/a><\/noindex> and build on site. Something like this:<\/p>\n<pre><code class=\"bash\">go get \"github.com\/micmonay\/keybd_event\"\ngo get \"github.com\/gvalkov\/golang-evdev\"\n\n### X11 headers for OpenSUSE\/deb-based\nzypper install libX11-devel libXmu-devel\napt-get install libx11-dev libxmu-dev\n\ncd \"x switcher\/src\/\"\ngo build -o xswitcher -ldflags \"-s -w\" --tags static_all src\/*.go\n<\/code><\/pre>\n<p>\nAdd autostart as desired (depending on DE).<\/p>\n<p>Works, \"doesn't ask for porridge\" (\u224830 seconds CPU per day, \u224812 MB in RSS).<\/p>\n<h2>Details<\/h2>\n<p>\nNow \u2014 details.<\/p>\n<p><i>The entire repository was initially dedicated to my pet project, and I'm too lazy to start another one for now. So everything is piled up (just in folders) and covered by AGPL (the 'reverse patent').<\/i><\/p>\n<p>The xswitcher code is written in golang, with minimal C integrations. This approach is expected to require the least labor (and so far it has). It maintains the ability to connect missing parts through cgo.<\/p>\n<p>The text includes comments explaining where I borrowed various elements from and why. Since the xneur code did not 'inspire me', I used <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/xintrea\/LoLoSwitcher\">loloswitcher<\/a><\/noindex>.<\/p>\n<p>Using \"\/dev\/input\/\" has its advantages (everything is visible including a pressed key with autorepeat) and disadvantages. The disadvantages are:<\/p>\n<ul>\n<li>Auto-repeat (events with code '2') does not correlate with repeats from X.<\/li>\n<li>Input via X11 interfaces is not visible (as VNC operates, for example).<\/li>\n<li>Root access is required.<\/li>\n<\/ul>\n<p>\nOn the other hand, you can subscribe to X events through 'XSelectExtensionEvent()'. You can see this in the <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/freedesktop\/xorg-xinput\/blob\/master\/src\/test.c\">xinput code<\/a><\/noindex>. I didn't find a similar solution for go, and the draft implementation produced an immediate hundred lines of C code. For now, I've put it aside.<\/p>\n<p>The 'reverse' output has been done by attaching a virtual keyboard. Thanks to the author of keybd_event, but that's a very high-level abstraction, and I'll have to redo it later. For example, my right Win key selects the third row. The left Win key is the only one that translates back.<\/p>\n<h2>Known issues<\/h2>\n<p><\/p>\n<ul>\n<li>We don't know anything about 'composite' input (e.g., \u00bd). <i>It isn't needed right now.<\/i><\/li>\n<li>The right Win is incorrectly reproduced. In my case, it breaks the placement of accents.<\/li>\n<li>There is no clear analysis of input. Instead, there are several functions: Compare(), CtrlSequence(), RepeatSequence(), SpaceSequence(). <i>Thank you <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/users\/nsmcan\/\" class=\"user_link\">nsmcan<\/a><\/noindex> for your attention: I fixed it in the code and here.<\/i> With a certain probability, bugs can be caught during replacement.<br \/>\n<b>At this point, I don't know 'how it's supposed to be' and I would welcome any suggestions.<\/b><\/li>\n<li><i>(Oh horror)<\/i> concurrent use of channels (keyboardEvents, miceEvents).<\/li>\n<\/ul>\n<p><\/p>\n<h2>Conclusion<\/h2>\n<p>\nThe code is the simplest procedural one. <i>And as blunt as I am.<\/i> So I comfort myself with the hope that any technician can complete the desired features. This product thus won't vanish without support like most just-for-fun projects.<\/p>\n<p>Good luck!<br \/>\n<br \/>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/495748\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 xneur \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u0443 \u043c\u0435\u043d\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 (\u0441 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c OpenSUSE 15.1 \u043d\u0430 \u043c\u043e\u0438\u0445 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u0430\u0445: \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u043e\u043c xneur \u043e\u043a\u043d\u0430 \u0442\u0435\u0440\u044f\u044e\u0442 \u0444\u043e\u043a\u0443\u0441 \u0438 \u0437\u0430\u0431\u0430\u0432\u043d\u043e \u043c\u0435\u0440\u0446\u0430\u044e\u0442 \u0432 \u0442\u0430\u043a\u0442 \u0432\u0432\u043e\u0434\u0430 \u0441 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b). \u00ab\u0410, \u0431\u043b\u0438\u043d, \u043e\u043f\u044f\u0442\u044c \u043d\u0435 \u0432 \u0442\u043e\u0439 \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u043a\u0435 \u043d\u0430\u0447\u0430\u043b \u043d\u0430\u0431\u0438\u0440\u0430\u0442\u044c\u00bb \u2014 \u0432 \u043c\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u043d\u0435\u043f\u0440\u0438\u043b\u0438\u0447\u0438\u044f \u0447\u0430\u0441\u0442\u043e. \u0418 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u0430 \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442. \u0412 \u0442\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":79738,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-79737","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 xneur \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u0443 \u043c\u0435\u043d\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 (\u0441 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c OpenSUSE 15.1 \u043d\u0430 \u043c\u043e\u0438\u0445 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u0430\u0445: \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u043e\u043c xneur \u043e\u043a\u043d\u0430 \u0442\u0435\u0440\u044f\u044e\u0442 \u0444\u043e\u043a\u0443\u0441 \u0438 \u0437\u0430\u0431\u0430\u0432\u043d\u043e \u043c\u0435\u0440\u0446\u0430\u044e\u0442 \u0432 \u0442\u0430\u043a\u0442 \u0432\u0432\u043e\u0434\u0430 \u0441.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/novyj-analog-punto-switcher-dlya-linux-xswitcher\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041d\u043e\u0432\u044b\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 Punto Switcher \u0434\u043b\u044f linux: xswitcher | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 xneur \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u0443 \u043c\u0435\u043d\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 (\u0441 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c OpenSUSE 15.1 \u043d\u0430 \u043c\u043e\u0438\u0445 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u0430\u0445: \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u043e\u043c xneur \u043e\u043a\u043d\u0430 \u0442\u0435\u0440\u044f\u044e\u0442 \u0444\u043e\u043a\u0443\u0441 \u0438 \u0437\u0430\u0431\u0430\u0432\u043d\u043e \u043c\u0435\u0440\u0446\u0430\u044e\u0442 \u0432 \u0442\u0430\u043a\u0442 \u0432\u0432\u043e\u0434\u0430 \u0441.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/novyj-analog-punto-switcher-dlya-linux-xswitcher\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-04-30T05:41:58+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-30T05:41:58+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47A new alternative to Punto Switcher for Linux: xswitcher | ProHoster","description":"The termination of xneur support has caused me some distress over the past six months (since the release of OpenSUSE 15.1 on my desktops: with xneur enabled, windows lose focus and amusingly flicker in time with the input).","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/novyj-analog-punto-switcher-dlya-linux-xswitcher","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041d\u043e\u0432\u044b\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 Punto Switcher \u0434\u043b\u044f linux: xswitcher | ProHoster","og:description":"\u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 xneur \u0432\u044b\u0437\u0432\u0430\u043b\u043e \u0443 \u043c\u0435\u043d\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 (\u0441 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c OpenSUSE 15.1 \u043d\u0430 \u043c\u043e\u0438\u0445 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u0430\u0445: \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u043e\u043c xneur \u043e\u043a\u043d\u0430 \u0442\u0435\u0440\u044f\u044e\u0442 \u0444\u043e\u043a\u0443\u0441 \u0438 \u0437\u0430\u0431\u0430\u0432\u043d\u043e \u043c\u0435\u0440\u0446\u0430\u044e\u0442 \u0432 \u0442\u0430\u043a\u0442 \u0432\u0432\u043e\u0434\u0430 \u0441.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/novyj-analog-punto-switcher-dlya-linux-xswitcher","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-04-30T05:41:58+00:00","article:modified_time":"2020-04-30T05:41:58+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"79737","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:32:22","updated":"2022-09-30 15:31:31","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/79737","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=79737"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/79737\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/79738"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=79737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=79737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=79737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}