Skip to content

Commit c5fd92a

Browse files
committed
[WIP]: add --line mode=wind
Fixes: #76
1 parent be4a023 commit c5fd92a

File tree

6 files changed

+195
-10
lines changed

6 files changed

+195
-10
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ options.c options.h \
3939
scrot_selection.c scrot_selection.h \
4040
selection_classic.c selection_classic.h \
4141
selection_edge.c selection_edge.h \
42+
selection_wind.c selection_wind.h \
4243
util.c util.h

src/options.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ static void optionsParseLine(char *optarg)
338338
opt.lineMode = LINE_MODE_CLASSIC;
339339
else if (!strcmp(value, "edge"))
340340
opt.lineMode = LINE_MODE_EDGE;
341+
else if (!strcmp(value, "wind"))
342+
opt.lineMode = LINE_MODE_WIND;
341343
else {
342344
errx(EXIT_FAILURE, "Unknown value for suboption '%s': %s",
343345
token[Mode], value);

src/scrot_selection.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5151
#include "scrot_selection.h"
5252
#include "selection_classic.h"
5353
#include "selection_edge.h"
54+
#include "selection_wind.h"
5455
#include "util.h"
5556

5657
static void scrotSelectionCreate(void);
@@ -132,6 +133,11 @@ static void scrotSelectionCreate(void)
132133
sel->draw = selectionEdgeDraw;
133134
sel->motionDraw = selectionEdgeMotionDraw;
134135
sel->destroy = selectionEdgeDestroy;
136+
} else if (opt.lineMode == LINE_MODE_WIND) {
137+
sel->create = selectionWindCreate;
138+
sel->draw = selectionWindDraw;
139+
sel->motionDraw = selectionWindMotionDraw;
140+
sel->destroy = selectionWindDestroy;
135141
} else {
136142
// It never happened, fix the options.c file
137143
scrotAssert(0);
@@ -405,16 +411,8 @@ Imlib_Image scrotSelectionSelectMode(void)
405411
opt.selection.mode = SELECTION_MODE_CAPTURE;
406412

407413
if (opt.lineMode == LINE_MODE_AUTO) {
408-
char buf[128];
409-
snprintf(buf, sizeof(buf), "_NET_WM_CM_S%d", DefaultScreen(disp));
410-
Atom cm = XInternAtom(disp, buf, False);
411-
/* edge mode has some issues with compositor.
412-
* also doesn't work well in combination with --freeze.
413-
*/
414-
if (XGetSelectionOwner(disp, cm) == None && !opt.freeze)
415-
opt.lineMode = LINE_MODE_EDGE;
416-
else
417-
opt.lineMode = LINE_MODE_CLASSIC;
414+
/* wind mode doesn't work well in combination with --freeze. */
415+
opt.lineMode = opt.freeze ? LINE_MODE_CLASSIC : LINE_MODE_WIND;
418416
}
419417

420418
if (opt.lineWidth == 0) {

src/scrot_selection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ enum LineMode {
5454
LINE_MODE_AUTO,
5555
LINE_MODE_CLASSIC,
5656
LINE_MODE_EDGE,
57+
LINE_MODE_WIND,
5758
};
5859

5960
enum {
@@ -92,13 +93,18 @@ struct SelectionEdge {
9293
Window wndDraw;
9394
bool isMapped;
9495
};
96+
struct SelectionWind {
97+
Window windows[4];
98+
bool isMapped;
99+
};
95100

96101
struct Selection {
97102
Cursor curCross, curAngleNW, curAngleNE, curAngleSW, curAngleSE;
98103

99104
struct SelectionRect rect;
100105
struct SelectionClassic classic;
101106
struct SelectionEdge edge;
107+
struct SelectionWind wind;
102108

103109
void (*create)(void);
104110
void (*destroy)(void);

src/selection_wind.c

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
Copyright 2020-2021 Daniel T. Borelli <danieltborelli@gmail.com>
3+
Copyright 2021-2023 Guilherme Janczak <guilherme.janczak@yandex.com>
4+
Copyright 2021 Peter Wu <peterwu@hotmail.com>
5+
Copyright 2023-2026 NRK <nrk@disroot.org>
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to
9+
deal in the Software without restriction, including without limitation the
10+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11+
sell copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies of the Software and its documentation and acknowledgment shall be
16+
given in the documentation and software packages that this Software was
17+
used.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25+
26+
*/
27+
28+
/*
29+
This file is part of the scrot project.
30+
Part of the code comes from the scrot.c file and maintains its authorship.
31+
*/
32+
33+
#include <errno.h>
34+
#include <stdlib.h>
35+
#include <time.h>
36+
37+
#include <X11/Xatom.h>
38+
#include <X11/Xlib.h>
39+
#include <X11/Xutil.h>
40+
#include <X11/extensions/shape.h>
41+
42+
#include "options.h"
43+
#include "scrot.h"
44+
#include "scrot_selection.h"
45+
#include "selection_wind.h"
46+
#include "util.h"
47+
48+
void selectionWindCreate(void)
49+
{
50+
struct SelectionWind *const pw = &selection.wind;
51+
52+
XColor color = scrotSelectionGetLineColor();
53+
54+
XSetWindowAttributes attr;
55+
attr.background_pixel = color.pixel;
56+
attr.override_redirect = True;
57+
Atom winType = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False);
58+
Atom winDock = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False);
59+
Atom winOpacity = XInternAtom(disp, "_NET_WM_WINDOW_OPACITY", False);
60+
61+
for (size_t i = 0; i < ARRAY_COUNT(pw->windows); ++i) {
62+
pw->windows[i] = XCreateWindow(disp, root,
63+
0, 0, WidthOfScreen(scr), HeightOfScreen(scr), 0,
64+
CopyFromParent, InputOutput, CopyFromParent,
65+
CWOverrideRedirect | CWBackPixel, &attr);
66+
67+
XChangeProperty(disp, pw->windows[i], winType, XA_ATOM, 32,
68+
PropModeReplace, (unsigned char *)&winDock, 1L);
69+
70+
// NOTE: opacity has not been tested...
71+
unsigned long opacity = opt.lineOpacity * (0xFFFFFFFFu / 255);
72+
XChangeProperty(disp, pw->windows[i], winOpacity, XA_CARDINAL, 32,
73+
PropModeReplace, (unsigned char *)&opacity, 1L);
74+
75+
XClassHint hint = { .res_name = "scrot", .res_class = "scrot" };
76+
XSetClassHint(disp, pw->windows[i], &hint);
77+
}
78+
pw->isMapped = false;
79+
80+
}
81+
82+
void selectionWindDraw(void)
83+
{
84+
struct Selection *const sel = &selection;
85+
struct SelectionWind *const pw = &sel->wind;
86+
87+
XRectangle rects[4] = {
88+
{ sel->rect.x, sel->rect.y, opt.lineWidth, sel->rect.h }, // left
89+
{ sel->rect.x, sel->rect.y, sel->rect.w, opt.lineWidth }, // top
90+
// right
91+
{ sel->rect.x + sel->rect.w, sel->rect.y, opt.lineWidth, sel->rect.h },
92+
// bottom
93+
{ sel->rect.x, sel->rect.y + sel->rect.h, sel->rect.w + opt.lineWidth,
94+
opt.lineWidth }
95+
};
96+
97+
if (sel->rect.w == 0 || sel->rect.h == 0)
98+
return;
99+
100+
for (size_t i = 0; i < ARRAY_COUNT(pw->windows); ++i) {
101+
XRectangle *rp = rects + i;
102+
XMoveResizeWindow(disp, pw->windows[i], rp->x, rp->y, rp->width, rp->height);
103+
XMapWindow(disp, pw->windows[i]);
104+
}
105+
pw->isMapped = true;
106+
}
107+
108+
void selectionWindMotionDraw(int x0, int y0, int x1, int y1)
109+
{
110+
struct Selection *const sel = &selection;
111+
112+
selectionCalculateRect(x0, y0, x1, y1);
113+
114+
sel->rect.x -= opt.lineWidth;
115+
sel->rect.y -= opt.lineWidth;
116+
sel->rect.w += opt.lineWidth;
117+
sel->rect.h += opt.lineWidth;
118+
119+
selectionWindDraw();
120+
}
121+
122+
void selectionWindDestroy(void)
123+
{
124+
struct SelectionWind *const pw = &selection.wind;
125+
126+
for (size_t i = 0; i < ARRAY_COUNT(pw->windows); ++i) {
127+
if (pw->windows[i] == None)
128+
continue;
129+
XSelectInput(disp, pw->windows[i], StructureNotifyMask);
130+
XDestroyWindow(disp, pw->windows[i]);
131+
bool isUnmapped = !pw->isMapped, isDestroyed = false;
132+
for (XEvent ev; !(isUnmapped && isDestroyed);) {
133+
XNextEvent(disp, &ev);
134+
if (ev.type == DestroyNotify && ev.xdestroywindow.window == pw->windows[i])
135+
isDestroyed = true;
136+
if (ev.type == UnmapNotify && ev.xunmap.window == pw->windows[i])
137+
isUnmapped = true;
138+
}
139+
}
140+
}

src/selection_wind.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2026 NRK <nrk@disroot.org>
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to
6+
deal in the Software without restriction, including without limitation the
7+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
sell copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in
12+
all copies of the Software and its documentation and acknowledgment shall be
13+
given in the documentation and software packages that this Software was
14+
used.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
23+
*/
24+
25+
/*
26+
This file is part of the scrot project.
27+
Part of the code comes from the scrot.c file and maintains its authorship.
28+
*/
29+
30+
#ifndef H_SELECTION_WINDOW
31+
#define H_SELECTION_WINDOW
32+
33+
void selectionWindCreate(void);
34+
void selectionWindDraw(void);
35+
void selectionWindMotionDraw(int, int, int, int);
36+
void selectionWindDestroy(void);
37+
38+
#endif /* !defined(H_SELECTION_WINDOW) */

0 commit comments

Comments
 (0)