slop.cpp 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #include <chrono>
  2. #include <thread>
  3. #include "slopstates.hpp"
  4. #include "mouse.hpp"
  5. #include "resource.hpp"
  6. #include "keyboard.hpp"
  7. #include "window.hpp"
  8. #include "shader.hpp"
  9. #include "framebuffer.hpp"
  10. #include "glrectangle.hpp"
  11. #include "xshaperectangle.hpp"
  12. #include "slop.hpp"
  13. namespace slop {
  14. X11* x11;
  15. Mouse* mouse;
  16. Keyboard* keyboard;
  17. Resource* resource;
  18. SlopSelection GLSlopSelect( slop::SlopOptions* options, bool* cancelled, slop::SlopWindow* window );
  19. SlopSelection XShapeSlopSelect( slop::SlopOptions* options, bool* cancelled);
  20. }
  21. using namespace slop;
  22. // Defaults!
  23. slop::SlopOptions::SlopOptions() {
  24. borderSize = 1;
  25. nokeyboard = false;
  26. nodecorations = false;
  27. tolerance = 2;
  28. padding = 0;
  29. shader = "textured";
  30. highlight = false;
  31. xdisplay = ":0";
  32. r = 0.5;
  33. g = 0.5;
  34. b = 0.5;
  35. a = 1;
  36. }
  37. slop::SlopSelection::SlopSelection( float x, float y, float w, float h, int id ) {
  38. this->x = x;
  39. this->y = y;
  40. this->w = w;
  41. this->h = h;
  42. this->id = id;
  43. }
  44. slop::SlopSelection slop::SlopSelect( slop::SlopOptions* options, bool* cancelled, bool quiet) {
  45. slop::SlopSelection returnval(0,0,0,0,0);
  46. bool deleteOptions = false;
  47. if ( !options ) {
  48. deleteOptions = true;
  49. options = new slop::SlopOptions();
  50. }
  51. resource = new Resource();
  52. // Set up x11 temporarily
  53. x11 = new X11(options->xdisplay);
  54. keyboard = new Keyboard( x11 );
  55. bool success = false;
  56. std::string errorstring = "";
  57. SlopWindow* window;
  58. // First we check if we have a compositor available
  59. if ( x11->hasCompositor() ) {
  60. // If we have a compositor, we try using OpenGL
  61. try {
  62. window = new SlopWindow();
  63. success = true;
  64. } catch (...) {
  65. success = false;
  66. }
  67. } else {
  68. errorstring += "Failed to detect a compositor, OpenGL hardware-accelleration disabled...\n";
  69. }
  70. if ( !success ) {
  71. // If we fail, we launch the XShape version of slop.
  72. if ( !quiet ) {
  73. if ( errorstring.length() <= 0 ) {
  74. errorstring += "Failed to launch OpenGL context, --shader parameter will be ignored.\n";
  75. std::cerr << errorstring;
  76. } else {
  77. std::cerr << errorstring;
  78. }
  79. }
  80. returnval = slop::XShapeSlopSelect( options, cancelled );
  81. } else {
  82. returnval = slop::GLSlopSelect( options, cancelled, window );
  83. }
  84. delete x11;
  85. delete slop::resource;
  86. if ( deleteOptions ) {
  87. delete options;
  88. }
  89. return returnval;
  90. }
  91. slop::SlopSelection slop::XShapeSlopSelect( slop::SlopOptions* options, bool* cancelled ) {
  92. // Init our little state machine, memory is a tad of a misnomer
  93. slop::SlopMemory memory( options, new XShapeRectangle(glm::vec2(0,0), glm::vec2(0,0), options->borderSize, options->padding, glm::vec4( options->r, options->g, options->b, options->a ), options->highlight) );
  94. slop::mouse = new slop::Mouse( x11, options->nodecorations, ((XShapeRectangle*)memory.rectangle)->window );
  95. // We have no GL context, so the matrix is useless...
  96. glm::mat4 fake;
  97. // This is where we'll run through all of our stuffs
  98. while( memory.running ) {
  99. slop::mouse->update();
  100. slop::keyboard->update();
  101. // We move our statemachine forward.
  102. memory.update( 1 );
  103. // We don't actually draw anything, but the state machine uses
  104. // this to know when to spawn the window.
  105. memory.draw( fake );
  106. // X11 explodes if we update as fast as possible, here's a tiny sleep.
  107. XFlush(x11->display);
  108. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  109. // Then we draw the framebuffer to the screen
  110. if ( (slop::keyboard->anyKeyDown() && !options->nokeyboard) || slop::mouse->getButton( 3 ) ) {
  111. memory.running = false;
  112. if ( cancelled ) {
  113. *cancelled = true;
  114. }
  115. } else {
  116. *cancelled = false;
  117. }
  118. }
  119. // Now we should have a selection! We parse everything we know about it here.
  120. glm::vec4 output = memory.rectangle->getRect();
  121. // Lets now clear both front and back buffers before closing.
  122. // hopefully it'll be completely transparent while closing!
  123. // Then we clean up.
  124. delete slop::mouse;
  125. // Finally return the data.
  126. return slop::SlopSelection( output.x, output.y, output.z, output.w, memory.selectedWindow );
  127. }
  128. slop::SlopSelection slop::GLSlopSelect( slop::SlopOptions* options, bool* cancelled, SlopWindow* window ) {
  129. slop::mouse = new slop::Mouse( x11, options->nodecorations, window->window );
  130. if ( options->shader != "textured" ) {
  131. window->framebuffer->setShader( options->shader );
  132. }
  133. // Init our little state machine, memory is a tad of a misnomer
  134. slop::SlopMemory memory( options, new GLRectangle(glm::vec2(0,0), glm::vec2(0,0), options->borderSize, options->padding, glm::vec4( options->r, options->g, options->b, options->a ), options->highlight) );
  135. // This is where we'll run through all of our stuffs
  136. while( memory.running ) {
  137. slop::mouse->update();
  138. slop::keyboard->update();
  139. // We move our statemachine forward.
  140. memory.update( 1 );
  141. // Then we draw our junk to a framebuffer.
  142. window->framebuffer->bind();
  143. glClearColor (0.0, 0.0, 0.0, 0.0);
  144. glClear (GL_COLOR_BUFFER_BIT);
  145. memory.draw( window->camera );
  146. window->framebuffer->unbind();
  147. // Then we draw the framebuffer to the screen
  148. window->framebuffer->draw();
  149. window->display();
  150. GLenum err = glGetError();
  151. if ( err != GL_NO_ERROR ) {
  152. throw err;
  153. }
  154. if ( (slop::keyboard->anyKeyDown() && !options->nokeyboard) || slop::mouse->getButton( 3 ) ) {
  155. memory.running = false;
  156. if ( cancelled ) {
  157. *cancelled = true;
  158. }
  159. } else {
  160. *cancelled = false;
  161. }
  162. }
  163. // Now we should have a selection! We parse everything we know about it here.
  164. glm::vec4 output = memory.rectangle->getRect();
  165. // Lets now clear both front and back buffers before closing.
  166. // hopefully it'll be completely transparent while closing!
  167. glClearColor (0.0, 0.0, 0.0, 0.0);
  168. glClear (GL_COLOR_BUFFER_BIT);
  169. window->display();
  170. glClear (GL_COLOR_BUFFER_BIT);
  171. window->display();
  172. // Then we clean up.
  173. delete window;
  174. delete slop::mouse;
  175. // Finally return the data.
  176. return slop::SlopSelection( output.x, output.y, output.z, output.w, memory.selectedWindow );
  177. }