소스 검색

fixed a few bugs and added window selections

naelstrof 10 년 전
부모
커밋
a4afa890fe
4개의 변경된 파일135개의 추가작업 그리고 27개의 파일을 삭제
  1. 7
    3
      README.md
  2. 51
    9
      main.cpp
  3. 64
    15
      x.cpp
  4. 13
    0
      x.hpp

+ 7
- 3
README.md 파일 보기

@@ -1,7 +1,11 @@
1 1
 slrn
2
-----
2
+====
3 3
 
4 4
 slrn is an application that literally just allows a user to select a region of his screen. It grabs the cursor, draws a fancy box, and prints the selection's dimensions and position to stdout.
5 5
 
6
-It does a better job than scrot's selection since it doesn't draw directly to the root window, it creates its own to draw the selection rectangle.
7
-However due to the X11's Shape extension and window resizing not being synchronized it doesn't render a perfect box during movement. I'm hoping to fix this later by never resizing the window.
6
+features
7
+--------
8
+* Clicking on a window makes slrn return the dimensions of the window.
9
+* 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.
10
+* Hovering over a window will cause a selection rectangle to appear over it.
11
+* On startup it turns your cursor into a crosshair, then adjusts the cursor into angles as you drag the selection rectangle.

+ 51
- 9
main.cpp 파일 보기

@@ -5,24 +5,50 @@ int main( int argc, char** argv ) {
5 5
     int state = 0;
6 6
     bool running = true;
7 7
     is::Rectangle* selection;
8
+    is::Rectangle* windowselection = NULL;
9
+    Window window = None;
8 10
 
9 11
     xengine->init( ":0" );
10 12
     xengine->grabCursor( is::Cross );
11 13
     while ( running ) {
12 14
         xengine->tick();
15
+        if ( xengine->mouseDown( 3 ) ) {
16
+            printf( "X: 0\n" );
17
+            printf( "Y: 0\n" );
18
+            printf( "W: 0\n" );
19
+            printf( "H: 0\n" );
20
+            printf( "User right-clicked. Canceled selection.\n" );
21
+            state = -1;
22
+            running = false;
23
+        }
13 24
         switch ( state ) {
25
+            default: {
26
+                break;
27
+            }
14 28
             case 0: {
29
+                if ( window != xengine->m_hoverXWindow ) {
30
+                    if ( windowselection ) {
31
+                        xengine->removeRect( windowselection );
32
+                    }
33
+                    is::WindowRectangle t = xengine->m_hoverWindow;
34
+                    windowselection = new is::Rectangle( t.m_x,
35
+                                                         t.m_y,
36
+                                                         t.m_width,
37
+                                                         t.m_height,
38
+                                                         10, 0 );
39
+                    xengine->addRect( windowselection );
40
+                    window = xengine->m_hoverXWindow;
41
+                }
15 42
                 if ( xengine->mouseDown( 1 ) ) {
43
+                    if ( windowselection ) {
44
+                        xengine->removeRect( windowselection );
45
+                    }
16 46
                     state++;
17 47
                 }
18 48
                 break;
19 49
             }
20 50
             case 1: {
21
-                // Check to make sure we actually have a cursor position before creating the selection rectangle.
22
-                if ( xengine->m_mousex == -1 ) {
23
-                    break;
24
-                }
25
-                selection = new is::Rectangle( xengine->m_mousex, xengine->m_mousey, 1, 1, 10, 0 );
51
+                selection = new is::Rectangle( xengine->m_mousex, xengine->m_mousey, 0, 0, 10, 0 );
26 52
                 selection->setPos( xengine->m_mousex, xengine->m_mousey );
27 53
                 xengine->addRect( selection );
28 54
                 state++;
@@ -50,12 +76,28 @@ int main( int argc, char** argv ) {
50 76
                 break;
51 77
             }
52 78
             case 3: {
53
-                printf( "X: %i\n", selection->m_x+selection->m_xoffset );
54
-                printf( "Y: %i\n", selection->m_y+selection->m_yoffset );
55
-                printf( "W: %i\n", selection->m_width + 1 );
56
-                printf( "H: %i\n", selection->m_height + 1 );
79
+                int x = selection->m_x+selection->m_xoffset;
80
+                int y = selection->m_y+selection->m_yoffset;
81
+                int w = selection->m_width;
82
+                int h = selection->m_height;
57 83
                 xengine->removeRect( selection );
58 84
                 running = false;
85
+                if ( w || h || xengine->m_hoverXWindow == None ) {
86
+                    printf( "X: %i\n", x );
87
+                    printf( "Y: %i\n", y );
88
+                    printf( "W: %i\n", w + 1 );
89
+                    printf( "H: %i\n", h + 1 );
90
+                    break;
91
+                }
92
+                is::WindowRectangle t = xengine->m_hoverWindow;
93
+                x = t.m_x;
94
+                y = t.m_y;
95
+                w = t.m_width + t.m_border;
96
+                h = t.m_height + t.m_border;
97
+                printf( "X: %i\n", x );
98
+                printf( "Y: %i\n", y );
99
+                printf( "W: %i\n", w );
100
+                printf( "H: %i\n", h );
59 101
                 break;
60 102
             }
61 103
         }

+ 64
- 15
x.cpp 파일 보기

@@ -9,6 +9,7 @@ is::XEngine::XEngine() {
9 9
     m_good = false;
10 10
     m_mousex = -1;
11 11
     m_mousey = -1;
12
+    m_hoverXWindow = None;
12 13
 }
13 14
 
14 15
 is::XEngine::~XEngine() {
@@ -76,6 +77,16 @@ int is::XEngine::grabCursor( is::CursorType type ) {
76 77
         printf( "Failed to grab X cursor\n" );
77 78
         return 1;
78 79
     }
80
+
81
+    // Quickly set the mouse position so we don't have to worry about x11 generating an event.
82
+    Window root, child;
83
+    int mx, my;
84
+    int wx, wy;
85
+    unsigned int mask;
86
+    XQueryPointer( m_display, m_root, &root, &child, &mx, &my, &wx, &wy, &mask );
87
+    m_mousex = mx;
88
+    m_mousex = my;
89
+    updateHoverWindow( child );
79 90
     return 0;
80 91
 }
81 92
 
@@ -91,7 +102,7 @@ void is::XEngine::tick() {
91 102
     if ( !m_good ) {
92 103
         return;
93 104
     }
94
-    XFlush( m_display );
105
+    XSync( m_display, false );
95 106
     XEvent event;
96 107
     while ( XPending( m_display ) ) {
97 108
         XNextEvent( m_display, &event );
@@ -119,8 +130,12 @@ void is::XEngine::tick() {
119 130
                 }
120 131
                 break;
121 132
             }
133
+            default: break;
122 134
         }
123 135
     }
136
+
137
+    // Since I couldn't get Xlib to send a EnterNotify or LeaveNotify events, we need to query the underlying window every frame.
138
+    updateHoverWindow();
124 139
 }
125 140
 
126 141
 Cursor is::XEngine::getCursor( is::CursorType type ) {
@@ -153,7 +168,7 @@ void is::XEngine::setCursor( is::CursorType type ) {
153 168
     }
154 169
     Cursor xfontcursor = getCursor( type );
155 170
     XChangeActivePointerGrab( m_display,
156
-                              ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
171
+                              PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
157 172
                               xfontcursor, CurrentTime );
158 173
 }
159 174
 
@@ -181,12 +196,6 @@ is::Rectangle::Rectangle( int x, int y, int width, int height, int border, int p
181 196
         m_yoffset += m_height;
182 197
         m_height = -m_height;
183 198
     }
184
-    if ( m_width == 0 ) {
185
-        m_width = 1;
186
-    }
187
-    if ( m_height == 0 ) {
188
-        m_height = 1;
189
-    }
190 199
 
191 200
     XAllocNamedColor( xengine->m_display, xengine->m_colormap, "black", &m_forground, &m_forgroundExact );
192 201
     XAllocNamedColor( xengine->m_display, xengine->m_colormap, "white", &m_background, &m_backgroundExact );
@@ -200,7 +209,7 @@ is::Rectangle::Rectangle( int x, int y, int width, int height, int border, int p
200 209
                               CWSaveUnder | CWOverrideRedirect |
201 210
                               CWColormap;
202 211
 
203
-    m_window = XCreateWindow( xengine->m_display, xengine->m_root, m_x+m_xoffset, m_y+m_yoffset, m_width+m_border*2, m_height+m_border*2,
212
+    m_window = XCreateWindow( xengine->m_display, xengine->m_root, m_x-m_border+m_xoffset, m_y-m_border+m_yoffset, m_width+m_border*2, m_height+m_border*2,
204 213
                               0, CopyFromParent, InputOutput,
205 214
                               CopyFromParent, valueMask, &attributes );
206 215
     XRectangle rect;
@@ -240,12 +249,6 @@ void is::Rectangle::setDim( int w, int h ) {
240 249
         m_yoffset += h;
241 250
         m_height = -h;
242 251
     }
243
-    if ( m_width == 0 ) {
244
-        m_width = 1;
245
-    }
246
-    if ( m_height == 0 ) {
247
-        m_height = 1;
248
-    }
249 252
     XResizeWindow( xengine->m_display, m_window, m_width+m_border*2, m_height+m_border*2 );
250 253
     XMoveWindow( xengine->m_display, m_window, m_x-m_border+m_xoffset, m_y-m_border+m_yoffset );
251 254
     // Now punch another hole in it.
@@ -264,3 +267,49 @@ void is::Rectangle::setDim( int w, int h ) {
264 267
 
265 268
 void is::Rectangle::draw() {
266 269
 }
270
+
271
+void is::XEngine::updateHoverWindow() {
272
+    Window root, child;
273
+    int mx, my;
274
+    int wx, wy;
275
+    unsigned int mask;
276
+    XQueryPointer( m_display, m_root, &root, &child, &mx, &my, &wx, &wy, &mask );
277
+    if ( m_hoverXWindow == child ) {
278
+        return;
279
+    }
280
+    for ( unsigned int i=0; i<m_rects.size(); i++ ) {
281
+        if ( m_rects.at( i )->m_window == child ) {
282
+            return;
283
+        }
284
+    }
285
+    m_hoverXWindow = child;
286
+    if ( child == None ) {
287
+        return;
288
+    }
289
+    unsigned int depth;
290
+    XGetGeometry( m_display, child, &root,
291
+                  &(m_hoverWindow.m_x), &(m_hoverWindow.m_y),
292
+                  &(m_hoverWindow.m_width), &(m_hoverWindow.m_height),
293
+                  &(m_hoverWindow.m_border), &depth );
294
+}
295
+
296
+void is::XEngine::updateHoverWindow( Window child ) {
297
+    if ( m_hoverXWindow == child ) {
298
+        return;
299
+    }
300
+    for ( unsigned int i=0; i<m_rects.size(); i++ ) {
301
+        if ( m_rects.at( i )->m_window == child ) {
302
+            return;
303
+        }
304
+    }
305
+    m_hoverXWindow = child;
306
+    if ( child == None ) {
307
+        return;
308
+    }
309
+    unsigned int depth;
310
+    Window root;
311
+    XGetGeometry( m_display, child, &root,
312
+                  &(m_hoverWindow.m_x), &(m_hoverWindow.m_y),
313
+                  &(m_hoverWindow.m_width), &(m_hoverWindow.m_height),
314
+                  &(m_hoverWindow.m_border), &depth );
315
+}

+ 13
- 0
x.hpp 파일 보기

@@ -25,6 +25,15 @@ enum CursorType {
25 25
     LowerLeftCorner
26 26
 };
27 27
 
28
+class WindowRectangle {
29
+public:
30
+    int m_x;
31
+    int m_y;
32
+    unsigned int m_width;
33
+    unsigned int m_height;
34
+    unsigned int m_border;
35
+};
36
+
28 37
 class Rectangle {
29 38
 public:
30 39
             Rectangle( int x, int y, int width, int height, int border, int padding );
@@ -66,7 +75,11 @@ public:
66 75
     int                 m_mousey;
67 76
     std::vector<bool>   m_mouse;
68 77
     bool                mouseDown( unsigned int button );
78
+    WindowRectangle     m_hoverWindow;
79
+    Window              m_hoverXWindow;
69 80
 private:
81
+    void                updateHoverWindow();
82
+    void                updateHoverWindow( Window child );
70 83
     bool                m_good;
71 84
     std::vector<Cursor> m_cursors;
72 85
     std::vector<Rectangle*> m_rects;