oshide.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <pthread.h>
  4. #include <dlfcn.h>
  5. #include <X11/Xlib.h>
  6. #include <X11/Xutil.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <unistd.h>
  11. #include <sys/ioctl.h>
  12. #include <termios.h>
  13. #include <linux/kd.h>
  14. #define PFX "oshide: "
  15. #define TERMIOS_DUMP_FILE "/tmp/pico_tios"
  16. #define FPTR(f) typeof(f) * p##f
  17. #define FPTR_LINK(xf, dl, f) { \
  18. xf.p##f = dlsym(dl, #f); \
  19. if (xf.p##f == NULL) { \
  20. fprintf(stderr, "missing symbol: %s\n", #f); \
  21. goto fail; \
  22. } \
  23. }
  24. struct xfuncs {
  25. FPTR(XCreateBitmapFromData);
  26. FPTR(XCreatePixmapCursor);
  27. FPTR(XFreePixmap);
  28. FPTR(XOpenDisplay);
  29. FPTR(XDisplayName);
  30. FPTR(XCloseDisplay);
  31. FPTR(XCreateSimpleWindow);
  32. FPTR(XChangeWindowAttributes);
  33. FPTR(XSelectInput);
  34. FPTR(XMapWindow);
  35. FPTR(XNextEvent);
  36. FPTR(XCheckTypedEvent);
  37. FPTR(XUnmapWindow);
  38. FPTR(XGrabKeyboard);
  39. };
  40. static Cursor transparent_cursor(struct xfuncs *xf, Display *display, Window win)
  41. {
  42. Cursor cursor;
  43. Pixmap pix;
  44. XColor dummy;
  45. char d = 0;
  46. memset(&dummy, 0, sizeof(dummy));
  47. pix = xf->pXCreateBitmapFromData(display, win, &d, 1, 1);
  48. cursor = xf->pXCreatePixmapCursor(display, pix, pix,
  49. &dummy, &dummy, 0, 0);
  50. xf->pXFreePixmap(display, pix);
  51. return cursor;
  52. }
  53. static void *x11h_handler(void *arg)
  54. {
  55. struct xfuncs xf;
  56. unsigned int display_width, display_height;
  57. XSetWindowAttributes attributes;
  58. Window win;
  59. XEvent report;
  60. Display *display;
  61. Visual *visual;
  62. void *x11lib;
  63. int screen;
  64. memset(&xf, 0, sizeof(xf));
  65. x11lib = dlopen("libX11.so.6", RTLD_LAZY);
  66. if (x11lib == NULL) {
  67. fprintf(stderr, "libX11.so load failed:\n%s\n", dlerror());
  68. goto fail;
  69. }
  70. FPTR_LINK(xf, x11lib, XCreateBitmapFromData);
  71. FPTR_LINK(xf, x11lib, XCreatePixmapCursor);
  72. FPTR_LINK(xf, x11lib, XFreePixmap);
  73. FPTR_LINK(xf, x11lib, XOpenDisplay);
  74. FPTR_LINK(xf, x11lib, XDisplayName);
  75. FPTR_LINK(xf, x11lib, XCloseDisplay);
  76. FPTR_LINK(xf, x11lib, XCreateSimpleWindow);
  77. FPTR_LINK(xf, x11lib, XChangeWindowAttributes);
  78. FPTR_LINK(xf, x11lib, XSelectInput);
  79. FPTR_LINK(xf, x11lib, XMapWindow);
  80. FPTR_LINK(xf, x11lib, XNextEvent);
  81. FPTR_LINK(xf, x11lib, XCheckTypedEvent);
  82. FPTR_LINK(xf, x11lib, XUnmapWindow);
  83. FPTR_LINK(xf, x11lib, XGrabKeyboard);
  84. //XInitThreads();
  85. display = xf.pXOpenDisplay(NULL);
  86. if (display == NULL)
  87. {
  88. fprintf(stderr, "cannot connect to X server %s, X handling disabled.\n",
  89. xf.pXDisplayName(NULL));
  90. goto fail2;
  91. }
  92. visual = DefaultVisual(display, 0);
  93. if (visual->class != TrueColor)
  94. fprintf(stderr, PFX "warning: non true color visual\n");
  95. printf(PFX "X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display),
  96. VendorRelease(display), DisplayString(display), ProtocolVersion(display),
  97. ProtocolRevision(display));
  98. screen = DefaultScreen(display);
  99. display_width = DisplayWidth(display, screen);
  100. display_height = DisplayHeight(display, screen);
  101. printf(PFX "display is %dx%d\n", display_width, display_height);
  102. win = xf.pXCreateSimpleWindow(display,
  103. RootWindow(display, screen),
  104. 0, 0, display_width, display_height, 0,
  105. BlackPixel(display, screen),
  106. BlackPixel(display, screen));
  107. attributes.override_redirect = True;
  108. attributes.cursor = transparent_cursor(&xf, display, win);
  109. xf.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
  110. xf.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask);
  111. xf.pXMapWindow(display, win);
  112. xf.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
  113. // XSetIOErrorHandler
  114. while (1)
  115. {
  116. xf.pXNextEvent(display, &report);
  117. switch (report.type)
  118. {
  119. case Expose:
  120. while (xf.pXCheckTypedEvent(display, Expose, &report))
  121. ;
  122. break;
  123. case FocusOut:
  124. // XFocusChangeEvent
  125. // printf("focus out\n");
  126. // xf.pXUnmapWindow(display, win);
  127. break;
  128. case KeyPress:
  129. // printf("press %d\n", report.xkey.keycode);
  130. break;
  131. default:
  132. break;
  133. }
  134. }
  135. fail2:
  136. dlclose(x11lib);
  137. fail:
  138. fprintf(stderr, "x11 handling disabled.\n");
  139. return NULL;
  140. }
  141. static struct termios g_kbd_termios_saved;
  142. static int g_kbdfd;
  143. static void hidecon_start(void)
  144. {
  145. struct termios kbd_termios;
  146. FILE *tios_f;
  147. int mode;
  148. g_kbdfd = open("/dev/tty", O_RDWR);
  149. if (g_kbdfd == -1) {
  150. perror(PFX "open /dev/tty");
  151. return;
  152. }
  153. if (ioctl(g_kbdfd, KDGETMODE, &mode) == -1) {
  154. perror(PFX "(not hiding FB): KDGETMODE");
  155. goto fail;
  156. }
  157. if (tcgetattr(g_kbdfd, &kbd_termios) == -1) {
  158. perror(PFX "tcgetattr");
  159. goto fail;
  160. }
  161. /* dump for picorestore */
  162. g_kbd_termios_saved = kbd_termios;
  163. tios_f = fopen(TERMIOS_DUMP_FILE, "wb");
  164. if (tios_f) {
  165. fwrite(&kbd_termios, sizeof(kbd_termios), 1, tios_f);
  166. fclose(tios_f);
  167. }
  168. kbd_termios.c_lflag &= ~(ICANON | ECHO); // | ISIG);
  169. kbd_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
  170. kbd_termios.c_cc[VMIN] = 0;
  171. kbd_termios.c_cc[VTIME] = 0;
  172. if (tcsetattr(g_kbdfd, TCSAFLUSH, &kbd_termios) == -1) {
  173. perror(PFX "tcsetattr");
  174. goto fail;
  175. }
  176. if (ioctl(g_kbdfd, KDSETMODE, KD_GRAPHICS) == -1) {
  177. perror(PFX "KDSETMODE KD_GRAPHICS");
  178. tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved);
  179. goto fail;
  180. }
  181. return;
  182. fail:
  183. close(g_kbdfd);
  184. g_kbdfd = -1;
  185. }
  186. static void hidecon_end(void)
  187. {
  188. if (g_kbdfd < 0)
  189. return;
  190. if (ioctl(g_kbdfd, KDSETMODE, KD_TEXT) == -1)
  191. perror(PFX "KDSETMODE KD_TEXT");
  192. if (tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved) == -1)
  193. perror(PFX "tcsetattr");
  194. remove(TERMIOS_DUMP_FILE);
  195. close(g_kbdfd);
  196. g_kbdfd = -1;
  197. }
  198. int oshide_init(void)
  199. {
  200. pthread_t tid;
  201. int ret;
  202. ret = pthread_create(&tid, NULL, x11h_handler, NULL);
  203. if (ret != 0) {
  204. fprintf(stderr, PFX "failed to create thread: %d\n", ret);
  205. return ret;
  206. }
  207. pthread_detach(tid);
  208. hidecon_start();
  209. return 0;
  210. }
  211. void oshide_finish(void)
  212. {
  213. /* XXX: the X thread.. */
  214. hidecon_end();
  215. }
  216. #if 0
  217. int main()
  218. {
  219. x11h_init();
  220. sleep(5);
  221. }
  222. #endif