33Copyright 2020-2021 Daniel T. Borelli <danieltborelli@gmail.com>
44Copyright 2021-2023 Guilherme Janczak <guilherme.janczak@yandex.com>
55Copyright 2021 Peter Wu <peterwu@hotmail.com>
6- Copyright 2023-2025 NRK <nrk@disroot.org>
6+ Copyright 2023-2026 NRK <nrk@disroot.org>
77
88Permission is hereby granted, free of charge, to any person obtaining a copy
99of this software and associated documentation files (the "Software"), to
@@ -38,7 +38,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3838#include <X11/Xatom.h>
3939#include <X11/Xlib.h>
4040#include <X11/Xutil.h>
41- #include <X11/extensions/shape.h>
4241
4342#include "options.h"
4443#include "scrot.h"
@@ -55,26 +54,28 @@ void selectionEdgeCreate(void)
5554 XSetWindowAttributes attr ;
5655 attr .background_pixel = color .pixel ;
5756 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 );
5860
59- pe -> wndDraw = XCreateWindow (disp , root , 0 , 0 , WidthOfScreen (scr ),
60- HeightOfScreen (scr ), 0 , CopyFromParent , InputOutput , CopyFromParent ,
61- CWOverrideRedirect | CWBackPixel , & attr );
62- pe -> isMapped = false;
61+ for (size_t i = 0 ; i < ARRAY_COUNT (pe -> windows ); ++ i ) {
62+ pe -> windows [i ] = XCreateWindow (disp , root ,
63+ 0 , 0 , WidthOfScreen (scr ), HeightOfScreen (scr ), 0 ,
64+ CopyFromParent , InputOutput , CopyFromParent ,
65+ CWOverrideRedirect | CWBackPixel , & attr );
6366
64- unsigned long opacity = opt .lineOpacity * (0xFFFFFFFFu / 255 );
67+ XChangeProperty (disp , pe -> windows [i ], winType , XA_ATOM , 32 ,
68+ PropModeReplace , (unsigned char * )& winDock , 1L );
6569
66- XChangeProperty ( disp , pe -> wndDraw ,
67- XInternAtom (disp , "_NET_WM_WINDOW_OPACITY" , False ) , XA_CARDINAL , 32 ,
68- PropModeReplace , (unsigned char * ) & opacity , 1L );
70+ unsigned long opacity = opt . lineOpacity * ( 0xFFFFFFFFu / 255 );
71+ XChangeProperty (disp , pe -> windows [ i ], winOpacity , XA_CARDINAL , 32 ,
72+ PropModeReplace , (unsigned char * )& opacity , 1L );
6973
70- XChangeProperty (disp , pe -> wndDraw ,
71- XInternAtom (disp , "_NET_WM_WINDOW_TYPE" , False ), XA_ATOM , 32 ,
72- PropModeReplace ,
73- (unsigned char * ) & (Atom ) { XInternAtom (disp , "_NET_WM_WINDOW_TYPE_DOCK" , False ) },
74- 1L );
74+ XClassHint hint = { .res_name = "scrot" , .res_class = "scrot" };
75+ XSetClassHint (disp , pe -> windows [i ], & hint );
76+ }
77+ pe -> isMapped = false;
7578
76- XClassHint hint = { .res_name = "scrot" , .res_class = "scrot" };
77- XSetClassHint (disp , pe -> wndDraw , & hint );
7879}
7980
8081void selectionEdgeDraw (void )
@@ -83,18 +84,22 @@ void selectionEdgeDraw(void)
8384 struct SelectionEdge * const pe = & sel -> edge ;
8485
8586 XRectangle rects [4 ] = {
86- { sel -> rect .x , sel -> rect .y , opt .lineWidth , sel -> rect .h }, // left
87+ { sel -> rect .x , sel -> rect .y + opt .lineWidth ,
88+ opt .lineWidth , sel -> rect .h - opt .lineWidth }, // left
8789 { sel -> rect .x , sel -> rect .y , sel -> rect .w , opt .lineWidth }, // top
88- // right
89- { sel -> rect .x + sel -> rect .w , sel -> rect .y , opt .lineWidth , sel -> rect .h },
90- // bottom
90+ { sel -> rect .x + sel -> rect .w , sel -> rect .y , opt .lineWidth , sel -> rect .h }, // right
9191 { sel -> rect .x , sel -> rect .y + sel -> rect .h , sel -> rect .w + opt .lineWidth ,
92- opt .lineWidth }
92+ opt .lineWidth } // bottom
9393 };
9494
95- XShapeCombineRectangles (disp , pe -> wndDraw , ShapeBounding , 0 , 0 , rects , 4 ,
96- ShapeSet , 0 );
97- XMapWindow (disp , pe -> wndDraw );
95+ if (sel -> rect .w == 0 || sel -> rect .h == 0 )
96+ return ;
97+
98+ for (size_t i = 0 ; i < ARRAY_COUNT (pe -> windows ); ++ i ) {
99+ XRectangle * rp = rects + i ;
100+ XMoveResizeWindow (disp , pe -> windows [i ], rp -> x , rp -> y , rp -> width , rp -> height );
101+ XMapWindow (disp , pe -> windows [i ]);
102+ }
98103 pe -> isMapped = true;
99104}
100105
@@ -116,15 +121,17 @@ void selectionEdgeDestroy(void)
116121{
117122 const struct SelectionEdge * pe = & selection .edge ;
118123
119- if (pe -> wndDraw != None ) {
120- XSelectInput (disp , pe -> wndDraw , StructureNotifyMask );
121- XDestroyWindow (disp , pe -> wndDraw );
124+ for (size_t i = 0 ; i < ARRAY_COUNT (pe -> windows ); ++ i ) {
125+ if (pe -> windows [i ] == None )
126+ continue ;
127+ XSelectInput (disp , pe -> windows [i ], StructureNotifyMask );
128+ XDestroyWindow (disp , pe -> windows [i ]);
122129 bool isUnmapped = !pe -> isMapped , isDestroyed = false;
123130 for (XEvent ev ; !(isUnmapped && isDestroyed );) {
124131 XNextEvent (disp , & ev );
125- if (ev .type == DestroyNotify && ev .xdestroywindow .window == pe -> wndDraw )
132+ if (ev .type == DestroyNotify && ev .xdestroywindow .window == pe -> windows [ i ] )
126133 isDestroyed = true;
127- if (ev .type == UnmapNotify && ev .xunmap .window == pe -> wndDraw )
134+ if (ev .type == UnmapNotify && ev .xunmap .window == pe -> windows [ i ] )
128135 isUnmapped = true;
129136 }
130137 }
0 commit comments