Enhancement: Fixes #308, Build - enable asan

This commit is contained in:
Rory Fewell
2024-06-05 06:46:08 +01:00
parent afb3922342
commit da7a18c76b
32 changed files with 960 additions and 357 deletions

View File

@@ -27,6 +27,8 @@ wintc_resolve_library(wintc-registry WINTC_REGISTRY)
add_executable(
wintc-regsvc
src/application.c
src/application.h
src/backend.c
src/backend.h
src/main.c

View File

@@ -0,0 +1,497 @@
#include <glib.h>
#include <gtk/gtk.h>
#include <wintc/comgtk.h>
#include <wintc/registry.h>
#include "application.h"
#include "backend.h"
//
// GTK OOP CLASS/INSTANCE DEFINITIONS
//
struct _WinTCRegSvcApplicationClass
{
GtkApplicationClass __parent__;
};
struct _WinTCRegSvcApplication
{
GtkApplication __parent__;
};
//
// FORWARD DECLARATIONS
//
static void wintc_regsvc_application_activate(
GApplication* application
);
static gint wintc_regsvc_application_command_line(
GApplication* application,
GApplicationCommandLine* command_line
);
static gint wintc_regsvc_application_handle_local_options(
GApplication* application,
GVariantDict* options
);
static void wintc_regsvc_application_shutdown(
GApplication* application
);
static void on_name_acquired(
GDBusConnection* connection,
const gchar* name,
gpointer user_data
);
static gboolean on_handle_create_key(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
gpointer user_data
);
static gboolean on_handle_get_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
WinTCRegistryValueType value_type,
gpointer user_data
);
static gboolean on_handle_set_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
GVariant* value_data,
gboolean silent,
gpointer user_data
);
//
// STATIC DATA
//
static const GOptionEntry S_OPTIONS[] = {
{
"quit",
'q',
G_OPTION_FLAG_NONE,
G_OPTION_ARG_NONE,
NULL,
"Quit a running Windows registry instance.",
NULL
},
{ 0 }
};
//
// GTK TYPE DEFINITIONS & CTORS
//
G_DEFINE_TYPE(
WinTCRegSvcApplication,
wintc_regsvc_application,
GTK_TYPE_APPLICATION
)
static void wintc_regsvc_application_class_init(
WinTCRegSvcApplicationClass* klass
)
{
GApplicationClass* application_class = G_APPLICATION_CLASS(klass);
application_class->activate =
wintc_regsvc_application_activate;
application_class->command_line =
wintc_regsvc_application_command_line;
application_class->handle_local_options =
wintc_regsvc_application_handle_local_options;
application_class->shutdown =
wintc_regsvc_application_shutdown;
}
static void wintc_regsvc_application_init(
WinTCRegSvcApplication* self
)
{
g_application_add_main_option_entries(
G_APPLICATION(self),
S_OPTIONS
);
}
//
// CLASS VIRTUAL METHODS
//
static void wintc_regsvc_application_activate(
GApplication* application
)
{
static gboolean started = FALSE;
if (started)
{
return;
}
started = TRUE;
// Init
//
if (!backend_init())
{
g_critical("%s", "Failed to initialize backend.");
g_application_quit(application);
return;
}
WINTC_LOG_DEBUG("regsvc: hosting name %s", "uk.oddmatics.wintc.registry");
g_bus_own_name(
G_BUS_TYPE_SESSION,
"uk.oddmatics.wintc.registry",
G_BUS_NAME_OWNER_FLAGS_NONE,
NULL,
on_name_acquired,
NULL,
application,
NULL
);
// Hold open since we have no toplevels
//
g_application_hold(application);
}
static gint wintc_regsvc_application_command_line(
GApplication* application,
GApplicationCommandLine* command_line
)
{
GVariantDict* options =
g_application_command_line_get_options_dict(command_line);
// Just check for --quit
//
if (g_variant_dict_contains(options, "quit"))
{
WINTC_LOG_DEBUG("%s", "regsvc: --quit recieved, exiting...");
g_application_release(application);
return 0;
}
g_application_activate(application);
return 0;
}
static gint wintc_regsvc_application_handle_local_options(
WINTC_UNUSED(GApplication* application),
WINTC_UNUSED(GVariantDict* options)
)
{
// Stub
return -1;
}
static void wintc_regsvc_application_shutdown(
GApplication* application
)
{
backend_close();
(G_APPLICATION_CLASS(wintc_regsvc_application_parent_class))
->shutdown(application);
}
//
// PUBLIC FUNCTIONS
//
WinTCRegSvcApplication* wintc_regsvc_application_new(void)
{
return WINTC_REGSVC_APPLICATION(
g_object_new(
wintc_regsvc_application_get_type(),
"application-id", "uk.co.oddmatics.wintc.regsvc",
"flags", G_APPLICATION_HANDLES_COMMAND_LINE,
NULL
)
);
}
//
// CALLBACKS
//
static void on_name_acquired(
GDBusConnection* connection,
WINTC_UNUSED(const gchar* name),
gpointer user_data
)
{
GError* error = NULL;
ZWinRegistryGDBUS* reg_dbus = zwin_registry_gdbus_skeleton_new();
g_signal_connect(
reg_dbus,
"handle-create-key",
G_CALLBACK(on_handle_create_key),
NULL
);
g_signal_connect(
reg_dbus,
"handle-get-key-value",
G_CALLBACK(on_handle_get_key_value),
NULL
);
g_signal_connect(
reg_dbus,
"handle-set-key-value",
G_CALLBACK(on_handle_set_key_value),
NULL
);
if (
!g_dbus_interface_skeleton_export(
G_DBUS_INTERFACE_SKELETON(reg_dbus),
connection,
"/uk/oddmatics/wintc/registry/GDBUS",
&error
)
)
{
wintc_log_error_and_clear(&error);
g_application_quit(G_APPLICATION(user_data));
}
}
static gboolean on_handle_create_key(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG("regsvc: received create key request for %s", key_path);
// Very simply just try creating the key
//
gboolean success = backend_create_key(key_path);
zwin_registry_gdbus_complete_create_key(
reg_dbus,
invocation,
success ? 1 : 0
);
return TRUE;
}
static gboolean on_handle_get_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
WinTCRegistryValueType value_type,
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG(
"regsvc: received get key value for %s->%s",
key_path,
value_name
);
// Wrap up in a variant
//
gboolean success = FALSE;
gint value_data_int = 0;
gint64 value_data_int64 = 0;
gchar* value_data_str = NULL;
GVariant* variant_ret = NULL;
switch (value_type)
{
case WINTC_REG_DWORD:
success =
backend_get_key_value(
key_path,
value_name,
WINTC_REG_DWORD,
&value_data_int
);
if (success)
{
variant_ret =
g_variant_new(
"v",
g_variant_new_int32(value_data_int)
);
}
break;
case WINTC_REG_QWORD:
success =
backend_get_key_value(
key_path,
value_name,
WINTC_REG_QWORD,
&value_data_int64
);
if (success)
{
variant_ret =
g_variant_new(
"v",
g_variant_new_int64(value_data_int64)
);
}
break;
case WINTC_REG_SZ:
success =
backend_get_key_value(
key_path,
value_name,
WINTC_REG_SZ,
&value_data_str
);
if (success)
{
variant_ret =
g_variant_new(
"v",
g_variant_new_string(value_data_str)
);
g_free(value_data_str);
}
break;
default:
g_critical("regsvc: unknown type %d", value_type);
success = FALSE;
break;
}
if (!success)
{
// Cannot use maybe-type variants because they're not supported by
// DBus/GDBus, so just respond with 0 - libwintc-registry will discard
// the variant regardless if the result code is 0 so we could respond
// with any variant here and be fine
//
variant_ret = g_variant_new("v", g_variant_new_int32(0));
}
zwin_registry_gdbus_complete_get_key_value(
reg_dbus,
invocation,
variant_ret,
success ? 1 : 0
);
return TRUE;
}
static gboolean on_handle_set_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
GVariant* value_data,
gboolean silent,
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG(
"regsvc: received set key value for %s->%s",
key_path,
value_name
);
// The variant incoming determines the type etc.
//
GVariant* inner = g_variant_get_variant(value_data);
gboolean success = FALSE;
WinTCRegistryValueType value_type = wintc_registry_get_type_for_variant(
inner
);
gint value_data_int = 0;
gint64 value_data_int64 = 0;
gchar* value_data_str = NULL;
switch (value_type)
{
case WINTC_REG_DWORD:
value_data_int = g_variant_get_int32(inner);
success =
backend_set_key_value(
key_path,
value_name,
WINTC_REG_DWORD,
&value_data_int
);
break;
case WINTC_REG_QWORD:
value_data_int64 = g_variant_get_int64(inner);
success =
backend_set_key_value(
key_path,
value_name,
WINTC_REG_QWORD,
&value_data_int64
);
break;
case WINTC_REG_SZ:
value_data_str = g_variant_dup_string(inner, NULL);
success =
backend_set_key_value(
key_path,
value_name,
WINTC_REG_SZ,
&value_data_str
);
g_free(value_data_str);
break;
default:
g_critical("%s", "regsvc: set key unknown variant type");
break;
}
zwin_registry_gdbus_complete_set_key_value(
reg_dbus,
invocation,
success ? 1 : 0
);
if (success & !silent)
{
g_signal_emit_by_name(
reg_dbus,
"key-value-changed",
key_path,
value_name,
value_data,
NULL
);
}
g_variant_unref(inner);
return TRUE;
}

View File

@@ -0,0 +1,27 @@
#ifndef __APPLICATION_H__
#define __APPLICATION_H__
#include <glib.h>
#include <gtk/gtk.h>
//
// GTK OOP BOILERPLATE
//
typedef struct _WinTCRegSvcApplicationClass WinTCRegSvcApplicationClass;
typedef struct _WinTCRegSvcApplication WinTCRegSvcApplication;
#define WINTC_TYPE_REGSVC_APPLICATION (wintc_regsvc_application_get_type())
#define WINTC_REGSVC_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_REGSVC_APPLICATION, WinTCRegSvcApplication))
#define WINTC_REGSVC_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_REGSVC_APPLICATION, WinTCRegSvcApplicationClass))
#define IS_WINTC_REGSVC_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_REGSVC_APPLICATION))
#define IS_WINTC_REGSVC_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_REGSVC_APPLICATION))
#define WINTC_REGSVC_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_REGSVC_APPLICATION, WinTCRegSvcApplicationClass))
GType wintc_regsvc_application_get_type(void) G_GNUC_CONST;
//
// PUBLIC FUNCTIONS
//
WinTCRegSvcApplication* wintc_regsvc_application_new(void);
#endif

View File

@@ -4,88 +4,38 @@
#include <wintc/comgtk.h>
#include <wintc/registry.h>
#include "application.h"
#include "backend.h"
//
// STATIC DATA
//
static GMainLoop* s_main_loop = NULL;
//
// FORWARD DECLARATIONS
//
static void on_name_acquired(
GDBusConnection* connection,
const gchar* name,
gpointer user_data
);
static gboolean on_handle_create_key(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
gpointer user_data
);
static gboolean on_handle_get_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
WinTCRegistryValueType value_type,
gpointer user_data
);
static gboolean on_handle_set_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
GVariant* value_data,
gboolean silent,
gpointer user_data
);
static gboolean on_sigterm(
gpointer user_data
);
//
// STATIC DATA
//
static GApplication* s_app = NULL;
//
// ENTRY POINT
//
int main(
WINTC_UNUSED(int argc),
WINTC_UNUSED(char* argv[])
int argc,
char* argv[]
)
{
s_main_loop = g_main_loop_new(NULL, FALSE);
if (!backend_init())
{
return 1;
}
WINTC_LOG_DEBUG("regsvc: hosting name %s", "uk.oddmatics.wintc.registry");
g_bus_own_name(
G_BUS_TYPE_SESSION,
"uk.oddmatics.wintc.registry",
G_BUS_NAME_OWNER_FLAGS_NONE,
NULL,
on_name_acquired,
NULL,
NULL,
NULL
);
s_app = G_APPLICATION(wintc_regsvc_application_new());
g_unix_signal_add(
SIGTERM,
on_sigterm,
NULL
);
g_main_loop_run(s_main_loop);
g_main_loop_unref(s_main_loop);
backend_close();
g_application_run(s_app, argc, argv);
return 0;
}
@@ -93,284 +43,13 @@ int main(
//
// CALLBACKS
//
static void on_name_acquired(
GDBusConnection* connection,
WINTC_UNUSED(const gchar* name),
WINTC_UNUSED(gpointer user_data)
)
{
GError* error = NULL;
ZWinRegistryGDBUS* reg_dbus = zwin_registry_gdbus_skeleton_new();
g_signal_connect(
reg_dbus,
"handle-create-key",
G_CALLBACK(on_handle_create_key),
NULL
);
g_signal_connect(
reg_dbus,
"handle-get-key-value",
G_CALLBACK(on_handle_get_key_value),
NULL
);
g_signal_connect(
reg_dbus,
"handle-set-key-value",
G_CALLBACK(on_handle_set_key_value),
NULL
);
if (
!g_dbus_interface_skeleton_export(
G_DBUS_INTERFACE_SKELETON(reg_dbus),
connection,
"/uk/oddmatics/wintc/registry/GDBUS",
&error
)
)
{
wintc_log_error_and_clear(&error);
}
}
static gboolean on_handle_create_key(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG("regsvc: received create key request for %s", key_path);
// Very simply just try creating the key
//
gboolean success = backend_create_key(key_path);
zwin_registry_gdbus_complete_create_key(
reg_dbus,
invocation,
success ? 1 : 0
);
return TRUE;
}
static gboolean on_handle_get_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
WinTCRegistryValueType value_type,
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG(
"regsvc: received get key value for %s->%s",
key_path,
value_name
);
// Wrap up in a variant
//
gboolean success = FALSE;
gint value_data_int = 0;
gint64 value_data_int64 = 0;
gchar* value_data_str = NULL;
GVariant* variant_ret = NULL;
switch (value_type)
{
case WINTC_REG_DWORD:
success =
backend_get_key_value(
key_path,
value_name,
WINTC_REG_DWORD,
&value_data_int
);
if (success)
{
variant_ret =
g_variant_new(
"v",
g_variant_new_int32(value_data_int)
);
}
break;
case WINTC_REG_QWORD:
success =
backend_get_key_value(
key_path,
value_name,
WINTC_REG_QWORD,
&value_data_int64
);
if (success)
{
variant_ret =
g_variant_new(
"v",
g_variant_new_int64(value_data_int64)
);
}
break;
case WINTC_REG_SZ:
success =
backend_get_key_value(
key_path,
value_name,
WINTC_REG_SZ,
&value_data_str
);
if (success)
{
variant_ret =
g_variant_new(
"v",
g_variant_new_string(value_data_str)
);
g_free(value_data_str);
}
break;
default:
g_critical("regsvc: unknown type %d", value_type);
success = FALSE;
break;
}
if (!success)
{
// Cannot use maybe-type variants because they're not supported by
// DBus/GDBus, so just respond with 0 - libwintc-registry will discard
// the variant regardless if the result code is 0 so we could respond
// with any variant here and be fine
//
variant_ret = g_variant_new("v", g_variant_new_int32(0));
}
zwin_registry_gdbus_complete_get_key_value(
reg_dbus,
invocation,
variant_ret,
success ? 1 : 0
);
return TRUE;
}
static gboolean on_handle_set_key_value(
ZWinRegistryGDBUS* reg_dbus,
GDBusMethodInvocation* invocation,
const gchar* key_path,
const gchar* value_name,
GVariant* value_data,
gboolean silent,
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG(
"regsvc: received set key value for %s->%s",
key_path,
value_name
);
// The variant incoming determines the type etc.
//
GVariant* inner = g_variant_get_variant(value_data);
gboolean success = FALSE;
WinTCRegistryValueType value_type = wintc_registry_get_type_for_variant(
inner
);
gint value_data_int = 0;
gint64 value_data_int64 = 0;
gchar* value_data_str = NULL;
switch (value_type)
{
case WINTC_REG_DWORD:
value_data_int = g_variant_get_int32(inner);
success =
backend_set_key_value(
key_path,
value_name,
WINTC_REG_DWORD,
&value_data_int
);
break;
case WINTC_REG_QWORD:
value_data_int64 = g_variant_get_int64(inner);
success =
backend_set_key_value(
key_path,
value_name,
WINTC_REG_QWORD,
&value_data_int64
);
break;
case WINTC_REG_SZ:
value_data_str = g_variant_dup_string(inner, NULL);
success =
backend_set_key_value(
key_path,
value_name,
WINTC_REG_SZ,
&value_data_str
);
g_free(value_data_str);
break;
default:
g_critical("%s", "regsvc: set key unknown variant type");
break;
}
zwin_registry_gdbus_complete_set_key_value(
reg_dbus,
invocation,
success ? 1 : 0
);
if (success && !silent)
{
g_signal_emit_by_name(
reg_dbus,
"key-value-changed",
key_path,
value_name,
value_data,
NULL
);
}
return TRUE;
}
static gboolean on_sigterm(
WINTC_UNUSED(gpointer user_data)
)
{
WINTC_LOG_DEBUG("%s", "regsvc: sigterm, exiting...");
g_main_loop_quit(s_main_loop);
g_application_quit(s_app);
return FALSE;
}

View File

@@ -29,6 +29,13 @@ if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
add_compile_definitions(WINTC_CHECKED)
endif()
# Enable ASAN for checked builds
#
if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
add_link_options(-fsanitize=address)
endif()
# Handle SKU stuff
#
set(

View File

@@ -8,6 +8,12 @@ License: @RPM_LICENCE@
URL: https://github.com/rozniak/xfce-winxp-tc
BugURL: https://github.com/rozniak/xfce-winxp-tc/issues
%if "@CMAKE_BUILD_TYPE@" == "Debug"
%global _enable_debug_package 0
%global debug_package %{nil}
%global __os_install_post /usr/lib/rpm/brp-compress %{nil}
%endif
%description
@PROJECT_DESCRIPTION@

View File

@@ -189,6 +189,8 @@ static gboolean parse_file_in_cmdline(
g_propagate_error(out_error, error);
}
g_clear_error(&error);
WINTC_SAFE_REF_SET(out_cmdline, g_strdup(cmdline));
return FALSE;

View File

@@ -52,6 +52,8 @@ gchar* wintc_query_mime_for_file(
return cmd_output;
}
g_free(cmd_output);
// Handle errors
//
if (error != NULL)

View File

@@ -224,6 +224,8 @@ gboolean wintc_registry_get_key_value(
g_critical("registry: unknown type %d", value_type);
break;
}
g_variant_unref(inner);
}
g_variant_unref(value_variant);
@@ -430,4 +432,6 @@ static void on_reg_key_value_changed(
inner,
cb_data->user_data
);
g_variant_unref(inner);
}

View File

@@ -119,7 +119,7 @@ GSList* wintc_sh_cpl_applet_get_all(void)
success = TRUE;
}
g_slist_free(entries);
g_slist_free_full(entries, g_free);
g_key_file_free(key_file);
return cpls;
@@ -148,4 +148,5 @@ void wintc_sh_cpl_applet_free(
g_free(applet->comment);
g_free(applet->exec);
g_free(applet->icon_name);
g_free(applet);
}

View File

@@ -120,6 +120,11 @@ extern WinTCWndMgmtWindow* (*wintc_wndmgmt_screen_get_active_window) (
*/
extern WinTCWndMgmtScreen* (*wintc_wndmgmt_screen_get_default) (void);
/**
* Shuts down window management functionality, releasing all resources.
*/
extern void (*wintc_wndmgmt_shutdown) (void);
/**
* Retrieves the icon for the specified window.
*

View File

@@ -30,6 +30,8 @@ WinTCWndMgmtWindow* (*wintc_wndmgmt_screen_get_active_window) (
) = NULL;
WinTCWndMgmtScreen* (*wintc_wndmgmt_screen_get_default) (void) = NULL;
void (*wintc_wndmgmt_shutdown) (void) = NULL;
GdkPixbuf* (*wintc_wndmgmt_window_get_mini_icon) (
WinTCWndMgmtWindow* window
) = NULL;

View File

@@ -23,6 +23,8 @@ WinTCWndMgmtWindow* (*p_wnck_screen_get_active_window) (
) = NULL;
WinTCWndMgmtScreen* (*p_wnck_screen_get_default) (void) = NULL;
void (*p_wnck_shutdown) (void) = NULL;
const gchar* (*p_wnck_window_get_class_instance_name) (
WinTCWndMgmtWindow* window
) = NULL;
@@ -91,6 +93,9 @@ gboolean init_dll_wnck()
p_wnck_screen_get_default =
dlsym(dl_wnck, "wnck_screen_get_default");
p_wnck_shutdown =
dlsym(dl_wnck, "wnck_shutdown");
p_wnck_window_get_class_instance_name =
dlsym(dl_wnck, "wnck_window_get_class_instance_name");
@@ -118,6 +123,7 @@ gboolean init_dll_wnck()
p_wnck_set_client_type == NULL ||
p_wnck_screen_get_active_window == NULL ||
p_wnck_screen_get_default == NULL ||
p_wnck_shutdown == NULL ||
p_wnck_window_get_class_instance_name == NULL ||
p_wnck_window_get_icon_is_fallback == NULL ||
p_wnck_window_get_mini_icon == NULL ||

View File

@@ -27,6 +27,8 @@ extern WinTCWndMgmtWindow* (*p_wnck_screen_get_active_window) (
);
extern WinTCWndMgmtScreen* (*p_wnck_screen_get_default) (void);
extern void (*p_wnck_shutdown) (void);
extern const gchar* (*p_wnck_window_get_class_instance_name) (
WinTCWndMgmtWindow* Window
);

View File

@@ -33,6 +33,7 @@ gboolean init_wndmgmt_wnck_impl(void)
//
wintc_wndmgmt_screen_get_active_window = p_wnck_screen_get_active_window;
wintc_wndmgmt_screen_get_default = p_wnck_screen_get_default;
wintc_wndmgmt_shutdown = p_wnck_shutdown;
wintc_wndmgmt_window_get_mini_icon = &wnck_window_get_mini_icon_real;
wintc_wndmgmt_window_get_name = p_wnck_window_get_name;
wintc_wndmgmt_window_is_skip_tasklist = p_wnck_window_is_skip_tasklist;

View File

@@ -10,6 +10,7 @@
//
// FORWARD DECLARATIONS
//
static void xfw_shutdown(void);
static GdkPixbuf* xfw_window_get_mini_icon(
WinTCWndMgmtWindow* window
);
@@ -36,6 +37,7 @@ gboolean init_wndmgmt_xfw_impl(void)
//
wintc_wndmgmt_screen_get_active_window = p_xfw_screen_get_active_window;
wintc_wndmgmt_screen_get_default = p_xfw_screen_get_default;
wintc_wndmgmt_shutdown = &xfw_shutdown;
wintc_wndmgmt_window_get_mini_icon = &xfw_window_get_mini_icon;
wintc_wndmgmt_window_get_name = p_xfw_window_get_name;
wintc_wndmgmt_window_is_skip_tasklist = p_xfw_window_is_skip_tasklist;
@@ -47,6 +49,11 @@ gboolean init_wndmgmt_xfw_impl(void)
// PRIVATE FUNCTIONS
//
static void xfw_shutdown(void)
{
// Nothing to do! xfce4windowing doesn't expose any shutdown method
}
static GdkPixbuf* xfw_window_get_mini_icon(
WinTCWndMgmtWindow* window
)

View File

@@ -25,6 +25,10 @@ typedef WinTCIShextView* (*LookupViewFunc) (
//
// FORWARD DECLARATIONS
//
static void wintc_shext_host_finalize(
GObject* object
);
WinTCIShextView* lookup_view_for_path_by_guid(
WinTCShextHost* host,
const gchar* path,
@@ -73,8 +77,13 @@ G_DEFINE_TYPE(
)
static void wintc_shext_host_class_init(
WINTC_UNUSED(WinTCShextHostClass* klass)
) {}
WinTCShextHostClass* klass
)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->finalize = wintc_shext_host_finalize;
}
static void wintc_shext_host_init(
WinTCShextHost* self
@@ -96,6 +105,21 @@ static void wintc_shext_host_init(
);
}
//
// CLASS VIRTUAL METHODS
//
static void wintc_shext_host_finalize(
GObject* object
)
{
WinTCShextHost* host = WINTC_SHEXT_HOST(object);
g_hash_table_unref(host->map_views_by_guid);
g_hash_table_unref(host->map_views_by_mime);
(G_OBJECT_CLASS(wintc_shext_host_parent_class))->finalize(object);
}
//
// PUBLIC FUNCTIONS
//

View File

@@ -272,6 +272,7 @@ static const gchar* translate_widget_text(
if (!g_regex_match(s_langstr_regex, widget_text, 0, &match_info))
{
g_match_info_unref(match_info);
return ret;
}

View File

@@ -152,6 +152,8 @@ static void wintc_desk_monitor_dispose(
g_clear_object(&(monitor->pixbuf_preview));
cairo_surface_destroy(g_steal_pointer(&monitor->surface_preview));
(G_OBJECT_CLASS(wintc_desk_monitor_parent_class))->dispose(object);
}
static gboolean wintc_desk_monitor_draw(

View File

@@ -28,10 +28,34 @@ struct _WinTCDesktopApplication
static void wintc_desktop_application_activate(
GApplication* application
);
static gint wintc_desktop_application_command_line(
GApplication* application,
GApplicationCommandLine* command_line
);
static gint wintc_desktop_application_handle_local_options(
GApplication* application,
GVariantDict* options
);
static void wintc_desktop_application_startup(
GApplication* application
);
//
// STATIC DATA
//
static const GOptionEntry S_OPTIONS[] = {
{
"quit",
'q',
G_OPTION_FLAG_NONE,
G_OPTION_ARG_NONE,
NULL,
"Quit a running Windows desktop instance.",
NULL
},
{ 0 }
};
//
// GTK TYPE DEFINITION & CTORS
//
@@ -47,15 +71,24 @@ static void wintc_desktop_application_class_init(
{
GApplicationClass* application_class = G_APPLICATION_CLASS(klass);
application_class->activate = wintc_desktop_application_activate;
application_class->startup = wintc_desktop_application_startup;
application_class->activate =
wintc_desktop_application_activate;
application_class->command_line =
wintc_desktop_application_command_line;
application_class->handle_local_options =
wintc_desktop_application_handle_local_options;
application_class->startup =
wintc_desktop_application_startup;
}
static void wintc_desktop_application_init(
WinTCDesktopApplication* self
)
{
self->settings = wintc_desktop_settings_new();
g_application_add_main_option_entries(
G_APPLICATION(self),
S_OPTIONS
);
}
//
@@ -71,6 +104,7 @@ WinTCDesktopApplication* wintc_desktop_application_new(void)
g_object_new(
wintc_desktop_application_get_type(),
"application-id", "uk.co.oddmatics.wintc.desktop",
"flags", G_APPLICATION_HANDLES_COMMAND_LINE,
NULL
);
@@ -94,6 +128,10 @@ static void wintc_desktop_application_activate(
return;
}
launched = TRUE;
desktop_app->settings = wintc_desktop_settings_new();
// FIXME: Just create a desktop window per monitor for now, connect up
// signals for monitors added/removed later
//
@@ -113,6 +151,36 @@ static void wintc_desktop_application_activate(
}
}
static gint wintc_desktop_application_command_line(
GApplication* application,
GApplicationCommandLine* command_line
)
{
GVariantDict* options =
g_application_command_line_get_options_dict(command_line);
// Just check for --quit
//
if (g_variant_dict_contains(options, "quit"))
{
g_application_quit(application);
return 0;
}
g_application_activate(application);
return 0;
}
static gint wintc_desktop_application_handle_local_options(
WINTC_UNUSED(GApplication* application),
WINTC_UNUSED(GVariantDict* options)
)
{
// Stub
return -1;
}
static void wintc_desktop_application_startup(
GApplication* application
)

View File

@@ -28,6 +28,10 @@ struct _WinTCExplorerApplication
//
// FORWARD DECLARATIONS
//
static void wintc_explorer_application_dispose(
GObject* object
);
static void wintc_explorer_application_activate(
GApplication* application
);
@@ -49,9 +53,12 @@ static void wintc_explorer_application_class_init(
)
{
GApplicationClass* application_class = G_APPLICATION_CLASS(klass);
GObjectClass* object_class = G_OBJECT_CLASS(klass);
application_class->activate = wintc_explorer_application_activate;
application_class->startup = wintc_explorer_application_startup;
object_class->dispose = wintc_explorer_application_dispose;
}
static void wintc_explorer_application_init(
@@ -61,6 +68,19 @@ static void wintc_explorer_application_init(
//
// CLASS VIRTUAL METHODS
//
static void wintc_explorer_application_dispose(
GObject* object
)
{
WinTCExplorerApplication* explorer_app =
WINTC_EXPLORER_APPLICATION(object);
g_clear_object(&(explorer_app->shext_host));
(G_OBJECT_CLASS(wintc_explorer_application_parent_class))
->dispose(object);
}
static void wintc_explorer_application_activate(
GApplication* application
)

View File

@@ -95,6 +95,8 @@ static void wintc_exp_address_toolbar_init(
self->combo_address =
GTK_WIDGET(gtk_builder_get_object(builder, "combo-address"));
g_object_unref(builder);
// Connect signals
//
g_signal_connect(

View File

@@ -32,6 +32,9 @@ enum
static void wintc_explorer_window_constructed(
GObject* object
);
static void wintc_explorer_window_finalize(
GObject* object
);
static void wintc_explorer_window_dispose(
GObject* object
);
@@ -110,6 +113,9 @@ struct _WinTCExplorerWindow
//
WinTCShextPathInfo current_path;
WinTCExplorerToolbar* toolbar_adr;
WinTCExplorerToolbar* toolbar_std;
// UI
//
WinTCShIconViewBehaviour* behaviour_icons;
@@ -135,6 +141,7 @@ static void wintc_explorer_window_class_init(
object_class->constructed = wintc_explorer_window_constructed;
object_class->dispose = wintc_explorer_window_dispose;
object_class->finalize = wintc_explorer_window_finalize;
object_class->set_property = wintc_explorer_window_set_property;
g_object_class_install_property(
@@ -221,20 +228,22 @@ static void wintc_explorer_window_init(
gtk_container_add(GTK_CONTAINER(self), main_box);
g_object_unref(builder);
// FIXME: Toolbars are configurable!
//
WinTCExplorerToolbar* toolbar_adr =
self->toolbar_adr =
wintc_exp_address_toolbar_new(self);
WinTCExplorerToolbar* toolbar_std =
self->toolbar_std =
wintc_exp_standard_toolbar_new(self);
gtk_container_add(
GTK_CONTAINER(self->box_toolbars),
wintc_explorer_toolbar_get_toolbar(toolbar_std)
wintc_explorer_toolbar_get_toolbar(self->toolbar_std)
);
gtk_container_add(
GTK_CONTAINER(self->box_toolbars),
wintc_explorer_toolbar_get_toolbar(toolbar_adr)
wintc_explorer_toolbar_get_toolbar(self->toolbar_adr)
);
}
@@ -293,9 +302,23 @@ static void wintc_explorer_window_dispose(
g_clear_object(&(wnd->browser));
g_clear_object(&(wnd->shext_host));
g_clear_object(&(wnd->toolbar_adr));
g_clear_object(&(wnd->toolbar_std));
(G_OBJECT_CLASS(wintc_explorer_window_parent_class))->dispose(object);
}
static void wintc_explorer_window_finalize(
GObject* object
)
{
WinTCExplorerWindow* wnd = WINTC_EXPLORER_WINDOW(object);
wintc_shext_path_info_free_data(&(wnd->current_path));
(G_OBJECT_CLASS(wintc_explorer_window_parent_class))->finalize(object);
}
static void wintc_explorer_window_set_property(
GObject* object,
guint prop_id,

View File

@@ -27,10 +27,37 @@ struct _WinTCTaskbandApplication
static void wintc_taskband_application_activate(
GApplication* application
);
static gint wintc_taskband_application_command_line(
GApplication* application,
GApplicationCommandLine* command_line
);
static gint wintc_taskband_application_handle_local_options(
GApplication* application,
GVariantDict* options
);
static void wintc_taskband_application_shutdown(
GApplication* application
);
static void wintc_taskband_application_startup(
GApplication* application
);
//
// STATIC DATA
//
static const GOptionEntry S_OPTIONS[] = {
{
"quit",
'q',
G_OPTION_FLAG_NONE,
G_OPTION_ARG_NONE,
NULL,
"Quit a running Windows taskband instance.",
NULL
},
{ 0 }
};
//
// GTK TYPE DEFINITION & CTORS
//
@@ -46,13 +73,27 @@ static void wintc_taskband_application_class_init(
{
GApplicationClass* application_class = G_APPLICATION_CLASS(klass);
application_class->activate = wintc_taskband_application_activate;
application_class->startup = wintc_taskband_application_startup;
application_class->activate =
wintc_taskband_application_activate;
application_class->command_line =
wintc_taskband_application_command_line;
application_class->handle_local_options =
wintc_taskband_application_handle_local_options;
application_class->shutdown =
wintc_taskband_application_shutdown;
application_class->startup =
wintc_taskband_application_startup;
}
static void wintc_taskband_application_init(
WINTC_UNUSED(WinTCTaskbandApplication* self)
) {}
WinTCTaskbandApplication* self
)
{
g_application_add_main_option_entries(
G_APPLICATION(self),
S_OPTIONS
);
}
//
// PUBLIC FUNCTIONS
@@ -67,6 +108,7 @@ WinTCTaskbandApplication* wintc_taskband_application_new(void)
g_object_new(
wintc_taskband_application_get_type(),
"application-id", "uk.co.oddmatics.wintc.taskband",
"flags", G_APPLICATION_HANDLES_COMMAND_LINE,
NULL
);
@@ -93,6 +135,54 @@ static void wintc_taskband_application_activate(
gtk_widget_show_all(taskband_app->host_window);
}
static gint wintc_taskband_application_command_line(
GApplication* application,
GApplicationCommandLine* command_line
)
{
GVariantDict* options =
g_application_command_line_get_options_dict(command_line);
// Just check for --quit
//
if (g_variant_dict_contains(options, "quit"))
{
g_application_quit(application);
return 0;
}
g_application_activate(application);
return 0;
}
static gint wintc_taskband_application_handle_local_options(
WINTC_UNUSED(GApplication* application),
WINTC_UNUSED(GVariantDict* options)
)
{
// Stub
return -1;
}
static void wintc_taskband_application_shutdown(
GApplication* application
)
{
GList* window_iter = NULL;
while (
(window_iter =
gtk_application_get_windows(GTK_APPLICATION(application)))
)
{
gtk_widget_destroy(GTK_WIDGET(window_iter->data));
}
(G_APPLICATION_CLASS(wintc_taskband_application_parent_class))
->shutdown(application);
}
static void wintc_taskband_application_startup(
GApplication* application
)

View File

@@ -26,6 +26,9 @@ static gint wintc_notification_behaviour_signals[N_SIGNALS] = { 0 };
//
// FORWARD DECLARATIONS
//
static void wintc_notification_behaviour_finalize(
GObject* object
);
static void wintc_notification_behaviour_get_property(
GObject* object,
guint prop_id,
@@ -54,6 +57,7 @@ static void wintc_notification_behaviour_class_init(
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->finalize = wintc_notification_behaviour_finalize;
object_class->get_property = wintc_notification_behaviour_get_property;
object_class->set_property = wintc_notification_behaviour_set_property;
@@ -105,6 +109,19 @@ static void wintc_notification_behaviour_init(
//
// CLASS VIRTUAL METHODS
//
static void wintc_notification_behaviour_finalize(
GObject* object
)
{
WinTCNotificationBehaviour* behaviour =
WINTC_NOTIFICATION_BEHAVIOUR(object);
g_free(behaviour->icon_name);
(G_OBJECT_CLASS(wintc_notification_behaviour_parent_class))
->finalize(object);
}
static void wintc_notification_behaviour_get_property(
GObject* object,
guint prop_id,

View File

@@ -30,6 +30,10 @@ struct _WinTCNotificationArea
//
// FORWARD DECLARATIONS
//
static void wintc_notification_area_dispose(
GObject* object
);
static GtkWidget* wintc_notification_area_append_icon(
WinTCNotificationArea* notif_area
);
@@ -59,8 +63,13 @@ G_DEFINE_TYPE(
)
static void wintc_notification_area_class_init(
WINTC_UNUSED(WinTCNotificationAreaClass* klass)
) {}
WinTCNotificationAreaClass* klass
)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->dispose = wintc_notification_area_dispose;
}
static void wintc_notification_area_init(
WinTCNotificationArea* self
@@ -69,7 +78,12 @@ static void wintc_notification_area_init(
// Create map for notification widgets --> behaviours
//
self->map_widget_to_behaviour =
g_hash_table_new(g_direct_hash, g_direct_equal);
g_hash_table_new_full(
g_direct_hash,
g_direct_equal,
NULL,
g_object_unref
);
// Set up UI
//
@@ -112,6 +126,27 @@ static void wintc_notification_area_init(
);
}
//
// CLASS VIRTUAL METHODS
//
static void wintc_notification_area_dispose(
GObject* object
)
{
WinTCNotificationArea* notif_area = WINTC_NOTIFICATION_AREA(object);
g_clear_object(&(notif_area->clock_runner));
if (notif_area->map_widget_to_behaviour)
{
g_hash_table_unref(
g_steal_pointer(&(notif_area->map_widget_to_behaviour))
);
}
(G_OBJECT_CLASS(wintc_notification_area_parent_class))->dispose(object);
}
//
// PUBLIC FUNCTIONS
//

View File

@@ -339,8 +339,10 @@ static void on_snd_output_muted_changed(
WinTCNotificationVolume* volume =
WINTC_NOTIFICATION_VOLUME(user_data);
gboolean muted = wintc_sndapi_output_is_muted(output);
gchar* icon_name = muted ? "audio-volume-muted" : "audio-volume-medium";
gboolean muted = wintc_sndapi_output_is_muted(output);
const gchar* icon_name = muted ?
"audio-volume-muted" :
"audio-volume-medium";
volume->syncing_state = TRUE;
gtk_toggle_button_set_active(

View File

@@ -29,6 +29,10 @@ struct _TaskButtonBar
//
// FORWARD DECLARATIONS
//
static void taskbutton_bar_finalize(
GObject* object
);
static void taskbutton_bar_get_preferred_height(
GtkWidget* widget,
gint* minimum_height,
@@ -94,6 +98,9 @@ static void taskbutton_bar_class_init(
{
GtkContainerClass* container_class = GTK_CONTAINER_CLASS(klass);
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->finalize = taskbutton_bar_finalize;
widget_class->get_preferred_height = taskbutton_bar_get_preferred_height;
widget_class->get_preferred_height_for_width =
@@ -124,6 +131,19 @@ static void taskbutton_bar_init(
//
// CLASS VIRTUAL METHODS
//
static void taskbutton_bar_finalize(
GObject* object
)
{
TaskButtonBar* taskbutton_bar = TASKBUTTON_BAR(object);
window_monitor_destroy(
taskbutton_bar->window_monitor
);
(G_OBJECT_CLASS(taskbutton_bar_parent_class))->finalize(object);
}
static void taskbutton_bar_add(
GtkContainer* container,
GtkWidget* widget

View File

@@ -78,6 +78,16 @@ static void window_manager_update_text(
//
// PUBLIC FUNCTIONS
//
void window_monitor_destroy(
WindowMonitor* monitor
)
{
g_hash_table_unref(monitor->window_manager_map);
g_free(monitor);
wintc_wndmgmt_shutdown();
}
WindowMonitor* window_monitor_init_management(
GtkContainer* container
)
@@ -86,9 +96,11 @@ WindowMonitor* window_monitor_init_management(
window_monitor->container = container;
window_monitor->screen = wintc_wndmgmt_screen_get_default();
window_monitor->window_manager_map = g_hash_table_new(
window_monitor->window_manager_map = g_hash_table_new_full(
g_direct_hash,
g_direct_equal
g_direct_equal,
NULL,
g_free
);
g_signal_connect(
@@ -319,7 +331,6 @@ static void on_window_closed(
gtk_widget_destroy(GTK_WIDGET(window_manager->button));
}
g_free(window_manager);
g_hash_table_remove(window_monitor->window_manager_map, window);
}

View File

@@ -14,6 +14,10 @@ typedef struct _WindowMonitor WindowMonitor;
//
// PUBLIC FUNCTIONS
//
void window_monitor_destroy(
WindowMonitor* monitor
);
WindowMonitor* window_monitor_init_management(
GtkContainer* container
);

View File

@@ -29,6 +29,10 @@ typedef enum
//
// FORWARD DECLARATIONS
//
static void wintc_taskband_window_dispose(
GObject* object
);
static void wintc_taskband_window_create_toolbar(
WinTCTaskbandWindow* taskband,
GType toolbar_type,
@@ -65,11 +69,15 @@ struct _WinTCTaskbandWindow
{
GtkApplicationWindow __parent__;
// UI
//
GtkWidget* main_box;
GtkWidget* notification_area;
GtkWidget* start_button;
GtkWidget* taskbuttons;
GSList* toolbars;
};
//
@@ -82,8 +90,13 @@ G_DEFINE_TYPE(
)
static void wintc_taskband_window_class_init(
WINTC_UNUSED(WinTCTaskbandWindowClass* klass)
) {}
WinTCTaskbandWindowClass* klass
)
{
GObjectClass* object_class = G_OBJECT_CLASS(klass);
object_class->dispose = wintc_taskband_window_dispose;
}
static void wintc_taskband_window_init(
WinTCTaskbandWindow* self
@@ -121,6 +134,20 @@ static void wintc_taskband_window_init(
);
}
//
// FORWARD DECLARATIONS
//
static void wintc_taskband_window_dispose(
GObject* object
)
{
WinTCTaskbandWindow* wnd = WINTC_TASKBAND_WINDOW(object);
g_clear_slist(&(wnd->toolbars), g_object_unref);
(G_OBJECT_CLASS(wintc_taskband_window_parent_class))->dispose(object);
}
//
// PUBLIC FUNCTIONS
//
@@ -155,6 +182,12 @@ static void wintc_taskband_window_create_toolbar(
toolbar
);
taskband->toolbars =
g_slist_append(
taskband->toolbars,
toolbar
);
gtk_box_pack_start(
GTK_BOX(taskband->main_box),
root,

View File

@@ -857,6 +857,7 @@ static void action_save_as(
{
if (g_file_set_contents(file_path, file_contents, -1, &error))
{
g_free(wnd->file_uri);
wnd->file_uri = g_strdup(uri);
gtk_text_buffer_set_modified(