diff --git a/lib/libmks.h b/lib/libmks.h index 0a2ce73..3fd0460 100644 --- a/lib/libmks.h +++ b/lib/libmks.h @@ -30,6 +30,7 @@ G_BEGIN_DECLS # include "mks-init.h" # include "mks-keyboard.h" # include "mks-mouse.h" +# include "mks-paintable.h" # include "mks-screen.h" # include "mks-session.h" # include "mks-types.h" diff --git a/lib/meson.build b/lib/meson.build index 59b8d99..b29ccd9 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -3,6 +3,7 @@ libmks_sources = [ 'mks-device.c', 'mks-keyboard.c', 'mks-mouse.c', + 'mks-paintable.c', 'mks-screen.c', 'mks-session.c', ] @@ -13,6 +14,7 @@ libmks_headers = [ 'mks-init.h', 'mks-keyboard.h', 'mks-mouse.h', + 'mks-paintable.h', 'mks-screen.h', 'mks-session.h', 'mks-types.h', diff --git a/lib/mks-init.c b/lib/mks-init.c index b93f269..1c73895 100644 --- a/lib/mks-init.c +++ b/lib/mks-init.c @@ -26,6 +26,7 @@ #include "mks-init.h" #include "mks-keyboard.h" #include "mks-mouse.h" +#include "mks-paintable.h" #include "mks-qemu.h" #include "mks-read-only-list-model-private.h" #include "mks-screen.h" @@ -53,6 +54,7 @@ mks_init_gtypes (void) g_type_ensure (MKS_TYPE_DEVICE); g_type_ensure (MKS_TYPE_KEYBOARD); g_type_ensure (MKS_TYPE_MOUSE); + g_type_ensure (MKS_TYPE_PAINTABLE); g_type_ensure (MKS_TYPE_SCREEN); g_type_ensure (MKS_TYPE_SESSION); } diff --git a/lib/mks-paintable.c b/lib/mks-paintable.c new file mode 100644 index 0000000..b045886 --- /dev/null +++ b/lib/mks-paintable.c @@ -0,0 +1,226 @@ +/* + * mks-paintable.c + * + * Copyright 2023 Christian Hergert + * + * 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 3 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "config.h" + +#include "mks-paintable.h" +#include "mks-screen.h" + +struct _MksPaintable +{ + GObject parent_instance; + MksScreen *screen; +}; + +static void paintable_iface_init (GdkPaintableInterface *iface); + +G_DEFINE_FINAL_TYPE_WITH_CODE (MksPaintable, mks_paintable, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, paintable_iface_init)) + +enum { + PROP_0, + PROP_SCREEN, + N_PROPS +}; + +static GParamSpec *properties [N_PROPS]; + +GdkPaintable * +mks_paintable_new (MksScreen *screen) +{ + g_return_val_if_fail (MKS_IS_SCREEN (screen), NULL); + + return g_object_new (MKS_TYPE_PAINTABLE, + "screen", screen, + NULL); +} + +static void +mks_paintable_set_screen (MksPaintable *self, + MksScreen *screen) +{ + g_assert (MKS_IS_PAINTABLE (self)); + g_assert (MKS_IS_SCREEN (screen)); + + if (g_set_object (&self->screen, screen)) + { + g_signal_connect_object (self->screen, + "notify::width", + G_CALLBACK (gdk_paintable_invalidate_size), + self, + G_CONNECT_SWAPPED); + g_signal_connect_object (self->screen, + "notify::height", + G_CALLBACK (gdk_paintable_invalidate_size), + self, + G_CONNECT_SWAPPED); + } +} + +static void +mks_paintable_dispose (GObject *object) +{ + MksPaintable *self = (MksPaintable *)object; + + g_clear_object (&self->screen); + + G_OBJECT_CLASS (mks_paintable_parent_class)->dispose (object); +} + +static void +mks_paintable_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MksPaintable *self = MKS_PAINTABLE (object); + + switch (prop_id) + { + case PROP_SCREEN: + g_value_set_object (value, mks_paintable_get_screen (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +mks_paintable_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MksPaintable *self = MKS_PAINTABLE (object); + + switch (prop_id) + { + case PROP_SCREEN: + mks_paintable_set_screen (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +mks_paintable_class_init (MksPaintableClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = mks_paintable_dispose; + object_class->get_property = mks_paintable_get_property; + object_class->set_property = mks_paintable_set_property; + + properties [PROP_SCREEN] = + g_param_spec_object ("screen", NULL, NULL, + MKS_TYPE_SCREEN, + (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +mks_paintable_init (MksPaintable *self) +{ +} + +/** + * mks_paintable_get_screen: + * @self: a #MksPaintable + * + * Gets the #MksScreen displayed in the paintable. + * + * Returns: (nullable) (transfer none): a #MksScreen or %NULL + */ +MksScreen * +mks_paintable_get_screen (MksPaintable *self) +{ + g_return_val_if_fail (MKS_IS_PAINTABLE (self), NULL); + + return self->screen; +} + +static int +mks_paintable_get_intrinsic_height (GdkPaintable *paintable) +{ + MksPaintable *self = MKS_PAINTABLE (paintable); + + return self->screen ? mks_screen_get_height (self->screen) : 0; +} + +static int +mks_paintable_get_intrinsic_width (GdkPaintable *paintable) +{ + MksPaintable *self = MKS_PAINTABLE (paintable); + + return self->screen ? mks_screen_get_width (self->screen) : 0; +} + +static double +mks_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable) +{ + MksPaintable *self = MKS_PAINTABLE (paintable); + double width; + double height; + + if (self->screen == NULL) + return 1.; + + width = mks_screen_get_width (self->screen); + height = mks_screen_get_height (self->screen); + + if (width == 0 || height == 0) + return 1; + + return width / height; +} + +static GdkPaintableFlags +mks_paintable_get_flags (GdkPaintable *paintable) +{ + return 0; +} + +static void +mks_paintable_snapshot (GdkPaintable *paintable, + GdkSnapshot *snapshot, + double width, + double height) +{ + MksPaintable *self = (MksPaintable *)paintable; + + g_assert (MKS_IS_PAINTABLE (self)); + g_assert (GDK_IS_SNAPSHOT (snapshot)); + +} + +static void +paintable_iface_init (GdkPaintableInterface *iface) +{ + iface->get_intrinsic_height = mks_paintable_get_intrinsic_height; + iface->get_intrinsic_width = mks_paintable_get_intrinsic_width; + iface->get_flags = mks_paintable_get_flags; + iface->get_intrinsic_aspect_ratio = mks_paintable_get_intrinsic_aspect_ratio; + iface->snapshot = mks_paintable_snapshot; +} diff --git a/lib/mks-paintable.h b/lib/mks-paintable.h new file mode 100644 index 0000000..17b6c13 --- /dev/null +++ b/lib/mks-paintable.h @@ -0,0 +1,45 @@ +/* + * mks-paintable.h + * + * Copyright 2023 Christian Hergert + * + * 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 3 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#if !defined(MKS_INSIDE) && !defined(MKS_COMPILATION) +# error "Only can be included directly." +#endif + +#include + +#include "mks-types.h" +#include "mks-version-macros.h" + +G_BEGIN_DECLS + +#define MKS_TYPE_PAINTABLE (mks_paintable_get_type()) + +MKS_AVAILABLE_IN_ALL +G_DECLARE_FINAL_TYPE (MksPaintable, mks_paintable, MKS, PAINTABLE, GObject) + +MKS_AVAILABLE_IN_ALL +GdkPaintable *mks_paintable_new (MksScreen *screen); +MKS_AVAILABLE_IN_ALL +MksScreen *mks_paintable_get_screen (MksPaintable *self); + +G_END_DECLS