ch11ng / exwm

Emacs X Window Manager
2.85k stars 134 forks source link

xmodmap freezes EXWM #483

Closed QiangF closed 5 years ago

QiangF commented 6 years ago

This happens every time after 0.16, when I try the new release. It hangs the computer for about 4 minutes then things go to normal. I will keep using 0.16 for now.

medranocalvo commented 6 years ago
  1. Does this happen with a barebones configuration?

You can try that placing the following in your .xinitrc.

emacs -Q -L /path/to/exwm/ -L /path/to/xelb/ \
    --eval "(require 'exwm)" \
    --eval "(exwm-init)";
  1. Please, follow these steps to record a debugging log. I'd recommend doing it from a fresh X session.

    1. M-x exwm-debug-toggle,
    2. suspend,
    3. resume
    4. (wait...)
    5. you can find the resulting log in a buffer named *XELB-DEBUG*.
    6. post the log as an attachment to this issue.
medranocalvo commented 6 years ago

@QiangF, could you try the steps above?

QiangF commented 6 years ago

Sorry for the delay. I was busy with my work. I think I have found the cause, the command in my setup that causes the freeze of emacs after suspend is:

xmodmap ~/.dotfiles/.Xmodmap

It causes the freeze every time it is run, I run it after resume with a system service. But no debug infomation is available even with this setting.

(setq debug-on-error nil)
(setq debug-on-quit nil)
(setq edebug-all-forms nil)
(setq exwm-debug-on t)

Please try with this .Xmodmap to see if you can repeat it.

keycode 47 = Mode_switch
keycode 66 = Control_L   Control_L     Control_L     Control_L
keycode 37 = Control_L   Control_L     Control_L     Control_L
keycode 50 = Shift_L
keycode 29 = y           Y             F11
keycode 46 = l           L             Caps_Lock
keycode 23 = Tab         ISO_Left_Tab  Next
keycode 28 = t           T             Prior         U03A4
keycode 24 = q           Q             quotedbl      U0398
keycode 25 = w           W             apostrophe    F11
keycode 27 = r           R             minus
keycode 30 = u           U             underscore    Caps_Lock
keycode 42 = g           G             equal         F5
keycode 43 = h           H             plus          F6
keycode 39 = s           S             semicolon     F2
keycode 52 = z           Z             braceleft     braceleft
keycode 53 = x           X             braceright    U03A7
keycode 31 = i           I             backslash     U03CA
keycode 32 = o           O             bar           U039F
keycode 54 = c           C             colon         colon
keycode 55 = v           V             Return        U03DE
keycode 44 = j           J             Down          Next
keycode 45 = k           K             Up            Prior
keycode 56 = b           B             Left
keycode 41 = f           F             Right         F4
keycode 38 = a           A             Home          F1
keycode 26 = e           E             End           F4
keycode 40 = d           D             Delete        F3
keycode 57 = n           N             bracketleft
keycode 58 = m           M             bracketright
keycode 59 = comma       less          question      less
keycode 60 = period      greater       slash         greater
keycode 48 = apostrophe  quotedbl
keycode 49 = grave       asciitilde
keycode  15 = 6 asciicircum asciicircum U2086
clear Lock
add Control = Control_L
ch11ng commented 6 years ago

Xmodmap is inefficient in handling a file with too many lines. It's built around Xlib and would make an individual call to XChangeKeyboardMapping (which is synchronous) for each effective line beginning with keycode. This may not be noticeable for the C implementation but really a challenge for XELB. In this issue XELB would be busy handling the events and hence the delay.

I'm not sure what you intend to achieve with the .Xmodmap but is it possible to leave out some unnecessary lines, or switch to some alternative? For example udev can be used to alter the system keyboard mapping (the mapping is even working for the Linux console) by making a configuration file under /etc/udev/hwdb.d/.

QiangF commented 6 years ago

My intention is to mimic the key binding in my 40 key keyboard Daisy. The philosophy is to reduce hand movement, 40 keys are within fingers' range without moving hand. (To see how the keyboard looks, go to http://ydkb.io/ and select daisy)

The xmodmap modeswitch corresponds to the layers in daisy. The fourth column of keys is not used for now. I think the following will be hard to do with keymapping with udev hwdb.

  1. set ; to be the Mode_switch key, seems Mode_switch doesn't have a key
  2. set the various keymap with Mode_switch modifier (the third column in my .Xmodmap)

In theory, the xmodmap only needs to be executed once at boot time. For unknown reasons (maybe it exwm related), sometimes the remapping lost after resuming from suspend, so I reexecute the xmodmap with a python script.

import socket
import sys
import time
import dbus
import gobject
import logging
import os
from dbus.mainloop.glib import DBusGMainLoop

def get_lock(process_name):
    # Without holding a reference to our socket somewhere it gets garbage
    # collected when the function exits
    get_lock._lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    try:
        get_lock._lock_socket.bind('\0' + process_name)
    except socket.error:
        sys.exit()

get_lock('my_dbus_monitor.py')
xmodmap = os.path.expanduser('~/.Xmodmap')
logging.basicConfig(filename="/home/my_bin/my_dbus_monitor.log", level=logging.INFO)
logger = logging.getLogger('my_dbus_monitor')

# DBus init
DBusGMainLoop(set_as_default=True)     # integrate into gobject main loop
bus = dbus.SystemBus()                 # connect to system wide dbus
system_bus = dbus.SystemBus()
session_bus = dbus.SessionBus()

def setkeymap():
    logger.info('setkeymap')
    status = os.system("pkill xcape")
    status = os.system("/usr/bin/setxkbmap -layout 'us(intl)' -option -option compose:rctrl -option altwin:meta_alt")
    if os.path.isfile(xmodmap):
        time.sleep(5)
        status = os.system('/usr/bin/xmodmap ' + xmodmap)
    status = os.system("xcape -e 'Shift_R=Control_L|c;Super_L=Super_L|c;Control_L=Escape;Shift_L=Control_L|x;Alt_L=Alt_L|x;Alt_R=Alt_L|c'")

def xautolock():
    status = os.system('/usr/bin/xautolock -time 15 -locker slock')

def handle_sleep(sleeping):
if sleeping:
    status = os.system('/usr/bin/xautolock -locknow')
else:
    setkeymap()

setkeymap()
medranocalvo commented 6 years ago

Perhaps you can try xkbcomp (https://wiki.archlinux.org/index.php/X_keyboard_extension). You might be able to freeze your configuration (after running your custom Xmodmap) and use that forwards. I have not tried this myself, nor do I know whether it will be any faster.

QiangF commented 6 years ago

@medranocalvo Thank you for the suggestion. It's not flexible to use xkbcomp for multiple keyboards. Since this can't be solved with elisp, I am closing this issue now.

QiangF commented 6 years ago

@ch11ng VMware totally freezes EXWM for me today, when it became responsive, I can't type keys with the keyboard. Why xmodmap doesn't freeze EXWM <=0.16? Is it possible to fall back to 0.16 on the handling of those event? Why EXWM needs to go in such a low level? This is related to https://github.com/ch11ng/exwm/issues/386

medranocalvo commented 6 years ago

Hello @QiangF, I can't help with your issue, but it will be helpful if you could post the backtrace.

QiangF commented 6 years ago

@medranocalvo There is no backtrace, it just freezed.

QiangF commented 6 years ago

The xelb version for exwm 0.16 is 0.12.

ch11ng commented 6 years ago

VMware totally freezes EXWM for me today, when it became responsive, I can't type keys with the keyboard.

Does a single pkill -USR2 emacs bring the backtrace?

Why xmodmap doesn't freeze EXWM <=0.16?

It's probably due to the change made to XELB.

Is it possible to fall back to 0.16 on the handling of those event?

While 0.16 (actually the corresponding version of XELB) works in this case does not necessarily mean it's implemented correctly and works for others. So the answer really depends.

Why EXWM needs to go in such a low level?

XELB is a replacement of Xlib in Elisp. It has to do whatever Xlib does.

QiangF commented 6 years ago

@ch11ng Is it possible to write an Xmodmap replacement in Elisp to get more flexibilities in setting keymaping?

ch11ng commented 6 years ago

Of course. The X requests xmodmap makes are all available in XELB. XCB will also do. Simply making requests to modify keyboard mapping and avoid flushing until the last one is made would greatly alleviate the symptom.

medranocalvo commented 5 years ago

Closing, because I think there's nothing EXWM can do here. Please, reopen if you think that's not the case.

QiangF commented 5 years ago

@ch11ng I have found two packages that do the key remapping without using xmodmap and hwdb. https://github.com/kozikow/keyremaplinux https://github.com/snyball/Hawck I have just tried the first one, works like a charm.

medranocalvo commented 5 years ago

@QiangF, thank you for reporting back! Could you add that to the Wiki? A new subsection under https://github.com/ch11ng/exwm/wiki/EXWM-User-Guide#known-issues would help other users.

QiangF commented 5 years ago

Added. In addition, Xmodmap and xcape mentioned above won't work in the console and neither in a virtual machine guest (vmware). Two better alternatives (works every where even in the console, no need to specify hardware ids) will be https://github.com/kozikow/keyremaplinux https://github.com/snyball/Hawck