จะทำให้แอพพลิเคชั่นทั้งหมดเป็นไปตามเค้าโครง xkb ที่ฉันแก้ไขหรือไม่


11

ฉันไม่ชอบกระโดดไปมาระหว่างแป้นพิมพ์หลักและปุ่มเคลื่อนไหวดังนั้นฉันจึงเพิ่มสิ่งต่อไปนี้ลงในไฟล์เลย์เอาต์ xkb ของฉัน

hidden partial xkb_symbols "movement"
{
    key <AD08> { [ NoSymbol, NoSymbol, Up,          Up          ] };
    key <AC08> { [ NoSymbol, NoSymbol, Down,        Down        ] };
    key <AC07> { [ NoSymbol, NoSymbol, Left,        Left        ] };
    key <AC09> { [ NoSymbol, NoSymbol, Right,       Right       ] };
    key <AD09> { [ NoSymbol, NoSymbol, Prior,       Prior       ] };
    key <AB09> { [ NoSymbol, NoSymbol, Next,        Next        ] };
    key <AB07> { [ NoSymbol, NoSymbol, Home,        Home        ] };
    key <AB08> { [ NoSymbol, NoSymbol, End,         End         ] };
    key <AC06> { [ NoSymbol, NoSymbol, Delete,      Delete      ] };
}

จากนั้นฉันก็รวมสิ่งเหล่านี้ไปยังเลย์เอาต์ในภายหลังในไฟล์ ตอนนี้ฉันควรจะมีเคอร์เซอร์คีย์ที่สามารถเข้าถึงได้ผ่าน AltGr + j, k, l, i (หรือ h, t, n, c ตามที่ฉันใช้ dvorak) เป็นต้นซึ่งสามารถใช้งานได้ในหลายกรณี (เช่น Firefox, urxvt, Eclipse, พื้นที่ข้อความหลักของ LyX แต่บางโปรแกรมไม่ทำอะไรเลยเมื่อฉันพยายามพูดย้ายเคอร์เซอร์โดยใช้ "ทางลัด" (เช่นกล่องโต้ตอบ NetBeans และ LyX)

ดังนั้นมีวิธีที่จะทำให้โปรแกรมอื่น ๆ เหล่านี้เคารพความปรารถนาของฉันด้วยหรือไม่? และทำไมพวกเขาไม่ทำงานตั้งแต่แรก? ฉันไม่ได้ใช้ DE เฉพาะ WM ที่ยอดเยี่ยม

แก้ไข:

  • ที่นี่ เป็นไฟล์เค้าโครงแป้นพิมพ์แบบเต็ม แต่ใช้งานง่าย ฉันมีสิ่งนี้เป็น /usr/share/X11/xkb/symbols/nonpop และฉันโหลดด้วย setxkbmap nonpop.
  • ฉันสังเกตเห็นว่าใน MonoDevelop เคลื่อนไหวไปรอบ ๆ งาน แต่การเลือกไม่ได้ นั่นคือถ้าฉันกด Shift + ขวาข้อความก็จะถูกเลือกตามปกติ แต่ถ้าฉันกด AltGr + Shift + n เคอร์เซอร์ก็จะขยับโดยไม่ต้องเลือก ตัวอย่างเช่นใน Firefox สามารถใช้ทั้งสองวิธีในการเลือก
  • ที่นี่ ในที่สุดพวกเขาก็พูดถึง ซ้อนทับ ซึ่งดูเหมือนสิ่งที่อาจเป็นวิธีแก้ปัญหา แต่ฉันไม่ได้คิดวิธีการใช้

1
ฉันไม่มีทางแก้ปัญหา แต่ถ้าคุณไม่สามารถหาคำตอบได้แม้ว่าคุณจะทนคุณก็สามารถลองถามได้ที่ unix.SE , ไซต์ Stackexchange ที่เป็นศูนย์กลางของ Unix / Linux
Glutanimate

คำตอบ:


9

ทำไมพวกเขาถึงไม่ทำงาน

ให้เป็นไปตาม บทความของ ArchWiki ที่คุณพูดถึง:

  • X server ได้รับ การพิมพ์ซ้ำ จากอุปกรณ์อินพุตและแปลงเป็น สถานะ และ keysym .

    • สถานะ คือ bitmask ของตัวดัดแปลง X (Ctrl / Shift / etc)

    • keysym คือ (ตาม /usr/include/X11/keysymdef.h ) จำนวนเต็ม ที่

      ระบุตัวอักษรหรือฟังก์ชั่นที่เกี่ยวข้องกับแต่ละคีย์ (เช่นผ่าน   การแกะสลักที่มองเห็นได้) ของรูปแบบแป้นพิมพ์

      อักขระที่พิมพ์ได้แต่ละตัวมี keysym ของตัวเองเช่น plus, a, A, หรือ Cyrillic_aแต่คีย์อื่น ๆ ก็สร้าง keysyms เช่นกัน Shift_L, Left หรือ F1.

  • แอปพลิเคชันในเหตุการณ์การกด / ปล่อยปุ่มได้รับข้อมูลทั้งหมดนี้

    แอปพลิเคชั่นบางตัวติดตาม keysyms เช่น Control_L ด้วยตัวเองคนอื่น ๆ เพียงแค่ มองหาบิตตัวดัดแปลงใน สถานะ .

ดังนั้นจะเกิดอะไรขึ้นเมื่อคุณกด AltGr + J :

  • คุณกด AltGr . แอปพลิเคชั่นรับ KeyPressed เหตุการณ์ด้วยรหัส 108 ( <RALT> ) และ keysym 0xfe03 ( ISO_Level3_Shift ) สถานะคือ 0

  • คุณกด J (ซึ่งแมปไปที่“ h” ใน dvorak โดยไม่มีตัวดัดแปลง) แอปพลิเคชั่นรับ KeyPressed เหตุการณ์ด้วยรหัส 44 ( <AC07> ), keysym 0xff51 ( Left ) และสถานะ 0x80 (ตัวดัดแปลง Mod5 เปิดอยู่)

  • คุณปล่อย J . แอปพลิเคชันรับเหตุการณ์ KeyRelease สำหรับกุญแจ <AC07> / Left ด้วยพารามิเตอร์เดียวกัน

  • จากนั้นปล่อย AltGr - เหตุการณ์ KeyRelease สำหรับ AltGr (ยังไงซะ, สถานะที่นี่ยังคงเป็น 0x80 แต่ไม่สำคัญเลย)

สิ่งนี้สามารถเห็นได้ถ้าคุณเรียกใช้ xev ประโยชน์

ดังนั้นนั่นหมายความว่าแม้ว่าแอปพลิเคชันจะได้รับรหัส keysym เดียวกัน ( Left ) จากคีย์ปกติ <LEFT>มันยังได้รับรหัส keysym และ สถานะตัวดัดแปลงจาก AltGr ส่วนใหญ่โปรแกรมที่ไม่สามารถใช้งานได้ ดูโมเดอเรเตอร์และไม่ต้องการทำงานเมื่อมีบางแอคทีฟ

วิธีที่จะทำให้พวกเขาทำงาน

เห็นได้ชัดว่าเราไม่สามารถเปลี่ยนทุกโปรแกรมเป็นไม่ให้มองหาตัวดัดแปลง แล้วก็ ตัวเลือกเดียวที่จะหลีกเลี่ยงสถานการณ์นี้คือการไม่สร้าง keysyms ตัวปรับแต่งเสียง และสถานะบิต

1. แยกกลุ่ม

วิธีเดียวที่อยู่ในใจของฉันคือ: กำหนดปุ่มการเคลื่อนไหวของเคอร์เซอร์ใน แยกกลุ่มและสวิตช์ด้วยการกดปุ่มแยกต่างหากไปยังกลุ่มนั้นก่อน กดปุ่ม J , k , ล. , ผม ( h, t, n, c ) (การล็อคกลุ่มเป็นวิธีที่ต้องการสำหรับกลุ่มครั้งเดียว การเปลี่ยนแปลงที่ฉันเข้าใจ)

ตัวอย่างเช่น:

xkb_keymap {
    xkb_keycodes { include "evdev+aliases(qwerty)" };
    xkb_types { include "complete" };
    xkb_compatibility {
        include "complete"

        interpret ISO_Group_Latch { action = LatchGroup(group=2); };
    };
    xkb_symbols {
        include "pc+us(dvorak)+inet(evdev)"

        key <RALT> { [ ISO_Group_Latch ] };

        key <AC07> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Left ]
        };
        key <AC08> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Down ]
        };
        key <AC09> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Right ]
        };
        key <AD08> {
            type[Group2] = "ONE_LEVEL",
            symbols[Group2] = [ Up ]
        };
    };
    xkb_geometry { include "pc(pc104)" };
};

ตอนนี้ถ้าคุณกดครั้งแรก AltGr และจากนั้น (แยก) อย่างใดอย่างหนึ่ง ปุ่มเคลื่อนไหวนี้ควรทำงาน

อย่างไรก็ตามมันไม่มีประโยชน์มากนัก LockGroup แทนสลักแล้วกด AltGr ก่อนและหลังสวิตช์กลุ่ม ดียิ่งขึ้นอาจ จะเป็น SetGroup - จากนั้น AltGr จะเลือกกลุ่มนั้นขณะกดเท่านั้น แต่นั่นจะเปิดเผยกับแอปพลิเคชันของ AltGr ( ISO_Group_Shift / ISO_Group_Latch / อะไรก็ตามที่ถูกกำหนด) (แต่สถานะตัวดัดแปลง รักษาความสะอาดอยู่เสมอ)

แต่ ... ยังมีความเป็นไปได้ที่แอพพลิเคชั่นจะอ่าน คีย์โค้ด (รหัสของคีย์จริง) จากนั้นมันจะสังเกตเห็นปุ่มเคอร์เซอร์“ ปลอม”

2. การวางซ้อน

การแก้ปัญหา "ระดับต่ำ" มากขึ้นจะเป็น วางซ้อน (เช่นเดียวกัน บทความ อธิบาย)

วางซ้อน เพียงหมายความว่าคีย์ (แป้นพิมพ์จริง) บางคีย์ส่งคืนรหัสของ คีย์อื่น เซิร์ฟเวอร์ X เปลี่ยนรหัสของคีย์และคำนวณ สถานะตัวดัดแปลงและ keysym สำหรับ keycode ใหม่นั้นดังนั้นแอปพลิเคชัน ไม่ควรสังเกตการเปลี่ยนแปลง

แต่การซ้อนทับมี จำกัด มาก:

  • มีบิตควบคุมการซ้อนทับเพียง 2 บิตในเซิร์ฟเวอร์ X (เช่นอาจมีได้ ซ้อนทับได้สูงสุด 2 อัน)
  • แต่ละคีย์สามารถมีได้ 1 รหัสทางเลือกเท่านั้น

สำหรับส่วนที่เหลือการดำเนินการค่อนข้างคล้ายกับวิธีการที่มี กลุ่มแยก:

xkb_keymap {
    xkb_keycodes { include "evdev+aliases(qwerty)" };
    xkb_types { include "complete" };
    xkb_compatibility {
        include "complete"

        interpret Overlay1_Enable {
            action = SetControls(controls=overlay1);
        };
    };
    xkb_symbols {
        include "pc+us(dvorak)+inet(evdev)"

        key <RALT> {
            type[Group1] = "ONE_LEVEL",
            symbols[Group1] = [ Overlay1_Enable ]
        };
        key <AC07> { overlay1 = <LEFT> };
        key <AC08> { overlay1 = <DOWN> };
        key <AC09> { overlay1 = <RGHT> };
        key <AD08> { overlay1 = <UP> };
    };
    xkb_geometry { include "pc(pc104)" };
};

SetControls หมายถึงการเปลี่ยนบิตควบคุมในขณะที่กดปุ่มและเรียกคืน มันในการเปิดตัวที่สำคัญ ควรมีฟังก์ชั่นที่คล้ายกัน LatchControlsแต่ xkbcomp ให้ฉัน

Error:            Unknown action LatchControls

ในการรวบรวม keymap

(โดยวิธีการที่ฉันใช้ dvorak และยังมี remaps การเคลื่อนไหวบางอย่างเพื่อ ปุ่มตัวอักษรในระดับสูง และยังเจอฟังก์ชั่นที่ใช้งานไม่ได้ (ตัวเลือกในโน้ต Xfce และสวิตช์เดสก์ท็อปโดย Ctrl-Alt-Left / Right) ขอบคุณที่ คำถามและคำตอบของคุณตอนนี้ฉันรู้แล้วว่าภาพซ้อนทับคืออะไร :))


ขอบคุณ! จริง ๆ แล้วฉันได้รับคำตอบอีก unix.se ซึ่งในตอนแรกดูเหมือนจะสมบูรณ์แบบ แต่กลับกลายเป็นว่าบางแอปพลิเคชั่นยังคงทำงานผิดปกติ โซลูชันนี้ (ภาพซ้อนทับ) ใช้งานได้ในกรณีเหล่านั้นเช่นกัน
nonpop

ฉันเพิ่งสังเกตเห็นว่า Google chrome [e | ium] ไม่สนใจเรื่องนี้เช่นกัน! :( โชคดีที่ฉันไม่ค่อยได้ใช้เท่าไหร่
nonpop

@nonpop goddamn chromium …ฉันได้เพิ่มการอัปเดตให้กับคำตอบของฉัน superuser.com/a/1000320/521612
Aleks-Daniel Jakimenko

น่าทึ่ง! ฉันค้นหาสิ่งนี้มาหลายปีแล้ว! ยังคงมีปัญหาเล็กน้อยเกี่ยวกับ Chromium ที่ตีความปุ่มกด Overlay1_Enable. ฉันมีอาการเช่นเดียวกับที่นี่: github.com/GalliumOS/galliumos-distro/issues/362
Tarrasch

ฉันจัดการเพื่อแก้ไขปัญหาข้างต้น ปุ่มลูกศรแถวบ้านของฉันทำงานใน Chromium ด้วยเช่นกัน! ฉันต้องการการเปลี่ยนแปลงต่อไปนี้สำหรับคำตอบนี้ gist.github.com/Tarrasch/1293692/...
Tarrasch

3

ผมมีปัญหาเดียวกัน. มันช่างเจ็บปวดเหลือเกิน

ดังนั้นชื่อเรื่องคือ“ วิธีทำให้แอพพลิเคชั่นทั้งหมดเป็นไปตามเค้าโครง xkb ที่แก้ไขของฉัน” ฉันคิดว่าวิธีเดียวคือแก้ไขโปรแกรมทั้งหมดที่ทำไม่ถูกต้อง มาทำกันเถอะ!

หลังจากรายงานบั๊กแล้ว NetBeans ( อัปเดต: ฉันลองรุ่นล่าสุดแล้วใช้งานได้ทันที! ) ฉันคิดว่าฉันจะรายงานข้อผิดพลาดนี้ต่อทุกแอปพลิเคชันต่อไป แอปพลิเคชันถัดไปในรายการคือ Speedcrunch .

อย่างไรก็ตามหลังจากค้นหารายงานข้อผิดพลาดที่คล้ายกันฉันพบ ปัญหานี้ . มีคนอื่นประสบปัญหาเดียวกันดีมาก!

หลังจากอ่านความคิดเห็นแล้วคุณจะเข้าใจว่าจุดบกพร่องนี้ควรปรากฏในแอพ QT ทั้งหมด นี่คือ รายงานข้อบกพร่องของ QT . ไม่ได้รับการแก้ไข แต่ดูเหมือนว่าปัญหาจะได้รับการแก้ไขใน Qt5 .

อย่างไรก็ตามถ้าคุณดูความคิดเห็นมีวิธีแก้ปัญหา! นี่คือวิธีการทำงาน หากคุณกำลังทำสิ่งนี้:

key <SPCE> { [ ISO_Level3_Shift ] };

จากนั้นคุณสามารถเปลี่ยนเป็น:

key <SPCE> {
  type[Group1]="ONE_LEVEL",
  symbols[Group1] = [ ISO_Level3_Shift ]
};

และมันจะแก้ปัญหาสำหรับแอปพลิเคชั่นบางตัว! ตัวอย่างเช่น, Speedcrunch ตอนนี้ใช้ได้สำหรับฉัน! เย้!

สรุป

ตอนนี้แอปพลิเคชันใด ๆ ควรทำงานอย่างถูกต้อง ถ้าไม่เช่นนั้นคุณต้องใช้ type[Group1]="ONE_LEVEL". หากคุณมีอยู่แล้วคุณต้องอัปเดตซอฟต์แวร์ของคุณ หากยังใช้งานไม่ได้แสดงว่าเป็นแอปเฉพาะและคุณต้องส่งรายงานข้อผิดพลาด

อัปเดต (2017-09-23)

ณ วันนี้แอปพลิเคชันทั้งหมดเคารพเค้าโครงแป้นพิมพ์ของฉัน ทั้งหมดยกเว้นหนึ่ง

อย่างจริงจัง, การจัดการแป้นพิมพ์ใน Chromium เป็นขยะ . มีปัญหาหลายประการกับมัน:

  • การเลือกกะไม่ได้มีปุ่มลูกศรที่กำหนดเอง (แต่ปุ่มลูกศรทำงานได้เอง)
  • หากคุณมีหลายเลย์เอาต์และในเลย์เอาต์บางคีย์เป็นพิเศษ (เช่นลูกศร Backspace ฯลฯ ) จากนั้นอีกเลย์เอาท์คีย์นี้จะถูกกำหนดเป็นสิ่งที่คุณมีในเลย์เอาต์แรกของคุณ ตัวอย่างเช่นหากคุณมีสองรูปแบบ: foo, bar และบางคีย์ทำ Backspace ใน fooจากนั้นมันจะทำงานเป็น Backspace ใน bar แม้ว่าจะมีการนิยามใหม่ที่นั่น

เป็นเวลาหลายปีที่ฉันไม่สนใจปัญหาเหล่านี้โดยไม่ได้ใช้โครเมียม อย่างไรก็ตามทุกวันนี้สิ่งต่าง ๆ มักจะใช้ อิเล็กตรอน ซึ่งน่าเสียดายที่สร้างขึ้นบน Chromium

วิธีที่ถูกต้องในการแก้ไขปัญหานี้คือการส่งรายงานข้อผิดพลาดใน Chromium และหวังว่าจะดีที่สุด ฉันไม่ทราบว่าจะต้องใช้เวลานานเท่าใดในการแก้ไขปัญหาที่ส่งผลกระทบต่อผู้ใช้เพียงไม่กี่คน… แต่ดูเหมือนจะเป็นทางออกเดียว ปัญหาของโครเมียมก็คือมันทำงานได้ดีจริง ๆ neo(de) แบบ เลย์เอาต์ Neo มีปุ่มลูกศรในระดับ 5 แต่ฉันไม่สามารถทำให้มันทำงานในเลย์เอาต์ที่กำหนดเองได้

รายงานบั๊กยังคงเปิดอยู่:


ขอบคุณสำหรับข้อมูล! วิธีแก้ปัญหาไม่ได้ช่วยฉันดังนั้นฉันเดาว่าฉันจะต้องรายงานข้อบกพร่องและรอการแปลง qt5
nonpop

1

วิธีทำให้พวกเขาทำงาน - โซลูชันที่ 3

ใช้ระดับเพิ่มเติมและ Action RedirectKey

โซลูชันต่อไปนี้ใช้ปุ่ม Alt ซ้ายเพื่อจัดเตรียมเคอร์เซอร์คีย์บน jkli, Home / End / PageUp / PageDown บนuopöและลบบน Backspace

ปุ่ม Alt ด้านซ้ายยังคงใช้งานได้สำหรับวัตถุประสงค์อื่นสำหรับปุ่มอื่น ๆ ทั้งหมด (เช่นสำหรับเมนูแอปพลิเคชัน) Alt ด้านซ้าย (Mod1) จะถูกลบออกจากสถานะตัวแก้ไขเมื่อใช้เคอร์เซอร์บล็อกเพื่อไม่ให้แอปพลิเคชันมองเห็น

xkb_keymap {
    xkb_keycodes { 
        include "evdev+aliases(qwertz)" 
    };
    xkb_types { 
        include "complete"  
    };
    xkb_compat { 
        include "complete"
        interpret osfLeft {
            action = RedirectKey(keycode=<LEFT>, clearmodifiers=Mod1);
        };
        interpret osfRight {
            action = RedirectKey(keycode=<RGHT>, clearmodifiers=Mod1);
        };
        interpret osfUp {
            action = RedirectKey(keycode=<UP>, clearmodifiers=Mod1);
        };
        interpret osfDown {
            action = RedirectKey(keycode=<DOWN>, clearmodifiers=Mod1);
        };
        interpret osfBeginLine {
            action = RedirectKey(keycode=<HOME>, clearmodifiers=Mod1);
        };
        interpret osfEndLine {
            action = RedirectKey(keycode=<END>, clearmodifiers=Mod1);
        };
        interpret osfPageUp {
            action = RedirectKey(keycode=<PGUP>, clearmodifiers=Mod1);
        };
        interpret osfPageDown {
            action = RedirectKey(keycode=<PGDN>, clearmodifiers=Mod1);
        };
        interpret osfDelete {
            action = RedirectKey(keycode=<DELE>, clearmodifiers=Mod1);
        };
    };
    xkb_symbols { 
        include "pc+de(nodeadkeys)"
        include "inet(evdev)"
        include "compose(rwin)"
        key <LALT> {
            type[Group1] = "ONE_LEVEL",
            symbols[Group1] = [ ISO_Level5_Shift ]
        };
        modifier_map Mod1 { <LALT> };
        key <AC07> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ j, J, dead_belowdot, dead_abovedot, osfLeft, osfLeft, osfLeft, osfLeft ]
        };
        key <AC08> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ k, K, kra, ampersand, osfDown, osfDown, osfDown, osfDown ]
        };
        key <AC09> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ l, L, lstroke, Lstroke, osfRight, osfRight, osfRight, osfRight ]
        };
        key <AC10> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ odiaeresis, Odiaeresis, doubleacute, doubleacute, osfPageDown, osfPageDown, osfPageDown, osfPageDown ]
        };
        key <AD07> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ u, U, downarrow, uparrow, osfBeginLine, osfBeginLine, osfBeginLine, osfBeginLine ]
        };
        key <AD08> {
            type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
            symbols[Group1] = [ i, I, rightarrow, idotless, osfUp, osfUp, osfUp, osfUp ]
        };
        key <AD09> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ o, O, oslash, Oslash, osfEndLine, osfEndLine, osfEndLine, osfEndLine ]
        };
        key <AD10> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ p, P, thorn, THORN, osfPageUp, osfPageUp, osfPageUp, osfPageUp ]
        };
        key <BKSP> {
            type[Group1] = "EIGHT_LEVEL_ALPHABETIC",
            symbols[Group1] = [ BackSpace, BackSpace, BackSpace, BackSpace, osfDelete, osfDelete, osfDelete, osfDelete ] 
        };
    };
    xkb_geometry { 
        include "pc(pc105)" 
    };
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.