Skip to content

Commit 3c8fac9

Browse files
authored
Update main.cpp
1 parent e9712f6 commit 3c8fac9

1 file changed

Lines changed: 111 additions & 73 deletions

File tree

source-code/Desktop/main.cpp

Lines changed: 111 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,111 @@
11
#include <gtk/gtk.h>
22
#include <gio/gio.h>
3-
#include <gio/gdesktopappinfo.h>
43
#include <gtk-layer-shell/gtk-layer-shell.h>
54
#include <stdlib.h>
65
#include <string.h>
76

8-
#define APP_DIR "/usr/share/applications/"
97
#define WALLPAPER_DIR "/usr/share/wallpapers/"
108
#define DEFAULT_WALLPAPER WALLPAPER_DIR "default_wallpaper.jpg" // Assume a default wallpaper file
119

12-
typedef struct {
10+
struct DesktopData {
1311
GtkWidget *window;
1412
GtkWidget *overlay;
1513
GtkWidget *background_image;
16-
GtkWidget *icon_view;
14+
GtkWidget *flow_box;
1715
GListModel *app_list;
18-
} DesktopData;
16+
};
1917

20-
static void launch_app(GtkWidget *widget, gpointer user_data) {
21-
GAppInfo *app_info = G_APP_INFO(user_data);
18+
static void launch_app(GAppInfo *app_info) {
2219
GError *error = NULL;
2320
if (!g_app_info_launch(app_info, NULL, NULL, &error)) {
2421
g_printerr("Failed to launch app: %s\n", error->message);
2522
g_error_free(error);
2623
}
2724
}
2825

29-
static void populate_icons(GtkIconView *icon_view, GListModel *model) {
30-
gtk_icon_view_set_model(icon_view, GTK_TREE_MODEL(model));
31-
gtk_icon_view_set_pixbuf_column(icon_view, 0);
32-
gtk_icon_view_set_text_column(icon_view, 1);
33-
gtk_icon_view_set_activate_on_single_click(icon_view, TRUE);
34-
g_signal_connect(icon_view, "item-activated", G_CALLBACK(launch_app), NULL);
26+
static void on_icon_pressed(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
27+
GtkEventController *controller = GTK_EVENT_CONTROLLER(gesture);
28+
GtkWidget *widget = gtk_event_controller_get_widget(controller);
29+
GAppInfo *app_info = (GAppInfo*)g_object_get_data(G_OBJECT(widget), "app_info");
30+
if (app_info) {
31+
launch_app(app_info);
32+
}
33+
}
34+
35+
static void populate_flowbox(GtkFlowBox *flow_box, GListModel *model) {
36+
for (guint i = 0; i < g_list_model_get_n_items(model); i++) {
37+
GAppInfo *app_info = G_APP_INFO(g_list_model_get_object(model, i));
38+
if (!app_info) continue;
39+
GIcon *gicon = g_app_info_get_icon(app_info);
40+
GtkWidget *image = gtk_image_new_from_gicon(gicon);
41+
gtk_image_set_pixel_size(GTK_IMAGE(image), 48);
42+
GtkWidget *label = gtk_label_new(g_app_info_get_display_name(app_info));
43+
gtk_label_set_wrap(GTK_LABEL(label), TRUE);
44+
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
45+
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
46+
gtk_box_append(GTK_BOX(box), image);
47+
gtk_box_append(GTK_BOX(box), label);
48+
gtk_widget_set_margin_start(box, 6);
49+
gtk_widget_set_margin_end(box, 6);
50+
gtk_widget_set_margin_top(box, 6);
51+
gtk_widget_set_margin_bottom(box, 6);
52+
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
53+
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
54+
g_object_set_data_full(G_OBJECT(box), "app_info", g_object_ref(app_info), g_object_unref);
55+
GtkGesture *gesture = gtk_gesture_click_new();
56+
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 1);
57+
g_signal_connect(gesture, "pressed", G_CALLBACK(on_icon_pressed), NULL);
58+
gtk_widget_add_controller(box, GTK_EVENT_CONTROLLER(gesture));
59+
gtk_flow_box_append(flow_box, box);
60+
g_object_unref(app_info);
61+
}
3562
}
3663

3764
static GListModel *load_apps() {
3865
GListStore *store = g_list_store_new(G_TYPE_APP_INFO);
39-
GDir *dir = g_dir_open(APP_DIR, 0, NULL);
40-
if (dir) {
41-
const gchar *filename;
42-
while ((filename = g_dir_read_name(dir)) != NULL) {
43-
if (g_str_has_suffix(filename, ".desktop")) {
44-
gchar *path = g_build_filename(APP_DIR, filename, NULL);
45-
GDesktopAppInfo *app_info = g_desktop_app_info_new_from_filename(path);
46-
if (app_info && g_app_info_should_show(G_APP_INFO(app_info))) {
47-
g_list_store_append(store, app_info);
48-
g_object_unref(app_info);
49-
}
50-
g_free(path);
51-
}
66+
GList *apps = g_app_info_get_all();
67+
for (GList *l = apps; l != NULL; l = l->next) {
68+
GAppInfo *app_info = G_APP_INFO(l->data);
69+
if (g_app_info_should_show(app_info)) {
70+
g_list_store_append(store, app_info);
5271
}
53-
g_dir_close(dir);
5472
}
73+
g_list_free_full(apps, g_object_unref);
5574
return G_LIST_MODEL(store);
5675
}
5776

58-
static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
59-
if (event->button == 3) { // Right click
60-
GtkWidget *menu = gtk_menu_new();
61-
GtkWidget *item_logout = gtk_menu_item_new_with_label("Logout");
62-
GtkWidget *item_shutdown = gtk_menu_item_new_with_label("Shutdown");
63-
GtkWidget *item_restart = gtk_menu_item_new_with_label("Restart");
64-
65-
// Connect signals (placeholders, implement actual commands)
66-
g_signal_connect(item_logout, "activate", G_CALLBACK(system), (gpointer)"dm-tool switch-to-greeter"); // Example
67-
g_signal_connect(item_shutdown, "activate", G_CALLBACK(system), (gpointer)"systemctl poweroff");
68-
g_signal_connect(item_restart, "activate", G_CALLBACK(system), (gpointer)"systemctl reboot");
69-
70-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item_logout);
71-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item_shutdown);
72-
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item_restart);
73-
74-
gtk_widget_show_all(menu);
75-
gtk_menu_popup_at_pointer(GTK_MENU(menu), (GdkEvent*)event);
76-
return TRUE;
77-
}
78-
return FALSE;
77+
static void on_logout(GSimpleAction *action, GVariant *param, gpointer user_data) {
78+
system("dm-tool switch-to-greeter");
79+
}
80+
81+
static void on_shutdown(GSimpleAction *action, GVariant *param, gpointer user_data) {
82+
system("systemctl poweroff");
83+
}
84+
85+
static void on_restart(GSimpleAction *action, GVariant *param, gpointer user_data) {
86+
system("systemctl reboot");
87+
}
88+
89+
static void show_context_menu(double x, double y, DesktopData *data) {
90+
GMenu *menu = g_menu_new();
91+
g_menu_append(menu, "Logout", "app.logout");
92+
g_menu_append(menu, "Shutdown", "app.shutdown");
93+
g_menu_append(menu, "Restart", "app.restart");
94+
GtkWidget *popover = gtk_popover_menu_new_from_model(G_MENU_MODEL(menu));
95+
gtk_widget_set_parent(popover, data->window);
96+
GdkRectangle point = { (int)x, (int)y, 0, 0 };
97+
gtk_popover_set_pointing_to(GTK_POPOVER(popover), &point);
98+
gtk_popover_popup(GTK_POPOVER(popover));
99+
g_object_unref(menu);
100+
}
101+
102+
static void on_desktop_click_pressed(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
103+
if (n_press != 1) return;
104+
show_context_menu(x, y, (DesktopData*)user_data);
79105
}
80106

81107
static void activate(GtkApplication *app, gpointer user_data) {
82108
DesktopData *data = (DesktopData *)user_data;
83-
84109
data->window = gtk_application_window_new(app);
85110
gtk_window_set_title(GTK_WINDOW(data->window), "Blue Desktop");
86111
gtk_window_fullscreen(GTK_WINDOW(data->window));
@@ -95,60 +120,73 @@ static void activate(GtkApplication *app, gpointer user_data) {
95120
gtk_layer_set_anchor(GTK_WINDOW(data->window), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE);
96121
gtk_layer_set_keyboard_mode(GTK_WINDOW(data->window), GTK_LAYER_SHELL_KEYBOARD_MODE_NONE);
97122

123+
// Add actions to app
124+
GSimpleAction *logout_action = g_simple_action_new("logout", NULL);
125+
g_signal_connect(logout_action, "activate", G_CALLBACK(on_logout), NULL);
126+
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(logout_action));
127+
g_object_unref(logout_action);
128+
129+
GSimpleAction *shutdown_action = g_simple_action_new("shutdown", NULL);
130+
g_signal_connect(shutdown_action, "activate", G_CALLBACK(on_shutdown), NULL);
131+
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(shutdown_action));
132+
g_object_unref(shutdown_action);
133+
134+
GSimpleAction *restart_action = g_simple_action_new("restart", NULL);
135+
g_signal_connect(restart_action, "activate", G_CALLBACK(on_restart), NULL);
136+
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(restart_action));
137+
g_object_unref(restart_action);
138+
98139
// Overlay for background and icons
99140
data->overlay = gtk_overlay_new();
100141

101142
// Background image
102-
data->background_image = gtk_image_new_from_file(DEFAULT_WALLPAPER);
143+
data->background_image = gtk_picture_new_for_filename(DEFAULT_WALLPAPER);
144+
gtk_picture_set_content_fit(GTK_PICTURE(data->background_image), GTK_CONTENT_FIT_COVER);
103145
gtk_widget_set_hexpand(data->background_image, TRUE);
104146
gtk_widget_set_vexpand(data->background_image, TRUE);
105-
gtk_image_set_pixel_size(GTK_IMAGE(data->background_image), -1); // Scale to fit
106-
gtk_overlay_add_overlay(GTK_OVERLAY(data->overlay), data->background_image);
107-
108-
// Icon view for desktop icons (apps)
109-
data->icon_view = gtk_icon_view_new();
110-
gtk_widget_set_hexpand(data->icon_view, TRUE);
111-
gtk_widget_set_vexpand(data->icon_view, TRUE);
112-
gtk_icon_view_set_item_orientation(GTK_ICON_VIEW(data->icon_view), GTK_ORIENTATION_VERTICAL);
113-
gtk_icon_view_set_columns(GTK_ICON_VIEW(data->icon_view), -1);
114-
gtk_icon_view_set_spacing(GTK_ICON_VIEW(data->icon_view), 12);
115-
gtk_icon_view_set_item_padding(GTK_ICON_VIEW(data->icon_view), 6);
147+
gtk_overlay_set_child(GTK_OVERLAY(data->overlay), data->background_image);
148+
149+
// Flow box for desktop icons (apps)
150+
data->flow_box = gtk_flow_box_new();
151+
gtk_flow_box_set_column_spacing(GTK_FLOW_BOX(data->flow_box), 12);
152+
gtk_flow_box_set_row_spacing(GTK_FLOW_BOX(data->flow_box), 12);
153+
gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(data->flow_box), GTK_SELECTION_NONE);
154+
gtk_widget_set_hexpand(data->flow_box, TRUE);
155+
gtk_widget_set_vexpand(data->flow_box, TRUE);
116156

117157
// Load and populate apps
118158
data->app_list = load_apps();
119-
populate_icons(GTK_ICON_VIEW(data->icon_view), data->app_list);
159+
populate_flowbox(GTK_FLOW_BOX(data->flow_box), data->app_list);
120160

121161
// Scrolled window for icons if many
122-
GtkWidget *scrolled = gtk_scrolled_window_new(NULL, NULL);
123-
gtk_container_add(GTK_CONTAINER(scrolled), data->icon_view);
162+
GtkWidget *scrolled = gtk_scrolled_window_new();
163+
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolled), data->flow_box);
124164
gtk_overlay_add_overlay(GTK_OVERLAY(data->overlay), scrolled);
125165

126-
gtk_container_add(GTK_CONTAINER(data->window), data->overlay);
166+
gtk_window_set_child(GTK_WINDOW(data->window), data->overlay);
127167

128168
// Handle right click
129-
gtk_widget_add_events(data->window, GDK_BUTTON_PRESS_MASK);
130-
g_signal_connect(data->window, "button-press-event", G_CALLBACK(on_button_press), NULL);
169+
GtkGesture *gesture = gtk_gesture_click_new();
170+
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 3);
171+
g_signal_connect(gesture, "pressed", G_CALLBACK(on_desktop_click_pressed), data);
172+
gtk_widget_add_controller(data->overlay, GTK_EVENT_CONTROLLER(gesture));
131173

132174
// Set dark theme
133175
GtkSettings *settings = gtk_settings_get_default();
134176
g_object_set(settings, "gtk-application-prefer-dark-theme", TRUE, NULL);
135177
g_object_set(settings, "gtk-theme-name", "Adwaita", NULL); // Or custom theme
136178

137-
gtk_widget_show_all(data->window);
179+
gtk_widget_set_visible(data->window, TRUE);
138180
}
139181

140182
int main(int argc, char **argv) {
141-
GtkApplication *app = gtk_application_new("org.blueenvironment.desktop", G_APPLICATION_FLAGS_NONE);
183+
GtkApplication *app = gtk_application_new("org.blueenvironment.desktop", G_APPLICATION_DEFAULT_FLAGS);
142184
DesktopData data = {0};
143-
144185
g_signal_connect(app, "activate", G_CALLBACK(activate), &data);
145-
146186
int status = g_application_run(G_APPLICATION(app), argc, argv);
147187
g_object_unref(app);
148-
149188
if (data.app_list) {
150189
g_object_unref(data.app_list);
151190
}
152-
153191
return status;
154192
}

0 commit comments

Comments
 (0)