/*
* Copyright (C) 2022 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*
* Author: Carlos Garnacho
*/
#include "config.h"
#include "meta-frame-content.h"
struct _MetaFrameContent
{
GtkWidget parent_instance;
Window window;
GtkBorder border;
gboolean border_initialized;
};
enum {
PROP_0,
PROP_XWINDOW,
PROP_BORDER,
N_PROPS
};
static GParamSpec *props[N_PROPS] = { 0, };
G_DEFINE_TYPE (MetaFrameContent, meta_frame_content, GTK_TYPE_WIDGET)
static void
meta_frame_content_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaFrameContent *frame_content = META_FRAME_CONTENT (object);
switch (prop_id)
{
case PROP_XWINDOW:
frame_content->window = (Window) g_value_get_ulong (value);
break;
case PROP_BORDER:
frame_content->border = *(GtkBorder*) g_value_get_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_frame_content_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaFrameContent *frame_content = META_FRAME_CONTENT (object);
switch (prop_id)
{
case PROP_XWINDOW:
g_value_set_ulong (value, (gulong) frame_content->window);
break;
case PROP_BORDER:
g_value_set_boxed (value, &frame_content->border);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_frame_content_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
*minimum_baseline = *natural_baseline = -1;
*minimum = *natural = 1;
}
static void
meta_frame_content_update_border (MetaFrameContent *content,
GtkBorder border)
{
if (content->border_initialized &&
content->border.left == border.left &&
content->border.right == border.right &&
content->border.top == border.top &&
content->border.bottom == border.bottom)
return;
content->border = border;
content->border_initialized = TRUE;
g_object_notify (G_OBJECT (content), "border");
}
static void
meta_frame_content_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
MetaFrameContent *content = META_FRAME_CONTENT (widget);
GtkWindow *window = GTK_WINDOW (gtk_widget_get_root (widget));
graphene_point_t point = {};
double scale;
if (!gtk_widget_compute_point (widget,
GTK_WIDGET (window),
&point, &point))
return;
scale = gdk_surface_get_scale_factor (gtk_native_get_surface (GTK_NATIVE (window)));
meta_frame_content_update_border (content,
/* FIXME: right/bottom are broken, if they
* are ever other than 0.
*/
(GtkBorder) {
point.x * scale, 0,
point.y * scale, 0,
});
}
static void
meta_frame_content_class_init (MetaFrameContentClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->set_property = meta_frame_content_set_property;
object_class->get_property = meta_frame_content_get_property;
widget_class->measure = meta_frame_content_measure;
widget_class->size_allocate = meta_frame_content_size_allocate;
props[PROP_XWINDOW] = g_param_spec_ulong ("xwindow", NULL, NULL,
0, G_MAXULONG, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB);
props[PROP_BORDER] = g_param_spec_boxed ("border", NULL, NULL,
GTK_TYPE_BORDER,
G_PARAM_READABLE |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB);
g_object_class_install_properties (object_class,
G_N_ELEMENTS (props),
props);
}
static void
meta_frame_content_init (MetaFrameContent *content)
{
}
GtkWidget *
meta_frame_content_new (Window window)
{
return g_object_new (META_TYPE_FRAME_CONTENT,
"xwindow", window,
NULL);
}
Window
meta_frame_content_get_window (MetaFrameContent *content)
{
return content->window;
}
GtkBorder
meta_frame_content_get_border (MetaFrameContent *content)
{
return content->border;
}