#include "Manager.h"
#include "Client.h"
#include <X11/keysym.h>
#include <gtk/gtkmain.h>
int WindowManager::loop() {
XEvent ev;
m_looping = True;
while(m_looping) {
if(gtk_events_pending())
gtk_main_iteration();
if(XPending(display()) > 0) {
XNextEvent(display(), &ev);
m_currentTime = CurrentTime;
switch (ev.type) {
case ButtonPress:
eventButton(&ev.xbutton);
break;
case ButtonRelease:
break;
case MapRequest:
eventMapRequest(&ev.xmaprequest);
break;
case ConfigureRequest:
eventConfigureRequest(&ev.xconfigurerequest);
updateClientList();
break;
case UnmapNotify:
eventUnmap(&ev.xunmap);
updateClientList();
break;
case CreateNotify:
eventCreate(&ev.xcreatewindow);
updateClientList();
break;
case DestroyNotify:
eventDestroy(&ev.xdestroywindow);
updateClientList();
break;
case ClientMessage:
eventClient(&ev.xclient);
break;
case ColormapNotify:
eventColormap(&ev.xcolormap);
break;
case PropertyNotify:
eventProperty(&ev.xproperty);
break;
case SelectionClear:
case SelectionNotify:
case SelectionRequest:
break;
case EnterNotify:
case LeaveNotify:
eventEnter(&ev.xcrossing);
break;
case ReparentNotify:
eventReparent(&ev.xreparent);
break;
case FocusIn:
eventFocusIn(&ev.xfocus);
break;
case Expose:
eventExposure(&ev.xexpose);
break;
case MotionNotify:
if (auto_raise && m_focusChanging) {
if (!m_focusPointerMoved) m_focusPointerMoved = True;
else m_focusPointerNowStill = False;
}
break;
case ConfigureNotify:
case FocusOut:
case MapNotify:
case MappingNotify:
updateClientList();
break;
default:
fprintf(stderr, "wmG: unsupported event type %d\n", ev.type);
break;
}
}
else
usleep(50);
}
release();
return m_returnCode;
}
void WindowManager::checkDelaysForFocus() {
if(!auto_raise)
return;
int t = timestamp(True);
if(m_focusPointerMoved) {
if(t < m_focusTimestamp || t - m_focusTimestamp > CONFIG_POINTER_STOPPED_DELAY) {
if(m_focusPointerNowStill) {
m_focusCandidate->focusIfAppropriate(True);
} else
m_focusPointerNowStill = True;
}
} else {
if(t < m_focusTimestamp || t - m_focusTimestamp > auto_raise_delay) {
m_focusCandidate->focusIfAppropriate(True);
}
}
}
void WindowManager::considerFocusChange(Client *c, Window w, Time timestamp) {
if(!auto_raise)
return;
if(m_focusChanging) {
stopConsideringFocus();
}
m_focusChanging = True;
m_focusTimestamp = timestamp;
m_focusCandidate = c;
m_focusCandidateWindow = w;
m_focusPointerMoved = False;
m_focusPointerNowStill = False;
m_focusCandidate->selectOnMotion(m_focusCandidateWindow, True);
}
void WindowManager::stopConsideringFocus() {
if(!auto_raise)
return;
m_focusChanging = False;
if(m_focusChanging && m_focusCandidateWindow) {
m_focusCandidate->selectOnMotion(m_focusCandidateWindow, False);
}
}
void Client::focusIfAppropriate(Boolean ifActive) {
if(!auto_raise)
return;
if(!m_managed || !isNormal())
return;
if(!ifActive && isActive())
return;
Window rw, cw;
int rx, ry, cx, cy;
unsigned int k;
XQueryPointer(display(), root(), &rw, &cw, &rx, &ry, &cx, &cy, &k);
if(hasWindow(cw)) {
activate();
mapRaised();
m_windowManager->stopConsideringFocus();
}
}
void WindowManager::eventConfigureRequest(XConfigureRequestEvent *e) {
XWindowChanges wc;
Client *c = windowToClient(e->window);
e->value_mask &= ~CWSibling;
if(c && e->window == c->handle())
c->eventConfigureRequest(e);
else {
wc.x = e->x;
wc.y = e->y;
wc.width = e->width;
wc.height = e->height;
wc.border_width = 0;
wc.sibling = None;
wc.stack_mode = Above;
e->value_mask &= ~CWStackMode;
e->value_mask |= CWBorderWidth;
XConfigureWindow(display(), e->window, e->value_mask, &wc);
}
}
void Client::eventConfigureRequest(XConfigureRequestEvent *e) {
XWindowChanges wc;
Boolean raise = False;
e->value_mask &= ~CWSibling;
if(e->value_mask & CWX)
m_x = e->x;
if(e->value_mask & CWY)
m_y = e->y;
if(e->value_mask & CWWidth)
m_w = e->width;
if(e->value_mask & CWHeight)
m_h = e->height;
if(e->value_mask & CWBorderWidth)
m_bw = e->border_width;
if(e->value_mask & CWStackMode) {
if(e->detail == Above)
raise = True;
e->value_mask &= ~CWStackMode;
}
if(parent() != root() && m_window == e->window) {
m_border->configure(m_x, m_y, m_w, m_h, e->value_mask, e->detail, isActive());
sendConfigureNotify();
}
if(m_managed && parent() != root()) {
wc.x = m_border->xIndent();
wc.y = m_border->yIndent();
} else {
wc.x = e->x;
wc.y = e->y;
}
wc.width = e->width;
wc.height = e->height;
wc.border_width = 0;
wc.sibling = None;
wc.stack_mode = Above;
e->value_mask &= ~CWStackMode;
e->value_mask |= CWBorderWidth;
XConfigureWindow(display(), e->window, e->value_mask, &wc);
if(raise && parent() != root()) {
if(auto_raise) {
m_windowManager->stopConsideringFocus();
if(!m_stubborn) {
Time popTime = windowManager()->timestamp(True);
if(m_lastPopTime > 0L && popTime > m_lastPopTime && popTime - m_lastPopTime < 2000) {
m_stubborn = True;
m_lastPopTime = 0L;
} else {
m_lastPopTime = popTime;
}
mapRaised();
}
} else {
mapRaised();
if(click_to_focus)
activate();
}
}
}
void WindowManager::eventMapRequest(XMapRequestEvent *e) {
Client *c = windowToClient(e->window);
if(c)
c->eventMapRequest(e);
}
void Client::eventMapRequest(XMapRequestEvent *e) {
switch(m_state) {
case WithdrawnState:
if(parent() == root()) {
manage(False);
return;
}
if(m_hasBorder == True && layer == 4)
m_border->reparent();
if(auto_raise)
m_windowManager->stopConsideringFocus();
XAddToSaveSet(display(), m_window);
XMapWindow(display(), m_window);
mapRaised();
setState(NormalState);
if(click_to_focus)
activate();
break;
case NormalState:
XMapWindow(display(), m_window);
mapRaised();
// if(click_to_focus)
// activate();
break;
case IconicState:
if(auto_raise)
m_windowManager->stopConsideringFocus();
unhide(True);
break;
}
}
void WindowManager::eventUnmap(XUnmapEvent *e) {
Client *c = windowToClient(e->window);
if(c)
c->eventUnmap(e);
}
void Client::eventUnmap(XUnmapEvent *e) {
switch(m_state) {
case IconicState:
if(e->send_event) {
unhide(False);
withdraw();
}
break;
case NormalState:
if(isActive())
m_windowManager->clearFocus();
if(!m_reparenting)
withdraw();
break;
}
m_reparenting = False;
m_stubborn = False;
}
void WindowManager::eventCreate(XCreateWindowEvent *e) {
Client *c = windowToClient(e->window, True);
}
void WindowManager::eventDestroy(XDestroyWindowEvent *e) {
Client *c = windowToClient(e->window);
if(c) {
if(auto_raise && m_focusChanging && c == m_focusCandidate) {
m_focusChanging = False;
}
for(int i = m_clients.count()-1; i >= 0; --i) {
if(m_clients.item(i) == c) {
m_clients.remove(i);
break;
}
}
c->release();
ignoreBadWindowErrors = True;
XSync(display(), False);
ignoreBadWindowErrors = False;
}
}
void WindowManager::eventClient(XClientMessageEvent *e) {
Client *c = windowToClient(e->window);
if(e->message_type == Atoms::wm_changeState) {
if(c && e->format == 32 && e->data.l[0] == IconicState && c != 0) {
if(c->isNormal())
c->hide();
}
return;
}
if(e->message_type == Atoms::wm_protocols) {
if(e->data.l[0] == Atoms::wm_takeFocus) {
c->activate();
if(raise_on_focus) {
c->mapRaised();
}
}
return;
}
}
void WindowManager::eventColormap(XColormapEvent *e) {
Client *c = windowToClient(e->window);
int i;
if(e->c_new) {
if(c)
c->eventColormap(e);
else {
for(i = 0; i < m_clients.count(); ++i) {
m_clients.item(i)->eventColormap(e);
}
}
}
}
void Client::eventColormap(XColormapEvent *e) {
if(e->window == m_window || e->window == parent()) {
m_colormap = e->colormap;
if(isActive())
installColormap();
} else {
for(int i = 0; i < m_colormapWinCount; ++i) {
if(m_colormapWindows[i] == e->window) {
m_windowColormaps[i] = e->colormap;
if(isActive())
installColormap();
return;
}
}
}
}
void WindowManager::eventProperty(XPropertyEvent *e) {
Client *c = windowToClient(e->window);
if(c)
c->eventProperty(e);
}
void Client::eventProperty(XPropertyEvent *e) {
Atom a = e->atom;
Boolean shouldDelete = (e->state == PropertyDelete);
switch(a) {
case XA_WM_ICON_NAME:
if(m_iconName)
XFree((char *)m_iconName);
m_iconName = shouldDelete ? 0 : getProperty(a);
if(setLabel())
rename();
return;
case XA_WM_NAME:
if(m_name)
XFree((char *)m_name);
m_name = shouldDelete ? 0 : getProperty(a);
if(setLabel())
rename();
return;
case XA_WM_TRANSIENT_FOR:
getTransient();
return;
}
if (a == Atoms::wm_colormaps) {
getColormaps();
if(isActive())
installColormap();
}
}
void WindowManager::eventReparent(XReparentEvent *e) {
(void)windowToClient(e->window, True);
}
void WindowManager::eventEnter(XCrossingEvent *e) {
if(e->type != EnterNotify)
return;
while(XCheckMaskEvent(m_display, EnterWindowMask, (XEvent *)e));
m_currentTime = e->time;
Client *c = windowToClient(e->window);
if(c)
c->eventEnter(e);
}
void Client::eventEnter(XCrossingEvent *e) {
if(e->type == EnterNotify) {
if(!isActive() && !click_to_focus) {
activate();
if(auto_raise) {
windowManager()->considerFocusChange(this, m_window, e->time);
} else if(raise_on_focus) {
mapRaised();
}
}
}
}
void WindowManager::eventFocusIn(XFocusInEvent *e) {
if(e->detail != NotifyNonlinearVirtual)
return;
Client *c = windowToClient(e->window);
if(c)
c->eventFocusIn(e);
}
void Client::eventFocusIn(XFocusInEvent *e) {
if(m_window == e->window && !isActive()) {
activate();
mapRaised();
}
}
void WindowManager::eventExposure(XExposeEvent *e) {
if(e->count != 0)
return;
Client *c = windowToClient(e->window);
if(c)
c->eventExposure(e);
}
void Client::eventExposure(XExposeEvent *e) {
if (m_border->hasWindow(e->window)) {
m_border->expose(e);
}
}
syntax highlighted by Code2HTML, v. 0.9.1