ericek111

X11 click-through transparent overlay

Aug 22nd, 2016
508
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.44 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <iostream>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <linux/input.h>
  8. #include <unistd.h>
  9. #include <sys/time.h>
  10. #include <climits>
  11. #include <chrono>
  12. #include <X11/Xos.h>
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/Xatom.h>
  16. #include <X11/extensions/shape.h>
  17. #include <X11/extensions/Xcomposite.h>
  18. #include <X11/extensions/Xfixes.h>
  19. #include <math.h>
  20. #include <sstream>
  21. #include <string>
  22.  
  23. using namespace std;
  24.  
  25. #define ALIGN_LEFT 0
  26. #define ALIGN_CENTER 1
  27. #define ALIGN_RIGHT 2
  28.  
  29. // Events for normal windows
  30. #define BASIC_EVENT_MASK (StructureNotifyMask|ExposureMask|PropertyChangeMask|EnterWindowMask|LeaveWindowMask|KeyPressMask|KeyReleaseMask|KeymapStateMask)
  31. #define NOT_PROPAGATE_MASK (KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|ButtonMotionMask)
  32.  
  33. #define FPSMETERSAMPLE 100
  34. #define CLEARSCREEN_ITERATIONS 2000
  35.  
  36. class Draw {
  37.  
  38.     public:
  39.     Draw();
  40.     void drawstring(const char * text, int x, int y, XColor fgcolor, XColor bgcolor, int align);
  41.     XColor createXColorFromRGBA(short red, short green, short blue, short alpha);
  42.     XColor createXColorFromRGB(short red, short green, short blue);
  43.     void createShapedWindow();
  44.     void openDisplay();
  45.     void allow_input_passthrough (Window w);
  46.     void list_fonts();
  47.     void init();
  48.     void halt();
  49.     void toggleoverlay(bool state);
  50.     void toggleoverlay();
  51.     void clearscreen();
  52.     void startdraw();
  53.     void enddraw();
  54.     void cleararea(int x, int y, int width, int height);
  55.     Display *g_display;
  56.     int      g_screen;
  57.     Window   g_win;
  58.     int      g_disp_width;
  59.     int      g_disp_height;
  60.     Colormap g_colormap;
  61.     bool overlayenabled = false;
  62.     bool overlayavailable = false;
  63.     GC       gc;
  64.     XGCValues   gcv;
  65.     XFontStruct * font;
  66.     XColor red, black, blacka, blackla, white, transparent, ltblue, blue, yellow, grey, ltgrey;
  67.  
  68.     const char * font_name = "9x15bold";
  69.     const int font_width = 9;
  70.     const int font_height = 15;
  71.  
  72.     // The window size
  73.     int WIDTH  = 1920;
  74.     int HEIGHT = 1080;
  75.  
  76.  
  77.     private:
  78.     long event_mask = (StructureNotifyMask|ExposureMask|PropertyChangeMask|EnterWindowMask|LeaveWindowMask|KeyRelease | ButtonPress|ButtonRelease|KeymapStateMask);
  79.     int shape_event_base;
  80.     int shape_error_base;
  81.     std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
  82.     std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
  83.     int fpsmeterc = 0;
  84.     uint64_t duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
  85.     string fpsstring = "";
  86.     int renderi = 0;
  87. };
  88.  
  89. // __________________________________________________________________________
  90. #include "draw.hpp"
  91.  
  92. Draw::Draw() {
  93.  
  94. }
  95. void Draw::allow_input_passthrough (Window w) {
  96.     XserverRegion region = XFixesCreateRegion (g_display, NULL, 0);
  97.  
  98.     //XFixesSetWindowShapeRegion (g_display, w, ShapeBounding, 0, 0, 0);
  99.     XFixesSetWindowShapeRegion (g_display, w, ShapeInput, 0, 0, region);
  100.  
  101.     XFixesDestroyRegion (g_display, region);
  102. }
  103.  
  104. void Draw::list_fonts() {
  105.     char **fontlist;
  106.     int num_fonts;
  107.     fontlist = XListFonts (g_display, "*", 1000, &num_fonts);
  108.     for (int i = 0; i < num_fonts; ++i) {
  109.         fprintf(stderr, "> %s\n", fontlist[i]);
  110.     }
  111. }
  112. XColor Draw::createXColorFromRGB(short red, short green, short blue) {
  113.     XColor color;
  114.  
  115.     // m_color.red = red * 65535 / 255;
  116.     color.red = (red * 0xFFFF) / 0xFF;
  117.     color.green = (green * 0xFFFF) / 0xFF;
  118.     color.blue = (blue * 0xFFFF) / 0xFF;
  119.     color.flags = DoRed | DoGreen | DoBlue;
  120.  
  121.     if (!XAllocColor(g_display, DefaultColormap(g_display, g_screen), &color)) {
  122.         std::cerr << "createXColorFromRGB: Cannot create color" << endl;
  123.         exit(-1);
  124.     }
  125.     return color;
  126. }
  127. XColor Draw::createXColorFromRGBA(short red, short green, short blue, short alpha) {
  128.     XColor color;
  129.  
  130.     // m_color.red = red * 65535 / 255;
  131.     color.red = (red * 0xFFFF) / 0xFF;
  132.     color.green = (green * 0xFFFF) / 0xFF;
  133.     color.blue = (blue * 0xFFFF) / 0xFF;
  134.     color.flags = DoRed | DoGreen | DoBlue;
  135.  
  136.     if (!XAllocColor(g_display, DefaultColormap(g_display, g_screen), &color)) {
  137.         std::cerr << "createXColorFromRGBA: Cannot create color" << endl;
  138.         exit(-1);
  139.     }
  140.  
  141.     *(&color.pixel) = ((*(&color.pixel)) & 0x00ffffff) | (alpha << 24);
  142.     return color;
  143. }
  144.  
  145. void Draw::openDisplay() {
  146.     g_display = XOpenDisplay(0);
  147.  
  148.     if (!g_display) {
  149.         cerr << "Failed to open X display!" << endl;
  150.         return;
  151.     }
  152.  
  153.     g_screen    = DefaultScreen(g_display);
  154.  
  155.     g_disp_width  = DisplayWidth(g_display, g_screen);
  156.     g_disp_height = DisplayHeight(g_display, g_screen);
  157.  
  158.     if (!XShapeQueryExtension (g_display, &shape_event_base, &shape_error_base)) {
  159.        cerr << "XShape extension is not available in your system!" << endl;
  160.        return;
  161.     }
  162.  
  163.     overlayavailable = true;
  164. }
  165.  
  166. // Create a window
  167. void Draw::createShapedWindow() {
  168.     XSetWindowAttributes wattr;
  169.     XColor bgcolor = createXColorFromRGBA(0, 0, 0, 0);
  170.  
  171.     Window root    = DefaultRootWindow(g_display);
  172.     Visual *visual = DefaultVisual(g_display, g_screen);
  173.  
  174.     XVisualInfo vinfo;
  175.     XMatchVisualInfo(g_display, DefaultScreen(g_display), 32, TrueColor, &vinfo);
  176.     g_colormap = XCreateColormap(g_display, DefaultRootWindow(g_display), vinfo.visual, AllocNone);
  177.  
  178.     XSetWindowAttributes attr;
  179.     attr.background_pixmap = None;
  180.     attr.background_pixel = bgcolor.pixel;
  181.     attr.border_pixel=0;
  182.     attr.win_gravity=NorthWestGravity;
  183.     attr.bit_gravity=ForgetGravity;
  184.     attr.save_under=1;
  185.     attr.event_mask=BASIC_EVENT_MASK;
  186.     attr.do_not_propagate_mask=NOT_PROPAGATE_MASK;
  187.     attr.override_redirect=1; // OpenGL > 0
  188.     attr.colormap = g_colormap;
  189.  
  190.     //unsigned long mask = CWBackPixel|CWBorderPixel|CWWinGravity|CWBitGravity|CWSaveUnder|CWEventMask|CWDontPropagate|CWOverrideRedirect;
  191.     unsigned long mask = CWColormap | CWBorderPixel | CWBackPixel | CWEventMask | CWWinGravity|CWBitGravity | CWSaveUnder | CWDontPropagate | CWOverrideRedirect;
  192.  
  193.     g_win = XCreateWindow(g_display, root, 0, 0, WIDTH, HEIGHT, 0, vinfo.depth, InputOutput, vinfo.visual, mask, &attr);
  194.  
  195.     //XShapeCombineMask(g_display, g_win, ShapeBounding, 900, 500, g_bitmap, ShapeSet);
  196.     XShapeCombineMask(g_display, g_win, ShapeInput, 0, 0, None, ShapeSet );
  197.  
  198.     // We want shape-changed event too
  199.     #define SHAPE_MASK ShapeNotifyMask
  200.     XShapeSelectInput (g_display, g_win, SHAPE_MASK );
  201.  
  202.     // Tell the Window Manager not to draw window borders (frame) or title.
  203.     wattr.override_redirect = 1;
  204.     XChangeWindowAttributes(g_display, g_win, CWOverrideRedirect, &wattr);
  205.     allow_input_passthrough(g_win);
  206.  
  207.     // Show the window
  208.     XMapWindow(g_display, g_win);
  209. }
  210.  
  211. void Draw::startdraw() {
  212.     if(!overlayenabled) return;
  213.  
  214.     fpsmeterc++;
  215.     if(fpsmeterc == FPSMETERSAMPLE) {
  216.         fpsmeterc = 0;
  217.         t1 = t2;
  218.         t2 = std::chrono::high_resolution_clock::now();
  219.         duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
  220.         fpsstring = /*to_string(duration) + " / " +*/ to_string(duration/FPSMETERSAMPLE);
  221.     }
  222.  
  223.     /*// Line width and type
  224.     gcv.line_width = 1;
  225.     gcv.line_style = LineSolid;
  226.     gcv.foreground = red.pixel;
  227.  
  228.     unsigned long mask = GCLineWidth | GCLineStyle | GCForeground;
  229.     gc = XCreateGC(g_display, g_win, mask, &gcv);*/
  230.     XSetBackground (g_display, gc, white.pixel);
  231.     XSetForeground (g_display, gc, red.pixel);
  232.     font = XLoadQueryFont (g_display, font_name);
  233.     XSetFont (g_display, gc, font->fid);
  234.    
  235. }
  236. void Draw::drawstring(const char * text, int x, int y, XColor fgcolor, XColor bgcolor, int align) {
  237.     if(!overlayenabled) return;
  238.  
  239.     int tlen = strlen(text);
  240.     XSetForeground (g_display, gc, bgcolor.pixel);
  241.     XFillRectangle(g_display, g_win, gc, x - (align == ALIGN_CENTER ? tlen*font_width/2 : (align == ALIGN_RIGHT ? tlen*font_width : 0)) - 4, y, tlen*font_width+8, font_height+4);
  242.     XSetForeground (g_display, gc, fgcolor.pixel);
  243.     XDrawString(g_display, g_win, gc, x - (align == ALIGN_CENTER ? tlen*font_width/2 : (align == ALIGN_RIGHT ? tlen*font_width : 0)), y+font_height, text, tlen);
  244. }
  245. void Draw::enddraw() {
  246.     if(!overlayenabled) return;
  247.  
  248.     if(duration > 0.0f) drawstring(fpsstring.c_str(), WIDTH/2, 44, red, blacka, ALIGN_CENTER);
  249.     renderi++;
  250.     if(renderi == CLEARSCREEN_ITERATIONS) {
  251.         clearscreen();
  252.         renderi = 0;
  253.     }
  254.     XFreeFont(g_display, font);
  255.     //XFreeGC(g_display, gc);
  256. }
  257. void Draw::clearscreen() {
  258.     if(!overlayenabled) return;
  259.     XClearArea(g_display, g_win, 0, 0, WIDTH, HEIGHT, false);
  260. }
  261. void Draw::cleararea(int x, int y, int width, int height) {
  262.     if(!overlayenabled) return;
  263.     XClearArea(g_display, g_win, x, y, width, height, false);
  264. }
  265. void Draw::init() {
  266.     openDisplay();
  267.     if(!overlayavailable) {
  268.         fprintf (stderr, "Overlay is not availalbe!\n");
  269.         return;
  270.     }
  271.  
  272.     createShapedWindow();
  273.     gc = XCreateGC (g_display, g_win, 0, 0);
  274.     font = XLoadQueryFont (g_display, font_name);
  275.  
  276.     red = createXColorFromRGBA(255, 0, 0, 255);
  277.     ltblue = createXColorFromRGBA(0, 255, 255, 255);
  278.     blue = createXColorFromRGBA(0, 0, 255, 255);
  279.     black = createXColorFromRGBA(0, 0, 0, 255);
  280.     blacka = createXColorFromRGBA(0, 0, 0, 150);
  281.     blackla = createXColorFromRGBA(0, 0, 0, 80);
  282.     grey = createXColorFromRGBA(110, 110, 110, 255);
  283.     ltgrey = createXColorFromRGBA(170, 170, 170, 255);
  284.     white = createXColorFromRGBA(255, 255, 255, 255);
  285.     yellow = createXColorFromRGBA(255, 255, 0, 255);
  286.     transparent = createXColorFromRGBA(255, 255, 255, 0);
  287.  
  288.     // const char * fontname = "-misc-fixed-bold-r-normal--18-120-100-100-c-90-iso8859-2";
  289.     // const char * fontname = "rk24"; // ~ chinese shit
  290.     // list_fonts();
  291.     font = XLoadQueryFont (g_display, font_name);
  292.     /* If the font could not be loaded, revert to the "fixed" font. */
  293.     if (!font) {
  294.         fprintf (stderr, "Unable to load font %s > using default (fixed)\n", font_name);
  295.         font = XLoadQueryFont (g_display, "fixed");
  296.     }
  297.  
  298. }
  299. void Draw::toggleoverlay(bool state) { if(overlayavailable) overlayenabled = state; }
  300. void Draw::toggleoverlay() { if(overlayavailable) overlayenabled = !overlayenabled; }
  301. void Draw::halt() { if(!overlayavailable) XCloseDisplay(g_display); }
Advertisement
Add Comment
Please, Sign In to add comment