void CefWindowView::CreateWidget()

in libcef/browser/views/window_view.cc [251:350]


void CefWindowView::CreateWidget() {
  DCHECK(!GetWidget());

  // |widget| is owned by the NativeWidget and will be destroyed in response to
  // a native destruction message.
  views::Widget* widget = cef::IsChromeRuntimeEnabled() ? new ChromeBrowserFrame
                                                        : new views::Widget;

  views::Widget::InitParams params;
  params.delegate = this;
  params.type = views::Widget::InitParams::TYPE_WINDOW;
  bool can_activate = true;

  // WidgetDelegate::DeleteDelegate() will delete |this| after executing the
  // registered callback.
  SetOwnedByWidget(true);
  RegisterDeleteDelegateCallback(
      base::BindOnce(&CefWindowView::DeleteDelegate, base::Unretained(this)));

  if (cef_delegate()) {
    CefRefPtr<CefWindow> cef_window = GetCefWindow();
    is_frameless_ = cef_delegate()->IsFrameless(cef_window);

    auto bounds = cef_delegate()->GetInitialBounds(cef_window);
    params.bounds = gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height);

    SetCanResize(cef_delegate()->CanResize(cef_window));

    const auto show_state = cef_delegate()->GetInitialShowState(cef_window);
    switch (show_state) {
      case CEF_SHOW_STATE_NORMAL:
        params.show_state = ui::SHOW_STATE_NORMAL;
        break;
      case CEF_SHOW_STATE_MINIMIZED:
        params.show_state = ui::SHOW_STATE_MINIMIZED;
        break;
      case CEF_SHOW_STATE_MAXIMIZED:
        params.show_state = ui::SHOW_STATE_MAXIMIZED;
        break;
      case CEF_SHOW_STATE_FULLSCREEN:
        params.show_state = ui::SHOW_STATE_FULLSCREEN;
        break;
    }

    bool is_menu = false;
    bool can_activate_menu = true;
    CefRefPtr<CefWindow> parent_window = cef_delegate()->GetParentWindow(
        cef_window, &is_menu, &can_activate_menu);
    if (parent_window && !parent_window->IsSame(cef_window)) {
      CefWindowImpl* parent_window_impl =
          static_cast<CefWindowImpl*>(parent_window.get());
      params.parent = view_util::GetNativeView(parent_window_impl->widget());
      if (is_menu) {
        // Don't clip the window to parent bounds.
        params.type = views::Widget::InitParams::TYPE_MENU;

        // Don't set "always on top" for the window.
        params.z_order = ui::ZOrderLevel::kNormal;

        can_activate = can_activate_menu;
        if (can_activate_menu)
          params.activatable = views::Widget::InitParams::Activatable::kYes;
      }
    }
  }

  if (params.bounds.IsEmpty()) {
    // The window will be placed on the default screen with origin (0,0).
    params.bounds = gfx::Rect(CalculatePreferredSize());
  }

#if defined(OS_WIN)
  if (is_frameless_) {
    // Don't show the native window caption. Setting this value on Linux will
    // result in window resize artifacts.
    params.remove_standard_frame = true;
  }
#endif

  widget->Init(std::move(params));
  widget->AddObserver(this);

  // |widget| should now be associated with |this|.
  DCHECK_EQ(widget, GetWidget());
  // |widget| must be top-level for focus handling to work correctly.
  DCHECK(widget->is_top_level());

  if (can_activate) {
    // |widget| must be activatable for focus handling to work correctly.
    DCHECK(widget->widget_delegate()->CanActivate());
  }

#if defined(OS_LINUX) && defined(USE_X11)
  if (is_frameless_) {
    auto window = view_util::GetWindowHandle(widget);
    DCHECK(window);
    ui::SetUseOSWindowFrame(static_cast<x11::Window>(window), false);
  }
#endif  // defined(OS_LINUX) && defined(USE_X11)
}