Initial commit: add code

- using meson build
 - implement shell using gobject API
 - support wlr-foreign-toplevel protocol
 - shell base UI (WIP)
This commit is contained in:
DanyLE
2024-04-14 16:29:02 +02:00
parent e9ef315aa4
commit ac300c32cf
17 changed files with 1146 additions and 1 deletions

33
src/background.c Normal file
View File

@@ -0,0 +1,33 @@
#include "background.h"
#include <assert.h>
#define NAMESPACE "background"
static void on_background_destroy(GtkWindow *window, GApplication *_data)
{
(void) window;
(void)_data;
//g_application_quit (G_APPLICATION (gtk_window_get_application (window)));
}
void diya_shell_init_background(DiyaShell * shell)
{
GtkWindow *gtk_window;
g_object_get(shell, "background", &gtk_window, NULL);
assert(gtk_window);
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_background_destroy), NULL);
// int layer shell for window
gtk_layer_init_for_window (gtk_window);
// anchor window to all edges
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
gtk_layer_set_anchor (gtk_window, i, true);
// set margin on window
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
gtk_layer_set_margin (gtk_window, i, 0);
gtk_layer_set_layer (gtk_window, GTK_LAYER_SHELL_LAYER_BACKGROUND);
gtk_layer_set_keyboard_mode (gtk_window, GTK_LAYER_SHELL_KEYBOARD_MODE_NONE);
gtk_layer_set_namespace (gtk_window, NAMESPACE);
gtk_widget_set_name(GTK_WIDGET(gtk_window),NAMESPACE);
//gtk_layer_auto_exclusive_zone_enable (gtk_window);
//g_signal_connect (gtk_window, "orientation-changed", G_CALLBACK (on_orientation_changed), /*data*/NULL);
gtk_window_present (GTK_WINDOW (gtk_window));
}

8
src/background.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef DIYA_SHELL_BACKGROUND_H
#define DIYA_SHELL_BACKGROUND_H
#include "shell.h"
void diya_shell_init_background(DiyaShell * shell);
#endif

21
src/base.c Normal file
View File

@@ -0,0 +1,21 @@
#include "base.h"
G_DEFINE_ABSTRACT_TYPE(DiyaObject, diya_object, G_TYPE_OBJECT)
static void diya_object_class_init(DiyaObjectClass *class)
{
class->to_string = NULL;
}
static void diya_object_init(DiyaObject *self)
{
(void) self;
}
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;
}

24
src/base.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef DIYA_OBJECT_H
#define DIYA_OBJECT_H
#include <glib-object.h>
/**
* Base class object
*
*/
#define DIYA_TYPE_OBJECT (diya_object_get_type ())
G_DECLARE_DERIVABLE_TYPE (DiyaObject, diya_object, DIYA, OBJECT, GObject)
struct _DiyaObjectClass {
GObjectClass parent_class;
const gchar* (*to_string) (DiyaObject *self);
/**
* @brief reserve for futur use to
* define common API for descendants
*
*/
};
const gchar* diya_object_to_string(gpointer object);
#endif

313
src/foreign.c Normal file
View File

@@ -0,0 +1,313 @@
#include <assert.h>
#include <inttypes.h>
#include "foreign.h"
/**
* @DiyaWindow Object definition
*
*/
enum
{
NO_PROP,
WIN_APP_ID,
WIN_TITLE,
WIN_HANDLE,
WIN_STATE,
WIN_PARENT,
SHELL,
N_PROPERTIES
};
static GParamSpec *win_properties[N_PROPERTIES] = {0};
struct _DiyaWindow
{
DiyaObject parent;
gchar * appid;
gpointer handle;
gchar* title;
enum diya_win_state state;
DiyaWindow * parent_win;
DiyaShell * shell;
gchar string[128];
};
G_DEFINE_TYPE(DiyaWindow, diya_window, DIYA_TYPE_OBJECT)
static void diya_window_finalize(GObject* object)
{
DiyaWindow * self = DIYA_WINDOW(object);
g_debug("diya_window_finalize: %s", diya_object_to_string(self));
if(self->appid)
{
g_free(self->appid);
}
if(self->title)
{
g_free(self->title);
}
}
static void diya_window_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaWindow * self = DIYA_WINDOW(object);
switch (property_id)
{
case WIN_APP_ID:
if(self->appid)
{
g_free(self->appid);
}
self->appid = g_strdup(g_value_get_string(value));
break;
case WIN_TITLE:
if(self->title)
{
g_free(self->title);
}
self->title = g_strdup(g_value_get_string(value));
break;
case WIN_HANDLE:
self->handle = g_value_get_pointer(value);
break;
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;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_window_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaWindow * self = DIYA_WINDOW(object);
switch (property_id)
{
case WIN_APP_ID:
g_value_set_string(value, self->appid);
break;
case WIN_TITLE:
g_value_set_string(value, self->title);
break;
case WIN_HANDLE:
g_value_set_pointer(value, self->handle);
break;
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;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_window_init(DiyaWindow *self)
{
self->appid = NULL;
//self->handle = NULL;
self->parent_win = NULL;
//self->shell = NULL;
self->state = DIYA_WIN_STATE_NONE;
self->title = NULL;
}
static const gchar* diya_window_to_string(DiyaObject* object)
{
DiyaWindow* self = DIYA_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)
{
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;
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);
}
static struct zwlr_foreign_toplevel_manager_v1 *g_toplevel_manager;
static void toplevel_handle_output_leave(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
struct wl_output *output)
{
(void) data;
(void) handle;
(void) output;
}
static void toplevel_handle_title(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
const char *title)
{
DiyaShell *shell = (DiyaShell *)data;
assert(shell);
DiyaWindow *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));
}
static void toplevel_handle_app_id(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
const char *app_id)
{
DiyaShell *shell = (DiyaShell *)data;
assert(shell);
DiyaWindow *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));
}
static void toplevel_handle_output_enter(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
struct wl_output *output)
{
(void) data;
(void) handle;
(void) output;
}
static void toplevel_handle_state(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
struct wl_array *state)
{
uint32_t *entry;
DiyaShell *shell = (DiyaShell *)data;
assert(shell);
DiyaWindow *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)
{
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED:
wstate |= DIYA_WIN_STATE_MINIMIZE;
break;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED:
wstate |= DIYA_WIN_STATE_MAXIMIZE;
break;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN:
wstate |= DIYA_WIN_STATE_FULLSCREEN;
break;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED:
wstate |= DIYA_WIN_STATE_FOCUS;
break;
}
g_object_set(win, "state", wstate, NULL);
}
static void toplevel_handle_done(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle)
{
DiyaShell *shell = (DiyaShell *)data;
assert(shell);
DiyaWindow *win = diya_shell_get_window(shell, handle);
assert(win);
g_signal_emit_by_name(shell, "foreign-window-changed", (void *)win);
}
static void toplevel_handle_closed(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle)
{
DiyaShell *shell = (DiyaShell *)data;
assert(shell);
DiyaWindow *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);
zwlr_foreign_toplevel_handle_v1_destroy(handle);
}
static void toplevel_handle_parent(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
struct zwlr_foreign_toplevel_handle_v1 *parent)
{
if (!parent)
{
return;
}
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);
assert(child_win);
assert(parent_win);
assert(child_win != parent_win);
g_object_set(child_win, "parent", parent_win, NULL);
g_debug("toplevel_handle_parent: %s is child of %s",
diya_object_to_string(child_win),
diya_object_to_string(parent_win));
}
static const struct zwlr_foreign_toplevel_handle_v1_listener g_toplevel_impl = {
.title = toplevel_handle_title,
.app_id = toplevel_handle_app_id,
.output_enter = toplevel_handle_output_enter,
.output_leave = toplevel_handle_output_leave,
.state = toplevel_handle_state,
.done = toplevel_handle_done,
.closed = toplevel_handle_closed,
.parent = toplevel_handle_parent};
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);
if (win)
{
g_debug("[%s] already exists",diya_object_to_string(win));
return;
}
// TODO: different between windows
win = diya_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;
// remove table entry
zwlr_foreign_toplevel_manager_v1_destroy(toplevel_manager);
}
static const struct zwlr_foreign_toplevel_manager_v1_listener g_toplevel_manager_impl =
{
.toplevel = toplevel_manager_handle_toplevel,
.finished = toplevel_manager_handle_finished,
};
void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell)
{
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;
}

7
src/foreign.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef DIYA_SHELL_FOREIGN_H
#define DIYA_SHELL_FOREIGN_H
#include "wlr-foreign-toplevel-management-unstable-v1.h"
#include "shell.h"
void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell);
#endif

78
src/launcher.c Normal file
View File

@@ -0,0 +1,78 @@
#include "launcher.h"
#include "foreign.h"
#include <assert.h>
#define NAMESPACE "launcher"
static void on_launcher_destroy(GtkWindow *window, GApplication *_data)
{
(void) window;
(void)_data;
//g_application_quit (G_APPLICATION (gtk_window_get_application (window)));
}
static void on_foreign_window_change(GtkApplication* app, DiyaWindow * win, gpointer data)
{
(void) app;
(void) data;
assert(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)
{
(void) app;
(void) data;
assert(win);
g_warning("WINDOW removed %s", diya_object_to_string(DIYA_OBJECT(win)));
}
void diya_launcher_init(DiyaShell * shell)
{
assert(shell);
GtkWindow *gtk_window;
g_object_get(shell, "launchpad", &gtk_window, NULL);
assert(gtk_window);
g_signal_connect (gtk_window, "destroy", G_CALLBACK (on_launcher_destroy), NULL);
// int layer shell for window
gtk_layer_init_for_window (gtk_window);
// anchor window to all edges
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, true);
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, true);
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_TOP, true);
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, false);
// set margin on window
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
gtk_layer_set_margin (gtk_window, i, 0);
gtk_layer_set_layer (gtk_window, GTK_LAYER_SHELL_LAYER_TOP);
gtk_layer_set_keyboard_mode (gtk_window, GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND);
gtk_layer_set_namespace (gtk_window, NAMESPACE);
// the top launcher shall be exclusive
gtk_layer_auto_exclusive_zone_enable (gtk_window);
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);
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
gtk_window_set_child (GTK_WINDOW (gtk_window), box);
//g_signal_connect (gtk_window, "orientation-changed", G_CALLBACK (on_orientation_changed), /*data*/NULL);
gtk_window_present (GTK_WINDOW (gtk_window));
g_signal_connect (shell, "foreign-window-changed", G_CALLBACK (on_foreign_window_change), NULL);
g_signal_connect (shell, "foreign-window-removed", G_CALLBACK (on_foreign_window_removed), NULL);
GList *apps = g_app_info_get_all ();
GList * l;
for (l = apps; l != NULL; l = l->next)
{
gpointer element_data = l->data;
g_warning("%s", g_app_info_get_display_name(element_data)); /*print out all of the display names of the .desktop files */
g_warning("%s", g_app_info_get_id(element_data));
g_warning("%s", g_app_info_get_name(element_data));
//g_warning("%s", g_app_info_get_icon(element_data));
}
g_list_free_full(apps, g_object_unref);
}

9
src/launcher.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef DIYA_SHELL_LAUNCHER_H
#define DIYA_SHELL_LAUNCHER_H
#include "shell.h"
void diya_launcher_init(DiyaShell * shell);
#endif

0
src/log.c Normal file
View File

0
src/log.h Normal file
View File

230
src/shell.c Normal file
View File

@@ -0,0 +1,230 @@
#include <assert.h>
#include "background.h"
#include "launcher.h"
#include "wayland.h"
#include "foreign.h"
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
enum
{
NO_PROP,
SHELL_APP,
SHELL_BACKGROUND_WIDGET,
SHELL_LAUNCHPAD_WIDGET,
SHELL_WINDOWS,
N_PROPERTIES
};
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
struct _DiyaShell
{
DiyaObject parent;
GtkApplication* app;
GtkWindow* background;
GtkWindow* launcher;
GHashTable* windows;
};
G_DEFINE_TYPE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT)
static void diya_shell_finalize(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");
}
static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaShell * self = DIYA_SHELL(object);
switch (property_id)
{
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:
case SHELL_LAUNCHPAD_WIDGET:
case SHELL_WINDOWS:
//self->windows = g_value_get_pointer(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_shell_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaShell * self = DIYA_SHELL(object);
switch (property_id)
{
case SHELL_APP:
g_value_set_pointer(value, self->app);
break;
case SHELL_BACKGROUND_WIDGET:
g_value_set_pointer(value, self->background);
break;
case SHELL_LAUNCHPAD_WIDGET:
assert(self->launcher);
g_value_set_pointer(value, self->launcher);
break;
case SHELL_WINDOWS:
g_value_set_pointer(value, self->windows);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static const gchar* diya_shell_to_string(DiyaObject* object)
{
(void) object;
return SHELL_DESCRIPTION;
}
static void diya_shell_class_init(DiyaShellClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
base_class->to_string = diya_shell_to_string;
gobject_class->finalize = diya_shell_finalize;
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_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
g_signal_new("foreign-window-changed",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_new("foreign-window-removed",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
}
static void diya_shell_init(DiyaShell *self)
{
//self->app = NULL;
self->background = NULL;
self->launcher = 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)
{
return g_hash_table_lookup(shell->windows, handle);
}
gboolean diya_shell_add_window(DiyaShell * shell, DiyaWindow * win)
{
gpointer handle;
g_object_get(win, "handle", &handle, NULL);
assert(handle);
return g_hash_table_insert(shell->windows,handle, win);
}
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaWindow * win)
{
gpointer handle;
g_object_get(win, "handle", &handle, NULL);
assert(handle);
return g_hash_table_remove(shell->windows,handle);
}
DiyaShell * diya_shell_new(GtkApplication * app)
{
return DIYA_SHELL(g_object_new(DIYA_TYPE_SHELL,"application",app, NULL));
}
/*
static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data)
{
(void)window;
GtkOrientation orient_toplevel, orient_sub;
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
switch (orientation) {
case WINDOW_ORIENTATION_HORIZONTAL:
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_HORIZONTAL;
break;
case WINDOW_ORIENTATION_VERTICAL:
orient_toplevel = GTK_ORIENTATION_VERTICAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
break;
case WINDOW_ORIENTATION_NONE:
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
break;
}
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->toplevel_box), orient_toplevel);
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->first_box), orient_sub);
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->second_box), orient_sub);
//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;
}

27
src/shell.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef DIYA_SHELL_H
#define DIYA_SHELL_H
#include <gtk4-layer-shell.h>
#include "base.h"
enum diya_win_state
{
DIYA_WIN_STATE_NONE = 0,
DIYA_WIN_STATE_MINIMIZE = 1 << 0,
DIYA_WIN_STATE_MAXIMIZE = 1 << 1,
DIYA_WIN_STATE_FULLSCREEN = 1 << 2,
DIYA_WIN_STATE_FOCUS = 1 << 3,
};
#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)
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);
#endif

57
src/wayland.c Normal file
View File

@@ -0,0 +1,57 @@
#include <wayland-client-protocol.h>
#include <gdk/wayland/gdkwayland.h>
#include "wayland.h"
#include "foreign.h"
static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const gchar *interface, uint32_t version)
{
/*if (!g_strcmp0(interface, zxdg_output_manager_v1_interface.name))
xdg_output_register(registry, name);
else if (!g_strcmp0(interface, wl_shm_interface.name))
shm_register(registry, name);
else if (!g_strcmp0(interface, zwlr_layer_shell_v1_interface.name))
layer_shell_register(registry, name, version);
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;
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);
}
}
static void handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name)
{
(void) data;
(void) registry;
(void) name;
}
static const struct wl_registry_listener registry_listener = {
.global = handle_global,
.global_remove = handle_global_remove
};
void diya_shell_wayland_init(DiyaShell *shell)
{
struct wl_display *display;
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");
registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, (void*)shell);
wl_display_roundtrip(display);
// wayland_monitor_probe();
// GdkMonitor *mon = wayland_monitor_get_default();
// g_info("default output: %s", (gchar *)g_object_get_data(G_OBJECT(mon), "xdg_name"));
// wl_display_roundtrip(display);
// wl_display_roundtrip(display);
}

8
src/wayland.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef DIYA_SHELL_WAYLAND_H
#define DIYA_SHELL_WAYLAND_H
#include "shell.h"
void diya_shell_wayland_init(DiyaShell *shell);
#endif