Linux์šฉ Punto Switcher์˜ ์ƒˆ๋กœ์šด ์•„๋‚ ๋กœ๊ทธ: xswitcher

xneur ์ง€์› ์ข…๋ฃŒ๋กœ ์ธํ•ด ์ง€๋‚œ XNUMX๊ฐœ์›” ๋™์•ˆ ์•ฝ๊ฐ„์˜ ๊ณ ํ†ต์„ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. (๋ฐ์Šคํฌํƒ‘์— OpenSUSE 15.1์ด ๋“ฑ์žฅํ•˜๋ฉด์„œ xneur๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ฉด ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์— ๋งž์ถฐ ์ฐฝ์ด ์ดˆ์ ์„ ์žƒ๊ณ  ์ด์ƒํ•˜๊ฒŒ ๊นœ๋ฐ•์ž…๋‹ˆ๋‹ค.).

"์•„, ์  ์žฅ, ๋˜ ์ž˜๋ชป๋œ ๋ ˆ์ด์•„์›ƒ์„ ์ž…๋ ฅํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์–ด์š”." - ๋‚ด ์ž‘์—…์—์„œ๋Š” ์ด๋Ÿฐ ์ผ์ด ์™ธ์„ค์ ์œผ๋กœ ์ž์ฃผ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ๊ธ์ •์ ์ธ ์–ด๋–ค ๊ฒƒ๋„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Linux์šฉ Punto Switcher์˜ ์ƒˆ๋กœ์šด ์•„๋‚ ๋กœ๊ทธ: xswitcher
๋™์‹œ์— ๋‚˜๋Š” (์„ค๊ณ„ ์—”์ง€๋‹ˆ์–ด๋กœ์„œ) ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์„ ์•„์ฃผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ณต์‹ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ €๋Š” ์ •ํ™•ํžˆ ํ•œ ๊ฐ€์ง€๋ฅผ ์›ํ–ˆ์Šต๋‹ˆ๋‹ค(์ฒ˜์Œ์—๋Š” Punto Switcher์—์„œ, ๊ทธ ๋‹ค์Œ์—๋Š” Windows Vista ๋•๋ถ„์— ๋งˆ์นจ๋‚ด xneur์—์„œ Linux๋กœ ์ „ํ™˜). ํ™”๋ฉด์˜ ์“ฐ๋ ˆ๊ธฐ๊ฐ€ ์ž˜๋ชป๋œ ๋ ˆ์ด์•„์›ƒ์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๋‹ค๋ฉด(์ด๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒˆ ๋‹จ์–ด๋ฅผ ์ž…๋ ฅํ•œ ํ›„์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค) "์ผ์‹œ ์ค‘์ง€/์ค‘๋‹จ"์„ ๋ฐŸ์œผ์‹ญ์‹œ์˜ค. ๊ทธ๋ฆฌ๊ณ  ์ธ์‡„ํ•œ ๊ฒƒ์„ ์–ป์œผ์„ธ์š”.

ํ˜„์žฌ ์ด ์ œํ’ˆ์€ (๋‚ด ๊ด€์ ์—์„œ) ์ตœ์ ์˜ ๊ธฐ๋Šฅ/๋ณต์žก์„ฑ ๋น„์œจ์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๊ณต์œ ํ•  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

TL.DR

๋ชจ๋“  ์ข…๋ฅ˜์˜ ๊ธฐ์ˆ ์ ์ธ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ๋‚˜์ค‘์— ๋‚˜์˜ฌ ๊ฒƒ์ด๋ฏ€๋กœ ๋จผ์ € - "๋งŒ์ง€๋‹ค" ๋งํฌ ์ฐธ์„์„ฑ์ด ์—†๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด.

ํ˜„์žฌ ๋‹ค์Œ ๋™์ž‘์ด ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • "์ผ์‹œ ์ค‘์ง€/์ค‘๋‹จ": ๋งˆ์ง€๋ง‰ ๋‹จ์–ด๋ฅผ ๋’ค๋กœ ์ด๋™ํ•˜๊ณ  ํ™œ์„ฑ ์ฐฝ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ „ํ™˜ํ•˜๊ณ (0๊ณผ 1 ์‚ฌ์ด) ๋‹ค์‹œ ์ „ํ™”๋ฅผ ๊ฒ๋‹ˆ๋‹ค.
  • "์•„๋ฌด๊ฒƒ๋„ ์—†์ด ์™ผ์ชฝ Ctrl": ํ™œ์„ฑ ์ฐฝ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค(0๊ณผ 1 ์‚ฌ์ด).
  • โ€œ์•„๋ฌด๊ฒƒ๋„ ์—†์ด ์™ผ์ชฝ Shiftโ€: ํ™œ์„ฑ ์ฐฝ์—์„œ ๋ ˆ์ด์•„์›ƒ ๋ฒˆํ˜ธ 0์„ ์ผญ๋‹ˆ๋‹ค.
  • โ€œ์•„๋ฌด๊ฒƒ๋„ ์—†์ด ์˜ค๋ฅธ์ชฝ Shiftโ€: ํ™œ์„ฑ ์ฐฝ์—์„œ ๋ ˆ์ด์•„์›ƒ 1๋ฒˆ์„ ์ผญ๋‹ˆ๋‹ค.

์ด์ œ๋ถ€ํ„ฐ๋Š” ๋™์ž‘์„ ๋งž์ถค์„ค์ •ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค. ํ”ผ๋“œ๋ฐฑ์ด ์—†์œผ๋ฉด ์žฌ๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค(์–ด์จŒ๋“  ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค). ๋‚˜๋Š” Habrรฉ์—์„œ ๋น„์Šทํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง„ ์ฒญ์ค‘์˜ ๋น„์œจ์ด ์ถฉ๋ถ„ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค.

NB ์™œ๋ƒํ•˜๋ฉด ํ˜„์žฌ ๋ฒ„์ „์—์„œ๋Š” ํ‚ค๋กœ๊ฑฐ๊ฐ€ "/dev/input/"์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์œผ๋ฉฐ xswitcher๋Š” ๋ฃจํŠธ ๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

chown root:root xswitcher
chmod +xs xswitcher

์ฐธ๊ณ  : suid๊ฐ€ ํฌํ•จ๋œ ํŒŒ์ผ์˜ ์†Œ์œ ์ž๋Š” ๋ฃจํŠธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์†Œ์œ ์ž๊ฐ€ ๋ˆ„๊ตฌ์ด๋“  ์‹œ์ž‘ ์‹œ suid๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.

ํŽธ์ง‘์ฆ(์ €๋„ ์˜ˆ์™ธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค)์€ ๋‹ค์Œ์—์„œ ๋ณต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. GIT ๊ทธ๋ฆฌ๊ณ  ํ˜„์žฅ์—์„œ ์กฐ๋ฆฝํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ:

go get "github.com/micmonay/keybd_event"
go get "github.com/gvalkov/golang-evdev"

### X11 headers for OpenSUSE/deb-based
zypper install libX11-devel libXmu-devel
apt-get install libx11-dev libxmu-dev

cd "x switcher/src/"
go build -o xswitcher -ldflags "-s -w" --tags static_all src/*.go

์ทจํ–ฅ์— ๋”ฐ๋ผ ์ž๋™ ์‹œ์ž‘์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(DE์— ๋”ฐ๋ผ ๋‹ค๋ฆ„).

์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. "์ฃฝ์„ ์š”๊ตฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค"(30์ผ CPU 12์ดˆ, RSS XNUMXMB).

์„ธ๋ถ€

์ด์ œ - ์„ธ๋ถ€ ์‚ฌํ•ญ.

์ „์ฒด ์ €์žฅ์†Œ๋Š” ์›๋ž˜ ๋‚ด ์• ์™„ ๋™๋ฌผ ํ”„๋กœ์ ํŠธ ์ „์šฉ์ด์—ˆ๊ณ  ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด ๊ฒŒ์œผ๋ฅด๋‹ค. ๊ทธ๋ž˜์„œ ๋ชจ๋“  ๊ฒƒ์ด (ํด๋”์—๋งŒ) ์Œ“์—ฌ ์žˆ๊ณ  AGPL(โ€œ์—ญํŠนํ—ˆโ€)๋กœ ๋ณดํ˜ธ๋ฉ๋‹ˆ๋‹ค.

xswitcher ์ฝ”๋“œ๋Š” C๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ํฌํ•จํ•˜๊ณ  golang์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ์†Œํ•œ์˜ ๋…ธ๋ ฅ๋งŒ ๋“ค์ธ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค(์ง€๊ธˆ๊นŒ์ง€). cgo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ˆ„๋ฝ๋œ ๋ถ€๋ถ„์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์œ ์ง€ํ•˜๋ฉด์„œ.

ํ…์ŠคํŠธ์—๋Š” ๋นŒ๋ฆฐ ๊ณณ๊ณผ ์ด์œ ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด xneur ์ฝ”๋“œ๋Š” "๋‚˜์—๊ฒŒ ์˜๊ฐ์„ ์ฃผ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค", ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ถœ๋ฐœ์ ์œผ๋กœ ์‚ผ์•˜์Šต๋‹ˆ๋‹ค ๋กค๋กœ์Šค์œ„์น˜.

"/dev/input/"์„ ์‚ฌ์šฉํ•˜๋ฉด ์žฅ์ (๋ˆ„๋ฅธ ์ž๋™ ๋ฐ˜๋ณต ํ‚ค๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์ด ํ‘œ์‹œ๋จ)๊ณผ ๋‹จ์ ์ด ๋ชจ๋‘ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ž๋™ ๋ฐ˜๋ณต(์ฝ”๋“œ "2"๊ฐ€ ์žˆ๋Š” ์ด๋ฒคํŠธ)์€ x์™€์˜ ๋ฐ˜๋ณต๊ณผ ์ƒ๊ด€ ๊ด€๊ณ„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • X11 ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ์ž…๋ ฅ์€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด VNC๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹).
  • ๋ฃจํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์— "XSelectExtensionEvent()"๋ฅผ ํ†ตํ•ด X ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์—ฟ๋ณผ ์ˆ˜ ์žˆ๋‹ค x์ž…๋ ฅ ์ฝ”๋“œ. ๋‚˜๋Š” go์—์„œ ์ด์™€ ๊ฐ™์€ ๊ฒƒ์„ ์ฐพ์ง€ ๋ชปํ–ˆ๊ณ  ๋Œ€๋žต์ ์ธ ๊ตฌํ˜„์—๋Š” ์ฆ‰์‹œ XNUMX์ค„์˜ C ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ๋”ฐ๋กœ ๋ณด๊ด€ํ•ด ๋‘์„ธ์š”.

"์—ญ๋ฐฉํ–ฅ" ์ถœ๋ ฅ์€ ํ˜„์žฌ ๊ฐ€์ƒ ํ‚ค๋ณด๋“œ๋ฅผ ์กฐ์ด๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. keybd_event์˜ ์ž‘์„ฑ์ž์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ถ”์ƒํ™” ์ˆ˜์ค€์ด ๋„ˆ๋ฌด ๋†’์•„ ์ถ”๊ฐ€๋กœ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์˜ค๋ฅธ์ชฝ Win ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ธ ๋ฒˆ์งธ ํ–‰์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์™ผ์ชฝ Win๋งŒ ๋‹ค์‹œ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.

์•Œ๋ ค์ง„ ๋ฒ„๊ทธ

  • ์šฐ๋ฆฌ๋Š” "๋ณตํ•ฉ" ์ž…๋ ฅ(์˜ˆ: ยฝ)์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ์˜ฌ๋ฐ”๋ฅธ ์Šน๋ฆฌ๋ฅผ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ ๊ฒฝ์šฐ์—๋Š” ๊ฐ•์กฐ๊ฐ€ ๊นจ์กŒ์Šต๋‹ˆ๋‹ค.
  • ๋ช…ํ™•ํ•œ ์ž…๋ ฅ ๊ตฌ๋ฌธ ๋ถ„์„์ด ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  Compare(), CtrlSequence(), RepeatSequence(), SpaceSequence()์™€ ๊ฐ™์€ ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌ nsmcan ์ฃผ์˜ ์‚ฌํ•ญ: ์ฝ”๋“œ์™€ ์—ฌ๊ธฐ์—์„œ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ผ์ • ํ™•๋ฅ ๋กœ ๊ต์ฒด ์‹œ ๋ฒ„๊ทธ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ํ˜„ ์‹œ์ ์—์„œ๋Š” "๋ฐฉ๋ฒ•"์„ ์•Œ์ง€ ๋ชปํ•˜๋ฏ€๋กœ ์–ด๋–ค ์ œ์•ˆ์ด๋ผ๋„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.
  • (์˜ค ๋ง™์†Œ์‚ฌ) ์ฑ„๋„์˜ ๊ฒฝ์Ÿ์  ์‚ฌ์šฉ(keyboardEvents, mouseEvents)

๊ฒฐ๋ก 

์ฝ”๋“œ๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์ ˆ์ฐจ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์ฒ˜๋Ÿผ ๋ฉ์ฒญํ•ด์š”. ๊ทธ๋ž˜์„œ ๋‚˜๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ๊ธฐ์ˆ ์ž๊ฐ€ ์ž์‹ ์ด ์›ํ•˜๋Š” ๊ฒƒ์„ ์™„์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ๋Š” ํฌ๋ง์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋•๋ถ„์— ์ด ์ œํ’ˆ์€ ๋Œ€๋ถ€๋ถ„์˜ ์žฌ๋ฏธ์šฉ ์ œํ’ˆ์ฒ˜๋Ÿผ ์ง€์› ์—†์ด๋Š” ์‚ฌ๋ผ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ–‰์šด์„ ๋น•๋‹ˆ๋‹ค!

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€