void CefWindowX11::ProcessXEvent()

in libcef/browser/native/window_x11.cc [334:424]


void CefWindowX11::ProcessXEvent(const x11::Event& event) {
  if (auto* configure = event.As<x11::ConfigureNotifyEvent>()) {
    DCHECK_EQ(xwindow_, configure->event);
    DCHECK_EQ(xwindow_, configure->window);
    // It's possible that the X window may be resized by some other means
    // than from within Aura (e.g. the X window manager can change the
    // size). Make sure the root window size is maintained properly.
    bounds_ = gfx::Rect(configure->x, configure->y, configure->width,
                        configure->height);

    if (browser_.get()) {
      auto child = FindChild(xwindow_);
      if (child != x11::Window::None) {
        // Resize the child DesktopWindowTreeHostLinux to match this window.
        x11::ConfigureWindowRequest req{
            .window = child,
            .width = bounds_.width(),
            .height = bounds_.height(),
        };
        connection_->ConfigureWindow(req);

        browser_->NotifyMoveOrResizeStarted();
      }
    }
  } else if (auto* client = event.As<x11::ClientMessageEvent>()) {
    if (client->type == x11::GetAtom(kWMProtocols)) {
      x11::Atom protocol = static_cast<x11::Atom>(client->data.data32[0]);
      if (protocol == x11::GetAtom(kWMDeleteWindow)) {
        // We have received a close message from the window manager.
        if (!browser_ || browser_->TryCloseBrowser()) {
          // Allow the close.
          connection_->DestroyWindow({xwindow_});
          xwindow_ = x11::Window::None;

          if (browser_) {
            // Force the browser to be destroyed and release the reference
            // added in PlatformCreateWindow().
            static_cast<AlloyBrowserHostImpl*>(browser_.get())
                ->WindowDestroyed();
          }

          delete this;
        }
      } else if (protocol == x11::GetAtom(kNetWMPing)) {
        x11::ClientMessageEvent reply_event = *client;
        reply_event.window = parent_xwindow_;
        x11::SendEvent(reply_event, reply_event.window,
                       x11::EventMask::SubstructureNotify |
                           x11::EventMask::SubstructureRedirect);
      }
    }
  } else if (auto* focus = event.As<x11::FocusEvent>()) {
    if (focus->opcode == x11::FocusEvent::In) {
      // This message is received first followed by a "_NET_ACTIVE_WINDOW"
      // message sent to the root window. When X11DesktopHandler handles the
      // "_NET_ACTIVE_WINDOW" message it will erroneously mark the WebView
      // (hosted in a DesktopWindowTreeHostLinux) as unfocused. Use a delayed
      // task here to restore the WebView's focus state.
      if (!focus_pending_) {
        focus_pending_ = true;
        CEF_POST_DELAYED_TASK(CEF_UIT,
                              base::BindOnce(&CefWindowX11::ContinueFocus,
                                             weak_ptr_factory_.GetWeakPtr()),
                              100);
      }
    } else {
      // Cancel the pending focus change if some other window has gained focus
      // while waiting for the async task to run. Otherwise we can get stuck in
      // a focus change loop.
      if (focus_pending_)
        focus_pending_ = false;
    }
  } else if (auto* property = event.As<x11::PropertyNotifyEvent>()) {
    const auto& wm_state_atom = x11::GetAtom(kNetWMState);
    if (property->atom == wm_state_atom) {
      // State change event like minimize/maximize.
      if (browser_.get()) {
        auto child = FindChild(xwindow_);
        if (child != x11::Window::None) {
          // Forward the state change to the child DesktopWindowTreeHostLinux
          // window so that resource usage will be reduced while the window is
          // minimized. |atom_list| may be empty.
          std::vector<x11::Atom> atom_list;
          x11::GetArrayProperty(xwindow_, wm_state_atom, &atom_list);
          x11::SetArrayProperty(child, wm_state_atom, x11::Atom::ATOM,
                                atom_list);
        }
      }
    }
  }
}