/ src / discord_register_linux.cpp
discord_register_linux.cpp
  1  #include "discord_rpc.h"
  2  #include "discord_register.h"
  3  #include <stdio.h>
  4  
  5  #include <errno.h>
  6  #include <stdlib.h>
  7  #include <string.h>
  8  #include <sys/stat.h>
  9  #include <sys/types.h>
 10  #include <unistd.h>
 11  
 12  static bool Mkdir(const char* path)
 13  {
 14      int result = mkdir(path, 0755);
 15      if (result == 0) {
 16          return true;
 17      }
 18      if (errno == EEXIST) {
 19          return true;
 20      }
 21      return false;
 22  }
 23  
 24  // we want to register games so we can run them from Discord client as discord-<appid>://
 25  extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
 26  {
 27      // Add a desktop file and update some mime handlers so that xdg-open does the right thing.
 28  
 29      const char* home = getenv("HOME");
 30      if (!home) {
 31          return;
 32      }
 33  
 34      char exePath[1024];
 35      if (!command || !command[0]) {
 36          ssize_t size = readlink("/proc/self/exe", exePath, sizeof(exePath));
 37          if (size <= 0 || size >= (ssize_t)sizeof(exePath)) {
 38              return;
 39          }
 40          exePath[size] = '\0';
 41          command = exePath;
 42      }
 43  
 44      const char* desktopFileFormat = "[Desktop Entry]\n"
 45                                     "Name=Game %s\n"
 46                                     "Exec=%s %%u\n" // note: it really wants that %u in there
 47                                     "Type=Application\n"
 48                                     "NoDisplay=true\n"
 49                                     "Categories=Discord;Games;\n"
 50                                     "MimeType=x-scheme-handler/discord-%s;\n";
 51      char desktopFile[2048];
 52      int fileLen = snprintf(
 53        desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId);
 54      if (fileLen <= 0) {
 55          return;
 56      }
 57  
 58      char desktopFilename[256];
 59      snprintf(desktopFilename, sizeof(desktopFilename), "/discord-%s.desktop", applicationId);
 60  
 61      char desktopFilePath[1024];
 62      snprintf(desktopFilePath, sizeof(desktopFilePath), "%s/.local", home);
 63      if (!Mkdir(desktopFilePath)) {
 64          return;
 65      }
 66      strcat(desktopFilePath, "/share");
 67      if (!Mkdir(desktopFilePath)) {
 68          return;
 69      }
 70      strcat(desktopFilePath, "/applications");
 71      if (!Mkdir(desktopFilePath)) {
 72          return;
 73      }
 74      strcat(desktopFilePath, desktopFilename);
 75  
 76      FILE* fp = fopen(desktopFilePath, "w");
 77      if (fp) {
 78          fwrite(desktopFile, 1, fileLen, fp);
 79          fclose(fp);
 80      }
 81      else {
 82          return;
 83      }
 84  
 85      char xdgMimeCommand[1024];
 86      snprintf(xdgMimeCommand,
 87               sizeof(xdgMimeCommand),
 88               "xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s",
 89               applicationId,
 90               applicationId);
 91      if (system(xdgMimeCommand) < 0) {
 92          fprintf(stderr, "Failed to register mime handler\n");
 93      }
 94  }
 95  
 96  extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
 97                                                           const char* steamId)
 98  {
 99      char command[256];
100      sprintf(command, "xdg-open steam://rungameid/%s", steamId);
101      Discord_Register(applicationId, command);
102  }