add basic cairo widget for session lock (WIP)
This commit is contained in:
parent
ac300c32cf
commit
f8deb67a5a
15
meson.build
15
meson.build
@ -2,7 +2,7 @@ project('diya-shell',
|
||||
['c'],
|
||||
version: '0.1.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.51.0',
|
||||
meson_version: '>=0.58.0',
|
||||
default_options: ['c_std=gnu11', 'warning_level=3'])
|
||||
|
||||
lib_so_version = '0'
|
||||
@ -22,7 +22,10 @@ wayland_client = dependency('wayland-client', version: '>=1.10.0')
|
||||
wayland_scanner = find_program('wayland-scanner')
|
||||
|
||||
# use system xdg-shell protocol when available
|
||||
#wayland_protocols = dependency('wayland-protocols', version: '>=1.16')
|
||||
wayland_protocols = dependency('wayland-protocols', version: '>=1.16')
|
||||
|
||||
wl_protocol_dir = wayland_protocols.get_variable('pkgdatadir')
|
||||
|
||||
|
||||
# pkg_config = import('pkgconfig')
|
||||
# gnome = import('gnome')
|
||||
@ -30,11 +33,12 @@ wayland_scanner = find_program('wayland-scanner')
|
||||
gtk_layer_shell = dependency('gtk4-layer-shell-0', version: '>=1.0.2')
|
||||
wayland_targets=[]
|
||||
|
||||
wayland_protos = [
|
||||
wl_protocols = [
|
||||
wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1',
|
||||
'protocols/wlr-foreign-toplevel-management-unstable-v1'
|
||||
]
|
||||
|
||||
foreach proto : wayland_protos
|
||||
foreach proto : wl_protocols
|
||||
xml = ''.join([proto,'.xml'])
|
||||
header = ''.join([proto.split('/').get(-1),'.h'])
|
||||
cfile = ''.join([proto.split('/').get(-1),'.c'])
|
||||
@ -51,6 +55,9 @@ src = [
|
||||
'src/wayland.c',
|
||||
'src/shell.c',
|
||||
'src/foreign.c',
|
||||
'src/session.c',
|
||||
'src/widgets/cairo-widget.c',
|
||||
'src/main.c',
|
||||
wayland_targets]
|
||||
|
||||
executable(
|
||||
|
@ -11,9 +11,12 @@ static void on_background_destroy(GtkWindow *window, GApplication *_data)
|
||||
|
||||
void diya_shell_init_background(DiyaShell * shell)
|
||||
{
|
||||
GtkWindow *gtk_window;
|
||||
g_object_get(shell, "background", >k_window, NULL);
|
||||
GtkApplication * app;
|
||||
g_object_get(shell, "application", &app, NULL);
|
||||
assert(app);
|
||||
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
|
||||
assert(gtk_window);
|
||||
g_object_set(shell, "background", gtk_window, NULL);
|
||||
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_background_destroy), NULL);
|
||||
// int layer shell for window
|
||||
gtk_layer_init_for_window (gtk_window);
|
||||
|
84
src/base.c
84
src/base.c
@ -1,10 +1,20 @@
|
||||
#include "base.h"
|
||||
#include "shell.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE(DiyaObject, diya_object, G_TYPE_OBJECT)
|
||||
|
||||
|
||||
static void diya_object_dispose(GObject* object)
|
||||
{
|
||||
g_debug("diya_object_dispose");
|
||||
G_OBJECT_CLASS (diya_object_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_object_class_init(DiyaObjectClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
class->to_string = NULL;
|
||||
gobject_class->dispose = diya_object_dispose;
|
||||
}
|
||||
|
||||
static void diya_object_init(DiyaObject *self)
|
||||
@ -12,10 +22,82 @@ static void diya_object_init(DiyaObject *self)
|
||||
(void) self;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
SO_NO_PROP,
|
||||
SO_SHELL,
|
||||
SO_N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *g_so_prop[SO_N_PROPERTIES] = {0};
|
||||
|
||||
typedef struct _DiyaShellObjectPrivate
|
||||
{
|
||||
DiyaObject * parent;
|
||||
DiyaShell * shell;
|
||||
} DiyaShellObjectPrivate;
|
||||
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShellObject, diya_shell_object, DIYA_TYPE_OBJECT);
|
||||
|
||||
static void diya_shell_object_dispose(GObject* object)
|
||||
{
|
||||
g_debug("diya_shell_object_dispose");
|
||||
G_OBJECT_CLASS(diya_shell_object_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_shell_object_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
DiyaShellObject * self = DIYA_SHELL_OBJECT(object);
|
||||
DiyaShellObjectPrivate* priv = diya_shell_object_get_instance_private(self);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case SO_SHELL:
|
||||
priv->shell = g_value_get_pointer(value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_shell_object_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
DiyaShellObject * self = DIYA_SHELL_OBJECT(object);
|
||||
DiyaShellObjectPrivate* priv = diya_shell_object_get_instance_private(self);
|
||||
switch (property_id)
|
||||
{
|
||||
case SO_SHELL:
|
||||
g_value_set_pointer(value, priv->shell);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void diya_shell_object_init(DiyaShellObject *self)
|
||||
{
|
||||
DiyaShellObjectPrivate* priv = diya_shell_object_get_instance_private(self);
|
||||
priv->shell = NULL;
|
||||
}
|
||||
|
||||
static void diya_shell_object_class_init(DiyaShellObjectClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
gobject_class->dispose = diya_shell_object_dispose;
|
||||
gobject_class->set_property = diya_shell_object_set_property;
|
||||
gobject_class->get_property = diya_shell_object_get_property;
|
||||
g_so_prop[SO_SHELL] = g_param_spec_pointer("shell", NULL, "Reference to global shell", G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); //
|
||||
|
||||
g_object_class_install_properties (gobject_class, SO_N_PROPERTIES, g_so_prop);
|
||||
}
|
||||
|
||||
|
||||
const gchar * diya_object_to_string(gpointer object)
|
||||
{
|
||||
g_return_val_if_fail(DIYA_IS_OBJECT(object), NULL);
|
||||
DiyaObject * self = DIYA_OBJECT(object);
|
||||
DiyaObjectClass *class = DIYA_OBJECT_GET_CLASS(self);
|
||||
return class->to_string ? class->to_string(self) : NULL;
|
||||
return class->to_string ? class->to_string(self) : "";
|
||||
}
|
28
src/base.h
28
src/base.h
@ -2,16 +2,26 @@
|
||||
#define DIYA_OBJECT_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
gint width;
|
||||
gint height;
|
||||
} diya_rect_t;
|
||||
|
||||
/**
|
||||
* Base class object
|
||||
*
|
||||
*/
|
||||
#define DIYA_TYPE_OBJECT (diya_object_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (DiyaObject, diya_object, DIYA, OBJECT, GObject)
|
||||
#define DIYA_TYPE_OBJECT (diya_object_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE(DiyaObject, diya_object, DIYA, OBJECT, GObject)
|
||||
|
||||
struct _DiyaObjectClass {
|
||||
struct _DiyaObjectClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
const gchar* (*to_string) (DiyaObject *self);
|
||||
const gchar *(*to_string)(DiyaObject *self);
|
||||
/**
|
||||
* @brief reserve for futur use to
|
||||
* define common API for descendants
|
||||
@ -19,6 +29,14 @@ struct _DiyaObjectClass {
|
||||
*/
|
||||
};
|
||||
|
||||
const gchar* diya_object_to_string(gpointer object);
|
||||
#define DIYA_TYPE_SHELL_OBJECT (diya_shell_object_get_type())
|
||||
G_DECLARE_DERIVABLE_TYPE(DiyaShellObject, diya_shell_object, DIYA, SHELL_OBJECT, DiyaObject)
|
||||
|
||||
struct _DiyaShellObjectClass
|
||||
{
|
||||
DiyaObjectClass parent_class;
|
||||
};
|
||||
|
||||
const gchar *diya_object_to_string(gpointer object);
|
||||
|
||||
#endif
|
@ -3,7 +3,7 @@
|
||||
#include "foreign.h"
|
||||
|
||||
/**
|
||||
* @DiyaWindow Object definition
|
||||
* @DiyaForeignWindow Object definition
|
||||
*
|
||||
*/
|
||||
enum
|
||||
@ -14,27 +14,25 @@ enum
|
||||
WIN_HANDLE,
|
||||
WIN_STATE,
|
||||
WIN_PARENT,
|
||||
SHELL,
|
||||
N_PROPERTIES
|
||||
};
|
||||
static GParamSpec *win_properties[N_PROPERTIES] = {0};
|
||||
struct _DiyaWindow
|
||||
struct _DiyaForeignWindow
|
||||
{
|
||||
DiyaObject parent;
|
||||
gchar * appid;
|
||||
gpointer handle;
|
||||
gchar* title;
|
||||
enum diya_win_state state;
|
||||
DiyaWindow * parent_win;
|
||||
DiyaShell * shell;
|
||||
DiyaForeignWindow * parent_win;
|
||||
gchar string[128];
|
||||
};
|
||||
G_DEFINE_TYPE(DiyaWindow, diya_window, DIYA_TYPE_OBJECT)
|
||||
G_DEFINE_FINAL_TYPE(DiyaForeignWindow, diya_foreign_window, DIYA_TYPE_SHELL_OBJECT)
|
||||
|
||||
static void diya_window_finalize(GObject* object)
|
||||
static void diya_foreign_window_dispose(GObject* object)
|
||||
{
|
||||
DiyaWindow * self = DIYA_WINDOW(object);
|
||||
g_debug("diya_window_finalize: %s", diya_object_to_string(self));
|
||||
DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
|
||||
g_debug("diya_foreign_window_dispose: %s", diya_object_to_string(self));
|
||||
if(self->appid)
|
||||
{
|
||||
g_free(self->appid);
|
||||
@ -43,11 +41,12 @@ static void diya_window_finalize(GObject* object)
|
||||
{
|
||||
g_free(self->title);
|
||||
}
|
||||
G_OBJECT_CLASS(diya_foreign_window_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_window_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
static void diya_foreign_window_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
DiyaWindow * self = DIYA_WINDOW(object);
|
||||
DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
|
||||
switch (property_id)
|
||||
{
|
||||
case WIN_APP_ID:
|
||||
@ -71,9 +70,6 @@ static void diya_window_set_property(GObject *object, guint property_id, const G
|
||||
case WIN_PARENT:
|
||||
self->parent_win = g_value_get_pointer(value);
|
||||
break;
|
||||
case SHELL:
|
||||
self->shell = g_value_get_pointer(value);
|
||||
break;
|
||||
case WIN_STATE:
|
||||
self->state = g_value_get_uint(value);
|
||||
break;
|
||||
@ -83,9 +79,9 @@ static void diya_window_set_property(GObject *object, guint property_id, const G
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_window_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
static void diya_foreign_window_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
DiyaWindow * self = DIYA_WINDOW(object);
|
||||
DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
|
||||
switch (property_id)
|
||||
{
|
||||
case WIN_APP_ID:
|
||||
@ -100,9 +96,6 @@ static void diya_window_get_property(GObject *object, guint property_id, GValue
|
||||
case WIN_PARENT:
|
||||
g_value_set_pointer(value, self->parent_win);
|
||||
break;
|
||||
case SHELL:
|
||||
g_value_set_pointer(value, self->shell);
|
||||
break;
|
||||
case WIN_STATE:
|
||||
g_value_set_uint(value, self->state);
|
||||
break;
|
||||
@ -112,7 +105,7 @@ static void diya_window_get_property(GObject *object, guint property_id, GValue
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_window_init(DiyaWindow *self)
|
||||
static void diya_foreign_window_init(DiyaForeignWindow *self)
|
||||
{
|
||||
self->appid = NULL;
|
||||
//self->handle = NULL;
|
||||
@ -120,32 +113,31 @@ static void diya_window_init(DiyaWindow *self)
|
||||
//self->shell = NULL;
|
||||
self->state = DIYA_WIN_STATE_NONE;
|
||||
self->title = NULL;
|
||||
memset(self->string, 0, sizeof(self->string));
|
||||
}
|
||||
|
||||
static const gchar* diya_window_to_string(DiyaObject* object)
|
||||
static const gchar* diya_foreign_window_to_string(DiyaObject* object)
|
||||
{
|
||||
DiyaWindow* self = DIYA_WINDOW(object);
|
||||
DiyaForeignWindow* self = DIYA_FOREIGN_WINDOW(object);
|
||||
g_snprintf(self->string, sizeof(self->string), "Window 0x%" PRIXPTR ": %s (%s)", (uintptr_t) self->handle, self->appid?self->appid:"", self->title?self->title:"");
|
||||
return self->string;
|
||||
}
|
||||
|
||||
static void diya_window_class_init(DiyaWindowClass *class)
|
||||
static void diya_foreign_window_class_init(DiyaForeignWindowClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||
|
||||
gobject_class->finalize = diya_window_finalize;
|
||||
gobject_class->set_property = diya_window_set_property;
|
||||
gobject_class->get_property = diya_window_get_property;
|
||||
base_class->to_string = diya_window_to_string;
|
||||
gobject_class->dispose = diya_foreign_window_dispose;
|
||||
gobject_class->set_property = diya_foreign_window_set_property;
|
||||
gobject_class->get_property = diya_foreign_window_get_property;
|
||||
base_class->to_string = diya_foreign_window_to_string;
|
||||
|
||||
win_properties[WIN_APP_ID] = g_param_spec_string("appid", NULL, "Window application id", "", G_PARAM_READWRITE);
|
||||
win_properties[WIN_TITLE] = g_param_spec_string("title", NULL, "Window title","", G_PARAM_READWRITE );
|
||||
win_properties[WIN_HANDLE] = g_param_spec_pointer("handle", NULL, "Foreign window handle", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY );
|
||||
win_properties[WIN_STATE] = g_param_spec_uint("state", NULL, "Window state",0, UINT_MAX , DIYA_WIN_STATE_NONE,G_PARAM_READWRITE);
|
||||
win_properties[WIN_PARENT] = g_param_spec_pointer("parent", NULL, "Window parent", G_PARAM_READWRITE);
|
||||
win_properties[SHELL] = g_param_spec_pointer("shell", NULL, "Reference to shell", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY );
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPERTIES, win_properties);
|
||||
}
|
||||
|
||||
@ -165,7 +157,7 @@ static void toplevel_handle_title(void *data,
|
||||
{
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *win = diya_shell_get_window(shell, handle);
|
||||
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
|
||||
assert(win);
|
||||
g_object_set(win, "title", title, NULL);
|
||||
g_debug("New title for: %s", diya_object_to_string(win));
|
||||
@ -176,7 +168,7 @@ static void toplevel_handle_app_id(void *data,
|
||||
{
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *win = diya_shell_get_window(shell, handle);
|
||||
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
|
||||
assert(win);
|
||||
g_object_set(win, "appid", app_id, NULL);
|
||||
g_debug("New appid for: %s", diya_object_to_string(win));
|
||||
@ -196,7 +188,7 @@ static void toplevel_handle_state(void *data,
|
||||
uint32_t *entry;
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *win = diya_shell_get_window(shell, handle);
|
||||
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
|
||||
assert(win);
|
||||
enum diya_win_state wstate = DIYA_WIN_STATE_NONE;
|
||||
wl_array_for_each(entry, state) switch (*entry)
|
||||
@ -221,7 +213,7 @@ static void toplevel_handle_done(void *data,
|
||||
{
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *win = diya_shell_get_window(shell, handle);
|
||||
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
|
||||
assert(win);
|
||||
g_signal_emit_by_name(shell, "foreign-window-changed", (void *)win);
|
||||
}
|
||||
@ -230,7 +222,7 @@ static void toplevel_handle_closed(void *data,
|
||||
{
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *win = diya_shell_get_window(shell, handle);
|
||||
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
|
||||
assert(win);
|
||||
g_signal_emit_by_name(shell, "foreign-window-removed", (void *)win);
|
||||
diya_shell_remove_window(shell, win);
|
||||
@ -247,8 +239,8 @@ static void toplevel_handle_parent(void *data,
|
||||
assert(handle != parent);
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *child_win = diya_shell_get_window(shell, handle);
|
||||
DiyaWindow *parent_win = diya_shell_get_window(shell, parent);
|
||||
DiyaForeignWindow *child_win = diya_shell_get_window(shell, handle);
|
||||
DiyaForeignWindow *parent_win = diya_shell_get_window(shell, parent);
|
||||
assert(child_win);
|
||||
assert(parent_win);
|
||||
assert(child_win != parent_win);
|
||||
@ -265,14 +257,24 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener g_toplevel_impl = {
|
||||
.state = toplevel_handle_state,
|
||||
.done = toplevel_handle_done,
|
||||
.closed = toplevel_handle_closed,
|
||||
.parent = toplevel_handle_parent};
|
||||
.parent = toplevel_handle_parent
|
||||
};
|
||||
|
||||
static DiyaForeignWindow * diya_shell_foreign_window_new(DiyaShell* shell, gpointer handle)
|
||||
{
|
||||
DiyaForeignWindow *win = DIYA_FOREIGN_WINDOW(g_object_new(DIYA_TYPE_FOREIGN_WINDOW,"handle", handle, "shell", shell, NULL));
|
||||
//g_object_set(win, "shell", shell, NULL);
|
||||
diya_shell_add_window(shell, win);
|
||||
g_debug("Add new window 0x%" PRIXPTR, (uintptr_t)handle);
|
||||
return win;
|
||||
}
|
||||
|
||||
static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager, struct zwlr_foreign_toplevel_handle_v1 *tl)
|
||||
{
|
||||
(void) toplevel_manager;
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
assert(shell);
|
||||
DiyaWindow *win = diya_shell_get_window(shell, tl);
|
||||
DiyaForeignWindow *win = diya_shell_get_window(shell, tl);
|
||||
|
||||
if (win)
|
||||
{
|
||||
@ -280,14 +282,15 @@ static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_top
|
||||
return;
|
||||
}
|
||||
// TODO: different between windows
|
||||
win = diya_window_new(shell, tl);
|
||||
win = diya_shell_foreign_window_new(shell, tl);
|
||||
zwlr_foreign_toplevel_handle_v1_add_listener(tl, &g_toplevel_impl, data);
|
||||
}
|
||||
|
||||
static void toplevel_manager_handle_finished(void *data,
|
||||
struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager)
|
||||
{
|
||||
(void) data;
|
||||
DiyaShell *shell = (DiyaShell *)data;
|
||||
diya_shell_remove_all_windows(shell);
|
||||
// remove table entry
|
||||
zwlr_foreign_toplevel_manager_v1_destroy(toplevel_manager);
|
||||
}
|
||||
@ -303,11 +306,3 @@ void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t
|
||||
g_toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3);
|
||||
zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)shell);
|
||||
}
|
||||
|
||||
DiyaWindow * diya_window_new(DiyaShell* shell, gpointer handle)
|
||||
{
|
||||
DiyaWindow *win = DIYA_WINDOW(g_object_new(DIYA_TYPE_WINDOW,"shell", shell, "handle", handle, NULL));
|
||||
diya_shell_add_window(shell, win);
|
||||
g_debug("Add new window 0x%" PRIXPTR, (uintptr_t)handle);
|
||||
return win;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "launcher.h"
|
||||
#include "foreign.h"
|
||||
#include "session.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define NAMESPACE "launcher"
|
||||
@ -11,7 +12,7 @@ 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, DiyaWindow * win, gpointer data)
|
||||
static void on_foreign_window_change(GtkApplication* app, DiyaForeignWindow * win, gpointer data)
|
||||
{
|
||||
(void) app;
|
||||
(void) data;
|
||||
@ -19,7 +20,7 @@ static void on_foreign_window_change(GtkApplication* app, DiyaWindow * win, gpoi
|
||||
g_warning("WINDOW CHANGEEEEEEEEE %s", diya_object_to_string(DIYA_OBJECT(win)));
|
||||
}
|
||||
|
||||
static void on_foreign_window_removed(GtkApplication* app, DiyaWindow * win, gpointer data)
|
||||
static void on_foreign_window_removed(GtkApplication* app, DiyaForeignWindow * win, gpointer data)
|
||||
{
|
||||
(void) app;
|
||||
(void) data;
|
||||
@ -27,12 +28,21 @@ static void on_foreign_window_removed(GtkApplication* app, DiyaWindow * win, gpo
|
||||
g_warning("WINDOW removed %s", diya_object_to_string(DIYA_OBJECT(win)));
|
||||
}
|
||||
|
||||
void diya_launcher_init(DiyaShell * shell)
|
||||
static void session_lock(GtkWidget *widget,gpointer data)
|
||||
{
|
||||
g_warning("Enter session lock");
|
||||
diya_shell_lock(data);
|
||||
}
|
||||
void diya_shell_launcher_init(DiyaShell * shell)
|
||||
{
|
||||
assert(shell);
|
||||
GtkWindow *gtk_window;
|
||||
g_object_get(shell, "launchpad", >k_window, NULL);
|
||||
GtkApplication * app;
|
||||
g_object_get(shell, "application", &app, NULL);
|
||||
assert(app);
|
||||
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
|
||||
assert(gtk_window);
|
||||
g_object_set(shell, "launchpad", gtk_window, NULL);
|
||||
|
||||
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_launcher_destroy), NULL);
|
||||
// int layer shell for window
|
||||
gtk_layer_init_for_window (gtk_window);
|
||||
@ -54,10 +64,14 @@ void diya_launcher_init(DiyaShell * shell)
|
||||
gtk_widget_set_name(GTK_WIDGET(gtk_window),NAMESPACE);
|
||||
gtk_window_set_default_size(gtk_window, 48, 48);
|
||||
|
||||
GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
|
||||
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
|
||||
gtk_window_set_child (GTK_WINDOW (gtk_window), box);
|
||||
|
||||
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
|
||||
GtkWidget * button = gtk_button_new_with_label ("lock");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (session_lock), shell);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
//g_signal_connect (gtk_window, "orientation-changed", G_CALLBACK (on_orientation_changed), /*data*/NULL);
|
||||
gtk_window_present (GTK_WINDOW (gtk_window));
|
||||
|
||||
|
@ -4,6 +4,6 @@
|
||||
#include "shell.h"
|
||||
|
||||
|
||||
void diya_launcher_init(DiyaShell * shell);
|
||||
void diya_shell_launcher_init(DiyaShell * shell);
|
||||
|
||||
#endif
|
72
src/main.c
Normal file
72
src/main.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include <glib-unix.h>
|
||||
#include "shell.h"
|
||||
#include "background.h"
|
||||
#include "launcher.h"
|
||||
#include "wayland.h"
|
||||
#include "foreign.h"
|
||||
|
||||
static gchar **g_shell_argv;
|
||||
|
||||
static void activate(GtkApplication *app, void *data)
|
||||
{
|
||||
(void)app;
|
||||
(void)data;
|
||||
}
|
||||
|
||||
static gboolean restart(gpointer d)
|
||||
{
|
||||
(void)d;
|
||||
gint i, fdlimit;
|
||||
|
||||
fdlimit = (int)sysconf(_SC_OPEN_MAX);
|
||||
g_debug("reload: closing fd's %d to %d", STDERR_FILENO + 1, fdlimit);
|
||||
for (i = STDERR_FILENO + 1; i < fdlimit; i++)
|
||||
{
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
g_debug("reload: exec: %s", g_shell_argv[0]);
|
||||
execvp(g_shell_argv[0], g_shell_argv);
|
||||
exit(1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void startup(GtkApplication *app, void *data)
|
||||
{
|
||||
DiyaShell *shell = data;
|
||||
|
||||
diya_shell_launcher_init(shell);
|
||||
diya_shell_wayland_init(shell);
|
||||
diya_shell_init_background(shell);
|
||||
|
||||
GtkCssProvider *provider = gtk_css_provider_new();
|
||||
const char *css = "#launcher {background-color: red;} #background {background-image:url(\"file:///etc/xdg/labwc/wpp.jpg\");background-size: cover;}";
|
||||
gtk_css_provider_load_from_string(provider, css);
|
||||
gtk_style_context_add_provider_for_display(
|
||||
gdk_display_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
// g_signal_connect (win, "destroy", G_CALLBACK (before_destroy), provider);
|
||||
g_object_unref(provider);
|
||||
// CSS support
|
||||
// set color for it
|
||||
// g_timeout_add (100,(GSourceFunc )shell_timer,NULL);
|
||||
g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL);
|
||||
g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
g_shell_argv = g_malloc0(sizeof(gchar *) * (argc + 1));
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
g_shell_argv[i] = argv[i];
|
||||
}
|
||||
GtkApplication *app = gtk_application_new("dev.iohub.diya.shell", G_APPLICATION_DEFAULT_FLAGS);
|
||||
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(app, "shutdown", G_CALLBACK(shutdown), (void*)shell);
|
||||
int status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||
g_warning("Exiting SHELL");
|
||||
g_object_unref(app);
|
||||
g_object_unref(shell);
|
||||
return status;
|
||||
}
|
332
src/session.c
Normal file
332
src/session.c
Normal file
@ -0,0 +1,332 @@
|
||||
#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 "session.h"
|
||||
#include "wayland.h"
|
||||
|
||||
#define DEF_SURF_W 600
|
||||
#define DEF_SURF_H 400
|
||||
|
||||
struct _DiyaLockSession
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
G_OBJECT_CLASS(diya_lock_session_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
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);
|
||||
assert(shell);
|
||||
g_object_get(shell, "application", &app, "wayland", &wayland, 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);
|
||||
}
|
||||
static void handle_session_lock_finished(void *data, struct ext_session_lock_v1 *lock)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
long r = ts.tv_nsec;
|
||||
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(size_t 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);
|
||||
int 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;
|
||||
}
|
||||
cairo_t *cr = cairo_create(self->cairo_surface);
|
||||
// Start of example
|
||||
double xc = 128.0;
|
||||
double yc = 128.0;
|
||||
double radius = 100.0;
|
||||
double angle1 = (double)(self->last_frame_time % 180) * (M_PI / 180.0); /* angles are specified */
|
||||
double angle2 = 180.0 * (M_PI / 180.0); /* in radians */
|
||||
|
||||
cairo_set_line_width(cr, 10.0);
|
||||
cairo_arc(cr, xc, yc, radius, angle1, angle2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
/* draw helping lines */
|
||||
cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.6);
|
||||
cairo_set_line_width(cr, 6.0);
|
||||
|
||||
cairo_arc(cr, xc, yc, 10.0, 0, 2 * M_PI);
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_arc(cr, xc, yc, radius, angle1, angle1);
|
||||
cairo_line_to(cr, xc, yc);
|
||||
cairo_arc(cr, xc, yc, radius, angle2, angle2);
|
||||
cairo_line_to(cr, xc, yc);
|
||||
cairo_stroke(cr);
|
||||
// End of example
|
||||
cairo_destroy(cr);
|
||||
|
||||
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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock->last_frame_time = time;
|
||||
lock_session_draw_frame(lock);
|
||||
}
|
||||
|
||||
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->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;
|
||||
}
|
9
src/session.h
Normal file
9
src/session.h
Normal file
@ -0,0 +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);
|
||||
#endif
|
119
src/shell.c
119
src/shell.c
@ -1,9 +1,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "background.h"
|
||||
#include "launcher.h"
|
||||
#include "wayland.h"
|
||||
#include "foreign.h"
|
||||
#include "session.h"
|
||||
|
||||
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
|
||||
|
||||
@ -14,6 +12,7 @@ enum
|
||||
SHELL_BACKGROUND_WIDGET,
|
||||
SHELL_LAUNCHPAD_WIDGET,
|
||||
SHELL_WINDOWS,
|
||||
SHELL_WAYLAND,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
@ -26,16 +25,25 @@ struct _DiyaShell
|
||||
GtkWindow* background;
|
||||
GtkWindow* launcher;
|
||||
GHashTable* windows;
|
||||
DiyaLockSession* lock;
|
||||
DiyaWayland * wayland;
|
||||
};
|
||||
G_DEFINE_TYPE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT)
|
||||
G_DEFINE_FINAL_TYPE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT)
|
||||
|
||||
static void diya_shell_finalize(GObject* object)
|
||||
static void diya_shell_dispose(GObject* object)
|
||||
{
|
||||
DiyaShell * self = DIYA_SHELL(object);
|
||||
g_hash_table_destroy(self->windows);
|
||||
// TODO: free element in each entry of the table
|
||||
// g_object_unref(self->app);
|
||||
g_warning("diya_shell_finalize");
|
||||
g_debug("diya_shell_dispose");
|
||||
if(self->wayland)
|
||||
{
|
||||
g_object_unref(self->wayland);
|
||||
}
|
||||
if(self->lock)
|
||||
{
|
||||
g_object_unref(self->lock);
|
||||
}
|
||||
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
@ -46,11 +54,16 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV
|
||||
case SHELL_APP:
|
||||
self->app = g_value_get_pointer(value);
|
||||
assert(self->app);
|
||||
self->background = GTK_WINDOW (gtk_application_window_new (self->app));
|
||||
self->launcher = GTK_WINDOW (gtk_application_window_new (self->app));
|
||||
break;
|
||||
case SHELL_BACKGROUND_WIDGET:
|
||||
self->background = g_value_get_pointer(value);
|
||||
break;
|
||||
case SHELL_LAUNCHPAD_WIDGET:
|
||||
self->launcher = g_value_get_pointer(value);
|
||||
break;
|
||||
case SHELL_WAYLAND:
|
||||
self->wayland = g_value_get_pointer(value);
|
||||
break;
|
||||
case SHELL_WINDOWS:
|
||||
//self->windows = g_value_get_pointer(value);
|
||||
break;
|
||||
@ -75,6 +88,9 @@ 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_WAYLAND:
|
||||
g_value_set_pointer(value, self->wayland);
|
||||
break;
|
||||
case SHELL_WINDOWS:
|
||||
g_value_set_pointer(value, self->windows);
|
||||
break;
|
||||
@ -96,14 +112,16 @@ static void diya_shell_class_init(DiyaShellClass *class)
|
||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||
|
||||
base_class->to_string = diya_shell_to_string;
|
||||
gobject_class->finalize = diya_shell_finalize;
|
||||
gobject_class->dispose = diya_shell_dispose;
|
||||
gobject_class->set_property = diya_shell_set_property;
|
||||
gobject_class->get_property = diya_shell_get_property;
|
||||
|
||||
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_READABLE );
|
||||
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READABLE );
|
||||
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_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 );
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
|
||||
|
||||
g_signal_new("foreign-window-changed",
|
||||
@ -137,14 +155,15 @@ static void diya_shell_init(DiyaShell *self)
|
||||
//self->app = NULL;
|
||||
self->background = NULL;
|
||||
self->launcher = NULL;
|
||||
self->wayland = NULL;
|
||||
self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
||||
}
|
||||
|
||||
gpointer diya_shell_get_window(DiyaShell * shell, gpointer handle)
|
||||
DiyaForeignWindow* diya_shell_get_window(DiyaShell * shell, gpointer handle)
|
||||
{
|
||||
return g_hash_table_lookup(shell->windows, handle);
|
||||
}
|
||||
gboolean diya_shell_add_window(DiyaShell * shell, DiyaWindow * win)
|
||||
gboolean diya_shell_add_window(DiyaShell * shell, DiyaForeignWindow * win)
|
||||
{
|
||||
gpointer handle;
|
||||
g_object_get(win, "handle", &handle, NULL);
|
||||
@ -152,7 +171,7 @@ gboolean diya_shell_add_window(DiyaShell * shell, DiyaWindow * win)
|
||||
return g_hash_table_insert(shell->windows,handle, win);
|
||||
}
|
||||
|
||||
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaWindow * win)
|
||||
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaForeignWindow * win)
|
||||
{
|
||||
gpointer handle;
|
||||
g_object_get(win, "handle", &handle, NULL);
|
||||
@ -160,10 +179,39 @@ gboolean diya_shell_remove_window(DiyaShell * shell, DiyaWindow * win)
|
||||
return g_hash_table_remove(shell->windows,handle);
|
||||
}
|
||||
|
||||
void diya_shell_remove_all_windows(DiyaShell * shell)
|
||||
{
|
||||
g_hash_table_destroy(shell->windows);
|
||||
shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
||||
}
|
||||
|
||||
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;
|
||||
g_object_get(shell,"wayland", &wayland, NULL);
|
||||
assert(DIYA_IS_WAYLAND(wayland));
|
||||
return wayland;
|
||||
}
|
||||
/*
|
||||
static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data)
|
||||
{
|
||||
@ -192,39 +240,10 @@ static void on_orientation_changed (GtkWindow *window, WindowOrientation orienta
|
||||
//gtk_window_resize (window, 1, 1); // force the window to shrink to the smallest size it can
|
||||
}
|
||||
*/
|
||||
static void shutdown(GtkApplication *app, void *data)
|
||||
{
|
||||
(void) app;
|
||||
g_warning("Application shutdown");
|
||||
DiyaShell * shell = data;
|
||||
assert(shell);
|
||||
g_object_unref(shell);
|
||||
}
|
||||
static void activate(GtkApplication *app, void *data)
|
||||
{
|
||||
(void)data;
|
||||
DiyaShell * shell = diya_shell_new(app);
|
||||
assert(shell);
|
||||
assert(DIYA_IS_SHELL(shell));
|
||||
g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), (void*)shell);
|
||||
|
||||
diya_launcher_init(shell);
|
||||
diya_shell_wayland_init(shell);
|
||||
diya_shell_init_background(shell);
|
||||
// CSS support
|
||||
// set color for it
|
||||
GtkCssProvider *provider = gtk_css_provider_new();
|
||||
const char *css = "#launcher {background-color: red;} #background {background-image:url(\"file:///etc/xdg/labwc/wpp.jpg\");background-size: cover;}";
|
||||
gtk_css_provider_load_from_string(provider, css);
|
||||
gtk_style_context_add_provider_for_display(
|
||||
gdk_display_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
GtkApplication* app = gtk_application_new("dev.iohub.diya-shell", G_APPLICATION_DEFAULT_FLAGS);
|
||||
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
||||
int status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||
g_object_unref(app);
|
||||
return status;
|
||||
/*
|
||||
static void before_destroy (GtkWidget *win, GtkCssProvider *provider) {
|
||||
GdkDisplay *display = gdk_display_get_default ();
|
||||
gtk_style_context_remove_provider_for_display (display, GTK_STYLE_PROVIDER (provider));
|
||||
}
|
||||
*/
|
||||
|
25
src/shell.h
25
src/shell.h
@ -15,13 +15,24 @@ enum diya_win_state
|
||||
#define DIYA_TYPE_SHELL (diya_shell_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaShell, diya_shell, DIYA, SHELL, DiyaObject)
|
||||
|
||||
#define DIYA_TYPE_WINDOW (diya_window_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaWindow, diya_window, DIYA, WINDOW, DiyaObject)
|
||||
#define DIYA_TYPE_WAYLAND (diya_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject)
|
||||
|
||||
#define DIYA_TYPE_FOREIGN_WINDOW (diya_foreign_window_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject)
|
||||
|
||||
#define DIYA_TYPE_LOCK_SESSION (diya_lock_session_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaLockSession, diya_lock_session, DIYA, LOCK_SESSION, DiyaShellObject)
|
||||
|
||||
|
||||
DiyaForeignWindow* diya_shell_get_window(DiyaShell * shell, gpointer handle);
|
||||
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);
|
||||
|
||||
gpointer diya_shell_get_window(DiyaShell * shell, gpointer handle);
|
||||
gboolean diya_shell_add_window(DiyaShell * shell, DiyaWindow * win);
|
||||
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaWindow * win);
|
||||
DiyaShell * diya_shell_new(GtkApplication * app);
|
||||
|
||||
DiyaWindow * diya_window_new(DiyaShell* shell, gpointer handle);
|
||||
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
|
||||
#endif
|
@ -1,7 +1,44 @@
|
||||
#include <wayland-client-protocol.h>
|
||||
#include <gdk/wayland/gdkwayland.h>
|
||||
#include <assert.h>
|
||||
#include "wayland.h"
|
||||
#include "foreign.h"
|
||||
#include "session.h"
|
||||
|
||||
|
||||
struct _DiyaWayland
|
||||
{
|
||||
DiyaObject parent;
|
||||
struct wl_compositor * compositor;
|
||||
struct wl_shm * shm;
|
||||
};
|
||||
G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT)
|
||||
|
||||
static void diya_wayland_dispose(GObject* object)
|
||||
{
|
||||
(void) object;
|
||||
//DiyaWayland * self = DIYA_WAYLAND(object);
|
||||
g_debug("diya_wayland_dispose");
|
||||
G_OBJECT_CLASS(diya_wayland_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_wayland_init(DiyaWayland * self)
|
||||
{
|
||||
self->compositor = NULL;
|
||||
self->shm = NULL;
|
||||
}
|
||||
|
||||
static void diya_wayland_class_init(DiyaWaylandClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
//DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||
|
||||
gobject_class->dispose = diya_wayland_dispose;
|
||||
//gobject_class->set_property = diya_lock_session_set_property;
|
||||
//gobject_class->get_property = diya_lock_session_get_property;
|
||||
//base_class->to_string = diya_lock_session_to_string;
|
||||
}
|
||||
|
||||
|
||||
static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const gchar *interface, uint32_t version)
|
||||
{
|
||||
@ -14,14 +51,28 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
|
||||
if (!g_strcmp0(interface,zwlr_foreign_toplevel_manager_v1_interface.name))
|
||||
foreign_toplevel_register(registry,name);
|
||||
*/
|
||||
//g_warning("register global: %s VS %s", interface, zwlr_foreign_toplevel_manager_v1_interface.name);
|
||||
(void) version;
|
||||
DiyaShell * shell = data;
|
||||
DiyaWayland * wayland;
|
||||
g_object_get(shell, "wayland", &wayland, NULL);
|
||||
assert(DIYA_IS_WAYLAND(wayland));
|
||||
g_warning("GLOBAL: %s", interface);
|
||||
if (!g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name))
|
||||
{
|
||||
g_warning("register global: %s", interface);
|
||||
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);
|
||||
}
|
||||
else if (strcmp(interface, wl_shm_interface.name) == 0)
|
||||
{
|
||||
wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_global_remove(void *data, struct wl_registry *registry,
|
||||
@ -32,7 +83,8 @@ static void handle_global_remove(void *data, struct wl_registry *registry,
|
||||
(void) name;
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
static const struct wl_registry_listener registry_listener =
|
||||
{
|
||||
.global = handle_global,
|
||||
.global_remove = handle_global_remove
|
||||
};
|
||||
@ -43,8 +95,13 @@ void diya_shell_wayland_init(DiyaShell *shell)
|
||||
struct wl_registry *registry;
|
||||
display = gdk_wayland_display_get_wl_display(gdk_display_get_default());
|
||||
if (!display)
|
||||
g_error("Can't get wayland display\n");
|
||||
|
||||
{
|
||||
g_error("Can't get wayland display");
|
||||
return;
|
||||
}
|
||||
DiyaWayland * wayland = g_object_new(DIYA_TYPE_WAYLAND, "shell", shell, NULL);
|
||||
g_object_set(shell, "wayland", wayland, NULL);
|
||||
//g_object_set(wayland, "shell", shell, NULL);
|
||||
registry = wl_display_get_registry(display);
|
||||
wl_registry_add_listener(registry, ®istry_listener, (void*)shell);
|
||||
wl_display_roundtrip(display);
|
||||
@ -55,3 +112,33 @@ void diya_shell_wayland_init(DiyaShell *shell)
|
||||
// wl_display_roundtrip(display);
|
||||
// wl_display_roundtrip(display);
|
||||
}
|
||||
|
||||
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self)
|
||||
{
|
||||
assert(self->compositor);
|
||||
struct wl_surface* surface = wl_compositor_create_surface(self->compositor);
|
||||
assert(surface);
|
||||
return surface;
|
||||
}
|
||||
|
||||
struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index)
|
||||
{
|
||||
(void) self;
|
||||
/**
|
||||
* TODO: listen to wl_ouput interface instead of using gdk
|
||||
*/
|
||||
GListModel * list = gdk_display_get_monitors(gdk_display_get_default());
|
||||
GdkMonitor * monitor = g_list_model_get_item(list,index);
|
||||
if(! monitor)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct wl_output * output = gdk_wayland_monitor_get_wl_output(monitor);
|
||||
assert(output);
|
||||
return output;
|
||||
}
|
||||
struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size)
|
||||
{
|
||||
assert(self->shm);
|
||||
return wl_shm_create_pool(self->shm, fd, size);
|
||||
}
|
||||
|
@ -4,5 +4,7 @@
|
||||
#include "shell.h"
|
||||
|
||||
void diya_shell_wayland_init(DiyaShell *shell);
|
||||
|
||||
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self);
|
||||
struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index);
|
||||
struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size);
|
||||
#endif
|
110
src/widgets/cairo-widget.c
Normal file
110
src/widgets/cairo-widget.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include <cairo/cairo.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "cairo-widget.h"
|
||||
|
||||
enum
|
||||
{
|
||||
CW_NO_PROP,
|
||||
CW_EXTENT,
|
||||
CW_PARENT,
|
||||
CW_N_PROPERTIES
|
||||
};
|
||||
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
|
||||
|
||||
typedef struct _DiyaCairoWidgetPrivate
|
||||
{
|
||||
DiyaObject * parent_object;
|
||||
diya_rect_t extent;
|
||||
DiyaCairoWidget * parent_widget;
|
||||
// TODO list of children
|
||||
gchar string[64];
|
||||
} 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");
|
||||
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);
|
||||
diya_rect_t * rect;
|
||||
switch (property_id)
|
||||
{
|
||||
case CW_PARENT:
|
||||
priv->parent_widget = g_value_get_pointer(value);
|
||||
break;
|
||||
case CW_EXTENT:
|
||||
rect = g_value_get_pointer(value);
|
||||
assert(rect);
|
||||
memcpy(&priv->extent,rect, sizeof(priv->extent));
|
||||
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:
|
||||
g_value_set_pointer(value, &priv->extent);
|
||||
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));
|
||||
priv->parent_widget = NULL;
|
||||
priv->string[0] = '\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);
|
||||
|
||||
g_snprintf(priv->string,sizeof(priv->string),
|
||||
"%s (%dx%d) at %d@%d",
|
||||
class->name,
|
||||
priv->extent.x, priv->extent.y,
|
||||
priv->extent.width, priv->extent.height
|
||||
);
|
||||
return priv->string;
|
||||
}
|
||||
|
||||
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, "");
|
||||
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;
|
||||
g_cw_prop[CW_EXTENT] = g_param_spec_pointer("extent", NULL, "Widget extent relative to its parent", G_PARAM_READWRITE); //
|
||||
g_cw_prop[CW_PARENT] = g_param_spec_pointer("parent", NULL, "Parent widget", 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);
|
||||
}
|
20
src/widgets/cairo-widget.h
Normal file
20
src/widgets/cairo-widget.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef CAIRO_WIDGET_H
|
||||
#define CAIRO_WIDGET_H
|
||||
|
||||
#include "../base.h"
|
||||
|
||||
#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)
|
||||
|
||||
struct _DiyaCairoWidgetClass
|
||||
{
|
||||
DiyaObjectClass parent_class;
|
||||
const gchar* name;
|
||||
/**
|
||||
* @brief TODO define more API function
|
||||
*
|
||||
*/
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user