Basic layout detection

Goes on top of #5201, addresses #2462.
Seems better than the localeId approach, but I'd still like to do something scancode-based at some point.