Ejemplo n.º 1
0
void Blackbox::process_event(XEvent *e) {
  switch (e->type) {
  case MapRequest: {
#ifdef    DEBUG
    fprintf(stderr, "Blackbox::process_event(): MapRequest for 0x%lx\n",
            e->xmaprequest.window);
#endif // DEBUG

    BlackboxWindow *win = findWindow(e->xmaprequest.window);

    if (win) {
      if ((!activeScreen() || activeScreen() == win->screen()) &&
          (win->isTransient() || _resource.focusNewWindows()))
        win->activate();
    } else {
      BScreen *screen = findScreen(e->xmaprequest.parent);

      if (! screen) {
        /*
          we got a map request for a window who's parent isn't root. this
          can happen in only one circumstance:

          a client window unmapped a managed window, and then remapped it
          somewhere between unmapping the client window and reparenting it
          to root.

          regardless of how it happens, we need to find the screen that
          the window is on
        */
        XWindowAttributes wattrib;
        if (! XGetWindowAttributes(XDisplay(), e->xmaprequest.window,
                                   &wattrib)) {
          // failed to get the window attributes, perhaps the window has
          // now been destroyed?
          break;
        }

        screen = findScreen(wattrib.root);
        assert(screen != 0); // this should never happen
      }
      screen->addWindow(e->xmaprequest.window);
    }

    break;
  }

  case ConfigureRequest: {
    BlackboxWindow *win = findWindow(e->xconfigurerequest.window);
    if (win) {
      // a window wants to resize
      win->configureRequestEvent(&e->xconfigurerequest);
      break;
    }

    Slit *slit =
      dynamic_cast<Slit *>(findEventHandler(e->xconfigurerequest.parent));
    if (slit) {
      // something in the slit wants to resize
      slit->configureRequestEvent(&e->xconfigurerequest);
      break;
    }

    /*
      handle configure requests for windows that have no EventHandlers
      by simply configuring them as requested.

      note: the event->window parameter points to the window being
      configured, and event->parent points to the window that received
      the event (in this case, the root window, since
      SubstructureRedirect has been selected).
    */
    XWindowChanges xwc;
    xwc.x = e->xconfigurerequest.x;
    xwc.y = e->xconfigurerequest.y;
    xwc.width = e->xconfigurerequest.width;
    xwc.height = e->xconfigurerequest.height;
    xwc.border_width = e->xconfigurerequest.border_width;
    xwc.sibling = e->xconfigurerequest.above;
    xwc.stack_mode = e->xconfigurerequest.detail;
    XConfigureWindow(XDisplay(),
                     e->xconfigurerequest.window,
                     e->xconfigurerequest.value_mask,
                     &xwc);
    break;
  }

  case FocusIn: {
#ifdef FOCUS_DEBUG
    printf("FocusIn : window %8lx mode %s detail %s\n",
           e->xfocus.window, Mode[e->xfocus.mode], Detail[e->xfocus.detail]);
#endif

    if (e->xfocus.mode == NotifyGrab
        || (e->xfocus.detail != NotifyNonlinearVirtual
            && e->xfocus.detail != NotifyVirtual)) {
      /*
        don't process FocusIns when:
        1. they are the result of a grab
        2. the new focus window isn't an ancestor or inferior of the
        old focus window (NotifyNonlinearVirtual and NotifyVirtual)
      */
      break;
    }

    BlackboxWindow *win = findWindow(e->xfocus.window);
    if (!win || win->isFocused())
      break;

#ifdef FOCUS_DEBUG
    printf("          win %p got focus\n", win);
#endif
    win->setFocused(true);
    setFocusedWindow(win);

    /*
      set the event window to None.  when the FocusOut event handler calls
      this function recursively, it uses this as an indication that focus
      has moved to a known window.
    */
    e->xfocus.window = None;

    break;
  }

  case FocusOut: {
#ifdef FOCUS_DEBUG
    printf("FocusOut: window %8lx mode %s detail %s\n",
           e->xfocus.window, Mode[e->xfocus.mode], Detail[e->xfocus.detail]);
#endif

    if (e->xfocus.mode == NotifyGrab
        || (e->xfocus.detail != NotifyNonlinearVirtual
            && e->xfocus.detail != NotifyVirtual)) {
      /*
        don't process FocusOuts when:
        1. they are the result of a grab
        2. the new focus window isn't an ancestor or inferior of the
        old focus window (NotifyNonlinearVirtual and NotifyNonlinearVirtual)
      */
      break;
    }

    BlackboxWindow *win = findWindow(e->xfocus.window);
    if (!win || !win->isFocused())
      break;

    bool lost_focus = true; // did the window really lose focus?
    bool no_focus = true;   // did another window get focus?

    XSync(XDisplay(), False);
    XEvent event;
    if (XCheckIfEvent(XDisplay(), &event, scanForFocusIn, NULL)) {
      process_event(&event);

      if (event.xfocus.window == None)
        no_focus = false;
    } else {
      XWindowAttributes attr;
      Window w;
      int unused;
      XGetInputFocus(XDisplay(), &w, &unused);
      if (w != None
          && XGetWindowAttributes(XDisplay(), w, &attr)
          && attr.override_redirect) {
#ifdef FOCUS_DEBUG
        printf("          focused moved to an override_redirect window\n");
#endif
        lost_focus = (e->xfocus.mode == NotifyNormal);
      }
    }

    if (lost_focus) {
#ifdef FOCUS_DEBUG
      printf("          win %p lost focus\n", win);
#endif
      win->setFocused(false);

      if (no_focus) {
#ifdef FOCUS_DEBUG
        printf("          no window has focus\n");
#endif
        setFocusedWindow(0);
      }
    }

    break;
  }

  default:
    // Send the event through the default EventHandlers.
    bt::Application::process_event(e);
    break;
  } // switch
}