From a2c780b8731a62b4f34bda7f4782b76853530df2 Mon Sep 17 00:00:00 2001 From: Rory Fewell Date: Sat, 25 Oct 2025 18:40:05 +0100 Subject: [PATCH] Enhancement: Fixes #340, Shell icon view behaviour support for the desktop --- shared/shell/CMakeLists.txt | 2 + shared/shell/public/browser.h | 19 ++- shared/shell/public/fldropts.h | 32 +++++ shared/shell/public/libapi.h.in | 2 + shared/shell/src/browser.c | 132 ++++++++++++++++++--- shared/shell/src/fldropts.c | 155 ++++++++++++++++++++++++ shared/shelldpa/public/deskwnd.h | 30 ++--- shared/shelldpa/src/deskwnd.c | 37 ++++-- shared/shellext/public/if_view.h | 10 ++ shared/shellext/src/if_view.c | 71 +++++++++++ shell/desktop/CMakeLists.txt | 16 +++ shell/desktop/deps | 3 + shell/desktop/src/application.c | 93 +++++++++++---- shell/desktop/src/application.h | 18 ++- shell/desktop/src/res/appstyles_p.css | 11 ++ shell/desktop/src/res/resources.xml | 6 + shell/desktop/src/settings.c | 5 - shell/desktop/src/settings.h | 18 ++- shell/desktop/src/window.c | 164 +++++++++++++++++++++----- shell/desktop/src/window.h | 23 ++-- shell/explorer/src/application.c | 12 +- shell/explorer/src/window.c | 90 +++++++++----- shell/explorer/src/window.h | 1 + 23 files changed, 790 insertions(+), 160 deletions(-) create mode 100644 shared/shell/public/fldropts.h create mode 100644 shared/shell/src/fldropts.c create mode 100644 shell/desktop/src/res/appstyles_p.css create mode 100644 shell/desktop/src/res/resources.xml diff --git a/shared/shell/CMakeLists.txt b/shared/shell/CMakeLists.txt index 0d68965..0ac9576 100644 --- a/shared/shell/CMakeLists.txt +++ b/shared/shell/CMakeLists.txt @@ -46,6 +46,8 @@ add_library( public/dialog.h src/error.c public/error.h + src/fldropts.c + public/fldropts.h src/fsclipbd.c public/fsclipbd.h src/fsop.c diff --git a/shared/shell/public/browser.h b/shared/shell/public/browser.h index 28a8c58..6ee1fa0 100644 --- a/shared/shell/public/browser.h +++ b/shared/shell/public/browser.h @@ -7,6 +7,8 @@ #include #include +#include "fldropts.h" + // // PUBLIC ENUMS // @@ -16,6 +18,11 @@ typedef enum WINTC_SH_BROWSER_LOAD_FINISHED } WinTCShBrowserLoadEvent; +typedef enum +{ + WINTC_SH_BROWSER_BEHAVIOUR_DONT_USE_SELF_EXE = 0x1 +} WinTCShBrowserBehaviourFlag; + // // GTK OOP BOILERPLATE // @@ -39,7 +46,8 @@ GType wintc_sh_browser_get_type(void) G_GNUC_CONST; // PUBLIC FUNCTIONS // WinTCShBrowser* wintc_sh_browser_new( - WinTCShextHost* shext_host + WinTCShextHost* shext_host, + WinTCShFolderOptions* fldr_opts ); gboolean wintc_sh_browser_activate_item( @@ -56,6 +64,10 @@ WinTCIShextView* wintc_sh_browser_get_current_view( WinTCShBrowser* browser ); +WinTCShBrowserBehaviourFlag wintc_sh_browser_get_behaviour_flags( + WinTCShBrowser* browser +); + void wintc_sh_browser_get_location( WinTCShBrowser* browser, WinTCShextPathInfo* path_info @@ -77,6 +89,11 @@ void wintc_sh_browser_refresh( WinTCShBrowser* browser ); +void wintc_sh_browser_set_behaviour_flags( + WinTCShBrowser* browser, + WinTCShBrowserBehaviourFlag flags +); + gboolean wintc_sh_browser_set_location( WinTCShBrowser* browser, const WinTCShextPathInfo* path_info, diff --git a/shared/shell/public/fldropts.h b/shared/shell/public/fldropts.h new file mode 100644 index 0000000..b578eb2 --- /dev/null +++ b/shared/shell/public/fldropts.h @@ -0,0 +1,32 @@ +#ifndef __SHELL_FLDROPTS_H__ +#define __SHELL_FLDROPTS_H__ + +#include + +// +// GTK OOP BOILERPLATE +// +#define WINTC_TYPE_SH_FOLDER_OPTIONS (wintc_sh_folder_options_get_type()) + +G_DECLARE_FINAL_TYPE( + WinTCShFolderOptions, + wintc_sh_folder_options, + WINTC, + SH_FOLDER_OPTIONS, + GObject +) + +// +// PUBLIC FUNCTIONS +// +WinTCShFolderOptions* wintc_sh_folder_options_new(void); + +gboolean wintc_sh_folder_options_get_browse_in_same_window( + WinTCShFolderOptions* fldr_opts +); +void wintc_sh_folder_options_set_browse_in_same_window( + WinTCShFolderOptions* fldr_opts, + gboolean browse_in_same_window +); + +#endif diff --git a/shared/shell/public/libapi.h.in b/shared/shell/public/libapi.h.in index b0ffb35..f6612c1 100644 --- a/shared/shell/public/libapi.h.in +++ b/shared/shell/public/libapi.h.in @@ -5,7 +5,9 @@ #include "@LIB_HEADER_DIR@/cpl.h" #include "@LIB_HEADER_DIR@/dialog.h" #include "@LIB_HEADER_DIR@/error.h" +#include "@LIB_HEADER_DIR@/fldropts.h" #include "@LIB_HEADER_DIR@/fsclipbd.h" +#include "@LIB_HEADER_DIR@/fsop.h" #include "@LIB_HEADER_DIR@/icnvwbeh.h" #include "@LIB_HEADER_DIR@/nmspace.h" #include "@LIB_HEADER_DIR@/sound.h" diff --git a/shared/shell/src/browser.c b/shared/shell/src/browser.c index 8802b94..743f7aa 100644 --- a/shared/shell/src/browser.c +++ b/shared/shell/src/browser.c @@ -2,16 +2,21 @@ #include #include #include +#include #include #include "../public/browser.h" +#include "../public/fldropts.h" // // PRIVATE ENUMS // enum { - PROP_SHEXT_HOST = 1 + PROP_NULL, + PROP_SHEXT_HOST, + PROP_FOLDER_OPTIONS, + N_PROPERTIES }; enum @@ -23,11 +28,15 @@ enum // // STATIC DATA // -static gint wintc_sh_browser_signals[N_SIGNALS] = { 0 }; +static GParamSpec* wintc_sh_browser_properties[N_PROPERTIES] = { 0 }; +static gint wintc_sh_browser_signals[N_SIGNALS] = { 0 }; // // FORWARD DECLARATIONS // +static void wintc_sh_browser_constructed( + GObject* object +); static void wintc_sh_browser_dispose( GObject* object ); @@ -62,7 +71,12 @@ struct _WinTCShBrowser { GObject __parent__; - WinTCShextHost* shext_host; + WinTCShBrowserBehaviourFlag flags; + + // Shell state + // + WinTCShFolderOptions* fldr_opts; + WinTCShextHost* shext_host; // Browser state // @@ -86,20 +100,32 @@ static void wintc_sh_browser_class_init( { GObjectClass* object_class = G_OBJECT_CLASS(klass); + object_class->constructed = wintc_sh_browser_constructed; object_class->dispose = wintc_sh_browser_dispose; object_class->get_property = wintc_sh_browser_get_property; object_class->set_property = wintc_sh_browser_set_property; - g_object_class_install_property( - object_class, - PROP_SHEXT_HOST, + wintc_sh_browser_properties[PROP_SHEXT_HOST] = g_param_spec_object( "shext-host", "ShextHost", "The shell extension host object to use.", WINTC_TYPE_SHEXT_HOST, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY - ) + ); + wintc_sh_browser_properties[PROP_FOLDER_OPTIONS] = + g_param_spec_object( + "folder-options", + "FolderOptions", + "The folder options object to use.", + WINTC_TYPE_SH_FOLDER_OPTIONS, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY + ); + + g_object_class_install_properties( + object_class, + N_PROPERTIES, + wintc_sh_browser_properties ); wintc_sh_browser_signals[SIGNAL_LOAD_CHANGED] = @@ -124,12 +150,28 @@ static void wintc_sh_browser_init( // // CLASS VIRTUAL METHODS // +static void wintc_sh_browser_constructed( + GObject* object +) +{ + (G_OBJECT_CLASS(wintc_sh_browser_parent_class)) + ->constructed(object); + + WinTCShBrowser* browser = WINTC_SH_BROWSER(object); + + if (!(browser->fldr_opts)) + { + browser->fldr_opts = wintc_sh_folder_options_new(); + } +} + static void wintc_sh_browser_dispose( GObject* object ) { WinTCShBrowser* browser = WINTC_SH_BROWSER(object); + g_clear_object(&(browser->fldr_opts)); g_clear_object(&(browser->shext_host)); g_clear_object(&(browser->current_view)); @@ -163,6 +205,10 @@ static void wintc_sh_browser_set_property( switch (prop_id) { + case PROP_FOLDER_OPTIONS: + browser->fldr_opts = g_value_dup_object(value); + break; + case PROP_SHEXT_HOST: browser->shext_host = g_value_dup_object(value); break; @@ -177,13 +223,15 @@ static void wintc_sh_browser_set_property( // PUBLIC FUNCTIONS // WinTCShBrowser* wintc_sh_browser_new( - WinTCShextHost* shext_host + WinTCShextHost* shext_host, + WinTCShFolderOptions* fldr_opts ) { return WINTC_SH_BROWSER( g_object_new( WINTC_TYPE_SH_BROWSER, - "shext-host", shext_host, + "shext-host", shext_host, + "folder-options", fldr_opts, NULL ) ); @@ -231,12 +279,51 @@ gboolean wintc_sh_browser_activate_item( // Navigate to the path // - gboolean success = - wintc_sh_browser_set_location( - browser, - &path_info, - &local_error - ); + gboolean success; + + if (wintc_sh_folder_options_get_browse_in_same_window(browser->fldr_opts)) + { + success = + wintc_sh_browser_set_location( + browser, + &path_info, + &local_error + ); + } + else + { + gchar* path = wintc_shext_path_info_get_as_single_path(&path_info); + + // Determine what to open with, us or explorer + // + GApplication* app = g_application_get_default(); + + if ( + browser->flags & WINTC_SH_BROWSER_BEHAVIOUR_DONT_USE_SELF_EXE || + !app + ) + { + gchar* cmdline = g_strdup_printf("explorer \"%s\"", path); + + success = + wintc_launch_command( + cmdline, + &local_error + ); + + g_free(cmdline); + } + else + { + GFile* file = g_file_new_for_path(path); + + g_application_open(app, &file, 1, NULL); + + success = TRUE; + } + + g_free(path); + } if (!success) { @@ -261,6 +348,13 @@ gboolean wintc_sh_browser_can_navigate_to_parent( return wintc_ishext_view_has_parent(browser->current_view); } +WinTCShBrowserBehaviourFlag wintc_sh_browser_get_behaviour_flags( + WinTCShBrowser* browser +) +{ + return browser->flags; +} + WinTCIShextView* wintc_sh_browser_get_current_view( WinTCShBrowser* browser ) @@ -333,6 +427,14 @@ void wintc_sh_browser_refresh( wintc_ishext_view_refresh_items(browser->current_view); } +void wintc_sh_browser_set_behaviour_flags( + WinTCShBrowser* browser, + WinTCShBrowserBehaviourFlag flags +) +{ + browser->flags = flags; +} + gboolean wintc_sh_browser_set_location( WinTCShBrowser* browser, const WinTCShextPathInfo* path_info, diff --git a/shared/shell/src/fldropts.c b/shared/shell/src/fldropts.c new file mode 100644 index 0000000..ac868c7 --- /dev/null +++ b/shared/shell/src/fldropts.c @@ -0,0 +1,155 @@ +#include +#include + +#include "../public/fldropts.h" + +// +// PRIVATE ENUMS +// +enum +{ + PROP_NULL, + PROP_BROWSE_IN_SAME_WINDOW, + N_PROPERTIES +}; + +// +// FORWARD DECLARATIONS +// +static void wintc_sh_folder_options_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +); +static void wintc_sh_folder_options_set_property( + GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec +); + +// +// STATIC DATA +// +static GParamSpec* wintc_sh_folder_options_properties[N_PROPERTIES] = { 0 }; + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +struct _WinTCShFolderOptions +{ + GObject __parent__; + + // Settings + // + gboolean browse_in_same_window; +}; + +// +// GTK TYPE DEFINITIONS & CTORS +// +G_DEFINE_TYPE( + WinTCShFolderOptions, + wintc_sh_folder_options, + G_TYPE_OBJECT +) + +static void wintc_sh_folder_options_class_init( + WinTCShFolderOptionsClass* klass +) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = wintc_sh_folder_options_get_property; + object_class->set_property = wintc_sh_folder_options_set_property; + + wintc_sh_folder_options_properties[PROP_BROWSE_IN_SAME_WINDOW] = + g_param_spec_boolean( + "browse-in-same-window", + "BrowseInSameWindow", + "Determines whether to open folders in the same window.", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT + ); + + g_object_class_install_properties( + object_class, + N_PROPERTIES, + wintc_sh_folder_options_properties + ); +} + +static void wintc_sh_folder_options_init( + WINTC_UNUSED(WinTCShFolderOptions* self) +) {} + +// +// CLASS VIRTUAL METHODS +// +static void wintc_sh_folder_options_get_property( + GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec +) +{ + WinTCShFolderOptions* fldr_opts = WINTC_SH_FOLDER_OPTIONS(object); + + switch (prop_id) + { + case PROP_BROWSE_IN_SAME_WINDOW: + g_value_set_boolean(value, fldr_opts->browse_in_same_window); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void wintc_sh_folder_options_set_property( + GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec +) +{ + WinTCShFolderOptions* fldr_opts = WINTC_SH_FOLDER_OPTIONS(object); + + switch (prop_id) + { + case PROP_BROWSE_IN_SAME_WINDOW: + fldr_opts->browse_in_same_window = g_value_get_boolean(value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +// +// PUBLIC FUNCTIONS +// +WinTCShFolderOptions* wintc_sh_folder_options_new(void) +{ + return WINTC_SH_FOLDER_OPTIONS( + g_object_new(WINTC_TYPE_SH_FOLDER_OPTIONS, NULL) + ); +} + +gboolean wintc_sh_folder_options_get_browse_in_same_window( + WinTCShFolderOptions* fldr_opts +) +{ + return fldr_opts->browse_in_same_window; +} + +void wintc_sh_folder_options_set_browse_in_same_window( + WinTCShFolderOptions* fldr_opts, + gboolean browse_in_same_window +) +{ + fldr_opts->browse_in_same_window = browse_in_same_window; +} diff --git a/shared/shelldpa/public/deskwnd.h b/shared/shelldpa/public/deskwnd.h index 65a1284..ca10e2a 100644 --- a/shared/shelldpa/public/deskwnd.h +++ b/shared/shelldpa/public/deskwnd.h @@ -7,25 +7,19 @@ // // GTK OOP BOILERPLATE // -typedef struct _WinTCDpaDesktopWindowClass +#define WINTC_TYPE_DPA_DESKTOP_WINDOW (wintc_dpa_desktop_window_get_type()) + +G_DECLARE_DERIVABLE_TYPE( + WinTCDpaDesktopWindow, + wintc_dpa_desktop_window, + WINTC, + DPA_DESKTOP_WINDOW, + GtkApplicationWindow +) + +struct _WinTCDpaDesktopWindowClass { GtkApplicationWindowClass __parent__; -} WinTCDpaDesktopWindowClass; - -typedef struct _WinTCDpaDesktopWindow -{ - GtkApplicationWindow __parent__; - - GdkMonitor* monitor; -} WinTCDpaDesktopWindow; - -#define WINTC_TYPE_DPA_DESKTOP_WINDOW (wintc_dpa_desktop_window_get_type()) -#define WINTC_DPA_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_DPA_DESKTOP_WINDOW, WinTCDpaDesktopWindow)) -#define WINTC_DPA_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_DPA_DESKTOP_WINDOW, WinTCDpaDesktopWindow)) -#define IS_WINTC_DPA_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_DPA_DESKTOP_WINDOW)) -#define IS_WINTC_DPA_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_DPA_DESKTOP_WINDOW)) -#define WINTC_DPA_DESKTOP_WINDOW_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), WINTC_TYPE_DPA_DESKTOP_WINDOW)) - -GType wintc_dpa_desktop_window_get_type(void) G_GNUC_CONST; +}; #endif diff --git a/shared/shelldpa/src/deskwnd.c b/shared/shelldpa/src/deskwnd.c index 93b5a55..572e6fc 100644 --- a/shared/shelldpa/src/deskwnd.c +++ b/shared/shelldpa/src/deskwnd.c @@ -14,6 +14,14 @@ enum PROP_MONITOR = 1 }; +// +// PRIVATE STRUCTURES +// +typedef struct _WinTCDpaDesktopWindowPrivate +{ + GdkMonitor* monitor; +} WinTCDpaDesktopWindowPrivate; + // // FORWARD DECLARATIONS // @@ -43,10 +51,11 @@ static void window_setup_x11( // // GTK TYPE DEFINITION & CTORS // -G_DEFINE_TYPE( +G_DEFINE_TYPE_WITH_CODE( WinTCDpaDesktopWindow, wintc_dpa_desktop_window, - GTK_TYPE_APPLICATION_WINDOW + GTK_TYPE_APPLICATION_WINDOW, + G_ADD_PRIVATE(WinTCDpaDesktopWindow) ) static void wintc_dpa_desktop_window_class_init( @@ -102,12 +111,15 @@ static void wintc_dpa_desktop_window_get_property( GParamSpec* pspec ) { - WinTCDpaDesktopWindow* wnd = WINTC_DPA_DESKTOP_WINDOW(object); + WinTCDpaDesktopWindowPrivate* priv = + wintc_dpa_desktop_window_get_instance_private( + WINTC_DPA_DESKTOP_WINDOW(object) + ); switch (prop_id) { case PROP_MONITOR: - g_value_set_object(value, wnd->monitor); + g_value_set_object(value, priv->monitor); break; default: @@ -123,12 +135,15 @@ static void wintc_dpa_desktop_window_set_property( GParamSpec* pspec ) { - WinTCDpaDesktopWindow* wnd = WINTC_DPA_DESKTOP_WINDOW(object); + WinTCDpaDesktopWindowPrivate* priv = + wintc_dpa_desktop_window_get_instance_private( + WINTC_DPA_DESKTOP_WINDOW(object) + ); switch (prop_id) { case PROP_MONITOR: - wnd->monitor = g_value_get_object(value); + priv->monitor = g_value_get_object(value); break; default: @@ -144,11 +159,14 @@ static void window_setup_wayland( WinTCDpaDesktopWindow* wnd ) { + WinTCDpaDesktopWindowPrivate* priv = + wintc_dpa_desktop_window_get_instance_private(wnd); + GtkWindow* window = GTK_WINDOW(wnd); p_gtk_layer_init_for_window(window); p_gtk_layer_set_layer(window, GTK_LAYER_SHELL_LAYER_BACKGROUND); - p_gtk_layer_set_monitor(window, wnd->monitor); + p_gtk_layer_set_monitor(window, priv->monitor); for (int edge = 0; edge <= GTK_LAYER_SHELL_EDGE_BOTTOM; edge++) { @@ -163,9 +181,12 @@ static void window_setup_x11( WinTCDpaDesktopWindow* wnd ) { + WinTCDpaDesktopWindowPrivate* priv = + wintc_dpa_desktop_window_get_instance_private(wnd); + GdkRectangle geometry; - gdk_monitor_get_geometry(wnd->monitor, &geometry); + gdk_monitor_get_geometry(priv->monitor, &geometry); gtk_window_move(GTK_WINDOW(wnd), geometry.x, geometry.y); gtk_window_set_type_hint(GTK_WINDOW(wnd), GDK_WINDOW_TYPE_HINT_DESKTOP); diff --git a/shared/shellext/public/if_view.h b/shared/shellext/public/if_view.h index d27f4ff..3da3251 100644 --- a/shared/shellext/public/if_view.h +++ b/shared/shellext/public/if_view.h @@ -145,6 +145,16 @@ void _wintc_ishext_view_refreshing( WinTCIShextView* view ); +// WinTCShextPathInfo methods +// +void wintc_shext_path_info_demangle_uri( + WinTCShextPathInfo* path_info, + const gchar* uri +); +gchar* wintc_shext_path_info_get_as_single_path( + WinTCShextPathInfo* path_info +); + void wintc_shext_path_info_copy( WinTCShextPathInfo* dst, WinTCShextPathInfo* src diff --git a/shared/shellext/src/if_view.c b/shared/shellext/src/if_view.c index e3b8056..04ed4b3 100644 --- a/shared/shellext/src/if_view.c +++ b/shared/shellext/src/if_view.c @@ -258,6 +258,77 @@ void _wintc_ishext_view_refreshing( ); } +void wintc_shext_path_info_demangle_uri( + WinTCShextPathInfo* path_info, + const gchar* uri +) +{ + // + // Fun stuff! There's a bunch of 'special' shell stuff we cram into URIs + // that aren't strictly valid... but they make sense to us -- this function + // 'demangles' the special sauce back into a valid WinTCShextPathInfo + // + // This is useful for handling GApplication::open when you might expect to + // handle a path incoming from WinTC + // + + wintc_shext_path_info_free_data(path_info); + + // + // STEP 1: Check if this is a GUID path + // + const gchar* p_guid_str = strstr(uri, "::%7B"); + + if (p_guid_str) + { + const gchar* p_end_guid = strstr(p_guid_str, "%7D"); + + if (p_end_guid) + { + gchar* guid_escaped = wintc_substr(p_guid_str, p_end_guid + 3); + + path_info->base_path = + g_uri_unescape_string(guid_escaped, NULL); + + g_free(guid_escaped); + } + } + + // + // STEP 2: Check if there's an extended path + // + const gchar* p_ext_delim = strstr(uri, "??"); + + if (p_ext_delim) + { + if (!path_info->base_path) + { + path_info->base_path = + wintc_substr(uri, p_ext_delim); + } + + path_info->extended_path = + wintc_substr(p_ext_delim + 2, NULL); + } +} + +gchar* wintc_shext_path_info_get_as_single_path( + WinTCShextPathInfo* path_info +) +{ + if (path_info->extended_path) + { + return + g_strdup_printf( + "%s??%s", + path_info->base_path, + path_info->extended_path + ); + } + + return g_strdup(path_info->base_path); +} + void wintc_shext_path_info_copy( WinTCShextPathInfo* dst, WinTCShextPathInfo* src diff --git a/shell/desktop/CMakeLists.txt b/shell/desktop/CMakeLists.txt index baf6d39..86f0080 100644 --- a/shell/desktop/CMakeLists.txt +++ b/shell/desktop/CMakeLists.txt @@ -18,19 +18,26 @@ include(GNUInstallDirs) include(../../packaging/cmake-inc/common/CMakeLists.txt) include(../../packaging/cmake-inc/linking/CMakeLists.txt) include(../../packaging/cmake-inc/packaging/CMakeLists.txt) +include(../../packaging/cmake-inc/resources/CMakeLists.txt) wintc_resolve_library(glib-2.0 GLIB) wintc_resolve_library(gtk+-3.0 GTK3) wintc_resolve_library(wintc-comgtk WINTC_COMGTK) wintc_resolve_library(wintc-registry WINTC_REGISTRY) +wintc_resolve_library(wintc-shcommon WINTC_SHCOMMON) +wintc_resolve_library(wintc-shell WINTC_SHELL) wintc_resolve_library(wintc-shelldpa WINTC_SHELLDPA) +wintc_resolve_library(wintc-shellext WINTC_SHELLEXT) wintc_resolve_library(wintc-syscfg WINTC_SYSCFG) +wintc_compile_resources() + add_executable( wintc-desktop src/application.c src/application.h src/main.c + src/resources.c src/settings.c src/settings.h src/window.c @@ -50,7 +57,10 @@ target_include_directories( PRIVATE ${GTK3_INCLUDE_DIRS} PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS} PRIVATE ${WINTC_REGISTRY_INCLUDE_DIRS} + PRIVATE ${WINTC_SHCOMMON_INCLUDE_DIRS} + PRIVATE ${WINTC_SHELL_INCLUDE_DIRS} PRIVATE ${WINTC_SHELLDPA_INCLUDE_DIRS} + PRIVATE ${WINTC_SHELLEXT_INCLUDE_DIRS} PRIVATE ${WINTC_SYSCFG_INCLUDE_DIRS} ) @@ -60,7 +70,10 @@ target_link_directories( PRIVATE ${GTK3_LIBRARY_DIRS} PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS} PRIVATE ${WINTC_REGISTRY_LIBRARY_DIRS} + PRIVATE ${WINTC_SHCOMMON_LIBRARY_DIRS} + PRIVATE ${WINTC_SHELL_LIBRARY_DIRS} PRIVATE ${WINTC_SHELLDPA_LIBRARY_DIRS} + PRIVATE ${WINTC_SHELLEXT_LIBRARY_DIRS} PRIVATE ${WINTC_SYSCFG_LIBRARY_DIRS} ) @@ -70,7 +83,10 @@ target_link_libraries( PRIVATE ${GTK3_LIBRARIES} PRIVATE ${WINTC_COMGTK_LIBRARIES} PRIVATE ${WINTC_REGISTRY_LIBRARIES} + PRIVATE ${WINTC_SHCOMMON_LIBRARIES} + PRIVATE ${WINTC_SHELL_LIBRARIES} PRIVATE ${WINTC_SHELLDPA_LIBRARIES} + PRIVATE ${WINTC_SHELLEXT_LIBRARIES} PRIVATE ${WINTC_SYSCFG_LIBRARIES} ) diff --git a/shell/desktop/deps b/shell/desktop/deps index e3e0864..3560c99 100644 --- a/shell/desktop/deps +++ b/shell/desktop/deps @@ -2,5 +2,8 @@ bt,rt:glib2 bt,rt:gtk3 bt,rt:wintc-comgtk bt,rt:wintc-registry +bt,rt:wintc-shcommon +bt,rt:wintc-shell bt,rt:wintc-shelldpa +bt,rt:wintc-shellext bt,rt:wintc-syscfg diff --git a/shell/desktop/src/application.c b/shell/desktop/src/application.c index 1a3be13..16343b9 100644 --- a/shell/desktop/src/application.c +++ b/shell/desktop/src/application.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include #include "application.h" #include "settings.h" @@ -10,21 +12,21 @@ // // GTK OOP CLASS/INSANCE DEFINITIONS // -struct _WinTCDesktopApplicationClass -{ - GtkApplicationClass __parent__; -}; - struct _WinTCDesktopApplication { GtkApplication __parent__; WinTCDesktopSettings* settings; + WinTCShextHost* shext_host; }; // // FORWARD DECLARATIONS // +static void wintc_desktop_application_dispose( + GObject* object +); + static void wintc_desktop_application_activate( GApplication* application ); @@ -70,6 +72,9 @@ static void wintc_desktop_application_class_init( ) { GApplicationClass* application_class = G_APPLICATION_CLASS(klass); + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + object_class->dispose = wintc_desktop_application_dispose; application_class->activate = wintc_desktop_application_activate; @@ -92,28 +97,21 @@ static void wintc_desktop_application_init( } // -// PUBLIC FUNCTIONS +// CLASS VIRTUAL METHODS // -WinTCDesktopApplication* wintc_desktop_application_new(void) +static void wintc_desktop_application_dispose( + GObject* object +) { - WinTCDesktopApplication* app; + WinTCDesktopApplication* desktop_app = + WINTC_DESKTOP_APPLICATION(object); - g_set_application_name("Desktop"); + g_clear_object(&(desktop_app->shext_host)); - app = - g_object_new( - wintc_desktop_application_get_type(), - "application-id", "uk.co.oddmatics.wintc.desktop", - "flags", G_APPLICATION_HANDLES_COMMAND_LINE, - NULL - ); - - return app; + (G_OBJECT_CLASS(wintc_desktop_application_parent_class)) + ->dispose(object); } -// -// CALLBACKS -// static void wintc_desktop_application_activate( GApplication* application ) @@ -144,7 +142,9 @@ static void wintc_desktop_application_activate( GtkWidget* wnd = wintc_desktop_window_new( desktop_app, monitor, - desktop_app->settings + desktop_app->settings, + gdk_monitor_is_primary(monitor) ? + desktop_app->shext_host : NULL ); gtk_widget_show_all(wnd); @@ -185,6 +185,9 @@ static void wintc_desktop_application_startup( GApplication* application ) { + WinTCDesktopApplication* desktop_app = + WINTC_DESKTOP_APPLICATION(application); + // Chain up for gtk init // G_APPLICATION_CLASS(wintc_desktop_application_parent_class) @@ -197,4 +200,50 @@ static void wintc_desktop_application_startup( g_critical("%s", "Failed to resolve display protocol APIs."); g_application_quit(application); } + + // Install styles + // + GtkCssProvider* css_provider = gtk_css_provider_new(); + + gtk_css_provider_load_from_resource( + css_provider, + "/uk/oddmatics/wintc/desktop/appstyles_p.css" + ); + + gtk_style_context_add_provider_for_screen( + gdk_screen_get_default(), + GTK_STYLE_PROVIDER(css_provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + ); + + // Init shext host + // + desktop_app->shext_host = wintc_shext_host_new(); + + wintc_sh_init_builtin_extensions(desktop_app->shext_host); + wintc_shext_host_load_extensions( + desktop_app->shext_host, + WINTC_SHEXT_LOAD_DEFAULT, + NULL + ); +} + +// +// PUBLIC MEHTODS +// +WinTCDesktopApplication* wintc_desktop_application_new(void) +{ + WinTCDesktopApplication* app; + + g_set_application_name("Desktop"); + + app = + g_object_new( + wintc_desktop_application_get_type(), + "application-id", "uk.co.oddmatics.wintc.desktop", + "flags", G_APPLICATION_HANDLES_COMMAND_LINE, + NULL + ); + + return app; } diff --git a/shell/desktop/src/application.h b/shell/desktop/src/application.h index 57dde99..286dcfe 100644 --- a/shell/desktop/src/application.h +++ b/shell/desktop/src/application.h @@ -7,17 +7,15 @@ // // GTK OOP BOILERPLATE // -typedef struct _WinTCDesktopApplicationClass WinTCDesktopApplicationClass; -typedef struct _WinTCDesktopApplication WinTCDesktopApplication; +#define WINTC_TYPE_DESKTOP_APPLICATION (wintc_desktop_application_get_type()) -#define WINTC_TYPE_DESKTOP_APPLICATION (wintc_desktop_application_get_type()) -#define WINTC_DESKTOP_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_DESKTOP_APPLICATION, WinTCDesktopApplication)) -#define WINTC_DESKTOP_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_DESKTOP_APPLICATION, WinTCDesktopApplicationClass)) -#define IS_WINTC_DESKTOP_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_DESKTOP_APPLICATION)) -#define IS_WINTC_DESKTOP_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_DESKTOP_APPLICATION)) -#define WINTC_DESKTOP_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_DESKTOP_APPLICATION, WinTCDesktopApplicationClass)) - -GType wintc_desktop_application_get_type(void) G_GNUC_CONST; +G_DECLARE_FINAL_TYPE( + WinTCDesktopApplication, + wintc_desktop_application, + WINTC, + DESKTOP_APPLICATION, + GtkApplication +) // // PUBLIC FUNCTIONS diff --git a/shell/desktop/src/res/appstyles_p.css b/shell/desktop/src/res/appstyles_p.css new file mode 100644 index 0000000..474de42 --- /dev/null +++ b/shell/desktop/src/res/appstyles_p.css @@ -0,0 +1,11 @@ +/** + * APPLICATION PRIORITY STYLES -- DO NOT OVERUSE!! + **/ + +/** + * Default styles for the icon view + */ +iconview +{ + background: transparent; +} diff --git a/shell/desktop/src/res/resources.xml b/shell/desktop/src/res/resources.xml new file mode 100644 index 0000000..ebed3e4 --- /dev/null +++ b/shell/desktop/src/res/resources.xml @@ -0,0 +1,6 @@ + + + + appstyles_p.css + + diff --git a/shell/desktop/src/settings.c b/shell/desktop/src/settings.c index e2c0d16..a25b520 100644 --- a/shell/desktop/src/settings.c +++ b/shell/desktop/src/settings.c @@ -18,11 +18,6 @@ enum // // GTK OOP CLASS/INSTANCE DEFINITIONS // -struct _WinTCDesktopSettingsClass -{ - GObjectClass __parent__; -}; - struct _WinTCDesktopSettings { GObject __parent__; diff --git a/shell/desktop/src/settings.h b/shell/desktop/src/settings.h index 6440073..a60b149 100644 --- a/shell/desktop/src/settings.h +++ b/shell/desktop/src/settings.h @@ -6,17 +6,15 @@ // // GTK OOP BOILERPLATE // -typedef struct _WinTCDesktopSettingsClass WinTCDesktopSettingsClass; -typedef struct _WinTCDesktopSettings WinTCDesktopSettings; +#define WINTC_TYPE_DESKTOP_SETTINGS (wintc_desktop_settings_get_type()) -#define WINTC_TYPE_DESKTOP_SETTINGS (wintc_desktop_settings_get_type()) -#define WINTC_DESKTOP_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_DESKTOP_SETTINGS, WinTCDesktopSettings)) -#define WINTC_DESKTOP_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_DESKTOP_SETTINGS, WinTCDesktopSettingsClass)) -#define IS_WINTC_DESKTOP_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_DESKTOP_SETTINGS)) -#define IS_WINTC_DESKTOP_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_DESKTOP_SETTINGS)) -#define WINTC_DESKTOP_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_DESKTOP_SETTINGS, WinTCDesktopSettingsClass)) - -GType wintc_desktop_settings_get_type(void) G_GNUC_CONST; +G_DECLARE_FINAL_TYPE( + WinTCDesktopSettings, + wintc_desktop_settings, + WINTC, + DESKTOP_SETTINGS, + GObject +) // // PUBLIC FUNCTIONS diff --git a/shell/desktop/src/window.c b/shell/desktop/src/window.c index 9d4f6ef..0d67bc4 100644 --- a/shell/desktop/src/window.c +++ b/shell/desktop/src/window.c @@ -3,7 +3,10 @@ #include #include #include +#include +#include #include +#include #include #include "application.h" @@ -15,29 +18,10 @@ // enum { - PROP_SETTINGS = 1 -}; - -// -// GTK OOP CLASS/INSTANCE DEFINITIONS -// -struct _WinTCDesktopWindowClass -{ - WinTCDpaDesktopWindowClass __parent__; -}; - -struct _WinTCDesktopWindow -{ - WinTCDpaDesktopWindow __parent__; - - // Drawing-related - // - GdkPixbuf* pixbuf_wallpaper; - cairo_surface_t* surface_wallpaper; - - // State - // - WinTCDesktopSettings* settings; + PROP_NULL, + PROP_SETTINGS, + PROP_SHEXT_HOST, + N_PROPERTIES }; // @@ -82,6 +66,39 @@ static void on_settings_notify_wallpaper_style( gpointer user_data ); +// +// STATIC DATA +// +static GParamSpec* wintc_desktop_window_properties[N_PROPERTIES] = { 0 }; + +// +// GTK OOP CLASS/INSTANCE DEFINITIONS +// +struct _WinTCDesktopWindow +{ + WinTCDpaDesktopWindow __parent__; + + // UI + // + GtkWidget* iconview_browser; + WinTCShIconViewBehaviour* behaviour_icons; + + // Shell stuff + // + WinTCShBrowser* browser; + WinTCShFolderOptions* fldr_opts; + WinTCShextHost* shext_host; + + // Drawing-related + // + GdkPixbuf* pixbuf_wallpaper; + cairo_surface_t* surface_wallpaper; + + // State + // + WinTCDesktopSettings* settings; +}; + // // GTK TYPE DEFINITION & CTORS // @@ -104,16 +121,27 @@ static void wintc_desktop_window_class_init( widget_class->draw = wintc_desktop_window_draw; - g_object_class_install_property( - object_class, - PROP_SETTINGS, + wintc_desktop_window_properties[PROP_SETTINGS] = g_param_spec_object( "settings", "Settings", "The shared desktop settings", WINTC_TYPE_DESKTOP_SETTINGS, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY - ) + ); + wintc_desktop_window_properties[PROP_SHEXT_HOST] = + g_param_spec_object( + "shext-host", + "ShextHost", + "The shell extension host object to use.", + WINTC_TYPE_SHEXT_HOST, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY + ); + + g_object_class_install_properties( + object_class, + N_PROPERTIES, + wintc_desktop_window_properties ); } @@ -121,6 +149,13 @@ static void wintc_desktop_window_init( WinTCDesktopWindow* self ) { + self->iconview_browser = gtk_icon_view_new(); + + gtk_container_add( + GTK_CONTAINER(self), + self->iconview_browser + ); + g_signal_connect( self, "map-event", @@ -138,6 +173,52 @@ static void wintc_desktop_window_constructed( { WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object); + // If we have a shext host, then we can set up the browser + // + if (wnd->shext_host) + { + wnd->fldr_opts = wintc_sh_folder_options_new(); + + wintc_sh_folder_options_set_browse_in_same_window( + wnd->fldr_opts, + FALSE + ); + + wnd->browser = + wintc_sh_browser_new( + wnd->shext_host, + wnd->fldr_opts + ); + + wintc_sh_browser_set_behaviour_flags( + wnd->browser, + WINTC_SH_BROWSER_BEHAVIOUR_DONT_USE_SELF_EXE + ); + + wnd->behaviour_icons = + wintc_sh_icon_view_behaviour_new( + GTK_ICON_VIEW(wnd->iconview_browser), + wnd->browser + ); + + // Navigate to desktop + // + WinTCShextPathInfo path_info = { 0 }; + + path_info.base_path = + g_strdup( + wintc_sh_get_place_path(WINTC_SH_PLACE_DESKTOP) + ); + + wintc_sh_browser_set_location( + wnd->browser, + &path_info, + NULL + ); + + wintc_shext_path_info_free_data(&path_info); + } + g_signal_connect( wnd->settings, "notify::pixbuf-wallpaper", @@ -160,6 +241,11 @@ static void wintc_desktop_window_dispose( { WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object); + g_clear_object(&(wnd->behaviour_icons)); + g_clear_object(&(wnd->browser)); + g_clear_object(&(wnd->fldr_opts)); + g_clear_object(&(wnd->shext_host)); + if (wnd->surface_wallpaper) { cairo_surface_destroy(g_steal_pointer(&(wnd->surface_wallpaper))); @@ -184,6 +270,10 @@ static void wintc_desktop_window_set_property( wnd->settings = g_value_get_object(value); break; + case PROP_SHEXT_HOST: + wnd->shext_host = g_value_dup_object(value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -195,8 +285,7 @@ static gboolean wintc_desktop_window_draw( cairo_t* cr ) { - WinTCDpaDesktopWindow* dpa_wnd = WINTC_DPA_DESKTOP_WINDOW(widget); - WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(widget); + WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(widget); gint wnd_w = gtk_widget_get_allocated_width(widget); gint wnd_h = gtk_widget_get_allocated_height(widget); @@ -259,7 +348,11 @@ static gboolean wintc_desktop_window_draw( // Rough watermark drawing // - if (gdk_monitor_is_primary(dpa_wnd->monitor)) + // NOTE: We assume that we're the primary monitor if we have a shext host + // passed in -- this is quite cheeky to do, until we properly deal + // with primary monitor business on Waheyland + // + if (wnd->shext_host) { static gchar* s_tag = NULL; @@ -324,6 +417,13 @@ static gboolean wintc_desktop_window_draw( cairo_show_text(cr, "Windows 'Total Conversion'"); } + // Draw the icon view + // + gtk_widget_draw(wnd->iconview_browser, cr); + +// (GTK_WIDGET_CLASS(wintc_desktop_window_parent_class)) +// ->draw(widget, cr); + return FALSE; } @@ -333,7 +433,8 @@ static gboolean wintc_desktop_window_draw( GtkWidget* wintc_desktop_window_new( WinTCDesktopApplication* app, GdkMonitor* monitor, - WinTCDesktopSettings* settings + WinTCDesktopSettings* settings, + WinTCShextHost* shext_host ) { return GTK_WIDGET( @@ -345,6 +446,7 @@ GtkWidget* wintc_desktop_window_new( "monitor", monitor, "resizable", FALSE, "settings", settings, + "shext-host", shext_host, NULL ) ); diff --git a/shell/desktop/src/window.h b/shell/desktop/src/window.h index 6df1d07..0ba1f66 100644 --- a/shell/desktop/src/window.h +++ b/shell/desktop/src/window.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include "application.h" #include "settings.h" @@ -10,17 +12,15 @@ // // GTK OOP BOILERPLATE // -typedef struct _WinTCDesktopWindowClass WinTCDesktopWindowClass; -typedef struct _WinTCDesktopWindow WinTCDesktopWindow; +#define WINTC_TYPE_DESKTOP_WINDOW (wintc_desktop_window_get_type()) -#define WINTC_TYPE_DESKTOP_WINDOW (wintc_desktop_window_get_type()) -#define WINTC_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_DESKTOP_WINDOW, WinTCDesktopWindow)) -#define WINTC_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_DESKTOP_WINDOW, WinTCDesktopWindow)) -#define IS_WINTC_DESKTOP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_DESKTOP_WINDOW)) -#define IS_WINTC_DESKTOP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_DESKTOP_WINDOW)) -#define WINTC_DESKTOP_WINDOW_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), WINTC_TYPE_DESKTOP_WINDOW)) - -GType wintc_desktop_window_get_type(void) G_GNUC_CONST; +G_DECLARE_FINAL_TYPE( + WinTCDesktopWindow, + wintc_desktop_window, + WINTC, + DESKTOP_WINDOW, + WinTCDpaDesktopWindow +) // // PUBLIC FUNCTIONS @@ -28,7 +28,8 @@ GType wintc_desktop_window_get_type(void) G_GNUC_CONST; GtkWidget* wintc_desktop_window_new( WinTCDesktopApplication* app, GdkMonitor* monitor, - WinTCDesktopSettings* settings + WinTCDesktopSettings* settings, + WinTCShextHost* shext_host ); #endif diff --git a/shell/explorer/src/application.c b/shell/explorer/src/application.c index cdb1f6f..35cebe2 100644 --- a/shell/explorer/src/application.c +++ b/shell/explorer/src/application.c @@ -24,8 +24,9 @@ struct _WinTCExplorerApplication // Application state // - WinTCExplorerLoader* exp_loader; - WinTCShextHost* shext_host; + WinTCExplorerLoader* exp_loader; + WinTCShFolderOptions* fldr_opts; + WinTCShextHost* shext_host; }; // @@ -132,6 +133,7 @@ static void wintc_explorer_application_dispose( WINTC_EXPLORER_APPLICATION(object); g_clear_object(&(explorer_app->shext_host)); + g_clear_object(&(explorer_app->fldr_opts)); g_clear_object(&(explorer_app->exp_loader)); (G_OBJECT_CLASS(wintc_explorer_application_parent_class)) @@ -149,6 +151,7 @@ static void wintc_explorer_application_activate( wintc_explorer_window_new( explorer_app, explorer_app->shext_host, + explorer_app->fldr_opts, explorer_app->exp_loader, NULL ); @@ -237,6 +240,7 @@ static void wintc_explorer_application_open( GtkWidget* wnd = wintc_explorer_window_new( explorer_app, explorer_app->shext_host, + explorer_app->fldr_opts, explorer_app->exp_loader, uri ); @@ -279,6 +283,10 @@ static void wintc_explorer_application_startup( WINTC_SHEXT_LOAD_DEFAULT, NULL ); + + // Create folder options + // + explorer_app->fldr_opts = wintc_sh_folder_options_new(); } // diff --git a/shell/explorer/src/window.c b/shell/explorer/src/window.c index 6c4b401..dd6cbc5 100644 --- a/shell/explorer/src/window.c +++ b/shell/explorer/src/window.c @@ -23,10 +23,13 @@ // enum { - PROP_SHEXT_HOST = 1, + PROP_NULL, + PROP_SHEXT_HOST, + PROP_FOLDER_OPTIONS, PROP_EXPLORER_LOADER, PROP_INITIAL_PATH, - PROP_ACTIVE_SIDEBAR + PROP_ACTIVE_SIDEBAR, + N_PROPERTIES }; enum @@ -150,7 +153,8 @@ static GActionEntry s_window_actions[] = { } }; -static gint wintc_explorer_window_signals[N_SIGNALS] = { 0 }; +static GParamSpec* wintc_explorer_window_properties[N_PROPERTIES] = { 0 }; +static gint wintc_explorer_window_signals[N_SIGNALS] = { 0 }; // // GTK OOP CLASS/INSTANCE DEFINITIONS @@ -166,8 +170,9 @@ struct _WinTCExplorerWindow // Shell stuff // - WinTCShBrowser* browser; - WinTCShextHost* shext_host; + WinTCShBrowser* browser; + WinTCShFolderOptions* fldr_opts; + WinTCShextHost* shext_host; // State // @@ -223,50 +228,51 @@ static void wintc_explorer_window_class_init( object_class->get_property = wintc_explorer_window_get_property; object_class->set_property = wintc_explorer_window_set_property; - g_object_class_install_property( - object_class, - PROP_SHEXT_HOST, + wintc_explorer_window_properties[PROP_SHEXT_HOST] = g_param_spec_object( "shext-host", "ShextHost", "The shell extension host object to use.", WINTC_TYPE_SHEXT_HOST, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY - ) - ); - g_object_class_install_property( - object_class, - PROP_EXPLORER_LOADER, + ); + wintc_explorer_window_properties[PROP_FOLDER_OPTIONS] = + g_param_spec_object( + "folder-options", + "FolderOptions", + "The folder options object to use", + WINTC_TYPE_SH_FOLDER_OPTIONS, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY + ); + wintc_explorer_window_properties[PROP_EXPLORER_LOADER] = g_param_spec_object( "explorer-loader", "ExplorerLoader", "The explorer sidebar and toolbar loader host object to use.", WINTC_TYPE_EXPLORER_LOADER, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY - ) - ); - g_object_class_install_property( - object_class, - PROP_INITIAL_PATH, + ); + wintc_explorer_window_properties[PROP_INITIAL_PATH] = g_param_spec_string( "initial-path", "InitialPath", "The initial path for the window to open.", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY - ) - ); - - g_object_class_install_property( - object_class, - PROP_ACTIVE_SIDEBAR, + ); + wintc_explorer_window_properties[PROP_ACTIVE_SIDEBAR] = g_param_spec_string( "active-sidebar", "ActiveSidebar", "The currently active sidebar.", NULL, G_PARAM_READWRITE - ) + ); + + g_object_class_install_properties( + object_class, + N_PROPERTIES, + wintc_explorer_window_properties ); wintc_explorer_window_signals[SIGNAL_LOCATION_CHANGED] = @@ -414,6 +420,11 @@ static void wintc_explorer_window_constructed( return; } + if (!wnd->fldr_opts) + { + wnd->fldr_opts = wintc_sh_folder_options_new(); + } + // Handle initial path // if (!wnd->initial_path) @@ -449,6 +460,7 @@ static void wintc_explorer_window_dispose( g_clear_object(&(wnd->behaviour_icons)); g_clear_object(&(wnd->browser)); + g_clear_object(&(wnd->fldr_opts)); g_clear_object(&(wnd->shext_host)); g_clear_object(&(wnd->iconview_browser)); @@ -512,13 +524,31 @@ static void wintc_explorer_window_set_property( wnd->shext_host = g_value_dup_object(value); break; + case PROP_FOLDER_OPTIONS: + wnd->fldr_opts = g_value_dup_object(value); + break; + case PROP_EXPLORER_LOADER: wnd->loader = g_value_dup_object(value); break; case PROP_INITIAL_PATH: - wnd->initial_path = g_value_dup_string(value); + { + // FIXME: We don't handle extended paths yet! + // + WinTCShextPathInfo path_info; + + wintc_shext_path_info_demangle_uri( + &path_info, + g_value_get_string(value) + ); + + wnd->initial_path = path_info.base_path; + path_info.base_path = NULL; + + wintc_shext_path_info_free_data(&path_info); break; + } case PROP_ACTIVE_SIDEBAR: // Check if this is a nothing burger @@ -599,6 +629,7 @@ static void wintc_explorer_window_set_property( GtkWidget* wintc_explorer_window_new( WinTCExplorerApplication* app, WinTCShextHost* shext_host, + WinTCShFolderOptions* fldr_opts, WinTCExplorerLoader* loader, const gchar* initial_path ) @@ -608,6 +639,7 @@ GtkWidget* wintc_explorer_window_new( WINTC_TYPE_EXPLORER_WINDOW, "application", GTK_APPLICATION(app), "shext-host", shext_host, + "folder-options", fldr_opts, "explorer-loader", loader, "initial-path", initial_path, NULL @@ -947,7 +979,11 @@ static void switch_mode_to( // Set up shell browser // - wnd->browser = wintc_sh_browser_new(wnd->shext_host); + wnd->browser = + wintc_sh_browser_new( + wnd->shext_host, + wnd->fldr_opts + ); g_signal_connect( wnd->browser, diff --git a/shell/explorer/src/window.h b/shell/explorer/src/window.h index f40e368..d5e9294 100644 --- a/shell/explorer/src/window.h +++ b/shell/explorer/src/window.h @@ -40,6 +40,7 @@ GType wintc_explorer_window_get_type(void) G_GNUC_CONST; GtkWidget* wintc_explorer_window_new( WinTCExplorerApplication* app, WinTCShextHost* shext_host, + WinTCShFolderOptions* fldr_opts, WinTCExplorerLoader* loader, const gchar* initial_path );