create Wayland desktop environment that simply binds keyboard shortcuts











up vote
0
down vote

favorite












There are dozens of questions on here asking how to create global keyboard bindings in a Wayland environment. Generally, the answer is "use your desktop environment" - an answer that is pretty much useless to most anyone asking the question.



So, in order to draw out a more useful answer, I ask how does one create a minimal Wayland desktop environment which can bind shortcut keys?



I've got Mutter running as my WM, and I'm using GNOME Do as a launcher. It's pretty much exactly the desktop environment I want, with the exception that I can't bind hotkeys.



I don't care if I have to write a 10k line C app to make this work. I just want to know how to proceed. How does GNOME bind keyboard shortcuts within Wayland? Where is the code for that? Where is the appropriate documentation for Wayland/Mutter?










share|improve this question


























    up vote
    0
    down vote

    favorite












    There are dozens of questions on here asking how to create global keyboard bindings in a Wayland environment. Generally, the answer is "use your desktop environment" - an answer that is pretty much useless to most anyone asking the question.



    So, in order to draw out a more useful answer, I ask how does one create a minimal Wayland desktop environment which can bind shortcut keys?



    I've got Mutter running as my WM, and I'm using GNOME Do as a launcher. It's pretty much exactly the desktop environment I want, with the exception that I can't bind hotkeys.



    I don't care if I have to write a 10k line C app to make this work. I just want to know how to proceed. How does GNOME bind keyboard shortcuts within Wayland? Where is the code for that? Where is the appropriate documentation for Wayland/Mutter?










    share|improve this question
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      There are dozens of questions on here asking how to create global keyboard bindings in a Wayland environment. Generally, the answer is "use your desktop environment" - an answer that is pretty much useless to most anyone asking the question.



      So, in order to draw out a more useful answer, I ask how does one create a minimal Wayland desktop environment which can bind shortcut keys?



      I've got Mutter running as my WM, and I'm using GNOME Do as a launcher. It's pretty much exactly the desktop environment I want, with the exception that I can't bind hotkeys.



      I don't care if I have to write a 10k line C app to make this work. I just want to know how to proceed. How does GNOME bind keyboard shortcuts within Wayland? Where is the code for that? Where is the appropriate documentation for Wayland/Mutter?










      share|improve this question













      There are dozens of questions on here asking how to create global keyboard bindings in a Wayland environment. Generally, the answer is "use your desktop environment" - an answer that is pretty much useless to most anyone asking the question.



      So, in order to draw out a more useful answer, I ask how does one create a minimal Wayland desktop environment which can bind shortcut keys?



      I've got Mutter running as my WM, and I'm using GNOME Do as a launcher. It's pretty much exactly the desktop environment I want, with the exception that I can't bind hotkeys.



      I don't care if I have to write a 10k line C app to make this work. I just want to know how to proceed. How does GNOME bind keyboard shortcuts within Wayland? Where is the code for that? Where is the appropriate documentation for Wayland/Mutter?







      keyboard-shortcuts wayland






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 8 at 16:57









      rich remer

      2,0842333




      2,0842333
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote













          After much research and experimentation, it looks like libevdev is maybe the right tool. I developed the program below as a proof-of-concept to bind Alt+X to launch xterm.



          Unfortunately, it has to be run as root, so I'm thinking I need to somehow tie this into the local desktop session. For my purposes, it's probably good enough to just setuid using the root user and call it a day.



          I'm also not convinced my keyboard detection heuristic is very good. I'm essentially looking for any device that has keys and a repeat rate, which on my system only matches my keyboard.



          #include <errno.h>
          #include <stdlib.h>
          #include <stdbool.h>
          #include <stdio.h>
          #include <string.h>
          #include <dirent.h>
          #include <fcntl.h>
          #include <libevdev/libevdev.h>

          #define DEVROOT "/dev/input/"
          #define DEVROOT_LEN 12
          #define PATH_LEN (DEVROOT_LEN + NAME_MAX)

          int outerr(int, const char*);
          struct libevdev* open_device(int);
          bool kblike(struct libevdev*);

          int main(int argc, char* argv) {
          DIR* dir;
          struct dirent* entry;
          char path[PATH_LEN];
          int fd, err;
          struct libevdev* dev = NULL;
          struct input_event ev;
          bool key, rep, alt;

          if (!(dir = opendir("/dev/input"))) {
          return outerr(errno, "cannot enumerate devices");
          }

          // look for keyboard device
          while (entry = readdir(dir)) {
          if (DT_CHR == entry->d_type) {
          sprintf(path, "/dev/input/%s", entry->d_name);

          if (-1 == (fd = open(path, O_RDONLY|O_NONBLOCK))) {
          return outerr(errno, "cannot read device");
          }

          if (dev = open_device(fd)) {
          if (kblike(dev)) break;
          libevdev_free(dev);
          dev = NULL;
          }
          }
          }

          closedir(dir);

          // check if keyboard was found
          if (dev == NULL) {
          return outerr(ENODEV, "could not detect keyboard");
          } else do {
          err = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

          if (err == 0 && ev.type == EV_KEY) switch (ev.code) {
          case KEY_LEFTALT:
          alt = ev.value == 1;
          break;
          case KEY_X:
          if (ev.value == 1 && alt) system("xterm");
          break;
          }
          } while (err == 1 || err == 0 || err == -EAGAIN);

          return 0;
          }

          int outerr(int errnum, const char* msg) {
          fprintf(stderr, "%s (%s)n", msg, strerror(errnum));
          return errnum;
          }

          bool kblike(struct libevdev* dev) {
          return libevdev_has_event_type(dev, EV_KEY)
          && libevdev_has_event_type(dev, EV_REP);
          }

          struct libevdev* open_device(int fd) {
          struct libevdev* dev = libevdev_new();
          int err;

          if (dev == NULL) {
          errno = ENOMEM;
          } else if (0 > (err = libevdev_set_fd(dev, fd))) {
          libevdev_free(dev);
          dev = NULL;
          errno = -err;
          }

          return dev;
          }





          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53212610%2fcreate-wayland-desktop-environment-that-simply-binds-keyboard-shortcuts%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote













            After much research and experimentation, it looks like libevdev is maybe the right tool. I developed the program below as a proof-of-concept to bind Alt+X to launch xterm.



            Unfortunately, it has to be run as root, so I'm thinking I need to somehow tie this into the local desktop session. For my purposes, it's probably good enough to just setuid using the root user and call it a day.



            I'm also not convinced my keyboard detection heuristic is very good. I'm essentially looking for any device that has keys and a repeat rate, which on my system only matches my keyboard.



            #include <errno.h>
            #include <stdlib.h>
            #include <stdbool.h>
            #include <stdio.h>
            #include <string.h>
            #include <dirent.h>
            #include <fcntl.h>
            #include <libevdev/libevdev.h>

            #define DEVROOT "/dev/input/"
            #define DEVROOT_LEN 12
            #define PATH_LEN (DEVROOT_LEN + NAME_MAX)

            int outerr(int, const char*);
            struct libevdev* open_device(int);
            bool kblike(struct libevdev*);

            int main(int argc, char* argv) {
            DIR* dir;
            struct dirent* entry;
            char path[PATH_LEN];
            int fd, err;
            struct libevdev* dev = NULL;
            struct input_event ev;
            bool key, rep, alt;

            if (!(dir = opendir("/dev/input"))) {
            return outerr(errno, "cannot enumerate devices");
            }

            // look for keyboard device
            while (entry = readdir(dir)) {
            if (DT_CHR == entry->d_type) {
            sprintf(path, "/dev/input/%s", entry->d_name);

            if (-1 == (fd = open(path, O_RDONLY|O_NONBLOCK))) {
            return outerr(errno, "cannot read device");
            }

            if (dev = open_device(fd)) {
            if (kblike(dev)) break;
            libevdev_free(dev);
            dev = NULL;
            }
            }
            }

            closedir(dir);

            // check if keyboard was found
            if (dev == NULL) {
            return outerr(ENODEV, "could not detect keyboard");
            } else do {
            err = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

            if (err == 0 && ev.type == EV_KEY) switch (ev.code) {
            case KEY_LEFTALT:
            alt = ev.value == 1;
            break;
            case KEY_X:
            if (ev.value == 1 && alt) system("xterm");
            break;
            }
            } while (err == 1 || err == 0 || err == -EAGAIN);

            return 0;
            }

            int outerr(int errnum, const char* msg) {
            fprintf(stderr, "%s (%s)n", msg, strerror(errnum));
            return errnum;
            }

            bool kblike(struct libevdev* dev) {
            return libevdev_has_event_type(dev, EV_KEY)
            && libevdev_has_event_type(dev, EV_REP);
            }

            struct libevdev* open_device(int fd) {
            struct libevdev* dev = libevdev_new();
            int err;

            if (dev == NULL) {
            errno = ENOMEM;
            } else if (0 > (err = libevdev_set_fd(dev, fd))) {
            libevdev_free(dev);
            dev = NULL;
            errno = -err;
            }

            return dev;
            }





            share|improve this answer

























              up vote
              1
              down vote













              After much research and experimentation, it looks like libevdev is maybe the right tool. I developed the program below as a proof-of-concept to bind Alt+X to launch xterm.



              Unfortunately, it has to be run as root, so I'm thinking I need to somehow tie this into the local desktop session. For my purposes, it's probably good enough to just setuid using the root user and call it a day.



              I'm also not convinced my keyboard detection heuristic is very good. I'm essentially looking for any device that has keys and a repeat rate, which on my system only matches my keyboard.



              #include <errno.h>
              #include <stdlib.h>
              #include <stdbool.h>
              #include <stdio.h>
              #include <string.h>
              #include <dirent.h>
              #include <fcntl.h>
              #include <libevdev/libevdev.h>

              #define DEVROOT "/dev/input/"
              #define DEVROOT_LEN 12
              #define PATH_LEN (DEVROOT_LEN + NAME_MAX)

              int outerr(int, const char*);
              struct libevdev* open_device(int);
              bool kblike(struct libevdev*);

              int main(int argc, char* argv) {
              DIR* dir;
              struct dirent* entry;
              char path[PATH_LEN];
              int fd, err;
              struct libevdev* dev = NULL;
              struct input_event ev;
              bool key, rep, alt;

              if (!(dir = opendir("/dev/input"))) {
              return outerr(errno, "cannot enumerate devices");
              }

              // look for keyboard device
              while (entry = readdir(dir)) {
              if (DT_CHR == entry->d_type) {
              sprintf(path, "/dev/input/%s", entry->d_name);

              if (-1 == (fd = open(path, O_RDONLY|O_NONBLOCK))) {
              return outerr(errno, "cannot read device");
              }

              if (dev = open_device(fd)) {
              if (kblike(dev)) break;
              libevdev_free(dev);
              dev = NULL;
              }
              }
              }

              closedir(dir);

              // check if keyboard was found
              if (dev == NULL) {
              return outerr(ENODEV, "could not detect keyboard");
              } else do {
              err = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

              if (err == 0 && ev.type == EV_KEY) switch (ev.code) {
              case KEY_LEFTALT:
              alt = ev.value == 1;
              break;
              case KEY_X:
              if (ev.value == 1 && alt) system("xterm");
              break;
              }
              } while (err == 1 || err == 0 || err == -EAGAIN);

              return 0;
              }

              int outerr(int errnum, const char* msg) {
              fprintf(stderr, "%s (%s)n", msg, strerror(errnum));
              return errnum;
              }

              bool kblike(struct libevdev* dev) {
              return libevdev_has_event_type(dev, EV_KEY)
              && libevdev_has_event_type(dev, EV_REP);
              }

              struct libevdev* open_device(int fd) {
              struct libevdev* dev = libevdev_new();
              int err;

              if (dev == NULL) {
              errno = ENOMEM;
              } else if (0 > (err = libevdev_set_fd(dev, fd))) {
              libevdev_free(dev);
              dev = NULL;
              errno = -err;
              }

              return dev;
              }





              share|improve this answer























                up vote
                1
                down vote










                up vote
                1
                down vote









                After much research and experimentation, it looks like libevdev is maybe the right tool. I developed the program below as a proof-of-concept to bind Alt+X to launch xterm.



                Unfortunately, it has to be run as root, so I'm thinking I need to somehow tie this into the local desktop session. For my purposes, it's probably good enough to just setuid using the root user and call it a day.



                I'm also not convinced my keyboard detection heuristic is very good. I'm essentially looking for any device that has keys and a repeat rate, which on my system only matches my keyboard.



                #include <errno.h>
                #include <stdlib.h>
                #include <stdbool.h>
                #include <stdio.h>
                #include <string.h>
                #include <dirent.h>
                #include <fcntl.h>
                #include <libevdev/libevdev.h>

                #define DEVROOT "/dev/input/"
                #define DEVROOT_LEN 12
                #define PATH_LEN (DEVROOT_LEN + NAME_MAX)

                int outerr(int, const char*);
                struct libevdev* open_device(int);
                bool kblike(struct libevdev*);

                int main(int argc, char* argv) {
                DIR* dir;
                struct dirent* entry;
                char path[PATH_LEN];
                int fd, err;
                struct libevdev* dev = NULL;
                struct input_event ev;
                bool key, rep, alt;

                if (!(dir = opendir("/dev/input"))) {
                return outerr(errno, "cannot enumerate devices");
                }

                // look for keyboard device
                while (entry = readdir(dir)) {
                if (DT_CHR == entry->d_type) {
                sprintf(path, "/dev/input/%s", entry->d_name);

                if (-1 == (fd = open(path, O_RDONLY|O_NONBLOCK))) {
                return outerr(errno, "cannot read device");
                }

                if (dev = open_device(fd)) {
                if (kblike(dev)) break;
                libevdev_free(dev);
                dev = NULL;
                }
                }
                }

                closedir(dir);

                // check if keyboard was found
                if (dev == NULL) {
                return outerr(ENODEV, "could not detect keyboard");
                } else do {
                err = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

                if (err == 0 && ev.type == EV_KEY) switch (ev.code) {
                case KEY_LEFTALT:
                alt = ev.value == 1;
                break;
                case KEY_X:
                if (ev.value == 1 && alt) system("xterm");
                break;
                }
                } while (err == 1 || err == 0 || err == -EAGAIN);

                return 0;
                }

                int outerr(int errnum, const char* msg) {
                fprintf(stderr, "%s (%s)n", msg, strerror(errnum));
                return errnum;
                }

                bool kblike(struct libevdev* dev) {
                return libevdev_has_event_type(dev, EV_KEY)
                && libevdev_has_event_type(dev, EV_REP);
                }

                struct libevdev* open_device(int fd) {
                struct libevdev* dev = libevdev_new();
                int err;

                if (dev == NULL) {
                errno = ENOMEM;
                } else if (0 > (err = libevdev_set_fd(dev, fd))) {
                libevdev_free(dev);
                dev = NULL;
                errno = -err;
                }

                return dev;
                }





                share|improve this answer












                After much research and experimentation, it looks like libevdev is maybe the right tool. I developed the program below as a proof-of-concept to bind Alt+X to launch xterm.



                Unfortunately, it has to be run as root, so I'm thinking I need to somehow tie this into the local desktop session. For my purposes, it's probably good enough to just setuid using the root user and call it a day.



                I'm also not convinced my keyboard detection heuristic is very good. I'm essentially looking for any device that has keys and a repeat rate, which on my system only matches my keyboard.



                #include <errno.h>
                #include <stdlib.h>
                #include <stdbool.h>
                #include <stdio.h>
                #include <string.h>
                #include <dirent.h>
                #include <fcntl.h>
                #include <libevdev/libevdev.h>

                #define DEVROOT "/dev/input/"
                #define DEVROOT_LEN 12
                #define PATH_LEN (DEVROOT_LEN + NAME_MAX)

                int outerr(int, const char*);
                struct libevdev* open_device(int);
                bool kblike(struct libevdev*);

                int main(int argc, char* argv) {
                DIR* dir;
                struct dirent* entry;
                char path[PATH_LEN];
                int fd, err;
                struct libevdev* dev = NULL;
                struct input_event ev;
                bool key, rep, alt;

                if (!(dir = opendir("/dev/input"))) {
                return outerr(errno, "cannot enumerate devices");
                }

                // look for keyboard device
                while (entry = readdir(dir)) {
                if (DT_CHR == entry->d_type) {
                sprintf(path, "/dev/input/%s", entry->d_name);

                if (-1 == (fd = open(path, O_RDONLY|O_NONBLOCK))) {
                return outerr(errno, "cannot read device");
                }

                if (dev = open_device(fd)) {
                if (kblike(dev)) break;
                libevdev_free(dev);
                dev = NULL;
                }
                }
                }

                closedir(dir);

                // check if keyboard was found
                if (dev == NULL) {
                return outerr(ENODEV, "could not detect keyboard");
                } else do {
                err = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

                if (err == 0 && ev.type == EV_KEY) switch (ev.code) {
                case KEY_LEFTALT:
                alt = ev.value == 1;
                break;
                case KEY_X:
                if (ev.value == 1 && alt) system("xterm");
                break;
                }
                } while (err == 1 || err == 0 || err == -EAGAIN);

                return 0;
                }

                int outerr(int errnum, const char* msg) {
                fprintf(stderr, "%s (%s)n", msg, strerror(errnum));
                return errnum;
                }

                bool kblike(struct libevdev* dev) {
                return libevdev_has_event_type(dev, EV_KEY)
                && libevdev_has_event_type(dev, EV_REP);
                }

                struct libevdev* open_device(int fd) {
                struct libevdev* dev = libevdev_new();
                int err;

                if (dev == NULL) {
                errno = ENOMEM;
                } else if (0 > (err = libevdev_set_fd(dev, fd))) {
                libevdev_free(dev);
                dev = NULL;
                errno = -err;
                }

                return dev;
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 12 at 4:06









                rich remer

                2,0842333




                2,0842333






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53212610%2fcreate-wayland-desktop-environment-that-simply-binds-keyboard-shortcuts%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Schultheiß

                    Liste der Kulturdenkmale in Wilsdruff

                    Android Play Services Check