add basic cairo widget for session lock (WIP)

This commit is contained in:
DanyLE 2024-04-17 01:05:53 +02:00
parent ac300c32cf
commit f8deb67a5a
18 changed files with 922 additions and 141 deletions

View File

@ -2,7 +2,7 @@ project('diya-shell',
['c'], ['c'],
version: '0.1.0', version: '0.1.0',
license: 'MIT', license: 'MIT',
meson_version: '>=0.51.0', meson_version: '>=0.58.0',
default_options: ['c_std=gnu11', 'warning_level=3']) default_options: ['c_std=gnu11', 'warning_level=3'])
lib_so_version = '0' lib_so_version = '0'
@ -22,7 +22,10 @@ wayland_client = dependency('wayland-client', version: '>=1.10.0')
wayland_scanner = find_program('wayland-scanner') wayland_scanner = find_program('wayland-scanner')
# use system xdg-shell protocol when available # 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') # pkg_config = import('pkgconfig')
# gnome = import('gnome') # 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') gtk_layer_shell = dependency('gtk4-layer-shell-0', version: '>=1.0.2')
wayland_targets=[] wayland_targets=[]
wayland_protos = [ wl_protocols = [
wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1',
'protocols/wlr-foreign-toplevel-management-unstable-v1' 'protocols/wlr-foreign-toplevel-management-unstable-v1'
] ]
foreach proto : wayland_protos foreach proto : wl_protocols
xml = ''.join([proto,'.xml']) xml = ''.join([proto,'.xml'])
header = ''.join([proto.split('/').get(-1),'.h']) header = ''.join([proto.split('/').get(-1),'.h'])
cfile = ''.join([proto.split('/').get(-1),'.c']) cfile = ''.join([proto.split('/').get(-1),'.c'])
@ -51,6 +55,9 @@ src = [
'src/wayland.c', 'src/wayland.c',
'src/shell.c', 'src/shell.c',
'src/foreign.c', 'src/foreign.c',
'src/session.c',
'src/widgets/cairo-widget.c',
'src/main.c',
wayland_targets] wayland_targets]
executable( executable(

View File

@ -11,9 +11,12 @@ static void on_background_destroy(GtkWindow *window, GApplication *_data)
void diya_shell_init_background(DiyaShell * shell) void diya_shell_init_background(DiyaShell * shell)
{ {
GtkWindow *gtk_window; GtkApplication * app;
g_object_get(shell, "background", &gtk_window, NULL); g_object_get(shell, "application", &app, NULL);
assert(app);
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
assert(gtk_window); assert(gtk_window);
g_object_set(shell, "background", gtk_window, NULL);
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_background_destroy), NULL); g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_background_destroy), NULL);
// int layer shell for window // int layer shell for window
gtk_layer_init_for_window (gtk_window); gtk_layer_init_for_window (gtk_window);

View File

@ -1,10 +1,20 @@
#include "base.h" #include "base.h"
#include "shell.h"
G_DEFINE_ABSTRACT_TYPE(DiyaObject, diya_object, G_TYPE_OBJECT) 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) static void diya_object_class_init(DiyaObjectClass *class)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
class->to_string = NULL; class->to_string = NULL;
gobject_class->dispose = diya_object_dispose;
} }
static void diya_object_init(DiyaObject *self) static void diya_object_init(DiyaObject *self)
@ -12,10 +22,82 @@ static void diya_object_init(DiyaObject *self)
(void) 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) const gchar * diya_object_to_string(gpointer object)
{ {
g_return_val_if_fail(DIYA_IS_OBJECT(object), NULL); g_return_val_if_fail(DIYA_IS_OBJECT(object), NULL);
DiyaObject * self = DIYA_OBJECT(object); DiyaObject * self = DIYA_OBJECT(object);
DiyaObjectClass *class = DIYA_OBJECT_GET_CLASS(self); DiyaObjectClass *class = DIYA_OBJECT_GET_CLASS(self);
return class->to_string ? class->to_string(self) : NULL; return class->to_string ? class->to_string(self) : "";
} }

View File

@ -2,16 +2,26 @@
#define DIYA_OBJECT_H #define DIYA_OBJECT_H
#include <glib-object.h> #include <glib-object.h>
typedef struct
{
gint x;
gint y;
gint width;
gint height;
} diya_rect_t;
/** /**
* Base class object * Base class object
* *
*/ */
#define DIYA_TYPE_OBJECT (diya_object_get_type ()) #define DIYA_TYPE_OBJECT (diya_object_get_type())
G_DECLARE_DERIVABLE_TYPE (DiyaObject, diya_object, DIYA, OBJECT, GObject) G_DECLARE_DERIVABLE_TYPE(DiyaObject, diya_object, DIYA, OBJECT, GObject)
struct _DiyaObjectClass { struct _DiyaObjectClass
{
GObjectClass parent_class; GObjectClass parent_class;
const gchar* (*to_string) (DiyaObject *self); const gchar *(*to_string)(DiyaObject *self);
/** /**
* @brief reserve for futur use to * @brief reserve for futur use to
* define common API for descendants * 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 #endif

View File

@ -3,7 +3,7 @@
#include "foreign.h" #include "foreign.h"
/** /**
* @DiyaWindow Object definition * @DiyaForeignWindow Object definition
* *
*/ */
enum enum
@ -14,27 +14,25 @@ enum
WIN_HANDLE, WIN_HANDLE,
WIN_STATE, WIN_STATE,
WIN_PARENT, WIN_PARENT,
SHELL,
N_PROPERTIES N_PROPERTIES
}; };
static GParamSpec *win_properties[N_PROPERTIES] = {0}; static GParamSpec *win_properties[N_PROPERTIES] = {0};
struct _DiyaWindow struct _DiyaForeignWindow
{ {
DiyaObject parent; DiyaObject parent;
gchar * appid; gchar * appid;
gpointer handle; gpointer handle;
gchar* title; gchar* title;
enum diya_win_state state; enum diya_win_state state;
DiyaWindow * parent_win; DiyaForeignWindow * parent_win;
DiyaShell * shell;
gchar string[128]; 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); DiyaForeignWindow * self = DIYA_FOREIGN_WINDOW(object);
g_debug("diya_window_finalize: %s", diya_object_to_string(self)); g_debug("diya_foreign_window_dispose: %s", diya_object_to_string(self));
if(self->appid) if(self->appid)
{ {
g_free(self->appid); g_free(self->appid);
@ -43,11 +41,12 @@ static void diya_window_finalize(GObject* object)
{ {
g_free(self->title); 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) switch (property_id)
{ {
case WIN_APP_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: case WIN_PARENT:
self->parent_win = g_value_get_pointer(value); self->parent_win = g_value_get_pointer(value);
break; break;
case SHELL:
self->shell = g_value_get_pointer(value);
break;
case WIN_STATE: case WIN_STATE:
self->state = g_value_get_uint(value); self->state = g_value_get_uint(value);
break; 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) switch (property_id)
{ {
case WIN_APP_ID: case WIN_APP_ID:
@ -100,9 +96,6 @@ static void diya_window_get_property(GObject *object, guint property_id, GValue
case WIN_PARENT: case WIN_PARENT:
g_value_set_pointer(value, self->parent_win); g_value_set_pointer(value, self->parent_win);
break; break;
case SHELL:
g_value_set_pointer(value, self->shell);
break;
case WIN_STATE: case WIN_STATE:
g_value_set_uint(value, self->state); g_value_set_uint(value, self->state);
break; 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->appid = NULL;
//self->handle = NULL; //self->handle = NULL;
@ -120,32 +113,31 @@ static void diya_window_init(DiyaWindow *self)
//self->shell = NULL; //self->shell = NULL;
self->state = DIYA_WIN_STATE_NONE; self->state = DIYA_WIN_STATE_NONE;
self->title = NULL; 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:""); 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; 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); GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
gobject_class->finalize = diya_window_finalize; gobject_class->dispose = diya_foreign_window_dispose;
gobject_class->set_property = diya_window_set_property; gobject_class->set_property = diya_foreign_window_set_property;
gobject_class->get_property = diya_window_get_property; gobject_class->get_property = diya_foreign_window_get_property;
base_class->to_string = diya_window_to_string; 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_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_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_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_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[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); 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; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, handle); DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
assert(win); assert(win);
g_object_set(win, "title", title, NULL); g_object_set(win, "title", title, NULL);
g_debug("New title for: %s", diya_object_to_string(win)); 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; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, handle); DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
assert(win); assert(win);
g_object_set(win, "appid", app_id, NULL); g_object_set(win, "appid", app_id, NULL);
g_debug("New appid for: %s", diya_object_to_string(win)); 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; uint32_t *entry;
DiyaShell *shell = (DiyaShell *)data; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, handle); DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
assert(win); assert(win);
enum diya_win_state wstate = DIYA_WIN_STATE_NONE; enum diya_win_state wstate = DIYA_WIN_STATE_NONE;
wl_array_for_each(entry, state) switch (*entry) wl_array_for_each(entry, state) switch (*entry)
@ -221,7 +213,7 @@ static void toplevel_handle_done(void *data,
{ {
DiyaShell *shell = (DiyaShell *)data; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, handle); DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
assert(win); assert(win);
g_signal_emit_by_name(shell, "foreign-window-changed", (void *)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; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, handle); DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
assert(win); assert(win);
g_signal_emit_by_name(shell, "foreign-window-removed", (void *)win); g_signal_emit_by_name(shell, "foreign-window-removed", (void *)win);
diya_shell_remove_window(shell, win); diya_shell_remove_window(shell, win);
@ -247,8 +239,8 @@ static void toplevel_handle_parent(void *data,
assert(handle != parent); assert(handle != parent);
DiyaShell *shell = (DiyaShell *)data; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *child_win = diya_shell_get_window(shell, handle); DiyaForeignWindow *child_win = diya_shell_get_window(shell, handle);
DiyaWindow *parent_win = diya_shell_get_window(shell, parent); DiyaForeignWindow *parent_win = diya_shell_get_window(shell, parent);
assert(child_win); assert(child_win);
assert(parent_win); assert(parent_win);
assert(child_win != 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, .state = toplevel_handle_state,
.done = toplevel_handle_done, .done = toplevel_handle_done,
.closed = toplevel_handle_closed, .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) 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; (void) toplevel_manager;
DiyaShell *shell = (DiyaShell *)data; DiyaShell *shell = (DiyaShell *)data;
assert(shell); assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, tl); DiyaForeignWindow *win = diya_shell_get_window(shell, tl);
if (win) if (win)
{ {
@ -280,14 +282,15 @@ static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_top
return; return;
} }
// TODO: different between windows // 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); zwlr_foreign_toplevel_handle_v1_add_listener(tl, &g_toplevel_impl, data);
} }
static void toplevel_manager_handle_finished(void *data, static void toplevel_manager_handle_finished(void *data,
struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager) struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager)
{ {
(void) data; DiyaShell *shell = (DiyaShell *)data;
diya_shell_remove_all_windows(shell);
// remove table entry // remove table entry
zwlr_foreign_toplevel_manager_v1_destroy(toplevel_manager); 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); 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); 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;
}

View File

@ -1,5 +1,6 @@
#include "launcher.h" #include "launcher.h"
#include "foreign.h" #include "foreign.h"
#include "session.h"
#include <assert.h> #include <assert.h>
#define NAMESPACE "launcher" #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))); //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) app;
(void) data; (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))); 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) app;
(void) data; (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))); 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); assert(shell);
GtkWindow *gtk_window; GtkApplication * app;
g_object_get(shell, "launchpad", &gtk_window, NULL); g_object_get(shell, "application", &app, NULL);
assert(app);
GtkWindow *gtk_window = GTK_WINDOW (gtk_application_window_new (app));
assert(gtk_window); assert(gtk_window);
g_object_set(shell, "launchpad", gtk_window, NULL);
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_launcher_destroy), NULL); g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_launcher_destroy), NULL);
// int layer shell for window // int layer shell for window
gtk_layer_init_for_window (gtk_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_widget_set_name(GTK_WIDGET(gtk_window),NAMESPACE);
gtk_window_set_default_size(gtk_window, 48, 48); 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_box_set_homogeneous (GTK_BOX (box), TRUE);
gtk_window_set_child (GTK_WINDOW (gtk_window), box); 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); //g_signal_connect (gtk_window, "orientation-changed", G_CALLBACK (on_orientation_changed), /*data*/NULL);
gtk_window_present (GTK_WINDOW (gtk_window)); gtk_window_present (GTK_WINDOW (gtk_window));

View File

@ -4,6 +4,6 @@
#include "shell.h" #include "shell.h"
void diya_launcher_init(DiyaShell * shell); void diya_shell_launcher_init(DiyaShell * shell);
#endif #endif

View File

View File

72
src/main.c Normal file
View 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
View 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
View 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

View File

@ -1,9 +1,7 @@
#include <assert.h> #include <assert.h>
#include "background.h"
#include "launcher.h"
#include "wayland.h"
#include "foreign.h" #include "foreign.h"
#include "session.h"
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)" #define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
@ -14,6 +12,7 @@ enum
SHELL_BACKGROUND_WIDGET, SHELL_BACKGROUND_WIDGET,
SHELL_LAUNCHPAD_WIDGET, SHELL_LAUNCHPAD_WIDGET,
SHELL_WINDOWS, SHELL_WINDOWS,
SHELL_WAYLAND,
N_PROPERTIES N_PROPERTIES
}; };
@ -26,16 +25,25 @@ struct _DiyaShell
GtkWindow* background; GtkWindow* background;
GtkWindow* launcher; GtkWindow* launcher;
GHashTable* windows; 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); DiyaShell * self = DIYA_SHELL(object);
g_hash_table_destroy(self->windows); g_hash_table_destroy(self->windows);
// TODO: free element in each entry of the table g_debug("diya_shell_dispose");
// g_object_unref(self->app); if(self->wayland)
g_warning("diya_shell_finalize"); {
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) 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: case SHELL_APP:
self->app = g_value_get_pointer(value); self->app = g_value_get_pointer(value);
assert(self->app); assert(self->app);
self->background = GTK_WINDOW (gtk_application_window_new (self->app));
self->launcher = GTK_WINDOW (gtk_application_window_new (self->app));
break; break;
case SHELL_BACKGROUND_WIDGET: case SHELL_BACKGROUND_WIDGET:
self->background = g_value_get_pointer(value);
break;
case SHELL_LAUNCHPAD_WIDGET: 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: case SHELL_WINDOWS:
//self->windows = g_value_get_pointer(value); //self->windows = g_value_get_pointer(value);
break; break;
@ -75,6 +88,9 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue *
assert(self->launcher); assert(self->launcher);
g_value_set_pointer(value, self->launcher); g_value_set_pointer(value, self->launcher);
break; break;
case SHELL_WAYLAND:
g_value_set_pointer(value, self->wayland);
break;
case SHELL_WINDOWS: case SHELL_WINDOWS:
g_value_set_pointer(value, self->windows); g_value_set_pointer(value, self->windows);
break; break;
@ -96,14 +112,16 @@ static void diya_shell_class_init(DiyaShellClass *class)
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
base_class->to_string = diya_shell_to_string; 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->set_property = diya_shell_set_property;
gobject_class->get_property = diya_shell_get_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_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_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_READABLE ); 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_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_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
g_signal_new("foreign-window-changed", g_signal_new("foreign-window-changed",
@ -137,14 +155,15 @@ static void diya_shell_init(DiyaShell *self)
//self->app = NULL; //self->app = NULL;
self->background = NULL; self->background = NULL;
self->launcher = NULL; self->launcher = NULL;
self->wayland = NULL;
self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); 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); 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; gpointer handle;
g_object_get(win, "handle", &handle, NULL); 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); 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; gpointer handle;
g_object_get(win, "handle", &handle, NULL); 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); 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) DiyaShell * diya_shell_new(GtkApplication * app)
{ {
return DIYA_SHELL(g_object_new(DIYA_TYPE_SHELL,"application",app, NULL)); 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) 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 //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); static void before_destroy (GtkWidget *win, GtkCssProvider *provider) {
diya_shell_init_background(shell); GdkDisplay *display = gdk_display_get_default ();
// CSS support gtk_style_context_remove_provider_for_display (display, GTK_STYLE_PROVIDER (provider));
// 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;
} }
*/

View File

@ -15,13 +15,24 @@ enum diya_win_state
#define DIYA_TYPE_SHELL (diya_shell_get_type ()) #define DIYA_TYPE_SHELL (diya_shell_get_type ())
G_DECLARE_FINAL_TYPE (DiyaShell, diya_shell, DIYA, SHELL, DiyaObject) G_DECLARE_FINAL_TYPE (DiyaShell, diya_shell, DIYA, SHELL, DiyaObject)
#define DIYA_TYPE_WINDOW (diya_window_get_type ()) #define DIYA_TYPE_WAYLAND (diya_wayland_get_type ())
G_DECLARE_FINAL_TYPE (DiyaWindow, diya_window, DIYA, WINDOW, DiyaObject) 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); DiyaShell * diya_shell_new(GtkApplication * app);
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
DiyaWindow * diya_window_new(DiyaShell* shell, gpointer handle);
#endif #endif

View File

@ -1,7 +1,44 @@
#include <wayland-client-protocol.h> #include <wayland-client-protocol.h>
#include <gdk/wayland/gdkwayland.h> #include <gdk/wayland/gdkwayland.h>
#include <assert.h>
#include "wayland.h" #include "wayland.h"
#include "foreign.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) 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)) if (!g_strcmp0(interface,zwlr_foreign_toplevel_manager_v1_interface.name))
foreign_toplevel_register(registry,name); foreign_toplevel_register(registry,name);
*/ */
//g_warning("register global: %s VS %s", interface, zwlr_foreign_toplevel_manager_v1_interface.name);
(void) version; (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)) 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); 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, 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; (void) name;
} }
static const struct wl_registry_listener registry_listener = { static const struct wl_registry_listener registry_listener =
{
.global = handle_global, .global = handle_global,
.global_remove = handle_global_remove .global_remove = handle_global_remove
}; };
@ -43,8 +95,13 @@ void diya_shell_wayland_init(DiyaShell *shell)
struct wl_registry *registry; struct wl_registry *registry;
display = gdk_wayland_display_get_wl_display(gdk_display_get_default()); display = gdk_wayland_display_get_wl_display(gdk_display_get_default());
if (!display) 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); registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, (void*)shell); wl_registry_add_listener(registry, &registry_listener, (void*)shell);
wl_display_roundtrip(display); wl_display_roundtrip(display);
@ -55,3 +112,33 @@ void diya_shell_wayland_init(DiyaShell *shell)
// wl_display_roundtrip(display); // wl_display_roundtrip(display);
// 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);
}

View File

@ -4,5 +4,7 @@
#include "shell.h" #include "shell.h"
void diya_shell_wayland_init(DiyaShell *shell); 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 #endif

110
src/widgets/cairo-widget.c Normal file
View 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);
}

View 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