Files
xfce-winxp-tc/shell/desktop/src/window.c
2024-11-10 00:35:04 +00:00

422 lines
9.3 KiB
C

#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <wintc/comgtk.h>
#include <wintc/shelldpa.h>
#include <wintc/syscfg.h>
#include "application.h"
#include "settings.h"
#include "window.h"
//
// PRIVATE ENUMS
//
enum
{
PROP_SETTINGS = 1
};
//
// GTK OOP CLASS/INSTANCE DEFINITIONS
//
struct _WinTCDesktopWindowClass
{
WinTCDpaDesktopWindowClass __parent__;
};
struct _WinTCDesktopWindow
{
WinTCDpaDesktopWindow __parent__;
// Drawing-related
//
GdkPixbuf* pixbuf_wallpaper;
cairo_surface_t* surface_wallpaper;
// State
//
WinTCDesktopSettings* settings;
};
//
// FORWARD DECLARATIONS
//
static void wintc_desktop_window_constructed(
GObject* object
);
static void wintc_desktop_window_dispose(
GObject* object
);
static void wintc_desktop_window_set_property(
GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec
);
static gboolean wintc_desktop_window_draw(
GtkWidget* widget,
cairo_t* cr
);
static void wintc_desktop_window_update_wallpaper(
WinTCDesktopWindow* wnd
);
static gboolean on_window_map_event(
GtkWidget* self,
GdkEventAny* event,
gpointer user_data
);
static void on_settings_notify_pixbuf_wallpaper(
GObject* self,
GParamSpec* pspec,
gpointer user_data
);
static void on_settings_notify_wallpaper_style(
GObject* self,
GParamSpec* pspec,
gpointer user_data
);
//
// GTK TYPE DEFINITION & CTORS
//
G_DEFINE_TYPE(
WinTCDesktopWindow,
wintc_desktop_window,
WINTC_TYPE_DPA_DESKTOP_WINDOW
)
static void wintc_desktop_window_class_init(
WinTCDesktopWindowClass* klass
)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
object_class->constructed = wintc_desktop_window_constructed;
object_class->dispose = wintc_desktop_window_dispose;
object_class->set_property = wintc_desktop_window_set_property;
widget_class->draw = wintc_desktop_window_draw;
g_object_class_install_property(
object_class,
PROP_SETTINGS,
g_param_spec_object(
"settings",
"Settings",
"The shared desktop settings",
WINTC_TYPE_DESKTOP_SETTINGS,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
)
);
}
static void wintc_desktop_window_init(
WinTCDesktopWindow* self
)
{
g_signal_connect(
self,
"map-event",
G_CALLBACK(on_window_map_event),
NULL
);
}
//
// CLASS VIRTUAL METHODS
//
static void wintc_desktop_window_constructed(
GObject* object
)
{
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object);
g_signal_connect(
wnd->settings,
"notify::pixbuf-wallpaper",
G_CALLBACK(on_settings_notify_pixbuf_wallpaper),
wnd
);
g_signal_connect(
wnd->settings,
"notify::wallpaper-style",
G_CALLBACK(on_settings_notify_wallpaper_style),
wnd
);
(G_OBJECT_CLASS(wintc_desktop_window_parent_class))->constructed(object);
}
static void wintc_desktop_window_dispose(
GObject* object
)
{
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object);
if (wnd->surface_wallpaper)
{
cairo_surface_destroy(g_steal_pointer(&(wnd->surface_wallpaper)));
g_clear_object(&(wnd->pixbuf_wallpaper));
}
(G_OBJECT_CLASS(wintc_desktop_window_parent_class))->dispose(object);
}
static void wintc_desktop_window_set_property(
GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec
)
{
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object);
switch (prop_id)
{
case PROP_SETTINGS:
wnd->settings = g_value_get_object(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static gboolean wintc_desktop_window_draw(
GtkWidget* widget,
cairo_t* cr
)
{
WinTCDpaDesktopWindow* dpa_wnd = WINTC_DPA_DESKTOP_WINDOW(widget);
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(widget);
gint wnd_w = gtk_widget_get_allocated_width(widget);
gint wnd_h = gtk_widget_get_allocated_height(widget);
// FIXME: Just drawing default desktop background colour atm
//
cairo_set_source_rgb(cr, 0.0f, 0.298f, 0.596f);
cairo_paint(cr);
// FIXME: Billy basic drawing of the wallpaper, if present
//
gint wallpaper_style = 0;
if (wnd->surface_wallpaper)
{
gint wallpaper_w = gdk_pixbuf_get_width(wnd->pixbuf_wallpaper);
gint wallpaper_h = gdk_pixbuf_get_height(wnd->pixbuf_wallpaper);
cairo_save(cr);
g_object_get(
wnd->settings,
"wallpaper-style", &wallpaper_style,
NULL
);
switch (wallpaper_style)
{
case WINTC_WALLPAPER_STYLE_CENTER:
cairo_translate(
cr,
((gdouble) wnd_w / 2) - ((gdouble) wallpaper_w / 2),
((gdouble) wnd_h / 2) - ((gdouble) wallpaper_h / 2)
);
break;
case WINTC_WALLPAPER_STYLE_STRETCH:
cairo_scale(
cr,
(gdouble) wnd_w / wallpaper_w,
(gdouble) wnd_h / wallpaper_h
);
break;
}
cairo_set_source_surface(cr, wnd->surface_wallpaper, 0.0f, 0.0f);
if (wallpaper_style == WINTC_WALLPAPER_STYLE_TILED)
{
cairo_pattern_set_extend(
cairo_get_source(cr),
CAIRO_EXTEND_REPEAT
);
}
cairo_paint(cr);
cairo_restore(cr);
}
// Rough watermark drawing
//
if (gdk_monitor_is_primary(dpa_wnd->monitor))
{
static gchar* s_tag = NULL;
cairo_text_extents_t extents;
gdouble y;
gint height = gtk_widget_get_allocated_height(widget);
gint width = gtk_widget_get_allocated_width(widget);
if (!s_tag)
{
s_tag =
g_strdup_printf(
"For testing purposes only. Build %s",
wintc_build_get_tag()
);
}
// Default to white, IDK if Windows changes this...
//
cairo_set_source_rgb(cr, 1.0f, 1.0f, 1.0f);
// Handle build string first...
//
cairo_select_font_face(
cr,
"sans-serif",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL
);
cairo_text_extents(cr, s_tag, &extents);
cairo_move_to(
cr,
width - extents.width - 10,
height - extents.height - 34 // FIXME: Hardcoded taskband height
);
cairo_show_text(cr, s_tag);
// ...and the product name
// FIXME: Hard coded temp name in here until we have a name
//
cairo_select_font_face(
cr,
"sans-serif",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_BOLD
);
cairo_text_extents(cr, "Windows 'Total Conversion'", &extents);
cairo_get_current_point(cr, NULL, &y);
cairo_move_to(
cr,
width - extents.width - 10,
y - extents.height - 4
);
cairo_show_text(cr, "Windows 'Total Conversion'");
}
return FALSE;
}
//
// PUBLIC FUNCTIONS
//
GtkWidget* wintc_desktop_window_new(
WinTCDesktopApplication* app,
GdkMonitor* monitor,
WinTCDesktopSettings* settings
)
{
return GTK_WIDGET(
g_object_new(
WINTC_TYPE_DESKTOP_WINDOW,
"application", GTK_APPLICATION(app),
"type", GTK_WINDOW_TOPLEVEL,
"decorated", TRUE,
"monitor", monitor,
"resizable", FALSE,
"settings", settings,
NULL
)
);
}
//
// PRIVATE FUNCTIONS
//
static void wintc_desktop_window_update_wallpaper(
WinTCDesktopWindow* wnd
)
{
WINTC_LOG_DEBUG("%s", "desktop: window updating wallpaper");
if (wnd->surface_wallpaper)
{
cairo_surface_destroy(g_steal_pointer(&(wnd->surface_wallpaper)));
g_clear_object(&(wnd->pixbuf_wallpaper));
}
g_object_get(
wnd->settings,
"pixbuf-wallpaper", &(wnd->pixbuf_wallpaper),
NULL
);
if (wnd->pixbuf_wallpaper)
{
wnd->surface_wallpaper =
gdk_cairo_surface_create_from_pixbuf(
wnd->pixbuf_wallpaper,
1,
NULL
);
gtk_widget_queue_draw(GTK_WIDGET(wnd));
}
}
//
// CALLBACKS
//
static gboolean on_window_map_event(
GtkWidget* self,
WINTC_UNUSED(GdkEventAny* event),
WINTC_UNUSED(gpointer user_data)
)
{
wintc_desktop_window_update_wallpaper(
WINTC_DESKTOP_WINDOW(self)
);
return FALSE;
}
static void on_settings_notify_pixbuf_wallpaper(
WINTC_UNUSED(GObject* self),
WINTC_UNUSED(GParamSpec* pspec),
gpointer user_data
)
{
wintc_desktop_window_update_wallpaper(
WINTC_DESKTOP_WINDOW(user_data)
);
}
static void on_settings_notify_wallpaper_style(
WINTC_UNUSED(GObject* self),
WINTC_UNUSED(GParamSpec* pspec),
gpointer user_data
)
{
gtk_widget_queue_draw(GTK_WIDGET(user_data));
}