1 //  wminterface.cc for bbtools.
2 //
3 //  Copyright (c) 1998-2000 by John Kennis, jkennis@chello.nl
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 2 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 // (See the included file COPYING / GPL-2.0)
20 //
21 
22 #include "wminterface.h"
23 #include "resource.h"
24 
25 #include <stdio.h>
26 
WMInterface(ToolWindow * toolwindow)27 WMInterface::WMInterface(ToolWindow *toolwindow) :
28     bt::EventHandler(), bbtool(toolwindow)
29 {
30     root_window = bbtool->getCurrentScreenInfo()->rootWindow();
31     XSelectInput(bbtool->XDisplay(), root_window, PropertyChangeMask);
32     bbtool->insertEventHandler(root_window, this);
33     ewmh = bbtool->ewmh();
34 }
35 
~WMInterface()36 WMInterface::~WMInterface()
37 {
38 }
39 
sendClientMessage(Window window,Atom atom,XID data,XID data1)40 void WMInterface::sendClientMessage(Window window, Atom atom, XID data, XID data1) {
41   XEvent e;
42   unsigned long mask;
43 
44   e.xclient.type = ClientMessage;
45   e.xclient.window = window;
46   e.xclient.message_type = atom;
47   e.xclient.format = 32;
48   e.xclient.data.l[0] = (unsigned long) data;
49   e.xclient.data.l[1] = (unsigned long) data1;
50   mask =  SubstructureRedirectMask;
51   XSendEvent(bbtool->XDisplay(),
52              root_window,
53              False, mask, &e);
54 }
55 
56 
updateWindowList(void)57 void WMInterface::updateWindowList(void)
58 {
59     bt::EWMH::WindowList window_vect;
60     PagerWindow *pwindow;
61 
62     if (ewmh->readClientList(bbtool->getCurrentScreenInfo()->rootWindow(), window_vect)) {
63         /* add any new window windows */
64         bt::EWMH::WindowList::iterator it = window_vect.begin();
65         bt::EWMH::WindowList::iterator it_end = window_vect.end();
66         for (; it != it_end; it++) {
67             // skip myself
68             if ((*it) == bbtool->frameWindow()->window())
69             {
70                 continue;
71             }
72             pwindow = bbtool->findPagerWindow((*it));
73             if ( pwindow == NULL) {
74                 PagerWindow *pager_window = new PagerWindow(bbtool, *it);
75                 bbtool->pagerWindowList().push_back(pager_window);
76             } else {
77                 pwindow->mark(true);
78             }
79         }
80         /* delete any windows not in list */
81         std::list<PagerWindow *>::iterator pit = bbtool->pagerWindowList().begin();
82         std::list<PagerWindow *>::iterator pit_end = bbtool->pagerWindowList().end();
83 
84         for (; pit != pit_end; pit++) {
85             if (!(*pit)->isMarked()) {
86                 delete (*pit);
87                 bbtool->pagerWindowList().erase(pit);
88                 pit--;
89             } else {
90             }
91         }
92 
93     }
94 }
95 
updateWindowStack()96 void WMInterface::updateWindowStack()
97 {
98     bt::EWMH::WindowList window_vect;
99     if (ewmh->readClientListStacking(bbtool->getCurrentScreenInfo()->rootWindow(), window_vect)) {
100         // some check to see if we need update
101         PagerWindow *pwindow;
102         bt::EWMH::WindowList::iterator it = window_vect.begin();
103         bt::EWMH::WindowList::iterator it_end = window_vect.end();
104         for (; it != it_end; it++) {
105             pwindow = bbtool->findPagerWindow((*it));
106             if ( pwindow == NULL) continue;
107             pwindow->raise();
108         }
109     }
110 }
111 
112 
changeDesktop(int desk_number)113 void WMInterface::changeDesktop(int desk_number)
114 {
115 
116     sendClientMessage(root_window, ewmh->currentDesktop(), desk_number);
117 }
118 
119 
sendWindowToDesktop(Window win,int desk_number)120 void WMInterface::sendWindowToDesktop(Window win,int desk_number)
121 {
122     sendClientMessage(win, ewmh->wmDesktop(), desk_number);
123 }
124 
setWindowFocus(Window win)125 void WMInterface::setWindowFocus(Window win)
126 {
127     //ewmh->setActiveWindow(root_window, win);
128     sendClientMessage(win, ewmh->activeWindow(), win);
129 
130 }
131 
isIconicState(Window win)132 int WMInterface::isIconicState(Window win)
133 {
134     Atom real_type;
135     int format;
136     unsigned long n, extra;
137     int status;
138     long *p=0;
139     int result = -1;
140 
141     status = XGetWindowProperty(bbtool->XDisplay(), win,
142                               bbtool->wmStateAtom(), 0L, 1L,
143                               False, bbtool->wmStateAtom(), &real_type,
144                               &format, &n, &extra,  (unsigned char**)&p);
145     if (!status) {
146         if (p) {
147             result = (p[0]==IconicState) ? 1 : 0;
148             XFree(p);
149         } else
150             result = 0;
151     }
152 
153     return(result);
154 }
155 
changeNumberOfDesktops(int number_of_desktops)156 void WMInterface::changeNumberOfDesktops(int number_of_desktops)
157 {
158   int old_number_of_desktops = bbtool->getNumberOfDesktops();
159   bbtool->setNumberOfDesktops(number_of_desktops);
160   if (number_of_desktops > old_number_of_desktops) {
161   int i;
162   for (i=old_number_of_desktops;i<number_of_desktops;i++) {
163     bbtool->addDesktopWindow(i);
164     }
165   } else if (number_of_desktops<old_number_of_desktops)
166     bbtool->removeDesktopWindow();
167 }
168 
169 
readActiveWindow(Window target,Window * active)170 bool WMInterface::readActiveWindow(Window target, Window *active)
171 {
172   unsigned char* data = NULL;
173   if (ewmh->getProperty(target, XA_WINDOW, ewmh->activeWindow(), &data)) {
174     *active = * (reinterpret_cast<Window *>(data));
175     XFree(data);
176     return True;
177   }
178   return False;
179 }
180 
181 //property notify events, send to root window.
propertyNotifyEvent(const XPropertyEvent * const event)182 void WMInterface::propertyNotifyEvent(const XPropertyEvent * const event)
183 {
184      if (event->atom == ewmh->clientList()) {
185         updateWindowList();
186     } else if (event->atom == ewmh->clientListStacking()) {
187         updateWindowStack();
188     } else if (event->atom ==  ewmh->numberOfDesktops()) {
189         unsigned int number;
190         if (ewmh->readNumberOfDesktops(root_window, &number))
191             changeNumberOfDesktops(number);
192     } else if (event->atom == ewmh->desktopGeometry()) {
193 
194     } else if (event->atom == ewmh->currentDesktop()) {
195         unsigned int current_desktop;
196         if (!ewmh->readCurrentDesktop(root_window, &current_desktop))
197             fprintf(stderr, "Error: Cannot read current desktop\n");
198         else {
199             bbtool->desktopChange(current_desktop);
200         }
201     } else if (event->atom == ewmh->desktopNames()) {
202 
203     } else if (event->atom == ewmh->activeWindow()) {
204         Window active;
205         if (!readActiveWindow(root_window, &active)) {
206             fprintf(stderr, "Error: Cannot read active window\n");
207         } else {
208             bbtool->focusWindow(active);
209         }
210     } else if (event->atom == ewmh->workarea()) {
211 
212     } else {
213         // ignore
214     }
215 
216 
217 
218     //wminterface->windowAttributeChange(event->xproperty.window);
219 }
220 
221 
222