ydotool.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // SPDX-FileCopyrightText: JingMatrix https://github.com/JingMatrix
  2. //
  3. // SPDX-License-Identifier: GPL-2.0-or-later
  4. import Gio from 'gi://Gio';
  5. import Gdk from 'gi://Gdk';
  6. const keyCodes = new Map([
  7. ['1', 2],
  8. ['2', 3],
  9. ['3', 4],
  10. ['4', 5],
  11. ['5', 6],
  12. ['6', 7],
  13. ['7', 8],
  14. ['8', 9],
  15. ['9', 10],
  16. ['0', 11],
  17. ['-', 12],
  18. ['=', 13],
  19. ['Q', 16],
  20. ['W', 17],
  21. ['E', 18],
  22. ['R', 19],
  23. ['T', 20],
  24. ['Y', 21],
  25. ['U', 22],
  26. ['I', 23],
  27. ['O', 24],
  28. ['P', 25],
  29. ['[', 26],
  30. [']', 27],
  31. ['A', 30],
  32. ['S', 31],
  33. ['D', 32],
  34. ['F', 33],
  35. ['G', 34],
  36. ['H', 35],
  37. ['J', 36],
  38. ['K', 37],
  39. ['L', 38],
  40. [';', 39],
  41. ["'", 40],
  42. ['Z', 44],
  43. ['X', 45],
  44. ['C', 46],
  45. ['V', 47],
  46. ['B', 48],
  47. ['N', 49],
  48. ['M', 50],
  49. [',', 51],
  50. ['.', 52],
  51. ['/', 53],
  52. ['\\', 43],
  53. ]);
  54. export default class Controller {
  55. constructor() {
  56. // laucher for wl-clipboard
  57. this._launcher = new Gio.SubprocessLauncher({
  58. flags:
  59. Gio.SubprocessFlags.STDOUT_PIPE |
  60. Gio.SubprocessFlags.STDERR_MERGE,
  61. });
  62. this._args = [];
  63. this.buttonMap = new Map([
  64. [Gdk.BUTTON_PRIMARY, '0'],
  65. [Gdk.BUTTON_MIDDLE, '2'],
  66. [Gdk.BUTTON_SECONDARY, '1'],
  67. ]);
  68. }
  69. get args() {
  70. return this._args;
  71. }
  72. set args(opts) {
  73. this._args = ['ydotool'].concat(opts);
  74. try {
  75. this._launcher.spawnv(this._args);
  76. } catch (e) {
  77. debug(e, this._args);
  78. }
  79. }
  80. /*
  81. * Pointer Events
  82. */
  83. movePointer(dx, dy) {
  84. if (dx === 0 && dy === 0)
  85. return;
  86. this.args = ['mousemove', '--', dx.toString(), dy.toString()];
  87. }
  88. pressPointer(button) {
  89. this.args = ['click', '0x4' + this.buttonMap.get(button)];
  90. }
  91. releasePointer(button) {
  92. this.args = ['click', '0x8' + this.buttonMap.get(button)];
  93. }
  94. clickPointer(button) {
  95. this.args = ['click', '0xC' + this.buttonMap.get(button)];
  96. }
  97. doubleclickPointer(button) {
  98. this.args = [
  99. 'click',
  100. '0xC' + this.buttonMap.get(button),
  101. 'click',
  102. '0xC' + this.buttonMap.get(button),
  103. ];
  104. }
  105. scrollPointer(dx, dy) {
  106. if (dx === 0 && dy === 0)
  107. return;
  108. this.args = ['mousemove', '-w', '--', dx.toString(), dy.toString()];
  109. }
  110. /*
  111. * Keyboard Events
  112. */
  113. pressKeys(input, modifiers_codes) {
  114. if (typeof input === 'string' && modifiers_codes.length === 0) {
  115. try {
  116. this._launcher.spawnv(['wtype', input]);
  117. } catch (e) {
  118. debug(e);
  119. this.arg = ['type', '--', input];
  120. }
  121. } else {
  122. if (typeof input === 'number') {
  123. modifiers_codes.push(input);
  124. } else if (typeof input === 'string') {
  125. input = input.toUpperCase();
  126. for (let i = 0; i < input.length; i++) {
  127. if (keyCodes.get(input[i])) {
  128. modifiers_codes.push(keyCodes.get(input[i]));
  129. } else {
  130. debug('Keycode for ' + input[i] + ' not found');
  131. return;
  132. }
  133. }
  134. }
  135. this._args = ['key'];
  136. modifiers_codes.forEach((code) => this._args.push(code + ':1'));
  137. modifiers_codes
  138. .reverse()
  139. .forEach((code) => this._args.push(code + ':0'));
  140. this.args = this._args;
  141. }
  142. }
  143. destroy() {
  144. this._args = [];
  145. }
  146. }