2 #-# Copyright © 2021 Eric Bina, Dave Black, TJ Phan,
3 #-# Vincent Renardias, Willem Vermin
5 #-# Permission is hereby granted, free of charge, to any person
6 #-# obtaining a copy of this software and associated documentation
7 #-# files (the “Software”), to deal in the Software without
8 #-# restriction, including without limitation the rights to use,
9 #-# copy, modify, merge, publish, distribute, sublicense, and/or
10 #-# sell copies of the Software, and to permit persons to whom
11 #-# the Software is furnished to do so, subject to the following
14 #-# The above copyright notice and this permission notice shall
15 #-# be included in all copies or substantial portions of the Software.
17 #-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
18 #-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 #-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 #-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 #-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 #-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 #-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 #-# OTHER DEALINGS IN THE SOFTWARE.
28 * This works with EWHM/NetWM compatible X Window managers,
29 * so enlightenment (for example) is a problem.
30 * In enlightenment there is no way to tell if a window is minimized,
31 * and on which workspace the focus is.
32 * There would be one advantage of enlightenment: you can tell easily
33 * if a window is on the screen (minimized or not) by looking at __E_WINDOW_MAPPED
39 #include <X11/Xatom.h>
40 #include <X11/extensions/shape.h>
44 //#include "windows.h"
45 //#include "dsimple.h"
46 #include "xfishtank.h"
49 int GetWindows(WinInfo
**windows
, int *nwin
)
54 unsigned char *properties
= NULL
;
56 static Display
*getdisplay
;;
58 long unsigned int nchildren
;
60 static Atom atom_gtk_frame_extents
;
61 static Atom atom_net_client_list
;
62 static Atom atom_net_frame_extents
;
63 static Atom atom_net_showing_desktop
;
64 static Atom atom_net_wm_desktop
;
65 static Atom atom_net_wm_state
;
66 static Atom atom_net_wm_window_type
;
67 static Atom atom_win_client_list
;
68 static Atom atom_win_workspace
;
69 static Atom atom_wm_state
;
71 static Window Rootwindow
;
73 static int firstcall
= 1;
79 atom_gtk_frame_extents
= XInternAtom(getdisplay
, "_GTK_FRAME_EXTENTS" ,False
);
80 atom_net_client_list
= XInternAtom(getdisplay
, "_NET_CLIENT_LIST" ,False
);
81 atom_net_frame_extents
= XInternAtom(getdisplay
, "_NET_FRAME_EXTENTS" ,False
);
82 atom_net_showing_desktop
= XInternAtom(getdisplay
, "_NET_SHOWING_DESKTOP" ,False
);
83 atom_net_wm_desktop
= XInternAtom(getdisplay
, "_NET_WM_DESKTOP" ,False
);
84 atom_net_wm_state
= XInternAtom(getdisplay
, "_NET_WM_STATE" ,False
);
85 atom_net_wm_window_type
= XInternAtom(getdisplay
, "_NET_WM_WINDOW_TYPE" ,False
);
86 atom_win_client_list
= XInternAtom(getdisplay
, "_WIN_CLIENT_LIST" ,False
);
87 atom_win_workspace
= XInternAtom(getdisplay
, "_WIN_WORKSPACE" ,False
);
88 atom_wm_state
= XInternAtom(getdisplay
, "WM_STATE" ,False
);
90 Rootwindow
= DefaultRootWindow(getdisplay
);
93 XGetWindowProperty(getdisplay
, DefaultRootWindow(getdisplay
), atom_net_client_list
, 0, 1000000, False
,
94 AnyPropertyType
, &type
, &format
, &nchildren
, &b
, (unsigned char**)&children
);
97 P("_NET_CLIENT_LIST succeeded\n");
101 P("No _NET_CLIENT_LIST, trying _WIN_CLIENT_LIST\n");
107 XGetWindowProperty(getdisplay
, DefaultRootWindow(getdisplay
), atom_win_client_list
, 0, 1000000, False
,
108 AnyPropertyType
, &type
, &format
, &nchildren
, &b
, (unsigned char**)&children
);
109 if(type
== XA_WINDOW
)
111 P("_WIN_CLIENT_LIST succeeded\n");
114 if(type
!= XA_WINDOW
)
116 P("No _WIN_CLIENT_LIST, trying XQueryTree\n");
124 XQueryTree(getdisplay
,DefaultRootWindow(getdisplay
),&dummy
,&dummy
,&children
,&n
);
127 P("----------------------------------------- nchildren: %ld\n",nchildren
);
131 (*windows
) = (WinInfo
*)malloc(nchildren
*sizeof(WinInfo
));
132 WinInfo
*w
= (*windows
);
135 // and yet another check if window is hidden (needed e.g. in KDE/plasma after 'hide all windows')
136 int globalhidden
= 0;
138 P("hidden3 %d %#lx\n",counter
++,w
->id
);
139 if (atom_net_showing_desktop
)
142 unsigned long nitems
, b
; int format
;
143 unsigned char *properties
= NULL
;
144 P("hidden3 try _NET_SHOWING_DESKTOP\n");
145 XGetWindowProperty(getdisplay
, Rootwindow
, atom_net_showing_desktop
, 0, (~0L), False
,
146 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
147 if(format
== 32 && nitems
>=1)
149 if(*(long*) properties
== 1)
151 P("hidden3 hidden:%d\n",globalhidden
);
153 if(properties
) XFree(properties
);
158 for (i
=0; i
<nchildren
; i
++)
165 XWindowAttributes winattr
;
166 XGetWindowAttributes(getdisplay
, w
->id
, &winattr
);
170 w
->w
= winattr
.width
;
171 w
->h
= winattr
.height
;
172 depth
= winattr
.depth
;
174 P("%d %#lx %d %d %d %d %d\n",counter
++,w
->id
,x0
,y0
,w
->w
,w
->h
,depth
);
175 // if this window is showing nothing, we ignore it:
180 XTranslateCoordinates(getdisplay
, w
->id
, Rootwindow
, 0, 0, &xr
, &yr
, &child_return
);
183 P("%d %#lx %d %d %d %d %d\n",counter
++,w
->id
,w
->xa
,w
->ya
,w
->w
,w
->h
,depth
);
185 XTranslateCoordinates(getdisplay
, w
->id
, xfishtankWin
, 0, 0, &(w
->x
), &(w
->y
), &child_return
);
188 Atom type
; int format
; unsigned long nitems
,b
; unsigned char *properties
= NULL
;
189 XGetWindowProperty(getdisplay
, w
->id
, atom_net_wm_desktop
, 0, 1, False
,
190 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
191 if(type
!= XA_CARDINAL
)
193 if(properties
) XFree(properties
);
195 XGetWindowProperty(getdisplay
, w
->id
, atom_win_workspace
, 0, 1, False
,
196 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
200 w
->ws
= *(long*) properties
;
201 if(properties
) XFree(properties
);
205 // maybe this window is sticky:
209 XGetWindowProperty(getdisplay
, w
->id
, atom_net_wm_state
, 0, (~0L), False
,
210 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
214 for(i
=0; (unsigned long)i
<nitems
; i
++)
217 s
= XGetAtomName(getdisplay
,((Atom
*)properties
)[i
]);
218 if (!strcmp(s
,"_NET_WM_STATE_STICKY"))
220 P("%#lx is sticky\n",w
->id
);
228 // another sticky test, needed in KDE en LXDE:
231 if(properties
) XFree(properties
);
233 // check if window is a "dock".
237 XGetWindowProperty(getdisplay
, w
->id
, atom_net_wm_window_type
, 0, (~0L), False
,
238 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
242 for(i
=0; (unsigned long)i
<nitems
; i
++)
245 s
= XGetAtomName(getdisplay
,((Atom
*)properties
)[i
]);
246 if (!strcmp(s
,"_NET_WM_WINDOW_TYPE_DOCK"))
248 P("%#lx is dock %d\n",w
->id
, counter
++);
256 if(properties
) XFree(properties
);
258 // check if window is hidden
259 w
->hidden
= globalhidden
;
262 if (winattr
.map_state
!= IsViewable
)
264 P("map_state: %#lx %d\n",w
->id
,winattr
.map_state
);
268 // another check on hidden
273 XGetWindowProperty(getdisplay
, w
->id
, atom_net_wm_state
, 0, (~0L), False
,
274 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
278 for (i
=0; i
<nitems
; i
++)
281 s
= XGetAtomName(getdisplay
,((Atom
*)properties
)[i
]);
282 if (!strcmp(s
,"_NET_WM_STATE_HIDDEN"))
284 P("%#lx is hidden %d\n",w
->id
, counter
++);
292 if(properties
) XFree(properties
);
295 // yet another check if window is hidden:
298 P("hidden2 %#lx\n",w
->id
);
301 XGetWindowProperty(getdisplay
, w
->id
, atom_wm_state
, 0, (~0L), False
,
302 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
303 if(format
== 32 && nitems
>=1)
305 // see https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1
309 if(*(long*) properties
!= NormalState
)
312 if(properties
) XFree(properties
);
318 // first try to get adjustments for _GTK_FRAME_EXTENTS
319 if (atom_gtk_frame_extents
)
320 XGetWindowProperty(getdisplay
, w
->id
, atom_gtk_frame_extents
, 0, 4, False
,
321 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
323 // if not succesfull, try _NET_FRAME_EXTENTS
326 if(properties
) XFree(properties
);
328 P("trying net...\n");
329 XGetWindowProperty(getdisplay
, w
->id
, atom_net_frame_extents
, 0, 4, False
,
330 AnyPropertyType
, &type
, &format
, &nitems
, &b
, &properties
);
333 P("nitems: %ld %ld %d\n",type
,nitems
,format
);
334 if(nitems
== 4 && format
== 32 && type
) // adjust x,y,w,h of window
336 long *r
; // borderleft, borderright, top decoration, bottomdecoration
337 r
= (long*)properties
;
338 P("RRRR: %ld %ld %ld %ld\n",r
[0],r
[1],r
[2],r
[3]);
356 I("Xfishtank encountered a serious problem, exiting ...\n");
360 P("NET/GTK: %#lx %d %d %d %d %d\n", w
->id
,w
->ws
,w
->x
,w
->y
,w
->w
,w
->h
);
364 // this is a problem....
365 // In for example TWM, neither NET nor GTK is the case.
366 // Let us try this one:
369 P("%d %#lx %d %d\n",counter
++,w
->id
,w
->x
,w
->y
);
371 if(properties
)XFree(properties
);
375 if(properties
) XFree(properties
);
377 //P("%d\n",counter++);printwindows(getdisplay,*windows,*nwin);