Просмотр исходного кода

Merge branch 'slop-release-candidate'

naelstrof 7 лет назад
Родитель
Сommit
ee3b25c6a7
67 измененных файлов: 5304 добавлений и 4779 удалений
  1. 0
    2
      .gitignore
  2. 64
    162
      CMakeLists.txt
  3. 12
    166
      README.md
  4. 0
    91
      cmakemodules/FindImlib2.cmake
  5. 0
    23
      cmakemodules/FindRT.cmake
  6. 0
    26
      cmakemodules/FindXRandr.cmake
  7. 0
    47
      cmakemodules/FindXRender.cmake
  8. 0
    12
      generateReadme.sh
  9. 52
    0
      modules/FindGLM.cmake
  10. 0
    0
      modules/FindGLX.cmake
  11. 0
    0
      modules/FindXExt.cmake
  12. 0
    38
      share/slop/cross.frag
  13. 0
    12
      share/slop/cross.vert
  14. 0
    1
      share/slop/gothic/corner_bl.png
  15. 0
    1
      share/slop/gothic/corner_br.png
  16. Двоичные данные
      share/slop/gothic/corner_tl.png
  17. 0
    1
      share/slop/gothic/corner_tr.png
  18. Двоичные данные
      share/slop/gothic/straight.png
  19. 0
    30
      share/slop/hippie.frag
  20. 0
    12
      share/slop/hippie.vert
  21. 0
    16
      share/slop/invert.frag
  22. 0
    13
      share/slop/invert.vert
  23. 0
    83
      share/slop/refract.frag
  24. 0
    12
      share/slop/refract.vert
  25. 0
    17
      share/slop/ripple.frag
  26. 0
    13
      share/slop/ripple.vert
  27. 0
    12
      share/slop/simple.frag
  28. 0
    12
      share/slop/simple.vert
  29. 0
    20
      share/slop/wiggle.frag
  30. 0
    12
      share/slop/wiggle.vert
  31. 74
    0
      slop.1
  32. Двоичные данные
      slop.1.gz
  33. 0
    893
      src/cmdline.c
  34. 0
    240
      src/cmdline.in
  35. 66
    424
      src/framebuffer.cpp
  36. 37
    36
      src/framebuffer.hpp
  37. 1261
    0
      src/gl_core_3_3.c
  38. 1700
    0
      src/gl_core_3_3.h
  39. 246
    0
      src/glrectangle.cpp
  40. 70
    0
      src/glrectangle.hpp
  41. 0
    683
      src/glselectrectangle.cpp
  42. 0
    102
      src/glselectrectangle.hpp
  43. 53
    0
      src/keyboard.cpp
  44. 22
    13
      src/keyboard.hpp
  45. 169
    529
      src/main.cpp
  46. 125
    0
      src/mouse.cpp
  47. 57
    0
      src/mouse.hpp
  48. 233
    0
      src/options.cpp
  49. 0
    125
      src/options.ggo
  50. 61
    0
      src/options.hpp
  51. 13
    0
      src/rectangle.cpp
  52. 39
    0
      src/rectangle.hpp
  53. 9
    26
      src/resource.cpp
  54. 9
    11
      src/resource.hpp
  55. 60
    67
      src/shader.cpp
  56. 38
    24
      src/shader.hpp
  57. 202
    0
      src/slop.cpp
  58. 60
    0
      src/slop.hpp
  59. 122
    0
      src/slopstates.cpp
  60. 87
    0
      src/slopstates.hpp
  61. 94
    0
      src/window.cpp
  62. 25
    30
      src/window.hpp
  63. 52
    445
      src/x.cpp
  64. 19
    83
      src/x.hpp
  65. 0
    189
      src/xselectrectangle.cpp
  66. 141
    0
      src/xshaperectangle.cpp
  67. 32
    25
      src/xshaperectangle.hpp

+ 0
- 2
.gitignore Просмотреть файл

@@ -1,2 +0,0 @@
1
-# These files are ignored since cmake generates them from cmdline.in
2
-src/cmdline.h

+ 64
- 162
CMakeLists.txt Просмотреть файл

@@ -1,172 +1,74 @@
1
-cmake_minimum_required( VERSION 2.8 )
1
+cmake_minimum_required(VERSION 2.6)
2 2
 
3
-project( "slop" )
4
-set( slop_VERSION_MAJOR 4 )
5
-set( slop_VERSION_MINOR 3 )
6
-set( slop_VERSION_PATCH 21 )
7
-
8
-set( CMAKE_OPENGL_SUPPORT FALSE CACHE BOOL "Whether or not to compile with OpenGL, shaders, magnification, and theming support." )
9
-
10
-set( BIN_TARGET     "${PROJECT_NAME}" )
11
-if( NOT CMAKE_INSTALL_PREFIX )
12
-   set( CMAKE_INSTALL_PREFIX "/usr" )
3
+set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build (Debug or Release)")
4
+if ( NOT CMAKE_INSTALL_PREFIX )
5
+    set(CMAKE_INSTALL_PREFIX "/usr")
13 6
 endif()
14 7
 
15
-if( NOT INSTALL_PREFIX )
16
-   set( INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "The path where slop thinks it resides in, so that it can find the shaders. This is not necessarily the CMAKE_INSTALL_PREFIX. For example if the shaders will exist in /usr/share/slop, INSTALL_PREFIX should be \"/usr\"." )
17
-endif()
8
+project(slop)
18 9
 
19
-if( NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE )
20
-   set( CMAKE_BUILD_TYPE RelWithDebInfo )
21
-endif()
10
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/")
22 11
 
23
-# Linux compiler initialization.
24
-if ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR
25
-     "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
26
-     "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" )
27
-     set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-parameter" )
28
-     set( CMAKE_CXX_FLAGS_DEBUG "-Wextra -pedantic-errors -O0 -g" )
29
-     set( CMAKE_CXX_FLAGS_RELEASE "-O2" )
30
-     set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g" )
31
-         # -Wall:   Enable all warnings.
32
-         # -Wextra: Enable some more warnings.
33
-         # -Werror: Have errors on warnings.
34
-         # -pedantic-errors: Even more errors.
35
-         # -Wno-unused-parameter: Prevent unused variable warning. (Several functions are required to have unecessary variables because X11.)
36
-else()
37
-    message( FATAL_ERROR "Your operating system isn't supported yet! CMake will now exit." )
38
-endif()
12
+set( CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Directory where man pages reside. (/usr/share/man, /usr/local/share/man, etc.)" )
39 13
 
40
-# Add a check target for our makefile.
41
-find_program( CPPCHECK_EXECUTABLE cppcheck
42
-              DOC "A tool for static C/C++ code analysis." )
43
-if (CPPCHECK_EXECUTABLE)
44
-    add_custom_target( "check"
45
-                       COMMAND "${CPPCHECK_EXECUTABLE}" "--enable=all" "*"
46
-                       WORKING_DIRECTORY src VERBATIM )
47
-endif()
14
+set( CMAKE_COMPRESS_MAN TRUE CACHE BOOL "Whether or not to compress the man pages for install." )
48 15
 
49
-# Here we generate some of our code if we can. I package it pre-generated
50
-# so nobody has to go find and install gengetopt if they don't want to.
51
-find_program( GENGETOPT_EXECUTABLE gengetopt
52
-              DOC "A tool to generate code to grab command line options." )
53
-find_program( SED_EXECUTABLE sed )
54
-if ( GENGETOPT_EXECUTABLE AND SED_EXECUTABLE )
55
-    message( "-- Regenerating cmdline.in" )
56
-    # gengetopt generates cmdline.h, then we move it to cmdline.in.
57
-    execute_process( COMMAND "${GENGETOPT_EXECUTABLE}" "--input=options.ggo"
58
-                     WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src" )
59
-    file( RENAME "${CMAKE_CURRENT_SOURCE_DIR}/src/cmdline.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/cmdline.in" )
60
-    # Due to a bug in gengetopt, we have to manually insert some code.
61
-    # Replace the first instance of REPLACEME with some text.
62
-    # Eight backslashes = two in the code because of how many instances of escaping is happening.
63
-    execute_process( COMMAND "${SED_EXECUTABLE}" "-i" "0,/REPLACEME/{s/REPLACEME/X=%x\\\\\\\\nY=%y\\\\\\\\nW=%w\\\\\\\\nH=%h\\\\\\\\nG=%g\\\\\\\\nID=%i\\\\\\\\nCancel=%c\\\\\\\\n/}" "cmdline.c"
64
-                     WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src" )
65
-    # Then replace remaining instances.
66
-    execute_process( COMMAND "${SED_EXECUTABLE}" "-i" "s/REPLACEME/X=%x\\\\nY=%y\\\\nW=%w\\\\nH=%h\\\\nG=%g\\\\nID=%i\\\\nCancel=%c\\\\n/" "cmdline.c"
67
-                     WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src" )
16
+if ( CMAKE_COMPRESS_MAN )
17
+    set( MANTARGET "slop.1.gz" )
68 18
 else()
69
-    message( "Warning: Command gengetopt or sed not found! Won't regenerate command line code. (If you're just compiling this doesn't matter.)" )
70
-endif()
71
-
72
-# By default our src/options.ggo has our cmake versions variables for
73
-# the 'version ""' line. We replace them here.
74
-# The ${CMAKE_SOURCE_DIR} is there to fix problems with OpenBSD's out-of-source build black magic.
75
-configure_file( "src/cmdline.in" "${CMAKE_SOURCE_DIR}/src/cmdline.h" )
76
-
77
-# This allows for "make README.md" to be ran to update the README's help
78
-# section automatically. We don't add it to ALL because running arbitrary
79
-# scripts is unsafe and I don't know if systems will actually have it
80
-# be executbable.
81
-add_custom_target( README.md "./generateReadme.sh" DEPENDS "slop" )
82
-
83
-# Sources
84
-if( CMAKE_OPENGL_SUPPORT )
85
-    set( source
86
-         src/cmdline.c
87
-         src/selectrectangle.cpp
88
-         src/glselectrectangle.cpp
89
-         src/shader.cpp
90
-         src/framebuffer.cpp
91
-         src/resource.cpp
92
-         src/xselectrectangle.cpp
93
-         src/x.cpp
94
-         src/main.cpp )
95
-else()
96
-    set( source
97
-         src/cmdline.c
98
-         src/selectrectangle.cpp
99
-         src/xselectrectangle.cpp
100
-         src/x.cpp
101
-         src/main.cpp )
102
-endif()
103
-
104
-# Obtain library paths and make sure they exist.
105
-set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmakemodules" )
106
-find_package( Imlib2    REQUIRED )
107
-find_package( X11       REQUIRED )
108
-find_package( XExt      REQUIRED )
109
-# This library is needed only for Ubuntu it seems, some platforms don't even
110
-# ship with it. I couldn't find a way to do a test compile to check if librt
111
-# was needed, so instead I just didn't mark it as REQUIRED.
112
-find_package( RT )
113
-
114
-set( CMAKE_CXX_FLAGS
115
-     "${CMAKE_CXX_FLAGS} ${CMAKE_IMLIB2_CXX_FLAGS}" )
116
-
117
-# Includes
118
-include_directories( "${X11_INCLUDE_DIR}"
119
-                     "${XEXT_INCLUDE_DIR}" )
120
-
121
-if ( CMAKE_OPENGL_SUPPORT )
122
-find_package( OpenGL    REQUIRED )
123
-find_package( GLX       REQUIRED )
124
-find_package( XRender   REQUIRED )
125
-find_package( XRandr    REQUIRED )
126
-find_package( GLEW      REQUIRED )
127
-include_directories( "${IMLIB2_INCLUDE_DIR}"
128
-                     "${XRANDR_INCLUDE_DIR}"
129
-                     "${OPENGL_INCLUDE_DIR}"
130
-                     "${GLX_INCLUDE_DIR}"
131
-                     ${GLEW_INCLUDE_DIRS}
132
-                     ${XRENDER_INCLUDE_DIRS} )
133
-endif()
134
-
135
-if ( RT_INCLUDE_DIR )
136
-    include_directories( ${RT_INCLUDE_DIR} )
19
+    set( MANTARGET "slop.1" )
137 20
 endif()
138 21
 
139
-# Executable
140
-add_executable( "${BIN_TARGET}" ${source} )
141
-
142
-# Libraries
143
-target_link_libraries( "${BIN_TARGET}"
144
-                       ${X11_LIBRARIES}
145
-                       "${XEXT_LIBRARY}" )
146
-
147
-if ( CMAKE_OPENGL_SUPPORT )
148
-    target_link_libraries( "${BIN_TARGET}"
149
-                           ${IMLIB2_LIBRARIES}
150
-                           ${OPENGL_LIBRARIES}
151
-                           ${GLX_LIBRARIES}
152
-                           ${GLEW_LIBRARIES}
153
-                           ${XRENDER_LIBRARIES}
154
-                           "${XRANDR_LIBRARY}" )
155
-endif()
156
-
157
-
158
-if ( RT_LIBRARY )
159
-    target_link_libraries( "${BIN_TARGET}"
160
-                           "${RT_LIBRARY}" )
161
-endif()
162
-
163
-install( TARGETS ${BIN_TARGET}
164
-         DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" )
165
-
166
-add_definitions(-DINSTALL_PREFIX="${INSTALL_PREFIX}")
167
-
168
-if( CMAKE_OPENGL_SUPPORT )
169
-    install( DIRECTORY "${CMAKE_SOURCE_DIR}/share"
170
-             DESTINATION "${CMAKE_INSTALL_PREFIX}" )
171
-    add_definitions(-DOPENGL_ENABLED=1)
172
-endif()
22
+include_directories("${PROJECT_BINARY_DIR}")
23
+
24
+add_definitions(-DSLOP_VERSION="v5.3.21")
25
+
26
+# The names have to be unique unfortunately.
27
+set(EXECUTABLE_NAME "slop")
28
+set(LIBRARY_NAME "slopy")
29
+
30
+add_library(${LIBRARY_NAME} SHARED  src/mouse.cpp
31
+                                    src/keyboard.cpp
32
+                                    src/x.cpp
33
+                                    src/slopstates.cpp
34
+                                    src/framebuffer.cpp
35
+                                    src/resource.cpp
36
+                                    src/gl_core_3_3.c
37
+                                    src/shader.cpp
38
+                                    src/window.cpp
39
+                                    src/slop.cpp
40
+                                    src/rectangle.cpp
41
+                                    src/xshaperectangle.cpp
42
+                                    src/glrectangle.cpp)
43
+
44
+set_property(TARGET ${LIBRARY_NAME} PROPERTY CXX_STANDARD 11)
45
+set_property(TARGET ${LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
46
+
47
+add_executable(${EXECUTABLE_NAME} src/options.cpp
48
+                                  src/main.cpp)
49
+
50
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/modules" )
51
+
52
+find_package(GLM REQUIRED)
53
+find_package(X11 REQUIRED)
54
+find_package(XExt REQUIRED)
55
+find_package(GLX REQUIRED)
56
+find_package(OpenGL REQUIRED)
57
+
58
+include_directories(${X11_INCLUDE_DIR}
59
+                    ${GLM_INCLUDE_DIR}
60
+                    ${XEXT_INCLUDE_DIR}
61
+                    ${GLX_INCLUDE_DIR}
62
+                    ${OPENGL_INCLUDE_DIR})
63
+
64
+target_link_libraries(${EXECUTABLE_NAME} ${X11_LIBRARIES}
65
+                                         ${GLM_LIBRARIES}
66
+                                         ${OPENGL_LIBRARIES}
67
+                                         ${GLX_LIBRARY}
68
+                                         ${XEXT_LIBRARIES}
69
+                                         ${LIBRARY_NAME})
70
+
71
+install( TARGETS ${EXECUTABLE_NAME} DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" )
72
+install( TARGETS ${LIBRARY_NAME} DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" )
73
+install( FILES ${CMAKE_SOURCE_DIR}/src/slop.hpp DESTINATION "${CMAKE_INSTALL_PREFIX}/include" COMPONENT development )
74
+install( FILES "${CMAKE_SOURCE_DIR}/${MANTARGET}" DESTINATION  "${CMAKE_INSTALL_MANDIR}/man1" COMPONENT doc )

+ 12
- 166
README.md Просмотреть файл

@@ -1,53 +1,35 @@
1 1
 # slop
2
-
3
-slop (Select Operation) is an application that queries for a selection from the user and prints the region to stdout. It grabs the mouse and turns it into a crosshair, lets the user click and drag to make a selection (or click on a window) while drawing a pretty box around it, then finally prints the selection's dimensions to stdout.
2
+slop (Select Operation) is an application that queries for a selection from the user and prints the region to stdout.
4 3
 
5 4
 ## Features
6 5
 * Hovering over a window will cause a selection rectangle to appear over it.
7
-* Clicking on a window makes slop return the dimensions of the window.
8
-* Clicking and dragging causes a selection rectangle to appear, renders pretty well (compared to scrot). And will return the dimensions of that rectangle in absolute screen coords.
9
-* On startup it turns your cursor into a crosshair, then adjusts the cursor into angles as you drag the selection rectangle.
6
+* Clicking on a window makes slop return the dimensions of the window, and it's ID.
7
+* OpenGL accelerated graphics where possible.
10 8
 * Supports simple arguments:
11 9
     * Change selection rectangle border size.
12 10
     * Select X display.
13
-    * Set padding size, even negative padding sizes!
14
-    * Set click tolerance for if you have a shaky mouse.
11
+    * Set padding size.
12
+    * Force window, or pixel selections with the tolerance flag.
15 13
     * Set the color of the selection rectangles to match your theme! (Even supports transparency!)
16 14
     * Remove window decorations from selections.
17
-* Supports OpenGL hardware acceleration.
18
-* Supports textured themes.
19
-* Supports programmable shaders.
20
-* Supports a magnifying glass.
15
+* Supports custom programmable shaders.
21 16
 
22
-## Practical applications
17
+## Practical Applications
23 18
 slop can be used to create a video recording script in only two lines of code.
24 19
 ```bash
25 20
 #!/bin/bash
26
-eval $(slop)
21
+read -r X Y W H G ID < <(slop -f "%x %y %w %h %g %i")
27 22
 ffmpeg -f x11grab -s "$W"x"$H" -i :0.0+$X,$Y -f alsa -i pulse ~/myfile.webm
28 23
 ```
29
-slop lets you select a region or window and ffmpeg will record it in the format of your choice!
30
-Combined with keybinds and a server on your filesystem you can make a really neat and unobtrusive screenshooter.
31 24
 
32 25
 You can also take images using imagemagick like so:
33 26
 ```bash
34 27
 #!/bin/bash
35
-eval $(slop)
28
+read -r G < <(slop -f "%g")
36 29
 import -window root -crop $G ~/myimage.png
37 30
 ```
38 31
 If you don't like ImageMagick's import: Check out [maim](https://github.com/naelstrof/maim) for a better screenshot utility.
39 32
 
40
-You can see my implementation of slop in a screenshooter here:
41
-https://gist.github.com/naelstrof/6530959
42
-
43
-For those of you who don't want eval to be an integral part of slop (Could be dangerous if I were evil!): You can change the output format and parse it manually like so:
44
-```bash
45
-#!/bin/bash
46
-read -r X Y W H G ID < <(slop -f "%x %y %w %h %g %i")
47
-maim -g "$G" -i "$ID"
48
-ffmpeg -f x11grab -s "$W"x"$H" -i ":0.0+$X,$Y" -f alsa -i pulse ~/myfile.webm
49
-```
50
-
51 33
 ## Lets see some action
52 34
 Ok. Here's a comparison between 'scrot -s's selection and slop's:
53 35
 
@@ -71,152 +53,16 @@ While slop not only looks nicer, it's impossible for it to end up in screenshots
71 53
 * [Debian: slop](https://packages.debian.org/sid/slop)
72 54
 * Please make a package for slop on your favorite system, and make a pull request to add it to this list.
73 55
 
74
-
75 56
 ### Install using CMake (Requires CMake)
76 57
 
77
-*Note: Dependencies should be installed first: libxext, imlib2, mesa, libxrender, libxrandr, glew and glm.*
58
+*Note: Dependencies should be installed first: libxext, OpenGL, and glm.*
78 59
 
79 60
 ```bash
80 61
 git clone https://github.com/naelstrof/slop.git
81 62
 cd slop
82
-cmake -DCMAKE_OPENGL_SUPPORT=true ./
63
+cmake -DCMAKE_INSTALL_PREFIX="/usr" ./
83 64
 make && sudo make install
84 65
 ```
85 66
 
86
-Make sure to check out and install [maim](https://github.com/naelstrof/maim) too if you want a proper screenshot utility.
87
-
88
-## Configuration
89
-Ever since slop had OpenGL support, it now has quite a few customizations that can be done.
90
-
91
-*Note: Configuration directories are located at __${XDG\_CONFIG\_HOME}/slop__ or __${CMAKE\_INSTALL\_PREFIX}/share/slop__, whichever comes first. These will be refferred to as __~/.config/slop__ and __/usr/share/slop__ respectively from here on.*
92
-
93 67
 ### Shaders
94
-[![Demo Shaders](http://farmpolice.com/content/images/slop_demo.gif)](http://farmpolice.com/content/videos/8a5c37c4.webm)
95
-
96
-*Click for video*
97
-
98
-Slop supports shaders that are loaded from the configuration directories.
99
-They're all completely programmable, but they do lack some features like chaining right now.
100
-To configure the shaders or create your own, first copy the global configuration folder to your ~/.config folder like so:
101
-```bash
102
-cp -r /usr/share/slop ~/.config
103
-```
104
-Then edit or add new shaders at ~/.config/slop as if you were editing the originals, slop will reflect the changes on restart.
105
-If there's any missing features in the shaders: don't hesitate to make an issue to request them, and feel free to make your own shaders and submit a pull request to see if it can be officially included!
106
-
107
-### Themes
108
-![Demo Themes](http://farmpolice.com/content/images/1436653680.png)
109
-Slop has primitive support for texture themes, I've included a poorly made *gothic* theme that you can test with `slop --opengl --theme gothic`.
110
-To create your own you'll have to copy the configuration directory, just like with the shaders above, like so:
111
-```bash
112
-cp -r /usr/share/slop ~/.config
113
-```
114
-The theme names are taken from the folder names, the files inside represent the corresponding textures. For example *~/config/gothic/corner\_tr.png* would correspond to the top right square texture in a gothic themed selection.
115
-The theming is still missing offset configuration, and is quite limiting in design. Themes probably won't be flushed out further unless someone makes an issue to request more features.
116
-Feel free to make your own themes and submit a pull request to see if it can be officially included!
117
-
118
-help
119
-----
120
-```text
121
-slop v4.3.21
122
-
123
-Copyright (C) 2014 Dalton Nell, Slop Contributors
124
-(https://github.com/naelstrof/slop/graphs/contributors)
125
-
126
-Usage: slop [options]
127
-
128
-slop (Select Operation) is an application that queries for a selection from the
129
-user and prints the region to stdout.
130
-
131
-  -h, --help                    Print help and exit
132
-  -V, --version                 Print version and exit
133
-Options
134
-      --xdisplay=hostname:number.screen_number
135
-                                Sets the x display.
136
-      --nokeyboard              Disables the ability to cancel selections with
137
-                                  the keyboard.  (default=off)
138
-  -b, --bordersize=INT          Set the selection rectangle's thickness. Does
139
-                                  nothing when --highlight is enabled.
140
-                                  (default=`5')
141
-  -p, --padding=INT             Set the padding size of the selection. Can be
142
-                                  negative.  (default=`0')
143
-  -t, --tolerance=INT           How far in pixels the mouse can move after
144
-                                  clicking and still be detected as a normal
145
-                                  click instead of a click and drag. Setting
146
-                                  this to 0 will disable window selections.
147
-                                  (default=`2')
148
-  -g, --gracetime=FLOAT         Set the amount of time before slop will check
149
-                                  for keyboard cancellations in seconds.
150
-                                  (default=`0.4')
151
-  -c, --color=FLOAT,FLOAT,FLOAT,FLOAT
152
-                                Set the selection rectangle's color. Supports
153
-                                  RGB or RGBA values.
154
-                                  (default=`0.5,0.5,0.5,1')
155
-  -n, --nodecorations           Attempt to select child windows in order to
156
-                                  avoid window decorations.  (default=off)
157
-      --min=INT                 Set the minimum output of width or height
158
-                                  values. This is useful to avoid outputting 0.
159
-                                  Setting min and max to the same value
160
-                                  disables drag selections.  (default=`0')
161
-      --max=INT                 Set the maximum output of width or height
162
-                                  values. Setting min and max to the same value
163
-                                  disables drag selections.  (default=`0')
164
-  -l, --highlight               Instead of outlining selections, slop
165
-                                  highlights it. This is only useful when
166
-                                  --color is set to a transparent color.
167
-                                  (default=off)
168
-      --opengl                  Enable hardware acceleration. Only works with
169
-                                  modern systems that are also running a
170
-                                  compositor.  (default=off)
171
-      --magnify                 Display a magnifying glass when --opengl is
172
-                                  also enabled.  (default=off)
173
-      --magstrength=FLOAT       Sets how many times the magnification window
174
-                                  size is multiplied.  (default=`4')
175
-      --magpixels=INT           Sets how many pixels are displayed in the
176
-                                  magnification. The less pixels the bigger the
177
-                                  magnification.  (default=`64')
178
-      --theme=STRING            Sets the theme of the selection, using textures
179
-                                  from ~/.config/slop/ or /usr/share/.
180
-                                  (default=`none')
181
-      --shader=STRING           Sets the shader to load and use from
182
-                                  ~/.config/slop/ or /usr/share/.
183
-                                  (default=`simple')
184
-  -f, --format=STRING           Set the output format string. Format specifiers
185
-                                  are %x, %y, %w, %h, %i, %g, and %c.
186
-                                  (default=`X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n')
187
-
188
-Examples
189
-    $ # Gray, thick, transparent border for maximum visiblity.
190
-    $ slop -b 20 -c 0.5,0.5,0.5,0.8
191
-
192
-    $ # Remove window decorations.
193
-    $ slop --nodecorations
194
-
195
-    $ # Disable window selections. Useful for selecting individual pixels.
196
-    $ slop -t 0
197
-
198
-    $ # Classic Windows XP selection.
199
-    $ slop -l -c 0.3,0.4,0.6,0.4
200
-
201
-    $ # Wiggle wiggle!
202
-    $ slop --opengl --shader wiggle
203
-
204
-    $ # Edgy textures or something.
205
-    $ slop --opengl --theme gothic
206
-
207
-    $ # Change output format to use safer parsing
208
-    $ slopoutput=$(slop -f "%x %y %w %h")
209
-    $ X=$(echo $slopoutput | awk '{print $1}')
210
-    $ Y=$(echo $slopoutput | awk '{print $2}')
211
-    $ W=$(echo $slopoutput | awk '{print $3}')
212
-    $ H=$(echo $slopoutput | awk '{print $4}')
213
-
214
-Tips
215
-    * You can use the arrow keys to move the starting point of a
216
-drag-selection, just in case you missed it by a few pixels.
217
-    * If you don't like a selection: you can cancel it by right-clicking
218
-regardless of which options are enabled or disabled for slop.
219
-    * If slop doesn't seem to select a window accurately, the problem could be
220
-because of decorations getting in the way. Try enabling the --nodecorations
221
-flag.
222
-```
68
+These are implemented, but not flushed out. I haven't gotten around to writing some tutorials on them. So check back later!

+ 0
- 91
cmakemodules/FindImlib2.cmake Просмотреть файл

@@ -1,91 +0,0 @@
1
-#
2
-# This module finds if IMLIB2 is available and determines where the
3
-# include files and libraries are.
4
-# On Unix/Linux it relies on the output of imlib2-config.
5
-# This code sets the following variables:
6
-#
7
-#
8
-#
9
-# IMLIB2_FOUND              = system has IMLIB2 lib
10
-#
11
-# IMLIB2_LIBRARIES          = full path to the libraries
12
-#    on Unix/Linux with additional linker flags from "imlib2-config --libs"
13
-#
14
-# CMAKE_IMLIB2_CXX_FLAGS    = Unix compiler flags for IMLIB2, essentially "`imlib2-config --cxxflags`"
15
-#
16
-# IMLIB2_INCLUDE_DIR        = where to find headers
17
-#
18
-# IMLIB2_LINK_DIRECTORIES   = link directories, useful for rpath on Unix
19
-#
20
-#
21
-# author Jan Woetzel and Jan-Friso Evers
22
-# www.mip.informatik.uni-kiel.de/~jw
23
-
24
-IF(WIN32)
25
-    MESSAGE("FindIMLIB2.cmake: IMLIB2 not (yet) supported on WIN32")
26
-    SET(IMLIB2_FOUND OFF	)
27
-ELSE(WIN32)
28
-    IF(UNIX)
29
-        SET(IMLIB2_CONFIG_PREFER_PATH "$ENV{IMLIB2_HOME}/bin" CACHE STRING "preferred path to imlib2")
30
-        FIND_PROGRAM(IMLIB2_CONFIG imlib2-config
31
-                     ${IMLIB2_CONFIG_PREFER_PATH}
32
-                     /usr/bin/
33
-                     /opt/gnome/bin/)
34
-
35
-        IF (IMLIB2_CONFIG)
36
-            # OK, found imlib2-config.
37
-            # set CXXFLAGS to be fed into CXX_FLAGS by the user:
38
-            SET(IMLIB2_CXX_FLAGS "`${IMLIB2_CONFIG} --cflags`")
39
-
40
-            # set INCLUDE_DIRS to prefix+include
41
-            EXEC_PROGRAM(${IMLIB2_CONFIG}
42
-            ARGS --prefix
43
-            OUTPUT_VARIABLE IMLIB2_PREFIX)
44
-            SET(IMLIB2_INCLUDE_DIR ${IMLIB2_PREFIX}/include CACHE STRING INTERNAL)
45
-
46
-            # extract link dirs for rpath
47
-            EXEC_PROGRAM(${IMLIB2_CONFIG}
48
-                         ARGS --libs
49
-                         OUTPUT_VARIABLE IMLIB2_CONFIG_LIBS)
50
-
51
-            # set link libraries and link flags
52
-            #SET(IMLIB2_LIBRARIES "`${IMLIB2_CONFIG} --libs`")
53
-            SET(IMLIB2_LIBRARIES ${IMLIB2_CONFIG_LIBS})
54
-
55
-            # split off the link dirs (for rpath)
56
-            # use regular expression to match wildcard equivalent "-L*<endchar>"
57
-            # with <endchar> is a space or a semicolon
58
-            STRING(REGEX MATCHALL "[-][L]([^ ;])+"
59
-                   IMLIB2_LINK_DIRECTORIES_WITH_PREFIX
60
-                   "${IMLIB2_CONFIG_LIBS}")
61
-            #MESSAGE("DBG  IMLIB2_LINK_DIRECTORIES_WITH_PREFIX=${IMLIB2_LINK_DIRECTORIES_WITH_PREFIX}")
62
-
63
-            # remove prefix -L because we need the pure directory for LINK_DIRECTORIES
64
-            # replace -L by ; because the separator seems to be lost otherwise (bug or feature?)
65
-            IF (IMLIB2_LINK_DIRECTORIES_WITH_PREFIX)
66
-                STRING(REGEX REPLACE "[-][L]" ";" IMLIB2_LINK_DIRECTORIES ${IMLIB2_LINK_DIRECTORIES_WITH_PREFIX} )
67
-                #MESSAGE("DBG  IMLIB2_LINK_DIRECTORIES=${IMLIB2_LINK_DIRECTORIES}")
68
-            ENDIF (IMLIB2_LINK_DIRECTORIES_WITH_PREFIX)
69
-
70
-            # replace space separated string by semicolon separated vector to make 
71
-            # it work with LINK_DIRECTORIES
72
-            SEPARATE_ARGUMENTS(IMLIB2_LINK_DIRECTORIES)
73
-
74
-            MARK_AS_ADVANCED(IMLIB2_CXX_FLAGS
75
-                             IMLIB2_INCLUDE_DIR
76
-                             IMLIB2_LIBRARIES
77
-                             IMLIB2_LINK_DIRECTORIES
78
-                             IMLIB2_CONFIG_PREFER_PATH
79
-                             IMLIB2_CONFIG)
80
-
81
-        ELSE(IMLIB2_CONFIG)
82
-            MESSAGE( "FindIMLIB2.cmake: imlib2-config not found. Please set it manually. IMLIB2_CONFIG=${IMLIB2_CONFIG}")
83
-        ENDIF(IMLIB2_CONFIG)
84
-    ENDIF(UNIX)
85
-ENDIF(WIN32)
86
-
87
-IF(IMLIB2_LIBRARIES)
88
-    IF(IMLIB2_INCLUDE_DIR OR IMLIB2_CXX_FLAGS)
89
-        SET(IMLIB2_FOUND 1)
90
-    ENDIF(IMLIB2_INCLUDE_DIR OR IMLIB2_CXX_FLAGS)
91
-ENDIF(IMLIB2_LIBRARIES)

+ 0
- 23
cmakemodules/FindRT.cmake Просмотреть файл

@@ -1,23 +0,0 @@
1
-# - Find rt
2
-# Find the rt libraries, this is to fix ubuntu not having clock_gettime defined without it.
3
-#
4
-#  This module defines the following variables:
5
-#     RT_FOUND        - 1 if RT_INCLUDE_DIR & RT_LIBRARY are found, 0 otherwise
6
-#     RT_INCLUDE_DIR  - where to find Xlib.h, etc.
7
-#     RT_LIBRARY      - the X11 library
8
-#
9
-
10
-find_path( RT_INCLUDE_DIR
11
-           NAMES time.h )
12
-
13
-find_library( RT_LIBRARY
14
-              NAMES rt
15
-              PATHS /usr/lib /lib )
16
-
17
-if( RT_INCLUDE_DIR AND RT_LIBRARY )
18
-    set( RT_FOUND 1 )
19
-else()
20
-    set( RT_FOUND 0 )
21
-endif()
22
-
23
-mark_as_advanced( RT_INCLUDE_DIR RT_LIBRARY )

+ 0
- 26
cmakemodules/FindXRandr.cmake Просмотреть файл

@@ -1,26 +0,0 @@
1
-# - Find XRandr
2
-# Find the XRandr libraries
3
-#
4
-#  This module defines the following variables:
5
-#     XRANDR_FOUND        - 1 if XRANDR_INCLUDE_DIR & XRANDR_LIBRARY are found, 0 otherwise
6
-#     XRANDR_INCLUDE_DIR  - where to find Xlib.h, etc.
7
-#     XRANDR_LIBRARY      - the X11 library
8
-#
9
-
10
-find_path( XRANDR_INCLUDE_DIR
11
-           NAMES X11/extensions/Xrandr.h
12
-           PATH_SUFFIXES X11/extensions
13
-           DOC "The XRandr include directory" )
14
-
15
-find_library( XRANDR_LIBRARY
16
-              NAMES Xrandr
17
-              PATHS /usr/lib /lib
18
-              DOC "The XRandr library" )
19
-
20
-if( XRANDR_INCLUDE_DIR AND XRANDR_LIBRARY )
21
-    set( XRANDR_FOUND 1 )
22
-else()
23
-    set( XRANDR_FOUND 0 )
24
-endif()
25
-
26
-mark_as_advanced( XRANDR_INCLUDE_DIR XRANDR_LIBRARY )

+ 0
- 47
cmakemodules/FindXRender.cmake Просмотреть файл

@@ -1,47 +0,0 @@
1
-# - Find XRender
2
-# Find the XRender libraries
3
-#
4
-# This module defines the following variables:
5
-#   XRENDER_FOUND - true if XRENDER_INCLUDE_DIR & XRENDER_LIBRARY are found
6
-#   XRENDER_LIBRARIES - Set when Xrender_LIBRARY is found
7
-#   XRENDER_INCLUDE_DIRS - Set when Xrender_INCLUDE_DIR is found
8
-#
9
-#   XRENDER_INCLUDE_DIR - where to find Xrender.h, etc.
10
-#   XRENDER_LIBRARY - the Xrender library
11
-#
12
-
13
-#=============================================================================
14
-# Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
15
-#
16
-# Licensed under the Apache License, Version 2.0 (the "License");
17
-# you may not use this file except in compliance with the License.
18
-# You may obtain a copy of the License at
19
-#
20
-#     http://www.apache.org/licenses/LICENSE-2.0
21
-#
22
-# Unless required by applicable law or agreed to in writing, software
23
-# distributed under the License is distributed on an "AS IS" BASIS,
24
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
-# See the License for the specific language governing permissions and
26
-# limitations under the License.
27
-#=============================================================================
28
-
29
-find_path(XRENDER_INCLUDE_DIR NAMES X11/extensions/Xrender.h
30
-          PATHS /opt/X11/include
31
-          DOC "The Xrender include directory")
32
-
33
-find_library(XRENDER_LIBRARY NAMES Xrender
34
-          PATHS /opt/X11/lib
35
-          DOC "The Xrender library")
36
-
37
-include(FindPackageHandleStandardArgs)
38
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xrender DEFAULT_MSG XRENDER_LIBRARY XRENDER_INCLUDE_DIR)
39
-
40
-if(XRENDER_FOUND)
41
-
42
-    set(XRENDER_LIBRARIES ${XRENDER_LIBRARY})
43
-    set(XRENDER_INCLUDE_DIRS ${XRENDER_INCLUDE_DIR})
44
-
45
-endif()
46
-
47
-mark_as_advanced(XRENDER_INCLUDE_DIR XRENDER_LIBRARY)

+ 0
- 12
generateReadme.sh Просмотреть файл

@@ -1,12 +0,0 @@
1
-#!/bin/sh
2
-# generateReadme.sh: Regenerates the help section of the README.md using output from ./slop --help.
3
-
4
-# Remove help section
5
-sed -i '/^help/,/^```$/d' README.md
6
-
7
-# Add the help section again.
8
-echo 'help' >> README.md
9
-echo '----' >> README.md
10
-echo '```text' >> README.md
11
-echo "$(./slop --help)" >> README.md
12
-echo '```' >> README.md

+ 52
- 0
modules/FindGLM.cmake Просмотреть файл

@@ -0,0 +1,52 @@
1
+#
2
+# Find GLM
3
+#
4
+# Try to find GLM : OpenGL Mathematics.
5
+# This module defines 
6
+# - GLM_INCLUDE_DIRS
7
+# - GLM_FOUND
8
+#
9
+# The following variables can be set as arguments for the module.
10
+# - GLM_ROOT_DIR : Root library directory of GLM 
11
+#
12
+# References:
13
+# - https://github.com/Groovounet/glm/blob/master/util/FindGLM.cmake
14
+# - https://bitbucket.org/alfonse/gltut/src/28636298c1c0/glm-0.9.0.7/FindGLM.cmake
15
+#
16
+
17
+# Additional modules
18
+include(FindPackageHandleStandardArgs)
19
+
20
+if (WIN32)
21
+	# Find include files
22
+	find_path(
23
+		GLM_INCLUDE_DIR
24
+		NAMES glm/glm.hpp
25
+		PATHS
26
+		$ENV{PROGRAMFILES}/include
27
+		${GLM_ROOT_DIR}/include
28
+		DOC "The directory where glm/glm.hpp resides")
29
+else()
30
+	# Find include files
31
+	find_path(
32
+		GLM_INCLUDE_DIR
33
+		NAMES glm/glm.hpp
34
+		PATHS
35
+		/usr/include
36
+		/usr/local/include
37
+		/sw/include
38
+		/opt/local/include
39
+		${GLM_ROOT_DIR}/include
40
+		DOC "The directory where glm/glm.hpp resides")
41
+endif()
42
+
43
+# Handle REQUIRD argument, define *_FOUND variable
44
+find_package_handle_standard_args(GLM DEFAULT_MSG GLM_INCLUDE_DIR)
45
+
46
+# Define GLM_INCLUDE_DIRS
47
+if (GLM_FOUND)
48
+	set(GLM_INCLUDE_DIRS ${GLM_INCLUDE_DIR})
49
+endif()
50
+
51
+# Hide some variables
52
+mark_as_advanced(GLM_INCLUDE_DIR)

cmakemodules/FindGLX.cmake → modules/FindGLX.cmake Просмотреть файл


cmakemodules/FindXExt.cmake → modules/FindXExt.cmake Просмотреть файл


+ 0
- 38
share/slop/cross.frag Просмотреть файл

@@ -1,38 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform int desktopWidth;
6
-uniform int desktopHeight;
7
-uniform float time;
8
-
9
-varying vec2 uvCoord;
10
-
11
-void main() {
12
-    float stitching_size = 6.0;
13
-    int invert = 0;
14
-
15
-    float size = stitching_size;
16
-    vec2 cPos = uvCoord * vec2(desktopWidth, desktopHeight);
17
-    vec2 tlPos = floor(cPos / vec2(size, size));
18
-    tlPos *= size;
19
-    int remX = int(mod(cPos.x, size));
20
-    int remY = int(mod(cPos.y, size));
21
-    if (remX == 0 && remY == 0)
22
-    tlPos = cPos;
23
-    vec2 blPos = tlPos;
24
-    blPos.y += (size - 1.0);
25
-    if ((remX == remY) || (((int(cPos.x) - int(blPos.x)) == (int(blPos.y) - int(cPos.y))))) {
26
-        if (invert == 1) {
27
-            gl_FragColor = vec4(0.2, 0.15, 0.05, 1.0);
28
-        } else {
29
-            gl_FragColor = texture2D(texture, tlPos * vec2(1.0/desktopWidth, 1.0/desktopHeight)) * 1.4;
30
-        }
31
-    } else {
32
-        if (invert == 1) {
33
-            gl_FragColor = texture2D(texture, tlPos * vec2(1.0/desktopWidth, 1.0/desktopHeight)) * 1.4;
34
-        } else {
35
-            gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
36
-        }
37
-    }
38
-}

+ 0
- 12
share/slop/cross.vert Просмотреть файл

@@ -1,12 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-	gl_Position = vec4(vertex,0,1);
12
-}

+ 0
- 1
share/slop/gothic/corner_bl.png Просмотреть файл

@@ -1 +0,0 @@
1
-corner_tl.png

+ 0
- 1
share/slop/gothic/corner_br.png Просмотреть файл

@@ -1 +0,0 @@
1
-corner_tl.png

Двоичные данные
share/slop/gothic/corner_tl.png Просмотреть файл


+ 0
- 1
share/slop/gothic/corner_tr.png Просмотреть файл

@@ -1 +0,0 @@
1
-corner_tl.png

Двоичные данные
share/slop/gothic/straight.png Просмотреть файл


+ 0
- 30
share/slop/hippie.frag Просмотреть файл

@@ -1,30 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform int desktopWidth;
6
-uniform int desktopHeight;
7
-uniform float time;
8
-
9
-varying vec2 uvCoord;
10
-
11
-const float pi = 3.14159265f;
12
-
13
-vec3 color(float x) {
14
-    return max(min(sin(vec3(x,x+pi*2.0/3.0,x+pi*4.0/3.0))+0.5,1.0),0.0);
15
-}
16
-
17
-void main() {
18
-    vec2 resolution = vec2( desktopWidth, desktopHeight );
19
-    vec2 pos = (( gl_FragCoord.xy / resolution.xy )-0.5)*resolution.xy/resolution.x*4.0;
20
-    pos+=normalize(pos);
21
-    pos.xy+=sin(pos.yx*10.0)*0.1;
22
-    float r=(2.0/(dot(pos,pos)*10.0+1.0));
23
-    vec2 rr=vec2(cos(r),sin(r));
24
-    pos=pos.xy*rr.xx+pos.yx*rr.yy*vec2(-1.0,1.0);
25
-    float f=(length(pos)*10.0)+time;
26
-    //f=acos((pos.x/length(pos)*0.5+0.5)*pi);
27
-    f+=sin(atan(pos.y,pos.x)*7.0)*5.0;
28
-    float alpha = texture2D(texture,uvCoord).a;
29
-    gl_FragColor = vec4(color(f),alpha);
30
-}

+ 0
- 12
share/slop/hippie.vert Просмотреть файл

@@ -1,12 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-	gl_Position = vec4(vertex,0,1);
12
-}

+ 0
- 16
share/slop/invert.frag Просмотреть файл

@@ -1,16 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform int desktopWidth;
6
-uniform int desktopHeight;
7
-uniform float time;
8
-
9
-varying vec2 uvCoord;
10
-
11
-void main() {
12
-    vec2 uv = vec2( uvCoord.x, -uvCoord.y );
13
-    vec4 color = texture2D(desktop,uv);
14
-    float alpha = texture2D(texture,uvCoord).a;
15
-    gl_FragColor = vec4( 1.0 - color.r, 1.0 - color.g, 1.0 - color.b, alpha );
16
-}

+ 0
- 13
share/slop/invert.vert Просмотреть файл

@@ -1,13 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-    gl_Position = vec4(vertex,0,1);
12
-}
13
-

+ 0
- 83
share/slop/refract.frag Просмотреть файл

@@ -1,83 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform int desktopWidth;
6
-uniform int desktopHeight;
7
-uniform float time;
8
-
9
-varying vec2 uvCoord;
10
-
11
-vec2 getDesktopUV( vec2 uv ) {
12
-    // Desktop image is upside-down, blame X11 lmao
13
-    uv.y = -uv.y;
14
-    return uv;
15
-}
16
-
17
-const float pi = 3.14159265f;
18
-
19
-void main() {
20
-    float sigma = 5;
21
-    float numBlurPixelsPerSide = 2.0f;
22
-    float blurMultiplier = 2.0f;
23
-
24
-    vec2 tc = uvCoord.xy;
25
-    vec2 p = -1.0 + 2.0 * tc;
26
-    float len = length(p);
27
-    vec2 offset = (p/len)*cos(len*12.0-time*4.0)*0.005;
28
-
29
-    // Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
30
-    float blurSize = 1.f/desktopWidth*blurMultiplier;
31
-    vec2 blurMultiplyVec      = vec2(0.0f, 1.0f);
32
-    vec3 incrementalGaussian;
33
-    incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * sigma);
34
-    incrementalGaussian.y = exp(-0.5f / (sigma * sigma));
35
-    incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
36
-
37
-    vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
38
-    float coefficientSum = 0.0f;
39
-
40
-    // Take the central sample first...
41
-    vec4 color = texture2D( desktop, getDesktopUV( uvCoord.xy ) + offset );
42
-    color.a = texture2D( texture, uvCoord.xy ).a;
43
-    avgValue += color * incrementalGaussian.x;
44
-    coefficientSum += incrementalGaussian.x;
45
-    incrementalGaussian.xy *= incrementalGaussian.yz;
46
-
47
-    // Go through the remaining 8 vertical samples (4 on each side of the center)
48
-    for (float i = 1.0f; i <= numBlurPixelsPerSide; i++) {
49
-        vec2 uv = (uvCoord.xy - i * blurSize * blurMultiplyVec);
50
-        color = texture2D( desktop, getDesktopUV( uv ) + offset );
51
-        color.a = texture2D( texture, uv ).a;
52
-        avgValue += color * incrementalGaussian.x;
53
-        uv = (uvCoord.xy + i * blurSize * blurMultiplyVec);
54
-        color = texture2D( desktop, getDesktopUV( uv ) + offset );
55
-        color.a = texture2D( texture, uv ).a;
56
-        avgValue += color * incrementalGaussian.x;
57
-        coefficientSum += 2 * incrementalGaussian.x;
58
-        incrementalGaussian.xy *= incrementalGaussian.yz;
59
-    }
60
-
61
-    //Reset
62
-    blurSize = 1.f/desktopWidth*blurMultiplier;
63
-    blurMultiplyVec      = vec2(1.0f, 0.0f);
64
-    incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * sigma);
65
-    incrementalGaussian.y = exp(-0.5f / (sigma * sigma));
66
-    incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
67
-
68
-    // Go through the remaining 8 horizontal samples (4 on each side of the center)
69
-    for (float i = 1.0f; i <= numBlurPixelsPerSide; i++) {
70
-        vec2 uv = (uvCoord.xy - i * blurSize * blurMultiplyVec);
71
-        vec4 color = texture2D( desktop, getDesktopUV( uv ) + offset );
72
-        color.a = texture2D( texture, uv ).a;
73
-        avgValue += color * incrementalGaussian.x;
74
-        uv = (uvCoord.xy + i * blurSize * blurMultiplyVec);
75
-        color = texture2D( desktop, getDesktopUV( uv ) + offset );
76
-        color.a = texture2D( texture, uv ).a;
77
-        avgValue += color * incrementalGaussian.x;
78
-        coefficientSum += 2 * incrementalGaussian.x;
79
-        incrementalGaussian.xy *= incrementalGaussian.yz;
80
-    }
81
-
82
-    gl_FragColor = avgValue / coefficientSum;
83
-}

+ 0
- 12
share/slop/refract.vert Просмотреть файл

@@ -1,12 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-	gl_Position = vec4(vertex,0,1);
12
-}

+ 0
- 17
share/slop/ripple.frag Просмотреть файл

@@ -1,17 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform int desktopWidth;
6
-uniform int desktopHeight;
7
-uniform float time;
8
-
9
-varying vec2 uvCoord;
10
-
11
-void main() {
12
-    vec2 tc = uvCoord.xy;
13
-    vec2 p = -1.0 + 2.0 * tc;
14
-    float len = length(p);
15
-    vec2 uv = tc + (p/len)*cos(len*12.0-time*4.0)*0.02;
16
-    gl_FragColor = texture2D(texture,uv);
17
-}

+ 0
- 13
share/slop/ripple.vert Просмотреть файл

@@ -1,13 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-    gl_Position = vec4(vertex,0,1);
12
-}
13
-

+ 0
- 12
share/slop/simple.frag Просмотреть файл

@@ -1,12 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform float time;
6
-
7
-varying vec2 uvCoord;
8
-
9
-void main()
10
-{
11
-    gl_FragColor = texture2D( texture, uvCoord );
12
-}

+ 0
- 12
share/slop/simple.vert Просмотреть файл

@@ -1,12 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-	gl_Position = vec4(vertex,0,1);
12
-}

+ 0
- 20
share/slop/wiggle.frag Просмотреть файл

@@ -1,20 +0,0 @@
1
-#version 120
2
-
3
-uniform sampler2D texture;
4
-uniform sampler2D desktop;
5
-uniform int desktopWidth;
6
-uniform int desktopHeight;
7
-uniform float time;
8
-
9
-varying vec2 uvCoord;
10
-
11
-void main()
12
-{
13
-    // Higher strength means bigger wobble
14
-    float strength = 8;
15
-    // Higher speed means faster wobble
16
-    float speed = 2;
17
-    float x = uvCoord.x + (sin( time*speed + uvCoord.y * desktopHeight/strength ) + 0.5)/desktopWidth*strength;
18
-    float y = uvCoord.y + (cos( time*speed + uvCoord.x * desktopWidth/strength ) + 0.5)/desktopHeight*strength;
19
-    gl_FragColor = texture2D( texture, vec2( x, y ) );
20
-}

+ 0
- 12
share/slop/wiggle.vert Просмотреть файл

@@ -1,12 +0,0 @@
1
-#version 120
2
-
3
-attribute vec2 vertex;
4
-attribute vec2 uv;
5
-
6
-varying vec2 uvCoord;
7
-
8
-void main()
9
-{
10
-    uvCoord = uv;
11
-	gl_Position = vec4(vertex,0,1);
12
-}

+ 74
- 0
slop.1 Просмотреть файл

@@ -0,0 +1,74 @@
1
+.\" Manpage for slop.
2
+.\" Contact naelstrof@gmail.com to correct errors or typos.
3
+.TH SLOP 1 2017-03-21 Linux "slop man page"
4
+.SH NAME
5
+slop \- select operation
6
+.SH SYNOPSIS
7
+slop [-klqn] [OPTIONS]
8
+.SH DESCRIPTION
9
+slop is an application that queries for a selection from the user and prints the region to stdout. It grabs the mouse and turns it into a crosshair, lets the user click and drag to make a selection (or click on a window) while drawing a pretty box around it, then finally prints the selection's dimensions to stdout.
10
+.SH OPTIONS
11
+.TP
12
+.BR \-h ", " \-\-help
13
+Print help and exit.
14
+.TP
15
+.BR \-v ", " \-\-version
16
+Print version and exit.
17
+.TP
18
+.BR \-x ", " \-\-xdisplay=\fIhostname:number.screen_number\fR
19
+Sets the xdisplay to use.
20
+.TP
21
+.BR \-b ", " \-\-bordersize=\fIFLOAT\fR
22
+Sets the selection rectangle's thickness.
23
+.TP
24
+.BR \-p ", " \-\-padding=\fIFLOAT\fR
25
+Sets the padding size for the selection, this can be negative.
26
+.TP
27
+.BR \-t ", " \-\-tolerance=\fIFLOAT\fR
28
+How far in pixels the mouse can move after clicking, and still be detected as a normal click instead of a click-and-drag. Setting this to 0 will disable window selections. Alternatively setting it to 9999999 would force a window selection.
29
+.TP
30
+.BR \-c ", " \-\-color=\fIFLOAT,FLOAT,FLOAT,FLOAT\fR
31
+Sets the selection rectangle's color. Supports RGB or RGBA input. Depending on the system's window manager/OpenGL support, the opacity may be ignored.
32
+.TP
33
+.BR \-r ", " \-\-shader=\fISTRING\fR
34
+This sets the vertex shader, and fragment shader combo to use when drawing the final framebuffer to the screen. This obviously only works when OpenGL is enabled. The shaders are loaded from ~/.config/slop. See https://github.com/naelstrof/slop for more information on how to create your own shaders.
35
+.TP
36
+.BR \-f ", " \-\-format=\fISTRING\fR
37
+Sets the output format for slop. Format specifiers are %x, %y, %w, %h, %i, and %g. If actual percentage signs are desired in output, use a double percentage sign like so `%%`.
38
+.TP
39
+.BR \-n ", " \-\-nodecorations=INT
40
+Sets the level of aggressiveness when trying to remove window decroations. `0' is off, `1' will try lightly to remove decorations, and `2' will recursively descend into the root tree until it gets the deepest available visible child under the mouse. Defaults to `0'.
41
+.TP
42
+.BR \-l ", " \-\-highlight
43
+Instead of outlining a selection, slop will highlight it instead. This is particularly useful if the color is set to an opacity lower than 1.
44
+.TP
45
+.BR \-q ", " \-\-quiet
46
+Disable any unnecessary cerr output. Any warnings simply won't print.
47
+.TP
48
+.BR \-k ", " \-\-nokeyboard
49
+Disables the ability to cancel selections with the keyboard.
50
+.SH EXAMPLES
51
+To emulate a windows XP selection, you can use something like this:
52
+.PP
53
+.nf
54
+.RS
55
+slop --highlight --tolerance=0 --color=0.3,0.4,0.6,0.4
56
+.RE
57
+.fi
58
+.PP
59
+In order to avoid using
60
+.BR eval(1)
61
+in your scripts (pretty big security issue), you can use slop like this instead:
62
+.PP
63
+.nf
64
+.RS
65
+read -r X Y W H G ID < <(slop -f "%x %y %w %h %g %i")
66
+.RE
67
+.fi
68
+.PP
69
+.SH SEE ALSO
70
+.BR maim(1) 
71
+.SH BUGS
72
+No known bugs.
73
+.SH AUTHOR
74
+Dalton Nell (naelstrof@gmail.com)

Двоичные данные
slop.1.gz Просмотреть файл


+ 0
- 893
src/cmdline.c Просмотреть файл

@@ -1,893 +0,0 @@
1
-/*
2
-  File autogenerated by gengetopt version 2.22.6
3
-  generated with the following command:
4
-  /usr/bin/gengetopt --input=options.ggo 
5
-
6
-  The developers of gengetopt consider the fixed text that goes in all
7
-  gengetopt output files to be in the public domain:
8
-  we make no copyright claims on it.
9
-*/
10
-
11
-/* If we use autoconf.  */
12
-#ifdef HAVE_CONFIG_H
13
-#include "config.h"
14
-#endif
15
-
16
-#include <stdio.h>
17
-#include <stdlib.h>
18
-#include <string.h>
19
-
20
-#ifndef FIX_UNUSED
21
-#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
22
-#endif
23
-
24
-#include <getopt.h>
25
-
26
-#include "cmdline.h"
27
-
28
-const char *gengetopt_args_info_purpose = "";
29
-
30
-const char *gengetopt_args_info_usage = "Usage: slop [options]";
31
-
32
-const char *gengetopt_args_info_versiontext = "Copyright (C) 2014 Dalton Nell, Slop Contributors\n(https://github.com/naelstrof/slop/graphs/contributors)";
33
-
34
-const char *gengetopt_args_info_description = "slop (Select Operation) is an application that queries for a selection from the\nuser and prints the region to stdout.";
35
-
36
-const char *gengetopt_args_info_help[] = {
37
-  "  -h, --help                    Print help and exit",
38
-  "  -V, --version                 Print version and exit",
39
-  "Options",
40
-  "      --xdisplay=hostname:number.screen_number\n                                Sets the x display.",
41
-  "      --nokeyboard              Disables the ability to cancel selections with\n                                  the keyboard.  (default=off)",
42
-  "  -b, --bordersize=INT          Set the selection rectangle's thickness. Does\n                                  nothing when --highlight is enabled.\n                                  (default=`5')",
43
-  "  -p, --padding=INT             Set the padding size of the selection. Can be\n                                  negative.  (default=`0')",
44
-  "  -t, --tolerance=INT           How far in pixels the mouse can move after\n                                  clicking and still be detected as a normal\n                                  click instead of a click and drag. Setting\n                                  this to 0 will disable window selections.\n                                  (default=`2')",
45
-  "  -g, --gracetime=FLOAT         Set the amount of time before slop will check\n                                  for keyboard cancellations in seconds.\n                                  (default=`0.4')",
46
-  "  -c, --color=FLOAT,FLOAT,FLOAT,FLOAT\n                                Set the selection rectangle's color. Supports\n                                  RGB or RGBA values.\n                                  (default=`0.5,0.5,0.5,1')",
47
-  "  -n, --nodecorations           Attempt to select child windows in order to\n                                  avoid window decorations.  (default=off)",
48
-  "      --min=INT                 Set the minimum output of width or height\n                                  values. This is useful to avoid outputting 0.\n                                  Setting min and max to the same value\n                                  disables drag selections.  (default=`0')",
49
-  "      --max=INT                 Set the maximum output of width or height\n                                  values. Setting min and max to the same value\n                                  disables drag selections.  (default=`0')",
50
-  "  -l, --highlight               Instead of outlining selections, slop\n                                  highlights it. This is only useful when\n                                  --color is set to a transparent color.\n                                  (default=off)",
51
-  "      --opengl                  Enable hardware acceleration. Only works with\n                                  modern systems that are also running a\n                                  compositor.  (default=off)",
52
-  "      --magnify                 Display a magnifying glass when --opengl is\n                                  also enabled.  (default=off)",
53
-  "      --magstrength=FLOAT       Sets how many times the magnification window\n                                  size is multiplied.  (default=`4')",
54
-  "      --magpixels=INT           Sets how many pixels are displayed in the\n                                  magnification. The less pixels the bigger the\n                                  magnification.  (default=`64')",
55
-  "      --theme=STRING            Sets the theme of the selection, using textures\n                                  from ~/.config/slop/ or /usr/share/.\n                                  (default=`none')",
56
-  "      --shader=STRING           Sets the shader to load and use from\n                                  ~/.config/slop/ or /usr/share/.\n                                  (default=`simple')",
57
-  "  -f, --format=STRING           Set the output format string. Format specifiers\n                                  are %x, %y, %w, %h, %i, %g, and %c.\n                                  (default=`X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n')",
58
-  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n\n    $ # Wiggle wiggle!\n    $ slop --opengl --shader wiggle\n\n    $ # Edgy textures or something.\n    $ slop --opengl --theme gothic\n\n    $ # Change output format to use safer parsing\n    $ slopoutput=$(slop -f \"%x %y %w %h\")\n    $ X=$(echo $slopoutput | awk '{print $1}')\n    $ Y=$(echo $slopoutput | awk '{print $2}')\n    $ W=$(echo $slopoutput | awk '{print $3}')\n    $ H=$(echo $slopoutput | awk '{print $4}')\n\nTips\n    * You can use the arrow keys to move the starting point of a\ndrag-selection, just in case you missed it by a few pixels.\n    * If you don't like a selection: you can cancel it by right-clicking\nregardless of which options are enabled or disabled for slop.\n    * If slop doesn't seem to select a window accurately, the problem could be\nbecause of decorations getting in the way. Try enabling the --nodecorations\nflag.\n",
59
-    0
60
-};
61
-
62
-typedef enum {ARG_NO
63
-  , ARG_FLAG
64
-  , ARG_STRING
65
-  , ARG_INT
66
-  , ARG_FLOAT
67
-} cmdline_parser_arg_type;
68
-
69
-static
70
-void clear_given (struct gengetopt_args_info *args_info);
71
-static
72
-void clear_args (struct gengetopt_args_info *args_info);
73
-
74
-static int
75
-cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
76
-                        struct cmdline_parser_params *params, const char *additional_error);
77
-
78
-
79
-static char *
80
-gengetopt_strdup (const char *s);
81
-
82
-static
83
-void clear_given (struct gengetopt_args_info *args_info)
84
-{
85
-  args_info->help_given = 0 ;
86
-  args_info->version_given = 0 ;
87
-  args_info->xdisplay_given = 0 ;
88
-  args_info->nokeyboard_given = 0 ;
89
-  args_info->bordersize_given = 0 ;
90
-  args_info->padding_given = 0 ;
91
-  args_info->tolerance_given = 0 ;
92
-  args_info->gracetime_given = 0 ;
93
-  args_info->color_given = 0 ;
94
-  args_info->nodecorations_given = 0 ;
95
-  args_info->min_given = 0 ;
96
-  args_info->max_given = 0 ;
97
-  args_info->highlight_given = 0 ;
98
-  args_info->opengl_given = 0 ;
99
-  args_info->magnify_given = 0 ;
100
-  args_info->magstrength_given = 0 ;
101
-  args_info->magpixels_given = 0 ;
102
-  args_info->theme_given = 0 ;
103
-  args_info->shader_given = 0 ;
104
-  args_info->format_given = 0 ;
105
-}
106
-
107
-static
108
-void clear_args (struct gengetopt_args_info *args_info)
109
-{
110
-  FIX_UNUSED (args_info);
111
-  args_info->xdisplay_arg = NULL;
112
-  args_info->xdisplay_orig = NULL;
113
-  args_info->nokeyboard_flag = 0;
114
-  args_info->bordersize_arg = 5;
115
-  args_info->bordersize_orig = NULL;
116
-  args_info->padding_arg = 0;
117
-  args_info->padding_orig = NULL;
118
-  args_info->tolerance_arg = 2;
119
-  args_info->tolerance_orig = NULL;
120
-  args_info->gracetime_arg = gengetopt_strdup ("0.4");
121
-  args_info->gracetime_orig = NULL;
122
-  args_info->color_arg = gengetopt_strdup ("0.5,0.5,0.5,1");
123
-  args_info->color_orig = NULL;
124
-  args_info->nodecorations_flag = 0;
125
-  args_info->min_arg = 0;
126
-  args_info->min_orig = NULL;
127
-  args_info->max_arg = 0;
128
-  args_info->max_orig = NULL;
129
-  args_info->highlight_flag = 0;
130
-  args_info->opengl_flag = 0;
131
-  args_info->magnify_flag = 0;
132
-  args_info->magstrength_arg = 4;
133
-  args_info->magstrength_orig = NULL;
134
-  args_info->magpixels_arg = 64;
135
-  args_info->magpixels_orig = NULL;
136
-  args_info->theme_arg = gengetopt_strdup ("none");
137
-  args_info->theme_orig = NULL;
138
-  args_info->shader_arg = gengetopt_strdup ("simple");
139
-  args_info->shader_orig = NULL;
140
-  args_info->format_arg = gengetopt_strdup ("X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n");
141
-  args_info->format_orig = NULL;
142
-  
143
-}
144
-
145
-static
146
-void init_args_info(struct gengetopt_args_info *args_info)
147
-{
148
-
149
-
150
-  args_info->help_help = gengetopt_args_info_help[0] ;
151
-  args_info->version_help = gengetopt_args_info_help[1] ;
152
-  args_info->xdisplay_help = gengetopt_args_info_help[3] ;
153
-  args_info->nokeyboard_help = gengetopt_args_info_help[4] ;
154
-  args_info->bordersize_help = gengetopt_args_info_help[5] ;
155
-  args_info->padding_help = gengetopt_args_info_help[6] ;
156
-  args_info->tolerance_help = gengetopt_args_info_help[7] ;
157
-  args_info->gracetime_help = gengetopt_args_info_help[8] ;
158
-  args_info->color_help = gengetopt_args_info_help[9] ;
159
-  args_info->nodecorations_help = gengetopt_args_info_help[10] ;
160
-  args_info->min_help = gengetopt_args_info_help[11] ;
161
-  args_info->max_help = gengetopt_args_info_help[12] ;
162
-  args_info->highlight_help = gengetopt_args_info_help[13] ;
163
-  args_info->opengl_help = gengetopt_args_info_help[14] ;
164
-  args_info->magnify_help = gengetopt_args_info_help[15] ;
165
-  args_info->magstrength_help = gengetopt_args_info_help[16] ;
166
-  args_info->magpixels_help = gengetopt_args_info_help[17] ;
167
-  args_info->theme_help = gengetopt_args_info_help[18] ;
168
-  args_info->shader_help = gengetopt_args_info_help[19] ;
169
-  args_info->format_help = gengetopt_args_info_help[20] ;
170
-  
171
-}
172
-
173
-void
174
-cmdline_parser_print_version (void)
175
-{
176
-  printf ("%s %s\n",
177
-     (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
178
-     CMDLINE_PARSER_VERSION);
179
-
180
-  if (strlen(gengetopt_args_info_versiontext) > 0)
181
-    printf("\n%s\n", gengetopt_args_info_versiontext);
182
-}
183
-
184
-static void print_help_common(void) {
185
-  cmdline_parser_print_version ();
186
-
187
-  if (strlen(gengetopt_args_info_purpose) > 0)
188
-    printf("\n%s\n", gengetopt_args_info_purpose);
189
-
190
-  if (strlen(gengetopt_args_info_usage) > 0)
191
-    printf("\n%s\n", gengetopt_args_info_usage);
192
-
193
-  printf("\n");
194
-
195
-  if (strlen(gengetopt_args_info_description) > 0)
196
-    printf("%s\n\n", gengetopt_args_info_description);
197
-}
198
-
199
-void
200
-cmdline_parser_print_help (void)
201
-{
202
-  int i = 0;
203
-  print_help_common();
204
-  while (gengetopt_args_info_help[i])
205
-    printf("%s\n", gengetopt_args_info_help[i++]);
206
-}
207
-
208
-void
209
-cmdline_parser_init (struct gengetopt_args_info *args_info)
210
-{
211
-  clear_given (args_info);
212
-  clear_args (args_info);
213
-  init_args_info (args_info);
214
-}
215
-
216
-void
217
-cmdline_parser_params_init(struct cmdline_parser_params *params)
218
-{
219
-  if (params)
220
-    { 
221
-      params->override = 0;
222
-      params->initialize = 1;
223
-      params->check_required = 1;
224
-      params->check_ambiguity = 0;
225
-      params->print_errors = 1;
226
-    }
227
-}
228
-
229
-struct cmdline_parser_params *
230
-cmdline_parser_params_create(void)
231
-{
232
-  struct cmdline_parser_params *params = 
233
-    (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
234
-  cmdline_parser_params_init(params);  
235
-  return params;
236
-}
237
-
238
-static void
239
-free_string_field (char **s)
240
-{
241
-  if (*s)
242
-    {
243
-      free (*s);
244
-      *s = 0;
245
-    }
246
-}
247
-
248
-
249
-static void
250
-cmdline_parser_release (struct gengetopt_args_info *args_info)
251
-{
252
-
253
-  free_string_field (&(args_info->xdisplay_arg));
254
-  free_string_field (&(args_info->xdisplay_orig));
255
-  free_string_field (&(args_info->bordersize_orig));
256
-  free_string_field (&(args_info->padding_orig));
257
-  free_string_field (&(args_info->tolerance_orig));
258
-  free_string_field (&(args_info->gracetime_arg));
259
-  free_string_field (&(args_info->gracetime_orig));
260
-  free_string_field (&(args_info->color_arg));
261
-  free_string_field (&(args_info->color_orig));
262
-  free_string_field (&(args_info->min_orig));
263
-  free_string_field (&(args_info->max_orig));
264
-  free_string_field (&(args_info->magstrength_orig));
265
-  free_string_field (&(args_info->magpixels_orig));
266
-  free_string_field (&(args_info->theme_arg));
267
-  free_string_field (&(args_info->theme_orig));
268
-  free_string_field (&(args_info->shader_arg));
269
-  free_string_field (&(args_info->shader_orig));
270
-  free_string_field (&(args_info->format_arg));
271
-  free_string_field (&(args_info->format_orig));
272
-  
273
-  
274
-
275
-  clear_given (args_info);
276
-}
277
-
278
-
279
-static void
280
-write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
281
-{
282
-  FIX_UNUSED (values);
283
-  if (arg) {
284
-    fprintf(outfile, "%s=\"%s\"\n", opt, arg);
285
-  } else {
286
-    fprintf(outfile, "%s\n", opt);
287
-  }
288
-}
289
-
290
-
291
-int
292
-cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
293
-{
294
-  int i = 0;
295
-
296
-  if (!outfile)
297
-    {
298
-      fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
299
-      return EXIT_FAILURE;
300
-    }
301
-
302
-  if (args_info->help_given)
303
-    write_into_file(outfile, "help", 0, 0 );
304
-  if (args_info->version_given)
305
-    write_into_file(outfile, "version", 0, 0 );
306
-  if (args_info->xdisplay_given)
307
-    write_into_file(outfile, "xdisplay", args_info->xdisplay_orig, 0);
308
-  if (args_info->nokeyboard_given)
309
-    write_into_file(outfile, "nokeyboard", 0, 0 );
310
-  if (args_info->bordersize_given)
311
-    write_into_file(outfile, "bordersize", args_info->bordersize_orig, 0);
312
-  if (args_info->padding_given)
313
-    write_into_file(outfile, "padding", args_info->padding_orig, 0);
314
-  if (args_info->tolerance_given)
315
-    write_into_file(outfile, "tolerance", args_info->tolerance_orig, 0);
316
-  if (args_info->gracetime_given)
317
-    write_into_file(outfile, "gracetime", args_info->gracetime_orig, 0);
318
-  if (args_info->color_given)
319
-    write_into_file(outfile, "color", args_info->color_orig, 0);
320
-  if (args_info->nodecorations_given)
321
-    write_into_file(outfile, "nodecorations", 0, 0 );
322
-  if (args_info->min_given)
323
-    write_into_file(outfile, "min", args_info->min_orig, 0);
324
-  if (args_info->max_given)
325
-    write_into_file(outfile, "max", args_info->max_orig, 0);
326
-  if (args_info->highlight_given)
327
-    write_into_file(outfile, "highlight", 0, 0 );
328
-  if (args_info->opengl_given)
329
-    write_into_file(outfile, "opengl", 0, 0 );
330
-  if (args_info->magnify_given)
331
-    write_into_file(outfile, "magnify", 0, 0 );
332
-  if (args_info->magstrength_given)
333
-    write_into_file(outfile, "magstrength", args_info->magstrength_orig, 0);
334
-  if (args_info->magpixels_given)
335
-    write_into_file(outfile, "magpixels", args_info->magpixels_orig, 0);
336
-  if (args_info->theme_given)
337
-    write_into_file(outfile, "theme", args_info->theme_orig, 0);
338
-  if (args_info->shader_given)
339
-    write_into_file(outfile, "shader", args_info->shader_orig, 0);
340
-  if (args_info->format_given)
341
-    write_into_file(outfile, "format", args_info->format_orig, 0);
342
-  
343
-
344
-  i = EXIT_SUCCESS;
345
-  return i;
346
-}
347
-
348
-int
349
-cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
350
-{
351
-  FILE *outfile;
352
-  int i = 0;
353
-
354
-  outfile = fopen(filename, "w");
355
-
356
-  if (!outfile)
357
-    {
358
-      fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
359
-      return EXIT_FAILURE;
360
-    }
361
-
362
-  i = cmdline_parser_dump(outfile, args_info);
363
-  fclose (outfile);
364
-
365
-  return i;
366
-}
367
-
368
-void
369
-cmdline_parser_free (struct gengetopt_args_info *args_info)
370
-{
371
-  cmdline_parser_release (args_info);
372
-}
373
-
374
-/** @brief replacement of strdup, which is not standard */
375
-char *
376
-gengetopt_strdup (const char *s)
377
-{
378
-  char *result = 0;
379
-  if (!s)
380
-    return result;
381
-
382
-  result = (char*)malloc(strlen(s) + 1);
383
-  if (result == (char*)0)
384
-    return (char*)0;
385
-  strcpy(result, s);
386
-  return result;
387
-}
388
-
389
-int
390
-cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
391
-{
392
-  return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
393
-}
394
-
395
-int
396
-cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
397
-                   struct cmdline_parser_params *params)
398
-{
399
-  int result;
400
-  result = cmdline_parser_internal (argc, argv, args_info, params, 0);
401
-
402
-  if (result == EXIT_FAILURE)
403
-    {
404
-      cmdline_parser_free (args_info);
405
-      exit (EXIT_FAILURE);
406
-    }
407
-  
408
-  return result;
409
-}
410
-
411
-int
412
-cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
413
-{
414
-  int result;
415
-  struct cmdline_parser_params params;
416
-  
417
-  params.override = override;
418
-  params.initialize = initialize;
419
-  params.check_required = check_required;
420
-  params.check_ambiguity = 0;
421
-  params.print_errors = 1;
422
-
423
-  result = cmdline_parser_internal (argc, argv, args_info, &params, 0);
424
-
425
-  if (result == EXIT_FAILURE)
426
-    {
427
-      cmdline_parser_free (args_info);
428
-      exit (EXIT_FAILURE);
429
-    }
430
-  
431
-  return result;
432
-}
433
-
434
-int
435
-cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
436
-{
437
-  FIX_UNUSED (args_info);
438
-  FIX_UNUSED (prog_name);
439
-  return EXIT_SUCCESS;
440
-}
441
-
442
-
443
-static char *package_name = 0;
444
-
445
-/**
446
- * @brief updates an option
447
- * @param field the generic pointer to the field to update
448
- * @param orig_field the pointer to the orig field
449
- * @param field_given the pointer to the number of occurrence of this option
450
- * @param prev_given the pointer to the number of occurrence already seen
451
- * @param value the argument for this option (if null no arg was specified)
452
- * @param possible_values the possible values for this option (if specified)
453
- * @param default_value the default value (in case the option only accepts fixed values)
454
- * @param arg_type the type of this option
455
- * @param check_ambiguity @see cmdline_parser_params.check_ambiguity
456
- * @param override @see cmdline_parser_params.override
457
- * @param no_free whether to free a possible previous value
458
- * @param multiple_option whether this is a multiple option
459
- * @param long_opt the corresponding long option
460
- * @param short_opt the corresponding short option (or '-' if none)
461
- * @param additional_error possible further error specification
462
- */
463
-static
464
-int update_arg(void *field, char **orig_field,
465
-               unsigned int *field_given, unsigned int *prev_given, 
466
-               char *value, const char *possible_values[],
467
-               const char *default_value,
468
-               cmdline_parser_arg_type arg_type,
469
-               int check_ambiguity, int override,
470
-               int no_free, int multiple_option,
471
-               const char *long_opt, char short_opt,
472
-               const char *additional_error)
473
-{
474
-  char *stop_char = 0;
475
-  const char *val = value;
476
-  int found;
477
-  char **string_field;
478
-  FIX_UNUSED (field);
479
-
480
-  stop_char = 0;
481
-  found = 0;
482
-
483
-  if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
484
-    {
485
-      if (short_opt != '-')
486
-        fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", 
487
-               package_name, long_opt, short_opt,
488
-               (additional_error ? additional_error : ""));
489
-      else
490
-        fprintf (stderr, "%s: `--%s' option given more than once%s\n", 
491
-               package_name, long_opt,
492
-               (additional_error ? additional_error : ""));
493
-      return 1; /* failure */
494
-    }
495
-
496
-  FIX_UNUSED (default_value);
497
-    
498
-  if (field_given && *field_given && ! override)
499
-    return 0;
500
-  if (prev_given)
501
-    (*prev_given)++;
502
-  if (field_given)
503
-    (*field_given)++;
504
-  if (possible_values)
505
-    val = possible_values[found];
506
-
507
-  switch(arg_type) {
508
-  case ARG_FLAG:
509
-    *((int *)field) = !*((int *)field);
510
-    break;
511
-  case ARG_INT:
512
-    if (val) *((int *)field) = strtol (val, &stop_char, 0);
513
-    break;
514
-  case ARG_FLOAT:
515
-    if (val) *((float *)field) = (float)strtod (val, &stop_char);
516
-    break;
517
-  case ARG_STRING:
518
-    if (val) {
519
-      string_field = (char **)field;
520
-      if (!no_free && *string_field)
521
-        free (*string_field); /* free previous string */
522
-      *string_field = gengetopt_strdup (val);
523
-    }
524
-    break;
525
-  default:
526
-    break;
527
-  };
528
-
529
-  /* check numeric conversion */
530
-  switch(arg_type) {
531
-  case ARG_INT:
532
-  case ARG_FLOAT:
533
-    if (val && !(stop_char && *stop_char == '\0')) {
534
-      fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
535
-      return 1; /* failure */
536
-    }
537
-    break;
538
-  default:
539
-    ;
540
-  };
541
-
542
-  /* store the original value */
543
-  switch(arg_type) {
544
-  case ARG_NO:
545
-  case ARG_FLAG:
546
-    break;
547
-  default:
548
-    if (value && orig_field) {
549
-      if (no_free) {
550
-        *orig_field = value;
551
-      } else {
552
-        if (*orig_field)
553
-          free (*orig_field); /* free previous string */
554
-        *orig_field = gengetopt_strdup (value);
555
-      }
556
-    }
557
-  };
558
-
559
-  return 0; /* OK */
560
-}
561
-
562
-
563
-int
564
-cmdline_parser_internal (
565
-  int argc, char **argv, struct gengetopt_args_info *args_info,
566
-                        struct cmdline_parser_params *params, const char *additional_error)
567
-{
568
-  int c;	/* Character of the parsed option.  */
569
-
570
-  int error_occurred = 0;
571
-  struct gengetopt_args_info local_args_info;
572
-  
573
-  int override;
574
-  int initialize;
575
-  int check_required;
576
-  int check_ambiguity;
577
-  
578
-  package_name = argv[0];
579
-  
580
-  override = params->override;
581
-  initialize = params->initialize;
582
-  check_required = params->check_required;
583
-  check_ambiguity = params->check_ambiguity;
584
-
585
-  if (initialize)
586
-    cmdline_parser_init (args_info);
587
-
588
-  cmdline_parser_init (&local_args_info);
589
-
590
-  optarg = 0;
591
-  optind = 0;
592
-  opterr = params->print_errors;
593
-  optopt = '?';
594
-
595
-  while (1)
596
-    {
597
-      int option_index = 0;
598
-
599
-      static struct option long_options[] = {
600
-        { "help",	0, NULL, 'h' },
601
-        { "version",	0, NULL, 'V' },
602
-        { "xdisplay",	1, NULL, 0 },
603
-        { "nokeyboard",	0, NULL, 0 },
604
-        { "bordersize",	1, NULL, 'b' },
605
-        { "padding",	1, NULL, 'p' },
606
-        { "tolerance",	1, NULL, 't' },
607
-        { "gracetime",	1, NULL, 'g' },
608
-        { "color",	1, NULL, 'c' },
609
-        { "nodecorations",	0, NULL, 'n' },
610
-        { "min",	1, NULL, 0 },
611
-        { "max",	1, NULL, 0 },
612
-        { "highlight",	0, NULL, 'l' },
613
-        { "opengl",	0, NULL, 0 },
614
-        { "magnify",	0, NULL, 0 },
615
-        { "magstrength",	1, NULL, 0 },
616
-        { "magpixels",	1, NULL, 0 },
617
-        { "theme",	1, NULL, 0 },
618
-        { "shader",	1, NULL, 0 },
619
-        { "format",	1, NULL, 'f' },
620
-        { 0,  0, 0, 0 }
621
-      };
622
-
623
-      c = getopt_long (argc, argv, "hVb:p:t:g:c:nlf:", long_options, &option_index);
624
-
625
-      if (c == -1) break;	/* Exit from `while (1)' loop.  */
626
-
627
-      switch (c)
628
-        {
629
-        case 'h':	/* Print help and exit.  */
630
-          cmdline_parser_print_help ();
631
-          cmdline_parser_free (&local_args_info);
632
-          exit (EXIT_SUCCESS);
633
-
634
-        case 'V':	/* Print version and exit.  */
635
-          cmdline_parser_print_version ();
636
-          cmdline_parser_free (&local_args_info);
637
-          exit (EXIT_SUCCESS);
638
-
639
-        case 'b':	/* Set the selection rectangle's thickness. Does nothing when --highlight is enabled..  */
640
-        
641
-        
642
-          if (update_arg( (void *)&(args_info->bordersize_arg), 
643
-               &(args_info->bordersize_orig), &(args_info->bordersize_given),
644
-              &(local_args_info.bordersize_given), optarg, 0, "5", ARG_INT,
645
-              check_ambiguity, override, 0, 0,
646
-              "bordersize", 'b',
647
-              additional_error))
648
-            goto failure;
649
-        
650
-          break;
651
-        case 'p':	/* Set the padding size of the selection. Can be negative..  */
652
-        
653
-        
654
-          if (update_arg( (void *)&(args_info->padding_arg), 
655
-               &(args_info->padding_orig), &(args_info->padding_given),
656
-              &(local_args_info.padding_given), optarg, 0, "0", ARG_INT,
657
-              check_ambiguity, override, 0, 0,
658
-              "padding", 'p',
659
-              additional_error))
660
-            goto failure;
661
-        
662
-          break;
663
-        case 't':	/* How far in pixels the mouse can move after clicking and still be detected as a normal click instead of a click and drag. Setting this to 0 will disable window selections..  */
664
-        
665
-        
666
-          if (update_arg( (void *)&(args_info->tolerance_arg), 
667
-               &(args_info->tolerance_orig), &(args_info->tolerance_given),
668
-              &(local_args_info.tolerance_given), optarg, 0, "2", ARG_INT,
669
-              check_ambiguity, override, 0, 0,
670
-              "tolerance", 't',
671
-              additional_error))
672
-            goto failure;
673
-        
674
-          break;
675
-        case 'g':	/* Set the amount of time before slop will check for keyboard cancellations in seconds..  */
676
-        
677
-        
678
-          if (update_arg( (void *)&(args_info->gracetime_arg), 
679
-               &(args_info->gracetime_orig), &(args_info->gracetime_given),
680
-              &(local_args_info.gracetime_given), optarg, 0, "0.4", ARG_STRING,
681
-              check_ambiguity, override, 0, 0,
682
-              "gracetime", 'g',
683
-              additional_error))
684
-            goto failure;
685
-        
686
-          break;
687
-        case 'c':	/* Set the selection rectangle's color. Supports RGB or RGBA values..  */
688
-        
689
-        
690
-          if (update_arg( (void *)&(args_info->color_arg), 
691
-               &(args_info->color_orig), &(args_info->color_given),
692
-              &(local_args_info.color_given), optarg, 0, "0.5,0.5,0.5,1", ARG_STRING,
693
-              check_ambiguity, override, 0, 0,
694
-              "color", 'c',
695
-              additional_error))
696
-            goto failure;
697
-        
698
-          break;
699
-        case 'n':	/* Attempt to select child windows in order to avoid window decorations..  */
700
-        
701
-        
702
-          if (update_arg((void *)&(args_info->nodecorations_flag), 0, &(args_info->nodecorations_given),
703
-              &(local_args_info.nodecorations_given), optarg, 0, 0, ARG_FLAG,
704
-              check_ambiguity, override, 1, 0, "nodecorations", 'n',
705
-              additional_error))
706
-            goto failure;
707
-        
708
-          break;
709
-        case 'l':	/* Instead of outlining selections, slop highlights it. This is only useful when --color is set to a transparent color..  */
710
-        
711
-        
712
-          if (update_arg((void *)&(args_info->highlight_flag), 0, &(args_info->highlight_given),
713
-              &(local_args_info.highlight_given), optarg, 0, 0, ARG_FLAG,
714
-              check_ambiguity, override, 1, 0, "highlight", 'l',
715
-              additional_error))
716
-            goto failure;
717
-        
718
-          break;
719
-        case 'f':	/* Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c..  */
720
-        
721
-        
722
-          if (update_arg( (void *)&(args_info->format_arg), 
723
-               &(args_info->format_orig), &(args_info->format_given),
724
-              &(local_args_info.format_given), optarg, 0, "X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n", ARG_STRING,
725
-              check_ambiguity, override, 0, 0,
726
-              "format", 'f',
727
-              additional_error))
728
-            goto failure;
729
-        
730
-          break;
731
-
732
-        case 0:	/* Long option with no short option */
733
-          /* Sets the x display..  */
734
-          if (strcmp (long_options[option_index].name, "xdisplay") == 0)
735
-          {
736
-          
737
-          
738
-            if (update_arg( (void *)&(args_info->xdisplay_arg), 
739
-                 &(args_info->xdisplay_orig), &(args_info->xdisplay_given),
740
-                &(local_args_info.xdisplay_given), optarg, 0, 0, ARG_STRING,
741
-                check_ambiguity, override, 0, 0,
742
-                "xdisplay", '-',
743
-                additional_error))
744
-              goto failure;
745
-          
746
-          }
747
-          /* Disables the ability to cancel selections with the keyboard..  */
748
-          else if (strcmp (long_options[option_index].name, "nokeyboard") == 0)
749
-          {
750
-          
751
-          
752
-            if (update_arg((void *)&(args_info->nokeyboard_flag), 0, &(args_info->nokeyboard_given),
753
-                &(local_args_info.nokeyboard_given), optarg, 0, 0, ARG_FLAG,
754
-                check_ambiguity, override, 1, 0, "nokeyboard", '-',
755
-                additional_error))
756
-              goto failure;
757
-          
758
-          }
759
-          /* Set the minimum output of width or height values. This is useful to avoid outputting 0. Setting min and max to the same value disables drag selections..  */
760
-          else if (strcmp (long_options[option_index].name, "min") == 0)
761
-          {
762
-          
763
-          
764
-            if (update_arg( (void *)&(args_info->min_arg), 
765
-                 &(args_info->min_orig), &(args_info->min_given),
766
-                &(local_args_info.min_given), optarg, 0, "0", ARG_INT,
767
-                check_ambiguity, override, 0, 0,
768
-                "min", '-',
769
-                additional_error))
770
-              goto failure;
771
-          
772
-          }
773
-          /* Set the maximum output of width or height values. Setting min and max to the same value disables drag selections..  */
774
-          else if (strcmp (long_options[option_index].name, "max") == 0)
775
-          {
776
-          
777
-          
778
-            if (update_arg( (void *)&(args_info->max_arg), 
779
-                 &(args_info->max_orig), &(args_info->max_given),
780
-                &(local_args_info.max_given), optarg, 0, "0", ARG_INT,
781
-                check_ambiguity, override, 0, 0,
782
-                "max", '-',
783
-                additional_error))
784
-              goto failure;
785
-          
786
-          }
787
-          /* Enable hardware acceleration. Only works with modern systems that are also running a compositor..  */
788
-          else if (strcmp (long_options[option_index].name, "opengl") == 0)
789
-          {
790
-          
791
-          
792
-            if (update_arg((void *)&(args_info->opengl_flag), 0, &(args_info->opengl_given),
793
-                &(local_args_info.opengl_given), optarg, 0, 0, ARG_FLAG,
794
-                check_ambiguity, override, 1, 0, "opengl", '-',
795
-                additional_error))
796
-              goto failure;
797
-          
798
-          }
799
-          /* Display a magnifying glass when --opengl is also enabled..  */
800
-          else if (strcmp (long_options[option_index].name, "magnify") == 0)
801
-          {
802
-          
803
-          
804
-            if (update_arg((void *)&(args_info->magnify_flag), 0, &(args_info->magnify_given),
805
-                &(local_args_info.magnify_given), optarg, 0, 0, ARG_FLAG,
806
-                check_ambiguity, override, 1, 0, "magnify", '-',
807
-                additional_error))
808
-              goto failure;
809
-          
810
-          }
811
-          /* Sets how many times the magnification window size is multiplied..  */
812
-          else if (strcmp (long_options[option_index].name, "magstrength") == 0)
813
-          {
814
-          
815
-          
816
-            if (update_arg( (void *)&(args_info->magstrength_arg), 
817
-                 &(args_info->magstrength_orig), &(args_info->magstrength_given),
818
-                &(local_args_info.magstrength_given), optarg, 0, "4", ARG_FLOAT,
819
-                check_ambiguity, override, 0, 0,
820
-                "magstrength", '-',
821
-                additional_error))
822
-              goto failure;
823
-          
824
-          }
825
-          /* Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification..  */
826
-          else if (strcmp (long_options[option_index].name, "magpixels") == 0)
827
-          {
828
-          
829
-          
830
-            if (update_arg( (void *)&(args_info->magpixels_arg), 
831
-                 &(args_info->magpixels_orig), &(args_info->magpixels_given),
832
-                &(local_args_info.magpixels_given), optarg, 0, "64", ARG_INT,
833
-                check_ambiguity, override, 0, 0,
834
-                "magpixels", '-',
835
-                additional_error))
836
-              goto failure;
837
-          
838
-          }
839
-          /* Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/..  */
840
-          else if (strcmp (long_options[option_index].name, "theme") == 0)
841
-          {
842
-          
843
-          
844
-            if (update_arg( (void *)&(args_info->theme_arg), 
845
-                 &(args_info->theme_orig), &(args_info->theme_given),
846
-                &(local_args_info.theme_given), optarg, 0, "none", ARG_STRING,
847
-                check_ambiguity, override, 0, 0,
848
-                "theme", '-',
849
-                additional_error))
850
-              goto failure;
851
-          
852
-          }
853
-          /* Sets the shader to load and use from ~/.config/slop/ or /usr/share/..  */
854
-          else if (strcmp (long_options[option_index].name, "shader") == 0)
855
-          {
856
-          
857
-          
858
-            if (update_arg( (void *)&(args_info->shader_arg), 
859
-                 &(args_info->shader_orig), &(args_info->shader_given),
860
-                &(local_args_info.shader_given), optarg, 0, "simple", ARG_STRING,
861
-                check_ambiguity, override, 0, 0,
862
-                "shader", '-',
863
-                additional_error))
864
-              goto failure;
865
-          
866
-          }
867
-          
868
-          break;
869
-        case '?':	/* Invalid option.  */
870
-          /* `getopt_long' already printed an error message.  */
871
-          goto failure;
872
-
873
-        default:	/* bug: option not considered.  */
874
-          fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
875
-          abort ();
876
-        } /* switch */
877
-    } /* while */
878
-
879
-
880
-
881
-
882
-  cmdline_parser_release (&local_args_info);
883
-
884
-  if ( error_occurred )
885
-    return (EXIT_FAILURE);
886
-
887
-  return 0;
888
-
889
-failure:
890
-  
891
-  cmdline_parser_release (&local_args_info);
892
-  return (EXIT_FAILURE);
893
-}

+ 0
- 240
src/cmdline.in Просмотреть файл

@@ -1,240 +0,0 @@
1
-/** @file cmdline.h
2
- *  @brief The header file for the command line option parser
3
- *  generated by GNU Gengetopt version 2.22.6
4
- *  http://www.gnu.org/software/gengetopt.
5
- *  DO NOT modify this file, since it can be overwritten
6
- *  @author GNU Gengetopt by Lorenzo Bettini */
7
-
8
-#ifndef CMDLINE_H
9
-#define CMDLINE_H
10
-
11
-/* If we use autoconf.  */
12
-#ifdef HAVE_CONFIG_H
13
-#include "config.h"
14
-#endif
15
-
16
-#include <stdio.h> /* for FILE */
17
-
18
-#ifdef __cplusplus
19
-extern "C" {
20
-#endif /* __cplusplus */
21
-
22
-#ifndef CMDLINE_PARSER_PACKAGE
23
-/** @brief the program name (used for printing errors) */
24
-#define CMDLINE_PARSER_PACKAGE "slop"
25
-#endif
26
-
27
-#ifndef CMDLINE_PARSER_PACKAGE_NAME
28
-/** @brief the complete program name (used for help and version) */
29
-#define CMDLINE_PARSER_PACKAGE_NAME "slop"
30
-#endif
31
-
32
-#ifndef CMDLINE_PARSER_VERSION
33
-/** @brief the program version */
34
-#define CMDLINE_PARSER_VERSION "v@slop_VERSION_MAJOR@.@slop_VERSION_MINOR@.@slop_VERSION_PATCH@"
35
-#endif
36
-
37
-/** @brief Where the command line options are stored */
38
-struct gengetopt_args_info
39
-{
40
-  const char *help_help; /**< @brief Print help and exit help description.  */
41
-  const char *version_help; /**< @brief Print version and exit help description.  */
42
-  char * xdisplay_arg;	/**< @brief Sets the x display..  */
43
-  char * xdisplay_orig;	/**< @brief Sets the x display. original value given at command line.  */
44
-  const char *xdisplay_help; /**< @brief Sets the x display. help description.  */
45
-  int nokeyboard_flag;	/**< @brief Disables the ability to cancel selections with the keyboard. (default=off).  */
46
-  const char *nokeyboard_help; /**< @brief Disables the ability to cancel selections with the keyboard. help description.  */
47
-  int bordersize_arg;	/**< @brief Set the selection rectangle's thickness. Does nothing when --highlight is enabled. (default='5').  */
48
-  char * bordersize_orig;	/**< @brief Set the selection rectangle's thickness. Does nothing when --highlight is enabled. original value given at command line.  */
49
-  const char *bordersize_help; /**< @brief Set the selection rectangle's thickness. Does nothing when --highlight is enabled. help description.  */
50
-  int padding_arg;	/**< @brief Set the padding size of the selection. Can be negative. (default='0').  */
51
-  char * padding_orig;	/**< @brief Set the padding size of the selection. Can be negative. original value given at command line.  */
52
-  const char *padding_help; /**< @brief Set the padding size of the selection. Can be negative. help description.  */
53
-  int tolerance_arg;	/**< @brief How far in pixels the mouse can move after clicking and still be detected as a normal click instead of a click and drag. Setting this to 0 will disable window selections. (default='2').  */
54
-  char * tolerance_orig;	/**< @brief How far in pixels the mouse can move after clicking and still be detected as a normal click instead of a click and drag. Setting this to 0 will disable window selections. original value given at command line.  */
55
-  const char *tolerance_help; /**< @brief How far in pixels the mouse can move after clicking and still be detected as a normal click instead of a click and drag. Setting this to 0 will disable window selections. help description.  */
56
-  char * gracetime_arg;	/**< @brief Set the amount of time before slop will check for keyboard cancellations in seconds. (default='0.4').  */
57
-  char * gracetime_orig;	/**< @brief Set the amount of time before slop will check for keyboard cancellations in seconds. original value given at command line.  */
58
-  const char *gracetime_help; /**< @brief Set the amount of time before slop will check for keyboard cancellations in seconds. help description.  */
59
-  char * color_arg;	/**< @brief Set the selection rectangle's color. Supports RGB or RGBA values. (default='0.5,0.5,0.5,1').  */
60
-  char * color_orig;	/**< @brief Set the selection rectangle's color. Supports RGB or RGBA values. original value given at command line.  */
61
-  const char *color_help; /**< @brief Set the selection rectangle's color. Supports RGB or RGBA values. help description.  */
62
-  int nodecorations_flag;	/**< @brief Attempt to select child windows in order to avoid window decorations. (default=off).  */
63
-  const char *nodecorations_help; /**< @brief Attempt to select child windows in order to avoid window decorations. help description.  */
64
-  int min_arg;	/**< @brief Set the minimum output of width or height values. This is useful to avoid outputting 0. Setting min and max to the same value disables drag selections. (default='0').  */
65
-  char * min_orig;	/**< @brief Set the minimum output of width or height values. This is useful to avoid outputting 0. Setting min and max to the same value disables drag selections. original value given at command line.  */
66
-  const char *min_help; /**< @brief Set the minimum output of width or height values. This is useful to avoid outputting 0. Setting min and max to the same value disables drag selections. help description.  */
67
-  int max_arg;	/**< @brief Set the maximum output of width or height values. Setting min and max to the same value disables drag selections. (default='0').  */
68
-  char * max_orig;	/**< @brief Set the maximum output of width or height values. Setting min and max to the same value disables drag selections. original value given at command line.  */
69
-  const char *max_help; /**< @brief Set the maximum output of width or height values. Setting min and max to the same value disables drag selections. help description.  */
70
-  int highlight_flag;	/**< @brief Instead of outlining selections, slop highlights it. This is only useful when --color is set to a transparent color. (default=off).  */
71
-  const char *highlight_help; /**< @brief Instead of outlining selections, slop highlights it. This is only useful when --color is set to a transparent color. help description.  */
72
-  int opengl_flag;	/**< @brief Enable hardware acceleration. Only works with modern systems that are also running a compositor. (default=off).  */
73
-  const char *opengl_help; /**< @brief Enable hardware acceleration. Only works with modern systems that are also running a compositor. help description.  */
74
-  int magnify_flag;	/**< @brief Display a magnifying glass when --opengl is also enabled. (default=off).  */
75
-  const char *magnify_help; /**< @brief Display a magnifying glass when --opengl is also enabled. help description.  */
76
-  float magstrength_arg;	/**< @brief Sets how many times the magnification window size is multiplied. (default='4').  */
77
-  char * magstrength_orig;	/**< @brief Sets how many times the magnification window size is multiplied. original value given at command line.  */
78
-  const char *magstrength_help; /**< @brief Sets how many times the magnification window size is multiplied. help description.  */
79
-  int magpixels_arg;	/**< @brief Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification. (default='64').  */
80
-  char * magpixels_orig;	/**< @brief Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification. original value given at command line.  */
81
-  const char *magpixels_help; /**< @brief Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification. help description.  */
82
-  char * theme_arg;	/**< @brief Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/. (default='none').  */
83
-  char * theme_orig;	/**< @brief Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/. original value given at command line.  */
84
-  const char *theme_help; /**< @brief Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/. help description.  */
85
-  char * shader_arg;	/**< @brief Sets the shader to load and use from ~/.config/slop/ or /usr/share/. (default='simple').  */
86
-  char * shader_orig;	/**< @brief Sets the shader to load and use from ~/.config/slop/ or /usr/share/. original value given at command line.  */
87
-  const char *shader_help; /**< @brief Sets the shader to load and use from ~/.config/slop/ or /usr/share/. help description.  */
88
-  char * format_arg;	/**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. (default='REPLACEME').  */
89
-  char * format_orig;	/**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. original value given at command line.  */
90
-  const char *format_help; /**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. help description.  */
91
-  
92
-  unsigned int help_given ;	/**< @brief Whether help was given.  */
93
-  unsigned int version_given ;	/**< @brief Whether version was given.  */
94
-  unsigned int xdisplay_given ;	/**< @brief Whether xdisplay was given.  */
95
-  unsigned int nokeyboard_given ;	/**< @brief Whether nokeyboard was given.  */
96
-  unsigned int bordersize_given ;	/**< @brief Whether bordersize was given.  */
97
-  unsigned int padding_given ;	/**< @brief Whether padding was given.  */
98
-  unsigned int tolerance_given ;	/**< @brief Whether tolerance was given.  */
99
-  unsigned int gracetime_given ;	/**< @brief Whether gracetime was given.  */
100
-  unsigned int color_given ;	/**< @brief Whether color was given.  */
101
-  unsigned int nodecorations_given ;	/**< @brief Whether nodecorations was given.  */
102
-  unsigned int min_given ;	/**< @brief Whether min was given.  */
103
-  unsigned int max_given ;	/**< @brief Whether max was given.  */
104
-  unsigned int highlight_given ;	/**< @brief Whether highlight was given.  */
105
-  unsigned int opengl_given ;	/**< @brief Whether opengl was given.  */
106
-  unsigned int magnify_given ;	/**< @brief Whether magnify was given.  */
107
-  unsigned int magstrength_given ;	/**< @brief Whether magstrength was given.  */
108
-  unsigned int magpixels_given ;	/**< @brief Whether magpixels was given.  */
109
-  unsigned int theme_given ;	/**< @brief Whether theme was given.  */
110
-  unsigned int shader_given ;	/**< @brief Whether shader was given.  */
111
-  unsigned int format_given ;	/**< @brief Whether format was given.  */
112
-
113
-} ;
114
-
115
-/** @brief The additional parameters to pass to parser functions */
116
-struct cmdline_parser_params
117
-{
118
-  int override; /**< @brief whether to override possibly already present options (default 0) */
119
-  int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
120
-  int check_required; /**< @brief whether to check that all required options were provided (default 1) */
121
-  int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
122
-  int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
123
-} ;
124
-
125
-/** @brief the purpose string of the program */
126
-extern const char *gengetopt_args_info_purpose;
127
-/** @brief the usage string of the program */
128
-extern const char *gengetopt_args_info_usage;
129
-/** @brief the description string of the program */
130
-extern const char *gengetopt_args_info_description;
131
-/** @brief all the lines making the help output */
132
-extern const char *gengetopt_args_info_help[];
133
-
134
-/**
135
- * The command line parser
136
- * @param argc the number of command line options
137
- * @param argv the command line options
138
- * @param args_info the structure where option information will be stored
139
- * @return 0 if everything went fine, NON 0 if an error took place
140
- */
141
-int cmdline_parser (int argc, char **argv,
142
-  struct gengetopt_args_info *args_info);
143
-
144
-/**
145
- * The command line parser (version with additional parameters - deprecated)
146
- * @param argc the number of command line options
147
- * @param argv the command line options
148
- * @param args_info the structure where option information will be stored
149
- * @param override whether to override possibly already present options
150
- * @param initialize whether to initialize the option structure my_args_info
151
- * @param check_required whether to check that all required options were provided
152
- * @return 0 if everything went fine, NON 0 if an error took place
153
- * @deprecated use cmdline_parser_ext() instead
154
- */
155
-int cmdline_parser2 (int argc, char **argv,
156
-  struct gengetopt_args_info *args_info,
157
-  int override, int initialize, int check_required);
158
-
159
-/**
160
- * The command line parser (version with additional parameters)
161
- * @param argc the number of command line options
162
- * @param argv the command line options
163
- * @param args_info the structure where option information will be stored
164
- * @param params additional parameters for the parser
165
- * @return 0 if everything went fine, NON 0 if an error took place
166
- */
167
-int cmdline_parser_ext (int argc, char **argv,
168
-  struct gengetopt_args_info *args_info,
169
-  struct cmdline_parser_params *params);
170
-
171
-/**
172
- * Save the contents of the option struct into an already open FILE stream.
173
- * @param outfile the stream where to dump options
174
- * @param args_info the option struct to dump
175
- * @return 0 if everything went fine, NON 0 if an error took place
176
- */
177
-int cmdline_parser_dump(FILE *outfile,
178
-  struct gengetopt_args_info *args_info);
179
-
180
-/**
181
- * Save the contents of the option struct into a (text) file.
182
- * This file can be read by the config file parser (if generated by gengetopt)
183
- * @param filename the file where to save
184
- * @param args_info the option struct to save
185
- * @return 0 if everything went fine, NON 0 if an error took place
186
- */
187
-int cmdline_parser_file_save(const char *filename,
188
-  struct gengetopt_args_info *args_info);
189
-
190
-/**
191
- * Print the help
192
- */
193
-void cmdline_parser_print_help(void);
194
-/**
195
- * Print the version
196
- */
197
-void cmdline_parser_print_version(void);
198
-
199
-/**
200
- * Initializes all the fields a cmdline_parser_params structure 
201
- * to their default values
202
- * @param params the structure to initialize
203
- */
204
-void cmdline_parser_params_init(struct cmdline_parser_params *params);
205
-
206
-/**
207
- * Allocates dynamically a cmdline_parser_params structure and initializes
208
- * all its fields to their default values
209
- * @return the created and initialized cmdline_parser_params structure
210
- */
211
-struct cmdline_parser_params *cmdline_parser_params_create(void);
212
-
213
-/**
214
- * Initializes the passed gengetopt_args_info structure's fields
215
- * (also set default values for options that have a default)
216
- * @param args_info the structure to initialize
217
- */
218
-void cmdline_parser_init (struct gengetopt_args_info *args_info);
219
-/**
220
- * Deallocates the string fields of the gengetopt_args_info structure
221
- * (but does not deallocate the structure itself)
222
- * @param args_info the structure to deallocate
223
- */
224
-void cmdline_parser_free (struct gengetopt_args_info *args_info);
225
-
226
-/**
227
- * Checks that all the required options were specified
228
- * @param args_info the structure to check
229
- * @param prog_name the name of the program that will be used to print
230
- *   possible errors
231
- * @return
232
- */
233
-int cmdline_parser_required (struct gengetopt_args_info *args_info,
234
-  const char *prog_name);
235
-
236
-
237
-#ifdef __cplusplus
238
-}
239
-#endif /* __cplusplus */
240
-#endif /* CMDLINE_H */

+ 66
- 424
src/framebuffer.cpp Просмотреть файл

@@ -1,444 +1,86 @@
1 1
 #include "framebuffer.hpp"
2 2
 
3
-slop::Framebuffer::Framebuffer() {
4
-    m_shader = new slop::Shader( "simple", resource->getRealPath( "simple.vert" ), resource->getRealPath( "simple.frag" ) );
5
-    generatedBuffers = false;
6
-    m_width = 0;
7
-    m_height = 0;
8
-    m_flags = (slop::Framebuffer::buffers)0;
9
-    m_depth = 0;
10
-    m_stencil = 0;
11
-    m_frame = 0;
12
-    m_buffers[0] = 0;
13
-    m_buffers[1] = 0;
14
-    m_texture = 0;
15
-}
16
-
17
-void slop::Framebuffer::setShader( std::string shader ) {
18
-    delete m_shader;
19
-    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
20
-}
21
-
22
-slop::Framebuffer::Framebuffer( unsigned int width, unsigned int height, unsigned char flags, std::string shader ) {
23
-    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
24
-    generatedBuffers = false;
25
-    m_width = width;
26
-    m_height = height;
27
-    m_flags = flags;
28
-    if ( m_flags & stencil && m_flags & depth ) {
29
-        fprintf( stderr, "Most hardware doesn't support using a FBO with a depth and stencil attached! Condensing them to one render buffer..." );
30
-    }
31
-    if ( GLEW_VERSION_3_0 ) {
32
-        glGenFramebuffers( 1, &m_frame );
33
-        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
34
-        if ( m_flags & color ) {
35
-            glGenTextures( 1, &m_texture );
36
-            glBindTexture( GL_TEXTURE_2D, m_texture );
37
-            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
38
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
39
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
40
-            glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0 );
41
-        }
42
-
43
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
44
-            glGenRenderbuffers( 1, &m_depth );
45
-            glBindRenderbuffer( GL_RENDERBUFFER, m_depth );
46
-            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_width, m_height );
47
-            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth );
48
-        }
49
-
50
-        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
51
-        if ( m_flags & stencil ) {
52
-            glGenRenderbuffers( 1, &m_stencil );
53
-            glBindRenderbuffer( GL_RENDERBUFFER, m_stencil );
54
-            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_width, m_height );
55
-            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
56
-            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
57
-        }
58
-        check();
59
-        //Make sure we unbind when we're done.
60
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
61
-    } else if ( GLEW_EXT_framebuffer_object ) {
62
-        glGenFramebuffersEXT( 1, &m_frame );
63
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
3
+slop::Framebuffer::Framebuffer( int w, int h ) {
4
+    std::string vert = "#version 130\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 uvCoord;\nvoid main()\n{\nuvCoord = uv;\ngl_Position = vec4(position,0,1);\n}\n";
5
+    std::string frag = "#version 130\nuniform sampler2D texture;\nvarying vec2 uvCoord;\nout vec4 outColor;void main()\n{\noutColor = texture2D( texture, uvCoord );\n}\n";
6
+    shader = new Shader( vert, frag, false );
7
+    glGenFramebuffers( 1, &fbuffer );
8
+    glBindFramebuffer( GL_FRAMEBUFFER, fbuffer );
9
+    glGenTextures(1, &image);
10
+    glBindTexture(GL_TEXTURE_2D, image);
11
+    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
14
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0);
15
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
16
+    // generate our vertex and uv buffers
17
+    std::vector<glm::vec2> verts;
18
+    std::vector<glm::vec2> uvs;
64 19
 
65
-        if ( m_flags & color ) {
66
-            glGenTextures( 1, &m_texture );
67
-            glBindTexture( GL_TEXTURE_2D, m_texture );
68
-            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
69
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
70
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
71
-            glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0 );
72
-        }
20
+    verts.push_back( glm::vec2(1,1) );
21
+    uvs.push_back( glm::vec2( 1, 1 ) );
22
+    verts.push_back( glm::vec2(-1,-1) );
23
+    uvs.push_back( glm::vec2( 0, 0 ) );
24
+    verts.push_back( glm::vec2(-1,1) );
25
+    uvs.push_back( glm::vec2( 0, 1 ) );
26
+    verts.push_back( glm::vec2(-1,-1) );
27
+    uvs.push_back( glm::vec2( 0, 0 ) );
28
+    verts.push_back( glm::vec2(1,1) );
29
+    uvs.push_back( glm::vec2( 1, 1 ) );
30
+    verts.push_back( glm::vec2(1,-1) );
31
+    uvs.push_back( glm::vec2( 1, 0 ) );
73 32
 
74
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
75
-            glGenRenderbuffersEXT( 1, &m_depth );
76
-            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depth );
77
-            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_width, m_height );
78
-            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depth );
79
-        }
33
+    glGenBuffers( 2, buffers );
34
+    glBindBuffer( GL_ARRAY_BUFFER, buffers[0] );
35
+    glBufferData( GL_ARRAY_BUFFER, verts.size() * sizeof( glm::vec2 ), &verts[0], GL_STATIC_DRAW );
36
+    glBindBuffer( GL_ARRAY_BUFFER, buffers[1] );
37
+    glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW );
38
+    vertCount = verts.size();
39
+}
80 40
 
81
-        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
82
-        if ( m_flags & stencil ) {
83
-            glGenRenderbuffersEXT( 1, &m_stencil );
84
-            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_stencil );
85
-            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_width, m_height );
86
-            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
87
-            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
88
-        }
89
-        check();
90
-        //Make sure we unbind when we're done.
91
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
92
-    } else {
93
-        throw std::runtime_error( "Error: Failed to create framebuffer! You need OpenGL 3.0 or the GL_EXT_framebuffer_object extension!" );
94
-    }
41
+void slop::Framebuffer::setShader( std::string name ) {
42
+    delete shader;
43
+    shader = new Shader( name + ".vert", name + ".frag" );
95 44
 }
96 45
 
97 46
 slop::Framebuffer::~Framebuffer() {
98
-    if ( GLEW_VERSION_3_0 ) {
99
-        glDeleteFramebuffers( 1, &m_frame );
100
-        if ( m_flags & color ) {
101
-            glDeleteTextures( 1, &m_texture );
102
-        }
103
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
104
-            glDeleteRenderbuffers( 1, &m_depth );
105
-        }
106
-        if ( m_flags & stencil ) {
107
-            glDeleteRenderbuffers( 1, &m_stencil );
108
-        }
109
-    } else if ( GLEW_EXT_framebuffer_object ) {
110
-        glDeleteFramebuffersEXT( 1, &m_frame );
111
-        if ( m_flags & color ) {
112
-            glDeleteTextures( 1, &m_texture );
113
-        }
114
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
115
-            glDeleteRenderbuffersEXT( 1, &m_depth );
116
-        }
117
-        if ( m_flags & stencil ) {
118
-            glDeleteRenderbuffersEXT( 1, &m_stencil );
119
-        }
120
-    }
121
-    if ( generatedBuffers ) {
122
-        glDeleteBuffers( 2, m_buffers );
123
-    }
124
-    delete m_shader;
47
+    glDeleteTextures(1, &image);
48
+    glDeleteFramebuffers(1,&fbuffer);
49
+    glDeleteBuffers(2,buffers);
50
+    delete shader;
125 51
 }
126 52
 
127
-void slop::Framebuffer::bind() {
128
-    if ( GLEW_VERSION_3_0 ) {
129
-        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
130
-    } else if ( GLEW_EXT_framebuffer_object ) {
131
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
132
-    }
53
+void slop::Framebuffer::resize( int w, int h ) {
54
+    // Regenerate the image
55
+    glDeleteTextures(1, &image);
56
+    glBindTexture(GL_TEXTURE_2D, image);
57
+    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
58
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
59
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
60
+
61
+    // Re-bind it to the framebuffer
62
+    glBindFramebuffer( GL_FRAMEBUFFER, fbuffer );
63
+    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0);
64
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
133 65
 }
134 66
 
135
-void slop::Framebuffer::unbind() {
136
-    if ( GLEW_VERSION_3_0 ) {
137
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
138
-    } else if ( GLEW_EXT_framebuffer_object ) {
139
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
140
-    }
67
+void slop::Framebuffer::bind() {
68
+    glBindFramebuffer( GL_FRAMEBUFFER, fbuffer );
141 69
 }
142 70
 
143
-void slop::Framebuffer::createFromTexture( unsigned int texture, std::string shader ) {
144
-    // First make sure we're empty.
145
-    if ( GLEW_VERSION_3_0 ) {
146
-        glDeleteFramebuffers( 1, &m_frame );
147
-        if ( m_flags & color ) {
148
-            glDeleteTextures( 1, &m_texture );
149
-        }
150
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
151
-            glDeleteRenderbuffers( 1, &m_depth );
152
-        }
153
-        if ( m_flags & stencil ) {
154
-            glDeleteRenderbuffers( 1, &m_stencil );
155
-        }
156
-    } else if ( GLEW_EXT_framebuffer_object ) {
157
-        glDeleteFramebuffersEXT( 1, &m_frame );
158
-        if ( m_flags & color ) {
159
-            glDeleteTextures( 1, &m_texture );
160
-        }
161
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
162
-            glDeleteRenderbuffersEXT( 1, &m_depth );
163
-        }
164
-        if ( m_flags & stencil ) {
165
-            glDeleteRenderbuffersEXT( 1, &m_stencil );
166
-        }
167
-    }
168
-    delete m_shader;
169
-    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
170
-    // Set flags to 0 so we don't delete the texture on deconstruction.
171
-    m_flags = 0;
172
-    m_texture = texture;
173
-    if ( GLEW_VERSION_3_0 ) {
174
-        glGenFramebuffers( 1, &m_frame );
175
-        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
176
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0 );
177
-    } else if ( GLEW_EXT_framebuffer_object ) {
178
-        glGenFramebuffersEXT( 1, &m_frame );
179
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
180
-        glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0 );
181
-    }
182
-    check();
71
+void slop::Framebuffer::unbind() {
183 72
     glBindFramebuffer( GL_FRAMEBUFFER, 0 );
184 73
 }
185 74
 
186
-void slop::Framebuffer::create( unsigned int width, unsigned int height, unsigned char flags, std::string shader ) {
187
-    if ( m_width == width && m_height == height && m_flags == flags ) {
188
-        return;
189
-    }
190
-    delete m_shader;
191
-    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
192
-    if ( GLEW_VERSION_3_0 ) {
193
-        glDeleteFramebuffers( 1, &m_frame );
194
-        if ( m_flags & color ) {
195
-            glDeleteTextures( 1, &m_texture );
196
-        }
197
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
198
-            glDeleteRenderbuffers( 1, &m_depth );
199
-        }
200
-        if ( m_flags & stencil ) {
201
-            glDeleteRenderbuffers( 1, &m_stencil );
202
-        }
203
-    } else if ( GLEW_EXT_framebuffer_object ) {
204
-        glDeleteFramebuffersEXT( 1, &m_frame );
205
-        if ( m_flags & color ) {
206
-            glDeleteTextures( 1, &m_texture );
207
-        }
208
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
209
-            glDeleteRenderbuffersEXT( 1, &m_depth );
210
-        }
211
-        if ( m_flags & stencil ) {
212
-            glDeleteRenderbuffersEXT( 1, &m_stencil );
213
-        }
214
-    }
215
-    m_flags = flags;
216
-    m_width = width;
217
-    m_height = height;
218
-    if ( GLEW_VERSION_3_0 ) {
219
-        glGenFramebuffers( 1, &m_frame );
220
-        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
221
-
222
-        if ( m_flags & color ) {
223
-            glGenTextures( 1, &m_texture );
224
-            glBindTexture( GL_TEXTURE_2D, m_texture );
225
-            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
226
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
227
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
228
-            glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0 );
229
-        }
230
-
231
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
232
-            glGenRenderbuffers( 1, &m_depth );
233
-            glBindRenderbuffer( GL_RENDERBUFFER, m_depth );
234
-            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_width, m_height );
235
-            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth );
236
-        }
237
-
238
-        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
239
-        if ( m_flags & stencil ) {
240
-            glGenRenderbuffers( 1, &m_stencil );
241
-            glBindRenderbuffer( GL_RENDERBUFFER, m_stencil );
242
-            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_width, m_height );
243
-            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
244
-            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
245
-        }
246
-        //Make sure we unbind when we're done.
247
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
248
-    } else if ( GLEW_EXT_framebuffer_object ) {
249
-        glGenFramebuffersEXT( 1, &m_frame );
250
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
251
-
252
-        if ( m_flags & color ) {
253
-            glGenTextures( 1, &m_texture );
254
-            glBindTexture( GL_TEXTURE_2D, m_texture );
255
-            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
256
-           glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
257
-            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
258
-            glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0 );
259
-        }
260
-
261
-        if ( m_flags & depth && !( m_flags & stencil ) ) {
262
-            glGenRenderbuffersEXT( 1, &m_depth );
263
-            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depth );
264
-            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_width, m_height );
265
-            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depth );
266
-        }
267
-
268
-        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
269
-        if ( m_flags & stencil ) {
270
-            glGenRenderbuffersEXT( 1, &m_stencil );
271
-            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_stencil );
272
-            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_width, m_height );
273
-            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
274
-            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
275
-        }
276
-        //Make sure we unbind when we're done.
277
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
278
-    }
279
-}
280
-
281
-void slop::Framebuffer::check()
282
-{
283
-    if ( GLEW_VERSION_3_0 ) {
284
-        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
285
-        unsigned int err = glCheckFramebufferStatus( GL_FRAMEBUFFER );
286
-        if ( err == GL_FRAMEBUFFER_COMPLETE ) {
287
-            return;
288
-        }
289
-        fprintf( stderr, "Error: Framebuffer failed a check procedure for reason: " );
290
-        switch ( err ) {
291
-            case GL_FRAMEBUFFER_UNDEFINED: {
292
-                fprintf( stderr, "GL_FRAMEBUFFER_UNDEFINED\n" );
293
-                break;
294
-            }
295
-            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: {
296
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n" );
297
-                break;
298
-            }
299
-            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: {
300
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n" );
301
-                break;
302
-            }
303
-            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: {
304
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER\n" );
305
-                break;
306
-            }
307
-            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: {
308
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER\n" );
309
-                break;
310
-            }
311
-            case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: {
312
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS\n" );
313
-                break;
314
-            }
315
-            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: {
316
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\n" );
317
-                break;
318
-            }
319
-            case GL_FRAMEBUFFER_UNSUPPORTED: {
320
-                fprintf( stderr, "GL_FRAMEBUFFER_UNSUPPORTED\n" );
321
-                break;
322
-            }
323
-            default: {
324
-                fprintf( stderr, "UNKNOWN\n" );
325
-                break;
326
-            }
327
-        }
328
-        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
329
-    } else if ( GLEW_EXT_framebuffer_object ) {
330
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
331
-        unsigned int err = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
332
-        if ( err == GL_FRAMEBUFFER_COMPLETE_EXT ) {
333
-            return;
334
-        }
335
-        switch ( err ) {
336
-            /* Apparently doesn't exist as an extension.
337
-               case GL_FRAMEBUFFER_UNDEFINED_EXT: {
338
-                fprintf( stderr, "GL_FRAMEBUFFER_UNDEFINED_EXT\n" );
339
-                break;
340
-            }*/
341
-            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: {
342
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n" );
343
-                break;
344
-            }
345
-            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: {
346
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n" );
347
-                break;
348
-            }
349
-            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: {
350
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n" );
351
-                break;
352
-            }
353
-            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: {
354
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n" );
355
-                break;
356
-            }
357
-            case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT: {
358
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT\n" );
359
-                break;
360
-            }
361
-            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: {
362
-                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT\n" );
363
-                break;
364
-            }
365
-            case GL_FRAMEBUFFER_UNSUPPORTED_EXT: {
366
-                fprintf( stderr, "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n" );
367
-                break;
368
-            }
369
-            default: {
370
-                fprintf( stderr, "Unknown framebuffer error!\n" );
371
-                break;
372
-            }
373
-        }
374
-        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
375
-    }
376
-}
377
-
378
-void slop::Framebuffer::generateBuffers() {
379
-    if ( generatedBuffers ) {
380
-        return;
381
-    }
382
-    std::vector<glm::vec2> verts;
383
-    std::vector<glm::vec2> uvs;
384
-    verts.push_back( glm::vec2( -1, -1 ) );
385
-    verts.push_back( glm::vec2( 1, -1 ) );
386
-    verts.push_back( glm::vec2( 1, 1 ) );
387
-    verts.push_back( glm::vec2( -1, 1 ) );
388
-    uvs.push_back( glm::vec2( 0, 0 ) );
389
-    uvs.push_back( glm::vec2( 1, 0 ) );
390
-    uvs.push_back( glm::vec2( 1, 1 ) );
391
-    uvs.push_back( glm::vec2( 0, 1 ) );
392
-
393
-    glGenBuffers( 2, m_buffers );
394
-    glBindBuffer( GL_ARRAY_BUFFER, m_buffers[0] );
395
-    glBufferData( GL_ARRAY_BUFFER, verts.size() * sizeof( glm::vec2 ), &verts[0], GL_STATIC_DRAW );
396
-    glBindBuffer( GL_ARRAY_BUFFER, m_buffers[1] );
397
-    glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW );
398
-    generatedBuffers = true;
399
-}
400
-
401
-void slop::Framebuffer::clear( glm::vec4 clearcolor, unsigned char flags ) {
402
-    // FIXME: This should auto-bind and unbind, but I was too lazy to find out how to push and pop gl states.
403
-    unsigned int colorbit = 0;
404
-    if ( flags & color ) {
405
-        colorbit = colorbit | GL_COLOR_BUFFER_BIT;
406
-    }
407
-    if ( m_flags & depth && flags & depth ) {
408
-        colorbit = colorbit | GL_DEPTH_BUFFER_BIT;
409
-    }
410
-    if ( m_flags & stencil && flags & stencil) {
411
-        colorbit = colorbit | GL_STENCIL_BUFFER_BIT;
412
-    }
413
-    glClearColor( clearcolor.x, clearcolor.y, clearcolor.z, clearcolor.w );
414
-    glClear( colorbit );
415
-}
416
-
417
-void slop::Framebuffer::draw( float time, unsigned int desktop ) {
418
-    if ( !( m_flags & color ) ) {
419
-        return;
420
-    }
421
-
422
-    generateBuffers();
423
-
424
-    //slop::Shader* shader = shaders->get( "simple" );
425
-    m_shader->bind();
426
-    m_shader->setParameter( "texture", 0 );
427
-    m_shader->setParameter( "desktop", 1 );
428
-    m_shader->setParameter( "time", time );
429
-    m_shader->setParameter( "desktopWidth", (int)xengine->getWidth() );
430
-    m_shader->setParameter( "desktopHeight", (int)xengine->getHeight() );
431
-    m_shader->setAttribute( "vertex", m_buffers[0], 2 );
432
-    m_shader->setAttribute( "uv", m_buffers[1], 2 );
433
-
434
-    glActiveTexture(GL_TEXTURE0 + 0);
435
-    glBindTexture( GL_TEXTURE_2D, m_texture );
436
-    glActiveTexture(GL_TEXTURE0 + 1);
437
-    glBindTexture( GL_TEXTURE_2D, desktop );
438
-    glActiveTexture(GL_TEXTURE0 + 0);
75
+void slop::Framebuffer::draw(){
76
+    shader->bind();
77
+    shader->setParameter( "texture", 0 );
78
+    shader->setAttribute( "position", buffers[0], 2 );
79
+    shader->setAttribute( "uv", buffers[1], 2 );
80
+    glActiveTexture(GL_TEXTURE0);
81
+    glBindTexture( GL_TEXTURE_2D, image );
439 82
     glEnable( GL_TEXTURE_2D );
440
-    glDrawArrays( GL_QUADS, 0, 4 );
83
+    glDrawArrays( GL_TRIANGLES, 0, vertCount );
441 84
     glDisable( GL_TEXTURE_2D );
442
-
443
-    m_shader->unbind();
85
+    shader->unbind();
444 86
 }

+ 37
- 36
src/framebuffer.hpp Просмотреть файл

@@ -1,51 +1,52 @@
1
-#ifndef IS_FRAMEBUFFER_H_
2
-#define IS_FRAMEBUFFER_H_
1
+/* framebuffer.hpp: Creates and manages an off-screen framebuffer. Uses supplied shader to draw it to the screen.
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
3 20
 
4
-#include <GL/glew.h>
5
-#include <GL/gl.h>
21
+#ifndef N_FRAMEBUFFER_H_
22
+#define N_FRAMEBUFFER_H_
23
+
24
+#include "gl_core_3_3.h"
6 25
 #include <glm/glm.hpp>
7
-#include <stdexcept>
26
+#include <GL/gl.h>
27
+#include <vector>
8 28
 
9
-#include "x.hpp"
10 29
 #include "shader.hpp"
11
-#include "resource.hpp"
12 30
 
13 31
 namespace slop {
14 32
 
15
-class Framebuffer
16
-{
33
+class Framebuffer {
34
+private:
35
+    unsigned int fbuffer;
36
+    unsigned int image;
37
+    unsigned int buffers[2];
38
+    unsigned int vertCount;
39
+    Shader* shader;
17 40
 public:
18
-    enum buffers
19
-    {
20
-        color = 0x01,
21
-        depth = 0x02,
22
-        stencil = 0x04
23
-    };
24
-    Framebuffer();
25
-    Framebuffer( unsigned int width, unsigned int height, unsigned char flags = color, std::string shader = "simple" );
41
+    Framebuffer( int w, int h );
26 42
     ~Framebuffer();
27
-    void create( unsigned int width, unsigned int height, unsigned char flags = color, std::string shader = "simple" );
28
-    void createFromTexture( unsigned int texture, std::string shader = "simple" );
29
-    void setShader( std::string shader = "simple" );
30
-    void clear( glm::vec4 color = glm::vec4( 0, 0, 0, 1 ), unsigned char flags = color | depth | stencil );
43
+    void setShader( std::string );
44
+    void draw();
45
+    void resize( int w, int h );
31 46
     void bind();
32 47
     void unbind();
33
-    void draw( float time, unsigned int image );
34
-    unsigned int m_texture;
35
-    unsigned int m_depth;
36
-    unsigned int m_stencil;
37
-    slop::Shader* m_shader;
38
-private:
39
-    unsigned int m_width;
40
-    unsigned int m_height;
41
-    void check();
42
-    void generateBuffers();
43
-    unsigned char m_flags;
44
-    bool generatedBuffers;
45
-    unsigned int m_frame;
46
-    unsigned int m_buffers[2];
47 48
 };
48 49
 
49 50
 }
50 51
 
51
-#endif //IS_FRAMEBUFFER_H_
52
+#endif

+ 1261
- 0
src/gl_core_3_3.c
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 1700
- 0
src/gl_core_3_3.h
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 246
- 0
src/glrectangle.cpp Просмотреть файл

@@ -0,0 +1,246 @@
1
+#include "glrectangle.hpp"
2
+
3
+slop::GLRectangle::GLRectangle( glm::vec2 p1, glm::vec2 p2, float border, float padding, glm::vec4 color, bool highlight ) {
4
+    this->color = color;
5
+    this->border = border;
6
+    this->padding = padding;
7
+    this->highlight = highlight;
8
+    // Find each corner of the rectangle
9
+    ul = glm::vec2( glm::min( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
10
+    bl = glm::vec2( glm::min( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
11
+    ur = glm::vec2( glm::max( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
12
+    br = glm::vec2( glm::max( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
13
+    // Offset the inner corners by the padding.
14
+    ul = ul + glm::vec2(-padding,padding);
15
+    bl = bl + glm::vec2(-padding,-padding);
16
+    ur = ur + glm::vec2(padding,padding);
17
+    br = br + glm::vec2(padding,-padding);
18
+    // Create the outer corners by offsetting the inner by the bordersize
19
+    oul = ul + glm::vec2(-border,border);
20
+    obl = bl + glm::vec2(-border,-border);
21
+    our = ur + glm::vec2(border,border);
22
+    obr = br + glm::vec2(border,-border);
23
+    generateBuffers();
24
+    std::string vert = "#version 130\nin vec2 position;\nuniform mat4 projection;\nvoid main() {\ngl_Position = projection*vec4(position,0,1);\n }";
25
+    std::string frag = "#version 130\nuniform vec4 color;\nout vec4 outColor;\nvoid main() {\noutColor = color;\n}";
26
+
27
+    shader = new Shader( vert, frag, false );
28
+}
29
+
30
+void slop::GLRectangle::setPoints( glm::vec2 p1, glm::vec2 p2 ) {
31
+    // Find each corner of the rectangle
32
+    ul = glm::vec2( glm::min( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
33
+    bl = glm::vec2( glm::min( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
34
+    ur = glm::vec2( glm::max( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
35
+    br = glm::vec2( glm::max( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
36
+    // Offset the inner corners by the padding.
37
+    ul = ul + glm::vec2(-padding,padding);
38
+    bl = bl + glm::vec2(-padding,-padding);
39
+    ur = ur + glm::vec2(padding,padding);
40
+    br = br + glm::vec2(padding,-padding);
41
+    // Create the outer corners by offsetting the inner by the bordersize
42
+    oul = ul + glm::vec2(-border,border);
43
+    obl = bl + glm::vec2(-border,-border);
44
+    our = ur + glm::vec2(border,border);
45
+    obr = br + glm::vec2(border,-border);
46
+    generateBuffers();
47
+}
48
+
49
+void slop::GLRectangle::generateBuffers() {
50
+    std::vector<glm::vec2> rectangle_verts;
51
+    std::vector<glm::vec2> rectangle_uvs;
52
+    std::vector<glm::vec2> corner_verts;
53
+    std::vector<glm::vec2> corner_uvs;
54
+    std::vector<glm::vec2> center_verts;
55
+    std::vector<glm::vec2> center_uvs;
56
+
57
+    // Top left corner
58
+    corner_verts.push_back( oul );
59
+    corner_uvs.push_back( glm::vec2(0, 1) );
60
+    corner_verts.push_back( ul );
61
+    corner_uvs.push_back( glm::vec2(1, 0) );
62
+    corner_verts.push_back( ul + glm::vec2( -border, 0 ) );
63
+    corner_uvs.push_back( glm::vec2(0, 0) );
64
+
65
+    corner_verts.push_back( oul );
66
+    corner_uvs.push_back( glm::vec2(0, 1) );
67
+    corner_verts.push_back( ul + glm::vec2( 0, border ) );
68
+    corner_uvs.push_back( glm::vec2(1, 1) );
69
+    corner_verts.push_back( ul );
70
+    corner_uvs.push_back( glm::vec2(1, 0) );
71
+
72
+    // Top right corner
73
+    corner_verts.push_back( ur + glm::vec2( 0, border ) );
74
+    corner_uvs.push_back( glm::vec2(0, 1) );
75
+    corner_verts.push_back( ur + glm::vec2( border, 0 ) );
76
+    corner_uvs.push_back( glm::vec2(1, 0) );
77
+    corner_verts.push_back( ur );
78
+    corner_uvs.push_back( glm::vec2(0, 0) );
79
+
80
+    corner_verts.push_back( ur + glm::vec2( 0, border ) );
81
+    corner_uvs.push_back( glm::vec2(0, 1) );
82
+    corner_verts.push_back( our );
83
+    corner_uvs.push_back( glm::vec2(1, 1) );
84
+    corner_verts.push_back( ur + glm::vec2( border, 0 ) );
85
+    corner_uvs.push_back( glm::vec2(1, 0) );
86
+
87
+    // Bottom left corner
88
+    corner_verts.push_back( bl + glm::vec2( -border, 0 ) );
89
+    corner_uvs.push_back( glm::vec2(0, 1) );
90
+    corner_verts.push_back( obl + glm::vec2( border, 0 ) );
91
+    corner_uvs.push_back( glm::vec2(1, 0) );
92
+    corner_verts.push_back( obl );
93
+    corner_uvs.push_back( glm::vec2(0, 0) );
94
+
95
+    corner_verts.push_back( bl + glm::vec2( -border, 0 ) );
96
+    corner_uvs.push_back( glm::vec2(0, 1) );
97
+    corner_verts.push_back( bl );
98
+    corner_uvs.push_back( glm::vec2(1, 1) );
99
+    corner_verts.push_back( bl + glm::vec2( 0, -border ) );
100
+    corner_uvs.push_back( glm::vec2(1, 0) );
101
+
102
+    // Bottom right corner
103
+    corner_verts.push_back( br );
104
+    corner_uvs.push_back( glm::vec2(0, 1) );
105
+    corner_verts.push_back( obr );
106
+    corner_uvs.push_back( glm::vec2(1, 0) );
107
+    corner_verts.push_back( br + glm::vec2( 0, -border ) );
108
+    corner_uvs.push_back( glm::vec2(0, 0) );
109
+
110
+    corner_verts.push_back( br );
111
+    corner_uvs.push_back( glm::vec2(0, 1) );
112
+    corner_verts.push_back( br + glm::vec2( border, 0 ) );
113
+    corner_uvs.push_back( glm::vec2(1, 1) );
114
+    corner_verts.push_back( obr );
115
+    corner_uvs.push_back( glm::vec2(1, 0) );
116
+
117
+    // Left GLRectangle
118
+    rectangle_verts.push_back( ul + glm::vec2( -border, 0 ) );
119
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
120
+    rectangle_verts.push_back( bl );
121
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
122
+    rectangle_verts.push_back( bl + glm::vec2( -border, 0 ) );
123
+    rectangle_uvs.push_back( glm::vec2(0, 0) );
124
+
125
+    rectangle_verts.push_back( ul + glm::vec2( -border, 0 ) );
126
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
127
+    rectangle_verts.push_back( ul );
128
+    rectangle_uvs.push_back( glm::vec2(1, 1) );
129
+    rectangle_verts.push_back( bl );
130
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
131
+
132
+    // Right GLRectangle
133
+    rectangle_verts.push_back( ur );
134
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
135
+    rectangle_verts.push_back( br + glm::vec2( border, 0 ) );
136
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
137
+    rectangle_verts.push_back( br );
138
+    rectangle_uvs.push_back( glm::vec2(0, 0) );
139
+
140
+    rectangle_verts.push_back( ur );
141
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
142
+    rectangle_verts.push_back( ur + glm::vec2( border, 0 ) );
143
+    rectangle_uvs.push_back( glm::vec2(1, 1) );
144
+    rectangle_verts.push_back( br + glm::vec2( border, 0 ) );
145
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
146
+
147
+    // Top GLRectangle
148
+    rectangle_verts.push_back( ul + glm::vec2( 0, border ) );
149
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
150
+    rectangle_verts.push_back( ur );
151
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
152
+    rectangle_verts.push_back( ul );
153
+    rectangle_uvs.push_back( glm::vec2(0, 0) );
154
+
155
+    rectangle_verts.push_back( ul + glm::vec2( 0, border ) );
156
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
157
+    rectangle_verts.push_back( ur + glm::vec2( 0, border ) );
158
+    rectangle_uvs.push_back( glm::vec2(1, 1) );
159
+    rectangle_verts.push_back( ur );
160
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
161
+
162
+    // Bot GLRectangle
163
+    rectangle_verts.push_back( bl );
164
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
165
+    rectangle_verts.push_back( br + glm::vec2( 0, -border ) );
166
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
167
+    rectangle_verts.push_back( bl + glm::vec2( 0, -border ) );
168
+    rectangle_uvs.push_back( glm::vec2(0, 0) );
169
+
170
+    rectangle_verts.push_back( bl );
171
+    rectangle_uvs.push_back( glm::vec2(0, 1) );
172
+    rectangle_verts.push_back( br );
173
+    rectangle_uvs.push_back( glm::vec2(1, 1) );
174
+    rectangle_verts.push_back( br + glm::vec2( 0, -border ) );
175
+    rectangle_uvs.push_back( glm::vec2(1, 0) );
176
+
177
+    center_verts.push_back( ul );
178
+    center_uvs.push_back( glm::vec2(0, 1) );
179
+    center_verts.push_back( br );
180
+    center_uvs.push_back( glm::vec2(1, 0) );
181
+    center_verts.push_back( bl );
182
+    center_uvs.push_back( glm::vec2(0, 0) );
183
+
184
+    center_verts.push_back( ul );
185
+    center_uvs.push_back( glm::vec2(0, 1) );
186
+    center_verts.push_back( ur );
187
+    center_uvs.push_back( glm::vec2(1, 1) );
188
+    center_verts.push_back( br );
189
+    center_uvs.push_back( glm::vec2(1, 0) );
190
+
191
+    glGenBuffers( 6, (GLuint*)&buffer );
192
+    glBindBuffer( GL_ARRAY_BUFFER, buffer.corner_verts );
193
+    glBufferData( GL_ARRAY_BUFFER, corner_verts.size() * sizeof( glm::vec2 ), &corner_verts[0], GL_STATIC_DRAW );
194
+    glBindBuffer( GL_ARRAY_BUFFER, buffer.corner_uvs );
195
+    glBufferData( GL_ARRAY_BUFFER, corner_uvs.size() * sizeof( glm::vec2 ), &corner_uvs[0], GL_STATIC_DRAW );
196
+
197
+    glBindBuffer( GL_ARRAY_BUFFER, buffer.rectangle_verts );
198
+    glBufferData( GL_ARRAY_BUFFER, rectangle_verts.size() * sizeof( glm::vec2 ), &rectangle_verts[0], GL_STATIC_DRAW );
199
+    glBindBuffer( GL_ARRAY_BUFFER, buffer.rectangle_uvs );
200
+    glBufferData( GL_ARRAY_BUFFER, rectangle_uvs.size() * sizeof( glm::vec2 ), &rectangle_uvs[0], GL_STATIC_DRAW );
201
+
202
+    glBindBuffer( GL_ARRAY_BUFFER, buffer.center_verts );
203
+    glBufferData( GL_ARRAY_BUFFER, center_verts.size() * sizeof( glm::vec2 ), &center_verts[0], GL_STATIC_DRAW );
204
+    glBindBuffer( GL_ARRAY_BUFFER, buffer.rectangle_uvs );
205
+    glBufferData( GL_ARRAY_BUFFER, center_uvs.size() * sizeof( glm::vec2 ), &center_uvs[0], GL_STATIC_DRAW );
206
+    corner_vertCount = corner_verts.size();
207
+    rectangle_vertCount = rectangle_verts.size();
208
+    center_vertCount = center_verts.size();
209
+}
210
+
211
+slop::GLRectangle::~GLRectangle() {
212
+    delete shader;
213
+    glDeleteBuffers( 6, (GLuint*)&buffer );
214
+}
215
+
216
+void slop::GLRectangle::draw( glm::mat4& matrix ) {
217
+    glEnable( GL_BLEND );
218
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
219
+    shader->bind();
220
+    shader->setParameter( "projection", matrix );
221
+    if ( highlight ) {
222
+        // Draw the center of the highlight
223
+        shader->setParameter( "color", color );
224
+        shader->setAttribute( "position", buffer.center_verts, 2 );
225
+        glDrawArrays(GL_TRIANGLES, 0, center_vertCount );
226
+        // Set the color to have no alpha, then draw the borders.
227
+        glm::vec4 fullAlpha = glm::vec4(color.r,color.g,color.b,1);
228
+        shader->setParameter( "color", fullAlpha );
229
+        shader->setAttribute( "position", buffer.corner_verts, 2 );
230
+        glDrawArrays(GL_TRIANGLES, 0, corner_vertCount );
231
+        shader->setAttribute( "position", buffer.rectangle_verts, 2 );
232
+        glDrawArrays(GL_TRIANGLES, 0, rectangle_vertCount );
233
+    } else {
234
+        shader->setParameter( "color", color );
235
+        shader->setAttribute( "position", buffer.corner_verts, 2 );
236
+        glDrawArrays(GL_TRIANGLES, 0, corner_vertCount );
237
+        shader->setAttribute( "position", buffer.rectangle_verts, 2 );
238
+        glDrawArrays(GL_TRIANGLES, 0, rectangle_vertCount );
239
+    }
240
+    shader->unbind();
241
+    glDisable( GL_BLEND );
242
+}
243
+
244
+glm::vec4 slop::GLRectangle::getRect() {
245
+    return glm::vec4( bl.x, bl.y, ur.x-ul.x, ul.y-bl.y );
246
+}

+ 70
- 0
src/glrectangle.hpp Просмотреть файл

@@ -0,0 +1,70 @@
1
+/* rectangle.hpp: generates a vertex mesh and draws it.
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#ifndef N_GLRECTANGLE_H_
22
+#define N_GLRECTANGLE_H_
23
+
24
+#include "gl_core_3_3.h"
25
+#include <iostream>
26
+#include <glm/glm.hpp>
27
+#include <GL/gl.h>
28
+#include <vector>
29
+
30
+#include "shader.hpp"
31
+#include "rectangle.hpp"
32
+
33
+namespace slop {
34
+
35
+struct RectangleBuffer {
36
+    unsigned int corner_verts;
37
+    unsigned int corner_uvs;
38
+    unsigned int rectangle_verts;
39
+    unsigned int rectangle_uvs;
40
+    unsigned int center_verts;
41
+    unsigned int center_uvs;
42
+};
43
+
44
+class GLRectangle : public Rectangle {
45
+private:
46
+    glm::vec2 ul, oul;
47
+    glm::vec2 bl, obl;
48
+    glm::vec2 ur, our;
49
+    glm::vec2 br, obr;
50
+    bool highlight;
51
+    void generateBuffers();
52
+    RectangleBuffer buffer;
53
+    unsigned int corner_vertCount;
54
+    unsigned int rectangle_vertCount;
55
+    unsigned int center_vertCount;
56
+    float border;
57
+    float padding;
58
+    Shader* shader;
59
+    glm::vec4 color;
60
+public:
61
+    glm::vec4 getRect();
62
+    GLRectangle(glm::vec2 p1, glm::vec2 p2, float border = 1, float padding = 0, glm::vec4 color = glm::vec4(1,1,1,1), bool highlight = false );
63
+    ~GLRectangle();
64
+    void setPoints( glm::vec2 p1, glm::vec2 p2 );
65
+    void draw(glm::mat4& matrix);
66
+};
67
+
68
+}
69
+
70
+#endif // N_RECTANGLE_H_

+ 0
- 683
src/glselectrectangle.cpp Просмотреть файл

@@ -1,683 +0,0 @@
1
-/* glrectangle.hpp: Handles creating hardware accelerated rectangles on the screen using X11 and OpenGL.
2
- *
3
- * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
- *
5
- * This file is part of Slop.
6
- *
7
- * Slop is free software: you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, either version 3 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * Slop is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-#include "glselectrectangle.hpp"
21
-
22
-static Bool isDestroyNotify( Display* dpy, XEvent* ev, XPointer win ) {
23
-    return ev->type == DestroyNotify && ev->xdestroywindow.window == *((Window*)win);
24
-}
25
-
26
-slop::GLSelectRectangle::~GLSelectRectangle() {
27
-    if ( m_window == None ) {
28
-        return;
29
-    }
30
-    xengine->freeCRTCS( m_monitors );
31
-    delete m_framebuffer;
32
-    // Try to erase the window before destroying it.
33
-    glClearColor( 0, 0, 0, 0 );
34
-    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
35
-    glXSwapBuffers( xengine->m_display, m_glxWindow );
36
-    // Sleep for 0.1 seconds in hope that the rectangle was erased.
37
-    usleep( 10000 );
38
-    XDestroyWindow( xengine->m_display, m_window );
39
-    XEvent event;
40
-    // Block until the window is actually completely removed.
41
-    XIfEvent( xengine->m_display, &event, &isDestroyNotify, (XPointer)&m_window );
42
-    // Sleep for 0.1 seconds in hope that the screen actually cleared the window.
43
-    usleep( 10000 );
44
-}
45
-
46
-void slop::GLSelectRectangle::constrainWithinMonitor( int* x, int* y, int* w, int* h ) {
47
-    m_offsetx = 0;
48
-    m_offsety = 0;
49
-    m_offsetw = 0;
50
-    m_offseth = 0;
51
-    for ( unsigned int i=0;i<m_monitors.size();i++ ) {
52
-        XRRCrtcInfo* monitor = m_monitors[ i ];
53
-        if ( !((int)xengine->m_mousex >= (int)monitor->x && (int)xengine->m_mousey >= (int)monitor->y &&
54
-               (int)xengine->m_mousex <= (int)(monitor->x+monitor->width) && (int)xengine->m_mousey <= (int)(monitor->y+monitor->height) ) ) {
55
-            continue;
56
-        }
57
-        if ( (int)*x < (int)monitor->x ) {
58
-            m_offsetx = monitor->x-*x;
59
-            *w += *x-monitor->x;
60
-            *x = monitor->x;
61
-        }
62
-        if ( (int)(*x+*w) >= (int)(monitor->x+monitor->width) ) {
63
-            m_offsetw = (monitor->width-1-(*x-monitor->x+*w));
64
-            *w = monitor->width-1-(*x-monitor->x);
65
-        }
66
-        if ( (int)*y < (int)monitor->y ) {
67
-            m_offsety = monitor->y-*y;
68
-            *h += *y-monitor->y;
69
-            *y = monitor->y;
70
-        }
71
-        if ( (int)(*y+*h) >= (int)(monitor->y+monitor->height) ) {
72
-            m_offseth = (monitor->height-1-(*y-monitor->y+*h));
73
-            *h = monitor->height-1-(*y-monitor->y);
74
-        }
75
-        break;
76
-    }
77
-    m_offsetx *= m_glassSize;
78
-    m_offsety *= m_glassSize;
79
-    m_offsetw *= m_glassSize;
80
-    m_offseth *= m_glassSize;
81
-}
82
-
83
-void slop::GLSelectRectangle::setShader( std::string shader ) {
84
-    m_shader = shader;
85
-    m_framebuffer->setShader( shader );
86
-}
87
-
88
-void slop::GLSelectRectangle::setMagnifySettings( bool on, float magstrength, unsigned int pixels ) {
89
-    m_glassSize = magstrength;
90
-    m_glassPixels = pixels;
91
-    m_glassEnabled = on;
92
-    m_glassx = xengine->m_mousex;
93
-    m_glassy = xengine->m_mousey;
94
-    m_realglassx = xengine->m_mousex;
95
-    m_realglassy = xengine->m_mousey;
96
-}
97
-
98
-void slop::GLSelectRectangle::pushOut( int* x, int* y, int w, int h, int rx, int ry, int rw, int rh ) {
99
-    // AABB to test for collision
100
-    if (!(
101
-          *x < rx + rw &&
102
-          *x + w > rx &&
103
-          *y < ry + rh &&
104
-          h + *y > ry
105
-       )) {
106
-        // No collision, so we do nothing.
107
-        return;
108
-    }
109
-    // Otherwise we find an optimal angle to push ourselves out at.
110
-    int centerx = rx+rw/2;
111
-    int centery = ry+rh/2;
112
-    float ang = -atan2( (float)(*y+(float)h/2.f)-(float)centery, (float)(*x+(float)w/2.f)-(float)centerx );
113
-    float pi = 3.1415926535897;
114
-    float upright = pi/2 - atan( (2.f*float(rx+rw)-2.f*(float)centerx)/(float)rh );
115
-    float upleft = pi/2 - atan( (2.f*(float)rx-2.f*(float)centerx)/(float)rh );
116
-    float downright = -upright;
117
-    float downleft = -upleft;
118
-    if ( ang >= upright && ang <= upleft ) {
119
-        *x = centerx + ((rh*cos(ang))/(2*sin(ang))) - w/2;
120
-        *y = centery - rh/2 - h;
121
-    } else if ( ang <= downright && ang >= downleft) {
122
-        *x = centerx - ((rh*cos(ang))/(2*sin(ang))) - w/2;
123
-        *y = centery + rh/2;
124
-    } else if ( ang < downleft || ang > upleft ) {
125
-        *x = centerx - rw/2 - w;
126
-        *y = centery + (rw*sin(ang))/(2*cos(ang)) - h/2;
127
-    } else {
128
-        *x = centerx + rw/2;
129
-        *y = centery - (rw*sin(ang))/(2*cos(ang)) - h/2;
130
-    }
131
-}
132
-
133
-void slop::GLSelectRectangle::pushIn( int* x, int* y, int w, int h, int rx, int ry, int rw, int rh ) {
134
-    if ( *x > rx && *y > ry &&
135
-         *x+w < rx+rw && *y+h < ry+rh ) {
136
-        // We're already fully contained...
137
-        return;
138
-    }
139
-    // Otherwise we find an optimal angle to push ourselves in at.
140
-    int centerx = rx+rw/2;
141
-    int centery = ry+rh/2;
142
-    float ang = -atan2( (float)(*y+(float)h/2.f)-(float)centery, (float)(*x+(float)w/2.f)-(float)centerx );
143
-    float pi = 3.1415926535897;
144
-    float upright = pi/2 - atan( (2.f*float(rx+rw)-2.f*(float)centerx)/(float)rh );
145
-    float upleft = pi/2 - atan( (2.f*(float)rx-2.f*(float)centerx)/(float)rh );
146
-    float downright = -upright;
147
-    float downleft = -upleft;
148
-    if ( ang >= upright && ang <= upleft ) {
149
-        *x = centerx + ((rh*cos(ang))/(2*sin(ang))) - w/2;
150
-        *y = centery - rh/2;
151
-    } else if ( ang <= downright && ang >= downleft) {
152
-        *x = centerx - ((rh*cos(ang))/(2*sin(ang))) - w/2;
153
-        *y = centery + rh/2 - h;
154
-    } else if ( ang < downleft || ang > upleft ) {
155
-        *x = centerx - rw/2;
156
-        *y = centery + (rw*sin(ang))/(2*cos(ang)) - h/2;
157
-    } else {
158
-        *x = centerx + rw/2 - w;
159
-        *y = centery - (rw*sin(ang))/(2*cos(ang)) - h/2;
160
-    }
161
-    if ( !(*x > rx && *y > ry &&
162
-         *x+w < rx+rw && *y+h < ry+rh) ) {
163
-        if ( *x+w > rx+rw ) {
164
-            *x -= w/2;
165
-        }
166
-        if ( *x < rx ) {
167
-            *x += w/2;
168
-        }
169
-        if ( *y+h > ry+rh ) {
170
-            *y -= h/2;
171
-        }
172
-        if ( *y < ry ) {
173
-            *y += h/2;
174
-        }
175
-    }
176
-}
177
-
178
-void slop::GLSelectRectangle::findOptimalGlassPosition() {
179
-    // Try to move the glass next to the mouse.
180
-    m_glassx = xengine->m_mousex+m_glassPixels/2+5-m_glassBorder;
181
-    m_glassy = xengine->m_mousey+m_glassPixels/2+5-m_glassBorder;
182
-    XRectangle view, selection, combined;
183
-    view.x = xengine->m_mousex-(m_glassPixels+1+m_glassBorder)/2;
184
-    view.y = xengine->m_mousey-(m_glassPixels+1+m_glassBorder)/2;
185
-    view.width = m_glassPixels+1;
186
-    view.height = m_glassPixels+1;
187
-    selection.x = m_x-m_border;
188
-    selection.y = m_y-m_border;
189
-    selection.width = m_width+m_border*2;
190
-    selection.height = m_height+m_border*2;
191
-    combined.x = std::min( selection.x, view.x );
192
-    combined.y = std::min( selection.y, view.y );
193
-    combined.width = selection.width + std::max( selection.x-view.x, (view.x+view.width)-(selection.x+selection.width) );
194
-    combined.height = selection.height + std::max( selection.y-view.y, (view.y+view.height)-(selection.y+selection.height) );
195
-    for ( unsigned int i=0;i<m_monitors.size();i++ ) {
196
-        XRRCrtcInfo* monitor = m_monitors[ i ];
197
-        // Push the glass inside the monitor the mouse is on.
198
-        if ( (int)xengine->m_mousex >= (int)monitor->x && (int)xengine->m_mousex <= (int)(monitor->x + monitor->width) &&
199
-             (int)xengine->m_mousey >= (int)monitor->y && (int)xengine->m_mousey <= (int)(monitor->y + monitor->height) ) {
200
-            pushIn( &m_glassx, &m_glassy, m_glassPixels*m_glassSize+m_glassBorder*2, m_glassPixels*m_glassSize+m_glassBorder*2, monitor->x, monitor->y, monitor->width, monitor->height );
201
-            break;
202
-        }
203
-    }
204
-    // Push the glass outside of the selection, but only if we are left clicking, and always keep it out of the "shot"
205
-    if ( xengine->getCursor() != slop::Left ) {
206
-        pushOut( &m_glassx, &m_glassy, m_glassPixels*m_glassSize+m_glassBorder*2, m_glassPixels*m_glassSize+m_glassBorder*2, combined.x, combined.y, combined.width, combined.height );
207
-    } else {
208
-        pushOut( &m_glassx, &m_glassy, m_glassPixels*m_glassSize+m_glassBorder*2, m_glassPixels*m_glassSize+m_glassBorder*2, view.x, view.y, view.width, view.height );
209
-    }
210
-    m_glassx += m_glassBorder;
211
-    m_glassy += m_glassBorder;
212
-}
213
-
214
-void slop::GLSelectRectangle::generateMagnifyingGlass() {
215
-    int x = xengine->m_mousex-m_glassPixels/2;
216
-    int y = xengine->m_mousey-m_glassPixels/2;
217
-    bool fx = xengine->m_mousex < m_x+m_width/2;
218
-    bool fy = xengine->m_mousey < m_y+m_height/2;
219
-    // Mouse behavior SUCKS
220
-    if ( !fx && !fy ) {
221
-        x += 1;
222
-        y += 1;
223
-    } else if ( fx && !fy ) {
224
-        y += 1;
225
-    } else if ( !fx && fy ) {
226
-        x += 1;
227
-    }
228
-    int w = m_glassPixels;
229
-    int h = m_glassPixels;
230
-    constrainWithinMonitor( &x, &y, &w, &h );
231
-    XImage* image = XGetImage( xengine->m_display, xengine->m_root, x, y, w, h, 0xffffffff, ZPixmap );
232
-    glEnable(GL_TEXTURE_2D);
233
-    glGenTextures(1, &m_texid);
234
-    glBindTexture(GL_TEXTURE_2D, m_texid);
235
-    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236
-    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
237
-    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
238
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(image->data[0])));
239
-    XDestroyImage( image );
240
-    glDisable(GL_TEXTURE_2D);
241
-}
242
-
243
-void slop::GLSelectRectangle::setTheme( bool on, std::string name ) {
244
-    if ( !on || name == "none" ) {
245
-        return;
246
-    }
247
-    std::string root = resource->getRealPath( name );
248
-    std::string tl = root + "/corner_tl.png";
249
-    std::string bl = root + "/corner_bl.png";
250
-    std::string tr = root + "/corner_tr.png";
251
-    std::string br = root + "/corner_br.png";
252
-    std::string straight = root + "/straight.png";
253
-    // One of the textures didn't exist, so we cancel the theme.
254
-    if (!resource->validatePath( tl ) ||
255
-        !resource->validatePath( bl ) ||
256
-        !resource->validatePath( tr ) ||
257
-        !resource->validatePath( br ) ||
258
-        !resource->validatePath( straight ) ) {
259
-        fprintf( stderr, "One of the textures was missing in the theme... disabling.\n" );
260
-        return;
261
-    }
262
-    // Otherwise we load each one :)
263
-    loadImage( &(m_cornerids[0]), tl );
264
-    loadImage( &(m_cornerids[1]), tr );
265
-    loadImage( &(m_cornerids[2]), bl );
266
-    loadImage( &(m_cornerids[3]), br );
267
-    loadImage( &(m_straightid), straight );
268
-    glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &m_straightwidth );
269
-    glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &m_straightheight );
270
-    m_themed = on;
271
-}
272
-
273
-unsigned int slop::GLSelectRectangle::loadImage( unsigned int* texture, std::string path ) {
274
-    glActiveTexture(GL_TEXTURE0);
275
-    glEnable(GL_TEXTURE_2D);
276
-    glGenTextures( 1, texture );
277
-    glBindTexture( GL_TEXTURE_2D, *texture );
278
-    Imlib_Load_Error err;
279
-    Imlib_Image image = imlib_load_image_with_error_return( path.c_str(), &err );
280
-    if ( err != IMLIB_LOAD_ERROR_NONE ) {
281
-        std::string message = "Failed to load image: ";
282
-        message += path;
283
-        message += "\n\t";
284
-        switch( err ) {
285
-            default: {
286
-                message += "unknown error ";
287
-                message += (int)err;
288
-                message += "\n";
289
-                break;
290
-            }
291
-            case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS:
292
-                message += "out of file descriptors\n";
293
-                break;
294
-            case IMLIB_LOAD_ERROR_OUT_OF_MEMORY:
295
-                message += "out of memory\n";
296
-                break;
297
-            case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS:
298
-                message += "path contains too many symbolic links\n";
299
-                break;
300
-            case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE:
301
-                message += "path points outside address space\n";
302
-                break;
303
-            case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY:
304
-                message += "path component is not a directory\n";
305
-                break;
306
-            case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT:
307
-                message += "path component is non-existant (~ isn't expanded inside quotes!)\n";
308
-                break;
309
-            case IMLIB_LOAD_ERROR_PATH_TOO_LONG:
310
-                message += "path is too long\n";
311
-                break;
312
-            case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT:
313
-                message += "no loader for file format (unsupported format)\n";
314
-                break;
315
-            case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE: {
316
-                message += "not enough disk space\n";
317
-                break;
318
-            }
319
-            case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST: {
320
-                message += "file does not exist\n";
321
-                break;
322
-            }
323
-            case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY: {
324
-                message += "file is a directory\n";
325
-                break;
326
-            }
327
-            case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE:
328
-            case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ: {
329
-                message += "permission denied\n";
330
-                break;
331
-            }
332
-        }
333
-        throw std::runtime_error( message.c_str() );
334
-        return *texture;
335
-    }
336
-    imlib_context_set_image( image );
337
-    DATA32* data = imlib_image_get_data_for_reading_only();
338
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, imlib_image_get_width(), imlib_image_get_height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)data );
339
-    if ( GLEW_VERSION_3_0 ) {
340
-        glHint( GL_GENERATE_MIPMAP_HINT, GL_NICEST );
341
-        glGenerateMipmap( GL_TEXTURE_2D );
342
-        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
343
-        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
344
-    } else {
345
-        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
346
-        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
347
-    }
348
-    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
349
-    imlib_free_image();
350
-    glDisable(GL_TEXTURE_2D);
351
-    return *texture;
352
-}
353
-
354
-
355
-
356
-slop::GLSelectRectangle::GLSelectRectangle( int sx, int sy, int ex, int ey, int border, bool highlight, float r, float g, float b, float a ) {
357
-    m_x = std::min( sx, ex );
358
-    m_y = std::min( sy, ey );
359
-    m_width = std::max( sx, ex ) - m_x;
360
-    m_height = std::max( sy, ey ) - m_y;
361
-    m_r = r;
362
-    m_g = g;
363
-    m_b = b;
364
-    m_a = a;
365
-    m_border = border;
366
-    m_window = None;
367
-    m_highlight = highlight;
368
-    m_glassPixels = 64;
369
-    m_glassx = xengine->m_mousex;
370
-    m_glassy = xengine->m_mousey;
371
-    m_realglassx = xengine->m_mousex;
372
-    m_realglassy = xengine->m_mousey;
373
-    m_glassSize = 4;
374
-    m_glassBorder = 1;
375
-    m_monitors = xengine->getCRTCS();
376
-    m_themed = false;
377
-    m_shader = "simple";
378
-    m_time = 0;
379
-
380
-    // If we don't have a border, we don't exist, so just die.
381
-    if ( m_border == 0 ) {
382
-        return;
383
-    }
384
-
385
-    if ( m_highlight ) {
386
-        m_border = 0;
387
-    }
388
-
389
-    static int visdata[] = {
390
-        GLX_RENDER_TYPE, GLX_RGBA_BIT,
391
-        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
392
-        GLX_DOUBLEBUFFER, True,
393
-        GLX_RED_SIZE, 8,
394
-        GLX_GREEN_SIZE, 8,
395
-        GLX_BLUE_SIZE, 8,
396
-        GLX_ALPHA_SIZE, 8,
397
-        GLX_DEPTH_SIZE, 16,
398
-        None
399
-    };
400
-
401
-    int numfbconfigs = 0;
402
-    GLXFBConfig* fbconfigs = glXChooseFBConfig( xengine->m_display,  DefaultScreen( xengine->m_display ), visdata, &numfbconfigs );
403
-    m_fbconfig = 0;
404
-    for ( int i=0; i<numfbconfigs; i++ ) {
405
-        m_visual = (XVisualInfo*)glXGetVisualFromFBConfig( xengine->m_display, fbconfigs[i] );
406
-        if ( !m_visual ) {
407
-            continue;
408
-        }
409
-        m_pictFormat = XRenderFindVisualFormat( xengine->m_display, m_visual->visual );
410
-        if ( !m_pictFormat ) {
411
-            continue;
412
-        }
413
-        m_fbconfig = fbconfigs[i];
414
-        if ( m_pictFormat->direct.alphaMask > 0 ) {
415
-            break;
416
-        }
417
-    }
418
-
419
-    if ( !m_fbconfig ) {
420
-        fprintf( stderr, "Couldn't find a matching FB config for a transparent OpenGL window!\n");
421
-    }
422
-
423
-    m_cmap = XCreateColormap( xengine->m_display, xengine->m_root, m_visual->visual, AllocNone );
424
-
425
-    XSetWindowAttributes attributes;
426
-    attributes.colormap = m_cmap;
427
-    attributes.background_pixmap = None;
428
-    attributes.border_pixmap = None;
429
-    attributes.border_pixel = 0;
430
-    // Disable window decorations.
431
-    attributes.override_redirect = True;
432
-    // Make sure we know when we've been successfully destroyed later!
433
-    attributes.event_mask = StructureNotifyMask;
434
-    unsigned long valueMask = CWOverrideRedirect | CWEventMask | CWBackPixmap | CWColormap | CWBorderPixel;
435
-
436
-
437
-    // Create the window
438
-    m_window = XCreateWindow( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(),
439
-                              0, m_visual->depth, InputOutput,
440
-                              m_visual->visual, valueMask, &attributes );
441
-
442
-    if ( !m_window ) {
443
-        fprintf( stderr, "Couldn't create a GL window!\n");
444
-    }
445
-
446
-    m_glxWindow = m_window;
447
-
448
-    static char title[] = "OpenGL Slop";
449
-    XWMHints* startup_state = XAllocWMHints();
450
-    startup_state->initial_state = NormalState;
451
-    startup_state->flags = StateHint;
452
-    XTextProperty textprop;
453
-    textprop.value = (unsigned char*)title;
454
-    textprop.encoding = XA_STRING;
455
-    textprop.format = 8;
456
-    textprop.nitems = strlen( title );
457
-    XSizeHints sizehints;
458
-    sizehints.x = 0;
459
-    sizehints.y = 0;
460
-    sizehints.width = xengine->getWidth();
461
-    sizehints.height = xengine->getHeight();
462
-    sizehints.flags = USPosition | USSize;
463
-    XClassHint classhints;
464
-    char name[] = "slop";
465
-    classhints.res_name = name;
466
-    classhints.res_class = name;
467
-    XSetClassHint( xengine->m_display, m_window, &classhints );
468
-    XSetWMProperties( xengine->m_display, m_window, &textprop, &textprop, NULL, 0, &sizehints, startup_state, NULL );
469
-    XFree( startup_state );
470
-
471
-    // Make it so all input falls through
472
-    XRectangle rect;
473
-    rect.x = rect.y = rect.width = rect.height = 0;
474
-    XShapeCombineRectangles( xengine->m_display, m_window, ShapeInput, 0, 0, &rect, 1, ShapeSet, 0);
475
-
476
-    XMapWindow( xengine->m_display, m_window );
477
-
478
-    int dummy;
479
-    if ( !glXQueryExtension( xengine->m_display, &dummy, &dummy ) ) {
480
-        fprintf( stderr, "OpenGL is not supported!\n" );
481
-    }
482
-    m_renderContext = glXCreateNewContext( xengine->m_display, m_fbconfig, GLX_RGBA_TYPE, 0, True );
483
-    if ( !m_renderContext ) {
484
-        fprintf( stderr, "Failed to create a GL context.\n" );
485
-    }
486
-    if ( !glXMakeContextCurrent( xengine->m_display, m_glxWindow, m_glxWindow, m_renderContext ) ) {
487
-        fprintf( stderr, "Failed to attach GL context to window!\n" );
488
-    }
489
-    GLenum err = glewInit();
490
-    if ( GLEW_OK != err ) {
491
-        /* Problem: glewInit failed, something is seriously wrong. */
492
-        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
493
-    }
494
-
495
-    // Get an image of the entire desktop for use in shaders.
496
-    XImage* image = XGetImage( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(), 0xffffffff, ZPixmap );
497
-    glEnable(GL_TEXTURE_2D);
498
-    glGenTextures(1, &m_desktop);
499
-    glBindTexture(GL_TEXTURE_2D, m_desktop);
500
-    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
501
-    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
502
-    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
503
-    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, xengine->getWidth(), xengine->getHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(image->data[0])));
504
-    XDestroyImage( image );
505
-
506
-    glDisable(GL_TEXTURE_2D);
507
-    m_framebuffer = new slop::Framebuffer( xengine->getWidth(), xengine->getHeight(), slop::Framebuffer::color, m_shader );
508
-    m_framebuffer->bind();
509
-    glEnable( GL_BLEND );
510
-    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
511
-    glClearColor( 0, 0, 0, 0 );
512
-    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
513
-    glXSwapBuffers( xengine->m_display, m_glxWindow );
514
-    m_framebuffer->unbind();
515
-}
516
-
517
-void slop::GLSelectRectangle::setGeo( int sx, int sy, int ex, int ey ) {
518
-    int x = std::min( sx, ex );
519
-    int y = std::min( sy, ey );
520
-    int w = std::max( sx, ex ) - x;
521
-    int h = std::max( sy, ey ) - y;
522
-
523
-    m_x = x;
524
-    m_y = y;
525
-    m_width = w;
526
-    m_height = h;
527
-}
528
-
529
-void slop::GLSelectRectangle::update( double dt ) {
530
-    m_time += dt;
531
-    m_framebuffer->bind();
532
-    glViewport( 0, 0, xengine->getWidth(), xengine->getHeight() );
533
-
534
-    glClearColor( 0, 0, 0, 0 );
535
-    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
536
-
537
-    glMatrixMode( GL_PROJECTION );
538
-    glLoadIdentity();
539
-    glOrtho( 0, xengine->getWidth(), xengine->getHeight(), 0, 1, -1 );
540
-
541
-    glMatrixMode( GL_MODELVIEW );
542
-    glLoadIdentity();
543
-
544
-    if ( !m_themed ) {
545
-        glColor4f( m_r, m_g, m_b, m_a );
546
-        if ( m_highlight ) {
547
-            glRecti( m_x-m_border, m_y+m_height+m_border, m_x+m_width+m_border, m_y-m_border );
548
-        } else {
549
-            glRecti( m_x-m_border, m_y, m_x+m_width+m_border, m_y-m_border );
550
-            glRecti( m_x-m_border, m_y+m_height, m_x+m_width+m_border, m_y+m_height+m_border );
551
-            glRecti( m_x-m_border, m_y, m_x, m_y+m_height );
552
-            glRecti( m_x+m_width, m_y, m_x+m_width+m_border, m_y+m_height );
553
-        }
554
-    } else {
555
-        glColor4f( m_r, m_g, m_b, m_a );
556
-        glEnable( GL_TEXTURE_2D );
557
-        if ( !m_highlight ) {
558
-            glBindTexture( GL_TEXTURE_2D, m_straightid );
559
-            float something = (float)(m_border)/(float)m_straightheight;
560
-            float txoffset = (((float)m_width+m_border)/(float)m_straightwidth)/something;
561
-            float tyoffset = (((float)m_height+m_border)/(float)m_straightwidth)/something;
562
-            //float ratio = ((float)m_straightwidth/(float)m_straightheight);
563
-            glBegin( GL_QUADS );
564
-            // straight top
565
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x-m_border/2, m_y-m_border );
566
-            glTexCoord2f(txoffset, 0.0); glVertex2f( m_x+m_width+m_border/2, m_y-m_border );
567
-            glTexCoord2f(txoffset, 1.0); glVertex2f( m_x+m_width+m_border/2, m_y );
568
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x-m_border/2, m_y );
569
-            // straight bot
570
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x-m_border/2, m_y+m_height );
571
-            glTexCoord2f(txoffset, 0.0); glVertex2f( m_x+m_width+m_border/2, m_y+m_height );
572
-            glTexCoord2f(txoffset, 1.0); glVertex2f( m_x+m_width+m_border/2, m_y+m_height+m_border );
573
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x-m_border/2, m_y+m_height+m_border );
574
-            // straight left
575
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x-m_border, m_y-m_border/2 );
576
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x, m_y-m_border/2 );
577
-            glTexCoord2f(tyoffset, 0.0); glVertex2f( m_x, m_y+m_height+m_border/2 );
578
-            glTexCoord2f(tyoffset, 1.0); glVertex2f( m_x-m_border, m_y+m_height+m_border/2 );
579
-            // straight right
580
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x+m_width, m_y-m_border/2 );
581
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x+m_width+m_border, m_y-m_border/2 );
582
-            glTexCoord2f(tyoffset, 0.0); glVertex2f( m_x+m_width+m_border, m_y+m_height+m_border/2 );
583
-            glTexCoord2f(tyoffset, 1.0); glVertex2f( m_x+m_width, m_y+m_height+m_border/2 );
584
-            glEnd();
585
-            // top left corner
586
-            glBindTexture( GL_TEXTURE_2D, m_cornerids[0] );
587
-            glBegin( GL_QUADS );
588
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x-m_border, m_y-m_border );
589
-            glTexCoord2f(1.0, 0.0); glVertex2f( m_x, m_y-m_border );
590
-            glTexCoord2f(1.0, 1.0); glVertex2f( m_x, m_y );
591
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x-m_border, m_y );
592
-            glEnd();
593
-            // top right
594
-            glBindTexture( GL_TEXTURE_2D, m_cornerids[1] );
595
-            glBegin( GL_QUADS );
596
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x+m_width, m_y-m_border );
597
-            glTexCoord2f(1.0, 0.0); glVertex2f( m_x+m_width+m_border, m_y-m_border );
598
-            glTexCoord2f(1.0, 1.0); glVertex2f( m_x+m_width+m_border, m_y );
599
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x+m_width, m_y );
600
-            glEnd();
601
-            // bottom left
602
-            glBindTexture( GL_TEXTURE_2D, m_cornerids[2] );
603
-            glBegin( GL_QUADS );
604
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x-m_border, m_y+m_height );
605
-            glTexCoord2f(1.0, 0.0); glVertex2f( m_x, m_y+m_height );
606
-            glTexCoord2f(1.0, 1.0); glVertex2f( m_x, m_y+m_height+m_border );
607
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x-m_border, m_y+m_height+m_border );
608
-            glEnd();
609
-            // bottom right
610
-            glBindTexture( GL_TEXTURE_2D, m_cornerids[2] );
611
-            glBegin( GL_QUADS );
612
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x+m_width, m_y+m_height );
613
-            glTexCoord2f(1.0, 0.0); glVertex2f( m_x+m_width+m_border, m_y+m_height );
614
-            glTexCoord2f(1.0, 1.0); glVertex2f( m_x+m_width+m_border, m_y+m_height+m_border );
615
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x+m_width, m_y+m_height+m_border );
616
-            glEnd();
617
-        } else {
618
-            glBindTexture( GL_TEXTURE_2D, m_cornerids[0] );
619
-            glBegin( GL_QUADS );
620
-            // straight top
621
-            glTexCoord2f(0.0, 1.0); glVertex2f( m_x-m_border, m_y+m_border+m_height );
622
-            glTexCoord2f(1.0, 1.0); glVertex2f( m_x+m_width+m_border, m_y+m_border+m_height );
623
-            glTexCoord2f(1.0, 0.0); glVertex2f( m_x+m_width+m_border, m_y-m_border );
624
-            glTexCoord2f(0.0, 0.0); glVertex2f( m_x-m_border, m_y-m_border );
625
-            glEnd();
626
-        }
627
-        glDisable( GL_TEXTURE_2D );
628
-    }
629
-
630
-    m_framebuffer->unbind();
631
-
632
-    glClearColor( 0, 0, 0, 0 );
633
-    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
634
-
635
-    m_framebuffer->draw( (float) m_time, m_desktop );
636
-
637
-    if ( m_glassEnabled ) {
638
-        generateMagnifyingGlass();
639
-        findOptimalGlassPosition();
640
-
641
-        // Takes .1 second to reach the real position. Used for easing.
642
-        m_realglassx -= float(m_realglassx - (float)m_glassx) * dt * 10;
643
-        m_realglassy -= float(m_realglassy - (float)m_glassy) * dt * 10;
644
-
645
-        // Black outline...
646
-
647
-        glColor4f( 0, 0, 0, 1 );
648
-        glBegin( GL_QUADS );
649
-        glTexCoord2f(0.0, 1.0); glVertex3f( m_realglassx+m_offsetx-m_glassBorder,                               m_realglassy+(m_glassSize*m_glassPixels)+m_offseth+m_glassBorder, 0.0);
650
-        glTexCoord2f(1.0, 1.0); glVertex3f( m_realglassx+(m_glassSize*m_glassPixels)+m_offsetw+m_glassBorder,   m_realglassy+(m_glassSize*m_glassPixels)+m_offseth+1, 0.0);
651
-        glTexCoord2f(1.0, 0.0); glVertex3f( m_realglassx+(m_glassSize*m_glassPixels)+m_offsetw+m_glassBorder,   m_realglassy+m_offsety-m_glassBorder, 0.0);
652
-        glTexCoord2f(0.0, 0.0); glVertex3f( m_realglassx+m_offsetx-m_glassBorder,                               m_realglassy+m_offsety-m_glassBorder, 0.0);
653
-        glEnd();
654
-
655
-        glEnable( GL_TEXTURE_2D );
656
-        glBindTexture( GL_TEXTURE_2D, m_texid );
657
-        glColor4f( 1, 1, 1, 1 );
658
-        glBegin( GL_QUADS );
659
-        glTexCoord2f(0.0, 1.0); glVertex3f( m_realglassx+m_offsetx,                             m_realglassy+(m_glassSize*m_glassPixels)+m_offseth, 0.0);
660
-        glTexCoord2f(1.0, 1.0); glVertex3f( m_realglassx+(m_glassSize*m_glassPixels)+m_offsetw, m_realglassy+(m_glassSize*m_glassPixels)+m_offseth, 0.0);
661
-        glTexCoord2f(1.0, 0.0); glVertex3f( m_realglassx+(m_glassSize*m_glassPixels)+m_offsetw, m_realglassy+m_offsety, 0.0);
662
-        glTexCoord2f(0.0, 0.0); glVertex3f( m_realglassx+m_offsetx,                             m_realglassy+m_offsety, 0.0);
663
-        glEnd();
664
-        glDisable( GL_TEXTURE_2D );
665
-
666
-        glLogicOp(GL_INVERT);
667
-        glEnable(GL_COLOR_LOGIC_OP);
668
-        glLineWidth( 2 );
669
-        glColor4f( 0, 0, 0, 1 );
670
-        glBegin( GL_LINES );
671
-        float cx = m_realglassx+(m_glassSize*m_glassPixels)/2;
672
-        float cy = m_realglassy+(m_glassSize*m_glassPixels)/2;
673
-        glVertex3f( cx-5, cy, 0 );
674
-        glVertex3f( cx+5, cy, 0 );
675
-        glVertex3f( cx, cy-5, 0 );
676
-        glVertex3f( cx, cy+5, 0 );
677
-        glEnd();
678
-        glLogicOp(GL_NOOP);
679
-        glDisable(GL_COLOR_LOGIC_OP);
680
-    }
681
-
682
-    glXSwapBuffers( xengine->m_display, m_glxWindow );
683
-}

+ 0
- 102
src/glselectrectangle.hpp Просмотреть файл

@@ -1,102 +0,0 @@
1
-/* glselectrectangle.hpp: Handles creating hardware accelerated rectangles on the screen using X11 and OpenGL.
2
- *
3
- * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
- *
5
- * This file is part of Slop.
6
- *
7
- * Slop is free software: you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, either version 3 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * Slop is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-
21
-#ifndef IS_GL_SELECT_RECTANGLE_H_
22
-#define IS_GL_SELECT_RECTANGLE_H_
23
-
24
-#include "x.hpp"
25
-#include "selectrectangle.hpp"
26
-#include "resource.hpp"
27
-#include "framebuffer.hpp"
28
-
29
-#include <unistd.h>
30
-
31
-#include <Imlib2.h>
32
-#include <GL/gl.h>
33
-#include <GL/glx.h>
34
-#include <GL/glew.h>
35
-#include <GL/glxext.h>
36
-#include <X11/Xlib.h>
37
-#include <X11/Xatom.h>
38
-#include <X11/extensions/Xrender.h>
39
-#include <X11/Xutil.h>
40
-
41
-#include <cstdlib>
42
-#include <cmath>
43
-#include <cstdio>
44
-#include <string>
45
-#include <vector>
46
-
47
-namespace slop {
48
-
49
-class GLSelectRectangle: public SelectRectangle {
50
-public:
51
-                        GLSelectRectangle( int sx, int sy, int ex, int ey, int border, bool highlight, float r, float g, float b, float a );
52
-                        ~GLSelectRectangle();
53
-    void                setGeo( int x, int y, int w, int h );
54
-    void                update( double dt );
55
-    void                generateMagnifyingGlass();
56
-    void                setMagnifySettings( bool on, float magstrength, unsigned int pixels );
57
-    void                pushIn( int* x, int* y, int w, int h, int rx, int ry, int rw, int rh );
58
-    void                pushOut( int* x, int* y, int w, int h, int rx, int ry, int rw, int rh );
59
-    void                findOptimalGlassPosition();
60
-    void                constrainWithinMonitor( int* x, int* y, int* w, int* h );
61
-    void                setTheme( bool on, std::string name );
62
-    void                setShader( std::string name );
63
-    float               m_r;
64
-    float               m_g;
65
-    float               m_b;
66
-    float               m_a;
67
-    GLXFBConfig         m_fbconfig;
68
-    XVisualInfo*        m_visual;
69
-    XRenderPictFormat*  m_pictFormat;
70
-    GLXContext          m_renderContext;
71
-    GLXWindow           m_glxWindow;
72
-    Colormap            m_cmap;
73
-    bool                m_themed;
74
-    unsigned int        m_texid;
75
-    unsigned int        m_cornerids[4];
76
-    unsigned int        m_straightid;
77
-    int                 m_straightwidth;
78
-    int                 m_straightheight;
79
-    int                 m_offsetx;
80
-    int                 m_offsety;
81
-    int                 m_offsetw;
82
-    int                 m_offseth;
83
-    unsigned int        m_desktop;
84
-    unsigned int        m_glassPixels;
85
-    float               m_glassSize;
86
-    int                 m_glassBorder;
87
-    float               m_realglassx;
88
-    float               m_realglassy;
89
-    int                 m_glassx;
90
-    int                 m_glassy;
91
-    bool                m_glassEnabled;
92
-    double              m_time;
93
-    std::string         m_shader;
94
-    std::vector<XRRCrtcInfo*> m_monitors;
95
-    slop::Framebuffer*  m_framebuffer;
96
-private:
97
-    unsigned int loadImage( unsigned int* texture, std::string path );
98
-};
99
-
100
-}
101
-
102
-#endif // IS_GL_SELECT_RECTANGLE_H_

+ 53
- 0
src/keyboard.cpp Просмотреть файл

@@ -0,0 +1,53 @@
1
+#include "keyboard.hpp"
2
+
3
+bool slop::Keyboard::getKey( KeySym key ) {
4
+    KeyCode keycode = XKeysymToKeycode( x11->display, key );
5
+    if ( keycode != 0 ) {
6
+        // Get the whole keyboard state
7
+        char keys[32];
8
+        XQueryKeymap( x11->display, keys );
9
+        // Check our keycode
10
+        return ( keys[ keycode / 8 ] & ( 1 << ( keycode % 8 ) ) ) != 0;
11
+    } else {
12
+        return false;
13
+    }
14
+}
15
+
16
+bool slop::Keyboard::anyKeyDown() {
17
+    return keyDown;
18
+}
19
+
20
+void slop::Keyboard::update() {
21
+    char keys[32];
22
+    XQueryKeymap( x11->display, keys );
23
+    keyDown = false;
24
+    for ( int i=0;i<32;i++ ) {
25
+        if ( deltaState[i] == keys[i] ) {
26
+            continue;
27
+        }
28
+        // Found a key in a group of 4 that's different
29
+        char a = deltaState[i];
30
+        char b = keys[i];
31
+        // Find the "different" bits
32
+        char c = a^b;
33
+        // A new key was pressed since the last update.
34
+        if ( c && b&c ) {
35
+            keyDown = true;
36
+        }
37
+        deltaState[i] = keys[i];
38
+    }
39
+}
40
+
41
+slop::Keyboard::Keyboard( X11* x11 ) {
42
+    this->x11 = x11;
43
+    int err = XGrabKeyboard( x11->display, x11->root, False, GrabModeAsync, GrabModeAsync, CurrentTime );
44
+    if ( err != GrabSuccess ) {
45
+        throw new std::runtime_error( "Failed to grab keyboard.\n" );
46
+    }
47
+    XQueryKeymap( x11->display, deltaState );
48
+    keyDown = false;
49
+}
50
+
51
+slop::Keyboard::~Keyboard() {
52
+    XUngrabKeyboard( x11->display, CurrentTime );
53
+}

src/selectrectangle.cpp → src/keyboard.hpp Просмотреть файл

@@ -1,4 +1,4 @@
1
-/* selectrectangle.cpp: Handles creating rectangles on the screen.
1
+/* keyboard.hpp: Interfaces with x11 to grab key press information.
2 2
  *
3 3
  * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4 4
  *
@@ -17,20 +17,29 @@
17 17
  * You should have received a copy of the GNU General Public License
18 18
  * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19 19
  */
20
-#include "selectrectangle.hpp"
21 20
 
22
-bool slop::isSelectRectangleSupported() {
23
-    int event_base;
24
-    int error_base;
25
-    return XShapeQueryExtension( xengine->m_display, &event_base, &error_base );
26
-}
21
+#ifndef N_KEYBOARD_H_
22
+#define N_KEYBOARD_H_
27 23
 
28
-slop::SelectRectangle::~SelectRectangle() {
29
-}
24
+#include "x.hpp"
30 25
 
31
-void slop::SelectRectangle::update( double dt ) {
32
-}
26
+namespace slop {
27
+
28
+class Keyboard {
29
+private:
30
+    char deltaState[32];
31
+    X11* x11;
32
+    bool keyDown;
33
+public:
34
+    Keyboard( X11* x11 );
35
+    ~Keyboard();
36
+    void update();
37
+    bool getKey( KeySym key );
38
+    bool anyKeyDown();
39
+};
40
+
41
+extern Keyboard* keyboard;
33 42
 
34
-void slop::SelectRectangle::setGeo( int sx, int sy, int ex, int ey ) {
35
-    fprintf( stderr, "Tried to use a class function that's meant to be overridden!\n");
36 43
 }
44
+
45
+#endif // N_KEYBOARD_H_

+ 169
- 529
src/main.cpp Просмотреть файл

@@ -1,4 +1,4 @@
1
-/* main.cpp
1
+/* main.cpp: parses options, runs slop, prints results.
2 2
  *
3 3
  * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4 4
  *
@@ -17,554 +17,194 @@
17 17
  * You should have received a copy of the GNU General Public License
18 18
  * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19 19
  */
20
-#include <unistd.h>
21
-#include <time.h>
22
-#include <cstdio>
23
-#include <sstream>
24
-#include <stdexcept>
25
-
26
-#ifdef __MACH__
27
-#include <mach/clock.h>
28
-#include <mach/mach.h>
29
-#endif
30 20
 
31
-#include "x.hpp"
32
-#include "selectrectangle.hpp"
33
-#ifdef OPENGL_ENABLED
34
-#include "glselectrectangle.hpp"
35
-#endif //OPENGL_ENABLED
36
-#include "xselectrectangle.hpp"
37
-#include "cmdline.h"
21
+#include <iostream>
22
+#include <sstream>
23
+#include "slop.hpp"
24
+#include "options.hpp"
38 25
 
39
-// Work around lack of clock_gettime in OSX
40
-// https://gist.github.com/jbenet/1087739
41
-void current_utc_time(struct timespec *ts) {
42
-    #ifdef __MACH__
43
-        // OS X does not have clock_gettime, use clock_get_time
44
-        clock_serv_t cclock;
45
-        mach_timespec_t mts;
46
-        host_get_clock_service( mach_host_self(), CALENDAR_CLOCK, &cclock );
47
-        clock_get_time( cclock, &mts );
48
-        mach_port_deallocate( mach_task_self(), cclock );
49
-        ts->tv_sec = mts.tv_sec;
50
-        ts->tv_nsec = mts.tv_nsec;
51
-    #else
52
-        clock_gettime( CLOCK_REALTIME, ts );
53
-    #endif
54
-}
26
+using namespace slop;
55 27
 
56
-int printSelection( std::string format, bool cancelled, int x, int y, int w, int h, int window ) {
57
-    size_t pos = 0;
58
-    while ( ( pos = format.find( "%", pos ) ) != std::string::npos ) {
59
-        if ( pos + 1 > format.size() ) {
60
-            fprintf( stderr, "Format error: %% found at the end of format string.\n" );
61
-            return EXIT_FAILURE;
62
-        }
63
-        std::stringstream foo;
64
-        switch( format[ pos + 1 ] ) {
65
-            case '%':
66
-                format.replace( pos, 2, "%" );
67
-                pos += 1;
68
-                break;
69
-            case 'x':
70
-            case 'X':
71
-                foo << x;
72
-                format.replace( pos, 2, foo.str() );
73
-                break;
74
-            case 'y':
75
-            case 'Y':
76
-                foo << y;
77
-                format.replace( pos, 2, foo.str() );
78
-                break;
79
-            case 'w':
80
-            case 'W':
81
-                foo << w;
82
-                format.replace( pos, 2, foo.str() );
83
-                break;
84
-            case 'h':
85
-            case 'H':
86
-                foo << h;
87
-                format.replace( pos, 2, foo.str() );
88
-                break;
89
-            case 'g':
90
-            case 'G':
91
-                foo << w << 'x' << h << '+' << x << '+' << y;
92
-                format.replace( pos, 2, foo.str() );
93
-                break;
94
-            case 'i':
95
-            case 'I':
96
-                foo << window;
97
-                format.replace( pos, 2, foo.str() );
98
-                break;
99
-            case 'c':
100
-            case 'C':
101
-                format.replace( pos, 2, cancelled ? "true" : "false" );
102
-                break;
103
-            default:
104
-                fprintf( stderr, "Format error: %%%c is an unknown replacement identifier.\n", format[ pos + 1 ] );
105
-                fprintf( stderr, "Valid replacements: %%x, %%y, %%w, %%h, %%i, %%c, %%.\n" );
106
-                return EXIT_FAILURE;
107
-                break;
108
-        }
109
-    }
110
-    pos = 0;
111
-    while ( ( pos = format.find( "\\", pos ) ) != std::string::npos ) {
112
-        if ( pos + 1 > format.size() ) {
113
-            break;
114
-        }
115
-        if ( format[ pos + 1 ] == 'n' ) {
116
-            format.replace( pos, 2, "\n" );
117
-        }
118
-        pos = pos + 1;
119
-    }
120
-    printf( "%s", format.c_str() );
121
-    return EXIT_SUCCESS;
28
+SlopOptions* getOptions( Options& options ) {
29
+    SlopOptions* foo = new SlopOptions();
30
+    options.getFloat("bordersize", 'b', foo->borderSize);
31
+    options.getFloat("padding", 'p', foo->padding);
32
+    options.getFloat("tolerance", 't', foo->tolerance);
33
+    glm::vec4 color = glm::vec4( foo->r, foo->g, foo->b, foo->a );
34
+    options.getColor("color", 'c', color);
35
+    options.getBool("nokeyboard", 'k', foo->nokeyboard);
36
+    options.getString( "xdisplay", 'x', foo->xdisplay );
37
+    options.getString( "shader", 's', foo->shader );
38
+    foo->r = color.r;
39
+    foo->g = color.g;
40
+    foo->b = color.b;
41
+    foo->a = color.a;
42
+    options.getBool("highlight", 'l', foo->highlight);
43
+    options.getInt("nodecorations", 'n', foo->nodecorations);
44
+    return foo;
122 45
 }
123 46
 
124
-int parseColor( std::string arg, float* r, float* g, float* b, float* a ) {
125
-    std::string copy = arg;
126
-    int find = copy.find( "," );
127
-    while( find != (int)copy.npos ) {
128
-        copy.at( find ) = ' ';
129
-        find = copy.find( "," );
130
-    }
131
-
132
-    // Just in case we didn't include an alpha value
133
-    *a = 1;
134
-    int num = sscanf( copy.c_str(), "%f %f %f %f", r, g, b, a );
135
-    if ( num != 3 && num != 4 ) {
136
-        return EXIT_FAILURE;
137
-    }
138
-    return EXIT_SUCCESS;
139
-}
140
-
141
-void constrain( int sx, int sy, int ex, int ey, int padding, int minimumsize, int maximumsize, int* rsx, int* rsy, int* rex, int* rey ) {
142
-    if ( minimumsize > maximumsize && maximumsize > 0 ) {
143
-        fprintf( stderr, "Error: minimumsize is greater than maximumsize.\n" );
144
-        exit( 1 );
145
-    }
146
-    int x = std::min( sx, ex );
147
-    int y = std::min( sy, ey );
148
-    // We add one to make sure we select the pixel under the mouse.
149
-    int w = std::max( sx, ex ) - x + 1;
150
-    int h = std::max( sy, ey ) - y + 1;
151
-    // Make sure we don't turn inside out...
152
-    if ( w + padding*2 >= 0 ) {
153
-        x -= padding;
154
-        w += padding*2;
155
-    }
156
-    if ( h + padding*2 >= 0 ) {
157
-        y -= padding;
158
-        h += padding*2;
159
-    }
160
-    if ( w < minimumsize ) {
161
-        int diff = minimumsize - w;
162
-        w = minimumsize;
163
-        x -= diff/2;
164
-    }
165
-    if ( h < minimumsize ) {
166
-        int diff = minimumsize - h;
167
-        h = minimumsize;
168
-        y -= diff/2;
169
-    }
170
-    if ( maximumsize > 0 ) {
171
-        if ( w > maximumsize ) {
172
-            int diff = w;
173
-            w = maximumsize;
174
-            x += diff/2 - maximumsize/2;
175
-        }
176
-        if ( h > maximumsize ) {
177
-            int diff = h;
178
-            h = maximumsize;
179
-            y += diff/2 - maximumsize/2;
47
+std::string formatOutput( std::string input, SlopSelection selection, bool cancelled ) {
48
+    std::stringstream output;
49
+    for( unsigned int i=0;i<input.length();i++) {
50
+        if ( input[i] == '%' ) {
51
+            if ( input.length() <= i+1 ) {
52
+                throw new std::invalid_argument( "Expected character after `%`, got END." );
53
+            }
54
+            switch( input[i+1] ) {
55
+                case 'x':
56
+                case 'X': output << round(selection.x); break;
57
+                case 'y':
58
+                case 'Y': output << round(selection.y); break;
59
+                case 'w':
60
+                case 'W': output << round(selection.w); break;
61
+                case 'c':
62
+                case 'C': output << cancelled; break;
63
+                case 'h':
64
+                case 'H': output << round(selection.h); break;
65
+                case 'g':
66
+                case 'G': output << round(selection.w) << "x" << round(selection.h)
67
+                          << "+" << round(selection.x) << "+" << round(selection.y); break;
68
+                case 'i':
69
+                case 'I': output << selection.id; break;
70
+                case '%': output << "%"; break;
71
+                default: throw new std::invalid_argument( std::string()+"Expected x, y, w, h, g, i, c, or % after % in format. Got `" + input[i+1] + "`." );
72
+             }
73
+            i++;
74
+            continue;
180 75
         }
76
+        output << input[i];
181 77
     }
182
-    // Center around mouse if we have a fixed size.
183
-    if ( maximumsize == minimumsize && w == maximumsize && h == maximumsize ) {
184
-        x = ex - maximumsize/2;
185
-        y = ey - maximumsize/2;
186
-    }
187
-    *rsx = x;
188
-    *rsy = y;
189
-    *rex = x + w;
190
-    *rey = y + h;
78
+    return output.str();
191 79
 }
192 80
 
193
-// Some complicated key detection to replicate key repeating
194
-bool keyRepeat( KeySym key, double curtime, double repeatdelay, double* time, bool* memory ) {
195
-    if ( xengine->keyPressed( key ) != *memory ) {
196
-        if ( xengine->keyPressed( key ) ) {
197
-            *memory = true;
198
-            *time = curtime;
199
-            return true;
200
-        } else {
201
-            *memory = false;
202
-        }
203
-    }
204
-    if ( xengine->keyPressed( key ) && curtime - *time > repeatdelay ) {
205
-        return true;
206
-    }
207
-    return false;
81
+void printHelp() {
82
+    std::cout << "slop v5.3.21\n";
83
+    std::cout << "\n";
84
+    std::cout << "Copyright (C) 2017 Dalton Nell, Slop Contributors\n";
85
+    std::cout << "(https://github.com/naelstrof/slop/graphs/contributors)\n";
86
+    std::cout << "Usage: slop [options]\n";
87
+    std::cout << "\n";
88
+    std::cout << "slop (Select Operation) is an application that queries for a selection from the\n";
89
+    std::cout << "user and prints the region to stdout.\n";
90
+    std::cout << "\n";
91
+    std::cout << "-h, --help                    Print help and exit\n";
92
+    std::cout << "-v, --version                 Print version and exit\n";
93
+    std::cout << "Options\n";
94
+    std::cout << "  -x, --xdisplay=hostname:number.screen_number\n";
95
+    std::cout << "                                Sets the x display.\n";
96
+	std::cout << "  -k, --nokeyboard              Disables the ability to cancel selections with\n";
97
+	std::cout << "                                  the keyboard.  (default=off)\n";
98
+	std::cout << "  -b, --bordersize=FLOAT        Set the selection rectangle's thickness.\n";
99
+	std::cout << "                                  (default=`1')\n";
100
+	std::cout << "  -p, --padding=FLOAT           Set the padding size of the selection. Can be\n";
101
+	std::cout << "                                  negative.  (default=`0')\n";
102
+	std::cout << "  -t, --tolerance=FLOAT         How far in pixels the mouse can move after\n";
103
+	std::cout << "                                  clicking and still be detected as a normal\n";
104
+	std::cout << "                                  click instead of a click and drag. Setting\n";
105
+	std::cout << "                                  this to 0 will disable window selections.\n";
106
+	std::cout << "                                  Alternatively setting it to 999999 would.\n";
107
+	std::cout << "                                  only allow for window selections.\n";
108
+	std::cout << "                                  (default=`2')\n";
109
+	std::cout << "  -c, --color=FLOAT,FLOAT,FLOAT,FLOAT\n";
110
+	std::cout << "                                Set the selection rectangle's color. Supports\n";
111
+	std::cout << "                                  RGB or RGBA values.\n";
112
+	std::cout << "                                  (default=`0.5,0.5,0.5,1')\n";
113
+	std::cout << "  -n, --nodecorations=INT       Attempt to select child windows in order to\n";
114
+	std::cout << "                                  avoid window decorations. Setting this to\n";
115
+    std::cout << "                                  1 will enable a light attempt to\n";
116
+    std::cout << "                                  remove decorations. Setting this to 2 will\n";
117
+    std::cout << "                                  enable aggressive decoration removal.\n";
118
+    std::cout << "                                  (default=`0')\n";
119
+	std::cout << "  -q, --quiet                   Disable any unnecessary cerr output. Any\n";
120
+	std::cout << "                                  warnings simply won't print.\n";
121
+	std::cout << "  -l, --highlight               Instead of outlining selections, slop\n";
122
+	std::cout << "                                  highlights it. This is only useful when\n";
123
+	std::cout << "                                  --color is set to a transparent color.\n";
124
+	std::cout << "                                  (default=off)\n";
125
+	std::cout << "  -r, --shader=STRING           Sets the shader to load and use from\n";
126
+	std::cout << "                                  ~/.config/slop/\n";
127
+	std::cout << "  -f, --format=STRING           Set the output format string. Format specifiers\n";
128
+	std::cout << "                                  are %x, %y, %w, %h, %i, %g, and %c.\n";
129
+	std::cout << "                                  (default=`%g\n')\n";
130
+	std::cout << "Examples\n";
131
+	std::cout << "    $ # Gray, thick, transparent border for maximum visiblity.\n";
132
+	std::cout << "    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n";
133
+	std::cout << "\n";
134
+	std::cout << "    $ # Remove window decorations.\n";
135
+	std::cout << "    $ slop --nodecorations\n";
136
+	std::cout << "\n";
137
+	std::cout << "    $ # Disable window selections. Useful for selecting individual pixels.\n";
138
+	std::cout << "    $ slop -t 0\n";
139
+	std::cout << "\n";
140
+	std::cout << "    $ # Classic Windows XP selection.\n";
141
+	std::cout << "    $ slop -l -c 0.3,0.4,0.6,0.4\n";
142
+	std::cout << "\n";
143
+	std::cout << "    $ # Read slop output for use in scripts.\n";
144
+	std::cout << "    $ read -r X Y W H G ID < <(slop -f '%x %y %w %h %g %i')\n";
145
+	std::cout << "\n";
146
+	std::cout << "Tips\n";
147
+	std::cout << "    * If you don't like a selection: you can cancel it by right-clicking\n";
148
+	std::cout << "regardless of which options are enabled or disabled for slop.\n";
149
+	std::cout << "    * If slop doesn't seem to select a window accurately, the problem could be\n";
150
+	std::cout << "because of decorations getting in the way. Try enabling the --nodecorations\n";
151
+	std::cout << "flag.\n";
208 152
 }
209 153
 
210 154
 int app( int argc, char** argv ) {
211
-    gengetopt_args_info options;
212
-    int err = cmdline_parser( argc, argv, &options );
213
-    if ( err != EXIT_SUCCESS ) {
214
-        return EXIT_FAILURE;
215
-    }
216
-    int state = 0;
217
-    bool running = true;
218
-    bool opengl = options.opengl_flag;
219
-    slop::SelectRectangle* selection = NULL;
220
-    Window window = None;
221
-    Window windowmemory = None;
222
-    std::string xdisplay;
223
-    if ( options.xdisplay_given ) {
224
-        xdisplay = options.xdisplay_arg;
225
-    } else {
226
-        // If we weren't specifically given a xdisplay, we try
227
-        // to parse it from environment variables
228
-        char* display = getenv( "DISPLAY" );
229
-        if ( display ) {
230
-            xdisplay = display;
231
-        } else {
232
-            fprintf( stderr, "Warning: Failed to parse environment variable: DISPLAY. Using \":0\" instead.\n" );
233
-            xdisplay = ":0";
234
-        }
235
-    }
236
-    int padding = options.padding_arg;
237
-    int borderSize = options.bordersize_arg;
238
-    int tolerance = options.tolerance_arg;
239
-    float r, g, b, a;
240
-    err = parseColor( options.color_arg, &r, &g, &b, &a );
241
-    if ( err != EXIT_SUCCESS ) {
242
-        fprintf( stderr, "Error parsing color %s\n", options.color_arg );
243
-        return EXIT_FAILURE;
244
-    }
245
-    float gracetime;
246
-    err = sscanf( options.gracetime_arg, "%f", &gracetime );
247
-    if ( err != 1 ) {
248
-        fprintf( stderr, "Error parsing %s as a float for gracetime!\n", options.gracetime_arg );
249
-        return EXIT_FAILURE;
250
-    }
251
-    bool highlight = options.highlight_flag;
252
-    bool keyboard = !options.nokeyboard_flag;
253
-    bool decorations = !options.nodecorations_flag;
254
-    bool themeon = (bool)options.theme_given;
255
-    std::string theme = options.theme_arg;
256
-#ifdef OPENGL_ENABLED
257
-    bool shadergiven = (bool)options.shader_given;
258
-#endif
259
-    std::string shader = options.shader_arg;
260
-    struct timespec start, time;
261
-    int xoffset = 0;
262
-    int yoffset = 0;
263
-    int cx = 0;
264
-    int cy = 0;
265
-    int xmem = 0;
266
-    int ymem = 0;
267
-    int wmem = 0;
268
-    int hmem = 0;
269
-    int minimumsize = options.min_arg;
270
-    int maximumsize = options.max_arg;
271
-    bool pressedMemory[4];
272
-    double pressedTime[4];
273
-    for ( int i=0;i<4;i++ ) {
274
-        pressedMemory[ i ] = false;
275
-        pressedTime[ i ] = 0;
276
-    }
277
-    std::string format = options.format_arg;
278
-    bool magenabled = options.magnify_flag;
279
-#ifdef OPENGL_ENABLED
280
-    float magstrength = options.magstrength_arg;
281
-    if ( options.magpixels_arg < 0 ) {
282
-        fprintf( stderr, "Error: --magpixels < 0, it's an unsigned integer you twat. Stop trying to underflow me!\n" );
283
-        return EXIT_FAILURE;
284
-    }
285
-    unsigned int magpixels = (unsigned int)options.magpixels_arg;
286
-#endif
287
-    cmdline_parser_free( &options );
288
-#ifndef OPENGL_ENABLED
289
-    if ( opengl || themeon || magenabled ) {
290
-        throw std::runtime_error( "Slop wasn't compiled with OpenGL support, so themes, magnifications, and shaders are disabled! Try compiling it with the CMAKE_OPENGL_SUPPORT set to true." );
291
-    }
292
-#else // OPENGL_ENABLED
293
-    if ( ( themeon || magenabled || shadergiven ) && !opengl ) {
294
-        throw std::runtime_error( "Slop needs --opengl enabled to use themes, shaders, or magnifications." );
295
-    }
296
-#endif
155
+    // Options just validates all of our input from argv
156
+    Options options( argc, argv );
157
+    bool quiet = false;
158
+    options.getBool( "quiet", 'q', quiet );
159
+    bool help = false;
160
+    if ( options.getBool( "help", 'h', help ) ) {
161
+        printHelp();
162
+        return 0;
163
+    }
164
+    if ( options.getBool( "version", 'v', help ) ) {
165
+        std::cout << SLOP_VERSION << "\n";
166
+        return 0;
167
+    }
168
+    // We then parse the options into something slop can understand.
169
+    SlopOptions* parsedOptions = getOptions( options );
297 170
 
298
-    // First we set up the x interface and grab the mouse,
299
-    // if we fail for either we exit immediately.
300
-    err = xengine->init( xdisplay.c_str() );
301
-    if ( err != EXIT_SUCCESS ) {
302
-        printSelection( format, true, 0, 0, 0, 0, None );
303
-        return EXIT_FAILURE;
304
-    }
305
-    if ( !slop::isSelectRectangleSupported() ) {
306
-        fprintf( stderr, "Error: Your X server doesn't support the XShape extension. There's nothing slop can do about this!\n" );
307
-        fprintf( stderr, "  Try updating X and making sure you have XExtensions installed. (/usr/lib/libXext.so, /usr/include/X11/extensions/shape.h)\n" );
308
-        return EXIT_FAILURE;
309
-    }
310
-    err = xengine->grabCursor( slop::Cross, gracetime );
311
-    if ( err != EXIT_SUCCESS ) {
312
-        printSelection( format, true, 0, 0, 0, 0, None );
313
-        return EXIT_FAILURE;
171
+    // We want to validate our format option if we got one, we do that by just doing a dry run
172
+    // on a fake selection.
173
+    SlopSelection selection(0,0,0,0,0);
174
+    std::string format;
175
+    bool gotFormat = options.getString("format", 'f', format);
176
+    if ( gotFormat ) {
177
+        formatOutput( format, selection, false );
314 178
     }
315
-    if ( keyboard ) {
316
-        err = xengine->grabKeyboard();
317
-        if ( err ) {
318
-            fprintf( stderr, "Warning: Failed to grab the keyboard. This is non-fatal, keyboard presses might fall through to other applications.\n" );
319
-        }
320
-    }
321
-    current_utc_time( &start );
322
-    double deltatime = 0;
323
-    double curtime = double( start.tv_sec*1000000000L + start.tv_nsec )/1000000000.f;
324
-    while ( running ) {
325
-        current_utc_time( &time );
326
-        // "ticking" the xengine makes it process all queued events.
327
-        xengine->tick();
328
-        // If the user presses any key on the keyboard, exit the application.
329
-        // Make sure at least gracetime has passed before allowing canceling
330
-        double newtime = double( time.tv_sec*1000000000L + time.tv_nsec )/1000000000.f;
331
-        deltatime = newtime-curtime;
332
-        curtime = newtime;
333
-        double starttime = double( start.tv_sec*1000000000L + start.tv_nsec )/1000000000.f;
334
-        if ( curtime - starttime > gracetime ) {
335
-            if ( keyRepeat( XK_Up, curtime, 0.5, &pressedTime[ 0 ], &pressedMemory[ 0 ] ) ) {
336
-                yoffset -= 1;
337
-            }
338
-            if ( keyRepeat( XK_Down, curtime, 0.5, &pressedTime[ 1 ], &pressedMemory[ 1 ] ) ) {
339
-                yoffset += 1;
340
-            }
341
-            if ( keyRepeat( XK_Left, curtime, 0.5, &pressedTime[ 2 ], &pressedMemory[ 2 ] ) ) {
342
-                xoffset -= 1;
343
-            }
344
-            if ( keyRepeat( XK_Right, curtime, 0.5, &pressedTime[ 3 ], &pressedMemory[ 3 ] ) ) {
345
-                xoffset += 1;
346
-            }
347
-            // If we pressed enter we move the state onward.
348
-            if ( xengine->keyPressed( XK_Return ) ) {
349
-                // If we're highlight windows, just select the active window.
350
-                if ( state == 0 ) {
351
-                    state = 1;
352
-                // If we're making a custom selection, select the custom selection.
353
-                } else if ( state == 2 ) {
354
-                    state = 3;
355
-                }
356
-            }
357
-            // If we press any key other than the arrow keys or enter key, we shut down!
358
-            if ( !( xengine->keyPressed( XK_Up ) || xengine->keyPressed( XK_Down ) || xengine->keyPressed( XK_Left ) || xengine->keyPressed( XK_Right ) ) &&
359
-                !( xengine->keyPressed( XK_Return ) ) &&
360
-                ( ( xengine->anyKeyPressed() && keyboard ) || xengine->mouseDown( 3 ) ) ) {
361
-                printSelection( format, true, 0, 0, 0, 0, None );
362
-                fprintf( stderr, "User pressed key. Canceled selection.\n" );
363
-                state = -1;
364
-                running = false;
365
-            }
366
-        }
367
-        // Our adorable little state manager will handle what state we're in.
368
-        switch ( state ) {
369
-            default: {
370
-                break;
371
-            }
372
-            case 0: {
373
-                // If xengine has found a window we're hovering over (or if it changed)
374
-                // create a rectangle around it so the user knows he/she can click on it.
375
-                // --but only if the user wants us to
376
-                if ( window != xengine->m_hoverWindow && tolerance > 0 ) {
377
-                    slop::WindowRectangle t;
378
-                    t.setGeometry( xengine->m_hoverWindow, decorations );
379
-                    t.applyPadding( padding );
380
-                    t.applyMinMaxSize( minimumsize, maximumsize );
381
-                    // Make sure we only apply offsets to windows that we've forcibly removed decorations on.
382
-                    if ( !selection ) {
383
-#ifdef OPENGL_ENABLED
384
-                        if ( opengl ) {
385
-                            selection = new slop::GLSelectRectangle( t.m_x, t.m_y,
386
-                                                                     t.m_x + t.m_width,
387
-                                                                     t.m_y + t.m_height,
388
-                                                                     borderSize,
389
-                                                                     highlight,
390
-                                                                     r, g, b, a );
391
-                            // Haha why is this so hard to cast?
392
-                            ((slop::GLSelectRectangle*)(selection))->setMagnifySettings( magenabled, magstrength, magpixels );
393
-                            ((slop::GLSelectRectangle*)(selection))->setTheme( themeon, theme );
394
-                            ((slop::GLSelectRectangle*)(selection))->setShader( shader );
395
-                        } else {
396
-#endif // OPENGL_ENABLED
397
-                            selection = new slop::XSelectRectangle( t.m_x, t.m_y,
398
-                                                                    t.m_x + t.m_width,
399
-                                                                    t.m_y + t.m_height,
400
-                                                                    borderSize,
401
-                                                                    highlight,
402
-                                                                    r, g, b, a );
403
-#ifdef OPENGL_ENABLED
404
-                        }
405
-#endif // OPENGL_ENABLED
406
-                    } else {
407
-                        selection->setGeo( t.m_x, t.m_y, t.m_x + t.m_width, t.m_y + t.m_height );
408
-                    }
409
-                    //window = xengine->m_hoverWindow;
410
-                    // Since WindowRectangle can select different windows depending on click location...
411
-                    window = t.getWindow();
412
-                }
413
-                if ( selection ) {
414
-                    selection->update( deltatime );
415
-                }
416
-                // If the user clicked we move on to the next state.
417
-                if ( xengine->mouseDown( 1 ) ) {
418
-                    state++;
419
-                }
420
-                break;
421
-            }
422
-            case 1: {
423
-                // Set the mouse position of where we clicked, used so that click tolerance doesn't affect the rectangle's position.
424
-                cx = xengine->m_mousex;
425
-                cy = xengine->m_mousey;
426
-                // Make sure we don't have un-seen applied offsets.
427
-                xoffset = 0;
428
-                yoffset = 0;
429
-                // Also remember where the original selection was
430
-                if ( selection ) {
431
-                    xmem = selection->m_x;
432
-                    ymem = selection->m_y;
433
-                    wmem = selection->m_width;
434
-                    hmem = selection->m_height;
435
-                } else {
436
-                    xmem = cx;
437
-                    ymem = cy;
438
-                }
439
-                state++;
440
-                break;
441
-            }
442
-            case 2: {
443
-                // It's possible that our selection doesn't exist still, lets make sure it actually gets created here.
444
-                if ( !selection ) {
445
-                    int sx, sy, ex, ey;
446
-                    constrain( cx, cy, xengine->m_mousex, xengine->m_mousey, padding, minimumsize, maximumsize, &sx, &sy, &ex, &ey );
447
-#ifdef OPENGL_ENABLED
448
-                    if ( opengl ) {
449
-                        selection = new slop::GLSelectRectangle( sx, sy,
450
-                                                                 ex, ey,
451
-                                                                 borderSize,
452
-                                                                 highlight,
453
-                                                                 r, g, b, a );
454
-                        // Haha why is this so hard to cast?
455
-                        ((slop::GLSelectRectangle*)(selection))->setMagnifySettings( magenabled, magstrength, magpixels );
456
-                        ((slop::GLSelectRectangle*)(selection))->setTheme( themeon, theme );
457
-                        ((slop::GLSelectRectangle*)(selection))->setShader( shader );
458
-                    } else {
459
-#endif // OPENGL_ENABLED
460
-                        selection = new slop::XSelectRectangle( sx, sy,
461
-                                                                ex, ey,
462
-                                                                borderSize,
463
-                                                                highlight,
464
-                                                                r, g, b, a );
465
-#ifdef OPENGL_ENABLED
466
-                    }
467
-#endif // OPENGL_ENABLED
468
-                }
469
-                windowmemory = window;
470
-                // If the user has let go of the mouse button, we'll just
471
-                // continue to the next state.
472
-                if ( !xengine->mouseDown( 1 ) ) {
473
-                    state++;
474
-                    break;
475
-                }
476
-                // Check to make sure the user actually wants to drag for a selection before moving things around.
477
-                int w = xengine->m_mousex - cx;
478
-                int h = xengine->m_mousey - cy;
479
-                if ( ( std::abs( w ) < tolerance && std::abs( h ) < tolerance ) ) {
480
-                    // We make sure the selection rectangle stays on the window we had selected
481
-                    selection->setGeo( xmem, ymem, xmem + wmem, ymem + hmem );
482
-                    selection->update( deltatime );
483
-                    xengine->setCursor( slop::Left );
484
-                    // Make sure
485
-                    window = windowmemory;
486
-                    continue;
487
-                }
488
-                // If we're not selecting a window.
489
-                windowmemory = window;
490
-                window = None;
491
-                // We also detect which way the user is pulling and set the mouse icon accordingly.
492
-                bool x = cx > xengine->m_mousex;
493
-                bool y = cy > xengine->m_mousey;
494
-                if ( ( selection->m_width <= 1 && selection->m_height <= 1 ) || ( minimumsize == maximumsize && minimumsize != 0 && maximumsize != 0 ) ) {
495
-                    xengine->setCursor( slop::Cross );
496
-                } else if ( !x && !y ) {
497
-                    xengine->setCursor( slop::LowerRightCorner );
498
-                } else if ( x && !y ) {
499
-                    xengine->setCursor( slop::LowerLeftCorner );
500
-                } else if ( !x && y ) {
501
-                    xengine->setCursor( slop::UpperRightCorner );
502
-                } else if ( x && y ) {
503
-                    xengine->setCursor( slop::UpperLeftCorner );
504
-                }
505
-                // Apply padding and minimum size adjustments.
506
-                int sx, sy, ex, ey;
507
-                constrain( cx, cy, xengine->m_mousex, xengine->m_mousey, padding, minimumsize, maximumsize, &sx, &sy, &ex, &ey );
508
-                // Set the selection rectangle's dimensions to mouse movement.
509
-                selection->setGeo( sx + xoffset, sy + yoffset, ex, ey );
510
-                selection->update( deltatime );
511
-                break;
512
-            }
513
-            case 3: {
514
-                int x, y, w, h;
515
-                // Exit the utility after this state runs once.
516
-                running = false;
517
-                // We pull the dimensions and positions from the selection rectangle.
518
-                // The selection rectangle automatically converts the positions and
519
-                // dimensions to absolute coordinates when we set them earilier.
520
-                x = selection->m_x;
521
-                y = selection->m_y;
522
-                w = selection->m_width;
523
-                h = selection->m_height;
524
-                // Delete the rectangle, which will remove it from the screen.
525
-                delete selection;
526
-                // Make sure if no window was specifically specified, that we output the root window.
527
-                Window temp = window;
528
-                if ( temp == None ) {
529
-                    temp = xengine->m_root;
530
-                }
531
-                // Print the selection :)
532
-                printSelection( format, false, x, y, w, h, temp );
533
-                break;
534
-            }
179
+
180
+    // Finally we do the real selection.
181
+    bool cancelled = false;
182
+    selection = SlopSelect(parsedOptions, &cancelled, quiet);
183
+    
184
+    // Here we're done with the parsed option data.
185
+    delete parsedOptions;
186
+    // We know if we cancelled or not
187
+    if ( cancelled ) {
188
+        if ( !quiet ) {
189
+            std::cerr << "Selection was cancelled by keystroke or right-click.\n";
535 190
         }
536
-        // This sleep is required because drawing the rectangles is a very expensive task that acts really weird with Xorg when called as fast as possible.
537
-        // 0.01 seconds
538
-        usleep( 10000 );
191
+        return 1;
539 192
     }
540
-    xengine->releaseCursor();
541
-    xengine->releaseKeyboard();
542
-    // Try to process any last-second requests.
543
-    //xengine->tick();
544
-    // Clean up global classes.
545
-    delete xengine;
546
-    // Sleep for 0.05 seconds to ensure everything was cleaned up. (Without this, slop's window often shows up in screenshots.)
547
-    usleep( 50000 );
548
-    // If we canceled the selection, return error.
549
-    if ( state == -1 ) {
550
-        return EXIT_FAILURE;
193
+    // If we recieved a format option, we output the specified output.
194
+    if ( gotFormat ) {
195
+        std::cout << formatOutput( format, selection, cancelled );
196
+        return 0;
551 197
     }
552
-    return EXIT_SUCCESS;
198
+    std::cout << formatOutput( "%g\n", selection, cancelled );
199
+    return 0;
553 200
 }
554 201
 
555 202
 int main( int argc, char** argv ) {
556 203
     try {
557 204
         return app( argc, argv );
558
-    } catch( std::bad_alloc const& exception ) {
559
-        fprintf( stderr, "Couldn't allocate enough memory! No space left in RAM." );
560
-    } catch( std::exception const& exception ) {
561
-        fprintf( stderr, "Unhandled Exception Thrown: %s\n", exception.what() );
562
-    } catch( std::string err ) {
563
-        fprintf( stderr, "Unhandled Exception Thrown: %s\n", err.c_str() );
564
-    } catch( char* err ) {
565
-        fprintf( stderr, "Unhandled Exception Thrown: %s\n", err );
566
-    } catch( ... ) {
567
-        fprintf( stderr, "Unknown Exception Thrown!\n" );
568
-    }
569
-    return EXIT_FAILURE;
205
+    } catch( std::exception* e ) {
206
+        std::cerr << "Slop encountered an error:\n" << e->what() << "\n";
207
+        return 1;
208
+    } // let the operating system handle any other kind of exception.
209
+    return 1;
570 210
 }

+ 125
- 0
src/mouse.cpp Просмотреть файл

@@ -0,0 +1,125 @@
1
+#include "mouse.hpp"
2
+
3
+void slop::Mouse::setButton( int button, int state ) {
4
+    for (unsigned int i=0;i<buttons.size();i++ ) {
5
+        if ( buttons[i].x == button ) {
6
+            buttons[i].y = state;
7
+            return;
8
+        }
9
+    }
10
+    buttons.push_back(glm::ivec2(button,state));
11
+}
12
+
13
+int slop::Mouse::getButton( int button ) {
14
+    for (unsigned int i=0;i<buttons.size();i++ ) {
15
+        if ( buttons[i].x == button ) {
16
+            return buttons[i].y;
17
+        }
18
+    }
19
+    return 0;
20
+}
21
+
22
+glm::vec2 slop::Mouse::getMousePos() {
23
+    Window root, child;
24
+    int mx, my;
25
+    int wx, wy;
26
+    unsigned int mask;
27
+    XQueryPointer( x11->display, x11->root, &root, &child, &mx, &my, &wx, &wy, &mask );
28
+    return glm::vec2( mx, my );
29
+}
30
+
31
+void slop::Mouse::setCursor( int cursor ) {
32
+    if ( currentCursor == cursor ) {
33
+        return;
34
+    }
35
+    XFreeCursor( x11->display, xcursor );
36
+    xcursor = XCreateFontCursor( x11->display, cursor );
37
+    XChangeActivePointerGrab( x11->display,
38
+                              PointerMotionMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask,
39
+                              xcursor, CurrentTime );
40
+}
41
+
42
+slop::Mouse::Mouse(X11* x11, int nodecorations, Window ignoreWindow ) {
43
+    this->x11 = x11;
44
+    currentCursor = XC_cross;
45
+    xcursor = XCreateFontCursor( x11->display, XC_cross );
46
+    hoverWindow = None;
47
+    XGrabPointer( x11->display, x11->root, True,
48
+                  PointerMotionMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask,
49
+                  GrabModeAsync, GrabModeAsync, None, xcursor, CurrentTime );
50
+    this->nodecorations = nodecorations;
51
+    this->ignoreWindow = ignoreWindow;
52
+    hoverWindow = findWindow(x11->root);
53
+}
54
+
55
+slop::Mouse::~Mouse() {
56
+	XUngrabPointer( x11->display, CurrentTime );
57
+}
58
+
59
+void slop::Mouse::update() {
60
+    XEvent event;
61
+    while ( XCheckTypedEvent( x11->display, ButtonPress, &event ) ) {
62
+		setButton( event.xbutton.button, 1 );
63
+	}
64
+    bool findNewWindow = false;
65
+    while ( XCheckTypedEvent( x11->display, MotionNotify, &event ) ) {
66
+        findNewWindow = true;
67
+	}
68
+    if ( findNewWindow ) {
69
+        hoverWindow = findWindow(x11->root);
70
+    }
71
+    while ( XCheckTypedEvent( x11->display, ButtonRelease, &event ) ) {
72
+		setButton( event.xbutton.button, 0 );
73
+	}
74
+    while ( XCheckTypedEvent( x11->display, EnterNotify, &event ) ) {
75
+        hoverWindow = event.xcrossing.window;
76
+	}
77
+}
78
+
79
+Window slop::Mouse::findWindow( Window foo ) {
80
+    glm::vec2 pos = getMousePos();
81
+    Window root, parent;
82
+    Window* children;
83
+    unsigned int nchildren;
84
+    Window selectedWindow;
85
+    XQueryTree( x11->display, foo, &root, &parent, &children, &nchildren );
86
+    if ( !children || nchildren <= 0 ) {
87
+        return foo;
88
+    }
89
+    // The children are ordered, so we traverse backwards.
90
+    for( int i=nchildren-1;i>=0;i-- ) {
91
+        if ( children[i] == ignoreWindow ) {
92
+            continue;
93
+        }
94
+        // We need to make sure the window isn't something that currently isn't mapped.
95
+        XWindowAttributes attr;         
96
+        XGetWindowAttributes( x11->display, children[i], &attr );
97
+        if ( attr.map_state != IsViewable ) {
98
+            continue;
99
+        }
100
+        glm::vec4 rect = getWindowGeometry(children[i], false);
101
+        float a = pos.x - rect.x;
102
+        float b = pos.y - rect.y;
103
+        if ( a <= rect.z && a >= 0 ) {
104
+            if ( b <= rect.w && b >= 0 ) {
105
+                selectedWindow = children[i];
106
+                switch( nodecorations ) {
107
+                    case 0:
108
+                        XFree(children);
109
+                        return selectedWindow;
110
+                    case 1:
111
+                        XFree(children);
112
+                        //return findWindow( selectedWindow );
113
+                        XQueryTree( x11->display, selectedWindow, &root, &parent, &children, &nchildren );
114
+                        if ( !children || nchildren <= 0 ) {
115
+                            return selectedWindow;
116
+                        }
117
+                        return children[nchildren-1];
118
+                    case 2:
119
+                        return findWindow( selectedWindow );
120
+                }
121
+            }
122
+        }
123
+    }
124
+    return foo;
125
+}

+ 57
- 0
src/mouse.hpp Просмотреть файл

@@ -0,0 +1,57 @@
1
+/* mouse.hpp: Interfaces with x11 to grab mouse information.
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#ifndef N_MOUSE_H_
22
+#define N_MOUSE_H_
23
+
24
+#include <vector>
25
+#include <glm/glm.hpp>
26
+#include <X11/cursorfont.h>
27
+#include <iostream>
28
+
29
+#include "x.hpp"
30
+
31
+namespace slop {
32
+
33
+class Mouse {
34
+private:
35
+    X11* x11;
36
+    std::vector<glm::ivec2> buttons;
37
+    Cursor xcursor;
38
+    int currentCursor;
39
+    Window findWindow( Window foo );
40
+    int nodecorations;
41
+    Window ignoreWindow;
42
+public:
43
+	Window hoverWindow;
44
+	void update();
45
+    Mouse( X11* x11, int nodecorations, Window ignoreWindow );
46
+    ~Mouse();
47
+    void setCursor( int cursor );
48
+    glm::vec2 getMousePos();
49
+    void setButton( int button, int state );
50
+    int getButton( int button );
51
+};
52
+
53
+extern Mouse* mouse;
54
+
55
+}
56
+
57
+#endif // N_MOUSE_H_

+ 233
- 0
src/options.cpp Просмотреть файл

@@ -0,0 +1,233 @@
1
+#include "options.hpp"
2
+
3
+Options::Options( int argc, char** argv ) {
4
+    validArguments.push_back( Argument( "bordersize",   'b', false ) );
5
+    validArguments.push_back( Argument( "padding",      'p', false ) );
6
+    validArguments.push_back( Argument( "color",        'c', false ) );
7
+    validArguments.push_back( Argument( "shader",       'r', false ) );
8
+    validArguments.push_back( Argument( "highlight",    'h', true ) );
9
+    validArguments.push_back( Argument( "format",       'f', false ) );
10
+    validArguments.push_back( Argument( "tolerance",    't', false ) );
11
+    validArguments.push_back( Argument( "nodecorations", 'n', false ) );
12
+    validArguments.push_back( Argument( "nokeyboard",   'k', true ) );
13
+    validArguments.push_back( Argument( "help",         'h', true ) );
14
+    validArguments.push_back( Argument( "xdisplay",     'x', false ) );
15
+    validArguments.push_back( Argument( "version",      'v', true ) );
16
+    validArguments.push_back( Argument( "quiet",        'q', true ) );
17
+    validate( argc, argv );
18
+}
19
+
20
+
21
+int Options::validateStringOption( int argc, char** argv, int argumentIndex ) {
22
+    std::string argument = argv[argumentIndex];
23
+    unsigned int index = 0;
24
+    while( index < validArguments.size() ) {
25
+        Argument& check = validArguments[index];
26
+        for( unsigned int i=0;i<check.name.length();i++ ) {
27
+            if ( check.name[i] != argument[i+2] ) {
28
+                break;
29
+            }
30
+            if ( i == check.name.length()-1 ) {
31
+                if ( !check.isFlagArgument && argument.find("=") == std::string::npos ) {
32
+                    throw new std::invalid_argument("Expected `=` after " + arguments[i]);
33
+                }
34
+                if ( check.isFlagArgument && i+3 != argument.length() ) {
35
+                    throw new std::invalid_argument("Trailing characters on flag " + argument );
36
+                }
37
+                return parseStringOption( argc, argv, argumentIndex, index );
38
+            }
39
+        }
40
+        index++;
41
+    }
42
+    throw new std::invalid_argument("Invalid argument " + argument);
43
+    return 0;
44
+}
45
+
46
+int Options::parseCharOption( int argc, char** argv, int argumentIndex, int validIndex ) {
47
+    std::string argument = argv[argumentIndex];
48
+    Argument& check = validArguments[validIndex];
49
+    // If we're a flag, we take no arguments, nor do we allow = signs or whatever.
50
+    if ( check.isFlagArgument ) {
51
+        if ( argument != std::string()+"-"+check.cname ) {
52
+            for( int o=1;o<argument.length();o++ ) {
53
+                bool isValid = false;
54
+                for( int i=0;i<validArguments.size()&&!isValid;i++ ) {
55
+                    if ( argument[o] == check.cname ) {
56
+                        if ( check.isFlagArgument ) {
57
+                            isValid = true;
58
+                            arguments.push_back( std::string()+check.cname );
59
+                            values.push_back("");
60
+                            break;
61
+                        } else {
62
+                            throw new std::invalid_argument( std::string()+"Truncating non-flag arguments is not allowed. Split this up: `" + argument + "`." );
63
+                        }
64
+                    }
65
+                }
66
+                if (!isValid) {
67
+                    throw new std::invalid_argument( std::string()+"Unexpected characters around flag `" + argument + "`." );
68
+                }
69
+            }
70
+            return 1;
71
+        } else {
72
+            arguments.push_back( std::string()+argument[1] );
73
+            values.push_back("");
74
+            return 1;
75
+        }
76
+    }
77
+    arguments.push_back( std::string()+argument[1] );
78
+    // If they supplied the parameters with spaces
79
+    if ( argument == std::string()+"-"+check.cname ) {
80
+        values.push_back(argv[argumentIndex+1]);
81
+        return 2;
82
+    }
83
+    // If they didn't supply the parameters with spaces
84
+    if ( argument[2] == '=' ) {
85
+        values.push_back(argument.substr(3));
86
+        return 1;
87
+    }
88
+    values.push_back(argument.substr(2));
89
+    return 1;
90
+}
91
+
92
+int Options::parseStringOption( int argc, char** argv, int argumentIndex, int validIndex ) {
93
+    std::string argument = argv[argumentIndex];
94
+    if ( validArguments[validIndex].isFlagArgument ) {
95
+        arguments.push_back( argument.substr(2) );
96
+        values.push_back("");
97
+        return 1;
98
+    }
99
+    arguments.push_back( argument.substr(2,argument.find_first_of('=')) );
100
+    values.push_back(argument.substr(argument.find_first_of('=')));
101
+    return 1;
102
+}
103
+
104
+int Options::validateCharOption( int argc, char** argv, int argumentIndex ) {
105
+    std::string argument = argv[argumentIndex];
106
+    unsigned int index = 0;
107
+    while( index < validArguments.size() ) {
108
+        char check = validArguments[index].cname;
109
+        if ( argument.length() < 2 ) {
110
+            continue;
111
+        }
112
+        if ( check == argument[1] && ( argument.find("=") == 2 || argument.find('=') == std::string::npos ) && argument[0] == '-' ) {
113
+            return parseCharOption( argc, argv, argumentIndex, index );
114
+        }
115
+        index++;
116
+    }
117
+    throw new std::invalid_argument("Invalid argument `" + argument + "`.");
118
+    return 0;
119
+}
120
+
121
+void Options::validate( int argc, char** argv ) {
122
+    for ( int i=1;i<argc;) {
123
+        std::string argument = argv[i];
124
+        if ( argument[0] != '-' ) {
125
+            floatingValues.push_back( argument );
126
+            if ( floatingValues.size() > maxFloatingValues ) {
127
+                throw new std::invalid_argument("Unexpected floating value `" + argument + "`. Forget to specify an option?" );
128
+            }
129
+            i++;
130
+            continue;
131
+        }
132
+        if ( argument[0] == '-' && argument[1] == '-' ) {
133
+            i += validateStringOption( argc, argv, i );
134
+            continue;
135
+        }
136
+        i += validateCharOption( argc, argv, i );
137
+    }
138
+}
139
+
140
+bool Options::getFloat( std::string name, char namec, float& found ) {
141
+    for( unsigned int i=0;i<arguments.size();i++ ) {
142
+        if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
143
+            std::string::size_type sz;
144
+            float retvar;
145
+            try {
146
+                retvar = std::stof(values[i],&sz);
147
+            } catch ( ... ) {
148
+                throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a float.");
149
+            }
150
+            if ( sz != values[i].length() ) {
151
+                throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a float.");
152
+            }
153
+            found = retvar;
154
+            return true;
155
+        }
156
+    }
157
+    return false;
158
+}
159
+
160
+bool Options::getInt( std::string name, char namec, int& found ) {
161
+    for( unsigned int i=0;i<arguments.size();i++ ) {
162
+        if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
163
+            if ( arguments[i].size() > 1 && arguments[i].find("=") == std::string::npos ) {
164
+                throw new std::invalid_argument("Expected `=` after " + arguments[i]);
165
+            }
166
+            std::string::size_type sz;
167
+            float retvar;
168
+            try {
169
+                retvar = std::stoi(values[i],&sz);
170
+            } catch ( ... ) {
171
+                throw new std::invalid_argument("Unable to parse " + arguments[i] + "'s value " + values[i] + " as an integer.");
172
+            }
173
+            if ( sz != values[i].length() ) {
174
+                throw new std::invalid_argument("Unable to parse " + arguments[i] + "'s value " + values[i] + " as an integer.");
175
+            }
176
+            found = retvar;
177
+            return true;
178
+        }
179
+    }
180
+    return false;
181
+}
182
+
183
+bool Options::getString( std::string name, char namec, std::string& found ) {
184
+    for( unsigned int i=0;i<arguments.size();i++ ) {
185
+        if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
186
+            found = values[i];
187
+            return true;
188
+        }
189
+    }
190
+    return false;
191
+}
192
+
193
+bool Options::getColor( std::string name, char namec, glm::vec4& found ) {
194
+    for( unsigned int i=0;i<arguments.size();i++ ) {
195
+        if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
196
+            std::string::size_type sz;
197
+            std::string value = values[i];
198
+            try {
199
+                found[0] = std::stof(value,&sz);
200
+                value = value.substr(sz+1);
201
+                found[1] = std::stof(value,&sz);
202
+                value = value.substr(sz+1);
203
+                found[2] = std::stof(value,&sz);
204
+                if ( value.size() != sz ) {
205
+                    value = value.substr(sz+1);
206
+                    found[3] = std::stof(value,&sz);
207
+                    if ( value.size() != sz ) {
208
+                        throw "dur";
209
+                    }
210
+                } else {
211
+                    found[3] = 1;
212
+                }
213
+            } catch ( ... ) {
214
+                throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a color. Should be in the format r,g,b or r,g,b,a. Like 1,1,1,1.");
215
+            }
216
+            return true;
217
+        }
218
+    }
219
+    return false;
220
+}
221
+
222
+bool Options::getBool( std::string name, char namec, bool& found ) {
223
+    for( unsigned int i=0;i<arguments.size();i++ ) {
224
+        if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
225
+            if ( values[i] != "" ) {
226
+                throw new std::invalid_argument("Unexpected value `" + values[i] + "` for flag argument `" + arguments[i] + "`.");
227
+            }
228
+            found = true;
229
+            return true;
230
+        }
231
+    }
232
+    return false;
233
+}

+ 0
- 125
src/options.ggo Просмотреть файл

@@ -1,125 +0,0 @@
1
-package "slop"
2
-version "v@slop_VERSION_MAJOR@.@slop_VERSION_MINOR@.@slop_VERSION_PATCH@"
3
-usage "slop [options]"
4
-description "slop (Select Operation) is an application that queries for a selection from the user and prints the region to stdout."
5
-versiontext "Copyright (C) 2014 Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors)"
6
-
7
-text "Options"
8
-
9
-option "xdisplay" - "Sets the x display."
10
-    string
11
-    typestr="hostname:number.screen_number"
12
-    optional
13
-
14
-option "nokeyboard" - "Disables the ability to cancel selections with the keyboard."
15
-    flag
16
-    off
17
-
18
-option "bordersize" b "Set the selection rectangle's thickness. Does nothing when --highlight is enabled."
19
-    int
20
-    default="5"
21
-    optional
22
-
23
-option "padding" p "Set the padding size of the selection. Can be negative."
24
-    int
25
-    default="0"
26
-    optional
27
-
28
-option "tolerance" t "How far in pixels the mouse can move after clicking and still be detected as a normal click instead of a click and drag. Setting this to 0 will disable window selections."
29
-    int
30
-    default="2"
31
-    optional
32
-
33
-option "gracetime" g "Set the amount of time before slop will check for keyboard cancellations in seconds."
34
-    string
35
-    typestr="FLOAT"
36
-    default="0.4"
37
-    optional
38
-
39
-option "color" c "Set the selection rectangle's color. Supports RGB or RGBA values."
40
-    string
41
-    typestr="FLOAT,FLOAT,FLOAT,FLOAT"
42
-    default="0.5,0.5,0.5,1"
43
-    optional
44
-
45
-option "nodecorations" n "Attempt to select child windows in order to avoid window decorations."
46
-    flag
47
-    off
48
-
49
-option "min" - "Set the minimum output of width or height values. This is useful to avoid outputting 0. Setting min and max to the same value disables drag selections."
50
-    int
51
-    default="0"
52
-    optional
53
-
54
-option "max" - "Set the maximum output of width or height values. Setting min and max to the same value disables drag selections."
55
-    int
56
-    default="0"
57
-    optional
58
-
59
-option "highlight" l "Instead of outlining selections, slop highlights it. This is only useful when --color is set to a transparent color."
60
-    flag
61
-    off
62
-
63
-option "opengl" - "Enable hardware acceleration. Only works with modern systems that are also running a compositor."
64
-    flag
65
-    off
66
-
67
-option "magnify" - "Display a magnifying glass when --opengl is also enabled."
68
-    flag
69
-    off
70
-
71
-option "magstrength" - "Sets how many times the magnification window size is multiplied."
72
-    float
73
-    default="4"
74
-    optional
75
-
76
-option "magpixels" - "Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification."
77
-    int
78
-    default="64"
79
-    optional
80
-
81
-option "theme" - "Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/."
82
-    string
83
-    default="none"
84
-    optional
85
-
86
-option "shader" - "Sets the shader to load and use from ~/.config/slop/ or /usr/share/."
87
-    string
88
-    default="simple"
89
-    optional
90
-
91
-option "format" f "Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c."
92
-    string
93
-    default="REPLACEME"
94
-    optional
95
-
96
-text "\nExamples\n"
97
-text "    $ # Gray, thick, transparent border for maximum visiblity.\n"
98
-text "    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n"
99
-text "\n"
100
-text "    $ # Remove window decorations.\n"
101
-text "    $ slop --nodecorations\n"
102
-text "\n"
103
-text "    $ # Disable window selections. Useful for selecting individual pixels.\n"
104
-text "    $ slop -t 0\n"
105
-text "\n"
106
-text "    $ # Classic Windows XP selection.\n"
107
-text "    $ slop -l -c 0.3,0.4,0.6,0.4\n"
108
-text "\n"
109
-text "    $ # Wiggle wiggle!\n"
110
-text "    $ slop --opengl --shader wiggle\n"
111
-text "\n"
112
-text "    $ # Edgy textures or something.\n"
113
-text "    $ slop --opengl --theme gothic\n"
114
-text "\n"
115
-text "    $ # Change output format to use safer parsing\n"
116
-text "    $ slopoutput=$(slop -f \"%x %y %w %h\")\n"
117
-text "    $ X=$(echo $slopoutput | awk '{print $1}')\n"
118
-text "    $ Y=$(echo $slopoutput | awk '{print $2}')\n"
119
-text "    $ W=$(echo $slopoutput | awk '{print $3}')\n"
120
-text "    $ H=$(echo $slopoutput | awk '{print $4}')\n"
121
-
122
-text "\nTips\n"
123
-text "    * You can use the arrow keys to move the starting point of a drag-selection, just in case you missed it by a few pixels.\n"
124
-text "    * If you don't like a selection: you can cancel it by right-clicking regardless of which options are enabled or disabled for slop.\n"
125
-text "    * If slop doesn't seem to select a window accurately, the problem could be because of decorations getting in the way. Try enabling the --nodecorations flag.\n"

+ 61
- 0
src/options.hpp Просмотреть файл

@@ -0,0 +1,61 @@
1
+/* options.hpp: parses arguments from the commandline.
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#ifndef N_OPTIONS_H_
22
+#define N_OPTIONS_H_
23
+
24
+#include <iostream>
25
+#include <string>
26
+#include <exception>
27
+#include <stdexcept>
28
+#include <vector>
29
+#include <glm/glm.hpp>
30
+
31
+class Argument {
32
+public:
33
+    std::string name;
34
+    char cname;
35
+    bool isFlagArgument;
36
+    Argument( std::string name, char cname, bool isFlagArgument ) : name(name), cname(cname), isFlagArgument(isFlagArgument) {}
37
+};
38
+
39
+static std::vector<Argument> validArguments;
40
+static unsigned int maxFloatingValues = 0;
41
+
42
+class Options {
43
+private:
44
+    std::vector<std::string> arguments;
45
+    std::vector<std::string> values;
46
+    std::vector<std::string> floatingValues;
47
+    int parseCharOption( int argc, char** argv, int argumentIndex, int validIndex );
48
+    int parseStringOption( int argc, char** argv, int argumentIndex, int validIndex );
49
+    int validateStringOption( int argc, char** argv, int argumentIndex );
50
+    int validateCharOption( int argc, char** argv, int argumentIndex );
51
+    void validate( int argc, char** argv );
52
+public:
53
+    Options( int argc, char** argv );
54
+    bool getFloat( std::string name, char namec, float& found );
55
+    bool getInt( std::string name, char namec, int& found );
56
+    bool getString( std::string name, char namec, std::string& found );
57
+    bool getColor( std::string name, char namec, glm::vec4& found );
58
+    bool getBool( std::string name, char namec, bool& found );
59
+};
60
+
61
+#endif // N_OPTIONS_H_

+ 13
- 0
src/rectangle.cpp Просмотреть файл

@@ -0,0 +1,13 @@
1
+#include "rectangle.hpp"
2
+
3
+slop::Rectangle::Rectangle() {
4
+}
5
+slop::Rectangle::~Rectangle() {
6
+}
7
+void slop::Rectangle::setPoints( glm::vec2 p1, glm::vec2 p2 ) {
8
+}
9
+void slop::Rectangle::draw(glm::mat4& matrix) {
10
+}
11
+glm::vec4 slop::Rectangle::getRect() {
12
+    return glm::vec4();
13
+}

+ 39
- 0
src/rectangle.hpp Просмотреть файл

@@ -0,0 +1,39 @@
1
+/* rectangle.hpp: Rectangle generic
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#ifndef N_RECTANGLE_H_
22
+#define N_RECTANGLE_H_
23
+
24
+#include <glm/glm.hpp>
25
+
26
+namespace slop {
27
+
28
+class Rectangle {
29
+public:
30
+    Rectangle();
31
+    virtual glm::vec4 getRect();
32
+    virtual ~Rectangle();
33
+    virtual void setPoints( glm::vec2 p1, glm::vec2 p2 );
34
+    virtual void draw(glm::mat4& matrix);
35
+};
36
+
37
+}
38
+
39
+#endif // N_RECTANGLE_H_

+ 9
- 26
src/resource.cpp Просмотреть файл

@@ -1,4 +1,4 @@
1
-/* resource.cpp: Handles getting resources like textures and stuff.
1
+/* resource.cpp: Handles converting local paths to full paths.
2 2
  *
3 3
  * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4 4
  *
@@ -20,52 +20,35 @@
20 20
 
21 21
 #include "resource.hpp"
22 22
 
23
-slop::Resource* resource = new slop::Resource();
24
-
25 23
 slop::Resource::Resource() {
26 24
     // Find the configuration directory.
27 25
     // usually ~/.config/slop and /usr/share/slop
28 26
     char* config = getenv( "XDG_CONFIG_HOME" );
29 27
     if ( config == NULL ) {
30 28
         char* home = getpwuid(getuid())->pw_dir;
31
-        m_usrconfig += home;
32
-        m_usrconfig += "/.config/slop/";
33
-        m_sysconfig = INSTALL_PREFIX;
34
-        m_sysconfig += "/share/slop/";
29
+        usrconfig += home;
30
+        usrconfig += "/.config/slop/";
35 31
         return;
36 32
     }
37
-    m_usrconfig += config;
38
-    m_usrconfig += "/slop/";
39
-    m_sysconfig = INSTALL_PREFIX;
40
-    m_sysconfig += "/share/slop/";
33
+    usrconfig += config;
34
+    usrconfig += "/slop/";
41 35
 }
42 36
 
43 37
 std::string slop::Resource::getRealPath( std::string localpath ) {
44
-    if ( validatePath( m_usrconfig + localpath ) ) {
45
-        return m_usrconfig + localpath;
46
-    }
47
-    if ( validatePath( m_sysconfig + localpath ) ) {
48
-        return m_sysconfig + localpath;
38
+    if ( validatePath( usrconfig + localpath ) ) {
39
+        return usrconfig + localpath;
49 40
     }
50
-    std::string err = "The file or folder " + localpath + " was not found in either " + m_sysconfig + " or " + m_usrconfig + "\n";
51
-    throw err;
41
+    std::string err = "The file or folder " + localpath + " was not found in " + usrconfig + "\n";
42
+    throw new std::runtime_error(err);
52 43
     return localpath;
53 44
 }
54 45
 
55 46
 bool slop::Resource::validatePath( std::string path ) {
56
-
57 47
     struct stat st;
58
-
59 48
     const char* dirname = path.c_str();
60 49
     if ( stat( dirname, &st ) != 0 ) {
61 50
         return false;
62 51
     }
63
-    // No read permissions.
64
-    //if ( !(st.st_mode & S_IROTH) &&
65
-         //(st.st_uid != getuid() || !(st.st_mode & S_IRUSR)) &&
66
-         //(st.st_gid != getgid() || !(st.st_mode & S_IRGRP)) ) {
67
-        //return false;
68
-    //}
69 52
     // Lookin' good!
70 53
     return true;
71 54
 }

+ 9
- 11
src/resource.hpp Просмотреть файл

@@ -18,9 +18,10 @@
18 18
  * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19 19
  */
20 20
 
21
-#ifndef IS_RESOURCE_H_
22
-#define IS_RESOURCE_H_
21
+#ifndef N_RESOURCE_H_
22
+#define N_RESOURCE_H_
23 23
 
24
+#include <stdexcept>
24 25
 #include <stdlib.h>
25 26
 #include <cassert>
26 27
 #include <cstdio>
@@ -36,18 +37,15 @@ namespace slop {
36 37
 
37 38
 class Resource {
38 39
 public:
39
-
40
-                    Resource();
41
-                    ~Resource();
42
-    std::string     getRealPath( std::string localpath );
43
-    bool            validatePath( std::string path );
40
+    Resource();
41
+    std::string getRealPath( std::string localpath );
44 42
 private:
45
-    std::string     m_usrconfig;
46
-    std::string     m_sysconfig;
43
+    bool validatePath( std::string path );
44
+    std::string usrconfig;
47 45
 };
48 46
 
49
-}
47
+extern Resource* resource;
50 48
 
51
-extern slop::Resource* resource;
49
+}
52 50
 
53 51
 #endif // IS_RESOURCE_H_

+ 60
- 67
src/shader.cpp Просмотреть файл

@@ -1,55 +1,67 @@
1 1
 #include "shader.hpp"
2 2
 
3
-slop::Shader::Shader( std::string name, std::string vert, std::string frag, std::string type ) {
4
-    m_name = name;
5
-    // Set up the type of the shader, this is read by render to know what kind of matricies it needs.
6
-    if ( type == "perspective" ) {
7
-        m_type = 0;
8
-    } else if ( type == "orthographic" ) {
9
-        m_type = 1;
3
+slop::Shader::Shader( std::string vert, std::string frag, bool file ) {
4
+    std::string vert_contents;
5
+    std::string frag_contents;
6
+    if ( file ) {
7
+        vert = resource->getRealPath(vert);
8
+        frag = resource->getRealPath(frag);
9
+        std::ifstream v( vert.c_str() );
10
+        vert_contents = std::string((std::istreambuf_iterator<char>(v)),
11
+                                   std::istreambuf_iterator<char>());
12
+        std::ifstream f( frag.c_str() );
13
+        frag_contents = std::string((std::istreambuf_iterator<char>(f)),
14
+                                  std::istreambuf_iterator<char>());
10 15
     } else {
11
-        m_type = -1;
16
+        vert_contents = vert;
17
+        frag_contents = frag;
12 18
     }
13
-    m_good = false;
14
-    // Create the program to link to.
15
-    m_program = glCreateProgram();
16
-
17
-    std::ifstream v( vert.c_str() );
18
-    std::string vert_contents((std::istreambuf_iterator<char>(v)),
19
-                               std::istreambuf_iterator<char>());
20
-    std::ifstream f( frag.c_str() );
21
-    std::string frag_contents((std::istreambuf_iterator<char>(f)),
22
-                              std::istreambuf_iterator<char>());
23 19
 
24 20
     const char* vertsrc = vert_contents.c_str();
25 21
     const char* fragsrc = frag_contents.c_str();
26 22
 
23
+    // Create the program to link to.
24
+    program = glCreateProgram();
25
+    
26
+    if ( vert_contents.length() <= 0 ) {
27
+        std::string errstring = "Failed to open file (or is empty) `" + vert + "`.\n";
28
+        throw new std::runtime_error(errstring);
29
+    }
30
+
31
+    if ( frag_contents.length() <= 0 ) {
32
+        std::string errstring = "Failed to open file (or is empty) `" + frag + "`.\n";
33
+        throw new std::runtime_error(errstring);
34
+    }
35
+
27 36
     // Compile both shaders.
28 37
     unsigned int vertShader = glCreateShader( GL_VERTEX_SHADER );
29 38
     glShaderSource( vertShader, 1, &vertsrc , NULL );
30
-    int err = compile( vertShader );
39
+    std::string errortxt;
40
+    int err = compile( vertShader, errortxt );
31 41
 
32 42
     if ( err ) {
33
-        fprintf( stderr, "Failed to compile shader %s.\n", vert.c_str() );
43
+        std::string errstring = "Failed to compile shader `" + vert + "`:\n" + errortxt;
44
+        throw new std::runtime_error(errstring);
34 45
         glDeleteShader( vertShader );
35 46
         return;
36 47
     }
37 48
 
38 49
     unsigned int fragShader = glCreateShader( GL_FRAGMENT_SHADER );
39 50
     glShaderSource( fragShader, 1, &fragsrc, NULL );
40
-    err = compile( fragShader );
51
+    err = compile( fragShader, errortxt );
41 52
     if ( err ) {
42
-        fprintf( stderr, "Failed to compile shader %s.\n", frag.c_str() );
53
+        std::string errstring = "Failed to compile shader `" + frag + "`:\n" + errortxt;
54
+        throw new std::runtime_error(errstring);
43 55
         glDeleteShader( vertShader );
44 56
         glDeleteShader( fragShader );
45 57
         return;
46 58
     }
47 59
 
48
-
49 60
     // Then attempt to link them to this shader.
50
-    err = link( vertShader, fragShader );
61
+    err = link( vertShader, fragShader, errortxt );
51 62
     if ( err ) {
52
-        fprintf( stderr, "Failed to link shader %s.\n", name.c_str() );
63
+        std::string errstring = "Failed to link shader `" + vert + "` and  `" + frag + "`:\n" + errortxt;
64
+        throw new std::runtime_error(errstring);
53 65
         glDeleteShader( vertShader );
54 66
         glDeleteShader( fragShader );
55 67
         return;
@@ -58,54 +70,53 @@ slop::Shader::Shader( std::string name, std::string vert, std::string frag, std:
58 70
     // Clean up :)
59 71
     glDeleteShader( vertShader );
60 72
     glDeleteShader( fragShader );
61
-    m_good = true;
62 73
     glUseProgram( 0 );
63 74
 }
64 75
 
65 76
 slop::Shader::~Shader() {
66
-    glDeleteProgram( m_program );
77
+    glDeleteProgram( program );
67 78
 }
68 79
 
69 80
 unsigned int slop::Shader::getProgram() {
70
-    return m_program;
81
+    return program;
71 82
 }
72 83
 
73 84
 void slop::Shader::bind() {
74
-    glUseProgram( m_program );
85
+    glUseProgram( program );
75 86
 }
76 87
 
77
-int slop::Shader::compile( unsigned int shader ) {
88
+int slop::Shader::compile( unsigned int shader, std::string& error ) {
78 89
     glCompileShader( shader );
79 90
 
80 91
     // Compiling the shader is the easy part, all this junk down here is for printing the error it might generate.
81
-    int result;
92
+    int result = GL_FALSE;
82 93
     int logLength;
83 94
     glGetShaderiv( shader, GL_COMPILE_STATUS, &result );
84 95
     glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLength );
85 96
     if ( result == GL_FALSE ) {
86 97
         char* errormsg = new char[ logLength ];
87 98
         glGetShaderInfoLog( shader, logLength, NULL, errormsg );
88
-        fprintf( stderr, "%s\n", errormsg );
99
+        error = errormsg;
89 100
         delete[] errormsg;
90 101
         return 1;
91 102
     }
92 103
     return 0;
93 104
 }
94 105
 
95
-int slop::Shader::link( unsigned int vertshader, unsigned int fragshader ) {
96
-    glAttachShader( m_program, vertshader );
97
-    glAttachShader( m_program, fragshader );
98
-    glLinkProgram( m_program );
106
+int slop::Shader::link( unsigned int vertshader, unsigned int fragshader, std::string& error ) {
107
+    glAttachShader( program, vertshader );
108
+    glAttachShader( program, fragshader );
109
+    glLinkProgram( program );
99 110
 
100 111
     // Linking the shader is the easy part, all this junk down here is for printing the error it might generate.
101
-    int result;
112
+    int result = GL_FALSE;
102 113
     int logLength;
103
-    glGetProgramiv( m_program, GL_LINK_STATUS, &result);
104
-    glGetProgramiv( m_program, GL_INFO_LOG_LENGTH, &logLength);
114
+    glGetProgramiv( program, GL_LINK_STATUS, &result);
115
+    glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logLength);
105 116
     if ( result == GL_FALSE ) {
106 117
         char* errormsg = new char[ logLength ];
107
-        glGetProgramInfoLog( m_program, logLength, NULL, errormsg );
108
-        fprintf( stderr, "%s\n", errormsg );
118
+        glGetProgramInfoLog( program, logLength, NULL, errormsg );
119
+        error = errormsg;
109 120
         delete[] errormsg;
110 121
         return 1;
111 122
     }
@@ -113,60 +124,42 @@ int slop::Shader::link( unsigned int vertshader, unsigned int fragshader ) {
113 124
 }
114 125
 
115 126
 unsigned int slop::Shader::getUniformLocation( std::string name ) {
116
-    if ( !m_good ) {
117
-        return 0;
118
-    }
119
-    glUseProgram( m_program );
120
-    return glGetUniformLocation( m_program, name.c_str() );
127
+    glUseProgram( program );
128
+    return glGetUniformLocation( program, name.c_str() );
121 129
 }
122 130
 
123 131
 void slop::Shader::setParameter( std::string name, int foo ) {
124
-    if ( !m_good ) {
125
-        return;
126
-    }
127 132
     glUniform1i( getUniformLocation( name ), foo );
128 133
 }
129 134
 
130 135
 void slop::Shader::setParameter( std::string name, float foo ) {
131
-    if ( !m_good ) {
132
-        return;
133
-    }
134 136
     glUniform1f( getUniformLocation( name ), foo );
135 137
 }
136 138
 
137
-void slop::Shader::setParameter( std::string name, glm::mat4 foo ) {
138
-    if ( !m_good ) {
139
-        return;
140
-    }
139
+void slop::Shader::setParameter( std::string name, glm::mat4& foo ) {
141 140
     glUniformMatrix4fv( getUniformLocation( name ), 1, GL_FALSE, glm::value_ptr( foo ) );
142 141
 }
143 142
 
144 143
 void slop::Shader::setParameter( std::string name, glm::vec4 foo ) {
145
-    if ( !m_good ) {
146
-        return;
147
-    }
148 144
     glUniform4f( getUniformLocation( name ), foo.x, foo.y, foo.z, foo.w );
149 145
 }
150 146
 
151 147
 void slop::Shader::setParameter( std::string name, glm::vec2 foo ) {
152
-    if ( !m_good ) {
153
-        return;
154
-    }
155 148
     glUniform2f( getUniformLocation( name ), foo.x, foo.y );
156 149
 }
157 150
 
158 151
 void slop::Shader::setAttribute( std::string name, unsigned int buffer, unsigned int stepsize ) {
159
-    unsigned int a = glGetAttribLocation( m_program, name.c_str() );
152
+    unsigned int a = glGetAttribLocation( program, name.c_str() );
160 153
     glEnableVertexAttribArray( a );
161 154
     glBindBuffer( GL_ARRAY_BUFFER, buffer );
162 155
     glVertexAttribPointer( a, stepsize, GL_FLOAT, GL_FALSE, 0, NULL );
163
-    m_activeattribs.push_back( a );
156
+    activeAttributes.push_back( a );
164 157
 }
165 158
 
166 159
 void slop::Shader::unbind() {
167
-    for ( unsigned int i=0; i<m_activeattribs.size(); i++ ) {
168
-        glDisableVertexAttribArray( m_activeattribs[i] );
160
+    for ( unsigned int i=0; i<activeAttributes.size(); i++ ) {
161
+        glDisableVertexAttribArray( activeAttributes[i] );
169 162
     }
170
-    m_activeattribs.clear();
163
+    activeAttributes.clear();
171 164
     glUseProgram( 0 );
172 165
 }

+ 38
- 24
src/shader.hpp Просмотреть файл

@@ -1,48 +1,62 @@
1
-// shader.hpp: Loads shaders into opengl
1
+/* shader.hpp: Handles compiling shaders.
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
2 20
 
3
-#ifndef IS_SHADER_H_
4
-#define IS_SHADER_H_
21
+#ifndef N_SHADER_H_
22
+#define N_SHADER_H_
5 23
 
6
-#include <string>
7
-#include <cstdio>
24
+#include <fstream>
8 25
 #include <vector>
9
-#ifdef OPENGL_ENABLED
26
+#include <string>
27
+#include <exception>
28
+
29
+#include "gl_core_3_3.h"
10 30
 #include <glm/glm.hpp>
11 31
 #include <glm/gtc/type_ptr.hpp>
12
-#include <GL/glew.h>
13
-#endif
14
-#include <string>
15
-#include <fstream>
16
-#include <streambuf>
32
+#include <EGL/egl.h>
33
+#include <GL/gl.h>
34
+
35
+#include "resource.hpp"
17 36
 
18 37
 namespace slop {
19 38
 
20 39
 class Shader {
21 40
 public:
22
-    Shader( std::string name, std::string vert, std::string frag, std::string shadertype = "other" );
41
+    Shader( std::string vert, std::string frag, bool file = true );
23 42
     ~Shader();
24 43
     unsigned int    getProgram();
25
-    std::string     m_name;
26 44
     void            bind();
27 45
     void            unbind();
28 46
     void            setParameter( std::string name, int foo );
29 47
     void            setParameter( std::string name, float foo );
30
-#ifdef OPENGL_ENABLED
31
-    void            setParameter( std::string name, glm::mat4 foo );
48
+    void            setParameter( std::string name, glm::mat4& foo );
32 49
     void            setParameter( std::string name, glm::vec4 foo );
33 50
     void            setParameter( std::string name, glm::vec2 foo );
34
-#endif
35 51
     void            setAttribute( std::string name, unsigned int buffer, unsigned int stepsize );
36
-    int             m_type;
37 52
 private:
38
-    std::vector<unsigned int>   m_activeattribs;
39
-    bool                        m_good;
53
+    std::vector<unsigned int>   activeAttributes;
40 54
     unsigned int                getUniformLocation( std::string );
41
-    int                         compile( unsigned int shader );
42
-    int                         link( unsigned int vert, unsigned int frag );
43
-    unsigned int                m_program;
55
+    int                         compile( unsigned int shader, std::string& error );
56
+    int                         link( unsigned int vert, unsigned int frag, std::string& error );
57
+    unsigned int                program;
44 58
 };
45 59
 
46
-};
60
+}
47 61
 
48
-#endif // IS_SHADER_H_
62
+#endif // N_SHADER_H_

+ 202
- 0
src/slop.cpp Просмотреть файл

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

+ 60
- 0
src/slop.hpp Просмотреть файл

@@ -0,0 +1,60 @@
1
+/* glslop.hpp: exposes an opengl selection interface
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#ifndef N_SLOP_H_
22
+#define N_SLOP_H_
23
+
24
+#include <string>
25
+
26
+namespace slop {
27
+
28
+class SlopOptions {
29
+public:
30
+    SlopOptions();
31
+    float borderSize;
32
+    float padding;
33
+    float tolerance;
34
+    bool highlight;
35
+    bool nokeyboard;
36
+    int nodecorations;
37
+    std::string shader;
38
+    float r;
39
+    float g;
40
+    float b;
41
+    float a;
42
+    std::string xdisplay;
43
+};
44
+
45
+class SlopSelection {
46
+public:
47
+    SlopSelection( float x, float y, float w, float h, int id );
48
+    float x;
49
+    float y;
50
+    float w;
51
+    float h;
52
+// This is an X11 Window ID
53
+    int id;
54
+};
55
+
56
+SlopSelection SlopSelect( SlopOptions* options = NULL, bool* cancelled = NULL, bool quiet = false );
57
+
58
+}
59
+
60
+#endif // N_SLOP_H_

+ 122
- 0
src/slopstates.cpp Просмотреть файл

@@ -0,0 +1,122 @@
1
+#include "slopstates.hpp"
2
+
3
+using namespace slop;
4
+
5
+slop::SlopMemory::SlopMemory( SlopOptions* options, Rectangle* rect ) {
6
+    running = true;
7
+    state = (SlopState*)new SlopStart();
8
+    nextState = NULL;
9
+    tolerance = options->tolerance;
10
+    nodecorations = options->nodecorations;
11
+    rectangle = rect;
12
+    selectedWindow = x11->root;
13
+    state->onEnter( *this );
14
+}
15
+
16
+slop::SlopMemory::~SlopMemory() {
17
+    delete state;
18
+    if ( nextState ) {
19
+        delete nextState;
20
+    }
21
+    delete rectangle;
22
+}
23
+
24
+void slop::SlopMemory::update( double dt ) {
25
+    state->update( *this, dt );
26
+    if ( nextState ) {
27
+        state->onExit( *this );
28
+        delete state;
29
+        state = nextState;
30
+        state->onEnter( *this );
31
+        nextState = NULL;
32
+    }
33
+}
34
+
35
+void slop::SlopMemory::setState( SlopState* state ) {
36
+    if ( nextState ) {
37
+        delete nextState;
38
+    }
39
+    nextState = state;
40
+}
41
+
42
+void slop::SlopMemory::draw( glm::mat4& matrix ) {
43
+    state->draw( *this, matrix );
44
+}
45
+
46
+
47
+slop::SlopState::~SlopState() {
48
+}
49
+void slop::SlopState::onEnter( SlopMemory& memory ) {
50
+}
51
+void slop::SlopState::onExit( SlopMemory& memory ) {
52
+}
53
+void slop::SlopState::update( SlopMemory& memory, double dt ) {
54
+}
55
+void slop::SlopState::draw( SlopMemory& memory, glm::mat4 matrix ) {
56
+}
57
+
58
+void slop::SlopStart::onEnter( SlopMemory& memory ) {
59
+    setStartPos = false;
60
+}
61
+void slop::SlopStart::update( SlopMemory& memory, double dt ) {
62
+    if ( mouse->getButton( 1 ) && !setStartPos ) {
63
+        startPos = mouse->getMousePos();
64
+        setStartPos = true;
65
+    }
66
+    if ( setStartPos && glm::distance( startPos, mouse->getMousePos() ) >= memory.tolerance ) {
67
+        memory.setState( (SlopState*)new SlopStartDrag( startPos ) );
68
+    }
69
+    if ( mouse->hoverWindow != None ) {
70
+        glm::vec4 rect = getWindowGeometry( mouse->hoverWindow, memory.nodecorations );
71
+        memory.rectangle->setPoints( glm::vec2( (float)rect.x, (float)rect.y ), glm::vec2( (float)rect.x+rect.z, (float)rect.y+rect.w ) );
72
+    }
73
+    if ( setStartPos && !mouse->getButton( 1 ) ) {
74
+        memory.selectedWindow = mouse->hoverWindow;
75
+        memory.setState( (SlopState*)new SlopEndDrag() );
76
+    }
77
+}
78
+
79
+void slop::SlopStart::draw( SlopMemory& memory, glm::mat4 matrix ) {
80
+    if ( memory.tolerance > 0 ) {
81
+        memory.rectangle->draw( matrix );
82
+    }
83
+}
84
+
85
+slop::SlopStartDrag::SlopStartDrag( glm::vec2 point ) {
86
+    startPoint = point;
87
+}
88
+
89
+void slop::SlopStartDrag::onEnter( SlopMemory& memory ) {
90
+    memory.rectangle->setPoints(startPoint, startPoint);
91
+}
92
+
93
+void slop::SlopStartDrag::update( SlopMemory& memory, double dt ) {
94
+    char a = startPoint.y > mouse->getMousePos().y;
95
+    char b = startPoint.x > mouse->getMousePos().x;
96
+    char c = (a << 1) | b;
97
+    switch ( c ) {
98
+        case 0: mouse->setCursor( XC_lr_angle );
99
+                memory.rectangle->setPoints(startPoint+glm::vec2(0,0), mouse->getMousePos()+glm::vec2(1,1));
100
+                break;
101
+        case 1: mouse->setCursor( XC_ll_angle );
102
+                memory.rectangle->setPoints(startPoint+glm::vec2(0,0), mouse->getMousePos()+glm::vec2(1,1));
103
+                break;
104
+        case 2: mouse->setCursor( XC_ur_angle );
105
+                memory.rectangle->setPoints(startPoint+glm::vec2(0,1), mouse->getMousePos()+glm::vec2(1,0));
106
+                break;
107
+        case 3: mouse->setCursor( XC_ul_angle );
108
+                memory.rectangle->setPoints(startPoint+glm::vec2(1,1), mouse->getMousePos()+glm::vec2(0,0));
109
+                break;
110
+    }
111
+    if ( !mouse->getButton( 1 ) ) {
112
+        memory.setState( (SlopState*)new SlopEndDrag() );
113
+    }
114
+}
115
+
116
+void slop::SlopStartDrag::draw( SlopMemory& memory, glm::mat4 matrix ) {
117
+    memory.rectangle->draw( matrix );
118
+}
119
+
120
+void slop::SlopEndDrag::onEnter( SlopMemory& memory ) {
121
+    memory.running = false;
122
+}

+ 87
- 0
src/slopstates.hpp Просмотреть файл

@@ -0,0 +1,87 @@
1
+/* slopstates.hpp: State machine stuffs.
2
+ *
3
+ * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
+ *
5
+ * This file is part of Slop.
6
+ *
7
+ * Slop is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * Slop is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#ifndef N_SLOPSTATES_H_
22
+#define N_SLOPSTATES_H_
23
+
24
+#include "mouse.hpp"
25
+#include "slop.hpp"
26
+
27
+#include "rectangle.hpp"
28
+
29
+namespace slop {
30
+
31
+class SlopMemory;
32
+class SlopOptions;
33
+
34
+class SlopState {
35
+public:
36
+    virtual ~SlopState();
37
+    virtual void onEnter( SlopMemory& memory );
38
+    virtual void onExit( SlopMemory& memory );
39
+    virtual void update( SlopMemory& memory, double dt );
40
+    virtual void draw( SlopMemory& memory, glm::mat4 matrix );
41
+};
42
+
43
+class SlopStart : SlopState {
44
+private:
45
+    bool setStartPos;
46
+    glm::vec2 startPos;
47
+public:
48
+    virtual void onEnter( SlopMemory& memory );
49
+    virtual void update( SlopMemory& memory, double dt );
50
+    virtual void draw( SlopMemory& memory, glm::mat4 matrix );
51
+};
52
+
53
+class SlopStartDrag : SlopState {
54
+private:
55
+    glm::vec2 startPoint;
56
+public:
57
+    SlopStartDrag( glm::vec2 point );
58
+    virtual void onEnter( SlopMemory& memory );
59
+    virtual void update( SlopMemory& memory, double dt );
60
+    virtual void draw( SlopMemory& memory, glm::mat4 matrix );
61
+};
62
+
63
+class SlopEndDrag : SlopState {
64
+public:
65
+    virtual void onEnter( SlopMemory& memory );
66
+};
67
+
68
+class SlopMemory {
69
+private:
70
+    SlopState* state;
71
+    SlopState* nextState;
72
+public:
73
+    SlopMemory( SlopOptions* options, Rectangle* rect );
74
+    ~SlopMemory();
75
+    Window selectedWindow;
76
+    bool running;
77
+    float tolerance;
78
+    bool nodecorations;
79
+    Rectangle* rectangle;
80
+    void setState( SlopState* state );
81
+    void update( double dt );
82
+    void draw( glm::mat4& matrix );
83
+};
84
+
85
+}
86
+
87
+#endif // N_SLOPSTATES_H_

+ 94
- 0
src/window.cpp Просмотреть файл

@@ -0,0 +1,94 @@
1
+#include "window.hpp"
2
+
3
+using namespace slop;
4
+
5
+slop::SlopWindow::SlopWindow() {
6
+    XVisualInfo visual;
7
+    XMatchVisualInfo(x11->display, DefaultScreen(x11->display), 32, TrueColor, &visual);
8
+
9
+    XSetWindowAttributes attributes;
10
+    attributes.colormap = XCreateColormap( x11->display, x11->root, visual.visual, AllocNone );
11
+    attributes.background_pixmap = None;
12
+    attributes.border_pixel = 0;
13
+    // Disable window decorations.
14
+    attributes.override_redirect = True;
15
+    // Make sure we know when we've been successfully destroyed later!
16
+    //attributes.event_mask = StructureNotifyMask;
17
+    unsigned long valueMask = CWOverrideRedirect | CWColormap | CWBackPixmap | CWBorderPixel;
18
+
19
+
20
+    // Create the window
21
+    window = XCreateWindow( slop::x11->display, x11->root, 0, 0, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ),
22
+                            0, visual.depth, InputOutput,
23
+                            visual.visual, valueMask, &attributes );
24
+
25
+    if ( !window ) {
26
+        throw new std::runtime_error( "Couldn't create a GL window!" );
27
+    }
28
+
29
+	// Prep some hints for the window
30
+    static char title[] = "slop";
31
+    XWMHints* startup_state = XAllocWMHints();
32
+    startup_state->initial_state = NormalState;
33
+    startup_state->flags = StateHint;
34
+    XTextProperty textprop;
35
+    textprop.value = (unsigned char*)title;
36
+    textprop.encoding = XA_STRING;
37
+    textprop.format = 8;
38
+    textprop.nitems = strlen( title );
39
+    XSizeHints sizehints;
40
+    sizehints.x = 0;
41
+    sizehints.y = 0;
42
+    sizehints.width = WidthOfScreen( x11->screen );
43
+    sizehints.height = HeightOfScreen( x11->screen );
44
+    sizehints.flags = USPosition | USSize;
45
+    XClassHint classhints;
46
+    char name[] = "slop";
47
+    classhints.res_name = name;
48
+    classhints.res_class = name;
49
+	// Finally send it all over...
50
+    XSetClassHint( x11->display, window, &classhints );
51
+    XSetWMProperties( x11->display, window, &textprop, &textprop, NULL, 0, &sizehints, startup_state, NULL );
52
+    XFree( startup_state );
53
+
54
+    // Load up a opengl context
55
+    context = glXCreateContext( x11->display, &visual, 0, True );
56
+    if ( !context ) {
57
+		throw new std::runtime_error( "Failed to create an OpenGL context." );
58
+    }
59
+    setCurrent();
60
+    // Finally we grab some OpenGL 3.3 stuffs.
61
+    if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
62
+    {
63
+        throw new std::runtime_error("Failed to load function pointers for OpenGL.");
64
+    }
65
+    framebuffer = new Framebuffer( WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ) );
66
+
67
+    glViewport( 0, 0, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ) );
68
+    camera = glm::ortho( 0.0f, (float)WidthOfScreen( x11->screen ), (float)HeightOfScreen( x11->screen ), 0.0f, -1.0f, 1.0f);
69
+
70
+    // Last, we actually display the window <:o)
71
+	XMapWindow( x11->display, window );
72
+}
73
+
74
+slop::SlopWindow::~SlopWindow() {
75
+    delete framebuffer;
76
+    // Try to erase the window before destroying it.
77
+    glClearColor( 0, 0, 0, 0 );
78
+    glClear( GL_COLOR_BUFFER_BIT );
79
+    display();
80
+    glClearColor( 0, 0, 0, 0 );
81
+    glClear( GL_COLOR_BUFFER_BIT );
82
+    display();
83
+    glXDestroyContext( x11->display, context );
84
+    XDestroyWindow( x11->display, window );
85
+}
86
+
87
+void slop::SlopWindow::display() {
88
+    glXSwapBuffers( x11->display, window );
89
+    glXWaitGL();
90
+}
91
+
92
+void slop::SlopWindow::setCurrent() {
93
+    glXMakeCurrent( x11->display, window, context ) ;
94
+}

src/selectrectangle.hpp → src/window.hpp Просмотреть файл

@@ -1,4 +1,4 @@
1
-/* selectrectangle.hpp: Handles creating rectangles on the screen.
1
+/* window.hpp: Spawns and manages windows. By default it creates an OpenGL context with them.
2 2
  *
3 3
  * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4 4
  *
@@ -18,43 +18,38 @@
18 18
  * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19 19
  */
20 20
 
21
-#ifndef IS_SELECT_RECTANGLE_H_
22
-#define IS_SELECT_RECTANGLE_H_
21
+#ifndef N_WINDOW_H_
22
+#define N_WINDOW_H_
23 23
 
24
-#include "x.hpp"
25
-#include "selectrectangle.hpp"
26
-#include "shader.hpp"
27
-
28
-#include <unistd.h>
29
-
30
-#include <X11/Xlib.h>
31
-#include <X11/extensions/shape.h>
24
+#include <string>
25
+#include <exception>
26
+
27
+#include <iostream>
28
+#include "gl_core_3_3.h"
29
+#include <GL/gl.h>
30
+#include <GL/glx.h>
31
+#include <glm/gtc/matrix_transform.hpp>
32
+#include <X11/Xutil.h>
32 33
 #include <X11/Xatom.h>
33 34
 
34
-#include <cstdlib>
35
-#include <cmath>
36
-#include <cstdio>
37
-#include <string>
38
-#include <vector>
35
+#include "x.hpp"
36
+#include "framebuffer.hpp"
39 37
 
40 38
 namespace slop {
41 39
 
42
-class SelectRectangle {
40
+class SlopWindow {
43 41
 public:
44
-    virtual ~SelectRectangle();
45
-    virtual void    setGeo( int x, int y, int w, int h );
46
-    virtual void    update( double dt );
47
-    Window          m_window;
48
-    int             m_x;
49
-    int             m_y;
50
-    int             m_width;
51
-    int             m_height;
52
-    int             m_border;
53
-    bool            m_highlight;
42
+    Framebuffer* framebuffer;
43
+    int width, height;
44
+    glm::mat4 camera;
45
+    GLXWindow window;
46
+    GLXContext context;
47
+    SlopWindow();
48
+    ~SlopWindow();
49
+    void setCurrent();
50
+    void display();
54 51
 };
55 52
 
56
-bool isSelectRectangleSupported();
57
-
58 53
 }
59 54
 
60
-#endif // IS_SELECT_RECTANGLE_H_
55
+#endif // N_WINDOW_H_

+ 52
- 445
src/x.cpp Просмотреть файл

@@ -1,453 +1,60 @@
1
-/* x.cpp: Handles starting and managing X.
2
- *
3
- * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
- *
5
- * This file is part of Slop.
6
- *
7
- * Slop is free software: you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, either version 3 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * Slop is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
- */
20 1
 #include "x.hpp"
21 2
 
22
-slop::XEngine* xengine = new slop::XEngine();
3
+using namespace slop;
23 4
 
24
-int slop::XEngineErrorHandler( Display* dpy, XErrorEvent* event ) {
25
-    // Ignore XGrabKeyboard BadAccess errors, we can work without it.
26
-    // 31 = XGrabKeyboard's request code
27
-    if ( event->request_code == 31 && event->error_code == BadAccess ) {
28
-        fprintf( stderr, "_X Error \"BadAccess\" for XGrabKeyboard ignored...\n" );
29
-        return EXIT_SUCCESS;
30
-    }
31
-    // Ignore XQueryKeymap BadValue errors, we can work without it.
32
-    // 128 = XShape request code, not sure why XQueryKeymap generates this?
33
-    if ( event->request_code == 128 && event->error_code == BadValue ) {
34
-        fprintf( stderr, "_X Error \"BadValue\" for XQueryKeymap ignored...\n" );
35
-        return EXIT_SUCCESS;
36
-    }
37
-    // Everything else should be fatal as I don't like undefined behavior.
38
-    char buffer[1024];
39
-    XGetErrorText( dpy, event->error_code, buffer, 1024 );
40
-    fprintf( stderr,
41
-             "_X Error of failed request: %s\n_  Error code of failed request: %3d\n_  Major opcode of failed request: %3d\n_  Minor opcode of failed request: %3d\n_  Serial number of failed request: %5li\n_  Current serial number in output stream:?????\n",
42
-             buffer,
43
-             event->error_code,
44
-             event->request_code,
45
-             event->minor_code,
46
-             event->serial );
47
-    exit(1);
48
-}
49
-
50
-unsigned int slop::XEngine::getWidth() {
51
-    if ( !m_good ) {
52
-        return -1;
53
-    }
54
-    return WidthOfScreen( m_screen );
55
-}
56
-
57
-unsigned int slop::XEngine::getHeight() {
58
-    if ( !m_good ) {
59
-        return -1;
60
-    }
61
-    return HeightOfScreen( m_screen );
62
-}
63
-
64
-slop::XEngine::XEngine() {
65
-    m_keypressed = false;
66
-    m_display = NULL;
67
-    m_visual = NULL;
68
-    m_screen = NULL;
69
-    m_good = false;
70
-    m_mousex = -1;
71
-    m_mousey = -1;
72
-    m_hoverWindow = None;
73
-}
74
-
75
-slop::XEngine::~XEngine() {
76
-    if ( !m_good ) {
77
-        return;
78
-    }
79
-    for ( unsigned int i=0; i<m_cursors.size(); i++ ) {
80
-        if ( m_cursors.at( i ) ) {
81
-            XFreeCursor( m_display, m_cursors[i] );
82
-        }
83
-    }
84
-    XCloseDisplay( m_display );
85
-}
86
-
87
-bool slop::XEngine::mouseDown( unsigned int button ) {
88
-    if ( button >= m_mouse.size() ) {
89
-        return false;
90
-    }
91
-    return m_mouse.at( button );
92
-}
93
-
94
-int slop::XEngine::init( std::string display ) {
5
+glm::vec4 slop::getWindowGeometry( Window win, bool removeDecoration) {
6
+    XWindowAttributes attr;         
7
+    XGetWindowAttributes( x11->display, win, &attr );
8
+    unsigned int width = attr.width;           
9
+    unsigned int height = attr.height;         
10
+    unsigned int border = attr.border_width;   
11
+    int x, y;
12
+    Window junk;
13
+    XTranslateCoordinates( x11->display, win, attr.root, -attr.border_width, -attr.border_width, &x, &y, &junk );
14
+    if ( !removeDecoration ) {
15
+        width += border*2;
16
+        height += border*2;
17
+        return glm::vec4( x, y, width, height );
18
+    }
19
+    // This is required to be defined by the window manager, so we can assume it exists.
20
+    Atom actual_type;
21
+    int actual_format;
22
+    unsigned long nitems, bytes_after;
23
+    unsigned char *data;
24
+    int result = XGetWindowProperty(x11->display, win,
25
+                                    XInternAtom(x11->display, "_NET_FRAME_EXTENTS", true),
26
+                                    0, 4, False, AnyPropertyType, 
27
+                                    &actual_type, &actual_format, &nitems, &bytes_after, &data);
28
+    if ( result == Success ) {
29
+        // Make sure we got the data we expect...
30
+        if ((nitems == 4) && (bytes_after == 0)) {
31
+            x += (int)data[0];
32
+            width -= (int)data[1];
33
+            y += (int)data[2];
34
+            height -= (int)data[3];
35
+        }
36
+    }
37
+    return glm::vec4( x, y, width, height );
38
+}
39
+
40
+bool X11::hasCompositor() {
41
+    std::stringstream prop_name;
42
+    prop_name << "_NET_WM_CM_S" << XScreenNumberOfScreen( screen );
43
+    Atom prop_atom = XInternAtom(display, prop_name.str().c_str(), False);
44
+    return XGetSelectionOwner(display, prop_atom) != None;
45
+}
46
+
47
+X11::X11( std::string displayName ) {
95 48
     // Initialize display
96
-    m_display = XOpenDisplay( display.c_str() );
97
-    if ( !m_display ) {
98
-        fprintf( stderr, "Error: Failed to open X display %s\n", display.c_str() );
99
-        return EXIT_FAILURE;
49
+    display = XOpenDisplay( displayName.c_str() );
50
+    if ( !display ) {
51
+        throw new std::runtime_error(std::string("Error: Failed to open X display: ") + displayName );
100 52
     }
101
-    m_screen    = ScreenOfDisplay( m_display, DefaultScreen( m_display ) );
102
-    m_visual    = DefaultVisual  ( m_display, XScreenNumberOfScreen( m_screen ) );
103
-    m_colormap  = DefaultColormap( m_display, XScreenNumberOfScreen( m_screen ) );
104
-    //m_root      = RootWindow     ( m_display, XScreenNumberOfScreen( m_screen ) );
105
-    m_root      = DefaultRootWindow( m_display );
106
-
107
-#ifdef OPENGL_ENABLED
108
-    m_res = XRRGetScreenResourcesCurrent( m_display, m_root);
109
-#endif // OPENGL_ENABLED
110
-
111
-    m_good = true;
112
-    XSetErrorHandler( slop::XEngineErrorHandler );
113
-    selectAllInputs( m_root, EnterWindowMask );
114
-    return EXIT_SUCCESS;
53
+    screen = ScreenOfDisplay( display, DefaultScreen( display ) );
54
+    visual = DefaultVisual( display, XScreenNumberOfScreen( screen ) );
55
+    root = DefaultRootWindow( display );
115 56
 }
116 57
 
117
-#ifdef OPENGL_ENABLED
118
-std::vector<XRRCrtcInfo*> slop::XEngine::getCRTCS() {
119
-    std::vector<XRRCrtcInfo*> monitors;
120
-    if ( !m_res ) {
121
-        return monitors;
122
-    }
123
-    for ( int i=0;i<m_res->ncrtc;i++ ) {
124
-        monitors.push_back( XRRGetCrtcInfo( m_display, m_res, m_res->crtcs[ i ] ) );
125
-    }
126
-    return monitors;
127
-}
128
-
129
-void slop::XEngine::freeCRTCS( std::vector<XRRCrtcInfo*> monitors ) {
130
-    for ( unsigned int i=0;i<monitors.size();i++ ) {
131
-        XRRFreeCrtcInfo( monitors[ i ] );
132
-    }
133
-}
134
-#endif // OPENGL_ENABLED
135
-
136
-bool slop::XEngine::keyPressed( KeySym key ) {
137
-    KeyCode keycode = XKeysymToKeycode( m_display, key );
138
-    if ( keycode != 0 ) {
139
-        // Get the whole keyboard state
140
-        char keys[32];
141
-        XQueryKeymap( m_display, keys );
142
-        // Check our keycode
143
-        return ( keys[ keycode / 8 ] & ( 1 << ( keycode % 8 ) ) ) != 0;
144
-    } else {
145
-        return false;
146
-    }
147
-}
148
-
149
-bool slop::XEngine::anyKeyPressed() {
150
-    if ( !m_good ) {
151
-        return false;
152
-    }
153
-    // Thanks to SFML for some reliable key state grabbing.
154
-    // Get the whole keyboard state
155
-    char keys[ 32 ];
156
-    XQueryKeymap( m_display, keys );
157
-    // Each bit indicates a different key, 1 for pressed, 0 otherwise.
158
-    // Every bit should be 0 if nothing is pressed.
159
-    for ( unsigned int i = 0; i < 32; i++ ) {
160
-        if ( keys[ i ] != 0 ) {
161
-            return true;
162
-        }
163
-    }
164
-    return false;
165
-}
166
-
167
-int slop::XEngine::grabKeyboard() {
168
-    if ( !m_good ) {
169
-        return EXIT_FAILURE;
170
-    }
171
-    int err = XGrabKeyboard( m_display, m_root, False, GrabModeAsync, GrabModeAsync, CurrentTime );
172
-    if ( err != GrabSuccess ) {
173
-        fprintf( stderr, "Warning: Failed to grab X keyboard.\n" );
174
-        fprintf( stderr, "         This happens when something has already grabbed your keybaord.\n" );
175
-        fprintf( stderr, "         slop should still run properly though.\n" );
176
-        return EXIT_FAILURE;
177
-    }
178
-    return EXIT_SUCCESS;
179
-}
180
-
181
-int slop::XEngine::releaseKeyboard() {
182
-    if ( !m_good ) {
183
-        return EXIT_FAILURE;
184
-    }
185
-    XUngrabKeyboard( m_display, CurrentTime );
186
-    return EXIT_SUCCESS;
187
-}
188
-
189
-void slop::XEngine::selectAllInputs( Window win, long event_mask) {
190
-    Window root, parent;
191
-    Window* children;
192
-    unsigned int nchildren;
193
-    XQueryTree( m_display, win, &root, &parent, &children, &nchildren );
194
-    for ( unsigned int i=0;i<nchildren;i++ ) {
195
-        XSelectInput( m_display, children[ i ], event_mask );
196
-        selectAllInputs( children[ i ], event_mask );
197
-    }
198
-    free( children );
199
-}
200
-
201
-// Grabs the cursor, be wary that setCursor changes the mouse masks.
202
-// waittime is how long grabCursor can repeatedly try to grab the cursor, if it fails to grab.
203
-// This is because tiling window managers like i3 grab the mouse while holding down certain keys,
204
-// while these certain keys also launch slop.
205
-int slop::XEngine::grabCursor( slop::CursorType type, double waittime ) {
206
-    if ( !m_good ) {
207
-        return EXIT_FAILURE;
208
-    }
209
-    int xfontcursor = makeCursor( type );
210
-    int err = XGrabPointer( m_display, m_root, True,
211
-                            PointerMotionMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask,
212
-                            GrabModeAsync, GrabModeAsync, None, xfontcursor, CurrentTime );
213
-    double accumulationtime = 0;
214
-    int timestep = 10000; // in microseconds
215
-    while ( err != GrabSuccess && accumulationtime < waittime ) {
216
-        err = XGrabPointer( m_display, m_root, True,
217
-                            PointerMotionMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask,
218
-                            GrabModeAsync, GrabModeAsync, None, xfontcursor, CurrentTime );
219
-        usleep( timestep );
220
-        accumulationtime += double( timestep/1000000.f );
221
-    }
222
-    if ( err != GrabSuccess ) {
223
-        fprintf( stderr, "Error: Failed to grab X cursor.\n" );
224
-        switch( err ) {
225
-            case 1:
226
-                fprintf( stderr, "       The cursor is already grabbed by another application.\n" );
227
-                break;
228
-            case 2:
229
-                fprintf( stderr, "       The cursor grab was initiated at an invalid time (in the past?) .\n" );
230
-                break;
231
-            case 3:
232
-                fprintf( stderr, "       The cursor is not viewable or outside of the bounds of the root window.\n" );
233
-                break;
234
-            case 4:
235
-                fprintf( stderr, "       The grab is frozen already by an active grab by another application.\n" );
236
-                break;
237
-            default:
238
-                break;
239
-        }
240
-        fprintf( stderr, "       This can be caused by launching slop weirdly.\n" );
241
-        return EXIT_FAILURE;
242
-    }
243
-    // Quickly set the mouse position so we don't have to worry about x11 generating an event.
244
-    Window root, child;
245
-    int mx, my;
246
-    int wx, wy;
247
-    unsigned int mask;
248
-    XQueryPointer( m_display, m_root, &root, &child, &mx, &my, &wx, &wy, &mask );
249
-    m_mousex = mx;
250
-    m_mousey = my;
251
-
252
-    // Get the deepest available window.
253
-    Window test = child;
254
-    while( test ) {
255
-        child = test;
256
-        XQueryPointer( m_display, child, &root, &test, &mx, &my, &wx, &wy, &mask );
257
-    }
258
-    m_hoverWindow = child;
259
-    return EXIT_SUCCESS;
260
-}
261
-
262
-int slop::XEngine::releaseCursor() {
263
-    if ( !m_good ) {
264
-        return EXIT_FAILURE;
265
-    }
266
-    XUngrabPointer( m_display, CurrentTime );
267
-    return EXIT_SUCCESS;
268
-}
269
-
270
-void slop::XEngine::tick() {
271
-    if ( !m_good ) {
272
-        return;
273
-    }
274
-    XEvent event;
275
-    while ( XPending( m_display ) ) {
276
-        XNextEvent( m_display, &event );
277
-        switch ( event.type ) {
278
-            case MotionNotify: {
279
-                m_mousex = event.xmotion.x;
280
-                m_mousey = event.xmotion.y;
281
-                break;
282
-            }
283
-            case ButtonPress: {
284
-                // Our pitiful mouse manager--
285
-                if ( m_mouse.size() > event.xbutton.button ) {
286
-                    m_mouse.at( event.xbutton.button ) = true;
287
-                } else {
288
-                    m_mouse.resize( event.xbutton.button+2, false );
289
-                    m_mouse.at( event.xbutton.button ) = true;
290
-                }
291
-                break;
292
-            }
293
-            case EnterNotify: {
294
-                if ( event.xcrossing.subwindow != None ) {
295
-                    m_hoverWindow = event.xcrossing.subwindow;
296
-                } else {
297
-                    m_hoverWindow = event.xcrossing.window;
298
-                }
299
-                break;
300
-            }
301
-            case ButtonRelease: {
302
-                if ( m_mouse.size() > event.xbutton.button ) {
303
-                    m_mouse.at( event.xbutton.button ) = false;
304
-                } else {
305
-                    m_mouse.resize( event.xbutton.button+2, false );
306
-                    m_mouse.at( event.xbutton.button ) = false;
307
-                }
308
-                break;
309
-            }
310
-            default: break;
311
-        }
312
-    }
313
-}
314
-
315
-// This converts an enum into a preallocated cursor, the cursor will automatically deallocate itself on ~XEngine
316
-Cursor slop::XEngine::makeCursor( slop::CursorType type ) {
317
-    int xfontcursor;
318
-    switch ( type ) {
319
-        default:
320
-        case Left:                  xfontcursor = XC_left_ptr; break;
321
-        case Crosshair:             xfontcursor = XC_crosshair; break;
322
-        case Cross:                 xfontcursor = XC_cross; break;
323
-        case UpperLeftCorner:       xfontcursor = XC_ul_angle; break;
324
-        case UpperRightCorner:      xfontcursor = XC_ur_angle; break;
325
-        case LowerLeftCorner:       xfontcursor = XC_ll_angle; break;
326
-        case LowerRightCorner:      xfontcursor = XC_lr_angle; break;
327
-        case Dot:                   xfontcursor = XC_dot; break;
328
-        case Box:                   xfontcursor = 40; break;
329
-    }
330
-    Cursor newcursor = 0;
331
-    if ( m_cursors.size() > (unsigned int)xfontcursor ) {
332
-        newcursor = m_cursors.at( xfontcursor );
333
-    }
334
-    if ( !newcursor ) {
335
-        newcursor = XCreateFontCursor( m_display, xfontcursor );
336
-        m_cursors.resize( xfontcursor+2, 0 );
337
-        m_cursors.at( xfontcursor ) = newcursor;
338
-    }
339
-    return newcursor;
340
-}
341
-
342
-slop::CursorType slop::XEngine::getCursor() {
343
-    if ( m_currentCursor ) {
344
-        return m_currentCursor;
345
-    } else {
346
-        return slop::Left;
347
-    }
348
-}
349
-
350
-// Swaps out the current cursor, bewary that XChangeActivePointerGrab also resets masks, so if you change the mouse masks on grab you need to change them here too.
351
-void slop::XEngine::setCursor( slop::CursorType type ) {
352
-    if ( !m_good ) {
353
-        return;
354
-    }
355
-    m_currentCursor = type;
356
-    Cursor xfontcursor = makeCursor( type );
357
-    XChangeActivePointerGrab( m_display,
358
-                              PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
359
-                              xfontcursor, CurrentTime );
360
-}
361
-
362
-void slop::WindowRectangle::applyPadding( int padding ) {
363
-    if ( (int)m_width + padding*2 >= 0 ) {
364
-        m_x -= padding;
365
-        m_width += padding*2;
366
-    }
367
-    if ( (int)m_height + padding*2 >= 0 ) {
368
-        m_y -= padding;
369
-        m_height += padding*2;
370
-    }
371
-}
372
-
373
-Window slop::WindowRectangle::getWindow() {
374
-    return m_window;
375
-}
376
-
377
-void slop::WindowRectangle::applyMinMaxSize( unsigned int minimumsize, unsigned int maximumsize ) {
378
-    if ( minimumsize > maximumsize && maximumsize > 0 ) {
379
-        fprintf( stderr, "Error: minimumsize is greater than maximumsize.\n" );
380
-        exit( 1 );
381
-    }
382
-    if ( m_width < minimumsize ) {
383
-        int diff = minimumsize - m_width;
384
-        m_width = minimumsize;
385
-        m_x -= diff/2;
386
-    }
387
-    if ( m_height < minimumsize ) {
388
-        int diff = minimumsize - m_height;
389
-        m_height = minimumsize;
390
-        m_y -= diff/2;
391
-    }
392
-    if ( maximumsize > 0 ) {
393
-        if ( m_width > maximumsize ) {
394
-            int diff = m_width;
395
-            m_width = maximumsize;
396
-            // Center in the center of the window
397
-            m_x += diff/2 - maximumsize/2;
398
-        }
399
-        if ( m_height > maximumsize ) {
400
-            int diff = m_height;
401
-            m_height = maximumsize;
402
-            // Center in the center of the window
403
-            m_y += diff/2 - maximumsize/2;
404
-        }
405
-    }
406
-}
407
-
408
-void slop::WindowRectangle::setGeometry( Window win, bool decorations ) {
409
-    if ( decorations ) {
410
-        Window root, parent, test, junk;
411
-        Window* childlist;
412
-        unsigned int ujunk;
413
-        // Try to find the actual decorations.
414
-        test = win;
415
-        int status = XQueryTree( xengine->m_display, test, &root, &parent, &childlist, &ujunk);
416
-        free( childlist );
417
-        while( parent != root ) {
418
-            if ( !parent || !status ) {
419
-                break;
420
-            }
421
-            test = parent;
422
-            status = XQueryTree( xengine->m_display, test, &root, &parent, &childlist, &ujunk);
423
-            free( childlist );
424
-        }
425
-        // test contains the window we're screenshotting.
426
-        m_window = test;
427
-        // Once found, proceed normally.
428
-        if ( test && parent == root && status ) {
429
-            XWindowAttributes attr;
430
-            XGetWindowAttributes( xengine->m_display, test, &attr );
431
-            m_width = attr.width;
432
-            m_height = attr.height;
433
-            m_border = attr.border_width;
434
-            XTranslateCoordinates( xengine->m_display, test, attr.root, -attr.border_width, -attr.border_width, &(m_x), &(m_y), &junk );
435
-            // We make sure we include borders, since we want decorations.
436
-            m_width += m_border * 2;
437
-            m_height += m_border * 2;
438
-        }
439
-        return;
440
-    }
441
-    Window junk;
442
-    // Now here we should be able to just use whatever we get.
443
-    XWindowAttributes attr;
444
-    // We use XGetWindowAttributes to know our root window.
445
-    XGetWindowAttributes( xengine->m_display, win, &attr );
446
-    //m_x = attr.x;
447
-    //m_y = attr.y;
448
-    m_width = attr.width;
449
-    m_height = attr.height;
450
-    m_border = attr.border_width;
451
-    XTranslateCoordinates( xengine->m_display, win, attr.root, -attr.border_width, -attr.border_width, &(m_x), &(m_y), &junk );
452
-    m_window = win;
58
+X11::~X11() {
59
+    XCloseDisplay( display );
453 60
 }

+ 19
- 83
src/x.hpp Просмотреть файл

@@ -1,4 +1,4 @@
1
-/* x.hpp: Handles starting and managing X.
1
+/* x.hpp: initializes x11
2 2
  *
3 3
  * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4 4
  *
@@ -18,98 +18,34 @@
18 18
  * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19 19
  */
20 20
 
21
-#ifndef IS_X_H_
22
-#define IS_X_H_
23
-
24
-#include <unistd.h>
21
+#ifndef N_X_H_
22
+#define N_X_H_
25 23
 
24
+#include <iostream>
26 25
 #include <X11/Xlib.h>
27
-#include <X11/cursorfont.h>
28
-#include <X11/extensions/shape.h>
29
-#include <X11/extensions/Xrandr.h>
30
-
31
-#include <stdlib.h>
32
-#include <cstring>
33
-#include <cstdlib>
34
-#include <cmath>
35
-#include <cstdio>
36 26
 #include <string>
37
-#include <vector>
27
+#include <sstream>
28
+#include <stdexcept>
29
+#include <X11/Xatom.h>
30
+#include <glm/glm.hpp>
38 31
 
39 32
 namespace slop {
40 33
 
41
-enum CursorType {
42
-    Left,
43
-    Crosshair,
44
-    Cross,
45
-    UpperLeftCorner,
46
-    UpperRightCorner,
47
-    LowerRightCorner,
48
-    LowerLeftCorner,
49
-    Dot,
50
-    Box
51
-};
34
+glm::vec4 getWindowGeometry( Window win, bool removeDecoration );
52 35
 
53
-class WindowRectangle {
36
+class X11 {
54 37
 public:
55
-    int          m_x;
56
-    int          m_y;
57
-    unsigned int m_width;
58
-    unsigned int m_height;
59
-    unsigned int m_border;
60
-    Window       m_window;
61
-    bool         m_decorations;
62
-    Window       getWindow();
63
-    void         setGeometry( Window win, bool decorations );
64
-    void         applyPadding( int padding );
65
-    void         applyMinMaxSize( unsigned int minimumsize, unsigned int maximumsize );
38
+    bool hasCompositor();
39
+    X11( std::string displayName );
40
+    ~X11();
41
+    Display* display;
42
+    Visual* visual;
43
+    Screen* screen;
44
+    Window root;
66 45
 };
67 46
 
68
-class XEngine {
69
-public:
70
-                        XEngine();
71
-                        ~XEngine();
72
-    int                 init( std::string display );
73
-    void                tick();
74
-    int                 grabCursor( slop::CursorType type, double waittime );
75
-    int                 grabKeyboard();
76
-    bool                anyKeyPressed();
77
-    bool                keyPressed( KeySym key );
78
-    int                 releaseCursor();
79
-    int                 releaseKeyboard();
80
-    void                setCursor( slop::CursorType type );
81
-    slop::CursorType    getCursor();
82
-    void                drawRect( int x, int y, unsigned int w, unsigned int h );
83
-    unsigned int        getWidth();
84
-    unsigned int        getHeight();
85
-#ifdef OPENGL_ENABLED
86
-    std::vector<XRRCrtcInfo*>        getCRTCS();
87
-    void                freeCRTCS( std::vector<XRRCrtcInfo*> monitors );
88
-#endif // OPENGL_ENABLED
89
-    int                 m_mousex;
90
-    int                 m_mousey;
91
-    Display*            m_display;
92
-    Visual*             m_visual;
93
-    Screen*             m_screen;
94
-    Colormap            m_colormap;
95
-    Window              m_root;
96
-    Window              m_hoverWindow;
97
-    std::vector<bool>   m_mouse;
98
-    bool                mouseDown( unsigned int button );
99
-    bool                m_keypressed;
100
-    XRRScreenResources* m_res;
101
-private:
102
-    slop::CursorType    m_currentCursor;
103
-    bool                m_good;
104
-    std::vector<Cursor> m_cursors;
105
-    Cursor              makeCursor( slop::CursorType type );
106
-    void                selectAllInputs( Window win, long event_mask);
107
-};
108
-
109
-int XEngineErrorHandler( Display* dpy, XErrorEvent* event );
47
+extern X11* x11;
110 48
 
111 49
 }
112 50
 
113
-extern slop::XEngine* xengine;
114
-
115
-#endif // IS_X_H_
51
+#endif

+ 0
- 189
src/xselectrectangle.cpp Просмотреть файл

@@ -1,189 +0,0 @@
1
-/* xselectrectangle.cpp: Handles creating rectangles on the screen in pure X11.
2
- *
3
- * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4
- *
5
- * This file is part of Slop.
6
- *
7
- * Slop is free software: you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, either version 3 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * Slop is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19
- */
20
-#include "xselectrectangle.hpp"
21
-
22
-static Bool isDestroyNotify( Display* dpy, XEvent* ev, XPointer win ) {
23
-    return ev->type == DestroyNotify && ev->xdestroywindow.window == *((Window*)win);
24
-}
25
-
26
-slop::XSelectRectangle::~XSelectRectangle() {
27
-    if ( m_window == None ) {
28
-        return;
29
-    }
30
-    // Try to erase the window before destroying it.
31
-    XSetWindowBackground( xengine->m_display, m_window, 0 );
32
-    XClearWindow( xengine->m_display, m_window );
33
-    // Sleep for 0.1 seconds in hope that the rectangle was erased.
34
-    usleep( 10000 );
35
-    // Free up our color.
36
-    XFreeColors( xengine->m_display, xengine->m_colormap, &m_color.pixel, 1, 0 );
37
-    XDestroyWindow( xengine->m_display, m_window );
38
-    XEvent event;
39
-    // Block until the window is actually completely removed.
40
-    XIfEvent( xengine->m_display, &event, &isDestroyNotify, (XPointer)&m_window );
41
-    // Sleep for 0.1 seconds in hope that the screen actually cleared the window.
42
-    usleep( 10000 );
43
-}
44
-
45
-slop::XSelectRectangle::XSelectRectangle( int sx, int sy, int ex, int ey, int border, bool highlight, float r, float g, float b, float a ) {
46
-    m_x = std::min( sx, ex );
47
-    m_y = std::min( sy, ey );
48
-    m_width = std::max( sx, ex ) - m_x;
49
-    m_height = std::max( sy, ey ) - m_y;
50
-    m_border = border;
51
-    m_window = None;
52
-    m_highlight = highlight;
53
-
54
-    // If we don't have a border, we don't exist, so just die.
55
-    if ( m_border == 0 ) {
56
-        return;
57
-    }
58
-
59
-    if ( m_highlight ) {
60
-        m_border = 0;
61
-    }
62
-
63
-    m_color = convertColor( r, g, b );
64
-    XSetWindowAttributes attributes;
65
-    // Set up the window so it's our color 
66
-    attributes.background_pixel = m_color.pixel;
67
-    // Disable window decorations.
68
-    attributes.override_redirect = True;
69
-    // Make sure we know when we've been successfully destroyed later!
70
-    attributes.event_mask = StructureNotifyMask;
71
-    unsigned long valueMask = CWBackPixel | CWOverrideRedirect | CWEventMask;
72
-
73
-    // Create the window
74
-    m_window = XCreateWindow( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(),
75
-                              0, CopyFromParent, InputOutput,
76
-                              CopyFromParent, valueMask, &attributes );
77
-
78
-
79
-    if ( a < 1 ) {
80
-        // Change the window opacity
81
-        unsigned int cardinal_alpha = (unsigned int) (a * (unsigned int)-1) ;
82
-        XChangeProperty( xengine->m_display, m_window, XInternAtom( xengine->m_display, "_NET_WM_WINDOW_OPACITY", 0),
83
-                         XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&cardinal_alpha, 1 );
84
-    }
85
-
86
-    XClassHint classhints;
87
-    char name[] = "slop";
88
-    classhints.res_name = name;
89
-    classhints.res_class = name;
90
-    XSetClassHint( xengine->m_display, m_window, &classhints );
91
-
92
-    // Now punch a hole into it so it looks like a selection rectangle, but only if we're not highlighting.
93
-    if ( !m_highlight ) {
94
-        XRectangle rects[4];
95
-        // Left
96
-        rects[0].x = m_x-m_border;
97
-        rects[0].y = m_y-m_border;
98
-        rects[0].width = m_border;
99
-        rects[0].height = m_height+m_border*2;
100
-        // Top
101
-        rects[1].x = m_x;
102
-        rects[1].y = m_y-m_border;
103
-        rects[1].width = m_width+m_border;
104
-        rects[1].height = m_border;
105
-        // Right
106
-        rects[2].x = m_x+m_width;
107
-        rects[2].y = m_y-m_border;
108
-        rects[2].width = m_border;
109
-        rects[2].height = m_height+m_border*2;
110
-        // Bottom
111
-        rects[3].x = m_x;
112
-        rects[3].y = m_y+m_height;
113
-        rects[3].width = m_width+m_border;
114
-        rects[3].height = m_border;
115
-        XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, rects, 4, ShapeSet, 0);
116
-    } else {
117
-        XRectangle rect;
118
-        rect.x = m_x;
119
-        rect.y = m_y;
120
-        rect.width = m_width;
121
-        rect.height = m_height;
122
-        XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
123
-    }
124
-    // Make it so all input falls through
125
-    XRectangle rect;
126
-    rect.x = rect.y = rect.width = rect.height = 0;
127
-    XShapeCombineRectangles( xengine->m_display, m_window, ShapeInput, 0, 0, &rect, 1, ShapeSet, 0);
128
-    XMapWindow( xengine->m_display, m_window );
129
-}
130
-
131
-void slop::XSelectRectangle::setGeo( int sx, int sy, int ex, int ey ) {
132
-    int x = std::min( sx, ex );
133
-    int y = std::min( sy, ey );
134
-    int w = std::max( sx, ex ) - x;
135
-    int h = std::max( sy, ey ) - y;
136
-
137
-    // Only resize or move if we have to, because they're oddly expensive.
138
-    m_x = x;
139
-    m_y = y;
140
-    m_width = w;
141
-    m_height = h;
142
-    if ( m_border > 0 ) {
143
-        XRectangle rects[4];
144
-        // Left
145
-        rects[0].x = m_x-m_border;
146
-        rects[0].y = m_y-m_border;
147
-        rects[0].width = m_border;
148
-        rects[0].height = m_height+m_border*2;
149
-        // Top
150
-        rects[1].x = m_x;
151
-        rects[1].y = m_y-m_border;
152
-        rects[1].width = m_width+m_border;
153
-        rects[1].height = m_border;
154
-        // Right
155
-        rects[2].x = m_x+m_width;
156
-        rects[2].y = m_y-m_border;
157
-        rects[2].width = m_border;
158
-        rects[2].height = m_height+m_border*2;
159
-        // Bottom
160
-        rects[3].x = m_x;
161
-        rects[3].y = m_y+m_height;
162
-        rects[3].width = m_width+m_border;
163
-        rects[3].height = m_border;
164
-        XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, rects, 4, ShapeSet, 0);
165
-    } else {
166
-        XRectangle rect;
167
-        rect.x = m_x;
168
-        rect.y = m_y;
169
-        rect.width = m_width;
170
-        rect.height = m_height;
171
-        XShapeCombineRectangles( xengine->m_display, m_window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
172
-    }
173
-}
174
-
175
-XColor slop::XSelectRectangle::convertColor( float r, float g, float b ) {
176
-    // Convert float colors to shorts.
177
-    short red   = short( floor( r * 65535.f ) );
178
-    short green = short( floor( g * 65535.f ) );
179
-    short blue  = short( floor( b * 65535.f ) );
180
-    XColor color;
181
-    color.red = red;
182
-    color.green = green;
183
-    color.blue = blue;
184
-    int err = XAllocColor( xengine->m_display, xengine->m_colormap, &color );
185
-    if ( err == BadColor ) {
186
-        fprintf( stderr, "Couldn't allocate color of value %f,%f,%f!\n", r, g, b );
187
-    }
188
-    return color;
189
-}

+ 141
- 0
src/xshaperectangle.cpp Просмотреть файл

@@ -0,0 +1,141 @@
1
+#include "xshaperectangle.hpp"
2
+
3
+slop::XShapeRectangle::XShapeRectangle( glm::vec2 p1, glm::vec2 p2, float border, float padding, glm::vec4 color, bool highlight ) {
4
+    this->color = convertColor( color );
5
+    this->border = border;
6
+    this->padding = padding;
7
+    this->highlight = highlight;
8
+    this->alpha = color.a;
9
+    // Find each corner of the rectangle
10
+    ul = glm::vec2( glm::min( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
11
+    bl = glm::vec2( glm::min( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
12
+    ur = glm::vec2( glm::max( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
13
+    br = glm::vec2( glm::max( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
14
+    // Offset the inner corners by the padding.
15
+    ul = ul + glm::vec2(-padding,padding);
16
+    bl = bl + glm::vec2(-padding,-padding);
17
+    ur = ur + glm::vec2(padding,padding);
18
+    br = br + glm::vec2(padding,-padding);
19
+    // Create the outer corners by offsetting the inner by the bordersize
20
+    oul = ul + glm::vec2(-border,border);
21
+    obl = bl + glm::vec2(-border,-border);
22
+    our = ur + glm::vec2(border,border);
23
+    obr = br + glm::vec2(border,-border);
24
+
25
+    XSetWindowAttributes attributes;
26
+    // Set up the window so it's our color 
27
+    attributes.background_pixel = this->color.pixel;
28
+    // Disable window decorations.
29
+    attributes.override_redirect = True;
30
+    // Make sure we know when we've been successfully destroyed later!
31
+    attributes.event_mask = StructureNotifyMask;
32
+    unsigned long valueMask = CWBackPixel | CWOverrideRedirect | CWEventMask;
33
+    // Create the window
34
+    window = XCreateWindow( x11->display, x11->root, 0, 0, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ),
35
+                              0, CopyFromParent, InputOutput,
36
+                              CopyFromParent, valueMask, &attributes );
37
+    if ( alpha < 1 ) {
38
+        // Change the window opacity
39
+        unsigned int cardinal_alpha = (unsigned int) (alpha * (unsigned int)-1) ;
40
+        XChangeProperty( x11->display, window, XInternAtom( x11->display, "_NET_WM_WINDOW_OPACITY", 0),
41
+                         XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&cardinal_alpha, 1 );
42
+    }
43
+    // Set the class hint, and title to "slop"
44
+    XClassHint classhints;
45
+    char name[] = "slop";
46
+    classhints.res_name = name;
47
+    classhints.res_class = name;
48
+    XSetClassHint( x11->display, window, &classhints );
49
+    // Now punch a hole into it so it looks like a selection rectangle, but only if we're not highlighting.
50
+    generateHoles();
51
+    createdWindow = false;
52
+}
53
+
54
+void slop::XShapeRectangle::createWindow() {
55
+    if ( createdWindow ) {
56
+        return;
57
+    }
58
+	XMapWindow( x11->display, window );
59
+    createdWindow = true;
60
+}
61
+
62
+void slop::XShapeRectangle::generateHoles() {
63
+    if ( !highlight ) {
64
+        XRectangle rects[4];
65
+        // Left
66
+        rects[0].x = oul.x;
67
+        rects[0].y = obl.y;
68
+        rects[0].width = border;
69
+        rects[0].height = oul.y-obl.y;
70
+        // Top
71
+        rects[1].x = ul.x;
72
+        rects[1].y = obl.y;
73
+        rects[1].width = ur.x-ul.x;
74
+        rects[1].height = border;
75
+        // Right
76
+        rects[2].x = ur.x;
77
+        rects[2].y = obr.y;
78
+        rects[2].width = border;
79
+        rects[2].height = our.y - obr.y;
80
+        // Bottom
81
+        rects[3].x = bl.x;
82
+        rects[3].y = ul.y;
83
+        rects[3].width = br.x-bl.x;
84
+        rects[3].height = border;
85
+        XShapeCombineRectangles( x11->display, window, ShapeBounding, 0, 0, rects, 4, ShapeSet, 0);
86
+        return;
87
+    }
88
+    XRectangle rect;
89
+    rect.x = oul.x;
90
+    rect.y = obl.y;
91
+    rect.width = our.x-oul.x;
92
+    rect.height = oul.y-obl.y;
93
+    XShapeCombineRectangles( x11->display, window, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
94
+}
95
+
96
+void slop::XShapeRectangle::setPoints( glm::vec2 p1, glm::vec2 p2 ) {
97
+    // Find each corner of the rectangle
98
+    ul = glm::vec2( glm::min( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
99
+    bl = glm::vec2( glm::min( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
100
+    ur = glm::vec2( glm::max( p1.x, p2.x ), glm::max( p1.y, p2.y ) ) ;
101
+    br = glm::vec2( glm::max( p1.x, p2.x ), glm::min( p1.y, p2.y ) ) ;
102
+    // Offset the inner corners by the padding.
103
+    ul = ul + glm::vec2(-padding,padding);
104
+    bl = bl + glm::vec2(-padding,-padding);
105
+    ur = ur + glm::vec2(padding,padding);
106
+    br = br + glm::vec2(padding,-padding);
107
+    // Create the outer corners by offsetting the inner by the bordersize
108
+    oul = ul + glm::vec2(-border,border);
109
+    obl = bl + glm::vec2(-border,-border);
110
+    our = ur + glm::vec2(border,border);
111
+    obr = br + glm::vec2(border,-border);
112
+    generateHoles();
113
+}
114
+
115
+slop::XShapeRectangle::~XShapeRectangle() {
116
+}
117
+
118
+void slop::XShapeRectangle::draw( glm::mat4& matrix ) {
119
+    // We don't want to be visible until we're asked to draw.
120
+    createWindow();
121
+}
122
+
123
+glm::vec4 slop::XShapeRectangle::getRect() {
124
+    return glm::vec4( bl.x, bl.y, ur.x-ul.x, ul.y-bl.y );
125
+}
126
+
127
+XColor slop::XShapeRectangle::convertColor( glm::vec4 color ) {
128
+    // Convert float colors to shorts.
129
+    short red   = short( floor( color.r * 65535.f ) );
130
+    short green = short( floor( color.g * 65535.f ) );
131
+    short blue  = short( floor( color.b * 65535.f ) );
132
+    XColor xc;
133
+    xc.red = red;
134
+    xc.green = green;
135
+    xc.blue = blue;
136
+    int err = XAllocColor( x11->display, DefaultColormap( x11->display, XScreenNumberOfScreen( x11->screen ) ), &xc );
137
+    if ( err == BadColor ) {
138
+        throw new std::runtime_error(std::string("Couldn't allocate a color"));
139
+    }
140
+    return xc;
141
+}

src/xselectrectangle.hpp → src/xshaperectangle.hpp Просмотреть файл

@@ -1,4 +1,4 @@
1
-/* xselectrectangle.hpp: Handles creating rectangles on the screen in pure X11.
1
+/* xshaperectangle.hpp: A rectangle that doesn't use OpenGL to function.
2 2
  *
3 3
  * Copyright (C) 2014: Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors).
4 4
  *
@@ -18,39 +18,46 @@
18 18
  * along with Slop.  If not, see <http://www.gnu.org/licenses/>.
19 19
  */
20 20
 
21
-#ifndef IS_X_SELECT_RECTANGLE_H_
22
-#define IS_X_SELECT_RECTANGLE_H_
23
-
24
-#include "x.hpp"
25
-#include "selectrectangle.hpp"
26
-
27
-#include <unistd.h>
21
+#ifndef N_XSHAPERECTANGLE_H_
22
+#define N_XSHAPERECTANGLE_H_
28 23
 
24
+#include <iostream>
25
+#include <glm/glm.hpp>
26
+#include <vector>
29 27
 #include <X11/Xlib.h>
30
-#include <X11/extensions/shape.h>
31 28
 #include <X11/Xatom.h>
29
+#include <X11/Xutil.h>
30
+#include <X11/extensions/shape.h>
32 31
 
33
-#include <cstdlib>
34
-#include <cmath>
35
-#include <cstdio>
36
-#include <string>
37
-#include <vector>
32
+#include "x.hpp"
33
+#include "rectangle.hpp"
38 34
 
39 35
 namespace slop {
40 36
 
41
-class XSelectRectangle: public SelectRectangle {
42
-public:
43
-            XSelectRectangle( int sx, int sy, int ex, int ey, int border, bool highlight, float r, float g, float b, float a );
44
-            ~XSelectRectangle();
45
-    void    setPos( int x, int y );
46
-    void    setDim( int w, int h );
47
-    void    setGeo( int x, int y, int w, int h );
48
-    XColor  m_color;
37
+class XShapeRectangle : public Rectangle {
49 38
 private:
50
-    XColor  convertColor( float r, float g, float b );
51
-    void    constrain( int w, int h );
39
+    glm::vec2 ul, oul;
40
+    glm::vec2 bl, obl;
41
+    glm::vec2 ur, our;
42
+    glm::vec2 br, obr;
43
+    bool createdWindow;
44
+    bool highlight;
45
+    float border;
46
+    float padding;
47
+    XColor color;
48
+    float alpha;
49
+    XColor convertColor( glm::vec4 color );
50
+    void generateHoles();
51
+    void createWindow();
52
+public:
53
+    Window window;
54
+    glm::vec4 getRect();
55
+    XShapeRectangle(glm::vec2 p1, glm::vec2 p2, float border = 1, float padding = 0, glm::vec4 color = glm::vec4(1,1,1,1), bool highlight = false );
56
+    ~XShapeRectangle();
57
+    void setPoints( glm::vec2 p1, glm::vec2 p2 );
58
+    void draw(glm::mat4& matrix);
52 59
 };
53 60
 
54 61
 }
55 62
 
56
-#endif // IS_X_SELECT_RECTANGLE_H_
63
+#endif // N_XSHAPERECTANGLE_H_