Browse Source

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

Dalton Nell 10 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;