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:
33
src/background.c
Normal file
33
src/background.c
Normal 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", >k_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
8
src/background.h
Normal 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
21
src/base.c
Normal 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
24
src/base.h
Normal 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
313
src/foreign.c
Normal 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
7
src/foreign.h
Normal 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
78
src/launcher.c
Normal 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", >k_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
9
src/launcher.h
Normal 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
|
230
src/shell.c
Normal file
230
src/shell.c
Normal 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
27
src/shell.h
Normal 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
57
src/wayland.c
Normal 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, ®istry_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
8
src/wayland.h
Normal 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
|
Reference in New Issue
Block a user