910e62b5创建于 1月15日历史提交
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_GTK_GTK_UTIL_H_
#define UI_GTK_GTK_UTIL_H_

#include <string>
#include <vector>

#include "base/component_export.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/glib/scoped_gobject.h"
#include "ui/color/color_id.h"
#include "ui/gtk/gtk_compat.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/window/frame_buttons.h"

class SkBitmap;

namespace aura {
class Window;
}

namespace gtk {

const char* GtkCssMenu();
const char* GtkCssMenuItem();
const char* GtkCssMenuScrollbar();

[[nodiscard]] bool GtkInitFromCommandLine(int* argc, char** argv);

// Sets |dialog| as transient for |parent|, which will keep it on top and center
// it above |parent|. Do nothing if |parent| is nullptr.
void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent);

// Gets the transient parent aura window for |dialog|.
aura::Window* GetAuraTransientParent(GtkWidget* dialog);

// Clears the transient parent for |dialog|.
void ClearAuraTransientParent(GtkWidget* dialog, aura::Window* parent);

// Disable input events handling on `parent` to make `dialog` modal.  The caller
// is responsible for running the returned closure when the dialog is hidden to
// reenable event processing on `parent`.
[[nodiscard]] base::OnceClosure DisableHostInputHandling(GtkWidget* dialog,
                                                         aura::Window* parent);

// Parses |button_string| into |leading_buttons| and
// |trailing_buttons|.  The string is of the format
// "<button>*:<button*>", for example, "close:minimize:maximize".
// This format is used by GTK settings.
void ParseButtonLayout(const std::string& button_string,
                       std::vector<views::FrameButton>* leading_buttons,
                       std::vector<views::FrameButton>* trailing_buttons);

class CairoSurface {
 public:
  // Attaches a cairo surface to an SkBitmap so that GTK can render
  // into it.  |bitmap| must outlive this CairoSurface.
  explicit CairoSurface(SkBitmap& bitmap);

  // Attaches a cairo surface to a pointer to pixel data.  `pixels`
  // must outlive this CairoSurface.
  CairoSurface(void* pixels, int width, int height);

  // Creates a new cairo surface with the given size.  The memory for
  // this surface is deallocated when this CairoSurface is destroyed.
  explicit CairoSurface(const gfx::Size& size);

  ~CairoSurface();

  // Get the drawing context for GTK to use.
  cairo_t* cairo() { return cairo_; }

  // Returns the average of all pixels in the surface.  If |frame| is
  // true, the resulting alpha will be the average alpha, otherwise it
  // will be the max alpha across all pixels.
  SkColor GetAveragePixelValue(bool frame);

 private:
  raw_ptr<cairo_surface_t> surface_;
  raw_ptr<cairo_t> cairo_;
};

class GtkCssContext {
 public:
  GtkCssContext();
  GtkCssContext(const GtkCssContext&);
  GtkCssContext(GtkCssContext&&);
  GtkCssContext& operator=(const GtkCssContext&);
  GtkCssContext& operator=(GtkCssContext&&);
  ~GtkCssContext();

  // GTK3 constructor.
  explicit GtkCssContext(GtkStyleContext* context);

  // GTK4 constructor.
  GtkCssContext(GtkWidget* widget, GtkWidget* root);

  // As a convenience, allow using a GtkCssContext as a gtk_style_context()
  // to avoid repeated use of an explicit getter.
  // NOLINTNEXTLINE(google-explicit-constructor)
  operator GtkStyleContext*();

  GtkCssContext GetParent();

  // Only available on GTK4.
  GtkWidget* widget();
  GtkWidget* root();

 private:
  // GTK3 state.
  ScopedGObject<GtkStyleContext> context_;

  // GTK4 state.
  // GTK widgets own their children, so instead of keeping a reference to the
  // widget directly, keep a reference to the root widget.
  raw_ptr<GtkWidget> widget_ = nullptr;
  ScopedGObject<GtkWidget> root_;
};

using ScopedCssProvider = ScopedGObject<GtkCssProvider>;

// Converts ui::NativeTheme::State to GtkStateFlags.
GtkStateFlags StateToStateFlags(ui::NativeTheme::State state);

// If |context| is nullptr, creates a new top-level style context
// specified by parsing |css_node|.  Otherwise, creates the child
// context with |context| as the parent.
GtkCssContext AppendCssNodeToStyleContext(GtkCssContext context,
                                          const std::string& css_node);

// Parses |css_selector| into a StyleContext.  The format is a
// sequence of whitespace-separated objects.  Each object may have at
// most one object name at the beginning of the string, and any number
// of '.'-prefixed classes and ':'-prefixed pseudoclasses.  An example
// is "GtkButton.button.suggested-action:hover:active".  The caller
// must g_object_unref() the returned context.
GtkCssContext GetStyleContextFromCss(const std::string& css_selector);

SkColor GetBgColorFromStyleContext(GtkCssContext context);

// Overrides properties on |context| and all its parents with those
// provided by |css|.
void ApplyCssToContext(GtkCssContext context, const std::string& css);

// Get the 'color' property from the style context created by
// GetStyleContextFromCss(|css_selector|).
SkColor GetFgColor(const std::string& css_selector);

ScopedCssProvider GetCssProvider(const std::string& css);

// Renders the backgrounds of all ancestors of |context|, then renders
// the background for |context| itself.
void RenderBackground(const gfx::Size& size,
                      cairo_t* cr,
                      GtkCssContext context);

// Renders a background from the style context created by
// GetStyleContextFromCss(|css_selector|) into a 24x24 bitmap and
// returns the average color.
SkColor GetBgColor(const std::string& css_selector);

// Renders the border from the style context created by
// GetStyleContextFromCss(|css_selector|) into a 24x24 bitmap and
// returns the average color.
SkColor GetBorderColor(const std::string& css_selector);

// Get the color of the GtkSeparator specified by |css_selector|.
SkColor GetSeparatorColor(const std::string& css_selector);

// Get a GtkSettings property as a C++ string.
std::string GetGtkSettingsStringProperty(GtkSettings* settings,
                                         const gchar* prop_name);

GtkIconTheme* GetDefaultIconTheme();

void GtkWindowDestroy(GtkWidget* widget);

GtkWidget* GetDummyWindow();

gfx::Size GetSeparatorSize(bool horizontal);

float GetDeviceScaleFactor();

// This should only be called on Gtk4.
GdkTexture* GetTextureFromRenderNode(GskRenderNode* node);

double GetOpacityFromContext(GtkStyleContext* context);

}  // namespace gtk

#endif  // UI_GTK_GTK_UTIL_H_