Browse Source

Changed build system to cmake, made error handling more verbose, fixed many warnings, and added exception handling.

Dalton Nell 9 years ago
parent
commit
61cc45f913
13 changed files with 147 additions and 72 deletions
  1. 59
    0
      CMakeLists.txt
  2. 5
    4
      README.md
  3. 26
    0
      cmakemodules/FindXExt.cmake
  4. 1
    0
      gengetopt.sh
  5. 0
    23
      makefile
  6. 0
    0
      src/cmdline.c
  7. 1
    1
      src/cmdline.h
  8. 28
    17
      src/main.cpp
  9. 1
    1
      src/options.ggo
  10. 1
    1
      src/rectangle.cpp
  11. 0
    0
      src/rectangle.hpp
  12. 22
    22
      src/x.cpp
  13. 3
    3
      src/x.hpp

+ 59
- 0
CMakeLists.txt View File

@@ -0,0 +1,59 @@
1
+cmake_minimum_required( VERSION 2.8 )
2
+
3
+set( PROJECT_NAME   "slop" )
4
+set( BIN_TARGET     "${PROJECT_NAME}" )
5
+set( CMAKE_INSTALL_PREFIX "/usr/bin" )
6
+
7
+project( ${PROJECT_NAME} )
8
+
9
+# Linux compiler initialization.
10
+if ( CMAKE_COMPILER_IS_GNUCXX )
11
+    set( CMAKE_CXX_FLAGS
12
+         "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -pedantic-errors -Wno-unused-parameter" )
13
+         # -Wall:   Enable all warnings.
14
+         # -Wextra: Enable some more warnings.
15
+         # -Werror: Have errors on warnings.
16
+         # -Wno-unused-parameter: Prevent unused variable warning. (Several functions are required to have unecessary variables because X11.)
17
+    add_definitions( -D_CMAKE_LINUX_ )
18
+else()
19
+    message( FATAL_ERROR "Your operating system isn't supported yet! CMake will now exit." )
20
+endif()
21
+
22
+# Add a check target for our makefile.
23
+find_program( CPPCHECK_EXECUTABLE cppcheck
24
+              DOC "A tool for static C/C++ code analysis." )
25
+if (CPPCHECK_EXECUTABLE)
26
+    add_custom_target( "check"
27
+                       COMMAND "${CPPCHECK_EXECUTABLE}" "--enable=all" "*"
28
+                       WORKING_DIRECTORY src VERBATIM )
29
+endif()
30
+
31
+# Sources
32
+set( source
33
+     src/cmdline.c
34
+     src/rectangle.cpp
35
+     src/x.cpp
36
+     src/main.cpp )
37
+
38
+# Obtain library paths and make sure they exist.
39
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmakemodules" )
40
+find_package( X11       REQUIRED )
41
+find_package( XExt      REQUIRED )
42
+
43
+set( CMAKE_CXX_FLAGS
44
+     "${CMAKE_CXX_FLAGS} ${CMAKE_IMLIB2_CXX_FLAGS}" )
45
+
46
+# Includes
47
+include_directories( ${X11_INCLUDE_DIR}
48
+                     ${XEXT_INCLUDE_DIR} )
49
+
50
+# Executable
51
+add_executable( ${BIN_TARGET} ${source} )
52
+
53
+# Libraries
54
+target_link_libraries( ${BIN_TARGET}
55
+                       ${X11_LIBRARIES}
56
+                       ${XEXT_LIBRARY} )
57
+
58
+install( TARGETS ${BIN_TARGET}
59
+         DESTINATION  ${CMAKE_INSTALL_PREFIX} )

+ 5
- 4
README.md View File

@@ -60,19 +60,20 @@ While slop not only looks nicer, it's impossible for it to end up in screenshots
60 60
 
61 61
 ## how to install
62 62
 
63
-### Install using your Package Manager (preferred)
63
+### Install using your Package Manager (Preferred)
64 64
 
65 65
 * [Arch Linux AUR (slop-git)](https://aur.archlinux.org/packages/slop-git/)
66 66
 * Please make a package for slop on your favorite system, and make a pull request to add it to this list.
67 67
 
68 68
 
69
-### Install using Make
69
+### Install using CMake (Requires CMake)
70 70
 
71
-Note: Dependencies should be installed first: libXext, and glibc.
71
+Note: Dependencies should be installed first: libXext.
72 72
 
73 73
 ```bash
74 74
 git clone https://github.com/naelstrof/slop.git
75 75
 cd slop
76
+cmake ./
76 77
 make && sudo make install
77 78
 ```
78 79
 
@@ -81,7 +82,7 @@ Make sure to check out and install [maim](https://github.com/naelstrof/maim) too
81 82
 help
82 83
 ----
83 84
 ```text
84
-slop v3.1.7
85
+slop v3.1.8
85 86
 
86 87
 Copyright (C) 2014 Dalton Nell, Slop Contributors
87 88
 (https://github.com/naelstrof/slop/graphs/contributors)

+ 26
- 0
cmakemodules/FindXExt.cmake View File

@@ -0,0 +1,26 @@
1
+# - Find XExt
2
+# Find the XExtension libraries (WARNING: It's geared and tested specifically for the XShape extension though)
3
+#
4
+#  This module defines the following variables:
5
+#     XEXT_FOUND        - 1 if XEXT_INCLUDE_DIR & XEXT_LIBRARY are found, 0 otherwise
6
+#     XEXT_INCLUDE_DIR  - where to find Xlib.h, etc.
7
+#     XEXT_LIBRARY      - the X11 library
8
+#
9
+
10
+find_path( XEXT_INCLUDE_DIR
11
+           NAMES X11/extensions/shape.h
12
+           PATH_SUFFIXES X11/extensions
13
+           DOC "The XExtension include directory" )
14
+
15
+find_library( XEXT_LIBRARY
16
+              NAMES Xext
17
+              PATHS /usr/lib /lib
18
+              DOC "The XExtension library" )
19
+
20
+if( XEXT_INCLUDE_DIR AND XEXT_LIBRARY )
21
+    set( XEXT_FOUND 1 )
22
+else()
23
+    set( XEXT_FOUND 0 )
24
+endif()
25
+
26
+mark_as_advanced( XEXT_INCLUDE_DIR XEXT_LIBRARY )

+ 1
- 0
gengetopt.sh View File

@@ -1,5 +1,6 @@
1 1
 #!/bin/bash
2 2
 # This is used because a bug in gengetopt keeps you from putting \n in default string options. All it does is replace REPLACEME with the correct code to make the application work properly.
3
+cd "$(dirname $0)/src"
3 4
 gengetopt < options.ggo
4 5
 sed -i '0,/REPLACEME/{s/REPLACEME/X=%x\\\\nY=%y\\\\nW=%w\\\\nH=%h\\\\nG=%g\\\\nID=%i\\\\nCancel=%c\\\\n/}' cmdline.c
5 6
 sed -i 's/REPLACEME/X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n/' cmdline.c

+ 0
- 23
makefile View File

@@ -1,23 +0,0 @@
1
-CXX ?= g++
2
-CXXFLAGS ?= -O2 -g
3
-LDFLAGS += -lX11 -lXext -lrt
4
-SOURCES = main.cpp x.cpp cmdline.c rectangle.cpp
5
-OBJECTS = main.o x.o cmdline.o rectangle.o
6
-EXECUTABLE = slop
7
-BINDIR = "/usr/bin"
8
-
9
-all: $(EXECUTABLE)
10
-
11
-$(EXECUTABLE): $(OBJECTS)
12
-	$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
13
-
14
-clean:
15
-	$(RM) $(OBJECTS)
16
-
17
-dist-clean: clean
18
-	$(RM) $(EXECUTABLE)
19
-
20
-install: all
21
-	mkdir -p $(DESTDIR)$(BINDIR)
22
-	cp $(CURDIR)/$(EXECUTABLE) $(DESTDIR)$(BINDIR)
23
-

cmdline.c → src/cmdline.c View File


cmdline.h → src/cmdline.h View File

@@ -31,7 +31,7 @@ extern "C" {
31 31
 
32 32
 #ifndef CMDLINE_PARSER_VERSION
33 33
 /** @brief the program version */
34
-#define CMDLINE_PARSER_VERSION "v3.1.7"
34
+#define CMDLINE_PARSER_VERSION "v3.1.8"
35 35
 #endif
36 36
 
37 37
 /** @brief Where the command line options are stored */

main.cpp → src/main.cpp View File

@@ -28,8 +28,8 @@ int printSelection( std::string format, bool cancelled, int x, int y, int w, int
28 28
     size_t pos = 0;
29 29
     while ( ( pos = format.find( "%", pos ) ) != std::string::npos ) {
30 30
         if ( pos + 1 > format.size() ) {
31
-            fprintf( stderr, "Format error: %% found at the end of format string.\n", format[ pos + 1 ] );
32
-            return 1;
31
+            fprintf( stderr, "Format error: %% found at the end of format string.\n" );
32
+            return EXIT_FAILURE;
33 33
         }
34 34
         std::stringstream foo;
35 35
         switch( format[ pos + 1 ] ) {
@@ -74,7 +74,7 @@ int printSelection( std::string format, bool cancelled, int x, int y, int w, int
74 74
             default:
75 75
                 fprintf( stderr, "Format error: %%%c is an unknown replacement identifier.\n", format[ pos + 1 ] );
76 76
                 fprintf( stderr, "Valid replacements: %%x, %%y, %%w, %%h, %%i, %%c, %%.\n" );
77
-                return 1;
77
+                return EXIT_FAILURE;
78 78
                 break;
79 79
         }
80 80
     }
@@ -89,13 +89,13 @@ int printSelection( std::string format, bool cancelled, int x, int y, int w, int
89 89
         pos = pos + 1;
90 90
     }
91 91
     printf( "%s", format.c_str() );
92
-    return 0;
92
+    return EXIT_SUCCESS;
93 93
 }
94 94
 
95 95
 int parseColor( std::string arg, float* r, float* g, float* b, float* a ) {
96 96
     std::string copy = arg;
97 97
     int find = copy.find( "," );
98
-    while( find != copy.npos ) {
98
+    while( find != (int)copy.npos ) {
99 99
         copy.at( find ) = ' ';
100 100
         find = copy.find( "," );
101 101
     }
@@ -105,9 +105,9 @@ int parseColor( std::string arg, float* r, float* g, float* b, float* a ) {
105 105
     int num = sscanf( copy.c_str(), "%f %f %f %f", r, g, b, a );
106 106
     if ( num != 3 && num != 4 ) {
107 107
         fprintf( stderr, "Error parsing color %s\n", arg.c_str() );
108
-        return 1;
108
+        return EXIT_FAILURE;
109 109
     }
110
-    return 0;
110
+    return EXIT_SUCCESS;
111 111
 }
112 112
 
113 113
 void constrain( int sx, int sy, int ex, int ey, int padding, int minimumsize, int maximumsize, int* rsx, int* rsy, int* rex, int* rey ) {
@@ -162,11 +162,11 @@ void constrain( int sx, int sy, int ex, int ey, int padding, int minimumsize, in
162 162
     *rey = y + h;
163 163
 }
164 164
 
165
-int main( int argc, char** argv ) {
165
+int app( int argc, char** argv ) {
166 166
     gengetopt_args_info options;
167 167
     int err = cmdline_parser( argc, argv, &options );
168
-    if ( err ) {
169
-        return err;
168
+    if ( err != EXIT_SUCCESS ) {
169
+        return EXIT_FAILURE;
170 170
     }
171 171
     int state = 0;
172 172
     bool running = true;
@@ -198,14 +198,14 @@ int main( int argc, char** argv ) {
198 198
     // First we set up the x interface and grab the mouse,
199 199
     // if we fail for either we exit immediately.
200 200
     err = xengine->init( xdisplay.c_str() );
201
-    if ( err ) {
201
+    if ( err != EXIT_SUCCESS ) {
202 202
         printSelection( format, true, 0, 0, 0, 0, None );
203
-        return err;
203
+        return EXIT_FAILURE;
204 204
     }
205 205
     err = xengine->grabCursor( slop::Cross );
206
-    if ( err ) {
206
+    if ( err != EXIT_SUCCESS ) {
207 207
         printSelection( format, true, 0, 0, 0, 0, None );
208
-        return err;
208
+        return EXIT_FAILURE;
209 209
     }
210 210
     if ( keyboard ) {
211 211
         err = xengine->grabKeyboard();
@@ -320,7 +320,7 @@ int main( int argc, char** argv ) {
320 320
                 // We also detect which way the user is pulling and set the mouse icon accordingly.
321 321
                 bool x = cx > xengine->m_mousex;
322 322
                 bool y = cy > xengine->m_mousey;
323
-                if ( selection->m_width <= 1 && selection->m_height <= 1 || ( minimumsize == maximumsize && minimumsize != 0 && maximumsize != 0 ) ) {
323
+                if ( ( selection->m_width <= 1 && selection->m_height <= 1 ) || ( minimumsize == maximumsize && minimumsize != 0 && maximumsize != 0 ) ) {
324 324
                     xengine->setCursor( slop::Cross );
325 325
                 } else if ( !x && !y ) {
326 326
                     xengine->setCursor( slop::LowerRightCorner );
@@ -370,7 +370,18 @@ int main( int argc, char** argv ) {
370 370
     usleep( 50000 );
371 371
     // If we canceled the selection, return error.
372 372
     if ( state == -1 ) {
373
-        return 1;
373
+        return EXIT_FAILURE;
374
+    }
375
+    return EXIT_SUCCESS;
376
+}
377
+
378
+int main( int argc, char** argv ) {
379
+    int exitvalue = EXIT_SUCCESS;
380
+    try {
381
+        exitvalue = app( argc, argv );
382
+    } catch( std::exception* exception ) {
383
+        fprintf( stderr, "Unhandled Exception Thrown: %s\n", exception->what() );
384
+        exit( EXIT_FAILURE );
374 385
     }
375
-    return 0;
386
+    return exitvalue;
376 387
 }

options.ggo → src/options.ggo View File

@@ -1,5 +1,5 @@
1 1
 package "slop"
2
-version "v3.1.7"
2
+version "v3.1.8"
3 3
 usage "slop [options]"
4 4
 description "slop (Select Operation) is an application that queries for a selection from the user and prints the region to stdout."
5 5
 versiontext "Copyright (C) 2014 Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors)"

rectangle.cpp → src/rectangle.cpp View File

@@ -71,7 +71,7 @@ slop::Rectangle::Rectangle( int sx, int sy, int ex, int ey, int border, bool hig
71 71
     unsigned long valueMask = CWBackPixel | CWOverrideRedirect | CWEventMask;
72 72
 
73 73
     // Create the window
74
-    m_window = XCreateWindow( xengine->m_display, xengine->m_root, 0, 0, WidthOfScreen( xengine->m_screen ), HeightOfScreen( xengine->m_screen ),
74
+    m_window = XCreateWindow( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(),
75 75
                               0, CopyFromParent, InputOutput,
76 76
                               CopyFromParent, valueMask, &attributes );
77 77
 

rectangle.hpp → src/rectangle.hpp View File


x.cpp → src/x.cpp View File

@@ -26,7 +26,7 @@ int slop::XEngineErrorHandler( Display* dpy, XErrorEvent* event ) {
26 26
     // 31 = XGrabKeyboard's request code
27 27
     if ( event->request_code == 31 && event->error_code == BadAccess ) {
28 28
         fprintf( stderr, "_X Error \"BadAccess\" for XGrabKeyboard ignored...\n" );
29
-        return 0;
29
+        return EXIT_SUCCESS;
30 30
     }
31 31
     // Everything else should be fatal as I don't like undefined behavior.
32 32
     char buffer[1024];
@@ -39,21 +39,22 @@ int slop::XEngineErrorHandler( Display* dpy, XErrorEvent* event ) {
39 39
     exit(1);
40 40
 }
41 41
 
42
-int slop::XEngine::getWidth() {
42
+unsigned int slop::XEngine::getWidth() {
43 43
     if ( !m_good ) {
44 44
         return -1;
45 45
     }
46
-    return (int)WidthOfScreen( m_screen );
46
+    return WidthOfScreen( m_screen );
47 47
 }
48 48
 
49
-int slop::XEngine::getHeight() {
49
+unsigned int slop::XEngine::getHeight() {
50 50
     if ( !m_good ) {
51 51
         return -1;
52 52
     }
53
-    return (int)HeightOfScreen( m_screen );
53
+    return HeightOfScreen( m_screen );
54 54
 }
55 55
 
56 56
 slop::XEngine::XEngine() {
57
+    m_keypressed = false;
57 58
     m_display = NULL;
58 59
     m_visual = NULL;
59 60
     m_screen = NULL;
@@ -87,7 +88,7 @@ int slop::XEngine::init( std::string display ) {
87 88
     m_display = XOpenDisplay( display.c_str() );
88 89
     if ( !m_display ) {
89 90
         fprintf( stderr, "Error: Failed to open X display %s\n", display.c_str() );
90
-        return 1;
91
+        return EXIT_FAILURE;
91 92
     }
92 93
     m_screen    = ScreenOfDisplay( m_display, DefaultScreen( m_display ) );
93 94
     m_visual    = DefaultVisual  ( m_display, XScreenNumberOfScreen( m_screen ) );
@@ -98,7 +99,7 @@ int slop::XEngine::init( std::string display ) {
98 99
     m_good = true;
99 100
     XSetErrorHandler( slop::XEngineErrorHandler );
100 101
     selectAllInputs( m_root, EnterWindowMask );
101
-    return 0;
102
+    return EXIT_SUCCESS;
102 103
 }
103 104
 
104 105
 bool slop::XEngine::anyKeyPressed() {
@@ -121,24 +122,24 @@ bool slop::XEngine::anyKeyPressed() {
121 122
 
122 123
 int slop::XEngine::grabKeyboard() {
123 124
     if ( !m_good ) {
124
-        return 1;
125
+        return EXIT_FAILURE;
125 126
     }
126 127
     int err = XGrabKeyboard( m_display, m_root, False, GrabModeAsync, GrabModeAsync, CurrentTime );
127 128
     if ( err != GrabSuccess ) {
128 129
         fprintf( stderr, "Warning: Failed to grab X keyboard.\n" );
129 130
         fprintf( stderr, "         This happens when something has already grabbed your keybaord.\n" );
130 131
         fprintf( stderr, "         slop should still run properly though.\n" );
131
-        return 1;
132
+        return EXIT_FAILURE;
132 133
     }
133
-    return 0;
134
+    return EXIT_SUCCESS;
134 135
 }
135 136
 
136 137
 int slop::XEngine::releaseKeyboard() {
137 138
     if ( !m_good ) {
138
-        return 1;
139
+        return EXIT_FAILURE;
139 140
     }
140 141
     XUngrabKeyboard( m_display, CurrentTime );
141
-    return 0;
142
+    return EXIT_SUCCESS;
142 143
 }
143 144
 
144 145
 void slop::XEngine::selectAllInputs( Window win, long event_mask) {
@@ -156,7 +157,7 @@ void slop::XEngine::selectAllInputs( Window win, long event_mask) {
156 157
 // Grabs the cursor, be wary that setCursor changes the mouse masks.
157 158
 int slop::XEngine::grabCursor( slop::CursorType type ) {
158 159
     if ( !m_good ) {
159
-        return 1;
160
+        return EXIT_FAILURE;
160 161
     }
161 162
     int xfontcursor = getCursor( type );
162 163
     int err = XGrabPointer( m_display, m_root, True,
@@ -165,7 +166,7 @@ int slop::XEngine::grabCursor( slop::CursorType type ) {
165 166
     if ( err != GrabSuccess ) {
166 167
         fprintf( stderr, "Error: Failed to grab X cursor.\n" );
167 168
         fprintf( stderr, "       This can be caused by launching slop weirdly.\n" );
168
-        return 1;
169
+        return EXIT_FAILURE;
169 170
     }
170 171
     // Quickly set the mouse position so we don't have to worry about x11 generating an event.
171 172
     Window root, child;
@@ -183,15 +184,15 @@ int slop::XEngine::grabCursor( slop::CursorType type ) {
183 184
         XQueryPointer( m_display, child, &root, &test, &mx, &my, &wx, &wy, &mask );
184 185
     }
185 186
     m_hoverWindow = child;
186
-    return 0;
187
+    return EXIT_SUCCESS;
187 188
 }
188 189
 
189 190
 int slop::XEngine::releaseCursor() {
190 191
     if ( !m_good ) {
191
-        return 1;
192
+        return EXIT_FAILURE;
192 193
     }
193 194
     XUngrabPointer( m_display, CurrentTime );
194
-    return 0;
195
+    return EXIT_SUCCESS;
195 196
 }
196 197
 
197 198
 void slop::XEngine::tick() {
@@ -255,7 +256,7 @@ Cursor slop::XEngine::getCursor( slop::CursorType type ) {
255 256
         case Box:                   xfontcursor = 40; break;
256 257
     }
257 258
     Cursor newcursor = 0;
258
-    if ( m_cursors.size() > xfontcursor ) {
259
+    if ( m_cursors.size() > (unsigned int)xfontcursor ) {
259 260
         newcursor = m_cursors.at( xfontcursor );
260 261
     }
261 262
     if ( !newcursor ) {
@@ -278,11 +279,11 @@ void slop::XEngine::setCursor( slop::CursorType type ) {
278 279
 }
279 280
 
280 281
 void slop::WindowRectangle::applyPadding( int padding ) {
281
-    if ( m_width + padding*2 >= 0 ) {
282
+    if ( (int)m_width + padding*2 >= 0 ) {
282 283
         m_x -= padding;
283 284
         m_width += padding*2;
284 285
     }
285
-    if ( m_height + padding*2 >= 0 ) {
286
+    if ( (int)m_height + padding*2 >= 0 ) {
286 287
         m_y -= padding;
287 288
         m_height += padding*2;
288 289
     }
@@ -292,7 +293,7 @@ Window slop::WindowRectangle::getWindow() {
292 293
     return m_window;
293 294
 }
294 295
 
295
-void slop::WindowRectangle::applyMinMaxSize( int minimumsize, int maximumsize ) {
296
+void slop::WindowRectangle::applyMinMaxSize( unsigned int minimumsize, unsigned int maximumsize ) {
296 297
     if ( minimumsize > maximumsize && maximumsize > 0 ) {
297 298
         fprintf( stderr, "Error: minimumsize is greater than maximumsize.\n" );
298 299
         exit( 1 );
@@ -328,7 +329,6 @@ void slop::WindowRectangle::setGeometry( Window win, bool decorations ) {
328 329
         Window root, parent, test, junk;
329 330
         Window* childlist;
330 331
         unsigned int ujunk;
331
-        unsigned int depth;
332 332
         // Try to find the actual decorations.
333 333
         test = win;
334 334
         int status = XQueryTree( xengine->m_display, test, &root, &parent, &childlist, &ujunk);

x.hpp → src/x.hpp View File

@@ -61,7 +61,7 @@ public:
61 61
     Window       getWindow();
62 62
     void         setGeometry( Window win, bool decorations );
63 63
     void         applyPadding( int padding );
64
-    void         applyMinMaxSize( int minimumsize, int maximumsize );
64
+    void         applyMinMaxSize( unsigned int minimumsize, unsigned int maximumsize );
65 65
 };
66 66
 
67 67
 class XEngine {
@@ -77,8 +77,8 @@ public:
77 77
     int                 releaseKeyboard();
78 78
     void                setCursor( slop::CursorType type );
79 79
     void                drawRect( int x, int y, unsigned int w, unsigned int h );
80
-    int                 getWidth();
81
-    int                 getHeight();
80
+    unsigned int        getWidth();
81
+    unsigned int        getHeight();
82 82
     int                 m_mousex;
83 83
     int                 m_mousey;
84 84
     Display*            m_display;