#include "Manager.h" #include "Client.h" #include #include 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); } }