bool NativeWindowViews::PreHandleMSG()

in shell/browser/native_window_views_win.cc [200:381]


bool NativeWindowViews::PreHandleMSG(UINT message,
                                     WPARAM w_param,
                                     LPARAM l_param,
                                     LRESULT* result) {
  NotifyWindowMessage(message, w_param, l_param);

  // Avoid side effects when calling SetWindowPlacement.
  if (is_setting_window_placement_) {
    // Let Chromium handle the WM_NCCALCSIZE message otherwise the window size
    // would be wrong.
    // See https://github.com/electron/electron/issues/22393 for more.
    if (message == WM_NCCALCSIZE)
      return false;
    // Otherwise handle the message with default proc,
    *result = DefWindowProc(GetAcceleratedWidget(), message, w_param, l_param);
    // and tell Chromium to ignore this message.
    return true;
  }

  switch (message) {
    // Screen readers send WM_GETOBJECT in order to get the accessibility
    // object, so take this opportunity to push Chromium into accessible
    // mode if it isn't already, always say we didn't handle the message
    // because we still want Chromium to handle returning the actual
    // accessibility object.
    case WM_GETOBJECT: {
      if (checked_for_a11y_support_)
        return false;

      const DWORD obj_id = static_cast<DWORD>(l_param);

      if (obj_id != static_cast<DWORD>(OBJID_CLIENT)) {
        return false;
      }

      if (!IsScreenReaderActive()) {
        return false;
      }

      checked_for_a11y_support_ = true;

      auto* const axState = content::BrowserAccessibilityState::GetInstance();
      if (axState && !axState->IsAccessibleBrowser()) {
        axState->OnScreenReaderDetected();
        Browser::Get()->OnAccessibilitySupportChanged();
      }

      return false;
    }
    case WM_GETMINMAXINFO: {
      WINDOWPLACEMENT wp;
      wp.length = sizeof(WINDOWPLACEMENT);

      // We do this to work around a Windows bug, where the minimized Window
      // would report that the closest display to it is not the one that it was
      // previously on (but the leftmost one instead). We restore the position
      // of the window during the restore operation, this way chromium can
      // use the proper display to calculate the scale factor to use.
      if (!last_normal_placement_bounds_.IsEmpty() &&
          (IsVisible() || IsMinimized()) &&
          GetWindowPlacement(GetAcceleratedWidget(), &wp)) {
        wp.rcNormalPosition = last_normal_placement_bounds_.ToRECT();

        // When calling SetWindowPlacement, Chromium would do window messages
        // handling. But since we are already in PreHandleMSG this would cause
        // crash in Chromium under some cases.
        //
        // We work around the crash by prevent Chromium from handling window
        // messages until the SetWindowPlacement call is done.
        //
        // See https://github.com/electron/electron/issues/21614 for more.
        is_setting_window_placement_ = true;
        SetWindowPlacement(GetAcceleratedWidget(), &wp);
        is_setting_window_placement_ = false;

        last_normal_placement_bounds_ = gfx::Rect();
      }

      return false;
    }
    case WM_COMMAND:
      // Handle thumbar button click message.
      if (HIWORD(w_param) == THBN_CLICKED)
        return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
      return false;
    case WM_SIZING: {
      is_resizing_ = true;
      bool prevent_default = false;
      gfx::Rect bounds = gfx::Rect(*reinterpret_cast<RECT*>(l_param));
      HWND hwnd = GetAcceleratedWidget();
      gfx::Rect dpi_bounds = ScreenToDIPRect(hwnd, bounds);
      NotifyWindowWillResize(dpi_bounds, GetWindowResizeEdge(w_param),
                             &prevent_default);
      if (prevent_default) {
        ::GetWindowRect(hwnd, reinterpret_cast<RECT*>(l_param));
        return true;  // Tells Windows that the Sizing is handled.
      }
      return false;
    }
    case WM_SIZE: {
      // Handle window state change.
      HandleSizeEvent(w_param, l_param);
      return false;
    }
    case WM_EXITSIZEMOVE: {
      if (is_resizing_) {
        NotifyWindowResized();
        is_resizing_ = false;
      }
      if (is_moving_) {
        NotifyWindowMoved();
        is_moving_ = false;
      }
      return false;
    }
    case WM_MOVING: {
      is_moving_ = true;
      bool prevent_default = false;
      gfx::Rect bounds = gfx::Rect(*reinterpret_cast<RECT*>(l_param));
      HWND hwnd = GetAcceleratedWidget();
      gfx::Rect dpi_bounds = ScreenToDIPRect(hwnd, bounds);
      NotifyWindowWillMove(dpi_bounds, &prevent_default);
      if (!movable_ || prevent_default) {
        ::GetWindowRect(hwnd, reinterpret_cast<RECT*>(l_param));
        return true;  // Tells Windows that the Move is handled. If not true,
                      // frameless windows can be moved using
                      // -webkit-app-region: drag elements.
      }
      return false;
    }
    case WM_ENDSESSION: {
      if (w_param) {
        NotifyWindowEndSession();
      }
      return false;
    }
    case WM_PARENTNOTIFY: {
      if (LOWORD(w_param) == WM_CREATE) {
        // Because of reasons regarding legacy drivers and stuff, a window that
        // matches the client area is created and used internally by Chromium.
        // This is used when forwarding mouse messages. We only cache the first
        // occurrence (the webview window) because dev tools also cause this
        // message to be sent.
        if (!legacy_window_) {
          legacy_window_ = reinterpret_cast<HWND>(l_param);
        }
      }
      return false;
    }
    case WM_CONTEXTMENU: {
      bool prevent_default = false;
      NotifyWindowSystemContextMenu(GET_X_LPARAM(l_param),
                                    GET_Y_LPARAM(l_param), &prevent_default);
      return prevent_default;
    }
    case WM_SYSCOMMAND: {
      // Mask is needed to account for double clicking title bar to maximize
      WPARAM max_mask = 0xFFF0;
      if (transparent() && ((w_param & max_mask) == SC_MAXIMIZE)) {
        return true;
      }
      return false;
    }
    case WM_INITMENU: {
      // This is handling the scenario where the menu might get triggered by the
      // user doing "alt + space" resulting in system maximization and restore
      // being used on transparent windows when that does not work.
      if (transparent()) {
        HMENU menu = GetSystemMenu(GetAcceleratedWidget(), false);
        EnableMenuItem(menu, SC_MAXIMIZE,
                       MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
        EnableMenuItem(menu, SC_RESTORE,
                       MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
        return true;
      }
      return false;
    }
    default: {
      return false;
    }
  }
}