Events.C

Index

      
      #include "Manager.h"
      #include "Client.h"
      
      
      int WindowManager::loop()
      {
          XEvent ev;
          m_looping = True;
  10  
          while (m_looping) {
      
              nextEvent(&ev);
              dispatchEvent(&ev);
          }
      
          release();
          return m_returnCode;
      }
  20  
      void WindowManager::dispatchEvent(XEvent *ev)
      {
          m_currentTime = CurrentTime;
      
          switch (ev->type) {
      
          case ButtonPress:
              eventButton(&ev->xbutton);
              break;
  30  
          case ButtonRelease:
              break;
              
          case KeyPress:
              eventKeyPress(&ev->xkey); // in Buttons.C
              break;
              
          case KeyRelease:
              eventKeyRelease(&ev->xkey); // in Buttons.C
  40          break;
              
          case MapRequest:
              eventMapRequest(&ev->xmaprequest);
              break;
              
          case ConfigureRequest:
              eventConfigureRequest(&ev->xconfigurerequest);
              break;
              
  50      case UnmapNotify:
              eventUnmap(&ev->xunmap);
              break;
              
          case CreateNotify:
      //      eventCreate(&ev->xcreatewindow);
              break;
              
          case DestroyNotify:
              eventDestroy(&ev->xdestroywindow);
  60          break;
              
          case ClientMessage:
              eventClient(&ev->xclient);
              break;
              
          case ColormapNotify:
              eventColormap(&ev->xcolormap);
              break;
              
  70      case PropertyNotify:
              eventProperty(&ev->xproperty);
              break;
              
          case SelectionClear:
              fprintf(stderr, "wmx: SelectionClear (this should not happen)\n");
              break;
              
          case SelectionNotify:
              fprintf(stderr, "wmx: SelectionNotify (this should not happen)\n");
  80          break;
              
          case SelectionRequest:
              fprintf(stderr, "wmx: SelectionRequest (this should not happen)\n");
              break;
              
          case EnterNotify:
          case LeaveNotify:
              eventEnter(&ev->xcrossing);
              break;
  90          
          case ReparentNotify:
      //      eventReparent(&ev->xreparent);
              break;
              
          case FocusIn:
              eventFocusIn(&ev->xfocus);
              break;
              
          case Expose:                // might be wm tab
 100          eventExposure(&ev->xexpose);
              break;
              
          case MotionNotify:
              if (CONFIG_AUTO_RAISE && m_focusChanging) {
                  if (!m_focusPointerMoved) m_focusPointerMoved = True;
                  else m_focusPointerNowStill = False;
              }
              break;
              
 110      case FocusOut:
          case ConfigureNotify:
          case MapNotify:
          case MappingNotify:
          case NoExpose:
              break;
              
          default:
      //          if (ev->type == m_shapeEvent) eventShapeNotify((XShapeEvent *)ev);
              if (ev->type == m_shapeEvent) {
 120              fprintf(stderr, "wmx: shaped windows are not supported\n");
              } else {
                  fprintf(stderr, "wmx: unsupported event type %d\n", ev->type);
              }
              break;
          }
      }
      
      
      void WindowManager::nextEvent(XEvent *e)
 130  {
          int fd;
          fd_set rfds;
          struct timeval t;
          int r;
      
          if (!m_signalled) {
      
          waiting:
      
 140          if (m_channelChangeTime > 0) {
                  Time t = timestamp(True);
      //!!!       if (t < m_channelChangeTime || t - m_channelChangeTime > 1000) {
                  if (t >= m_channelChangeTime) {
                      instateChannel();
                  }
              }
      
              if (QLength(m_display) > 0) {
                  XNextEvent(m_display, e);
 150              return;
              }
      
              fd = ConnectionNumber(m_display);
              memset((void *)&rfds, 0, sizeof(fd_set)); // SGI's FD_ZERO is fucked
              FD_SET(fd, &rfds);
              t.tv_sec = t.tv_usec = 0;
      
      #if CONFIG_USE_SESSION_MANAGER != False
              if (m_smFD >= 0) FD_SET(m_smFD, &rfds);
 160  #endif
      
      #ifdef hpux
      #define select(a,b,c,d,e) select((a),(int *)(b),(c),(d),(e))
      #endif
      
              if (select(fd + 1, &rfds, NULL, NULL, &t) > 0) {
      
                  //!!! This two-select structure is getting disgusting;
                  // a marginal improvement would be to put this body in
 170              // another function, but it'd be better to go back and
                  // think hard about why the code is like this at all
      
      #if CONFIG_USE_SESSION_MANAGER != False
                  if (m_smFD >= 0 && FD_ISSET(m_smFD, &rfds)) {
                      Bool rep;
                      if (IceProcessMessages(m_smIceConnection, NULL, &rep)
                          == IceProcessMessagesIOError) {
                          SmcCloseConnection(m_smConnection, 0, NULL);
                          m_smIceConnection = NULL;
 180                      m_smConnection = NULL;
                      }
                      goto waiting;
                  }
      #endif
                  if (FD_ISSET(fd, &rfds)) {
                      XNextEvent(m_display, e);
                      return;
                  }
      
 190  //          XNextEvent(m_display, e);
      //          return;
              }
      
              XFlush(m_display);
              FD_SET(fd, &rfds);
              t.tv_sec = 0; t.tv_usec = 20000;
      
      #if CONFIG_USE_SESSION_MANAGER != False
              if (m_smFD >= 0) FD_SET(m_smFD, &rfds);
 200  #endif
      
              if ((r = select(fd + 1, &rfds, NULL, NULL,
                              (m_channelChangeTime > 0 || m_focusChanging) ? &t :
                              (struct timeval *)NULL)) > 0) {
      
      #if CONFIG_USE_SESSION_MANAGER != False
                  if (m_smFD >= 0 && FD_ISSET(m_smFD, &rfds)) {
                      Bool rep;
                      if (IceProcessMessages(m_smIceConnection, NULL, &rep)
 210                      == IceProcessMessagesIOError) {
                          SmcCloseConnection(m_smConnection, 0, NULL);
                          m_smIceConnection = NULL;
                          m_smConnection = NULL;
                      }
                      goto waiting;
                  }
      #endif
                  if (FD_ISSET(fd, &rfds)) {
                      XNextEvent(m_display, e);
 220                  return;
                  }
      
      //          return;
              }
      
              if (CONFIG_AUTO_RAISE && m_focusChanging) { // timeout on select
                  checkDelaysForFocus();
              }
      
 230          if (r == 0) goto waiting;
      
              if (errno != EINTR || !m_signalled) {
                  perror("wmx: select failed");
                  m_looping = False;
              }
          }
      
          fprintf(stderr, "wmx: signal caught, exiting\n");
          ignoreBadWindowErrors = True;
 240      m_looping = False;
          m_returnCode = 0;
      }
      
      
      void WindowManager::checkDelaysForFocus()
      {
          if (!CONFIG_AUTO_RAISE) return;
      
          int t = timestamp(True);
 250  
          if (m_focusPointerMoved) {  // only raise when pointer stops
      
              if (t < m_focusTimestamp ||
                  t - m_focusTimestamp > CONFIG_POINTER_STOPPED_DELAY) {
      
                  if (m_focusPointerNowStill) {
                      m_focusCandidate->focusIfAppropriate(True);
      //              if (m_focusCandidate->isNormal()) m_focusCandidate->mapRaised();
      //              stopConsideringFocus();
 260  
                  } else m_focusPointerNowStill = True; // until proven false
              }
          } else {
      
              if (t < m_focusTimestamp ||
                  t - m_focusTimestamp > CONFIG_AUTO_RAISE_DELAY) {
      
                  m_focusCandidate->focusIfAppropriate(True);
      
 270  //          if (m_focusCandidate->isNormal()) m_focusCandidate->mapRaised();
      //          stopConsideringFocus();
              }
          }
      }
      
      
      void WindowManager::considerFocusChange(Client *c, Window w, Time timestamp)
      {
          if (!CONFIG_AUTO_RAISE) return;
 280  
          if (m_focusChanging) {
              stopConsideringFocus();
          }
      
          m_focusChanging = True;
          m_focusTimestamp = timestamp;
          m_focusCandidate = c;
          m_focusCandidateWindow = w;
      
 290      // we need to wait until at least one pointer-motion event has
          // come in before we can start to wonder if the pointer's
          // stopped moving -- otherwise we'll be caught out by all the
          // windows for which we don't get motion events at all
      
          m_focusPointerMoved = False;
          m_focusPointerNowStill = False;
          m_focusCandidate->selectOnMotion(m_focusCandidateWindow, True);
      }
      
 300  
      void WindowManager::stopConsideringFocus()
      {
          if (!CONFIG_AUTO_RAISE) return;
      
          m_focusChanging = False;
          if (m_focusChanging && m_focusCandidateWindow) {
              m_focusCandidate->selectOnMotion(m_focusCandidateWindow, False);
          }
      }
 310  
      
      void Client::focusIfAppropriate(Boolean ifActive)
      {
          if (!CONFIG_AUTO_RAISE) return;
          if (!m_managed || !isNormal()) return;
          if (!ifActive && isActive()) return;
          
          Window rw, cw;
          int rx, ry, cx, cy;
 320      unsigned int k;
      
          XQueryPointer(display(), root(), &rw, &cw, &rx, &ry, &cx, &cy, &k);
      
          if (hasWindow(cw)) {
              activate();
              mapRaised();
              m_windowManager->stopConsideringFocus();
          }
      }
 330  
      
      void WindowManager::eventConfigureRequest(XConfigureRequestEvent *e)
      {
          XWindowChanges wc;
          Client *c = windowToClient(e->window);
      
          e->value_mask &= ~CWSibling;
          if (c) c->eventConfigureRequest(e);
          else {
 340  
              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;
 350  
              XConfigureWindow(display(), e->window, e->value_mask, &wc);
          }
      }
      
      
      void Client::eventConfigureRequest(XConfigureRequestEvent *e)
      {
          XWindowChanges wc;
          Boolean raise = False;
 360  
          e->value_mask &= ~CWSibling;
      
          gravitate(True);
      
          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;
 370  
          gravitate(False);
      
          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);
 380          sendConfigureNotify();
          }
      
          if (m_managed) {
              wc.x = m_border->xIndent();
              wc.y = m_border->yIndent();
          } else {
              wc.x = e->x;
              wc.y = e->y;
          }
 390  
          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);
 400  
          // if parent==root, it's not managed yet -- & it'll be raised when it is
          if (raise && parent() != root()) {
      
              if (CONFIG_AUTO_RAISE) {
      
                  m_windowManager->stopConsideringFocus();
      
                  if (!m_stubborn) { // outstubborn stubborn windows
                      Time popTime = windowManager()->timestamp(True);
 410  
                      if (m_lastPopTime > 0L &&
                          popTime > m_lastPopTime &&
                          popTime - m_lastPopTime < 2000) { // 2 pops in 2 seconds
                          m_stubborn = True;
                          m_lastPopTime = 0L;
      
                          fprintf(stderr, "wmx: client \"%s\" declared stubborn\n",
                                  label());
      
 420                  } else {
                          m_lastPopTime = popTime;
                      }
      
                      mapRaised();
                  }
              } else {
                  mapRaised();
                  if (CONFIG_CLICK_TO_FOCUS) activate();
              }
 430      }
      }
      
      
      void WindowManager::eventMapRequest(XMapRequestEvent *e)
      {
          Client *c = windowToClient(e->window);
      
          // JG
          if (!c) {
 440          // fprintf(stderr, "wm2: start managing window %lx\n", e->window);
              c = windowToClient(e->window, True);
              c->eventMapRequest(e);
              c->sendConfigureNotify();
          } else {
              c->eventMapRequest(e);
          }
      
          // some stuff for multi-screen fuckups here, omitted
      
 450  //    if (c) c->eventMapRequest(e);
      //    else {
      //      fprintf(stderr, "wmx: bad map request for window %lx\n", e->window);
      //    }
      }
      
      
      void Client::eventMapRequest(XMapRequestEvent *)
      {
          switch(m_state) {
 460  
          case WithdrawnState:
              if (parent() == root()) {
                  manage(False);
                  return;
              }
      
              m_border->reparent();
      
              if (CONFIG_AUTO_RAISE) m_windowManager->stopConsideringFocus();
 470          XAddToSaveSet(display(), m_window);
              if (m_channel == windowManager()->channel()) {
                  XMapWindow(display(), m_window);
              }
              mapRaised();
              setState(NormalState);
              if (CONFIG_CLICK_TO_FOCUS) activate();
              break;
      
          case NormalState:
 480          if (m_channel == windowManager()->channel()) {
                  XMapWindow(display(), m_window);
              }
              mapRaised();
              if (CONFIG_CLICK_TO_FOCUS) activate();
              break;
      
          case IconicState:
              if (CONFIG_AUTO_RAISE) m_windowManager->stopConsideringFocus();
              unhide(True);
 490          break;
          }
      }
      
      
      void WindowManager::eventUnmap(XUnmapEvent *e)
      {
          Client *c = windowToClient(e->window);
          if (c) c->eventUnmap(e);
      }
 500  
      
      void Client::eventUnmap(XUnmapEvent *e)
      {
          if (e->window != m_window) return;
      
          if (m_unmappedForChannel) {
              setState(NormalState);
              return;
          }
 510  
          switch (m_state) {
      
          case IconicState:
              if (e->send_event) {
                  unhide(False);
                  withdraw();
              }
              break;
      
 520      case NormalState:
              if (isActive()) m_windowManager->clearFocus();
              if (!m_reparenting) withdraw();
              break;
          }
      
          // When unmapped transient window.  Should change a focus to not
          // transient window.
          if (transientFor()) {
              Client* c = windowManager()->windowToClient(transientFor());
 530          if (c && !c->isActive() && !CONFIG_CLICK_TO_FOCUS) {
                  c->activate();
                  if (CONFIG_AUTO_RAISE) {
                      c->windowManager()->considerFocusChange(this, c->m_window, windowManager()->timestamp(False));
                  } else if (CONFIG_RAISE_ON_FOCUS) {
                      c->mapRaised();
                  }
              }
          }
      
 540      m_reparenting = False;
          m_stubborn = False;
      }
      
      
      void WindowManager::eventCreate(XCreateWindowEvent *e)
      {
          // not currently used! windows created on first MapRequest instead
      //    if (e->override_redirect) return;
      //    Client *c = windowToClient(e->window, True);
 550  }
      
      
      void WindowManager::eventDestroy(XDestroyWindowEvent *e)
      {
          Client *c = windowToClient(e->window);
      
          if (c) {
      
              if (CONFIG_AUTO_RAISE && m_focusChanging && c == m_focusCandidate) {
 560              m_focusChanging = False;
              }
      
              for (int i = m_clients.count()-1; i >= 0; --i) {
                  if (m_clients.item(i) == c) {
                      m_clients.remove(i);
                      break;
                  }
              }
      
 570          checkChannel(c->channel());
              c->release();
      
              ignoreBadWindowErrors = True;
              XSync(display(), False);
              ignoreBadWindowErrors = False;
          }
      }
      
      
 580  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;
              }
          }
 590  
          fprintf(stderr, "wmx: unexpected XClientMessageEvent, type 0x%lx, "
                  "window 0x%lx\n", e->message_type, e->window);
      }
      
      
      void WindowManager::eventColormap(XColormapEvent *e)
      {
          Client *c = windowToClient(e->window);
          int i;
 600  
          if (e->c_new) {  // this field is called "new" in the old C++-unaware Xlib
      
              if (c) c->eventColormap(e);
              else {
                  for (i = 0; i < m_clients.count(); ++i) {
                      m_clients.item(i)->eventColormap(e);
                  }
              }
          }
 610  }
      
      
      void Client::eventColormap(XColormapEvent *e)
      {
          if (e->window == m_window || e->window == parent()) {
      
              m_colormap = e->colormap;
              if (isActive()) installColormap();
      
 620      } else {
      
              for (int i = 0; i < m_colormapWinCount; ++i) {
                  if (m_colormapWindows[i] == e->window) {
                      m_windowColormaps[i] = e->colormap;
                      if (isActive()) installColormap();
                      return;
                  }
              }
          }
 630  }
      
      
      void WindowManager::eventProperty(XPropertyEvent *e)
      {
          Client *c = windowToClient(e->window);
          if (c) c->eventProperty(e);
      }
      
      
 640  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);
 650          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:
 660          getTransient();
              return;
          }
      
          if (a == Atoms::wm_colormaps) {
              getColormaps();
              if (isActive()) installColormap();
          }
      }
      
 670  
      void WindowManager::eventReparent(XReparentEvent *e)
      {
          // not currently used! map events used instead, only
      //    if (e->override_redirect) return;
      //    (void)windowToClient(e->window, True); // create if absent
      
          // odd screen complications, omitted
      }
      
 680  
      void WindowManager::eventEnter(XCrossingEvent *e)
      {
          // quick hack for multi-screen stuff; although it still only
          // manages one screen, it will now allow focus on others.
          // thanks to Johan Danielsson
      
          if (e->type != EnterNotify) {
              if (e->same_screen == 0) {
                  if (m_activeClient) m_activeClient->deactivate();
 690              m_activeClient = 0;
                  XSetInputFocus(m_display, PointerRoot, None, timestamp(False));
              }
              return;
          }
      
          while (XCheckMaskEvent(m_display, EnterWindowMask, (XEvent *)e));
          m_currentTime = e->time;    // not CurrentTime
      
          Client *c = windowToClient(e->window);
 700      if (c) c->eventEnter(e);
      }
      
      
      void Client::eventEnter(XCrossingEvent *e)
      {
          // first, big checks so as not to allow focus to change "through"
          // the hole in the tab
      
          if (!isActive() && activeClient() && activeClient()->isNormal() &&
 710          !activeClient()->isTransient()) {
      
              int x, y;
              Window c;
      
              XTranslateCoordinates
                  (display(), activeClient()->parent(), e->window, 0, 0, &x, &y, &c);
      
              if (activeClient()->coordsInHole(e->x - x, e->y - y)) return;
          }
 720  
          if (e->type == EnterNotify) {
              if (!isActive() && !CONFIG_CLICK_TO_FOCUS) {
                  activate();
                  if (CONFIG_AUTO_RAISE) {
                      windowManager()->considerFocusChange(this, m_window, e->time);
                  } else if (CONFIG_RAISE_ON_FOCUS) {
                      mapRaised();
                  }
              }
 730      }
      }
      
      
      Boolean Client::coordsInHole(int x, int y)      // relative to parent
      {
          return m_border->coordsInHole(x, y);
      }
      
      
 740  Boolean Border::coordsInHole(int x, int y)      // this is all a bit of a hack
      {
          return (x > 1 && x < m_tabWidth-1 &&
                  y > 1 && y < m_tabWidth-1);
      }
      
      
      void WindowManager::eventFocusIn(XFocusInEvent *e)
      {
          if (e->detail != NotifyNonlinearVirtual) return;
 750      Client *c = windowToClient(e->window);
      
          if (c) c->eventFocusIn(e);
      }
      
      
      void Client::eventFocusIn(XFocusInEvent *e)
      {
          if (m_window == e->window && !isActive()) {
              activate();
 760          mapRaised();
          }
      }
      
      
      void WindowManager::eventExposure(XExposeEvent *e)
      {
          if (e->count != 0) return;
          Client *c = windowToClient(e->window);
          if (c) c->eventExposure(e);
 770  }
      
      
      void Client::eventExposure(XExposeEvent *e)
      {
          if (m_border->hasWindow(e->window)) {
              m_border->expose(e);
          }
      }
      
 780  
      

Index

  • WindowManager::loop (function) returns int
  • WindowManager::dispatchEvent (function) returns void
  • WindowManager::nextEvent (function) returns void
  • WindowManager::checkDelaysForFocus (function) returns void
  • WindowManager::considerFocusChange (function) returns void
  • WindowManager::stopConsideringFocus (function) returns void
  • Client::focusIfAppropriate (function) returns void
  • WindowManager::eventConfigureRequest (function) returns void
  • Client::eventConfigureRequest (function) returns void
  • WindowManager::eventMapRequest (function) returns void
  • Client::eventMapRequest (function) returns void
  • WindowManager::eventUnmap (function) returns void
  • Client::eventUnmap (function) returns void
  • WindowManager::eventCreate (function) returns void
  • WindowManager::eventDestroy (function) returns void
  • WindowManager::eventClient (function) returns void
  • WindowManager::eventColormap (function) returns void
  • Client::eventColormap (function) returns void
  • WindowManager::eventProperty (function) returns void
  • Client::eventProperty (function) returns void
  • WindowManager::eventReparent (function) returns void
  • WindowManager::eventEnter (function) returns void
  • Client::eventEnter (function) returns void
  • Client::coordsInHole (function) returns Boolean
  • Border::coordsInHole (function) returns Boolean
  • WindowManager::eventFocusIn (function) returns void
  • Client::eventFocusIn (function) returns void
  • WindowManager::eventExposure (function) returns void
  • Client::eventExposure (function) returns void