Use gt4-layer-shell 1.1.0 that supports session lock

This commit is contained in:
DanyLE 2025-03-05 14:29:54 +01:00
parent 98885e34a3
commit f722acdd20
18 changed files with 151 additions and 2538 deletions

View File

@ -30,7 +30,7 @@ wl_protocol_dir = wayland_protocols.get_variable('pkgdatadir')
# pkg_config = import('pkgconfig')
# gnome = import('gnome')
gtk_layer_shell = dependency('gtk4-layer-shell-0', version: '>=1.0.2')
gtk_layer_shell = dependency('gtk4-layer-shell-0', version: '>=1.1.0')
wayland_targets=[]
wl_protocols = [
@ -56,11 +56,6 @@ src = [
'src/shell.c',
'src/foreign.c',
'src/session.c',
'src/widgets/cairo-widget.c',
'src/widgets/cairo-box.c',
'src/widgets/cairo-window.c',
'src/widgets/cairo-image.c',
'src/widgets/cairo-text.c',
'src/main.c',
wayland_targets]

View File

@ -12,27 +12,29 @@ static void on_launcher_destroy(GtkWindow *window, GApplication *_data)
//g_application_quit (G_APPLICATION (gtk_window_get_application (window)));
}
static void on_foreign_window_change(GtkApplication* app, DiyaForeignWindow * win, gpointer data)
static void on_foreign_window_change(DiyaShell* shell, DiyaForeignWindow * win, gpointer data)
{
(void) app;
(void) data;
assert(win);
g_warning("WINDOW CHANGEEEEEEEEE %s", diya_object_to_string(DIYA_OBJECT(win)));
assert(shell);
g_warning("on_foreign_window_change: WINDOW CHANGE %s, shell %s", diya_object_to_string(DIYA_OBJECT(win)), diya_object_to_string(DIYA_OBJECT(shell)));
}
static void on_foreign_window_removed(GtkApplication* app, DiyaForeignWindow * win, gpointer data)
static void on_foreign_window_removed(DiyaShell* shell, DiyaForeignWindow * win, gpointer data)
{
(void) app;
(void) data;
assert(win);
g_warning("WINDOW removed %s", diya_object_to_string(DIYA_OBJECT(win)));
assert(shell);
g_warning("on_foreign_window_removed: WINDOW REMOVED %s, shell %s", diya_object_to_string(DIYA_OBJECT(win)), diya_object_to_string(DIYA_OBJECT(shell)));
}
static void session_lock(GtkWidget *widget,gpointer data)
{
(void) widget;
g_warning("Enter session lock");
diya_shell_lock(data);
}
void diya_shell_launcher_init(DiyaShell * shell)
{
assert(shell);
@ -84,10 +86,10 @@ void diya_shell_launcher_init(DiyaShell * shell)
{
gpointer element_data = l->data;
/*g_warning("%s", g_app_info_get_display_name(element_data));
g_warning("%s", g_app_info_get_display_name(element_data));
g_warning("%s", g_app_info_get_id(element_data));
g_warning("%s", g_app_info_get_name(element_data));
//g_warning("%s", g_app_info_get_icon(element_data));*/
//g_warning("%s", g_app_info_get_icon(element_data));
}
g_list_free_full(apps, g_object_unref);
}

View File

@ -1,9 +1,11 @@
#include <glib-unix.h>
#include <assert.h>
#include "shell.h"
#include "background.h"
#include "launcher.h"
#include "wayland.h"
#include "foreign.h"
#include "session.h"
static gchar **g_shell_argv;
@ -55,6 +57,20 @@ static void startup(GtkApplication *app, void *data)
g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app);
}
static void session_locked(DiyaShell* shell, void* data)
{
(void)data;
assert(shell);
g_warning("session_locked callback triggered");
}
static void session_unlocked(DiyaShell* shell, void* data)
{
(void)data;
assert(shell);
g_warning("session_unlocked callback triggered");
}
int main(int argc, char *argv[])
{
g_shell_argv = g_malloc0(sizeof(gchar *) * (argc + 1));
@ -66,6 +82,8 @@ int main(int argc, char *argv[])
DiyaShell *shell = diya_shell_new(app);
g_signal_connect(app, "startup", G_CALLBACK(startup), (void *)shell);
g_signal_connect(app, "activate", G_CALLBACK(activate), (void *)shell);
g_signal_connect(shell, "session-locked", G_CALLBACK(session_locked), NULL);
g_signal_connect(shell, "session-unlocked", G_CALLBACK(session_unlocked), NULL);
// g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), (void*)shell);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_warning("Exiting SHELL");

View File

@ -1,434 +1,71 @@
#include <assert.h>
// #include <wayland-egl.h>
// #include <EGL/egl.h>
#include <cairo/cairo.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#include <gtk4-session-lock.h>
#include <gtk/gtk.h>
#include "session.h"
#include "wayland.h"
#include "widgets/cairo-window.h"
#include "widgets/cairo-box.h"
#include "widgets/cairo-image.h"
#include "widgets/cairo-text.h"
#define DEF_SURF_W 600
#define DEF_SURF_H 400
#define LOREM "Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n" \
"sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n" \
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \n" \
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in \n" \
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n" \
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia \n" \
"deserunt mollit anim id est laborum."
struct _DiyaLockSession
static void unlock_session(GtkButton *button, DiyaShell *shell)
{
DiyaObject parent;
struct ext_session_lock_v1 *session_lock;
struct ext_session_lock_v1_listener session_listener;
struct ext_session_lock_surface_v1_listener surface_listener;
struct wl_callback_listener frame_listener;
struct wl_surface *wl_surface;
struct wl_buffer *wl_buffer;
void * raw_shared_buffer;
guint32 raw_shared_buffer_size;
cairo_surface_t *cairo_surface;
DiyaCairoWindow * window;
guint surface_width;
guint surface_height;
guint32 last_frame_time;
guint hold;
};
G_DEFINE_FINAL_TYPE(DiyaLockSession, diya_lock_session, DIYA_TYPE_SHELL_OBJECT)
static struct ext_session_lock_manager_v1 *g_session_lock_manager;
static const cairo_user_data_key_t shm_surface_data_key;
static void diya_lock_session_dispose(GObject *object)
{
DiyaLockSession *self = DIYA_LOCK_SESSION(object);
g_debug("diya_lock_session_dispose: %s", diya_object_to_string(self));
if (self->session_lock && !self->hold)
{
ext_session_lock_v1_unlock_and_destroy(self->session_lock);
}
else
{
g_warning("diya_lock_session_dispose: the lock session is disposed but the lock has not been released");
}
if (self->cairo_surface)
{
cairo_surface_destroy(self->cairo_surface);
self->cairo_surface = NULL;
}
if(self->window)
{
g_object_unref(self->window);
self->window = NULL;
}
G_OBJECT_CLASS(diya_lock_session_parent_class)->dispose(object);
(void)button;
assert(shell);
diya_shell_unlock(shell);
}
static void handle_session_locked(void *data, struct ext_session_lock_v1 *lock)
{
(void) lock;
DiyaShell *shell;
GtkApplication *app;
DiyaWayland *wayland;
DiyaLockSession *self = data;
g_object_get(self, "shell", &shell, NULL);
void diya_shell_lock(DiyaShell* shell)
{
assert(shell);
g_object_get(shell, "application", &app, "wayland", &wayland, NULL);
GtkSessionLockInstance * lock;
g_object_get(shell, "session-lock", &lock, NULL);
assert(lock);
if(gtk_session_lock_instance_is_locked(lock))
{
g_warning("Shell session is already locked, doing nothing");
return;
}
if(!gtk_session_lock_instance_lock(lock))
{
g_error("gtk_session_lock_instance_lock:Unable to lock the current session");
return;
}
GtkApplication * app;
g_object_get(shell, "application", &app, NULL);
assert(app);
assert(DIYA_IS_WAYLAND(wayland));
g_debug("Session locked on shell: %s", diya_object_to_string(shell));
struct wl_surface *surface = diya_wayland_create_surface(wayland);
struct wl_output *output = diya_wayland_get_output(wayland, 0);
assert(output);
self->wl_surface = surface;
struct ext_session_lock_surface_v1 *lock_surface = ext_session_lock_v1_get_lock_surface(self->session_lock, surface, output);
ext_session_lock_surface_v1_add_listener(lock_surface, &self->surface_listener, data);
struct wl_callback *cb = wl_surface_frame(self->wl_surface);
wl_callback_add_listener(cb, &self->frame_listener, data);
GdkDisplay *display = gdk_display_get_default();
GListModel *monitors = gdk_display_get_monitors(display);
guint n_monitors = g_list_model_get_n_items(monitors);
for (guint i = 0; i < n_monitors; ++i)
{
GdkMonitor *monitor = g_list_model_get_item(monitors, i);
GtkWindow *gtk_window = GTK_WINDOW(gtk_application_window_new(app));
gtk_session_lock_instance_assign_window_to_monitor(lock, gtk_window, monitor);
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
gtk_box_set_spacing(GTK_BOX (box), 10);
GtkWidget *label = gtk_label_new("GTK Session Lock example");
gtk_box_append(GTK_BOX(box), label);
GtkWidget *button = gtk_button_new_with_label("Unlock");
g_signal_connect(button, "clicked", G_CALLBACK(unlock_session), shell);
gtk_box_append(GTK_BOX(box), button);
// Not displayed, but allows testing that creating popups doesn't crash GTK
gtk_widget_set_tooltip_text(button, "Foo Bar Baz");
gtk_window_set_child(GTK_WINDOW(gtk_window), box);
gtk_window_present(gtk_window);
}
}
static void handle_session_lock_finished(void *data, struct ext_session_lock_v1 *lock)
void diya_shell_unlock(DiyaShell* shell)
{
DiyaShell *shell;
g_object_get(data, "shell", &shell, NULL);
assert(shell);
ext_session_lock_v1_destroy(lock);
g_warning("Session locked finished on shell %s", diya_object_to_string(shell));
}
static void randname(char *buf)
{
long r = g_get_real_time() / 1000000;
for (int i = 0; i < 6; ++i)
{
buf[i] = 'A' + (r & 15) + (r & 16) * 2;
r >>= 5;
}
}
static int create_shm_file(void)
{
int retries = 100;
do
{
char name[] = "/diya_shell_wl_shm-XXXXXX";
randname(name + sizeof(name) - 7);
--retries;
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd >= 0)
{
shm_unlink(name);
return fd;
}
} while (retries > 0 && errno == EEXIST);
return -1;
}
static int allocate_shm_file(guint size)
{
int fd = create_shm_file();
if (fd < 0)
{
g_error("allocate_shm_file: unable to create_shm_file: %s", strerror(errno));
return -1;
}
int ret;
do
{
ret = ftruncate(fd, size);
} while (ret < 0 && errno == EINTR);
if (ret < 0)
{
g_error("allocate_shm_file: unable to ftruncate: %s", strerror(errno));
close(fd);
return -1;
}
return fd;
}
static void session_lock_free_surface(void *data)
{
DiyaLockSession * self = data;
assert(DIYA_IS_LOCK_SESSION(self));
if (self->wl_buffer)
{
g_debug("Destroy share buffer wl_buffer");
wl_buffer_destroy(self->wl_buffer);
self->wl_buffer = NULL;
}
if(self->raw_shared_buffer)
{
g_debug("unmapped shared buffer of %d bytes", self->raw_shared_buffer_size);
munmap(self->raw_shared_buffer, self->raw_shared_buffer_size);
self->raw_shared_buffer = NULL;
self->raw_shared_buffer_size = 0;
}
}
static void session_lock_realloc_surface(DiyaLockSession *self)
{
DiyaShell *shell;
g_object_get(self, "shell", &shell, NULL);
assert(DIYA_IS_SHELL(shell));
DiyaWayland *wayland = diya_shell_get_wayland(shell);
assert(DIYA_IS_WAYLAND(wayland));
if (self->cairo_surface)
{
cairo_surface_destroy(self->cairo_surface);
self->cairo_surface = NULL;
}
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, self->surface_width);
guint size = stride * self->surface_height;
int fd = allocate_shm_file(size);
if (fd == -1)
{
g_error("session_lock_realloc_surface: unable to allocate_shm_file");
return;
}
void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED)
{
g_error("session_lock_realloc_surface: unable to mmap: %s", strerror(errno));
close(fd);
return;
}
self->cairo_surface = cairo_image_surface_create_for_data(data,
CAIRO_FORMAT_ARGB32,
self->surface_width,
self->surface_height,
stride);
cairo_surface_set_user_data(self->cairo_surface, &shm_surface_data_key, self, session_lock_free_surface);
struct wl_shm_pool *pool = diya_wayland_create_shm_pool(wayland, fd, size);
self->wl_buffer = wl_shm_pool_create_buffer(pool, 0,
self->surface_width, self->surface_height, stride, WL_SHM_FORMAT_XRGB8888);
wl_shm_pool_destroy(pool);
close(fd);
self->raw_shared_buffer = data;
self->raw_shared_buffer_size = size;
}
static void lock_session_draw_frame(DiyaLockSession *self)
{
if(!self->cairo_surface)
{
return;
}
diya_cairo_window_render(self->window, self->cairo_surface);
wl_surface_attach(self->wl_surface, self->wl_buffer, 0, 0);
wl_surface_damage_buffer(self->wl_surface, 0, 0, self->surface_width, self->surface_height);
wl_surface_commit(self->wl_surface);
}
static void lock_surface_configure(void *data,
struct ext_session_lock_surface_v1 *lock_surface,
uint32_t serial, uint32_t width, uint32_t height)
{
DiyaLockSession *self = data;
assert(DIYA_IS_LOCK_SESSION(self));
if (!self->wl_buffer || self->surface_width != width || self->surface_height != height)
{
self->surface_width = width;
self->surface_height = height;
session_lock_realloc_surface(self);
diya_cairo_widget_set_size(self->window, width, height);
g_warning("update and damaged window");
diya_cairo_window_update(self->window);
}
ext_session_lock_surface_v1_ack_configure(lock_surface, serial);
lock_session_draw_frame(self);
}
static void lock_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time)
{
/* Destroy this callback */
wl_callback_destroy(cb);
DiyaLockSession *lock = data;
assert(DIYA_IS_LOCK_SESSION(lock));
cb = wl_surface_frame(lock->wl_surface);
wl_callback_add_listener(cb, &lock->frame_listener, data);
if (!lock->cairo_surface || !lock->wl_buffer || lock->window)
{
return;
}
lock->last_frame_time = time;
lock_session_draw_frame(lock);
}
static void diya_lock_session_ui(DiyaCairoWindow * window)
{
diya_stroke_t stroke = {
2.0,
{ 1.0, 0.0, 1.0, 1.0 }
};
diya_stroke_t stroke1 = {
2.0,
{ 0.0, 0.0, 1.0, 1.0 }
};
diya_offset_t margin = {10,20,10,20};
diya_offset_t padding = {20, 10, 20, 10};
g_object_set(window, "margin", &margin, "padding", &padding, NULL);
DiyaCairoBox * root = g_object_new(
DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"stroke", &stroke,
NULL);
diya_cairo_window_set_background_image(window, "/etc/xdg/labwc/wpp.jpg", TRUE);
diya_cairo_window_set_root(window, root);
DiyaCairoBox * box = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"stroke", &stroke1,
NULL);
diya_cairo_container_add(root, box);
box = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_VERTICAL,
"vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
"hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
"stroke", &stroke,
NULL);
diya_cairo_container_add(root, box);
DiyaCairoBox* hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"stroke", &stroke1,
NULL);
diya_cairo_container_add(box, hbox);
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
"hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT,
"stroke", &stroke,
"padding", &padding,
"corner-radius", 10.0,
NULL);
diya_cairo_container_add(box, hbox);
diya_stroke_t stroke_img = {
2.0,
{ 0.0, 0.0, 1.0, 1.0 }
};
diya_color_t fill = { 1.0,1.0,1.0,1.0 };
diya_color_t color = { 0.0,0.0,0.0,1.0 };
DiyaCairoText *text = g_object_new(DIYA_TYPE_CAIRO_TEXT,
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
"stroke", &stroke,
"padding", &padding,
"corner-radius", 5.0,
"fill", &fill,
"color", &color,
"font-size", 11,
"font-family", "Monospace",
"halign", DIYA_CAIRO_WIDGET_ALIGN_START,
"valign", DIYA_CAIRO_WIDGET_ALIGN_START,
NULL);
diya_cairo_text_set_text(text, LOREM);
diya_cairo_widget_set_size(text, 600, 400);
diya_cairo_container_add(hbox, text);
/*DiyaCairoImage * image = g_object_new(DIYA_TYPE_CAIRO_IMAGE,
"file",
"/home/diya/test.jpg",
"stroke",
&stroke_img,
"vspace", DIYA_CAIRO_WIDGET_FILL_NONE,
"hspace", DIYA_CAIRO_WIDGET_FILL_NONE,
NULL);
diya_cairo_container_add(hbox, image);*/
hbox = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"stroke", &stroke1,
NULL);
diya_cairo_container_add(box, hbox);
box = g_object_new(DIYA_TYPE_CAIRO_BOX,
"mode", DIYA_CAIRO_BOX_HORIZONTAL,
"stroke", &stroke1,
NULL);
diya_cairo_container_add(root, box);
}
static void diya_lock_session_init(DiyaLockSession *self)
{
self->session_lock = ext_session_lock_manager_v1_lock(g_session_lock_manager);
self->session_listener.locked = handle_session_locked;
self->session_listener.finished = handle_session_lock_finished;
self->surface_listener.configure = lock_surface_configure;
ext_session_lock_v1_add_listener(self->session_lock, &self->session_listener, self);
self->frame_listener.done = lock_surface_frame_done;
self->surface_width = DEF_SURF_W;
self->surface_height = DEF_SURF_H;
self->hold = true;
self->last_frame_time = 0;
self->wl_surface = NULL;
self->wl_buffer = NULL;
self->window = g_object_new(DIYA_TYPE_CAIRO_WINDOW,NULL);
diya_lock_session_ui(self->window);
self->cairo_surface = NULL;
self->raw_shared_buffer = NULL;
self->raw_shared_buffer_size = 0;
}
static const gchar *diya_lock_session_to_string(DiyaObject *object)
{
(void)object;
// DiyaLockSession* self = DIYA_LOCK_SESSION(object);
return "DIYA SHELL LOCK SESSION";
}
static void diya_lock_session_class_init(DiyaLockSessionClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
gobject_class->dispose = diya_lock_session_dispose;
base_class->to_string = diya_lock_session_to_string;
}
void diya_shell_session_lock_register(struct wl_registry *registry, uint32_t name)
{
g_session_lock_manager = wl_registry_bind(registry, name, &ext_session_lock_manager_v1_interface, 1);
}
void diya_shell_session_lock_release(DiyaLockSession *self)
{
self->hold = false;
GtkSessionLockInstance * lock;
g_object_get(shell, "session-lock", &lock, NULL);
assert(lock);
gtk_session_lock_instance_unlock(lock);
g_debug("gtk_session_lock_instance_unlock: Shell unlocked");
}

View File

@ -1,9 +1,9 @@
#ifndef DIYA_SESSION_H
#define DIYA_SESSION_H
#include "ext-session-lock-v1.h"
#include "shell.h"
void diya_shell_session_lock_register(struct wl_registry *registry, uint32_t name);
void diya_shell_session_lock_release(DiyaLockSession * self);
void diya_shell_lock(DiyaShell* shell);
void diya_shell_unlock(DiyaShell* shell);
#endif

View File

@ -1,7 +1,6 @@
#include <assert.h>
#include "foreign.h"
#include "session.h"
#include <gtk4-session-lock.h>
#include "shell.h"
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
@ -11,6 +10,7 @@ enum
SHELL_APP,
SHELL_BACKGROUND_WIDGET,
SHELL_LAUNCHPAD_WIDGET,
SHELL_LOCK_SESSION,
SHELL_WINDOWS,
SHELL_WAYLAND,
N_PROPERTIES
@ -25,7 +25,7 @@ struct _DiyaShell
GtkWindow* background;
GtkWindow* launcher;
GHashTable* windows;
DiyaLockSession* lock;
GtkSessionLockInstance* lock;
DiyaWayland * wayland;
};
G_DEFINE_FINAL_TYPE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT)
@ -88,6 +88,10 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue *
assert(self->launcher);
g_value_set_pointer(value, self->launcher);
break;
case SHELL_LOCK_SESSION:
assert(self->lock);
g_value_set_pointer(value, self->lock);
break;
case SHELL_WAYLAND:
g_value_set_pointer(value, self->wayland);
break;
@ -119,6 +123,7 @@ static void diya_shell_class_init(DiyaShellClass *class)
shell_properties[SHELL_APP] = g_param_spec_pointer("application", NULL, "Shell application", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer("background", NULL, "Shell background widget", G_PARAM_READWRITE );
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READWRITE );
shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer("session-lock", NULL, "Shell lock session", G_PARAM_READABLE );
shell_properties[SHELL_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE);
shell_properties[SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READWRITE );
@ -148,6 +153,52 @@ static void diya_shell_class_init(DiyaShellClass *class)
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_new("session-locked",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new("session-unlocked",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
}
static void on_session_locked(GtkSessionLockInstance *lock, DiyaShell *shell) {
(void)lock;
assert(shell);
g_message("Session locked successfully");
g_signal_emit_by_name(shell, "session-locked");
}
/*
static void failed(GtkSessionLockInstance *lock, void *data) {
(void)lock;
(void)data;
g_critical("The session could not be locked");
g_application_quit(G_APPLICATION(app));
}
*/
static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaShell *shell) {
(void)lock;
assert(shell);
g_message("Session unlocked");
g_signal_emit_by_name(shell, "session-unlocked");
}
static void diya_shell_init(DiyaShell *self)
@ -156,6 +207,10 @@ static void diya_shell_init(DiyaShell *self)
self->background = NULL;
self->launcher = NULL;
self->wayland = NULL;
self->lock = gtk_session_lock_instance_new();
g_signal_connect(self->lock, "locked", G_CALLBACK(on_session_locked), self);
// g_signal_connect(lock, "failed", G_CALLBACK(failed), NULL);
g_signal_connect(self->lock, "unlocked", G_CALLBACK(on_session_unlocked), self);
self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
}
@ -190,21 +245,6 @@ DiyaShell * diya_shell_new(GtkApplication * app)
return DIYA_SHELL(g_object_new(DIYA_TYPE_SHELL,"application",app, NULL));
}
void diya_shell_lock(DiyaShell* shell)
{
if(shell->lock)
{
g_warning("Shell session is already locked, doing nothing");
return;
}
shell->lock = g_object_new(DIYA_TYPE_LOCK_SESSION, "shell", shell, NULL);
}
void diya_shell_unlock(DiyaShell* shell)
{
diya_shell_session_lock_release(shell->lock);
g_object_unref(shell->lock);
shell->lock = NULL;
}
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell)
{
DiyaWayland * wayland;

View File

@ -30,9 +30,6 @@ gboolean diya_shell_add_window(DiyaShell * shell, DiyaForeignWindow * win);
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaForeignWindow * win);
void diya_shell_remove_all_windows(DiyaShell * shell);
void diya_shell_lock(DiyaShell* shell);
void diya_shell_unlock(DiyaShell* shell);
DiyaShell * diya_shell_new(GtkApplication * app);
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
#endif

View File

@ -61,10 +61,12 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
{
diya_shell_foreign_toplevel_register(registry, name, data);
}
/*
else if(!g_strcmp0(interface, ext_session_lock_manager_v1_interface.name))
{
diya_shell_session_lock_register(registry, name);
}
*/
else if (strcmp(interface, wl_compositor_interface.name) == 0)
{
wayland->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);

View File

@ -1,299 +0,0 @@
#include <assert.h>
#include <math.h>
#include "cairo-box.h"
enum
{
NO_PROP,
BOX_MODE,
N_PROPERTIES
};
static GParamSpec *g_prop[N_PROPERTIES] = {0};
struct _DiyaCairoBox
{
DiyaCairoContainer parent_object;
guint mode;
};
G_DEFINE_FINAL_TYPE(DiyaCairoBox, diya_cairo_box, DIYA_TYPE_CAIRO_CONTAINER)
static void diya_cairo_box_dispose(GObject * object)
{
g_debug("diya_cairo_box_dispose: %s", diya_object_to_string(object));
G_OBJECT_CLASS(diya_cairo_box_parent_class)->dispose(object);
}
static void diya_cairo_box_init(DiyaCairoBox* self)
{
self->mode = DIYA_CAIRO_BOX_HORIZONTAL;
}
static void diya_cairo_box_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaCairoBox * self = DIYA_CAIRO_BOX(object);
switch (property_id)
{
case BOX_MODE:
self->mode = g_value_get_uint(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_cairo_box_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaCairoBox * self = DIYA_CAIRO_BOX(object);
switch (property_id)
{
case BOX_MODE:
g_value_set_uint(value, self->mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static gboolean cairo_box_draw(gpointer object, cairo_t * cairo)
{
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_box_parent_class)->draw(object, cairo);
GList * children = DIYA_CAIRO_CONTAINER_GET_CLASS(object)->children(object);
gpointer item;
G_LIST_FOREACH(item, children)
{
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(item))->draw(item, cairo);
}
return TRUE;
}
static void cairo_box_update(gpointer object)
{
diya_offset_t margin = {0};
g_object_set(
object,
"halign", DIYA_CAIRO_WIDGET_ALIGN_START,
"valign", DIYA_CAIRO_WIDGET_ALIGN_START,
"margin", &margin,
NULL
);
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_box_parent_class)->update(object);
assert(DIYA_IS_CAIRO_BOX(object));
DiyaCairoBox * self = DIYA_CAIRO_BOX(object);
GList * children = DIYA_CAIRO_CONTAINER_GET_CLASS(object)->children(object);
if(!children)
{
return;
}
diya_rect_t space = diya_cairo_widget_get_extent(object);
diya_offset_t * padding;
diya_stroke_t * stroke;
diya_rect_t * default_extent;
g_object_get(object,"padding", &padding, "stroke", &stroke, NULL);
gint stroke_size = ceil(stroke->size);
gpointer item;
guint n_extended = 0;
gint occupied_space = 2*stroke_size;
guint vspace, hspace;
guint cwidth, cheight;
// explore all other children
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
{
occupied_space += padding->left + padding->right;
}
else
{
occupied_space += padding->right + padding->bottom;
}
G_LIST_FOREACH(item, children)
{
g_object_get(item, "vspace", &vspace, "hspace", &hspace, "default-extent", &default_extent, NULL);
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
{
switch (hspace)
{
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
n_extended++;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
occupied_space += cwidth;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
occupied_space += default_extent->width;
break;
default:
break;
}
}
else
{
switch (vspace)
{
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
n_extended++;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
occupied_space += cheight;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
occupied_space += default_extent->height;
break;
default:
break;
}
}
}
gint off_x = padding->left + stroke_size;
gint off_y = padding->top + stroke_size;
G_LIST_FOREACH(item, children)
{
g_object_get(item, "vspace", &vspace, "hspace", &hspace, "default-extent", &default_extent, NULL);
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight);
diya_rect_t rect = {0};
rect.x = off_x;
rect.y = off_y;
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
{
rect.height = space.height - padding->top - padding->bottom - stroke_size*2;
switch (hspace)
{
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
rect.width = (occupied_space >= space.width)?0:(space.width - occupied_space) / n_extended;
off_x += rect.width;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
rect.width = cwidth;
if(!DIYA_IS_CAIRO_BOX(item))
{
rect.height = cheight;
}
off_x += cwidth;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
rect.width = default_extent->width;
if(!DIYA_IS_CAIRO_BOX(item))
{
rect.height = default_extent->height;
}
off_x += default_extent->width;
break;
default:
break;
}
}
else
{
rect.width = space.width - padding->left - padding->right - stroke_size*2;
switch (vspace)
{
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
rect.height = (occupied_space >= space.height)?0:(space.height - occupied_space) / n_extended;
off_y += rect.height;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
rect.height = cheight;
if(!DIYA_IS_CAIRO_BOX(item))
{
rect.width = cwidth;
}
off_y += cheight;
break;
case DIYA_CAIRO_WIDGET_FILL_NONE:
rect.height = default_extent->height;
if(!DIYA_IS_CAIRO_BOX(item))
{
rect.width = default_extent->width;
}
off_y += default_extent->height;
break;
default:
break;
}
}
diya_rect_t * item_extent = DIYA_CAIRO_WIDGET_GET_CLASS(item)->extent(item);
memcpy(item_extent, &rect, sizeof(rect));
}
G_LIST_FOREACH(item, children)
{
// back up vspace hspace
g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL);
g_object_set(item,
"vspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
"hspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
NULL);
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(item))->update(item);
g_object_set(item,
"vspace", vspace,
"hspace", hspace,
NULL);
}
}
static diya_rect_t cairo_box_allocate_space(gpointer object, gpointer child)
{
(void) object;
return diya_cairo_widget_get_extent(child);
}
static void cairo_box_content_size(gpointer object, gint* width, gint * height)
{
DiyaCairoBox * self = DIYA_CAIRO_BOX(object);
*width = 0;
*height = 0;
gpointer item;
GList * children = DIYA_CAIRO_CONTAINER_GET_CLASS(object)->children(object);
diya_stroke_t * stroke;
diya_offset_t * padding;
g_object_get(object, "stroke", &stroke,"padding", &padding, NULL);
gint stroke_size = ceil(stroke->size) * 2;
G_LIST_FOREACH(item, children)
{
gint cw,ch;
DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item,&cw,&ch);
if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL)
{
*width += cw;
*height = MAX(*height,ch);
}
else
{
*height += ch;
*width = MAX(*width,cw);
}
}
*height += stroke_size + padding->bottom + padding->top;
*width += stroke_size + padding->left + padding->right;
}
static void diya_cairo_box_class_init(DiyaCairoBoxClass * class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoBox");
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
wclass->draw = cairo_box_draw;
wclass->update = cairo_box_update;
wclass->alloc_space = cairo_box_allocate_space;
wclass->content_size = cairo_box_content_size;
gobject_class->dispose = diya_cairo_box_dispose;
gobject_class->set_property = diya_cairo_box_set_property;
gobject_class->get_property = diya_cairo_box_get_property;
g_prop[BOX_MODE] = g_param_spec_uint(
"mode", NULL,
"Box mode", DIYA_CAIRO_BOX_HORIZONTAL,
DIYA_CAIRO_BOX_VERTICAL, DIYA_CAIRO_BOX_HORIZONTAL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (gobject_class, N_PROPERTIES, g_prop);
}

View File

@ -1,14 +0,0 @@
#ifndef CAIRO_BOX_H
#define CAIRO_BOX_H
#include "cairo-widget.h"
enum {
DIYA_CAIRO_BOX_HORIZONTAL,
DIYA_CAIRO_BOX_VERTICAL
};
#define DIYA_TYPE_CAIRO_BOX (diya_cairo_box_get_type ())
G_DECLARE_FINAL_TYPE (DiyaCairoBox, diya_cairo_box, DIYA, CAIRO_BOX, DiyaCairoContainer)
#endif

View File

@ -1,263 +0,0 @@
#include <gdk/gdk.h>
#include <math.h>
#include "cairo-image.h"
enum
{
NO_PROP,
IMG_FILE,
IMG_ALPHA,
IMG_PIXBUF,
IMG_FIT,
N_PROPERTIES
};
static GParamSpec *g_prop[N_PROPERTIES] = {0};
struct _DiyaCairoImage
{
DiyaCairoWidget parent_object;
gchar * file;
GdkPixbuf * buffer;
gdouble alpha;
gboolean fit;
};
G_DEFINE_FINAL_TYPE(DiyaCairoImage, diya_cairo_image, DIYA_TYPE_CAIRO_WIDGET)
static void diya_cairo_image_dispose(GObject * object)
{
g_debug("diya_cairo_image_dispose: %s", diya_object_to_string(object));
DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object);
if(self->file)
{
g_free(self->file);
}
if(self->buffer)
{
g_debug("diya_cairo_image_dispose: release image buffer");
g_object_unref(self->buffer);
}
G_OBJECT_CLASS(diya_cairo_image_parent_class)->dispose(object);
}
static void diya_cairo_set_pixbuf(DiyaCairoImage* self, GdkPixbuf * buf)
{
if(self->buffer)
{
g_object_unref(self->buffer);
self->buffer = NULL;
}
self->buffer = buf;
diya_cairo_widget_set_size(self,
gdk_pixbuf_get_width(self->buffer),
gdk_pixbuf_get_height(self->buffer)
);
diya_cairo_widget_damage(self);
}
static void diya_cairo_load_image_from_file(DiyaCairoImage* self, const gchar* path)
{
if(self->file)
{
g_free(self->file);
}
self->file = g_strdup(path);
GError *error = NULL;
GdkPixbuf * buf = gdk_pixbuf_new_from_file(self->file,&error);
if(!buf)
{
g_error("diya_cairo_load_image_from_file: [%s] %s", self->file, error->message);
return;
}
diya_cairo_set_pixbuf(self,buf);
}
static void diya_cairo_image_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object);
switch (property_id)
{
case IMG_FILE:
diya_cairo_load_image_from_file(self, g_value_get_pointer(value));
break;
case IMG_ALPHA:
self->alpha = g_value_get_double(value);
break;
case IMG_FIT:
self->fit = g_value_get_boolean(value);
break;
case IMG_PIXBUF:
if(self->file)
{
g_free(self->file);
self->file = NULL;
}
diya_cairo_set_pixbuf(self,g_value_get_pointer(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_cairo_image_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object);
switch (property_id)
{
case IMG_FILE:
g_value_set_pointer(value, self->file);
break;
case IMG_ALPHA:
g_value_set_double(value, self->alpha);
break;
case IMG_FIT:
g_value_set_boolean(value, self->fit);
break;
case IMG_PIXBUF:
g_value_set_pointer(value, self->buffer);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_cairo_image_init(DiyaCairoImage * self)
{
self->file = NULL;
self->buffer = NULL;
self->alpha = 1.0;
self->fit = FALSE;
}
static gboolean diya_cairo_image_draw(gpointer object, cairo_t * context)
{
DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object);
if(!self->buffer || !diya_cairo_widget_is_damaged(self) || !diya_cairo_widget_is_visible(self))
{
return FALSE;
}
diya_rect_t view_port = diya_cairo_widget_get_view_port(object);
diya_rect_dump("view port: ", &view_port);
if(diya_rect_is_empty(&view_port))
{
return FALSE;
}
cairo_save(context);
cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height);
cairo_clip(context);
diya_color_t * color;
diya_stroke_t * stroke;
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
diya_rect_t * default_extent;
guint halign, valign;
diya_offset_t * margin;
diya_rect_t extent = diya_cairo_widget_get_extent(object);
diya_rect_dump("extent: ", &extent);
g_object_get(object,
"fill", &color,
"stroke", &stroke,
"halign", &halign,
"valign", &valign,
"margin", &margin,
"default-extent", &default_extent,
NULL);
gint img_width = default_extent->width;
gint img_height = default_extent->height;
gint stroke_size = ceil(stroke->size);
GdkPixbuf * buf = NULL;
if(self->fit)
{
img_width = extent.width;
img_height = extent.height;
buf = gdk_pixbuf_scale_simple(self->buffer,img_width, img_height, GDK_INTERP_BILINEAR);
}
else
{
buf = g_object_ref(self->buffer);
}
gint off_x = margin->left + stroke->size / 2.0;
gint off_y = margin->top + stroke->size / 2.0;
switch (halign)
{
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
off_x += (extent.width - img_width) / 2;
break;
case DIYA_CAIRO_WIDGET_ALIGN_END:
off_x += extent.width - img_width;
break;
default:
break;
}
switch (valign)
{
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
off_y += (extent.height - img_height) / 2;
break;
case DIYA_CAIRO_WIDGET_ALIGN_END:
off_y += extent.height - img_height;
break;
default:
break;
}
//g_warning("Global position %d %d offset %d %d", gpos.x, gpos.y, off_x, off_y);
if(color->a > 0)
{
//cairo_move_to(context, (double)gpos.x, (double)gpos.y);
cairo_rectangle(context,
gpos.x + margin->left + stroke_size,
gpos.y + margin->top + stroke_size,
extent.width - margin->left - margin->right - 2*stroke_size,
extent.height - margin->bottom - margin->top - 2*stroke_size);
cairo_set_source_rgba(context, color->r, color->g, color->b, color->a);
cairo_fill(context);
}
// draw image
gdk_cairo_set_source_pixbuf(context, buf, (double)(gpos.x + off_x), (double)(gpos.y + off_y));
cairo_paint_with_alpha(context, self->alpha);
if(stroke->size > 0 && stroke->color.a != 0)
{
//cairo_move_to(context, (double)gpos.x, (double)gpos.y);
cairo_rectangle(context,
gpos.x + margin->left + stroke_size,
gpos.y + margin->top + stroke_size,
extent.width - margin->left - margin->right - 2*stroke_size,
extent.height - margin->bottom - margin->top - 2*stroke_size);
cairo_set_source_rgba(context, stroke->color.r, stroke->color.g, stroke->color.b, stroke->color.a);
cairo_set_line_width(context,stroke->size);
cairo_stroke(context);
}
g_object_unref(buf);
cairo_restore(context);
return TRUE;
}
static void diya_cairo_image_class_init(DiyaCairoImageClass* class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
wclass->draw = diya_cairo_image_draw;
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoImage");
gobject_class->dispose = diya_cairo_image_dispose;
gobject_class->set_property = diya_cairo_image_set_property;
gobject_class->get_property = diya_cairo_image_get_property;
g_prop[IMG_FILE] = g_param_spec_pointer("file", NULL, "Image file", G_PARAM_READWRITE );
g_prop[IMG_ALPHA] = g_param_spec_pointer("alpha", NULL, "Image alpha", G_PARAM_READWRITE );
g_prop[IMG_PIXBUF] = g_param_spec_pointer("pixbuf", NULL, "Image data from gdk_pixbuf", G_PARAM_READWRITE );
g_prop[IMG_FIT] = g_param_spec_boolean("scale-to-fit", NULL, "Scale image to fit space", FALSE, G_PARAM_READWRITE );
g_object_class_install_properties (gobject_class, N_PROPERTIES, g_prop);
}

View File

@ -1,9 +0,0 @@
#ifndef CAIRO_IMAGE_H
#define CAIRO_IMAGE_H
#include "cairo-widget.h"
#define DIYA_TYPE_CAIRO_IMAGE (diya_cairo_image_get_type ())
G_DECLARE_FINAL_TYPE (DiyaCairoImage, diya_cairo_image, DIYA, CAIRO_IMAGE, DiyaCairoWidget)
#endif

View File

@ -1,367 +0,0 @@
#include <assert.h>
#include <pango/pangocairo.h>
#include <math.h>
#include "cairo-text.h"
#define FONT "Sans Bold 10"
enum
{
NO_PROP,
C_TEXT,
C_FONT_FAMILY,
C_FONT_SIZE,
C_FONT_STYLE,
C_FONT_WEIGHT,
C_COLOR,
C_WRAP,
N_PROPERTIES
};
static GParamSpec *g_prop[N_PROPERTIES] = {0};
typedef struct _DiyaCairoTextPrivate
{
DiyaCairoWidget parent_object;
gchar *text;
gchar *family;
int size;
guint style;
guint wrap;
guint weight;
diya_color_t color;
} DiyaCairoTextPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoText, diya_cairo_text, DIYA_TYPE_CAIRO_WIDGET)
static void diya_cairo_text_dispose(GObject *object)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
g_debug("diya_cairo_text_dispose: %s", diya_object_to_string(object));
if (priv->text)
{
g_free(priv->text);
}
if (priv->family)
{
g_free(priv->family);
}
G_OBJECT_CLASS(diya_cairo_text_parent_class)->dispose(object);
}
static void diya_cairo_text_init(DiyaCairoText *self)
{
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
priv->text = NULL;
priv->family = NULL;
priv->size = 10;
priv->style = DIYA_CAIRO_FONT_STYLE_NORMAL;
priv->weight = DIYA_CAIRO_FONT_WEIGHT_NORMAL;
priv->wrap = DIYA_CAIRO_TEXT_WRAP_WORD;
}
static void diya_cairo_text_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
switch (property_id)
{
case C_TEXT:
if (priv->text)
{
g_free(priv->text);
}
priv->text = g_strdup(g_value_get_pointer(value));
break;
case C_FONT_FAMILY:
if (priv->family)
{
g_free(priv->family);
}
priv->family = g_strdup(g_value_get_pointer(value));
break;
case C_FONT_SIZE:
priv->size = g_value_get_int(value);
break;
case C_FONT_STYLE:
priv->style = g_value_get_uint(value);
break;
case C_WRAP:
priv->wrap = g_value_get_uint(value);
break;
case C_FONT_WEIGHT:
priv->weight = g_value_get_uint(value);
break;
case C_COLOR:
memcpy(&priv->color,g_value_get_pointer(value), sizeof(priv->color));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void diya_cairo_text_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
switch (property_id)
{
case C_TEXT:
g_value_set_pointer(value, priv->text);
break;
case C_FONT_FAMILY:
g_value_set_pointer(value, priv->family);
break;
case C_FONT_SIZE:
g_value_set_int(value, priv->size);
break;
case C_FONT_STYLE:
g_value_set_uint(value, priv->style);
break;
case C_WRAP:
g_value_set_uint(value, priv->wrap);
break;
case C_FONT_WEIGHT:
g_value_set_uint(value, priv->weight);
break;
case C_COLOR:
g_value_set_pointer(value, &priv->color);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static PangoFontDescription *diya_cairo_text_get_pango_font_desc(DiyaCairoText *self)
{
PangoFontDescription *desc = pango_font_description_new();
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
if (priv->family)
{
pango_font_description_set_family(desc, priv->family);
}
pango_font_description_set_size(desc, priv->size * PANGO_SCALE);
pango_font_description_set_style(desc, priv->style);
pango_font_description_set_weight(desc, priv->weight);
return desc;
}
static gboolean diya_cairo_text_draw(gpointer object, cairo_t *context)
{
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
if(!diya_cairo_widget_is_damaged(object) || !diya_cairo_widget_is_visible(object))
{
return FALSE;
}
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_text_parent_class)->draw(object, context);
diya_rect_t view_port = diya_cairo_widget_get_view_port(object);
diya_rect_dump("diya_cairo_text_draw: ", &view_port);
if(diya_rect_is_empty(&view_port))
{
return FALSE;
}
cairo_save(context);
cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height);
cairo_clip(context);
diya_rect_t extent = diya_cairo_widget_get_extent(object);
g_warning("diya_cairo_widget_get_extent: width %d, %d", extent.width, extent.height);
diya_offset_t * padding, *margin;
diya_stroke_t *stroke;
diya_color_t *color;
guint halign, valign;
g_object_get(object,
"stroke", &stroke,
"halign", &halign,
"valign", &valign,
"margin", &margin,
"padding", &padding,
"color", &color,
NULL);
gint stroke_size = ceil(stroke->size);
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
PangoFontDescription *desc = diya_cairo_text_get_pango_font_desc(object);
cairo_set_source_rgba(context, color->r, color->g, color->b, color->a);
int display_w = extent.width - padding->left - padding->right - margin->left - margin->right - 2*stroke_size;
int display_h = extent.height - padding->top - padding->bottom - margin->top - margin->bottom - 2*stroke_size;
int off_x = padding->left + margin->left + stroke_size;
int off_y = padding->top + margin->top + stroke_size;
PangoLayout *layout = pango_cairo_create_layout(context);
// take into account my padding setting
pango_layout_set_text(layout, priv->text, -1);
pango_layout_set_font_description(layout, desc);
pango_layout_set_width(layout,display_w*PANGO_SCALE);
pango_layout_set_height(layout, display_h*PANGO_SCALE);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
pango_layout_set_wrap(layout, priv->wrap);
switch(halign)
{
case DIYA_CAIRO_WIDGET_ALIGN_START:
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
break;
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
break;
case DIYA_CAIRO_WIDGET_ALIGN_END:
pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
break;
}
PangoRectangle text_rect = {0};
pango_layout_get_extents(layout, NULL, &text_rect);
pango_extents_to_pixels(&text_rect, NULL);
// draw text
switch (valign)
{
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
off_y += (display_h - text_rect.height)/ 2;
break;
case DIYA_CAIRO_WIDGET_ALIGN_END:
off_y += display_h - text_rect.height;
break;
default:
break;
}
cairo_move_to(context, gpos.x + off_x, gpos.y + off_y);
pango_cairo_update_layout(context, layout);
pango_cairo_show_layout(context, layout);
cairo_restore(context);
pango_font_description_free(desc);
g_object_unref(layout);
return TRUE;
}
static void diya_cairo_text_content_size(gpointer object, int *width, int *height)
{
diya_offset_t* padding, *margin;
diya_stroke_t * stroke;
diya_rect_t * def_xtent;
guint hspace,vspace;
g_object_get(object,
"padding", &padding,
"margin", &margin,
"stroke", &stroke,
"hspace", &hspace,
"vspace", &vspace,
"default-extent", &def_xtent,
NULL);
gint stroke_size = ceil(stroke->size) * 2;
*width = padding->left + padding->right + margin->left + margin->right + stroke_size;
*height = padding->top + padding->bottom + margin->top + margin->bottom + stroke_size;
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
// diya_rect_t default_extent = DIYA_CAIRO_WIDGET_GET_CLASS(object)->default_extent(object);
int text_width = 0;
int text_height = 0;
if (priv->text)
{
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
cairo_t *context = cairo_create(surface);
PangoLayout *layout = pango_cairo_create_layout(context);
PangoFontDescription *desc = diya_cairo_text_get_pango_font_desc(object);
pango_layout_set_font_description(layout, desc);
pango_layout_set_text(layout, priv->text, -1);
pango_layout_set_width(layout, -1);
pango_layout_set_height(layout, -1);
pango_layout_set_single_paragraph_mode(layout, FALSE);
//pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_MIDDLE);
PangoRectangle rect = {0};
pango_layout_get_extents(layout, NULL, &rect);
pango_extents_to_pixels(&rect, NULL);
//rect.width += 4;
text_width = rect.width;
text_height = rect.height;
cairo_destroy(context);
cairo_surface_destroy(surface);
pango_font_description_free(desc);
g_object_unref(layout);
}
switch (hspace)
{
case DIYA_CAIRO_WIDGET_FILL_NONE:
*width = def_xtent->width;
break;
default:
*width += text_width;
break;
}
switch (vspace)
{
case DIYA_CAIRO_WIDGET_FILL_NONE:
*height = def_xtent->height;
break;
default:
*height += text_height;
break;
}
}
static void diya_cairo_text_class_init(DiyaCairoTextClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
class->set_text = diya_cairo_text_set_text;
class->get_text = diya_cairo_text_get_text;
wclass->draw = diya_cairo_text_draw;
wclass->content_size = diya_cairo_text_content_size;
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoText");
gobject_class->dispose = diya_cairo_text_dispose;
gobject_class->set_property = diya_cairo_text_set_property;
gobject_class->get_property = diya_cairo_text_get_property;
g_prop[C_TEXT] = g_param_spec_pointer("text", NULL, "text content", G_PARAM_READWRITE);
g_prop[C_FONT_FAMILY] = g_param_spec_pointer("font-family", NULL, "text font face", G_PARAM_READWRITE);
g_prop[C_COLOR] = g_param_spec_pointer("color", NULL, "text color", G_PARAM_READWRITE);
g_prop[C_FONT_STYLE] = g_param_spec_uint(
"font-style", NULL, "text font style",
DIYA_CAIRO_FONT_STYLE_NORMAL,
DIYA_CAIRO_FONT_STYLE_ITALIC,
DIYA_CAIRO_FONT_STYLE_NORMAL,
G_PARAM_READWRITE);
g_prop[C_FONT_WEIGHT] = g_param_spec_uint(
"font-weight", NULL, "text font weight",
PANGO_WEIGHT_THIN,
PANGO_WEIGHT_ULTRAHEAVY,
DIYA_CAIRO_FONT_WEIGHT_NORMAL,
G_PARAM_READWRITE);
g_prop[C_FONT_SIZE] = g_param_spec_int(
"font-size", NULL, "text font size",
0,
G_MAXINT,
10,
G_PARAM_READWRITE);
g_prop[C_WRAP] = g_param_spec_uint(
"wrap", NULL, "text wrap mode",
DIYA_CAIRO_TEXT_WRAP_WORD,
DIYA_CAIRO_TEXT_WRAP_WORD_CHAR,
DIYA_CAIRO_TEXT_WRAP_WORD,
G_PARAM_READWRITE);
g_object_class_install_properties(gobject_class, N_PROPERTIES, g_prop);
}
void diya_cairo_text_set_text(gpointer object, const gchar *text)
{
assert(DIYA_IS_CAIRO_TEXT(object));
g_object_set(object, "text", text, NULL);
}
const gchar *diya_cairo_text_get_text(gpointer object)
{
assert(DIYA_IS_CAIRO_TEXT(object));
DiyaCairoText *self = DIYA_CAIRO_TEXT(object);
DiyaCairoTextPrivate *priv = diya_cairo_text_get_instance_private(self);
return priv->text;
}

View File

@ -1,31 +0,0 @@
#ifndef CAIRO_TEXT_H
#define CAIRO_TEXT_H
#include <pango/pangocairo.h>
#include "cairo-widget.h"
#define DIYA_CAIRO_FONT_STYLE_NORMAL PANGO_STYLE_NORMAL
#define DIYA_CAIRO_FONT_STYLE_ITALIC PANGO_STYLE_ITALIC
#define DIYA_CAIRO_FONT_STYLE_OBLIQUE PANGO_STYLE_OBLIQUE
#define DIYA_CAIRO_FONT_WEIGHT_NORMAL PANGO_WEIGHT_NORMAL
#define DIYA_CAIRO_FONT_WEIGHT_BOLD PANGO_WEIGHT_BOLD
#define DIYA_CAIRO_TEXT_WRAP_WORD PANGO_WRAP_WORD
#define DIYA_CAIRO_TEXT_WRAP_CHAR PANGO_WRAP_CHAR
#define DIYA_CAIRO_TEXT_WRAP_WORD_CHAR PANGO_WRAP_WORD_CHAR
#define DIYA_TYPE_CAIRO_TEXT (diya_cairo_text_get_type ())
G_DECLARE_DERIVABLE_TYPE (DiyaCairoText, diya_cairo_text, DIYA, CAIRO_TEXT, DiyaCairoWidget)
struct _DiyaCairoTextClass
{
DiyaCairoWidgetClass parent_class;
void (*set_text)(gpointer object, const gchar* text);
const gchar* (*get_text)(gpointer object);
};
void diya_cairo_text_set_text(gpointer object, const gchar* text);
const gchar* diya_cairo_text_get_text(gpointer object);
#endif

View File

@ -1,804 +0,0 @@
#include <cairo/cairo.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <math.h>
#include "cairo-widget.h"
/*
#include <cairo.h>
int main()
{
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 150, 50);
cairo_t *cr = cairo_create(s);
cairo_set_source_rgb(cr, 1, 0, 0);
cairo_paint(cr);
cairo_rectangle(cr, 0, 0, 100, 100);
cairo_clip(cr);
cairo_move_to(cr, 50, 25);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_show_text(cr, "pretend that this string is > 100px wide");
cairo_destroy(cr);
cairo_surface_write_to_png(s, "out.png");
cairo_surface_destroy(s);
return 0;
}
*/
enum
{
CW_NO_PROP,
CW_EXTENT_DEF,
CW_EXTENT,
CW_PARENT,
CW_VISIBILITY,
CW_HALIGN,
CW_VALIGN,
CW_HSPACE,
CW_VSPACE,
CW_PADDING,
CW_PADDING_LEFT,
CW_PADDING_TOP,
CW_PADDING_BOTTOM,
CW_PADDING_RIGHT,
CW_MARGIN_LEFT,
CW_MARGIN_RIGHT,
CW_MARGIN_TOP,
CW_MARGIN_BOTTOM,
CW_MARGIN,
CW_FILL,
CW_STROKE,
CW_CORNER_RADIUS,
CW_N_PROPERTIES
};
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
typedef struct _DiyaCairoWidgetPrivate
{
DiyaObject parent_object;
diya_rect_t extent;
diya_rect_t default_extent;
DiyaCairoWidget * parent_widget;
gchar string[64];
guint16 visibility;
guint16 halign;
guint16 valign;
guint16 hspace;
guint16 vspace;
gdouble corner_radius;
diya_offset_t margin;
diya_offset_t padding;
diya_color_t fill;
diya_stroke_t stroke;
gboolean damaged;
} DiyaCairoWidgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoWidget, diya_cairo_widget, DIYA_TYPE_OBJECT);
static void diya_cairo_widget_dispose(GObject* object)
{
g_debug("diya_cairo_widget_dispose: %s", diya_object_to_string(object));
G_OBJECT_CLASS(diya_cairo_widget_parent_class)->dispose(object);
}
static void diya_cairo_widget_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
gpointer ptr;
switch (property_id)
{
case CW_PARENT:
priv->parent_widget = g_value_get_pointer(value);
assert(DIYA_IS_CAIRO_WIDGET(priv->parent_widget));
break;
case CW_EXTENT_DEF:
ptr = g_value_get_pointer(value);
assert(ptr);
priv->default_extent = *(diya_rect_t*)ptr;
break;
case CW_EXTENT:
break;
case CW_VISIBILITY:
priv->visibility = (guint16) g_value_get_uint(value);
break;
case CW_HALIGN:
priv->halign = (guint16)g_value_get_uint(value);
break;
case CW_VALIGN:
priv->valign = (guint16)g_value_get_uint(value);
break;
case CW_HSPACE:
priv->hspace = (guint16)g_value_get_uint(value);
break;
case CW_VSPACE:
priv->vspace = (guint16)g_value_get_uint(value);
break;
case CW_PADDING:
ptr = g_value_get_pointer(value);
assert(ptr);
priv->padding = *(diya_offset_t*)ptr;
break;
case CW_PADDING_LEFT:
priv->padding.left = g_value_get_int(value);
break;
case CW_PADDING_RIGHT:
priv->padding.right = g_value_get_int(value);
break;
case CW_PADDING_BOTTOM:
priv->padding.bottom = g_value_get_int(value);
break;
case CW_PADDING_TOP:
priv->padding.top = g_value_get_int(value);
break;
case CW_MARGIN:
ptr = g_value_get_pointer(value);
assert(ptr);
priv->margin = *(diya_offset_t*)ptr;
break;
case CW_MARGIN_LEFT:
priv->margin.left = g_value_get_int(value);
break;
case CW_MARGIN_RIGHT:
priv->margin.right = g_value_get_int(value);
break;
case CW_MARGIN_BOTTOM:
priv->margin.bottom = g_value_get_int(value);
break;
case CW_MARGIN_TOP:
priv->margin.top = g_value_get_int(value);
break;
case CW_FILL:
ptr = g_value_get_pointer(value);
assert(ptr);
priv->fill = *(diya_color_t*)ptr;
break;
case CW_STROKE:
ptr = g_value_get_pointer(value);
assert(ptr);
priv->stroke = *(diya_stroke_t*) ptr;
break;
case CW_CORNER_RADIUS:
priv->corner_radius = g_value_get_double(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_cairo_widget_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
switch (property_id)
{
case CW_PARENT:
g_value_set_pointer(value, priv->parent_widget);
break;
case CW_EXTENT_DEF:
g_value_set_pointer(value, &priv->default_extent);
break;
case CW_EXTENT:
g_value_set_pointer(value, &priv->extent);
break;
case CW_VISIBILITY:
g_value_set_uint(value, priv->visibility);
break;
case CW_HALIGN:
g_value_set_uint(value, priv->halign);
break;
case CW_VALIGN:
g_value_set_uint(value, priv->valign);
break;
case CW_HSPACE:
g_value_set_uint(value, priv->hspace);
break;
case CW_VSPACE:
g_value_set_uint(value, priv->vspace);
break;
case CW_PADDING:
g_value_set_pointer(value, &priv->padding);
break;
case CW_MARGIN:
g_value_set_pointer(value, &priv->margin);
break;
case CW_FILL:
g_value_set_pointer(value, &priv->fill);
break;
case CW_STROKE:
g_value_set_pointer(value, &priv->stroke);
break;
case CW_CORNER_RADIUS:
g_value_set_double(value, priv->corner_radius);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_cairo_widget_init(DiyaCairoWidget *self)
{
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
memset(&priv->extent,0,sizeof(priv->extent));
memset(&priv->extent,0,sizeof(priv->default_extent));
priv->parent_widget = NULL;
priv->string[0] = '\0';
priv->visibility = DIYA_CAIRO_WIDGET_VISIBLE_ON;
priv->hspace = DIYA_CAIRO_WIDGET_FILL_EXTEND;
priv->vspace = DIYA_CAIRO_WIDGET_FILL_EXTEND;
priv->halign = DIYA_CAIRO_WIDGET_ALIGN_MIDDLE;
priv->valign = DIYA_CAIRO_WIDGET_ALIGN_MIDDLE;
memset(&priv->padding,0,sizeof(priv->padding));
memset(&priv->margin,0,sizeof(priv->margin));
memset(&priv->fill, 0, sizeof(priv->fill));
priv->damaged = TRUE;
priv->corner_radius = 0;
}
static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetClass *class = DIYA_CAIRO_WIDGET_GET_CLASS(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
g_snprintf(priv->string,sizeof(priv->string),
"%s (%dx%d) at %d@%d (local %d@%d)",
class->name,
priv->extent.width, priv->extent.height,
gpos.x, gpos.y,
priv->extent.x, priv->extent.y
);
return priv->string;
}
diya_rect_t diya_cairo_widget_get_view_port(gpointer object)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
diya_offset_t * margin;
g_object_get(object,"margin", &margin, NULL);
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
diya_rect_t view = {
gpos.x + margin->left,
gpos.y + margin->top,
priv->extent.width - margin->left - margin->right,
priv->extent.height - margin->bottom - margin->top
};
if(priv->parent_widget)
{
diya_rect_t parent_view = diya_cairo_widget_get_view_port(priv->parent_widget);
diya_offset_t* padding;
g_object_get(priv->parent_widget,"padding", &padding, NULL);
parent_view.x += padding->left;
parent_view.y += padding->top;
parent_view.width -= (padding->left + padding->right);
parent_view.height -= (padding->top + padding->bottom);
if(!diya_rect_overlap(&view, &parent_view))
{
view.x = view.y = view.width = view.height = 0;
return view;
}
view.width = MIN(view.x + view.width, parent_view.x + parent_view.width) ;
view.height = MIN(view.y + view.height, parent_view.y + parent_view.height);
view.x = MAX(view.x, parent_view.x);
view.y = MAX(view.y, parent_view.y);
view.width -= view.x;
view.height -= view.y;
}
return view;
}
static gboolean diya_cairo_widget_draw(gpointer object, cairo_t* context)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
if(!priv->damaged)
{
return FALSE;
}
if(priv->visibility != DIYA_CAIRO_WIDGET_VISIBLE_ON)
{
return FALSE;
}
diya_rect_t view_port = diya_cairo_widget_get_view_port(object);
if(diya_rect_is_empty(&view_port))
{
return FALSE;
}
cairo_save(context);
cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height);
cairo_clip(context);
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
//cairo_move_to(context, (double)gpos.x +, (double)gpos.y);
guint stroke_size = ceil(priv->stroke.size);
guint half_stroke_size = ceil(priv->stroke.size / 2.0);
double width = (double)(priv->extent.width - priv->margin.left - priv->margin.right - stroke_size);
int height = (double)(priv->extent.height - priv->margin.bottom - priv->margin.top - stroke_size);
int x = (double)(gpos.x + priv->margin.left + half_stroke_size);
int y = (double)(gpos.y + priv->margin.top + half_stroke_size);
if(priv->corner_radius > 0)
{
double degrees = M_PI / 180.0;
cairo_new_sub_path(context);
cairo_arc (context, x + width - priv->corner_radius, y + priv->corner_radius, priv->corner_radius, -90 * degrees, 0);
cairo_arc (context, x + width - priv->corner_radius, y + height - priv->corner_radius, priv->corner_radius, 0, 90 * degrees);
cairo_arc (context, x + priv->corner_radius, y + height - priv->corner_radius, priv->corner_radius, 90 * degrees, 180 * degrees);
cairo_arc (context, x + priv->corner_radius, y + priv->corner_radius, priv->corner_radius, 180 * degrees, 270 * degrees);
cairo_close_path (context);
}
else
{
cairo_rectangle(context,x,y,width,height);
}
if(priv->fill.a > 0)
{
cairo_set_source_rgba(context, priv->fill.r, priv->fill.g, priv->fill.b, priv->fill.a);
cairo_fill_preserve(context);
}
if(priv->stroke.size > 0 && priv->stroke.color.a != 0)
{
cairo_set_source_rgba(context, priv->stroke.color.r, priv->stroke.color.g, priv->stroke.color.b, priv->stroke.color.a);
cairo_set_line_width(context,priv->stroke.size);
cairo_stroke(context);
}
cairo_restore(context);
priv->damaged = FALSE;
return TRUE;
}
static void diya_cairo_widget_content_size(gpointer object, gint* width, gint* height)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
gint stroke_size = ceil(priv->stroke.size) *2;
*width = priv->default_extent.width + priv->margin.left + priv->margin.right + stroke_size;
*height = priv->default_extent.height + priv->margin.top + priv->margin.bottom + stroke_size;
}
static void diya_cairo_widget_update(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
gint stroke_size = ceil(priv->stroke.size) *2;
if(priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN)
{
/**
* Item is hidden, set extent to empty
*/
if(!diya_rect_is_empty(&priv->extent))
{
priv->damaged = TRUE;
}
priv->extent.width = 0;
priv->extent.height = 0;
priv->extent.x = 0;
priv->extent.y = 0;
return;
}
diya_rect_t space = {
0,
0,
priv->default_extent.width,
priv->default_extent.height };
if(priv->parent_widget)
{
space = DIYA_CAIRO_WIDGET_GET_CLASS(priv->parent_widget)->alloc_space(priv->parent_widget, object);
}
gint width,height,cwidth = 0,cheight = 0;
DIYA_CAIRO_WIDGET_GET_CLASS(self)->content_size(object, &cwidth, &cheight);
switch(priv->hspace)
{
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
width = space.width;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
width = cwidth;
break;
default:
width = priv->default_extent.width + priv->margin.left + priv->margin.right + stroke_size;
break;
}
switch(priv->vspace)
{
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
height = space.height;
break;
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
height = cheight;
break;
default:
height = priv->default_extent.height + priv->margin.top + priv->margin.bottom + stroke_size;
break;
}
if(width != priv->extent.width || height != priv->extent.height)
{
priv->damaged = TRUE;
}
priv->extent.width = width;
priv->extent.height = height;
if(space.x != priv->extent.x || space.y != priv->extent.y)
{
priv->damaged = TRUE;
}
priv->extent.x = space.x;
priv->extent.y = space.y;
}
static diya_rect_t diya_cairo_widget_alloc_space(gpointer object, gpointer child)
{
(void) child;
assert(object);
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
diya_rect_t space = {0,0,priv->extent.width, priv->extent.height};
guint stroke_size = ceil(priv->stroke.size);
space.x += priv->padding.left + priv->margin.left + stroke_size;
space.y += priv->padding.top + priv->margin.top + stroke_size;
space.width -= (priv->padding.right + priv->padding.left + priv->margin.left+ priv->margin.right + stroke_size*2);
space.height -= (priv->padding.bottom + priv->padding.top + priv->margin.top + priv->margin.bottom + stroke_size*2);
return space;
}
static diya_rect_t diya_cairo_widget_get_default_extent(gpointer object)
{
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return priv->default_extent;
}
static diya_rect_t* diya_cairo_widget_get_extent_mut(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return &priv->extent;
}
static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoWidget");
gobject_class->dispose = diya_cairo_widget_dispose;
gobject_class->set_property = diya_cairo_widget_set_property;
gobject_class->get_property = diya_cairo_widget_get_property;
class->draw = diya_cairo_widget_draw;
class->update = diya_cairo_widget_update;
class->alloc_space = diya_cairo_widget_alloc_space;
class->content_size = diya_cairo_widget_content_size;
class->parent = diya_cairo_widget_get_parent;
class->position = diya_cairo_widget_get_position;
class->global_position = diya_cairo_widget_get_global_position;
class->extent = diya_cairo_widget_get_extent_mut;
class->view_port = diya_cairo_widget_get_view_port;
class->damaged = diya_cairo_widget_is_damaged;
class->default_extent = diya_cairo_widget_get_default_extent;
g_cw_prop[CW_EXTENT_DEF] = g_param_spec_pointer("default-extent", NULL, "Widget actual extent relative to its parent", G_PARAM_READWRITE); //
g_cw_prop[CW_EXTENT] = g_param_spec_pointer("extent", NULL, "Widget default extent", G_PARAM_READABLE);
g_cw_prop[CW_PARENT] = g_param_spec_pointer("parent", NULL, "Parent widget", G_PARAM_READWRITE); //
g_cw_prop[CW_FILL] = g_param_spec_pointer("fill", NULL, "Fill color", G_PARAM_READWRITE);
g_cw_prop[CW_STROKE] = g_param_spec_pointer("stroke", NULL, "Border size and color", G_PARAM_READWRITE);
g_cw_prop[CW_VISIBILITY] = g_param_spec_uint(
"visibility", NULL, "Widget visibility",
DIYA_CAIRO_WIDGET_VISIBLE_ON,
DIYA_CAIRO_WIDGET_VISIBLE_MAX,
DIYA_CAIRO_WIDGET_VISIBLE_ON,
G_PARAM_READWRITE);
g_cw_prop[CW_HALIGN] = g_param_spec_uint(
"halign", NULL, "Widget halign",
DIYA_CAIRO_WIDGET_ALIGN_START,
DIYA_CAIRO_WIDGET_ALIGN_MAX,
DIYA_CAIRO_WIDGET_ALIGN_MIDDLE,
G_PARAM_READWRITE);
g_cw_prop[CW_VALIGN] = g_param_spec_uint(
"valign", NULL, "Widget valign",
DIYA_CAIRO_WIDGET_ALIGN_START,
DIYA_CAIRO_WIDGET_ALIGN_MAX,
DIYA_CAIRO_WIDGET_ALIGN_MIDDLE,
G_PARAM_READWRITE);
g_cw_prop[CW_HSPACE] = g_param_spec_uint(
"hspace", NULL, "Widget hspace",
DIYA_CAIRO_WIDGET_FILL_NONE,
DIYA_CAIRO_WIDGET_FILL_MAX,
DIYA_CAIRO_WIDGET_FILL_EXTEND,
G_PARAM_READWRITE);
g_cw_prop[CW_VSPACE] = g_param_spec_uint(
"vspace", NULL, "Widget vspace",
DIYA_CAIRO_WIDGET_FILL_NONE,
DIYA_CAIRO_WIDGET_FILL_MAX,
DIYA_CAIRO_WIDGET_FILL_EXTEND,
G_PARAM_READWRITE);
g_cw_prop[CW_PADDING] = g_param_spec_pointer("padding", NULL, "Widget padding", G_PARAM_READWRITE);
g_cw_prop[CW_MARGIN] = g_param_spec_pointer("margin", NULL, "Widget margin", G_PARAM_READWRITE);
g_cw_prop[CW_PADDING_LEFT] = g_param_spec_int(
"padding-left", NULL, "Widget padding-left",
G_MININT,
G_MAXINT,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_PADDING_RIGHT] = g_param_spec_int(
"padding-right", NULL, "Widget padding-right",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_PADDING_TOP] = g_param_spec_int(
"padding-top", NULL, "Widget padding-top",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_PADDING_BOTTOM] = g_param_spec_int(
"padding-bottom", NULL, "Widget padding-bottom",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_MARGIN_LEFT] = g_param_spec_int(
"margin-left", NULL, "Widget margin-left",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_MARGIN_RIGHT] = g_param_spec_int(
"margin-right", NULL, "Widget margin-right",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_MARGIN_TOP] = g_param_spec_int(
"margin-top", NULL, "Widget margin-top",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_MARGIN_BOTTOM] = g_param_spec_int(
"margin-bottom", NULL, "Widget margin-bottom",
INT_MIN,
INT_MAX,
0,
G_PARAM_WRITABLE);
g_cw_prop[CW_CORNER_RADIUS] = g_param_spec_double(
"corner-radius", NULL, "Corner radius",
0,
DBL_MAX,
0,
G_PARAM_READWRITE);
base_class->to_string = diya_cairo_widget_to_string;
g_object_class_install_properties (gobject_class, CW_N_PROPERTIES, g_cw_prop);
}
diya_point_t diya_cairo_widget_get_position(gpointer object)
{
diya_point_t p = {0};
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
p.x = priv->extent.x;
p.y = priv->extent.y;
return p;
}
diya_point_t diya_cairo_widget_get_global_position(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
diya_point_t p = {priv->extent.x, priv->extent.y};
if(priv->parent_widget)
{
diya_point_t parent_pos = diya_cairo_widget_get_global_position(priv->parent_widget);
p.x += parent_pos.x;
p.y += parent_pos.y;
}
return p;
}
DiyaCairoWidget* diya_cairo_widget_get_parent(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return priv->parent_widget;
}
diya_rect_t diya_cairo_widget_get_extent(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return priv->extent;
}
gboolean diya_cairo_widget_is_visible(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_ON;
}
gboolean diya_cairo_widget_is_hidden(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN;
}
void diya_cairo_widget_set_size(gpointer object, guint width, guint height)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
priv->default_extent.width = width;
priv->default_extent.height = height;
}
void diya_cairo_widget_set_position(gpointer object, gint x, gint y)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
priv->default_extent.x = x;
priv->default_extent.y = y;
}
void diya_cairo_widget_fill(gpointer object, diya_color_t * color)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
priv->fill = *color;
}
void diya_cairo_widget_set_stroke_size(gpointer object, gdouble size)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
priv->stroke.size = size;
}
void diya_cairo_widget_set_stroke_color(gpointer object, diya_color_t * color)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
priv->stroke.color = *color;
}
gboolean diya_cairo_widget_is_damaged(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
return priv->damaged;
}
void diya_cairo_widget_damage(gpointer object)
{
assert(DIYA_IS_CAIRO_WIDGET(object));
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
priv->damaged = TRUE;
}
/*Container API*/
typedef struct _DiyaCairoContainerPrivate
{
DiyaCairoWidget parent_object;
GList* children;
} DiyaCairoContainerPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoContainer, diya_cairo_container, DIYA_TYPE_CAIRO_WIDGET)
static void diya_cairo_container_dispose(GObject* object)
{
DiyaCairoContainer * self = DIYA_CAIRO_CONTAINER(object);
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
g_debug("diya_cairo_container_dispose: %s", diya_object_to_string(object));
g_list_free_full(priv->children, g_object_unref);
G_OBJECT_CLASS(diya_cairo_container_parent_class)->dispose(object);
}
static void diya_cairo_container_init(DiyaCairoContainer *self)
{
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
priv->children = NULL;
}
static GList * diya_cairo_container_get_children(gpointer object)
{
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(DIYA_CAIRO_CONTAINER(object));
return priv->children;
}
static void diya_cairo_container_class_init(DiyaCairoContainerClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
//DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoContainer");
gobject_class->dispose = diya_cairo_container_dispose;
class->children = diya_cairo_container_get_children;
}
void diya_cairo_container_add(gpointer object, gpointer child)
{
assert(DIYA_IS_CAIRO_WIDGET(child));
assert(DIYA_IS_CAIRO_CONTAINER(object));
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(DIYA_CAIRO_CONTAINER(object));
g_object_set(child,"parent", object, NULL);
if(g_list_find (priv->children,child))
{
return;
}
priv->children = g_list_append(priv->children, child);
}
void diya_offset_normalize(diya_offset_t * offset)
{
gint tmp;
if(offset->left > offset->right)
{
tmp = offset->left;
offset->left = offset->right;
offset->right = tmp;
}
if(offset->top > offset->bottom)
{
tmp = offset->top;
offset->top = offset->bottom;
offset->bottom = tmp;
}
}

View File

@ -1,138 +0,0 @@
#ifndef CAIRO_WIDGET_H
#define CAIRO_WIDGET_H
#include <cairo/cairo.h>
#include "../base.h"
// basic type
typedef struct
{
gint x;
gint y;
gint width;
gint height;
} diya_rect_t;
typedef struct
{
gint x;
gint y;
}
diya_point_t;
typedef struct
{
gint left;
gint top;
gint right;
gint bottom;
}
diya_offset_t;
typedef struct
{
gdouble r;
gdouble g;
gdouble b;
gdouble a;
}
diya_color_t;
typedef struct
{
gdouble size;
diya_color_t color;
} diya_stroke_t;
#define BETWEEN(value,min,max) ((value >= min) && (value <= max))
#define diya_rect_is_empty(rect) (((rect)->width <= 0) || ((rect)->height <= 0))
#define diya_rect_to_offset(rect) ({(rect)->x,(rect)->y,(rect)->y+(rect)->height, (rect)->x + (rect)->width})
#define diya_rect_overlap(a,b) ( \
(BETWEEN((a)->x, (b)->x, (b)->x + (b)->width) || BETWEEN((b)->x, (a)->x, (a)->x + (a)->width)) && \
(BETWEEN((a)->y, (b)->y, (b)->y + (b)->height) || BETWEEN((b)->y, (a)->y, (a)->y + (a)->height)))
#define diya_rect_dump(prefix, rect) (g_warning(prefix ": [%d@%d, %dx%d]", (rect)->x,(rect)->y, (rect)->width, (rect)->height))
#define G_LIST_FOREACH(item, list) for(GList *__glist = list; __glist && (item = __glist->data, TRUE); __glist = __glist->next)
void diya_offset_normalize(diya_offset_t * offset);
#define DIYA_CAIRO_WIDGET_SET_NAME(c, n) (DIYA_CAIRO_WIDGET_CLASS(c)->name = n)
#define DIYA_TYPE_CAIRO_WIDGET (diya_cairo_widget_get_type ())
G_DECLARE_DERIVABLE_TYPE (DiyaCairoWidget, diya_cairo_widget, DIYA, CAIRO_WIDGET, DiyaObject)
enum
{
/*Align enum*/
DIYA_CAIRO_WIDGET_ALIGN_START,
DIYA_CAIRO_WIDGET_ALIGN_MIDDLE,
DIYA_CAIRO_WIDGET_ALIGN_END,
DIYA_CAIRO_WIDGET_ALIGN_DEFAULT,
DIYA_CAIRO_WIDGET_ALIGN_MAX, // not used
/*fill enum*/
DIYA_CAIRO_WIDGET_FILL_NONE, // using extent size
DIYA_CAIRO_WIDGET_FILL_CONTENT, // extent calculated by its content
DIYA_CAIRO_WIDGET_FILL_EXTEND, // extend to the entire free space of the parent
DIYA_CAIRO_WIDGET_FILL_MAX, //not used
/* Visibility enum*/
DIYA_CAIRO_WIDGET_VISIBLE_ON,
DIYA_CAIRO_WIDGET_VISIBLE_OFF, // not show but take space
DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN, // not show and does not take space
DIYA_CAIRO_WIDGET_VISIBLE_MAX, // not used
};
struct _DiyaCairoWidgetClass
{
DiyaObjectClass parent_class;
gboolean (*draw)(gpointer, cairo_t*);
void (*update)(gpointer);
void (*content_size)(gpointer, gint*, gint*);
diya_rect_t (*alloc_space)(gpointer, gpointer);
DiyaCairoWidget* (*parent)(gpointer);
diya_point_t (*position)(gpointer);
diya_point_t (*global_position)(gpointer);
diya_rect_t* (*extent)(gpointer);
diya_rect_t (*default_extent)(gpointer);
diya_rect_t (*view_port)(gpointer);
gboolean (*damaged)(gpointer);
const gchar* name;
};
diya_point_t diya_cairo_widget_get_position(gpointer object);
diya_point_t diya_cairo_widget_get_global_position(gpointer object);
DiyaCairoWidget* diya_cairo_widget_get_parent(gpointer object);
diya_rect_t diya_cairo_widget_get_extent(gpointer object);
gboolean diya_cairo_widget_is_visible(gpointer object);
gboolean diya_cairo_widget_is_hidden(gpointer object);
gboolean diya_cairo_widget_is_damaged(gpointer object);
diya_rect_t diya_cairo_widget_get_view_port(gpointer object);
void diya_cairo_widget_damage(gpointer object);
void diya_cairo_widget_set_size(gpointer object, guint width, guint height);
void diya_cairo_widget_set_position(gpointer object, gint x, gint y);
void diya_cairo_widget_fill(gpointer object, diya_color_t * color);
void diya_cairo_widget_set_stroke_size(gpointer object, gdouble size);
void diya_cairo_widget_set_stroke_color(gpointer object, diya_color_t * color);
#define DIYA_TYPE_CAIRO_CONTAINER (diya_cairo_container_get_type ())
G_DECLARE_DERIVABLE_TYPE (DiyaCairoContainer, diya_cairo_container, DIYA, CAIRO_CONTAINER, DiyaCairoWidget)
struct _DiyaCairoContainerClass
{
DiyaCairoWidgetClass parent_class;
GList* (*children)(gpointer);
};
void diya_cairo_container_add(gpointer object, gpointer child);
#endif

View File

@ -1,139 +0,0 @@
#include <assert.h>
#include "cairo-window.h"
#include "cairo-image.h"
/*
enum
{
NO_PROP,
BOX_MODE,
N_PROPERTIES
};
static GParamSpec *g_prop[N_PROPERTIES] = {0};
*/
struct _DiyaCairoWindow
{
DiyaCairoWidget parent_object;
DiyaCairoWidget * root;
gpointer background;
};
G_DEFINE_FINAL_TYPE(DiyaCairoWindow, diya_cairo_window, DIYA_TYPE_CAIRO_WIDGET)
static void diya_cairo_window_dispose(GObject * object)
{
g_debug("diya_cairo_window_dispose: %s", diya_object_to_string(object));
DiyaCairoWindow * window = DIYA_CAIRO_WINDOW(object);
if(window->root)
{
g_object_unref(window->root);
}
if(window->background)
{
g_object_unref(window->background);
}
G_OBJECT_CLASS(diya_cairo_window_parent_class)->dispose(object);
}
static void diya_cairo_window_init(DiyaCairoWindow * window)
{
window->root = NULL;
window->background = NULL;
}
static gboolean cairo_window_draw(gpointer object, cairo_t * cairo)
{
DiyaCairoWindow * window = DIYA_CAIRO_WINDOW(object);
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_window_parent_class)->draw(object, cairo);
if(window->background)
{
g_warning("drawing background");
assert(DIYA_IS_CAIRO_IMAGE(window->background));
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(window->background))->draw(window->background, cairo);
}
if(window->root)
{
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(window->root))->draw(window->root, cairo);
}
return TRUE;
}
static void cairo_window_update(gpointer object)
{
g_warning("Updating cairo window");
DiyaCairoWindow * self = DIYA_CAIRO_WINDOW(object);
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_window_parent_class)->update(object);
if(self->background)
{
g_warning("Updating cairo image");
assert(DIYA_IS_CAIRO_IMAGE(self->background));
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(self->background))->update(self->background);
}
if(self->root)
{
g_warning("Updating root");
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(self->root))->update(self->root);
}
}
static void diya_cairo_window_class_init(DiyaCairoWindowClass* class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
wclass->draw = cairo_window_draw;
wclass->update = cairo_window_update;
// wclass->alloc_space = cairo_window_allocate_space;
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoWindow");
gobject_class->dispose = diya_cairo_window_dispose;
}
void diya_cairo_window_set_root(gpointer object, gpointer root)
{
assert(DIYA_IS_CAIRO_WINDOW(object));
assert(DIYA_IS_CAIRO_WIDGET(root));
DiyaCairoWindow * window = DIYA_CAIRO_WINDOW(object);
window->root = DIYA_CAIRO_WIDGET(root);
diya_rect_t extent = diya_cairo_widget_get_extent(window);
g_object_set(root,
"parent", window,
"default-extent", &extent,
"vspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
"hspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
NULL
);
}
void diya_cairo_window_render(gpointer object, cairo_surface_t * surface)
{
assert(DIYA_IS_CAIRO_WINDOW(object));
DiyaCairoWidget * widget = DIYA_CAIRO_WIDGET(object);
cairo_t *cr = cairo_create(surface);
DIYA_CAIRO_WIDGET_GET_CLASS(widget)->draw(object,cr);
cairo_destroy(cr);
}
void diya_cairo_window_update(gpointer object)
{
assert(DIYA_IS_CAIRO_WINDOW(object));
g_warning("update and damaged widget");
DiyaCairoWidget * widget = DIYA_CAIRO_WIDGET(object);
assert(DIYA_IS_CAIRO_WIDGET(widget));
DIYA_CAIRO_WIDGET_GET_CLASS(widget)->update(object);
}
void diya_cairo_window_set_background_image(gpointer object, const char* path, gboolean scale_to_fit)
{
assert(DIYA_IS_CAIRO_WINDOW(object));
DiyaCairoWindow * self = DIYA_CAIRO_WINDOW(object);
self->background = g_object_new(DIYA_TYPE_CAIRO_IMAGE,
"file",path, "parent", object,
"scale-to-fit", scale_to_fit,
"hspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
"vspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
"halign", DIYA_CAIRO_WIDGET_ALIGN_START,
"valign", DIYA_CAIRO_WIDGET_ALIGN_START,
NULL);
}

View File

@ -1,14 +0,0 @@
#ifndef DIYA_CAIRO_WINDOW_H
#define DIYA_CAIRO_WINDOW_H
#include "cairo-widget.h"
#define DIYA_TYPE_CAIRO_WINDOW (diya_cairo_window_get_type ())
G_DECLARE_FINAL_TYPE (DiyaCairoWindow, diya_cairo_window, DIYA, CAIRO_WINDOW, DiyaCairoWidget)
void diya_cairo_window_set_root(gpointer object, gpointer root);
void diya_cairo_window_render(gpointer object, cairo_surface_t * surface);
void diya_cairo_window_update(gpointer object);
void diya_cairo_window_set_background_image(gpointer object, const char * file, gboolean scale_to_fit);
#endif