X-Git-Url: http://git.ieval.ro/?p=xfishtank.git;a=blobdiff_plain;f=src%2Fwmctrl.c;fp=src%2Fwmctrl.c;h=80a452cc2bcabd9884fea58402ac268f0f7f7c14;hp=0000000000000000000000000000000000000000;hb=da1c4a843de05b6ee70dc60fa1fcb4b5ec2d606e;hpb=46b872af07138bfc36763f380b876098af4a6b5d diff --git a/src/wmctrl.c b/src/wmctrl.c new file mode 100644 index 0000000..80a452c --- /dev/null +++ b/src/wmctrl.c @@ -0,0 +1,382 @@ +/* -copyright- +#-# Copyright © 2021 Eric Bina, Dave Black, TJ Phan, +#-# Vincent Renardias, Willem Vermin +#-# +#-# Permission is hereby granted, free of charge, to any person +#-# obtaining a copy of this software and associated documentation +#-# files (the “Software”), to deal in the Software without +#-# restriction, including without limitation the rights to use, +#-# copy, modify, merge, publish, distribute, sublicense, and/or +#-# sell copies of the Software, and to permit persons to whom +#-# the Software is furnished to do so, subject to the following +#-# conditions: +#-# +#-# The above copyright notice and this permission notice shall +#-# be included in all copies or substantial portions of the Software. +#-# +#-# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +#-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +#-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +#-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +#-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +#-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +#-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +#-# OTHER DEALINGS IN THE SOFTWARE. +#-# +*/ +/* + * This works with EWHM/NetWM compatible X Window managers, + * so enlightenment (for example) is a problem. + * In enlightenment there is no way to tell if a window is minimized, + * and on which workspace the focus is. + * There would be one advantage of enlightenment: you can tell easily + * if a window is on the screen (minimized or not) by looking at __E_WINDOW_MAPPED + */ + +#include +#include +#include +#include +#include +#include +#include +#include "wmctrl.h" +//#include "windows.h" +//#include "dsimple.h" +#include "xfishtank.h" +#include "debug.h" + +int GetWindows(WinInfo **windows, int *nwin) +{ + Atom type; + int format; + unsigned long b; + unsigned char *properties = NULL; + (*windows) = NULL; + static Display *getdisplay;; + Window *children; + long unsigned int nchildren; + + static Atom atom_gtk_frame_extents; + static Atom atom_net_client_list; + static Atom atom_net_frame_extents; + static Atom atom_net_showing_desktop; + static Atom atom_net_wm_desktop; + static Atom atom_net_wm_state; + static Atom atom_net_wm_window_type; + static Atom atom_win_client_list; + static Atom atom_win_workspace; + static Atom atom_wm_state; + + static Window Rootwindow; + + static int firstcall = 1; + if(firstcall) + { + firstcall = 0; + getdisplay = Dpy; + + atom_gtk_frame_extents = XInternAtom(getdisplay, "_GTK_FRAME_EXTENTS" ,False); + atom_net_client_list = XInternAtom(getdisplay, "_NET_CLIENT_LIST" ,False); + atom_net_frame_extents = XInternAtom(getdisplay, "_NET_FRAME_EXTENTS" ,False); + atom_net_showing_desktop = XInternAtom(getdisplay, "_NET_SHOWING_DESKTOP" ,False); + atom_net_wm_desktop = XInternAtom(getdisplay, "_NET_WM_DESKTOP" ,False); + atom_net_wm_state = XInternAtom(getdisplay, "_NET_WM_STATE" ,False); + atom_net_wm_window_type = XInternAtom(getdisplay, "_NET_WM_WINDOW_TYPE" ,False); + atom_win_client_list = XInternAtom(getdisplay, "_WIN_CLIENT_LIST" ,False); + atom_win_workspace = XInternAtom(getdisplay, "_WIN_WORKSPACE" ,False); + atom_wm_state = XInternAtom(getdisplay, "WM_STATE" ,False); + + Rootwindow = DefaultRootWindow(getdisplay); + } + + XGetWindowProperty(getdisplay, DefaultRootWindow(getdisplay), atom_net_client_list, 0, 1000000, False, + AnyPropertyType, &type, &format, &nchildren, &b, (unsigned char**)&children); + if(type == XA_WINDOW) + { + P("_NET_CLIENT_LIST succeeded\n"); + } + else + { + P("No _NET_CLIENT_LIST, trying _WIN_CLIENT_LIST\n"); + if(children) + { + XFree(children); + children = NULL; + } + XGetWindowProperty(getdisplay, DefaultRootWindow(getdisplay), atom_win_client_list, 0, 1000000, False, + AnyPropertyType, &type, &format, &nchildren, &b, (unsigned char**)&children); + if(type == XA_WINDOW) + { + P("_WIN_CLIENT_LIST succeeded\n"); + } + } + if(type != XA_WINDOW) + { + P("No _WIN_CLIENT_LIST, trying XQueryTree\n"); + if(children) + { + XFree(children); + children = NULL; + } + Window dummy; + unsigned int n; + XQueryTree(getdisplay,DefaultRootWindow(getdisplay),&dummy,&dummy,&children,&n); + nchildren = n; + } + P("----------------------------------------- nchildren: %ld\n",nchildren); + (*nwin) = nchildren; + (*windows) = NULL; + if(nchildren>0) + (*windows) = (WinInfo *)malloc(nchildren*sizeof(WinInfo)); + WinInfo *w = (*windows); + int k = 0; + + // and yet another check if window is hidden (needed e.g. in KDE/plasma after 'hide all windows') + int globalhidden = 0; + { + P("hidden3 %d %#lx\n",counter++,w->id); + if (atom_net_showing_desktop) + { + Atom type; + unsigned long nitems, b; int format; + unsigned char *properties = NULL; + P("hidden3 try _NET_SHOWING_DESKTOP\n"); + XGetWindowProperty(getdisplay, Rootwindow, atom_net_showing_desktop, 0, (~0L), False, + AnyPropertyType, &type, &format, &nitems, &b, &properties); + if(format == 32 && nitems >=1) + { + if(*(long*) properties == 1) + globalhidden = 1; + P("hidden3 hidden:%d\n",globalhidden); + } + if(properties) XFree(properties); + } + } + + unsigned long i; + for (i=0; iid = children[i]; + + XWindowAttributes winattr; + XGetWindowAttributes(getdisplay, w->id, &winattr); + + x0 = winattr.x; + y0 = winattr.y; + w->w = winattr.width; + w->h = winattr.height; + depth = winattr.depth; + + P("%d %#lx %d %d %d %d %d\n",counter++,w->id,x0,y0,w->w,w->h,depth); + // if this window is showing nothing, we ignore it: + if (depth == 0) + continue; + + Window child_return; + XTranslateCoordinates(getdisplay, w->id, Rootwindow, 0, 0, &xr, &yr, &child_return); + w->xa = xr - x0; + w->ya = yr - y0; + P("%d %#lx %d %d %d %d %d\n",counter++,w->id,w->xa,w->ya,w->w,w->h,depth); + + XTranslateCoordinates(getdisplay, w->id, xfishtankWin, 0, 0, &(w->x), &(w->y), &child_return); + + enum{NET,GTK}; + Atom type; int format; unsigned long nitems,b; unsigned char *properties = NULL; + XGetWindowProperty(getdisplay, w->id, atom_net_wm_desktop, 0, 1, False, + AnyPropertyType, &type, &format, &nitems, &b, &properties); + if(type != XA_CARDINAL) + { + if(properties) XFree(properties); + properties = NULL; + XGetWindowProperty(getdisplay, w->id, atom_win_workspace, 0, 1, False, + AnyPropertyType, &type, &format, &nitems, &b, &properties); + } + if(properties) + { + w->ws = *(long*) properties; + if(properties) XFree(properties); + } + else + w->ws = 0; + // maybe this window is sticky: + w->sticky = 0; + properties = NULL; + nitems = 0; + XGetWindowProperty(getdisplay, w->id, atom_net_wm_state, 0, (~0L), False, + AnyPropertyType, &type, &format, &nitems, &b, &properties); + if (type == XA_ATOM) + { + int i; + for(i=0; (unsigned long)iid); + w->sticky = 1; + if(s) XFree(s); + break; + } + if(s) XFree(s); + } + } + // another sticky test, needed in KDE en LXDE: + if (w->ws == -1) + w->sticky = 1; + if(properties) XFree(properties); + + // check if window is a "dock". + w->dock = 0; + properties = NULL; + nitems = 0; + XGetWindowProperty(getdisplay, w->id, atom_net_wm_window_type, 0, (~0L), False, + AnyPropertyType, &type, &format, &nitems, &b, &properties); + if(format == 32) + { + int i; + for(i=0; (unsigned long)iid, counter++); + w->dock = 1; + if(s) XFree(s); + break; + } + if(s) XFree(s); + } + } + if(properties) XFree(properties); + + // check if window is hidden + w->hidden = globalhidden; + if(!w->hidden) + { + if (winattr.map_state != IsViewable) + { + P("map_state: %#lx %d\n",w->id,winattr.map_state); + w->hidden = 1; + } + } + // another check on hidden + if (!w->hidden) + { + properties = NULL; + nitems = 0; + XGetWindowProperty(getdisplay, w->id, atom_net_wm_state, 0, (~0L), False, + AnyPropertyType, &type, &format, &nitems, &b, &properties); + if(format == 32) + { + unsigned long i; + for (i=0; i