mirror of
https://github.com/rozniak/xfce-winxp-tc.git
synced 2026-01-26 11:39:44 +00:00
Enhancement: Fixes #291, Implement desktop wallpaper support
This commit is contained in:
82
base/regsvc/CMakeLists.txt
Normal file
82
base/regsvc/CMakeLists.txt
Normal file
@@ -0,0 +1,82 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(
|
||||
wintc-regsvc
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion registry service."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS true)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(sqlite3 SQLITE3)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
wintc_resolve_library(wintc-registry WINTC_REGISTRY)
|
||||
|
||||
add_executable(
|
||||
wintc-regsvc
|
||||
src/backend.c
|
||||
src/backend.h
|
||||
src/main.c
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
wintc-regsvc
|
||||
PROPERTIES
|
||||
OUTPUT_NAME regsvc
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
wintc-regsvc
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
wintc-regsvc
|
||||
SYSTEM
|
||||
BEFORE
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${SQLITE3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_REGISTRY_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
wintc-regsvc
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${SQLITE3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_REGISTRY_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
wintc-regsvc
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${SQLITE3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_REGISTRY_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
|
||||
install(
|
||||
TARGETS wintc-regsvc
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
8
base/regsvc/README.MD
Normal file
8
base/regsvc/README.MD
Normal file
@@ -0,0 +1,8 @@
|
||||
# regsvc
|
||||
This directory contains the source-code for the registry service/daemon.
|
||||
|
||||
## Details
|
||||
Essentially `regsvc` is a very billy-basic daemon that provides the backend for the simplified 'registry' interface defined by `libwintc-registry`.
|
||||
- The registry is implemented as a daemon for DBus-based IPC, so things like Control Panel applets can configure settings and the recipient programs (like the desktop) can be notified
|
||||
- It's not a full clone of the Windows Registry, just a very simple form
|
||||
- The backend uses SQLite3 for storage in the user profile
|
||||
5
base/regsvc/deps
Normal file
5
base/regsvc/deps
Normal file
@@ -0,0 +1,5 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:sqlite3
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-registry
|
||||
713
base/regsvc/src/backend.c
Normal file
713
base/regsvc/src/backend.c
Normal file
@@ -0,0 +1,713 @@
|
||||
#include <glib.h>
|
||||
#include <sqlite3.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "backend.h"
|
||||
|
||||
#define WINTC_COMPONENT_REGISTRY "registry"
|
||||
|
||||
#define BAIL_ON_FAIL(query) \
|
||||
rc = (query); \
|
||||
if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) \
|
||||
{ \
|
||||
handle_sqlite_problem(rc); \
|
||||
sqlite3_finalize(stmt); \
|
||||
return FALSE; \
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE CONSTANTS
|
||||
//
|
||||
static const gchar* S_SQL_INIT =
|
||||
"CREATE TABLE IF NOT EXISTS RegKey ("
|
||||
" Id INTEGER PRIMARY KEY,"
|
||||
" ParentId INTEGER,"
|
||||
" Name VARCHAR(255) NOT NULL,"
|
||||
" FOREIGN KEY(ParentId) REFERENCES RegKey(Id),"
|
||||
" UNIQUE(ParentId, Name)"
|
||||
");"
|
||||
"CREATE TABLE IF NOT EXISTS RegKeyValue ("
|
||||
" Id INTEGER PRIMARY KEY,"
|
||||
" OwnerKey INTEGER,"
|
||||
" Name VARCHAR(255),"
|
||||
" ItemType INTEGER,"
|
||||
" ItemValue BLOB,"
|
||||
" FOREIGN KEY(OwnerKey) REFERENCES RegKey(Id),"
|
||||
" UNIQUE(OwnerKey, Name)"
|
||||
");"
|
||||
"INSERT OR REPLACE INTO RegKey VALUES (1, NULL, 'HKEY_CURRENT_USER');";
|
||||
|
||||
//
|
||||
// STATIC DATA
|
||||
//
|
||||
static sqlite3* s_db = NULL;
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static gboolean db_create_regkey(
|
||||
const gchar* key_name,
|
||||
gint parent_id,
|
||||
gint* out_id
|
||||
);
|
||||
static gboolean db_get_regkey_id(
|
||||
const gchar* key_name,
|
||||
gint parent_id,
|
||||
gint* out_id
|
||||
);
|
||||
static gboolean db_traverse_to_key(
|
||||
const gchar* key_path,
|
||||
gint* out_id
|
||||
);
|
||||
|
||||
static void handle_sqlite_problem(
|
||||
gint rc
|
||||
);
|
||||
|
||||
static gboolean is_valid_key_path(
|
||||
GSList* components
|
||||
);
|
||||
|
||||
static gboolean is_valid_value_name(
|
||||
const gchar* value_name
|
||||
);
|
||||
|
||||
static GSList* path_to_components(
|
||||
const gchar* key_path
|
||||
);
|
||||
|
||||
//
|
||||
// INTERNAL FUNCTIONS
|
||||
//
|
||||
void backend_close(void)
|
||||
{
|
||||
if (!s_db)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("%s", "regsvc: sqlite closing profile");
|
||||
|
||||
sqlite3_close(s_db);
|
||||
s_db = NULL;
|
||||
}
|
||||
|
||||
gboolean backend_init(void)
|
||||
{
|
||||
GError* error = NULL;
|
||||
gchar* path;
|
||||
gint rc;
|
||||
|
||||
if (s_db)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Open DB handle
|
||||
//
|
||||
if (!wintc_profile_ensure_exists(WINTC_COMPONENT_REGISTRY, &error))
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
path = wintc_profile_get_path(WINTC_COMPONENT_REGISTRY, "ntuser.db");
|
||||
rc = sqlite3_open(path, &s_db);
|
||||
|
||||
WINTC_LOG_DEBUG("regsvc: sqlite opening %s", path);
|
||||
|
||||
g_free(path);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
g_critical(
|
||||
"regsvc: failed to open profile sqlite %s",
|
||||
sqlite3_errmsg(s_db)
|
||||
);
|
||||
sqlite3_close(s_db);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Ensure tables initialised
|
||||
//
|
||||
char* error_sql = NULL;
|
||||
|
||||
rc =
|
||||
sqlite3_exec(
|
||||
s_db,
|
||||
S_SQL_INIT,
|
||||
NULL,
|
||||
NULL,
|
||||
&error_sql
|
||||
);
|
||||
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
g_critical(
|
||||
"regsvc: failed to init tables %s",
|
||||
error_sql
|
||||
);
|
||||
|
||||
sqlite3_free(error_sql);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean backend_create_key(
|
||||
const gchar* key_path
|
||||
)
|
||||
{
|
||||
GSList* components = path_to_components(key_path);
|
||||
|
||||
WINTC_LOG_DEBUG("regsvc: backend create key %s", key_path);
|
||||
|
||||
if (!is_valid_key_path(components))
|
||||
{
|
||||
WINTC_LOG_DEBUG(
|
||||
"regsvc: backend create key: key/value not valid '%s'",
|
||||
key_path
|
||||
);
|
||||
|
||||
g_slist_free_full(components, g_free);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Iterate over to create the key
|
||||
//
|
||||
gint last_id = 0;
|
||||
gboolean success = TRUE;
|
||||
|
||||
for (GSList* iter = components; iter; iter = iter->next)
|
||||
{
|
||||
const gchar* key_name = (gchar*) iter->data;
|
||||
gint this_id = 0;
|
||||
|
||||
WINTC_LOG_DEBUG("regsvc: create key checking for part '%s'", key_name);
|
||||
|
||||
// Check if key exists first
|
||||
//
|
||||
if (!db_get_regkey_id(key_name, last_id, &this_id))
|
||||
{
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
// If needed, create the key
|
||||
//
|
||||
if (!this_id)
|
||||
{
|
||||
WINTC_LOG_DEBUG("%s", "regsvc: need to create that key");
|
||||
|
||||
if (!db_create_regkey(key_name, last_id, &this_id))
|
||||
{
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last_id = this_id;
|
||||
}
|
||||
|
||||
g_slist_free_full(components, g_free);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gboolean backend_get_key_value(
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
void* value_data
|
||||
)
|
||||
{
|
||||
gint key_id = 0;
|
||||
gint rc;
|
||||
|
||||
if (value_data == NULL)
|
||||
{
|
||||
g_critical("%s", "regsvc: backend nowhere to store kv");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (
|
||||
!is_valid_value_name(value_name) ||
|
||||
!db_traverse_to_key(key_path, &key_id)
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG(
|
||||
"regsvc: backend get kv: key/value not valid '%s->%s'",
|
||||
key_path,
|
||||
value_name
|
||||
);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Retrieve key stuff
|
||||
//
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_prepare(
|
||||
s_db,
|
||||
"SELECT ItemType, ItemValue FROM RegKeyValue WHERE OwnerKey = ? AND Name = ?;",
|
||||
-1,
|
||||
&stmt,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 1, key_id));
|
||||
BAIL_ON_FAIL(sqlite3_bind_text(stmt, 2, value_name, -1, SQLITE_STATIC));
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_step(stmt));
|
||||
|
||||
// Analyze result
|
||||
//
|
||||
WinTCRegistryValueType found_type = WINTC_REG_INVALID;
|
||||
gboolean success = FALSE;
|
||||
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
found_type = (WinTCRegistryValueType) sqlite3_column_int(stmt, 0);
|
||||
|
||||
if (found_type == value_type)
|
||||
{
|
||||
switch (value_type)
|
||||
{
|
||||
case WINTC_REG_DWORD:
|
||||
*((gint*) value_data) =
|
||||
sqlite3_column_int(stmt, 1);
|
||||
break;
|
||||
|
||||
case WINTC_REG_QWORD:
|
||||
*((gint64*) value_data) =
|
||||
sqlite3_column_int64(stmt, 1);
|
||||
break;
|
||||
|
||||
case WINTC_REG_SZ:
|
||||
*((gchar**) value_data) =
|
||||
g_strdup((const gchar*) sqlite3_column_text(stmt, 1));
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical(
|
||||
"regsvc: backend unknown key type %d",
|
||||
value_type
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gboolean backend_set_key_value(
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
void* value_data
|
||||
)
|
||||
{
|
||||
gint key_id = 0;
|
||||
gint rc;
|
||||
|
||||
if (value_data == NULL)
|
||||
{
|
||||
g_critical("%s", "regsvc: backend no data provided to set kv");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (
|
||||
!is_valid_value_name(value_name) ||
|
||||
!db_traverse_to_key(key_path, &key_id)
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG(
|
||||
"regsvc: backend set kv: key/value not valid '%s->%s'",
|
||||
key_path,
|
||||
value_name
|
||||
);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("regsvc: traversed to key id %d", key_id);
|
||||
|
||||
// Check if we already have a key value
|
||||
//
|
||||
gint value_id = 0;
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_prepare(
|
||||
s_db,
|
||||
"SELECT Id FROM RegKeyValue WHERE OwnerKey = ? AND Name = ?;",
|
||||
-1,
|
||||
&stmt,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 1, key_id));
|
||||
BAIL_ON_FAIL(sqlite3_bind_text(stmt, 2, value_name, -1, SQLITE_STATIC));
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_step(stmt));
|
||||
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
value_id = sqlite3_column_int(stmt, 0);
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
// Set new value
|
||||
//
|
||||
gint blob_bind_pos;
|
||||
|
||||
if (value_id)
|
||||
{
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_prepare(
|
||||
s_db,
|
||||
"UPDATE RegKeyValue SET ItemType = ?, ItemValue = ? WHERE Id = ?;",
|
||||
-1,
|
||||
&stmt,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 1, value_type));
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 3, value_id));
|
||||
|
||||
blob_bind_pos = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_prepare(
|
||||
s_db,
|
||||
"INSERT INTO RegKeyValue VALUES (NULL, ?, ?, ?, ?);",
|
||||
-1,
|
||||
&stmt,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 1, key_id));
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_bind_text(
|
||||
stmt,
|
||||
2,
|
||||
value_name,
|
||||
-1,
|
||||
SQLITE_STATIC
|
||||
)
|
||||
);
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 3, value_type));
|
||||
|
||||
blob_bind_pos = 4;
|
||||
}
|
||||
|
||||
switch (value_type)
|
||||
{
|
||||
case WINTC_REG_DWORD:
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_bind_int(
|
||||
stmt,
|
||||
blob_bind_pos,
|
||||
*((gint*) value_data)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_REG_QWORD:
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_bind_int64(
|
||||
stmt,
|
||||
blob_bind_pos,
|
||||
*((gint64*) value_data)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_REG_SZ:
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_bind_text(
|
||||
stmt,
|
||||
blob_bind_pos,
|
||||
*((gchar**) value_data),
|
||||
-1,
|
||||
SQLITE_STATIC
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical("regsvc: sqlite no binding for %d", value_type);
|
||||
break;
|
||||
}
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_step(stmt));
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static gboolean db_create_regkey(
|
||||
const gchar* key_name,
|
||||
gint parent_id,
|
||||
gint* out_id
|
||||
)
|
||||
{
|
||||
gint rc;
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
|
||||
WINTC_SAFE_REF_SET(out_id, 0);
|
||||
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_prepare(
|
||||
s_db,
|
||||
"INSERT INTO RegKey VALUES (NULL, ?, ?);",
|
||||
-1,
|
||||
&stmt,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
if (!parent_id)
|
||||
{
|
||||
BAIL_ON_FAIL(sqlite3_bind_null(stmt, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 1, parent_id));
|
||||
}
|
||||
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_bind_text(
|
||||
stmt,
|
||||
2,
|
||||
key_name,
|
||||
-1,
|
||||
SQLITE_STATIC
|
||||
)
|
||||
);
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_step(stmt));
|
||||
|
||||
return db_get_regkey_id(
|
||||
key_name,
|
||||
parent_id,
|
||||
out_id
|
||||
);
|
||||
}
|
||||
|
||||
static gboolean db_get_regkey_id(
|
||||
const gchar* key_name,
|
||||
gint parent_id,
|
||||
gint* out_id
|
||||
)
|
||||
{
|
||||
gint rc;
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
|
||||
WINTC_SAFE_REF_SET(out_id, 0);
|
||||
|
||||
BAIL_ON_FAIL(
|
||||
sqlite3_prepare(
|
||||
s_db,
|
||||
"SELECT Id FROM RegKey WHERE ParentId IS ? AND Name = ?;",
|
||||
-1,
|
||||
&stmt,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
if (!parent_id)
|
||||
{
|
||||
BAIL_ON_FAIL(sqlite3_bind_null(stmt, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
BAIL_ON_FAIL(sqlite3_bind_int(stmt, 1, parent_id));
|
||||
}
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_bind_text(stmt, 2, key_name, -1, SQLITE_STATIC));
|
||||
|
||||
BAIL_ON_FAIL(sqlite3_step(stmt));
|
||||
|
||||
if (rc == SQLITE_ROW)
|
||||
{
|
||||
WINTC_SAFE_REF_SET(out_id, sqlite3_column_int(stmt, 0));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean db_traverse_to_key(
|
||||
const gchar* key_path,
|
||||
gint* out_id
|
||||
)
|
||||
{
|
||||
GSList* components = path_to_components(key_path);
|
||||
|
||||
WINTC_SAFE_REF_SET(out_id, 0);
|
||||
|
||||
if (!is_valid_key_path(components))
|
||||
{
|
||||
// FIXME: Respond invalid path
|
||||
g_slist_free_full(components, g_free);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Attempt to traverse to the key
|
||||
//
|
||||
gint last_id = 0;
|
||||
gboolean success = TRUE;
|
||||
|
||||
for (GSList* iter = components; iter; iter = iter->next)
|
||||
{
|
||||
const gchar* key_name = (gchar*) iter->data;
|
||||
gint this_id = 0;
|
||||
|
||||
if (!db_get_regkey_id(key_name, last_id, &this_id))
|
||||
{
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
last_id = this_id;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
WINTC_SAFE_REF_SET(out_id, last_id);
|
||||
}
|
||||
|
||||
g_slist_free_full(components, g_free);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void handle_sqlite_problem(
|
||||
gint rc
|
||||
)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case SQLITE_ERROR:
|
||||
WINTC_LOG_DEBUG("regsvc: sqlite error: %s", sqlite3_errmsg(s_db));
|
||||
break;
|
||||
|
||||
case SQLITE_MISUSE:
|
||||
g_critical("%s", "regsvc: sqlite misuse detected");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical("regsvc: unknown sqlite problem %d", rc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean is_valid_key_path(
|
||||
GSList* components
|
||||
)
|
||||
{
|
||||
if (g_slist_length(components) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Root must be HKCU
|
||||
//
|
||||
if (
|
||||
g_strcmp0(
|
||||
(gchar*) g_slist_nth_data(components, 0),
|
||||
"HKEY_CURRENT_USER"
|
||||
) != 0
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Max length of individual components is 255
|
||||
//
|
||||
for (GSList* iter = components; iter; iter = iter->next)
|
||||
{
|
||||
if (strlen((gchar*) iter->data) > 255)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean is_valid_value_name(
|
||||
const gchar* value_name
|
||||
)
|
||||
{
|
||||
// Can't contain backslashes
|
||||
//
|
||||
if (strchr(value_name, '\\'))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Max length of string is 255
|
||||
//
|
||||
if (strlen(value_name) > 255)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GSList* path_to_components(
|
||||
const gchar* key_path
|
||||
)
|
||||
{
|
||||
GSList* components = NULL;
|
||||
gchar** split = g_strsplit(key_path, "\\", -1);
|
||||
|
||||
// Move strings into list
|
||||
//
|
||||
for (gint i = 0; split[i] != NULL; i++)
|
||||
{
|
||||
components = g_slist_append(components, split[i]);
|
||||
}
|
||||
|
||||
g_free(split); // The list now owns the strings
|
||||
|
||||
// Naughty hack... if the first component is HKCU, expand it to
|
||||
// HKEY_CURRENT_USER
|
||||
//
|
||||
GSList* first = g_slist_nth(components, 0);
|
||||
|
||||
if (
|
||||
g_strcmp0(
|
||||
(gchar*) first->data,
|
||||
"HKCU"
|
||||
) == 0
|
||||
)
|
||||
{
|
||||
g_free(first->data);
|
||||
first->data = g_strdup("HKEY_CURRENT_USER");
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
29
base/regsvc/src/backend.h
Normal file
29
base/regsvc/src/backend.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef __BACKEND_H__
|
||||
#define __BACKEND_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <wintc/registry.h>
|
||||
|
||||
//
|
||||
// INTERNAL FUNCTIONS
|
||||
//
|
||||
void backend_close(void);
|
||||
gboolean backend_init(void);
|
||||
|
||||
gboolean backend_create_key(
|
||||
const gchar* key_path
|
||||
);
|
||||
gboolean backend_get_key_value(
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
void* value_data
|
||||
);
|
||||
gboolean backend_set_key_value(
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
void* value_data
|
||||
);
|
||||
|
||||
#endif
|
||||
376
base/regsvc/src/main.c
Normal file
376
base/regsvc/src/main.c
Normal file
@@ -0,0 +1,376 @@
|
||||
#include <glib.h>
|
||||
#include <glib-unix.h>
|
||||
#include <signal.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/registry.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
|
||||
);
|
||||
|
||||
//
|
||||
// ENTRY POINT
|
||||
//
|
||||
int main(
|
||||
WINTC_UNUSED(int argc),
|
||||
WINTC_UNUSED(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
|
||||
);
|
||||
|
||||
g_unix_signal_add(
|
||||
SIGTERM,
|
||||
on_sigterm,
|
||||
NULL
|
||||
);
|
||||
g_main_loop_run(s_main_loop);
|
||||
|
||||
g_main_loop_unref(s_main_loop);
|
||||
|
||||
backend_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// 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);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ do_packaging()
|
||||
|
||||
# Build package now
|
||||
#
|
||||
(cd "${pkg_dir}/usr/local" && find . -type f,l) | sed 's/\.\///' > plist
|
||||
(cd "${pkg_dir}/usr/local" && find -L . -type f) | sed 's/\.\///' > plist
|
||||
pkg create -M manifest -r "${pkg_dir}" -p plist
|
||||
|
||||
cd "${CURDIR}"
|
||||
|
||||
55
packaging/cmake-inc/codegen/CMakeLists.txt
Normal file
55
packaging/cmake-inc/codegen/CMakeLists.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# Define function for gdbus-codegen
|
||||
#
|
||||
function(wintc_gdbus_codegen XML_FILE OUT_FILE_NOEXT CP_PUBLIC)
|
||||
find_program(GDBUS_CODEGEN gdbus-codegen REQUIRED)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/${OUT_FILE_NOEXT}.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/${OUT_FILE_NOEXT}.h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
COMMAND ${GDBUS_CODEGEN}
|
||||
ARGS
|
||||
--interface-prefix uk.oddmatics.wintc.
|
||||
--generate-c-code ${OUT_FILE_NOEXT}
|
||||
--c-namespace ZWin
|
||||
--c-generate-object-manager
|
||||
${XML_FILE}
|
||||
VERBATIM
|
||||
DEPENDS
|
||||
src/${XML_FILE}
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
dbus-codegen
|
||||
DEPENDS
|
||||
src/${OUT_FILE_NOEXT}.c
|
||||
src/${OUT_FILE_NOEXT}.h
|
||||
)
|
||||
|
||||
# If the header is needed in public/ for libraries then copy it
|
||||
#
|
||||
if (CP_PUBLIC)
|
||||
find_program(CP cp REQUIRED)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/public/${OUT_FILE_NOEXT}.h
|
||||
COMMAND ${CP}
|
||||
ARGS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/${OUT_FILE_NOEXT}.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/public/${OUT_FILE_NOEXT}.h
|
||||
VERBATIM
|
||||
DEPENDS
|
||||
src/${OUT_FILE_NOEXT}.h
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
dbus-codegen-header
|
||||
DEPENDS
|
||||
public/${OUT_FILE_NOEXT}.h
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
set(REPO_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../..)
|
||||
|
||||
@@ -26,7 +26,7 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
|
||||
add_definitions(-DWINTC_CHECKED)
|
||||
add_compile_definitions(WINTC_CHECKED)
|
||||
endif()
|
||||
|
||||
# Handle SKU stuff
|
||||
|
||||
@@ -16,6 +16,10 @@ if (NOT DEFINED WINTC_PKGMGR OR "${WINTC_PKGMGR}" STREQUAL "")
|
||||
set(WINTC_PKGMGR raw)
|
||||
endif()
|
||||
|
||||
# Export install prefix (useful for retrieving data at runtime)
|
||||
#
|
||||
add_compile_definitions(WINTC_RT_PREFIX="${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
# Set up library directory
|
||||
#
|
||||
if (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
base/bootvid
|
||||
base/bldtag
|
||||
base/logonui
|
||||
base/regsvc
|
||||
cursors/no-shadow/standard
|
||||
cursors/with-shadow/standard
|
||||
fonts
|
||||
@@ -9,6 +10,7 @@ sounds
|
||||
themes/native
|
||||
themes/professional
|
||||
themes/luna/blue
|
||||
shell/cpl/desk
|
||||
shell/cpl/printers
|
||||
shell/cpl/sysdm
|
||||
shell/desktop
|
||||
|
||||
2
private/play/dbus/.gitignore
vendored
Normal file
2
private/play/dbus/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Ignore generated output
|
||||
testreg-skel.*
|
||||
74
private/play/dbus/clt/CMakeLists.txt
Normal file
74
private/play/dbus/clt/CMakeLists.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(
|
||||
wintc-dbus-test-clt
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion DBus test client."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS true)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../../../packaging/cmake-inc/codegen/CMakeLists.txt)
|
||||
include(../../../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
|
||||
wintc_gdbus_codegen(
|
||||
testreg.xml
|
||||
testreg-skel
|
||||
)
|
||||
|
||||
add_executable(
|
||||
wintc-dbus-test-clt
|
||||
src/main.c
|
||||
src/testreg-skel.c
|
||||
src/testreg-skel.h
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
wintc-dbus-test-clt
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
wintc-dbus-test-clt
|
||||
SYSTEM
|
||||
BEFORE
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
wintc-dbus-test-clt
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
wintc-dbus-test-clt
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
|
||||
install(
|
||||
TARGETS wintc-dbus-test-clt
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
49
private/play/dbus/clt/src/main.c
Normal file
49
private/play/dbus/clt/src/main.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "testreg-skel.h"
|
||||
|
||||
//
|
||||
// ENTRY POINT
|
||||
//
|
||||
int main()
|
||||
{
|
||||
GError* error = NULL;
|
||||
WinTCTestregGDBUS* proxy;
|
||||
gchar* szoutput;
|
||||
|
||||
proxy =
|
||||
win_tc_testreg_gdbus_proxy_new_for_bus_sync(
|
||||
G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"uk.oddmatics.wintc.testreg",
|
||||
"/uk/oddmatics/wintc/testreg/GDBUS",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
if (!proxy)
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
win_tc_testreg_gdbus_call_testing_sync(
|
||||
proxy,
|
||||
"hello!",
|
||||
&szoutput,
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
if (error)
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_message("Client got: %s", szoutput);
|
||||
|
||||
g_object_unref(proxy);
|
||||
return 0;
|
||||
}
|
||||
8
private/play/dbus/clt/src/testreg.xml
Normal file
8
private/play/dbus/clt/src/testreg.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<node>
|
||||
<interface name="uk.oddmatics.wintc.testreg.GDBUS">
|
||||
<method name="Testing">
|
||||
<arg name="szinput" direction="in" type="s" />
|
||||
<arg name="szoutput" direction="out" type="s" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
75
private/play/dbus/srv/CMakeLists.txt
Normal file
75
private/play/dbus/srv/CMakeLists.txt
Normal file
@@ -0,0 +1,75 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(
|
||||
wintc-dbus-test-srv
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion DBus test server."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS true)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../../../packaging/cmake-inc/codegen/CMakeLists.txt)
|
||||
include(../../../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
|
||||
wintc_gdbus_codegen(
|
||||
testreg.xml
|
||||
testreg-skel
|
||||
FALSE
|
||||
)
|
||||
|
||||
add_executable(
|
||||
wintc-dbus-test-srv
|
||||
src/main.c
|
||||
src/testreg-skel.c
|
||||
src/testreg-skel.h
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
wintc-dbus-test-srv
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
wintc-dbus-test-srv
|
||||
SYSTEM
|
||||
BEFORE
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
wintc-dbus-test-srv
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
wintc-dbus-test-srv
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
|
||||
install(
|
||||
TARGETS wintc-dbus-test-srv
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
3
private/play/dbus/srv/deps
Normal file
3
private/play/dbus/srv/deps
Normal file
@@ -0,0 +1,3 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
98
private/play/dbus/srv/src/main.c
Normal file
98
private/play/dbus/srv/src/main.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "testreg-skel.h"
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void on_name_acquired(
|
||||
GDBusConnection* connection,
|
||||
const gchar* name,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static gboolean on_handle_testing(
|
||||
WinTCTestregGDBUS* iface,
|
||||
GDBusMethodInvocation* invocation,
|
||||
const gchar* szinput,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// ENTRY POINT
|
||||
//
|
||||
int main()
|
||||
{
|
||||
GMainLoop* loop;
|
||||
|
||||
loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
g_bus_own_name(
|
||||
G_BUS_TYPE_SESSION,
|
||||
"uk.oddmatics.wintc.testreg",
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
NULL,
|
||||
on_name_acquired,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_main_loop_run(loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void on_name_acquired(
|
||||
GDBusConnection* connection,
|
||||
WINTC_UNUSED(const gchar* name),
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
GError* error = NULL;
|
||||
WinTCTestregGDBUS* iface = win_tc_testreg_gdbus_skeleton_new();
|
||||
|
||||
g_signal_connect(
|
||||
iface,
|
||||
"handle-testing",
|
||||
G_CALLBACK(on_handle_testing),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (
|
||||
!g_dbus_interface_skeleton_export(
|
||||
G_DBUS_INTERFACE_SKELETON(iface),
|
||||
connection,
|
||||
"/uk/oddmatics/wintc/testreg/GDBUS",
|
||||
&error
|
||||
)
|
||||
)
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean on_handle_testing(
|
||||
WinTCTestregGDBUS* iface,
|
||||
GDBusMethodInvocation* invocation,
|
||||
const gchar* szinput,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
gchar* szoutput = g_strdup_printf("GDBUS IN: %s", szinput);
|
||||
|
||||
win_tc_testreg_gdbus_complete_testing(
|
||||
iface,
|
||||
invocation,
|
||||
szoutput
|
||||
);
|
||||
|
||||
g_message("%s", szoutput);
|
||||
g_free(szoutput);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
8
private/play/dbus/srv/src/testreg.xml
Normal file
8
private/play/dbus/srv/src/testreg.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<node>
|
||||
<interface name="uk.oddmatics.wintc.testreg.GDBUS">
|
||||
<method name="Testing">
|
||||
<arg name="szinput" direction="in" type="s" />
|
||||
<arg name="szoutput" direction="out" type="s" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
@@ -25,6 +25,8 @@ wintc_resolve_library(gdk-pixbuf-2.0 GDK_PIXBUF)
|
||||
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-shcommon WINTC_SHCOMMON)
|
||||
wintc_resolve_library(wintc-shlang WINTC_SHLANG)
|
||||
|
||||
wintc_compile_resources()
|
||||
|
||||
@@ -33,6 +35,8 @@ add_library(
|
||||
src/resources.c
|
||||
src/animctl.c
|
||||
public/animctl.h
|
||||
src/cpl.c
|
||||
public/cpl.h
|
||||
src/style.c
|
||||
public/style.h
|
||||
)
|
||||
@@ -57,6 +61,8 @@ target_include_directories(
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHCOMMON_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHLANG_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
@@ -65,6 +71,8 @@ target_link_directories(
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHCOMMON_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHLANG_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@@ -73,6 +81,8 @@ target_link_libraries(
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHCOMMON_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHLANG_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -2,3 +2,4 @@ bt,rt:gdk-pixbuf2
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-shlang
|
||||
|
||||
13
shared/comctl/public/cpl.h
Normal file
13
shared/comctl/public/cpl.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef __COMCTL_CPL_H__
|
||||
#define __COMCTL_CPL_H__
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
void wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GtkNotebook* notebook,
|
||||
const gchar* resource_path,
|
||||
...
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __WINTC_COMCTL_H__
|
||||
|
||||
#include "@LIB_HEADER_DIR@/animctl.h"
|
||||
#include "@LIB_HEADER_DIR@/cpl.h"
|
||||
#include "@LIB_HEADER_DIR@/style.h"
|
||||
|
||||
#endif
|
||||
|
||||
60
shared/comctl/src/cpl.c
Normal file
60
shared/comctl/src/cpl.c
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdarg.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shlang.h>
|
||||
|
||||
#include "../public/cpl.h"
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
void wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GtkNotebook* notebook,
|
||||
const gchar* resource_path,
|
||||
...
|
||||
)
|
||||
{
|
||||
GtkBuilder* builder;
|
||||
GtkWidget* box_page;
|
||||
GtkWidget* label_title;
|
||||
|
||||
builder = gtk_builder_new_from_resource(resource_path);
|
||||
|
||||
// Handle construction into UI
|
||||
//
|
||||
wintc_lc_builder_preprocess_widget_text(builder);
|
||||
|
||||
box_page = GTK_WIDGET(gtk_builder_get_object(builder, "page-box"));
|
||||
label_title = GTK_WIDGET(gtk_builder_get_object(builder, "label-title"));
|
||||
|
||||
gtk_notebook_append_page(
|
||||
notebook,
|
||||
box_page,
|
||||
label_title
|
||||
);
|
||||
|
||||
// Pull out objects as requested, args are provided as pairs (name, dstptr)
|
||||
//
|
||||
va_list ap;
|
||||
GtkWidget** next_dst;
|
||||
gchar* next_name;
|
||||
|
||||
va_start(ap, resource_path);
|
||||
|
||||
next_name = va_arg(ap, gchar*);
|
||||
|
||||
while (next_name)
|
||||
{
|
||||
next_dst = va_arg(ap, GtkWidget**);
|
||||
*next_dst = GTK_WIDGET(gtk_builder_get_object(builder, next_name));
|
||||
|
||||
// Iter
|
||||
//
|
||||
next_name = va_arg(ap, gchar*);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
g_object_unref(G_OBJECT(builder));
|
||||
}
|
||||
2
shared/registry/.gitignore
vendored
Normal file
2
shared/registry/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Ignore generated output
|
||||
reg-dbus.*
|
||||
91
shared/registry/CMakeLists.txt
Normal file
91
shared/registry/CMakeLists.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(
|
||||
libwintc-registry
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion registry library."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS true)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set(WINTC_NO_PEDANTIC_COMPILE true) # Necessary for gdbus-codegen
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/codegen/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/libraries/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
|
||||
wintc_gdbus_codegen(
|
||||
dbus-if.xml
|
||||
reg-dbus
|
||||
TRUE
|
||||
)
|
||||
|
||||
add_library(
|
||||
libwintc-registry
|
||||
public/reg-dbus.h
|
||||
src/reg-dbus.c
|
||||
src/reg-dbus.h
|
||||
src/regwrap.c
|
||||
public/regwrap.h
|
||||
src/variant.c
|
||||
public/variant.h
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
libwintc-registry
|
||||
PROPERTIES
|
||||
SOVERSION 1
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
libwintc-registry
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
libwintc-registry
|
||||
SYSTEM
|
||||
BEFORE
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
libwintc-registry
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
libwintc-registry
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
wintc_add_pkgconfig_install()
|
||||
wintc_install_public_headers()
|
||||
|
||||
install(
|
||||
TARGETS libwintc-registry
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
)
|
||||
5
shared/registry/README.MD
Normal file
5
shared/registry/README.MD
Normal file
@@ -0,0 +1,5 @@
|
||||
# libwintc-registry
|
||||
This directory contains the source code for the registry library.
|
||||
|
||||
## Purpose
|
||||
This library provides the GDBus interface and a simple client-side wrapper for interacting with the registry.
|
||||
4
shared/registry/deps
Normal file
4
shared/registry/deps
Normal file
@@ -0,0 +1,4 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:python3-packaging
|
||||
bt,rt:wintc-comgtk
|
||||
8
shared/registry/public/libapi.h.in
Normal file
8
shared/registry/public/libapi.h.in
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef __WINTC_REGISTRY_H__
|
||||
#define __WINTC_REGISTRY_H__
|
||||
|
||||
#include "@LIB_HEADER_DIR@/reg-dbus.h"
|
||||
#include "@LIB_HEADER_DIR@/regwrap.h"
|
||||
#include "@LIB_HEADER_DIR@/variant.h"
|
||||
|
||||
#endif
|
||||
80
shared/registry/public/regwrap.h
Normal file
80
shared/registry/public/regwrap.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef __REGISTRY_REGWRAP_H__
|
||||
#define __REGISTRY_REGWRAP_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
//
|
||||
// PUBLIC ENUMS
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
WINTC_REG_INVALID,
|
||||
WINTC_REG_DWORD,
|
||||
WINTC_REG_QWORD,
|
||||
WINTC_REG_SZ
|
||||
} WinTCRegistryValueType;
|
||||
|
||||
//
|
||||
// GLIB OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCRegistryClass WinTCRegistryClass;
|
||||
typedef struct _WinTCRegistry WinTCRegistry;
|
||||
|
||||
#define WINTC_TYPE_REGISTRY (wintc_registry_get_type())
|
||||
#define WINTC_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_REGISTRY, WinTCRegistry))
|
||||
#define WINTC_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_REGISTRY, WinTCRegistryClass))
|
||||
#define IS_WINTC_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_REGISTRY))
|
||||
#define IS_WINTC_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_REGISTRY))
|
||||
#define WINTC_REGISTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_REGISTRY, WinTCRegistry))
|
||||
|
||||
GType wintc_registry_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// CALLBACK PROTOTYPES
|
||||
//
|
||||
typedef void (*WinTCRegistryKeyCallback) (
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
GVariant* value_variant,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCRegistry* wintc_registry_new(void);
|
||||
|
||||
gboolean wintc_registry_create_key(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
GError** error
|
||||
);
|
||||
|
||||
gboolean wintc_registry_get_key_value(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
void* value_data,
|
||||
GError** error
|
||||
);
|
||||
|
||||
gboolean wintc_registry_set_key_value(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
const void* value_data,
|
||||
gboolean silent,
|
||||
GError** error
|
||||
);
|
||||
|
||||
void wintc_registry_watch_key(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
WinTCRegistryKeyCallback callback,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
#endif
|
||||
15
shared/registry/public/variant.h
Normal file
15
shared/registry/public/variant.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __REGISTRY_VARIANT_H__
|
||||
#define __REGISTRY_VARIANT_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "regwrap.h"
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCRegistryValueType wintc_registry_get_type_for_variant(
|
||||
GVariant* variant
|
||||
);
|
||||
|
||||
#endif
|
||||
30
shared/registry/src/dbus-if.xml
Normal file
30
shared/registry/src/dbus-if.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<node>
|
||||
<interface name="uk.oddmatics.wintc.registry.GDBUS">
|
||||
<method name="CreateKey">
|
||||
<arg name="key_path" direction="in" type="s" />
|
||||
<arg name="result" direction="out" type="i" />
|
||||
</method>
|
||||
|
||||
<method name="GetKeyValue">
|
||||
<arg name="key_path" direction="in" type="s" />
|
||||
<arg name="value_name" direction="in" type="s" />
|
||||
<arg name="value_type" direction="in" type="i" />
|
||||
<arg name="value_data" direction="out" type="v" />
|
||||
<arg name="result" direction="out" type="i" />
|
||||
</method>
|
||||
|
||||
<method name="SetKeyValue">
|
||||
<arg name="key_path" direction="in" type="s" />
|
||||
<arg name="value_name" direction="in" type="s" />
|
||||
<arg name="value_data" direction="in" type="v" />
|
||||
<arg name="silent" direction="in" type="b" />
|
||||
<arg name="result" direction="out" type="i" />
|
||||
</method>
|
||||
|
||||
<signal name="KeyValueChanged">
|
||||
<arg name="key_path" type="s" />
|
||||
<arg name="value_name" type="s" />
|
||||
<arg name="value_data" type="v" />
|
||||
</signal>
|
||||
</interface>
|
||||
</node>
|
||||
433
shared/registry/src/regwrap.c
Normal file
433
shared/registry/src/regwrap.c
Normal file
@@ -0,0 +1,433 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "../public/reg-dbus.h"
|
||||
#include "../public/regwrap.h"
|
||||
|
||||
//
|
||||
// PRIVATE STRUCTS
|
||||
//
|
||||
typedef struct _RegistryCBData
|
||||
{
|
||||
WinTCRegistryKeyCallback callback;
|
||||
gpointer user_data;
|
||||
} RegistryCBData;
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_registry_dispose(
|
||||
GObject* object
|
||||
);
|
||||
|
||||
static gboolean wintc_registry_ensure_proxy(
|
||||
WinTCRegistry* registry,
|
||||
GError** error
|
||||
);
|
||||
|
||||
static void on_reg_key_value_changed(
|
||||
ZWinRegistryGDBUS* proxy,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
GVariant* value_data,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GLIB OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCRegistryClass
|
||||
{
|
||||
GObjectClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCRegistry
|
||||
{
|
||||
GObject __parent__;
|
||||
|
||||
gboolean connected_signal;
|
||||
GHashTable* map_key_to_cb;
|
||||
ZWinRegistryGDBUS* proxy;
|
||||
};
|
||||
|
||||
//
|
||||
// GLIB TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCRegistry,
|
||||
wintc_registry,
|
||||
G_TYPE_OBJECT
|
||||
)
|
||||
|
||||
static void wintc_registry_class_init(
|
||||
WinTCRegistryClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = wintc_registry_dispose;
|
||||
}
|
||||
|
||||
static void wintc_registry_init(
|
||||
WinTCRegistry* self
|
||||
)
|
||||
{
|
||||
self->map_key_to_cb =
|
||||
g_hash_table_new_full(
|
||||
g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_registry_dispose(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCRegistry* registry = WINTC_REGISTRY(object);
|
||||
|
||||
g_hash_table_destroy(
|
||||
registry->map_key_to_cb
|
||||
);
|
||||
|
||||
(G_OBJECT_CLASS(wintc_registry_parent_class))->dispose(object);
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCRegistry* wintc_registry_new(void)
|
||||
{
|
||||
return WINTC_REGISTRY(
|
||||
g_object_new(
|
||||
WINTC_TYPE_REGISTRY,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
gboolean wintc_registry_create_key(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
GError* local_error = NULL;
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
if (!wintc_registry_ensure_proxy(registry, &local_error))
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Perform dbus call
|
||||
//
|
||||
gint result = 0;
|
||||
|
||||
if (
|
||||
!zwin_registry_gdbus_call_create_key_sync(
|
||||
registry->proxy,
|
||||
key_path,
|
||||
&result,
|
||||
NULL,
|
||||
&local_error
|
||||
)
|
||||
)
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return !!result;
|
||||
}
|
||||
|
||||
gboolean wintc_registry_get_key_value(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
void* value_data,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
GError* local_error = NULL;
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
switch (value_type)
|
||||
{
|
||||
case WINTC_REG_DWORD: *((gint*) value_data) = 0; break;
|
||||
case WINTC_REG_QWORD: *((gint64*) value_data) = 0; break;
|
||||
case WINTC_REG_SZ: *((gchar**) value_data) = NULL; break;
|
||||
|
||||
default:
|
||||
g_critical("registry: unknown type %d", value_type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!wintc_registry_ensure_proxy(registry, &local_error))
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Perform dbus call
|
||||
//
|
||||
gint result = 0;
|
||||
GVariant* value_variant = NULL;
|
||||
|
||||
if (
|
||||
!zwin_registry_gdbus_call_get_key_value_sync(
|
||||
registry->proxy,
|
||||
key_path,
|
||||
value_name,
|
||||
value_type,
|
||||
&value_variant,
|
||||
&result,
|
||||
NULL,
|
||||
&local_error
|
||||
)
|
||||
)
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
GVariant* inner = g_variant_get_variant(value_variant);
|
||||
|
||||
switch (value_type)
|
||||
{
|
||||
case WINTC_REG_DWORD:
|
||||
*((gint*) value_data) =
|
||||
g_variant_get_int32(inner);
|
||||
break;
|
||||
|
||||
case WINTC_REG_QWORD:
|
||||
*((gint64*) value_data) =
|
||||
g_variant_get_int64(inner);
|
||||
break;
|
||||
|
||||
case WINTC_REG_SZ:
|
||||
*((gchar**) value_data) =
|
||||
g_variant_dup_string(inner, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical("registry: unknown type %d", value_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_variant_unref(value_variant);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean wintc_registry_set_key_value(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
WinTCRegistryValueType value_type,
|
||||
const void* value_data,
|
||||
gboolean silent,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
GError* local_error = NULL;
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
if (!wintc_registry_ensure_proxy(registry, &local_error))
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Set up variant
|
||||
//
|
||||
GVariant* value_variant = NULL;
|
||||
|
||||
switch (value_type)
|
||||
{
|
||||
case WINTC_REG_DWORD:
|
||||
value_variant =
|
||||
g_variant_new(
|
||||
"v",
|
||||
g_variant_new_int32(
|
||||
*((const gint*) value_data)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_REG_QWORD:
|
||||
value_variant =
|
||||
g_variant_new(
|
||||
"v",
|
||||
g_variant_new_int64(
|
||||
*((const gint64*) value_data)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_REG_SZ:
|
||||
value_variant =
|
||||
g_variant_new(
|
||||
"v",
|
||||
g_variant_new_string(
|
||||
*((const gchar**) value_data)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical("registry: unknown type %d", value_type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Perform dbus call
|
||||
//
|
||||
gint result = 0;
|
||||
|
||||
if (
|
||||
!zwin_registry_gdbus_call_set_key_value_sync(
|
||||
registry->proxy,
|
||||
key_path,
|
||||
value_name,
|
||||
value_variant,
|
||||
silent,
|
||||
&result,
|
||||
NULL,
|
||||
&local_error
|
||||
)
|
||||
)
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return !!result;
|
||||
}
|
||||
|
||||
void wintc_registry_watch_key(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
WinTCRegistryKeyCallback callback,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
GError* error = NULL;
|
||||
|
||||
if (!wintc_registry_ensure_proxy(registry, &error))
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add watcher
|
||||
//
|
||||
RegistryCBData* cb_data = g_new(RegistryCBData, 1);
|
||||
|
||||
cb_data->callback = callback;
|
||||
cb_data->user_data = user_data;
|
||||
|
||||
if (!registry->connected_signal)
|
||||
{
|
||||
g_signal_connect(
|
||||
registry->proxy,
|
||||
"key-value-changed",
|
||||
G_CALLBACK(on_reg_key_value_changed),
|
||||
registry
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!g_hash_table_replace(
|
||||
registry->map_key_to_cb,
|
||||
g_strdup(key_path),
|
||||
cb_data
|
||||
)
|
||||
)
|
||||
{
|
||||
g_warning("registry: overwritten key watcher for %s", key_path);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static gboolean wintc_registry_ensure_proxy(
|
||||
WinTCRegistry* registry,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
GError* local_error = NULL;
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
if (registry->proxy)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
registry->proxy =
|
||||
zwin_registry_gdbus_proxy_new_for_bus_sync(
|
||||
G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"uk.oddmatics.wintc.registry",
|
||||
"/uk/oddmatics/wintc/registry/GDBUS",
|
||||
NULL,
|
||||
&local_error
|
||||
);
|
||||
|
||||
if (!registry->proxy)
|
||||
{
|
||||
g_propagate_error(error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void on_reg_key_value_changed(
|
||||
WINTC_UNUSED(ZWinRegistryGDBUS* proxy),
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
GVariant* value_data,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCRegistry* registry = WINTC_REGISTRY(user_data);
|
||||
|
||||
// Look up if there's a handler for this key
|
||||
//
|
||||
RegistryCBData* cb_data =
|
||||
g_hash_table_lookup(registry->map_key_to_cb, key_path);
|
||||
|
||||
if (!cb_data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Issue the callback
|
||||
//
|
||||
GVariant* inner = g_variant_get_variant(value_data);
|
||||
|
||||
cb_data->callback(
|
||||
registry,
|
||||
key_path,
|
||||
value_name,
|
||||
inner,
|
||||
cb_data->user_data
|
||||
);
|
||||
}
|
||||
28
shared/registry/src/variant.c
Normal file
28
shared/registry/src/variant.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "../public/regwrap.h"
|
||||
#include "../public/variant.h"
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCRegistryValueType wintc_registry_get_type_for_variant(
|
||||
GVariant* variant
|
||||
)
|
||||
{
|
||||
if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32))
|
||||
{
|
||||
return WINTC_REG_DWORD;
|
||||
}
|
||||
else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT64))
|
||||
{
|
||||
return WINTC_REG_QWORD;
|
||||
}
|
||||
else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING))
|
||||
{
|
||||
return WINTC_REG_SZ;
|
||||
}
|
||||
|
||||
return WINTC_REG_INVALID;
|
||||
}
|
||||
@@ -26,6 +26,8 @@ wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
|
||||
add_library(
|
||||
libwintc-shcommon
|
||||
src/fs.c
|
||||
public/fs.h
|
||||
src/path.c
|
||||
public/path.h
|
||||
src/places.c
|
||||
|
||||
15
shared/shcommon/public/fs.h
Normal file
15
shared/shcommon/public/fs.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __SHCOMMON_FS_H__
|
||||
#define __SHCOMMON_FS_H__
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GSList* wintc_sh_fs_get_names_as_list(
|
||||
const gchar* path,
|
||||
gboolean full_names,
|
||||
GFileTest test,
|
||||
gboolean recursive,
|
||||
GError** error
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __WINTC_SHCOMMON_H__
|
||||
#define __WINTC_SHCOMMON_H__
|
||||
|
||||
#include "@LIB_HEADER_DIR@/fs.h"
|
||||
#include "@LIB_HEADER_DIR@/path.h"
|
||||
#include "@LIB_HEADER_DIR@/places.h"
|
||||
|
||||
|
||||
93
shared/shcommon/src/fs.c
Normal file
93
shared/shcommon/src/fs.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "../public/fs.h"
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GSList* wintc_sh_fs_get_names_as_list(
|
||||
const gchar* path,
|
||||
gboolean full_names,
|
||||
GFileTest test,
|
||||
gboolean recursive,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
GDir* dir;
|
||||
const gchar* dir_entry = NULL;
|
||||
GSList* dirs_to_enum = NULL;
|
||||
GSList* entries = NULL;
|
||||
GSList* iter = NULL;
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
WINTC_LOG_DEBUG(
|
||||
"shcommon: enum dir %s%s",
|
||||
path,
|
||||
recursive ? " (recursive)" : ""
|
||||
);
|
||||
|
||||
// Push requested path as the first item
|
||||
//
|
||||
dirs_to_enum = g_slist_append(dirs_to_enum, g_strdup(path));
|
||||
iter = dirs_to_enum;
|
||||
|
||||
while (iter)
|
||||
{
|
||||
WINTC_LOG_DEBUG("shcommon: enum iter dir %s", (gchar*) iter->data);
|
||||
|
||||
dir = g_dir_open((gchar*) iter->data, 0, error);
|
||||
|
||||
if (!dir)
|
||||
{
|
||||
g_slist_free_full(dirs_to_enum, g_free);
|
||||
g_slist_free_full(entries, g_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((dir_entry = g_dir_read_name(dir)))
|
||||
{
|
||||
gchar* full_path =
|
||||
g_build_path(
|
||||
G_DIR_SEPARATOR_S,
|
||||
(gchar*) iter->data,
|
||||
dir_entry,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Take a copy into dirs to enum if needed
|
||||
//
|
||||
if (recursive && g_file_test(full_path, G_FILE_TEST_IS_DIR))
|
||||
{
|
||||
WINTC_LOG_DEBUG("shcommon: enum iter, add dir %s", dir_entry);
|
||||
|
||||
dirs_to_enum =
|
||||
g_slist_append(dirs_to_enum, g_strdup(full_path));
|
||||
}
|
||||
|
||||
// Move into entries list if it's one we're interested in
|
||||
//
|
||||
if (!test || g_file_test(full_path, test))
|
||||
{
|
||||
entries =
|
||||
g_slist_append(
|
||||
entries,
|
||||
g_strdup(full_names ? full_path : dir_entry)
|
||||
);
|
||||
}
|
||||
|
||||
g_free(full_path);
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
|
||||
// Iter to next dir
|
||||
//
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
g_slist_free_full(dirs_to_enum, g_free);
|
||||
|
||||
return entries;
|
||||
}
|
||||
@@ -37,8 +37,6 @@ add_library(
|
||||
public/cpl.h
|
||||
src/error.c
|
||||
public/error.h
|
||||
src/fs.c
|
||||
src/fs.h
|
||||
src/icnvwbeh.c
|
||||
public/icnvwbeh.h
|
||||
public/trevwbeh.h
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shcommon.h>
|
||||
|
||||
#include "../public/cpl.h"
|
||||
#include "fs.h"
|
||||
|
||||
//
|
||||
// PRIVATE CONSTANTS
|
||||
@@ -20,7 +20,14 @@ static const gchar* S_CPL_KEY_ICON_NAME = "Icon";
|
||||
//
|
||||
GSList* wintc_sh_cpl_applet_get_all(void)
|
||||
{
|
||||
GSList* entries = wintc_sh_fs_get_names_as_list(S_CPL_ENTRIES_DIR, TRUE, NULL);
|
||||
GSList* entries =
|
||||
wintc_sh_fs_get_names_as_list(
|
||||
S_CPL_ENTRIES_DIR,
|
||||
TRUE,
|
||||
G_FILE_TEST_IS_REGULAR,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!entries)
|
||||
{
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "fs.h"
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GSList* wintc_sh_fs_get_names_as_list(
|
||||
const gchar* path,
|
||||
gboolean full_names,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
GDir* dir;
|
||||
const gchar* dir_entry = NULL;
|
||||
GSList* entries = NULL;
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(error);
|
||||
|
||||
WINTC_LOG_DEBUG("fs: enum dir %s", path);
|
||||
|
||||
dir = g_dir_open(path, 0, error);
|
||||
|
||||
if (!dir)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((dir_entry = g_dir_read_name(dir)))
|
||||
{
|
||||
gchar* next_name = full_names ?
|
||||
g_build_path(
|
||||
G_DIR_SEPARATOR_S,
|
||||
path,
|
||||
dir_entry,
|
||||
NULL
|
||||
) :
|
||||
g_strdup(dir_entry);
|
||||
|
||||
entries = g_slist_append(entries, next_name);
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
|
||||
return entries;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef __FS_H__
|
||||
#define __FS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
//
|
||||
// FIXME: Temp! fs.c/h should be moved to another lib!
|
||||
//
|
||||
// For now we just have sync I/O here, we need:
|
||||
// - Should move to async I/O
|
||||
// - Move FS stuff to a separate lib
|
||||
// - MIME type detection
|
||||
// - Symlink/shortcut handling
|
||||
//
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GSList* wintc_sh_fs_get_names_as_list(
|
||||
const gchar* path,
|
||||
gboolean full_names,
|
||||
GError** error
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <wintc/shcommon.h>
|
||||
|
||||
#include "../public/vwfs.h"
|
||||
#include "fs.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
@@ -262,7 +261,14 @@ void wintc_sh_view_fs_refresh_items(
|
||||
|
||||
// FIXME: Error handling (no way of passing to caller)
|
||||
//
|
||||
GSList* entries = wintc_sh_fs_get_names_as_list(view_fs->path, FALSE, NULL);
|
||||
GSList* entries =
|
||||
wintc_sh_fs_get_names_as_list(
|
||||
view_fs->path,
|
||||
FALSE,
|
||||
0,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Create actual array
|
||||
// FIXME: list->array should probs be in comgtk
|
||||
|
||||
116
shell/cpl/desk/CMakeLists.txt
Normal file
116
shell/cpl/desk/CMakeLists.txt
Normal file
@@ -0,0 +1,116 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(
|
||||
wintc-cpl-desk
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion Display Control Panel applet."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS true)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../../packaging/cmake-inc/locale/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-comctl WINTC_COMCTL)
|
||||
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-shlang WINTC_SHLANG)
|
||||
|
||||
wintc_compile_resources()
|
||||
wintc_create_meta_h()
|
||||
|
||||
add_executable(
|
||||
wintc-cpl-desk
|
||||
src/application.c
|
||||
src/application.h
|
||||
src/main.c
|
||||
src/meta.h
|
||||
src/monitor.c
|
||||
src/monitor.h
|
||||
src/resources.c
|
||||
src/settings.c
|
||||
src/settings.h
|
||||
src/window.c
|
||||
src/window.h
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
wintc-cpl-desk
|
||||
PROPERTIES
|
||||
OUTPUT_NAME desk.cpl
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
wintc-cpl-desk
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
wintc-cpl-desk
|
||||
SYSTEM
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_REGISTRY_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHCOMMON_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHLANG_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
wintc-cpl-desk
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_REGISTRY_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHCOMMON_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHLANG_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
wintc-cpl-desk
|
||||
PRIVATE m
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_REGISTRY_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHCOMMON_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHLANG_LIBRARIES}
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
wintc-cpl-desk
|
||||
build-gresources
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
|
||||
install(
|
||||
FILES desk.desktop
|
||||
DESTINATION share/wintc/cpl
|
||||
)
|
||||
install(
|
||||
FILES uk.co.oddmatics.wintc.cpl-desk.desktop
|
||||
DESTINATION share/applications
|
||||
)
|
||||
install(
|
||||
TARGETS wintc-cpl-desk
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
7
shell/cpl/desk/deps
Normal file
7
shell/cpl/desk/deps
Normal file
@@ -0,0 +1,7 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comctl
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-registry
|
||||
bt,rt:wintc-shcommon
|
||||
bt,rt:wintc-shlang
|
||||
5
shell/cpl/desk/desk.desktop
Normal file
5
shell/cpl/desk/desk.desktop
Normal file
@@ -0,0 +1,5 @@
|
||||
[CplApplet]
|
||||
Name=Display
|
||||
Comment=Change the appearance of your desktop, such as the background, screen saver, colors, font sizes, and screen resolution.
|
||||
Exec=desk.cpl
|
||||
Icon=preferences-desktop-display
|
||||
97
shell/cpl/desk/src/application.c
Normal file
97
shell/cpl/desk/src/application.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc/comctl.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "window.h"
|
||||
|
||||
//
|
||||
// CONSTANTS
|
||||
//
|
||||
static const gchar* S_APP_ID = "uk.co.oddmatics.wintc.cpl-desk";
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCCplDeskApplicationClass
|
||||
{
|
||||
GtkApplicationClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCCplDeskApplication
|
||||
{
|
||||
GtkApplication __parent__;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_cpl_desk_application_activate(
|
||||
GApplication* application
|
||||
);
|
||||
static void wintc_cpl_desk_application_startup(
|
||||
GApplication* application
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCCplDeskApplication,
|
||||
wintc_cpl_desk_application,
|
||||
GTK_TYPE_APPLICATION
|
||||
)
|
||||
|
||||
static void wintc_cpl_desk_application_class_init(
|
||||
WinTCCplDeskApplicationClass* klass
|
||||
)
|
||||
{
|
||||
GApplicationClass* application_class = G_APPLICATION_CLASS(klass);
|
||||
|
||||
application_class->activate = wintc_cpl_desk_application_activate;
|
||||
application_class->startup = wintc_cpl_desk_application_startup;
|
||||
}
|
||||
|
||||
static void wintc_cpl_desk_application_init(
|
||||
WINTC_UNUSED(WinTCCplDeskApplication* self)
|
||||
) { }
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_cpl_desk_application_activate(
|
||||
GApplication* application
|
||||
)
|
||||
{
|
||||
GtkWidget* new_window =
|
||||
wintc_cpl_desk_window_new(WINTC_CPL_DESK_APPLICATION(application));
|
||||
|
||||
gtk_widget_show_all(new_window);
|
||||
}
|
||||
|
||||
static void wintc_cpl_desk_application_startup(
|
||||
GApplication* application
|
||||
)
|
||||
{
|
||||
(G_APPLICATION_CLASS(wintc_cpl_desk_application_parent_class))
|
||||
->startup(application);
|
||||
|
||||
g_set_prgname(S_APP_ID);
|
||||
|
||||
wintc_ctl_install_default_styles();
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCCplDeskApplication* wintc_cpl_desk_application_new(void)
|
||||
{
|
||||
return WINTC_CPL_DESK_APPLICATION(
|
||||
g_object_new(
|
||||
wintc_cpl_desk_application_get_type(),
|
||||
"application-id", S_APP_ID,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
27
shell/cpl/desk/src/application.h
Normal file
27
shell/cpl/desk/src/application.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef __APPLICATION_H__
|
||||
#define __APPLICATION_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCCplDeskApplicationClass WinTCCplDeskApplicationClass;
|
||||
typedef struct _WinTCCplDeskApplication WinTCCplDeskApplication;
|
||||
|
||||
#define WINTC_TYPE_CPL_DESK_APPLICATION (wintc_cpl_desk_application_get_type())
|
||||
#define WINTC_CPL_DESK_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_CPL_DESK_APPLICATION, WinTCCplDeskApplication))
|
||||
#define WINTC_CPL_DESK_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_CPL_DESK_APPLICATION, WinTCCplDeskApplicationClass))
|
||||
#define IS_WINTC_CPL_DESK_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_CPL_DESK_APPLICATION))
|
||||
#define IS_WINTC_CPL_DESK_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_CPL_DESK_APPLICATION))
|
||||
#define WINTC_CPL_DESK_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_CPL_DESK_APPLICATION, WinTCCplDeskApplicationClass))
|
||||
|
||||
GType wintc_cpl_desk_application_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCCplDeskApplication* wintc_cpl_desk_application_new(void);
|
||||
|
||||
#endif
|
||||
32
shell/cpl/desk/src/main.c
Normal file
32
shell/cpl/desk/src/main.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <locale.h>
|
||||
#include <wintc/shlang.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "meta.h"
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char* argv[]
|
||||
)
|
||||
{
|
||||
// Set up locales
|
||||
//
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PKG_NAME, WINTC_LOCALE_DIR);
|
||||
textdomain(PKG_NAME);
|
||||
|
||||
// Launch application
|
||||
//
|
||||
WinTCCplDeskApplication* app = wintc_cpl_desk_application_new();
|
||||
int status;
|
||||
|
||||
g_set_application_name("Display");
|
||||
|
||||
status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||
|
||||
g_object_unref(app);
|
||||
|
||||
return status;
|
||||
}
|
||||
303
shell/cpl/desk/src/monitor.c
Normal file
303
shell/cpl/desk/src/monitor.c
Normal file
@@ -0,0 +1,303 @@
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <math.h>
|
||||
#include <wintc/comgtk.h>
|
||||
|
||||
#include "monitor.h"
|
||||
|
||||
//
|
||||
// STATIC CONSTANTS
|
||||
//
|
||||
static const gint S_PREVIEW_IMAGE_OFFSET_X = 16;
|
||||
static const gint S_PREVIEW_IMAGE_OFFSET_Y = 17;
|
||||
|
||||
static const gint S_PREVIEW_IMAGE_WIDTH = 152;
|
||||
static const gint S_PREVIEW_IMAGE_HEIGHT = 112;
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCDeskMonitorClass
|
||||
{
|
||||
GtkWidgetClass __parent__;
|
||||
|
||||
GdkPixbuf* pixbuf_monitor;
|
||||
cairo_surface_t* surface_monitor;
|
||||
|
||||
gint pixbuf_monitor_height;
|
||||
gint pixbuf_monitor_width;
|
||||
};
|
||||
|
||||
struct _WinTCDeskMonitor
|
||||
{
|
||||
GtkWidget __parent__;
|
||||
|
||||
// UI
|
||||
//
|
||||
GdkPixbuf* pixbuf_preview;
|
||||
cairo_surface_t* surface_preview;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_desk_monitor_dispose(
|
||||
GObject* object
|
||||
);
|
||||
|
||||
static gboolean wintc_desk_monitor_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
);
|
||||
static void wintc_desk_monitor_get_preferred_height(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
);
|
||||
static void wintc_desk_monitor_get_preferred_height_for_width(
|
||||
GtkWidget* widget,
|
||||
gint width,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
);
|
||||
static void wintc_desk_monitor_get_preferred_width(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
);
|
||||
static void wintc_desk_monitor_get_preferred_width_for_height(
|
||||
GtkWidget* widget,
|
||||
gint height,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCDeskMonitor,
|
||||
wintc_desk_monitor,
|
||||
GTK_TYPE_WIDGET
|
||||
)
|
||||
|
||||
static void wintc_desk_monitor_class_init(
|
||||
WinTCDeskMonitorClass* klass
|
||||
)
|
||||
{
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = wintc_desk_monitor_dispose;
|
||||
|
||||
widget_class->draw =
|
||||
wintc_desk_monitor_draw;
|
||||
widget_class->get_preferred_height =
|
||||
wintc_desk_monitor_get_preferred_height;
|
||||
widget_class->get_preferred_height_for_width =
|
||||
wintc_desk_monitor_get_preferred_height_for_width;
|
||||
widget_class->get_preferred_width =
|
||||
wintc_desk_monitor_get_preferred_width;
|
||||
widget_class->get_preferred_width_for_height =
|
||||
wintc_desk_monitor_get_preferred_width_for_height;
|
||||
|
||||
// Load shared monitor graphic resource
|
||||
//
|
||||
GError* error = NULL;
|
||||
|
||||
klass->pixbuf_monitor =
|
||||
gdk_pixbuf_new_from_resource(
|
||||
"/uk/oddmatics/wintc/cpl-desk/monitor.png",
|
||||
&error
|
||||
);
|
||||
|
||||
wintc_log_error_and_clear(&error);
|
||||
|
||||
if (klass->pixbuf_monitor)
|
||||
{
|
||||
klass->surface_monitor =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
klass->pixbuf_monitor,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
klass->pixbuf_monitor_height =
|
||||
gdk_pixbuf_get_height(
|
||||
klass->pixbuf_monitor
|
||||
);
|
||||
klass->pixbuf_monitor_width =
|
||||
gdk_pixbuf_get_width(
|
||||
klass->pixbuf_monitor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void wintc_desk_monitor_init(
|
||||
WinTCDeskMonitor* self
|
||||
)
|
||||
{
|
||||
gtk_widget_set_has_window(GTK_WIDGET(self), FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_desk_monitor_dispose(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCDeskMonitor* monitor = WINTC_DESK_MONITOR(object);
|
||||
|
||||
g_clear_object(&(monitor->pixbuf_preview));
|
||||
cairo_surface_destroy(g_steal_pointer(&monitor->surface_preview));
|
||||
}
|
||||
|
||||
static gboolean wintc_desk_monitor_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
)
|
||||
{
|
||||
WinTCDeskMonitorClass* klass = WINTC_DESK_MONITOR_GET_CLASS(widget);
|
||||
WinTCDeskMonitor* monitor = WINTC_DESK_MONITOR(widget);
|
||||
|
||||
// monitor size
|
||||
gint monitor_height = klass->pixbuf_monitor_height;
|
||||
gint monitor_width = klass->pixbuf_monitor_width;
|
||||
|
||||
// my size
|
||||
gint my_height = gtk_widget_get_allocated_height(widget);
|
||||
gint my_width = gtk_widget_get_allocated_width(widget);
|
||||
|
||||
// drawing origin
|
||||
gdouble target_x = floor((my_width / 2.0f) - (monitor_width / 2.0f));
|
||||
gdouble target_y = floor((my_height / 2.0f) - (monitor_height / 2.0f));
|
||||
|
||||
cairo_translate(
|
||||
cr,
|
||||
target_x,
|
||||
target_y
|
||||
);
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
klass->surface_monitor,
|
||||
0.0f,
|
||||
0.0f
|
||||
);
|
||||
cairo_pattern_set_extend(
|
||||
cairo_get_source(cr),
|
||||
CAIRO_EXTEND_NONE
|
||||
);
|
||||
cairo_paint(cr);
|
||||
|
||||
if (monitor->surface_preview)
|
||||
{
|
||||
cairo_translate(
|
||||
cr,
|
||||
S_PREVIEW_IMAGE_OFFSET_X,
|
||||
S_PREVIEW_IMAGE_OFFSET_Y
|
||||
);
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
monitor->surface_preview,
|
||||
0.0f,
|
||||
0.0f
|
||||
);
|
||||
cairo_pattern_set_extend(
|
||||
cairo_get_source(cr),
|
||||
CAIRO_EXTEND_NONE
|
||||
);
|
||||
cairo_paint(cr);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void wintc_desk_monitor_get_preferred_height(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
)
|
||||
{
|
||||
WinTCDeskMonitorClass* klass = WINTC_DESK_MONITOR_GET_CLASS(widget);
|
||||
|
||||
*minimum_height = klass->pixbuf_monitor_height;
|
||||
*natural_height = klass->pixbuf_monitor_height;
|
||||
}
|
||||
|
||||
static void wintc_desk_monitor_get_preferred_height_for_width(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(gint width),
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
)
|
||||
{
|
||||
wintc_desk_monitor_get_preferred_height(
|
||||
widget,
|
||||
minimum_height,
|
||||
natural_height
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_desk_monitor_get_preferred_width(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
)
|
||||
{
|
||||
WinTCDeskMonitorClass* klass = WINTC_DESK_MONITOR_GET_CLASS(widget);
|
||||
|
||||
*minimum_width = klass->pixbuf_monitor_width;
|
||||
*natural_width = klass->pixbuf_monitor_width;
|
||||
}
|
||||
|
||||
static void wintc_desk_monitor_get_preferred_width_for_height(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(gint height),
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
)
|
||||
{
|
||||
wintc_desk_monitor_get_preferred_width(
|
||||
widget,
|
||||
minimum_width,
|
||||
natural_width
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_desk_monitor_new(void)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
WINTC_TYPE_DESK_MONITOR,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void wintc_desk_monitor_set_pixbuf(
|
||||
WinTCDeskMonitor* monitor,
|
||||
const GdkPixbuf* pixbuf
|
||||
)
|
||||
{
|
||||
g_clear_object(&(monitor->pixbuf_preview));
|
||||
cairo_surface_destroy(g_steal_pointer(&monitor->surface_preview));
|
||||
|
||||
monitor->pixbuf_preview =
|
||||
gdk_pixbuf_scale_simple(
|
||||
pixbuf,
|
||||
S_PREVIEW_IMAGE_WIDTH,
|
||||
S_PREVIEW_IMAGE_HEIGHT,
|
||||
GDK_INTERP_NEAREST
|
||||
);
|
||||
monitor->surface_preview =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
monitor->pixbuf_preview,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
33
shell/cpl/desk/src/monitor.h
Normal file
33
shell/cpl/desk/src/monitor.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __MONITOR_H__
|
||||
#define __MONITOR_H__
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCDeskMonitorClass WinTCDeskMonitorClass;
|
||||
typedef struct _WinTCDeskMonitor WinTCDeskMonitor;
|
||||
|
||||
#define WINTC_TYPE_DESK_MONITOR (wintc_desk_monitor_get_type())
|
||||
#define WINTC_DESK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_DESK_MONITOR, WinTCDeskMonitor))
|
||||
#define WINTC_DESK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_DESK_MONITOR, WinTCDeskMonitorClass))
|
||||
#define IS_WINTC_DESK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_DESK_MONITOR))
|
||||
#define IS_WINTC_DESK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_DESK_MONITOR))
|
||||
#define WINTC_DESK_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_DESK_MONITOR, WinTCDeskMonitorClass))
|
||||
|
||||
GType wintc_desk_monitor_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_desk_monitor_new(void);
|
||||
|
||||
void wintc_desk_monitor_set_pixbuf(
|
||||
WinTCDeskMonitor* monitor,
|
||||
const GdkPixbuf* pixbuf
|
||||
);
|
||||
|
||||
#endif
|
||||
80
shell/cpl/desk/src/res/desk.ui
Normal file
80
shell/cpl/desk/src/res/desk.ui
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkBox" id="main-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="main-notebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-apply">
|
||||
<property name="label" translatable="no">Apply</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.apply</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-cancel">
|
||||
<property name="label" translatable="no">%CTL_CANCEL%</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.cancel</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button-ok">
|
||||
<property name="label" translatable="no">%CTL_OK%</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.ok</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="wintc-button-box"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
BIN
shell/cpl/desk/src/res/monitor.png
Normal file
BIN
shell/cpl/desk/src/res/monitor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
164
shell/cpl/desk/src/res/page-appearance.ui
Normal file
164
shell/cpl/desk/src/res/page-appearance.ui
Normal file
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkLabel" id="label-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="label" translatable="yes">Appearance</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="page-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<!-- TODO: Need theme preview thing - uxtheme -->
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<!-- Drop downs column -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Windows and buttons:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Color scheme:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Font size:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- Side buttons column -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="valign">2</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="halign">2</property>
|
||||
<property name="label" translatable="yes">Effects...</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="halign">2</property>
|
||||
<property name="label" translatable="yes">Advanced</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
183
shell/cpl/desk/src/res/page-desktop.ui
Normal file
183
shell/cpl/desk/src/res/page-desktop.ui
Normal file
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkLabel" id="label-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="label" translatable="yes">Desktop</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="page-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="WinTCDeskMonitor" id="monitor">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Background:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- Form stuff - one horizontal outer box with two inner vert boxes -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<!-- Wallpaper selection -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="overlay-scrolling">False</property>
|
||||
<property name="vscrollbar-policy">0</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBox" id="listbox-wallpapers">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="yes">Customize Desktop...</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- Additional wallpaper settings -->
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="yes">%PUNC_MOREINPUT%%CTL_BROWSE%</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Position:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Color:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
219
shell/cpl/desk/src/res/page-scrnsave.ui
Normal file
219
shell/cpl/desk/src/res/page-scrnsave.ui
Normal file
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkLabel" id="label-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="label" translatable="yes">Screen Saver</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="page-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="WinTCDeskMonitor" id="monitor">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- Screen saver options -->
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Screen saver</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="yes">Settings</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="label" translatable="yes">Preview</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Wait:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">minutes</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">On resume, display Welcome screen</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Monitor power</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">To adjust monitor power settings and save energy, click Power.</property>
|
||||
<property name="max-width-chars">49</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">1.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="halign">2</property>
|
||||
<property name="label" translatable="yes">Power</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
187
shell/cpl/desk/src/res/page-settings.ui
Normal file
187
shell/cpl/desk/src/res/page-settings.ui
Normal file
@@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkLabel" id="label-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="label" translatable="yes">Settings</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="page-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<!-- TODO: Need monitor preview widget -->
|
||||
<child>
|
||||
<object class="WinTCDeskMonitor" id="monitor">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Display:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">(not implemented)</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<!-- Screen resolution frame -->
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Screen resolution</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Less</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">More</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">blam! pixels</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Color quality</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- TODO: Color graphic thing here -->
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
113
shell/cpl/desk/src/res/page-themes.ui
Normal file
113
shell/cpl/desk/src/res/page-themes.ui
Normal file
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkLabel" id="label-title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="label" translatable="yes">Themes</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="page-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">A theme is a background plus a set of sounds, icons, and other elements to help you personalize your computer with one click.</property>
|
||||
<property name="max-width-chars">71</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- Theme selection -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Theme:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkComboBox">
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">%CTL_SAVEAS%</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">%CTL_DELETE%</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<!-- Theme preview -->
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Sample:</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
13
shell/cpl/desk/src/res/resources.xml
Normal file
13
shell/cpl/desk/src/res/resources.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/uk/oddmatics/wintc/cpl-desk">
|
||||
<file>desk.ui</file>
|
||||
<file>page-appearance.ui</file>
|
||||
<file>page-desktop.ui</file>
|
||||
<file>page-scrnsave.ui</file>
|
||||
<file>page-settings.ui</file>
|
||||
<file>page-themes.ui</file>
|
||||
<file>monitor.png</file>
|
||||
<file>sample.png</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
BIN
shell/cpl/desk/src/res/sample.png
Normal file
BIN
shell/cpl/desk/src/res/sample.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
246
shell/cpl/desk/src/settings.c
Normal file
246
shell/cpl/desk/src/settings.c
Normal file
@@ -0,0 +1,246 @@
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/registry.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_SETTINGS_CHANGED = 1
|
||||
};
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCCplDeskSettingsClass
|
||||
{
|
||||
GObjectClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCCplDeskSettings
|
||||
{
|
||||
GObject __parent__;
|
||||
|
||||
// Properties
|
||||
//
|
||||
gchar* wallpaper_path;
|
||||
|
||||
// State
|
||||
//
|
||||
gboolean changed;
|
||||
WinTCRegistry* registry;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DELCARATIONS
|
||||
//
|
||||
static void wintc_cpl_desk_settings_get_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
static void wintc_cpl_desk_settings_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
|
||||
static void wintc_cpl_desk_settings_bump_changed(
|
||||
WinTCCplDeskSettings* settings
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCCplDeskSettings,
|
||||
wintc_cpl_desk_settings,
|
||||
G_TYPE_OBJECT
|
||||
)
|
||||
|
||||
static void wintc_cpl_desk_settings_class_init(
|
||||
WinTCCplDeskSettingsClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->get_property = wintc_cpl_desk_settings_get_property;
|
||||
object_class->set_property = wintc_cpl_desk_settings_set_property;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_SETTINGS_CHANGED,
|
||||
g_param_spec_boolean(
|
||||
"settings-changed",
|
||||
"SettingsChanged",
|
||||
"The state of whether there are unsaved changes to settings.",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_cpl_desk_settings_init(
|
||||
WinTCCplDeskSettings* self
|
||||
)
|
||||
{
|
||||
self->registry = wintc_registry_new();
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_cpl_desk_settings_get_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCCplDeskSettings* settings = WINTC_CPL_DESK_SETTINGS(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SETTINGS_CHANGED:
|
||||
g_value_set_boolean(value, settings->changed);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wintc_cpl_desk_settings_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCCplDeskSettings* settings = WINTC_CPL_DESK_SETTINGS(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SETTINGS_CHANGED:
|
||||
settings->changed = g_value_get_boolean(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCCplDeskSettings* wintc_cpl_desk_settings_new(void)
|
||||
{
|
||||
return g_object_new(WINTC_TYPE_CPL_DESK_SETTINGS, NULL);
|
||||
}
|
||||
|
||||
gboolean wintc_cpl_desk_settings_apply(
|
||||
WinTCCplDeskSettings* settings,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
if (
|
||||
!wintc_registry_set_key_value(
|
||||
settings->registry,
|
||||
"HKCU\\Control Panel\\Desktop",
|
||||
"Wallpaper",
|
||||
WINTC_REG_SZ,
|
||||
&(settings->wallpaper_path),
|
||||
FALSE,
|
||||
error
|
||||
)
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_set(
|
||||
settings,
|
||||
"settings-changed", FALSE,
|
||||
NULL
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean wintc_cpl_desk_settings_load(
|
||||
WinTCCplDeskSettings* settings,
|
||||
GError** error
|
||||
)
|
||||
{
|
||||
gchar* sz_wallpaper = NULL;
|
||||
|
||||
if (
|
||||
!wintc_registry_get_key_value(
|
||||
settings->registry,
|
||||
"HKCU\\Control Panel\\Desktop",
|
||||
"Wallpaper",
|
||||
WINTC_REG_SZ,
|
||||
&sz_wallpaper,
|
||||
error
|
||||
)
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Bin old settings
|
||||
//
|
||||
g_free(g_steal_pointer(&(settings->wallpaper_path)));
|
||||
|
||||
// Load in new settings
|
||||
//
|
||||
settings->wallpaper_path = sz_wallpaper;
|
||||
|
||||
g_object_set(
|
||||
settings,
|
||||
"settings-changed", FALSE,
|
||||
NULL
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar* wintc_cpl_desk_settings_get_wallpaper(
|
||||
WinTCCplDeskSettings* settings
|
||||
)
|
||||
{
|
||||
return settings->wallpaper_path;
|
||||
}
|
||||
|
||||
void wintc_cpl_desk_settings_set_wallpaper(
|
||||
WinTCCplDeskSettings* settings,
|
||||
const gchar* path
|
||||
)
|
||||
{
|
||||
g_free(g_steal_pointer(&(settings->wallpaper_path)));
|
||||
|
||||
settings->wallpaper_path = g_strdup(path);
|
||||
|
||||
wintc_cpl_desk_settings_bump_changed(settings);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void wintc_cpl_desk_settings_bump_changed(
|
||||
WinTCCplDeskSettings* settings
|
||||
)
|
||||
{
|
||||
g_object_set(
|
||||
settings,
|
||||
"settings-changed", TRUE,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
43
shell/cpl/desk/src/settings.h
Normal file
43
shell/cpl/desk/src/settings.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef __SETTINGS_H__
|
||||
#define __SETTINGS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCCplDeskSettingsClass WinTCCplDeskSettingsClass;
|
||||
typedef struct _WinTCCplDeskSettings WinTCCplDeskSettings;
|
||||
|
||||
#define WINTC_TYPE_CPL_DESK_SETTINGS (wintc_cpl_desk_settings_get_type())
|
||||
#define WINTC_CPL_DESK_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_CPL_DESK_SETTINGS, WinTCCplDeskSettings))
|
||||
#define WINTC_CPL_DESK_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_CPL_DESK_SETTINGS, WinTCCplDeskSettingsClass))
|
||||
#define IS_WINTC_CPL_DESK_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_CPL_DESK_SETTINGS))
|
||||
#define IS_WINTC_CPL_DESK_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_CPL_DESK_SETTINGS))
|
||||
#define WINTC_CPL_DESK_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_CPL_DESK_SETTINGS, WinTCCplDeskSettingsClass))
|
||||
|
||||
GType wintc_cpl_desk_settings_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCCplDeskSettings* wintc_cpl_desk_settings_new(void);
|
||||
|
||||
gboolean wintc_cpl_desk_settings_apply(
|
||||
WinTCCplDeskSettings* settings,
|
||||
GError** error
|
||||
);
|
||||
gboolean wintc_cpl_desk_settings_load(
|
||||
WinTCCplDeskSettings* settings,
|
||||
GError** error
|
||||
);
|
||||
|
||||
const gchar* wintc_cpl_desk_settings_get_wallpaper(
|
||||
WinTCCplDeskSettings* settings
|
||||
);
|
||||
void wintc_cpl_desk_settings_set_wallpaper(
|
||||
WinTCCplDeskSettings* settings,
|
||||
const gchar* path
|
||||
);
|
||||
|
||||
#endif
|
||||
520
shell/cpl/desk/src/window.c
Normal file
520
shell/cpl/desk/src/window.c
Normal file
@@ -0,0 +1,520 @@
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc/comctl.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shcommon.h>
|
||||
#include <wintc/shlang.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "monitor.h"
|
||||
#include "settings.h"
|
||||
#include "window.h"
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_cpl_desk_window_finalize(
|
||||
GObject* object
|
||||
);
|
||||
|
||||
static void add_wallpaper_to_list(
|
||||
WinTCCplDeskWindow* wnd,
|
||||
const gchar* path
|
||||
);
|
||||
static void refresh_wallpaper_list(
|
||||
WinTCCplDeskWindow* wnd
|
||||
);
|
||||
static void select_wallpaper_from_list(
|
||||
WinTCCplDeskWindow* wnd,
|
||||
const gchar* path
|
||||
);
|
||||
|
||||
static void action_apply(
|
||||
GSimpleAction* action,
|
||||
GVariant* parameter,
|
||||
gpointer user_data
|
||||
);
|
||||
static void action_cancel(
|
||||
GSimpleAction* action,
|
||||
GVariant* parameter,
|
||||
gpointer user_data
|
||||
);
|
||||
static void action_ok(
|
||||
GSimpleAction* action,
|
||||
GVariant* parameter,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static void on_listbox_wallpapers_row_selected(
|
||||
GtkListBox* self,
|
||||
GtkListBoxRow* row,
|
||||
gpointer user_data
|
||||
);
|
||||
static gboolean on_window_map_event(
|
||||
GtkWidget* self,
|
||||
GdkEventAny* event,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// STATIC DATA
|
||||
//
|
||||
static GActionEntry s_window_actions[] = {
|
||||
{
|
||||
.name = "apply",
|
||||
.activate = action_apply,
|
||||
.parameter_type = NULL,
|
||||
.state = NULL,
|
||||
.change_state = NULL
|
||||
},
|
||||
{
|
||||
.name = "cancel",
|
||||
.activate = action_cancel,
|
||||
.parameter_type = NULL,
|
||||
.state = NULL,
|
||||
.change_state = NULL
|
||||
},
|
||||
{
|
||||
.name = "ok",
|
||||
.activate = action_ok,
|
||||
.parameter_type = NULL,
|
||||
.state = NULL,
|
||||
.change_state = NULL
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCCplDeskWindowClass
|
||||
{
|
||||
GtkApplicationWindowClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCCplDeskWindow
|
||||
{
|
||||
GtkApplicationWindow __parent__;
|
||||
|
||||
// State
|
||||
//
|
||||
GSList* list_wallpapers;
|
||||
WinTCCplDeskSettings* settings;
|
||||
|
||||
// UI
|
||||
//
|
||||
GtkWidget* monitor_desktop;
|
||||
GtkWidget* listbox_wallpapers;
|
||||
GtkWidget* notebook_main;
|
||||
|
||||
gboolean sync_settings;
|
||||
};
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITION & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCCplDeskWindow,
|
||||
wintc_cpl_desk_window,
|
||||
GTK_TYPE_APPLICATION_WINDOW
|
||||
)
|
||||
|
||||
static void wintc_cpl_desk_window_class_init(
|
||||
WinTCCplDeskWindowClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = wintc_cpl_desk_window_finalize;
|
||||
}
|
||||
|
||||
static void wintc_cpl_desk_window_init(
|
||||
WinTCCplDeskWindow* self
|
||||
)
|
||||
{
|
||||
GtkBuilder* builder;
|
||||
GtkWidget* main_box;
|
||||
|
||||
gtk_widget_set_size_request(
|
||||
GTK_WIDGET(self),
|
||||
414, // Approx.
|
||||
454
|
||||
);
|
||||
gtk_window_set_default_size(
|
||||
GTK_WINDOW(self),
|
||||
414, // Approx.
|
||||
454
|
||||
);
|
||||
gtk_window_set_icon_name(
|
||||
GTK_WINDOW(self),
|
||||
"preferences-desktop-display"
|
||||
);
|
||||
gtk_window_set_resizable(
|
||||
GTK_WINDOW(self),
|
||||
FALSE
|
||||
);
|
||||
gtk_window_set_skip_taskbar_hint(
|
||||
GTK_WINDOW(self),
|
||||
TRUE
|
||||
);
|
||||
|
||||
// Init settings
|
||||
//
|
||||
self->settings = wintc_cpl_desk_settings_new();
|
||||
|
||||
// Define GActions
|
||||
//
|
||||
g_action_map_add_action_entries(
|
||||
G_ACTION_MAP(self),
|
||||
s_window_actions,
|
||||
G_N_ELEMENTS(s_window_actions),
|
||||
self
|
||||
);
|
||||
|
||||
g_object_bind_property(
|
||||
self->settings,
|
||||
"settings-changed",
|
||||
g_action_map_lookup_action(
|
||||
G_ACTION_MAP(self),
|
||||
"apply"
|
||||
),
|
||||
"enabled",
|
||||
0
|
||||
);
|
||||
|
||||
// Initialize UI
|
||||
//
|
||||
g_type_ensure(WINTC_TYPE_DESK_MONITOR);
|
||||
|
||||
builder =
|
||||
gtk_builder_new_from_resource(
|
||||
"/uk/oddmatics/wintc/cpl-desk/desk.ui"
|
||||
);
|
||||
|
||||
wintc_lc_builder_preprocess_widget_text(builder);
|
||||
|
||||
main_box = GTK_WIDGET(gtk_builder_get_object(builder, "main-box"));
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(self), main_box);
|
||||
|
||||
// Pull out widgets
|
||||
//
|
||||
self->notebook_main = GTK_WIDGET(
|
||||
gtk_builder_get_object(
|
||||
builder,
|
||||
"main-notebook"
|
||||
)
|
||||
);
|
||||
|
||||
g_object_unref(G_OBJECT(builder));
|
||||
|
||||
// Init pages
|
||||
//
|
||||
wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GTK_NOTEBOOK(self->notebook_main),
|
||||
"/uk/oddmatics/wintc/cpl-desk/page-themes.ui",
|
||||
NULL
|
||||
);
|
||||
wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GTK_NOTEBOOK(self->notebook_main),
|
||||
"/uk/oddmatics/wintc/cpl-desk/page-desktop.ui",
|
||||
"listbox-wallpapers", &(self->listbox_wallpapers),
|
||||
"monitor", &(self->monitor_desktop),
|
||||
NULL
|
||||
);
|
||||
wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GTK_NOTEBOOK(self->notebook_main),
|
||||
"/uk/oddmatics/wintc/cpl-desk/page-scrnsave.ui",
|
||||
NULL
|
||||
);
|
||||
wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GTK_NOTEBOOK(self->notebook_main),
|
||||
"/uk/oddmatics/wintc/cpl-desk/page-appearance.ui",
|
||||
NULL
|
||||
);
|
||||
wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GTK_NOTEBOOK(self->notebook_main),
|
||||
"/uk/oddmatics/wintc/cpl-desk/page-settings.ui",
|
||||
NULL
|
||||
);
|
||||
|
||||
// Attach signals
|
||||
//
|
||||
g_signal_connect(
|
||||
self,
|
||||
"map-event",
|
||||
G_CALLBACK(on_window_map_event),
|
||||
NULL
|
||||
);
|
||||
|
||||
g_signal_connect(
|
||||
self->listbox_wallpapers,
|
||||
"row-selected",
|
||||
G_CALLBACK(on_listbox_wallpapers_row_selected),
|
||||
self
|
||||
);
|
||||
|
||||
// Initial load stuff
|
||||
//
|
||||
refresh_wallpaper_list(self);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_cpl_desk_window_finalize(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCCplDeskWindow* wnd = WINTC_CPL_DESK_WINDOW(object);
|
||||
|
||||
g_slist_free_full(wnd->list_wallpapers, g_free);
|
||||
|
||||
(G_OBJECT_CLASS(wintc_cpl_desk_window_parent_class))->finalize(object);
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_cpl_desk_window_new(
|
||||
WinTCCplDeskApplication* app
|
||||
)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
WINTC_TYPE_CPL_DESK_WINDOW,
|
||||
"application", GTK_APPLICATION(app),
|
||||
"title", _("Display Properties"),
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void add_wallpaper_to_list(
|
||||
WinTCCplDeskWindow* wnd,
|
||||
const gchar* path
|
||||
)
|
||||
{
|
||||
gchar* filename = g_path_get_basename(path);
|
||||
GtkWidget* label = gtk_label_new(filename);
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(label), 0.0f);
|
||||
|
||||
gtk_list_box_insert(
|
||||
GTK_LIST_BOX(wnd->listbox_wallpapers),
|
||||
label,
|
||||
-1
|
||||
);
|
||||
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
static void refresh_wallpaper_list(
|
||||
WinTCCplDeskWindow* wnd
|
||||
)
|
||||
{
|
||||
g_slist_free_full(wnd->list_wallpapers, g_free);
|
||||
wintc_container_clear(GTK_CONTAINER(wnd->listbox_wallpapers));
|
||||
|
||||
// Load up wallpapers
|
||||
//
|
||||
GError* error = NULL;
|
||||
GSList* iter = NULL;
|
||||
|
||||
wnd->list_wallpapers =
|
||||
wintc_sh_fs_get_names_as_list(
|
||||
WINTC_RT_PREFIX "/share/backgrounds",
|
||||
TRUE,
|
||||
G_FILE_TEST_IS_REGULAR,
|
||||
TRUE,
|
||||
&error
|
||||
);
|
||||
|
||||
if (!wnd->list_wallpapers)
|
||||
{
|
||||
wintc_nice_error_and_clear(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
iter = wnd->list_wallpapers;
|
||||
|
||||
while (iter)
|
||||
{
|
||||
add_wallpaper_to_list(wnd, (gchar*) iter->data);
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void select_wallpaper_from_list(
|
||||
WinTCCplDeskWindow* wnd,
|
||||
const gchar* path
|
||||
)
|
||||
{
|
||||
gint i = 0;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (GSList* iter = wnd->list_wallpapers; iter; iter = iter->next)
|
||||
{
|
||||
if (g_strcmp0((gchar*) iter->data, path) == 0)
|
||||
{
|
||||
gtk_list_box_select_row(
|
||||
GTK_LIST_BOX(wnd->listbox_wallpapers),
|
||||
gtk_list_box_get_row_at_index(
|
||||
GTK_LIST_BOX(wnd->listbox_wallpapers),
|
||||
i
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// The path isnt in the listbox, so add it and select last item
|
||||
//
|
||||
add_wallpaper_to_list(wnd, path);
|
||||
|
||||
gtk_list_box_select_row(
|
||||
GTK_LIST_BOX(wnd->listbox_wallpapers),
|
||||
gtk_list_box_get_row_at_index(
|
||||
GTK_LIST_BOX(wnd->listbox_wallpapers),
|
||||
g_slist_length(wnd->list_wallpapers) - 1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void action_apply(
|
||||
WINTC_UNUSED(GSimpleAction* action),
|
||||
WINTC_UNUSED(GVariant* parameter),
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCCplDeskWindow* wnd = WINTC_CPL_DESK_WINDOW(user_data);
|
||||
|
||||
GError* error = NULL;
|
||||
|
||||
if (!wintc_cpl_desk_settings_apply(wnd->settings, &error))
|
||||
{
|
||||
wintc_nice_error_and_clear(&error);
|
||||
}
|
||||
}
|
||||
|
||||
static void action_cancel(
|
||||
WINTC_UNUSED(GSimpleAction* action),
|
||||
WINTC_UNUSED(GVariant* parameter),
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
gtk_window_close(GTK_WINDOW(user_data));
|
||||
}
|
||||
|
||||
static void action_ok(
|
||||
WINTC_UNUSED(GSimpleAction* action),
|
||||
WINTC_UNUSED(GVariant* parameter),
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
GAction* action_apply =
|
||||
g_action_map_lookup_action(
|
||||
G_ACTION_MAP(user_data),
|
||||
"apply"
|
||||
);
|
||||
|
||||
// Try applying settings...
|
||||
//
|
||||
g_action_activate(
|
||||
action_apply,
|
||||
NULL
|
||||
);
|
||||
|
||||
// ...we can assume it worked if the apply action is disabled
|
||||
//
|
||||
if (!g_action_get_enabled(action_apply))
|
||||
{
|
||||
gtk_window_close(GTK_WINDOW(user_data));
|
||||
}
|
||||
}
|
||||
|
||||
static void on_listbox_wallpapers_row_selected(
|
||||
WINTC_UNUSED(GtkListBox* self),
|
||||
GtkListBoxRow* row,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCCplDeskWindow* wnd = WINTC_CPL_DESK_WINDOW(user_data);
|
||||
|
||||
GError* error = NULL;
|
||||
GdkPixbuf* pixbuf_wallpaper;
|
||||
const gchar* wallpaper_path;
|
||||
|
||||
wallpaper_path =
|
||||
g_slist_nth_data(
|
||||
wnd->list_wallpapers,
|
||||
gtk_list_box_row_get_index(row)
|
||||
);
|
||||
|
||||
pixbuf_wallpaper =
|
||||
gdk_pixbuf_new_from_file(
|
||||
wallpaper_path,
|
||||
&error
|
||||
);
|
||||
|
||||
if (!pixbuf_wallpaper)
|
||||
{
|
||||
wintc_nice_error_and_clear(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
wintc_desk_monitor_set_pixbuf(
|
||||
WINTC_DESK_MONITOR(wnd->monitor_desktop),
|
||||
pixbuf_wallpaper
|
||||
);
|
||||
|
||||
if (!wnd->sync_settings)
|
||||
{
|
||||
wintc_cpl_desk_settings_set_wallpaper(
|
||||
wnd->settings,
|
||||
wallpaper_path
|
||||
);
|
||||
}
|
||||
|
||||
g_object_unref(pixbuf_wallpaper);
|
||||
}
|
||||
|
||||
static gboolean on_window_map_event(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(GdkEventAny* event),
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
WinTCCplDeskWindow* wnd = WINTC_CPL_DESK_WINDOW(self);
|
||||
|
||||
GError* error = NULL;
|
||||
|
||||
if (!wintc_cpl_desk_settings_load(wnd->settings, &error))
|
||||
{
|
||||
wintc_nice_error_and_clear(&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wnd->sync_settings = TRUE;
|
||||
|
||||
select_wallpaper_from_list(
|
||||
wnd,
|
||||
wintc_cpl_desk_settings_get_wallpaper(wnd->settings)
|
||||
);
|
||||
|
||||
wnd->sync_settings = FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
31
shell/cpl/desk/src/window.h
Normal file
31
shell/cpl/desk/src/window.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __WINDOW_H__
|
||||
#define __WINDOW_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "application.h"
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCCplDeskWindowClass WinTCCplDeskWindowClass;
|
||||
typedef struct _WinTCCplDeskWindow WinTCCplDeskWindow;
|
||||
|
||||
#define WINTC_TYPE_CPL_DESK_WINDOW (wintc_cpl_desk_window_get_type())
|
||||
#define WINTC_CPL_DESK_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WINTC_TYPE_CPL_DESK_WINDOW, WinTCCplDeskWindow))
|
||||
#define WINTC_CPL_DESK_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WINTC_TYPE_CPL_DESK_WINDOW, WinTCCplDeskWindowClass))
|
||||
#define IS_WINTC_CPL_DESK_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WINTC_TYPE_CPL_DESK_WINDOW))
|
||||
#define IS_WINTC_CPL_DESK_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WINTC_TYPE_CPL_DESK_WINDOW))
|
||||
#define WINTC_CPL_DESK_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WINTC_TYPE_CPL_DESK_WINDOW, WinTCCplDeskWindowClass))
|
||||
|
||||
GType wintc_cpl_desk_window_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_cpl_desk_window_new(
|
||||
WinTCCplDeskApplication* app
|
||||
);
|
||||
|
||||
#endif
|
||||
10
shell/cpl/desk/uk.co.oddmatics.wintc.cpl-desk.desktop
Normal file
10
shell/cpl/desk/uk.co.oddmatics.wintc.cpl-desk.desktop
Normal file
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Name=Display
|
||||
Comment=Change the appearance of your desktop, such as the background, screen saver, colors, font sizes, and screen resolution.
|
||||
Exec=desk.cpl
|
||||
Icon=preferences-desktop-display
|
||||
Terminal=false
|
||||
StartupNotify=false
|
||||
Type=Application
|
||||
Categories=Settings;GTK;
|
||||
OnlyShowIn=WINTC;
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc/comctl.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shlang.h>
|
||||
|
||||
@@ -10,11 +11,6 @@
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void add_sysdm_page(
|
||||
GtkNotebook* notebook_main,
|
||||
gchar* resource_path
|
||||
);
|
||||
|
||||
static void action_close(
|
||||
GSimpleAction* action,
|
||||
GVariant* parameter,
|
||||
@@ -117,9 +113,10 @@ static void wintc_cpl_sysdm_window_init(
|
||||
|
||||
// Init pages
|
||||
//
|
||||
add_sysdm_page(
|
||||
wintc_ctl_cpl_notebook_append_page_from_resource(
|
||||
GTK_NOTEBOOK(self->notebook_main),
|
||||
"/uk/oddmatics/wintc/cpl-sysdm/page-gen.ui"
|
||||
"/uk/oddmatics/wintc/cpl-sysdm/page-gen.ui",
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
@@ -140,34 +137,6 @@ GtkWidget* wintc_cpl_sysdm_window_new(
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void add_sysdm_page(
|
||||
GtkNotebook* notebook_main,
|
||||
gchar* resource_path
|
||||
)
|
||||
{
|
||||
GtkBuilder* builder;
|
||||
GtkWidget* box_page;
|
||||
GtkWidget* label_title;
|
||||
|
||||
builder = gtk_builder_new_from_resource(resource_path);
|
||||
|
||||
wintc_lc_builder_preprocess_widget_text(builder);
|
||||
|
||||
box_page = GTK_WIDGET(gtk_builder_get_object(builder, "page-box"));
|
||||
label_title = GTK_WIDGET(gtk_builder_get_object(builder, "label-title"));
|
||||
|
||||
gtk_notebook_append_page(
|
||||
notebook_main,
|
||||
box_page,
|
||||
label_title
|
||||
);
|
||||
|
||||
g_object_unref(G_OBJECT(builder));
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
|
||||
@@ -22,6 +22,7 @@ include(../../packaging/cmake-inc/packaging/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-shelldpa WINTC_SHELLDPA)
|
||||
|
||||
add_executable(
|
||||
@@ -29,6 +30,8 @@ add_executable(
|
||||
src/application.c
|
||||
src/application.h
|
||||
src/main.c
|
||||
src/settings.c
|
||||
src/settings.h
|
||||
src/window.c
|
||||
src/window.h
|
||||
)
|
||||
@@ -45,6 +48,7 @@ target_include_directories(
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_REGISTRY_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_SHELLDPA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
@@ -53,6 +57,7 @@ target_link_directories(
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_REGISTRY_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_SHELLDPA_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
@@ -61,6 +66,7 @@ target_link_libraries(
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_REGISTRY_LIBRARIES}
|
||||
PRIVATE ${WINTC_SHELLDPA_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-registry
|
||||
bt,rt:wintc-shelldpa
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <wintc/shelldpa.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "settings.h"
|
||||
#include "window.h"
|
||||
|
||||
//
|
||||
@@ -17,6 +18,8 @@ struct _WinTCDesktopApplicationClass
|
||||
struct _WinTCDesktopApplication
|
||||
{
|
||||
GtkApplication __parent__;
|
||||
|
||||
WinTCDesktopSettings* settings;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -49,8 +52,11 @@ static void wintc_desktop_application_class_init(
|
||||
}
|
||||
|
||||
static void wintc_desktop_application_init(
|
||||
WINTC_UNUSED(WinTCDesktopApplication* self)
|
||||
) {}
|
||||
WinTCDesktopApplication* self
|
||||
)
|
||||
{
|
||||
self->settings = wintc_desktop_settings_new();
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
@@ -97,7 +103,11 @@ static void wintc_desktop_application_activate(
|
||||
for (int i = 0; i < n_monitors; i++)
|
||||
{
|
||||
GdkMonitor* monitor = gdk_display_get_monitor(display, i);
|
||||
GtkWidget* wnd = wintc_desktop_window_new(desktop_app, monitor);
|
||||
GtkWidget* wnd = wintc_desktop_window_new(
|
||||
desktop_app,
|
||||
monitor,
|
||||
desktop_app->settings
|
||||
);
|
||||
|
||||
gtk_widget_show_all(wnd);
|
||||
}
|
||||
|
||||
283
shell/desktop/src/settings.c
Normal file
283
shell/desktop/src/settings.c
Normal file
@@ -0,0 +1,283 @@
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/registry.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_PIXBUF_WALLPAPER = 1
|
||||
};
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCDesktopSettingsClass
|
||||
{
|
||||
GObjectClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCDesktopSettings
|
||||
{
|
||||
GObject __parent__;
|
||||
|
||||
// State
|
||||
//
|
||||
WinTCRegistry* registry;
|
||||
|
||||
// Properties
|
||||
//
|
||||
GdkPixbuf* pixbuf_wallpaper;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_desktop_settings_dispose(
|
||||
GObject* object
|
||||
);
|
||||
static void wintc_desktop_settings_get_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
static void wintc_desktop_settings_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
|
||||
static void wintc_desktop_settings_set_wallpaper_path(
|
||||
WinTCDesktopSettings* settings,
|
||||
const gchar* wallpaper_path
|
||||
);
|
||||
|
||||
static void regkey_changed_desktop_cb(
|
||||
WinTCRegistry* registry,
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
GVariant* value_variant,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCDesktopSettings,
|
||||
wintc_desktop_settings,
|
||||
G_TYPE_OBJECT
|
||||
)
|
||||
|
||||
static void wintc_desktop_settings_class_init(
|
||||
WinTCDesktopSettingsClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->dispose = wintc_desktop_settings_dispose;
|
||||
object_class->get_property = wintc_desktop_settings_get_property;
|
||||
object_class->set_property = wintc_desktop_settings_set_property;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_PIXBUF_WALLPAPER,
|
||||
g_param_spec_object(
|
||||
"pixbuf-wallpaper",
|
||||
"PixbufWallpaper",
|
||||
"The pixbuf that should be used as the desktop wallpaper.",
|
||||
GDK_TYPE_PIXBUF,
|
||||
G_PARAM_READWRITE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_desktop_settings_init(
|
||||
WinTCDesktopSettings* self
|
||||
)
|
||||
{
|
||||
GError* error = NULL;
|
||||
|
||||
// Initial registry set up
|
||||
//
|
||||
self->registry = wintc_registry_new();
|
||||
|
||||
if (
|
||||
!wintc_registry_create_key(
|
||||
self->registry,
|
||||
"HKCU\\Control Panel\\Desktop",
|
||||
&error
|
||||
)
|
||||
)
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
}
|
||||
|
||||
// Get some stuff from registry for startup
|
||||
//
|
||||
gchar* sz_wallpaper = NULL;
|
||||
|
||||
if (
|
||||
!wintc_registry_get_key_value(
|
||||
self->registry,
|
||||
"HKCU\\Control Panel\\Desktop",
|
||||
"Wallpaper",
|
||||
WINTC_REG_SZ,
|
||||
&sz_wallpaper,
|
||||
&error
|
||||
)
|
||||
)
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
}
|
||||
|
||||
if (sz_wallpaper)
|
||||
{
|
||||
wintc_desktop_settings_set_wallpaper_path(self, sz_wallpaper);
|
||||
g_free(sz_wallpaper);
|
||||
}
|
||||
|
||||
// Set up watcher
|
||||
//
|
||||
wintc_registry_watch_key(
|
||||
self->registry,
|
||||
"HKCU\\Control Panel\\Desktop",
|
||||
regkey_changed_desktop_cb,
|
||||
self
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_desktop_settings_dispose(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCDesktopSettings* settings = WINTC_DESKTOP_SETTINGS(object);
|
||||
|
||||
g_clear_object(&(settings->pixbuf_wallpaper));
|
||||
|
||||
(G_OBJECT_CLASS(wintc_desktop_settings_parent_class))->dispose(object);
|
||||
}
|
||||
|
||||
static void wintc_desktop_settings_get_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCDesktopSettings* settings = WINTC_DESKTOP_SETTINGS(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PIXBUF_WALLPAPER:
|
||||
g_value_set_object(value, settings->pixbuf_wallpaper);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wintc_desktop_settings_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCDesktopSettings* settings = WINTC_DESKTOP_SETTINGS(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PIXBUF_WALLPAPER:
|
||||
g_clear_object(&(settings->pixbuf_wallpaper));
|
||||
settings->pixbuf_wallpaper = g_value_dup_object(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCDesktopSettings* wintc_desktop_settings_new(void)
|
||||
{
|
||||
return g_object_new(WINTC_TYPE_DESKTOP_SETTINGS, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void wintc_desktop_settings_set_wallpaper_path(
|
||||
WinTCDesktopSettings* settings,
|
||||
const gchar* wallpaper_path
|
||||
)
|
||||
{
|
||||
GError* error = NULL;
|
||||
GdkPixbuf* pixbuf_wallpaper;
|
||||
|
||||
WINTC_LOG_DEBUG("desktop: setting wallpaper to %s", wallpaper_path);
|
||||
|
||||
pixbuf_wallpaper =
|
||||
gdk_pixbuf_new_from_file(
|
||||
wallpaper_path,
|
||||
&error
|
||||
);
|
||||
|
||||
if (!pixbuf_wallpaper)
|
||||
{
|
||||
wintc_log_error_and_clear(&error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_set(
|
||||
settings,
|
||||
"pixbuf-wallpaper", pixbuf_wallpaper,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_object_unref(pixbuf_wallpaper);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACK
|
||||
//
|
||||
static void regkey_changed_desktop_cb(
|
||||
WINTC_UNUSED(WinTCRegistry* registry),
|
||||
const gchar* key_path,
|
||||
const gchar* value_name,
|
||||
GVariant* value_variant,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
WinTCDesktopSettings* settings = WINTC_DESKTOP_SETTINGS(user_data);
|
||||
|
||||
WINTC_LOG_DEBUG("desktop: saw key changed %s->%s", key_path, value_name);
|
||||
|
||||
if (g_strcmp0(value_name, "Wallpaper") == 0)
|
||||
{
|
||||
if (wintc_registry_get_type_for_variant(value_variant) != WINTC_REG_SZ)
|
||||
{
|
||||
WINTC_LOG_DEBUG("%s", "desktop: wallpaper setting is not REG_SZ");
|
||||
return;
|
||||
}
|
||||
|
||||
wintc_desktop_settings_set_wallpaper_path(
|
||||
settings,
|
||||
g_variant_get_string(value_variant, NULL)
|
||||
);
|
||||
}
|
||||
}
|
||||
26
shell/desktop/src/settings.h
Normal file
26
shell/desktop/src/settings.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __SETTINGS_H__
|
||||
#define __SETTINGS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCDesktopSettingsClass WinTCDesktopSettingsClass;
|
||||
typedef struct _WinTCDesktopSettings WinTCDesktopSettings;
|
||||
|
||||
#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;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCDesktopSettings* wintc_desktop_settings_new(void);
|
||||
|
||||
#endif
|
||||
@@ -1,12 +1,22 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc/comgtk.h>
|
||||
#include <wintc/shelldpa.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "settings.h"
|
||||
#include "window.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_SETTINGS = 1
|
||||
};
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
@@ -18,16 +28,51 @@ struct _WinTCDesktopWindowClass
|
||||
struct _WinTCDesktopWindow
|
||||
{
|
||||
WinTCDpaDesktopWindow __parent__;
|
||||
|
||||
// Drawing-related
|
||||
//
|
||||
GdkPixbuf* pixbuf_wallpaper;
|
||||
cairo_surface_t* surface_wallpaper;
|
||||
|
||||
// State
|
||||
//
|
||||
WinTCDesktopSettings* settings;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATION
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_desktop_window_dispose(
|
||||
GObject* object
|
||||
);
|
||||
static void wintc_desktop_window_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
|
||||
static gboolean wintc_desktop_window_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
);
|
||||
|
||||
static void wintc_desktop_window_update_wallpaper(
|
||||
WinTCDesktopWindow* wnd
|
||||
);
|
||||
|
||||
static gboolean on_window_map_event(
|
||||
GtkWidget* self,
|
||||
GdkEventAny* event,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static void on_settings_notify_pixbuf_wallpaper(
|
||||
GObject* self,
|
||||
GParamSpec* pspec,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITION & CTORS
|
||||
//
|
||||
@@ -41,28 +86,175 @@ static void wintc_desktop_window_class_init(
|
||||
WinTCDesktopWindowClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||
|
||||
object_class->dispose = wintc_desktop_window_dispose;
|
||||
object_class->set_property = wintc_desktop_window_set_property;
|
||||
|
||||
widget_class->draw = wintc_desktop_window_draw;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_SETTINGS,
|
||||
g_param_spec_object(
|
||||
"settings",
|
||||
"Settings",
|
||||
"The shared desktop settings",
|
||||
WINTC_TYPE_DESKTOP_SETTINGS,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_desktop_window_init(
|
||||
WINTC_UNUSED(WinTCDesktopWindow* self)
|
||||
) {}
|
||||
WinTCDesktopWindow* self
|
||||
)
|
||||
{
|
||||
g_signal_connect(
|
||||
self,
|
||||
"map-event",
|
||||
G_CALLBACK(on_window_map_event),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static gboolean wintc_desktop_window_draw(
|
||||
WINTC_UNUSED(GtkWidget* widget),
|
||||
cairo_t* cr
|
||||
static void wintc_desktop_window_dispose(
|
||||
GObject* object
|
||||
)
|
||||
{
|
||||
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object);
|
||||
|
||||
if (wnd->surface_wallpaper)
|
||||
{
|
||||
cairo_surface_destroy(g_steal_pointer(&(wnd->surface_wallpaper)));
|
||||
g_clear_object(&(wnd->pixbuf_wallpaper));
|
||||
}
|
||||
|
||||
(G_OBJECT_CLASS(wintc_desktop_window_parent_class))->dispose(object);
|
||||
}
|
||||
|
||||
static void wintc_desktop_window_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SETTINGS:
|
||||
wnd->settings = g_value_get_object(value);
|
||||
|
||||
g_signal_connect(
|
||||
wnd->settings,
|
||||
"notify::pixbuf-wallpaper",
|
||||
G_CALLBACK(on_settings_notify_pixbuf_wallpaper),
|
||||
wnd
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean wintc_desktop_window_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
)
|
||||
{
|
||||
WinTCDpaDesktopWindow* dpa_wnd = WINTC_DPA_DESKTOP_WINDOW(widget);
|
||||
WinTCDesktopWindow* wnd = WINTC_DESKTOP_WINDOW(widget);
|
||||
|
||||
// FIXME: Just drawing default desktop background colour atm
|
||||
//
|
||||
cairo_set_source_rgb(cr, 0.0f, 0.298f, 0.596f);
|
||||
cairo_paint(cr);
|
||||
|
||||
// FIXME: Billy basic drawing of the wallpaper, if present
|
||||
//
|
||||
if (wnd->surface_wallpaper)
|
||||
{
|
||||
cairo_set_source_surface(cr, wnd->surface_wallpaper, 0.0f, 0.0f);
|
||||
cairo_paint(cr);
|
||||
}
|
||||
|
||||
// Rough watermark drawing
|
||||
//
|
||||
if (gdk_monitor_is_primary(dpa_wnd->monitor))
|
||||
{
|
||||
static gchar* s_tag = NULL;
|
||||
|
||||
cairo_text_extents_t extents;
|
||||
gdouble y;
|
||||
|
||||
gint height = gtk_widget_get_allocated_height(widget);
|
||||
gint width = gtk_widget_get_allocated_width(widget);
|
||||
|
||||
if (!s_tag)
|
||||
{
|
||||
gchar* tag = wintc_build_get_tag();
|
||||
|
||||
s_tag =
|
||||
g_strdup_printf("For testing purposes only. Build %s", tag);
|
||||
|
||||
g_free(tag);
|
||||
}
|
||||
|
||||
// Default to white, IDK if Windows changes this...
|
||||
//
|
||||
cairo_set_source_rgb(cr, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// Handle build string first...
|
||||
//
|
||||
cairo_select_font_face(
|
||||
cr,
|
||||
"sans-serif",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL
|
||||
);
|
||||
|
||||
cairo_text_extents(cr, s_tag, &extents);
|
||||
|
||||
cairo_move_to(
|
||||
cr,
|
||||
width - extents.width - 10,
|
||||
height - extents.height - 34 // FIXME: Hardcoded taskband height
|
||||
);
|
||||
|
||||
cairo_show_text(cr, s_tag);
|
||||
|
||||
// ...and the product name
|
||||
// FIXME: Hard coded temp name in here until we have a name
|
||||
//
|
||||
cairo_select_font_face(
|
||||
cr,
|
||||
"sans-serif",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_BOLD
|
||||
);
|
||||
|
||||
cairo_text_extents(cr, "Windows 'Total Conversion'", &extents);
|
||||
|
||||
cairo_get_current_point(cr, NULL, &y);
|
||||
|
||||
cairo_move_to(
|
||||
cr,
|
||||
width - extents.width - 10,
|
||||
y - extents.height - 4
|
||||
);
|
||||
|
||||
cairo_show_text(cr, "Windows 'Total Conversion'");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -71,7 +263,8 @@ static gboolean wintc_desktop_window_draw(
|
||||
//
|
||||
GtkWidget* wintc_desktop_window_new(
|
||||
WinTCDesktopApplication* app,
|
||||
GdkMonitor* monitor
|
||||
GdkMonitor* monitor,
|
||||
WinTCDesktopSettings* settings
|
||||
)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
@@ -82,7 +275,69 @@ GtkWidget* wintc_desktop_window_new(
|
||||
"decorated", TRUE,
|
||||
"monitor", monitor,
|
||||
"resizable", FALSE,
|
||||
"settings", settings,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void wintc_desktop_window_update_wallpaper(
|
||||
WinTCDesktopWindow* wnd
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("%s", "desktop: window updating wallpaper");
|
||||
|
||||
if (wnd->surface_wallpaper)
|
||||
{
|
||||
cairo_surface_destroy(g_steal_pointer(&(wnd->surface_wallpaper)));
|
||||
g_clear_object(&(wnd->pixbuf_wallpaper));
|
||||
}
|
||||
|
||||
g_object_get(
|
||||
wnd->settings,
|
||||
"pixbuf-wallpaper", &(wnd->pixbuf_wallpaper),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (wnd->pixbuf_wallpaper)
|
||||
{
|
||||
wnd->surface_wallpaper =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
wnd->pixbuf_wallpaper,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
gtk_widget_queue_draw(GTK_WIDGET(wnd));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static gboolean on_window_map_event(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(GdkEventAny* event),
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
wintc_desktop_window_update_wallpaper(
|
||||
WINTC_DESKTOP_WINDOW(self)
|
||||
);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void on_settings_notify_pixbuf_wallpaper(
|
||||
WINTC_UNUSED(GObject* self),
|
||||
WINTC_UNUSED(GParamSpec* pspec),
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
wintc_desktop_window_update_wallpaper(
|
||||
WINTC_DESKTOP_WINDOW(user_data)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "settings.h"
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
@@ -26,7 +27,8 @@ GType wintc_desktop_window_get_type(void) G_GNUC_CONST;
|
||||
//
|
||||
GtkWidget* wintc_desktop_window_new(
|
||||
WinTCDesktopApplication* app,
|
||||
GdkMonitor* monitor
|
||||
GdkMonitor* monitor,
|
||||
WinTCDesktopSettings* settings
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,13 +14,17 @@ msgfmt-->bt,rt-->gettext
|
||||
plymouth-->bt,rt-->plymouth
|
||||
pulseaudio-->bt-->pulseaudio-dev
|
||||
pulseaudio-->rt-->libpulse
|
||||
python3-packaging-->bt,rt-->py3-packaging
|
||||
python3-venv-->bt,rt-->py3-virtualenv
|
||||
sass-->bt,rt-->sassc
|
||||
sqlite3-->bt-->sqlite-dev
|
||||
sqlite3-->rt-->sqlite
|
||||
sysinfo-->bt,rt-->NULL
|
||||
wintc-comctl-->bt,rt-->libwintc-comctl
|
||||
wintc-comgtk-->bt,rt-->libwintc-comgtk
|
||||
wintc-exec-->bt,rt-->libwintc-exec
|
||||
wintc-msgina-->bt,rt-->libwintc-msgina
|
||||
wintc-registry-->bt,rt-->libwintc-registry
|
||||
wintc-shcommon-->bt,rt-->libwintc-shcommon
|
||||
wintc-shell-->bt,rt-->libwintc-shell
|
||||
wintc-shelldpa-->bt,rt-->libwintc-shelldpa
|
||||
|
||||
@@ -7,13 +7,16 @@ lightdm-->bt,rt-->lightdm
|
||||
msgfmt-->bt,rt-->gettext
|
||||
plymouth-->bt,rt-->plymouth
|
||||
pulseaudio-->bt,rt-->libpulse
|
||||
python3-packaging-->bt,rt-->python-packaging
|
||||
python3-venv-->bt,rt-->python3
|
||||
sass-->bt,rt-->ruby-sass
|
||||
sqlite3-->bt,rt-->sqlite
|
||||
sysinfo-->bt,rt-->NULL
|
||||
wintc-comctl-->bt,rt-->wintc-comctl
|
||||
wintc-comgtk-->bt,rt-->wintc-comgtk
|
||||
wintc-exec-->bt,rt-->wintc-exec
|
||||
wintc-msgina-->bt,rt-->wintc-msgina
|
||||
wintc-registry-->bt,rt-->wintc-registry
|
||||
wintc-shcommon-->bt,rt-->wintc-shcommon
|
||||
wintc-shell-->bt,rt-->wintc-shell
|
||||
wintc-shelldpa-->bt,rt-->wintc-shelldpa
|
||||
|
||||
@@ -7,13 +7,16 @@ lightdm-->bt,rt-->lightdm
|
||||
msgfmt-->bt,rt-->gettext
|
||||
plymouth-->bt,rt-->splash
|
||||
pulseaudio-->bt,rt-->pulseaudio
|
||||
python3-packaging-->bt,rt-->py39-packaging
|
||||
python3-venv-->bt,rt-->py39-virtualenv
|
||||
sass-->bt,rt-->rubygem-sass
|
||||
sqlite3-->bt,rt-->sqlite3
|
||||
sysinfo-->bt,rt-->libsysinfo
|
||||
wintc-comctl-->bt,rt-->wintc-comctl
|
||||
wintc-comgtk-->bt,rt-->wintc-comgtk
|
||||
wintc-exec-->bt,rt-->wintc-exec
|
||||
wintc-msgina-->bt,rt-->wintc-msgina
|
||||
wintc-registry-->bt,rt-->wintc-registry
|
||||
wintc-shcommon-->bt,rt-->wintc-shcommon
|
||||
wintc-shell-->bt,rt-->wintc-shell
|
||||
wintc-shelldpa-->bt,rt-->wintc-shelldpa
|
||||
|
||||
@@ -14,13 +14,17 @@ msgfmt-->bt,rt-->gettext
|
||||
plymouth-->bt,rt-->plymouth
|
||||
pulseaudio-->bt-->libpulse-dev
|
||||
pulseaudio-->rt-->libpulse0
|
||||
python3-packaging-->bt,rt-->python3-packaging
|
||||
python3-venv-->bt,rt-->python3-venv
|
||||
sass-->bt,rt-->ruby-sass
|
||||
sqlite3-->bt-->libsqlite3-dev
|
||||
sqlite3-->rt-->libsqlite3-0
|
||||
sysinfo-->bt,rt-->NULL
|
||||
wintc-comctl-->bt,rt-->libwintc-comctl
|
||||
wintc-comgtk-->bt,rt-->libwintc-comgtk
|
||||
wintc-exec-->bt,rt-->libwintc-exec
|
||||
wintc-msgina-->bt,rt-->libwintc-msgina
|
||||
wintc-registry-->bt,rt-->libwintc-registry
|
||||
wintc-shcommon-->bt,rt-->libwintc-shcommon
|
||||
wintc-shell-->bt,rt-->libwintc-shell
|
||||
wintc-shelldpa-->bt,rt-->libwintc-shelldpa
|
||||
|
||||
@@ -14,13 +14,17 @@ msgfmt-->bt,rt-->gettext
|
||||
plymouth-->bt,rt-->plymouth
|
||||
pulseaudio-->bt-->pulseaudio-libs-devel
|
||||
pulseaudio-->rt-->pulseaudio-libs
|
||||
python3-packaging-->bt,rt-->python3-packaging
|
||||
python3-venv-->bt,rt-->python3-virtualenv
|
||||
sass-->bt,rt-->rubygem-sass
|
||||
sqlite3-->bt-->sqlite-devel
|
||||
sqlite3-->rt-->sqlite
|
||||
sysinfo-->bt,rt-->NULL
|
||||
wintc-comctl-->bt,rt-->wintc-comctl
|
||||
wintc-comgtk-->bt,rt-->wintc-comgtk
|
||||
wintc-exec-->bt,rt-->wintc-exec
|
||||
wintc-msgina-->bt,rt-->wintc-msgina
|
||||
wintc-registry-->bt,rt-->wintc-registry
|
||||
wintc-shcommon-->bt,rt-->wintc-shcommon
|
||||
wintc-shell-->bt,rt-->wintc-shell
|
||||
wintc-shelldpa-->bt,rt-->wintc-shelldpa
|
||||
|
||||
Reference in New Issue
Block a user