Enhancement: Fixes #205, Create logonui LightDM greeter
111
base/logonui/CMakeLists.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(
|
||||
wintc-logonui
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion logon user interface."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS false)
|
||||
set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Necessary because we use g_signal_handlers_disconnect...
|
||||
set(WINTC_NO_PEDANTIC_COMPILE true)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/resources/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(gdk-pixbuf-2.0 GDK_PIXBUF)
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(liblightdm-gobject-1 LIGHTDM)
|
||||
wintc_resolve_library(wintc-comctl WINTC_COMCTL)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
wintc_resolve_library(wintc-msgina WINTC_MSGINA)
|
||||
|
||||
wintc_compile_resources()
|
||||
|
||||
add_executable(
|
||||
wintc-logonui
|
||||
src/main.c
|
||||
src/resources.c
|
||||
src/window.c
|
||||
src/window.h
|
||||
src/classic/ui.c
|
||||
src/classic/ui.h
|
||||
src/welcome/ui.c
|
||||
src/welcome/ui.h
|
||||
src/welcome/userlist.c
|
||||
src/welcome/userlist.h
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
wintc-logonui
|
||||
PROPERTIES
|
||||
OUTPUT_NAME logonui
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
wintc-logonui
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
wintc-logonui
|
||||
SYSTEM
|
||||
PRIVATE ${GDK_PIXBUF_INCLUDE_DIRS}
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${LIGHTDM_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_MSGINA_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
wintc-logonui
|
||||
PRIVATE ${GDK_PIXBUF_LIBRARY_DIRS}
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${LIGHTDM_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_MSGINA_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
wintc-logonui
|
||||
PRIVATE ${GDK_PIXBUF_LIBRARIES}
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${LIGHTDM_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_MSGINA_LIBRARIES}
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
wintc-logonui
|
||||
build-gresources
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
|
||||
install(
|
||||
FILES wintc-logonui.desktop
|
||||
DESTINATION share/xgreeters
|
||||
)
|
||||
install(
|
||||
TARGETS wintc-logonui
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
|
||||
)
|
||||
4
base/logonui/README.MD
Normal file
@@ -0,0 +1,4 @@
|
||||
# logonui
|
||||
This directory contains the source-code for the Windows Logon User Interface.
|
||||
|
||||

|
||||
7
base/logonui/deps
Normal file
@@ -0,0 +1,7 @@
|
||||
bt,rt:gdk-pixbuf2
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:lightdm
|
||||
bt,rt:wintc-comctl
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-msgina
|
||||
128
base/logonui/src/classic/ui.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comgtk.h>
|
||||
#include <wintc-msgina.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "../window.h"
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCClassicUIPrivate
|
||||
{
|
||||
GtkWidget* wnd_gina;
|
||||
};
|
||||
|
||||
struct _WinTCClassicUIClass
|
||||
{
|
||||
GtkWidgetClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCClassicUI
|
||||
{
|
||||
GtkWidget __parent__;
|
||||
|
||||
WinTCClassicUIPrivate* priv;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static gboolean wintc_classic_ui_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
);
|
||||
|
||||
static void on_self_realized(
|
||||
GtkWidget* self,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCClassicUI,
|
||||
wintc_classic_ui,
|
||||
GTK_TYPE_WIDGET,
|
||||
G_ADD_PRIVATE(WinTCClassicUI)
|
||||
)
|
||||
|
||||
static void wintc_classic_ui_class_init(
|
||||
WinTCClassicUIClass* klass
|
||||
)
|
||||
{
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||
|
||||
widget_class->draw = wintc_classic_ui_draw;
|
||||
}
|
||||
|
||||
static void wintc_classic_ui_init(
|
||||
WinTCClassicUI* self
|
||||
)
|
||||
{
|
||||
self->priv = wintc_classic_ui_get_instance_private(self);
|
||||
|
||||
gtk_widget_set_has_window(GTK_WIDGET(self), FALSE);
|
||||
|
||||
// Set up widgets
|
||||
//
|
||||
self->priv->wnd_gina = wintc_gina_auth_window_new();
|
||||
|
||||
// Connect to realize signal to begin when we're ready
|
||||
//
|
||||
g_signal_connect(
|
||||
self,
|
||||
"realize",
|
||||
G_CALLBACK(on_self_realized),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static gboolean wintc_classic_ui_draw(
|
||||
WINTC_UNUSED(GtkWidget* widget),
|
||||
cairo_t* cr
|
||||
)
|
||||
{
|
||||
// BG color is #004E98
|
||||
// FIXME: This is the default desktop colour, should be it be defined in
|
||||
// a shell lib? Also see shell/desktop
|
||||
//
|
||||
cairo_set_source_rgb(cr, 0.0f, 0.298f, 0.596f);
|
||||
cairo_paint(cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_classic_ui_new(void)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
TYPE_WINTC_CLASSIC_UI,
|
||||
"hexpand", TRUE,
|
||||
"vexpand", TRUE,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void on_self_realized(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
WinTCClassicUI* classic_ui = WINTC_CLASSIC_UI(self);
|
||||
|
||||
gtk_widget_show_all(classic_ui->priv->wnd_gina);
|
||||
}
|
||||
28
base/logonui/src/classic/ui.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __CLASSIC_UI_H__
|
||||
#define __CLASSIC_UI_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCClassicUIPrivate WinTCClassicUIPrivate;
|
||||
typedef struct _WinTCClassicUIClass WinTCClassicUIClass;
|
||||
typedef struct _WinTCClassicUI WinTCClassicUI;
|
||||
|
||||
#define TYPE_WINTC_CLASSIC_UI (wintc_classic_ui_get_type())
|
||||
#define WINTC_CLASSIC_UI(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_CLASSIC_UI, WinTCClassicUI))
|
||||
#define WINTC_CLASSIC_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), TYPE_WINTC_CLASSIC_UI, WinTCClassicUI))
|
||||
#define IS_WINTC_CLASSIC_UI(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_CLASSIC_UI))
|
||||
#define IS_WINTC_CLASSIC_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_CLASSIC_UI))
|
||||
#define WINTC_CLASSIC_UI_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_CLASSIC_UI))
|
||||
|
||||
GType wintc_classic_ui_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_classic_ui_new(void);
|
||||
|
||||
#endif
|
||||
41
base/logonui/src/main.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comgtk.h>
|
||||
|
||||
#include "window.h"
|
||||
|
||||
//
|
||||
// ENTRY POINT
|
||||
//
|
||||
int main(
|
||||
int argc,
|
||||
char* argv[]
|
||||
)
|
||||
{
|
||||
GtkWidget* window;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// Set up theme
|
||||
// FIXME: There should probably be an API for this rather than directly
|
||||
// plopping the name straight in GTK
|
||||
// FIXME: This should be configurable via INI option and simply default to
|
||||
// Luna for clients, and Classic for servers
|
||||
//
|
||||
g_object_set(
|
||||
gtk_settings_get_default(),
|
||||
"gtk-theme-name",
|
||||
"Windows XP style (Blue)",
|
||||
NULL
|
||||
);
|
||||
|
||||
// Create the window and launch
|
||||
//
|
||||
window = wintc_logonui_window_new();
|
||||
|
||||
gtk_widget_show_all(window);
|
||||
|
||||
gtk_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
base/logonui/src/res/bglight.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
base/logonui/src/res/ejctbtn.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
base/logonui/src/res/ejctbtna.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
base/logonui/src/res/entry.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
base/logonui/src/res/gobtn.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
base/logonui/src/res/gobtna.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
base/logonui/src/res/hintbtn.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
base/logonui/src/res/hintbtna.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
base/logonui/src/res/hsepa.png
Normal file
|
After Width: | Height: | Size: 664 B |
BIN
base/logonui/src/res/hsepb.png
Normal file
|
After Width: | Height: | Size: 690 B |
BIN
base/logonui/src/res/logo.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
base/logonui/src/res/logoani.png
Normal file
|
After Width: | Height: | Size: 260 KiB |
35
base/logonui/src/res/resources.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/uk/oddmatics/wintc/logonui">
|
||||
<!-- -->
|
||||
<!-- GRAPHICAL RESOURCES -->
|
||||
<!-- -->
|
||||
<file>bglight.png</file>
|
||||
<file>ejctbtna.png</file>
|
||||
<file>ejctbtn.png</file>
|
||||
<file>entry.png</file>
|
||||
<file>gobtna.png</file>
|
||||
<file>gobtn.png</file>
|
||||
<file>hintbtna.png</file>
|
||||
<file>hintbtn.png</file>
|
||||
<file>hsepa.png</file>
|
||||
<file>hsepb.png</file>
|
||||
<file>logoani.png</file>
|
||||
<file>logo.png</file>
|
||||
<file>scdnbtn.png</file>
|
||||
<file>scrollbar.png</file>
|
||||
<file>scupbtn.png</file>
|
||||
<file>shtdbtna.png</file>
|
||||
<file>shtdbtn.png</file>
|
||||
<file>tilehot.png</file>
|
||||
<file>tile.png</file>
|
||||
<file>userpic.png</file>
|
||||
<file>usersel.png</file>
|
||||
<file>vsep.png</file>
|
||||
|
||||
<!-- -->
|
||||
<!-- CSS RESOURCES -->
|
||||
<!-- -->
|
||||
<file>welcome-ui.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
BIN
base/logonui/src/res/scdnbtn.png
Normal file
|
After Width: | Height: | Size: 828 B |
BIN
base/logonui/src/res/scrollbar.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
base/logonui/src/res/scupbtn.png
Normal file
|
After Width: | Height: | Size: 826 B |
BIN
base/logonui/src/res/shtdbtn.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
base/logonui/src/res/shtdbtna.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
base/logonui/src/res/tile.png
Normal file
|
After Width: | Height: | Size: 591 B |
BIN
base/logonui/src/res/tilehot.png
Normal file
|
After Width: | Height: | Size: 709 B |
BIN
base/logonui/src/res/userpic.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
base/logonui/src/res/usersel.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
base/logonui/src/res/vsep.png
Normal file
|
After Width: | Height: | Size: 506 B |
21
base/logonui/src/res/welcome-ui.css
Normal file
@@ -0,0 +1,21 @@
|
||||
.box-instruction label,
|
||||
.box-wait label,
|
||||
.box-welcome label
|
||||
{
|
||||
color: #EFF7FF;
|
||||
font-family: 'Arial';
|
||||
}
|
||||
|
||||
.box-instruction label,
|
||||
.box-wait label
|
||||
{
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
.box-welcome label
|
||||
{
|
||||
font-size: 36pt;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
text-shadow: 2px 3px 0px #3151B5;
|
||||
}
|
||||
846
base/logonui/src/welcome/ui.c
Normal file
@@ -0,0 +1,846 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comctl.h>
|
||||
#include <wintc-comgtk.h>
|
||||
#include <wintc-msgina.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "userlist.h"
|
||||
#include "../window.h"
|
||||
|
||||
#define DELAY_SECONDS_AT_LEAST 2
|
||||
#define DELAY_SECONDS_POLL 1
|
||||
|
||||
#define LOGOANI_FRAME_COUNT 50
|
||||
#define LOGOANI_FRAME_RATE 15
|
||||
|
||||
#define TOP_RIBBON_THICKNESS 78
|
||||
#define BOTTOM_RIBBON_THICKNESS 94
|
||||
#define STRIP_THICKNESS 2
|
||||
|
||||
// HMARGIN is potentially 40 or thereabouts
|
||||
// WIDTH is based off 360 per half + 1 for vseparator
|
||||
// VMARGIN is a guesstimate
|
||||
//
|
||||
#define INNER_BOX_HMARGIN 32
|
||||
#define INNER_BOX_WIDTH (720 + 1)
|
||||
#define INNER_BOX_VMARGIN 8
|
||||
#define INNER_BOX_COLLAPSE ((INNER_BOX_HMARGIN * 2) + INNER_BOX_WIDTH)
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCWelcomeUIPrivate
|
||||
{
|
||||
GSList* child_widgets;
|
||||
|
||||
// Graphic resources
|
||||
//
|
||||
GdkPixbuf* pixbuf_bglight;
|
||||
GdkPixbuf* pixbuf_hsepa;
|
||||
GdkPixbuf* pixbuf_hsepb;
|
||||
cairo_surface_t* surface_bglight;
|
||||
cairo_surface_t* surface_hsepa;
|
||||
cairo_surface_t* surface_hsepb;
|
||||
|
||||
// Logo resources
|
||||
//
|
||||
guint ani_id_logo_ins;
|
||||
guint ani_id_logo_wait;
|
||||
GdkPixbuf* pixbuf_logo;
|
||||
GdkPixbuf* pixbuf_logoani;
|
||||
|
||||
// UI
|
||||
//
|
||||
GtkWidget* box_container;
|
||||
|
||||
GtkWidget* box_instruction;
|
||||
GtkWidget* box_login;
|
||||
GtkWidget* box_wait;
|
||||
GtkWidget* box_welcome;
|
||||
|
||||
GtkWidget* animation_logo_ins;
|
||||
GtkWidget* animation_logo_wait;
|
||||
GtkWidget* label_instruction;
|
||||
GtkWidget* label_wait;
|
||||
GtkWidget* label_welcome;
|
||||
GtkWidget* scrollwnd;
|
||||
GtkWidget* user_list;
|
||||
|
||||
// State
|
||||
//
|
||||
WinTCGinaState current_state;
|
||||
WinTCGinaLogonSession* logon_session;
|
||||
};
|
||||
|
||||
struct _WinTCWelcomeUIClass
|
||||
{
|
||||
GtkContainerClass __parent__;
|
||||
|
||||
GtkCssProvider* css_provider;
|
||||
};
|
||||
|
||||
struct _WinTCWelcomeUI
|
||||
{
|
||||
GtkContainer __parent__;
|
||||
|
||||
WinTCWelcomeUIPrivate* priv;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_welcome_ui_finalize(
|
||||
GObject* gobject
|
||||
);
|
||||
|
||||
static gboolean wintc_welcome_ui_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
);
|
||||
static void wintc_welcome_ui_size_allocate(
|
||||
GtkWidget* widget,
|
||||
GtkAllocation* allocation
|
||||
);
|
||||
|
||||
static void wintc_welcome_ui_add(
|
||||
GtkContainer* container,
|
||||
GtkWidget* widget
|
||||
);
|
||||
static void wintc_welcome_ui_forall(
|
||||
GtkContainer* container,
|
||||
gboolean include_internals,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data
|
||||
);
|
||||
static void wintc_welcome_ui_remove(
|
||||
GtkContainer* container,
|
||||
GtkWidget* widget
|
||||
);
|
||||
|
||||
static void wintc_welcome_ui_change_state(
|
||||
WinTCWelcomeUI* welcome_ui,
|
||||
WinTCGinaState next_state
|
||||
);
|
||||
static void wintc_welcome_ui_internal_add(
|
||||
WinTCWelcomeUI* welcome_ui,
|
||||
GtkWidget* widget
|
||||
);
|
||||
|
||||
static void on_self_realized(
|
||||
GtkWidget* self,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static void on_logon_session_attempt_complete(
|
||||
WinTCGinaLogonSession* logon_session,
|
||||
WinTCGinaResponse response,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static gboolean on_timeout_delay_done(
|
||||
gpointer user_data
|
||||
);
|
||||
static gboolean on_timeout_poll_ready(
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCWelcomeUI,
|
||||
wintc_welcome_ui,
|
||||
GTK_TYPE_CONTAINER,
|
||||
G_ADD_PRIVATE(WinTCWelcomeUI)
|
||||
)
|
||||
|
||||
static void wintc_welcome_ui_class_init(
|
||||
WinTCWelcomeUIClass* klass
|
||||
)
|
||||
{
|
||||
GtkContainerClass* container_class = GTK_CONTAINER_CLASS(klass);
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = wintc_welcome_ui_finalize;
|
||||
|
||||
widget_class->draw = wintc_welcome_ui_draw;
|
||||
widget_class->size_allocate = wintc_welcome_ui_size_allocate;
|
||||
|
||||
container_class->add = wintc_welcome_ui_add;
|
||||
container_class->forall = wintc_welcome_ui_forall;
|
||||
container_class->remove = wintc_welcome_ui_remove;
|
||||
|
||||
klass->css_provider = gtk_css_provider_new();
|
||||
|
||||
gtk_css_provider_load_from_resource(
|
||||
klass->css_provider,
|
||||
"/uk/oddmatics/wintc/logonui/welcome-ui.css"
|
||||
);
|
||||
|
||||
gtk_style_context_add_provider_for_screen(
|
||||
gdk_screen_get_default(),
|
||||
GTK_STYLE_PROVIDER(klass->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_FALLBACK
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_welcome_ui_init(
|
||||
WinTCWelcomeUI* self
|
||||
)
|
||||
{
|
||||
self->priv = wintc_welcome_ui_get_instance_private(self);
|
||||
|
||||
gtk_widget_set_has_window(GTK_WIDGET(self), FALSE);
|
||||
|
||||
// Set initial state
|
||||
//
|
||||
self->priv->current_state = WINTC_GINA_STATE_NONE;
|
||||
self->priv->logon_session = wintc_gina_logon_session_new();
|
||||
|
||||
g_signal_connect(
|
||||
self->priv->logon_session,
|
||||
"attempt-complete",
|
||||
G_CALLBACK(on_logon_session_attempt_complete),
|
||||
self
|
||||
);
|
||||
|
||||
// Set up image resources
|
||||
//
|
||||
self->priv->pixbuf_bglight =
|
||||
gdk_pixbuf_new_from_resource(
|
||||
"/uk/oddmatics/wintc/logonui/bglight.png",
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
self->priv->pixbuf_hsepa =
|
||||
gdk_pixbuf_new_from_resource(
|
||||
"/uk/oddmatics/wintc/logonui/hsepa.png",
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
self->priv->pixbuf_hsepb =
|
||||
gdk_pixbuf_new_from_resource(
|
||||
"/uk/oddmatics/wintc/logonui/hsepb.png",
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
|
||||
self->priv->surface_bglight =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
self->priv->pixbuf_bglight,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
self->priv->surface_hsepa =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
self->priv->pixbuf_hsepa,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
self->priv->surface_hsepb =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
self->priv->pixbuf_hsepb,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
self->priv->pixbuf_logo =
|
||||
gdk_pixbuf_new_from_resource(
|
||||
"/uk/oddmatics/wintc/logonui/logo.png",
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
self->priv->pixbuf_logoani =
|
||||
gdk_pixbuf_new_from_resource(
|
||||
"/uk/oddmatics/wintc/logonui/logoani.png",
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
|
||||
// Set up 'Please wait...' box
|
||||
//
|
||||
self->priv->box_wait = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
self->priv->animation_logo_wait = wintc_animation_new();
|
||||
self->priv->label_wait = gtk_label_new("Please wait...");
|
||||
|
||||
self->priv->ani_id_logo_wait =
|
||||
wintc_animation_add_static(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_wait),
|
||||
self->priv->pixbuf_logo
|
||||
);
|
||||
wintc_animation_set_halign(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_wait),
|
||||
GTK_ALIGN_END
|
||||
);
|
||||
wintc_animation_set_valign(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_wait),
|
||||
GTK_ALIGN_END
|
||||
);
|
||||
wintc_animation_play(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_wait),
|
||||
self->priv->ani_id_logo_wait,
|
||||
0,
|
||||
WINTC_ANIMATION_INFINITE
|
||||
);
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(self->priv->label_wait), 1.0f);
|
||||
gtk_label_set_yalign(GTK_LABEL(self->priv->label_wait), 0.0f);
|
||||
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_wait),
|
||||
self->priv->animation_logo_wait,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_wait),
|
||||
self->priv->label_wait,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
|
||||
// Set up instruction box
|
||||
//
|
||||
self->priv->box_instruction = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
self->priv->animation_logo_ins = wintc_animation_new();
|
||||
self->priv->label_instruction =
|
||||
gtk_label_new("To begin, click your user name");
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(self->priv->label_instruction), 1.0f);
|
||||
gtk_label_set_yalign(GTK_LABEL(self->priv->label_instruction), 0.0f);
|
||||
|
||||
self->priv->ani_id_logo_ins =
|
||||
wintc_animation_add_framesheet(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_ins),
|
||||
self->priv->pixbuf_logoani,
|
||||
LOGOANI_FRAME_COUNT
|
||||
);
|
||||
wintc_animation_set_halign(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_ins),
|
||||
GTK_ALIGN_END
|
||||
);
|
||||
wintc_animation_set_valign(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_ins),
|
||||
GTK_ALIGN_END
|
||||
);
|
||||
wintc_animation_play(
|
||||
WINTC_ANIMATION(self->priv->animation_logo_ins),
|
||||
self->priv->ani_id_logo_ins,
|
||||
LOGOANI_FRAME_RATE,
|
||||
WINTC_ANIMATION_INFINITE
|
||||
);
|
||||
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_instruction),
|
||||
self->priv->animation_logo_ins,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_instruction),
|
||||
self->priv->label_instruction,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
|
||||
// Set up login box
|
||||
//
|
||||
self->priv->box_login = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
self->priv->scrollwnd = gtk_scrolled_window_new(NULL, NULL);
|
||||
self->priv->user_list =
|
||||
wintc_welcome_user_list_new(self->priv->logon_session);
|
||||
|
||||
gtk_container_add(
|
||||
GTK_CONTAINER(self->priv->scrollwnd),
|
||||
self->priv->user_list
|
||||
);
|
||||
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_login),
|
||||
self->priv->scrollwnd,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0
|
||||
);
|
||||
gtk_box_set_center_widget(
|
||||
GTK_BOX(self->priv->box_login),
|
||||
self->priv->scrollwnd
|
||||
);
|
||||
|
||||
// Set up 'welcome' box
|
||||
//
|
||||
self->priv->box_welcome = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
self->priv->label_welcome = gtk_label_new("welcome");
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(self->priv->label_welcome), 0.8f);
|
||||
gtk_label_set_yalign(GTK_LABEL(self->priv->label_welcome), 0.5f);
|
||||
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_welcome),
|
||||
self->priv->label_welcome,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
|
||||
// Set up container
|
||||
//
|
||||
self->priv->box_container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
|
||||
gtk_box_set_homogeneous(
|
||||
GTK_BOX(self->priv->box_container),
|
||||
TRUE
|
||||
);
|
||||
|
||||
wintc_welcome_ui_internal_add(self, self->priv->box_container);
|
||||
|
||||
// Add style classes
|
||||
//
|
||||
wintc_widget_add_style_class(self->priv->box_instruction, "box-instruction");
|
||||
wintc_widget_add_style_class(self->priv->box_login, "box-login");
|
||||
wintc_widget_add_style_class(self->priv->box_wait, "box-wait");
|
||||
wintc_widget_add_style_class(self->priv->box_welcome, "box-welcome");
|
||||
|
||||
// Hold an additional reference to the boxes, so we can add/remove
|
||||
// them ourselves without them getting binned
|
||||
//
|
||||
g_object_ref(self->priv->box_instruction);
|
||||
g_object_ref(self->priv->box_login);
|
||||
g_object_ref(self->priv->box_wait);
|
||||
g_object_ref(self->priv->box_welcome);
|
||||
|
||||
// Connect to realize signal to kick off everything when we're
|
||||
// actually live
|
||||
//
|
||||
g_signal_connect(
|
||||
self,
|
||||
"realize",
|
||||
G_CALLBACK(on_self_realized),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_welcome_ui_finalize(
|
||||
GObject* gobject
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(gobject);
|
||||
|
||||
// Bin graphical resources
|
||||
//
|
||||
cairo_surface_destroy(welcome_ui->priv->surface_bglight);
|
||||
cairo_surface_destroy(welcome_ui->priv->surface_hsepa);
|
||||
cairo_surface_destroy(welcome_ui->priv->surface_hsepb);
|
||||
g_clear_object(&(welcome_ui->priv->pixbuf_bglight));
|
||||
g_clear_object(&(welcome_ui->priv->pixbuf_hsepa));
|
||||
g_clear_object(&(welcome_ui->priv->pixbuf_hsepb));
|
||||
g_clear_object(&(welcome_ui->priv->pixbuf_logoani));
|
||||
|
||||
// Bin additional references held for the boxes
|
||||
//
|
||||
g_clear_object(&(welcome_ui->priv->box_instruction));
|
||||
g_clear_object(&(welcome_ui->priv->box_login));
|
||||
g_clear_object(&(welcome_ui->priv->box_wait));
|
||||
g_clear_object(&(welcome_ui->priv->box_welcome));
|
||||
|
||||
(G_OBJECT_CLASS(wintc_welcome_ui_parent_class))->finalize(gobject);
|
||||
}
|
||||
|
||||
static gboolean wintc_welcome_ui_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(widget);
|
||||
|
||||
gint height = gtk_widget_get_allocated_height(widget);
|
||||
gint width = gtk_widget_get_allocated_width(widget);
|
||||
|
||||
// Background is #5A7EDC
|
||||
//
|
||||
cairo_set_source_rgb(cr, 0.35f, 0.49f, 0.86f);
|
||||
cairo_paint(cr);
|
||||
|
||||
// Draw top banner edge
|
||||
//
|
||||
gint hsepa_width = gdk_pixbuf_get_width(welcome_ui->priv->pixbuf_hsepa);
|
||||
|
||||
cairo_save(cr);
|
||||
|
||||
cairo_scale(cr, (double) width / (double) hsepa_width, 1.0f);
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
welcome_ui->priv->surface_hsepa,
|
||||
0.0f,
|
||||
(double) TOP_RIBBON_THICKNESS
|
||||
);
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_restore(cr);
|
||||
|
||||
// Draw top banner fill (#00309C)
|
||||
//
|
||||
cairo_save(cr);
|
||||
|
||||
cairo_rectangle(
|
||||
cr,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(double) width,
|
||||
(double) TOP_RIBBON_THICKNESS
|
||||
);
|
||||
cairo_clip(cr);
|
||||
cairo_set_source_rgb(cr, 0.0f, 0.19f, 0.61f);
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_restore(cr);
|
||||
|
||||
// Draw bg light
|
||||
//
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
welcome_ui->priv->surface_bglight,
|
||||
0.0f,
|
||||
(double) (TOP_RIBBON_THICKNESS + STRIP_THICKNESS)
|
||||
);
|
||||
cairo_paint(cr);
|
||||
|
||||
// Draw bottom banner edge
|
||||
//
|
||||
gint hsepb_width = gdk_pixbuf_get_width(welcome_ui->priv->pixbuf_hsepb);
|
||||
|
||||
cairo_save(cr);
|
||||
|
||||
cairo_scale(cr, (double) width / (double) hsepb_width, 1.0f);
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
welcome_ui->priv->surface_hsepb,
|
||||
0.0f,
|
||||
(double) (height - BOTTOM_RIBBON_THICKNESS - STRIP_THICKNESS)
|
||||
);
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_restore(cr);
|
||||
|
||||
// Draw bottom banner fill (#1D32A4)
|
||||
// FIXME: This should actually be a gradient!
|
||||
//
|
||||
cairo_save(cr);
|
||||
|
||||
cairo_rectangle(
|
||||
cr,
|
||||
0.0f,
|
||||
(double) (height - BOTTOM_RIBBON_THICKNESS),
|
||||
(double) width,
|
||||
(double) BOTTOM_RIBBON_THICKNESS
|
||||
);
|
||||
cairo_clip(cr);
|
||||
cairo_set_source_rgb(cr, 0.11f, 0.19f, 0.64f);
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_restore(cr);
|
||||
|
||||
// Chain up
|
||||
//
|
||||
(GTK_WIDGET_CLASS(wintc_welcome_ui_parent_class))->draw(widget, cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void wintc_welcome_ui_size_allocate(
|
||||
GtkWidget* widget,
|
||||
GtkAllocation* allocation
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(widget);
|
||||
|
||||
gtk_widget_set_allocation(widget, allocation);
|
||||
|
||||
// FIXME: We're not handling collapse at low res (640x480)
|
||||
// FIXME: We're also not doing anything about low res on the Y axis
|
||||
//
|
||||
if (allocation->width < INNER_BOX_COLLAPSE)
|
||||
{
|
||||
g_critical(
|
||||
"Screen res is too low, 800x600 required and we got width of %d",
|
||||
allocation->width
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Just deal with >= 800x600 for now
|
||||
//
|
||||
gint centre_ui = allocation->width / 2;
|
||||
gint centre_box = (INNER_BOX_WIDTH / 2);
|
||||
|
||||
GtkAllocation box_alloc;
|
||||
|
||||
box_alloc.x = centre_ui - centre_box + INNER_BOX_HMARGIN;
|
||||
box_alloc.y = TOP_RIBBON_THICKNESS
|
||||
+ STRIP_THICKNESS
|
||||
+ INNER_BOX_VMARGIN;
|
||||
box_alloc.width = INNER_BOX_WIDTH;
|
||||
box_alloc.height = allocation->height
|
||||
- TOP_RIBBON_THICKNESS
|
||||
- BOTTOM_RIBBON_THICKNESS
|
||||
- (STRIP_THICKNESS * 2)
|
||||
- (INNER_BOX_VMARGIN * 2);
|
||||
|
||||
gtk_widget_size_allocate(
|
||||
welcome_ui->priv->box_container,
|
||||
&box_alloc
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_welcome_ui_add(
|
||||
WINTC_UNUSED(GtkContainer* container),
|
||||
WINTC_UNUSED(GtkWidget* widget)
|
||||
)
|
||||
{
|
||||
g_critical("%s", "wintc_welcome_ui_add - not allowed!");
|
||||
}
|
||||
|
||||
static void wintc_welcome_ui_forall(
|
||||
GtkContainer* container,
|
||||
WINTC_UNUSED(gboolean include_internals),
|
||||
GtkCallback callback,
|
||||
gpointer callback_data
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(container);
|
||||
|
||||
g_slist_foreach(
|
||||
welcome_ui->priv->child_widgets,
|
||||
(GFunc) callback,
|
||||
callback_data
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_welcome_ui_remove(
|
||||
WINTC_UNUSED(GtkContainer* container),
|
||||
WINTC_UNUSED(GtkWidget* widget)
|
||||
)
|
||||
{
|
||||
g_critical("%s", "wintc_welcome_ui_remove - not allowed!");
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_welcome_ui_new(void)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
TYPE_WINTC_WELCOME_UI,
|
||||
"hexpand", TRUE,
|
||||
"vexpand", TRUE,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void wintc_welcome_ui_change_state(
|
||||
WinTCWelcomeUI* welcome_ui,
|
||||
WinTCGinaState next_state
|
||||
)
|
||||
{
|
||||
// Disable current state, if any
|
||||
//
|
||||
switch (welcome_ui->priv->current_state)
|
||||
{
|
||||
case WINTC_GINA_STATE_STARTING:
|
||||
gtk_container_remove(
|
||||
GTK_CONTAINER(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_wait
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_PROMPT:
|
||||
gtk_container_remove(
|
||||
GTK_CONTAINER(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_instruction
|
||||
);
|
||||
gtk_container_remove(
|
||||
GTK_CONTAINER(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_login
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_LAUNCHING:
|
||||
gtk_container_remove(
|
||||
GTK_CONTAINER(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_welcome
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Set up new state
|
||||
//
|
||||
switch (next_state)
|
||||
{
|
||||
case WINTC_GINA_STATE_STARTING:
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_wait,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
wintc_gina_logon_session_establish(
|
||||
welcome_ui->priv->logon_session
|
||||
);
|
||||
g_timeout_add_seconds(
|
||||
DELAY_SECONDS_AT_LEAST,
|
||||
on_timeout_delay_done,
|
||||
welcome_ui
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_PROMPT:
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_instruction,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_login,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_LAUNCHING:
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(welcome_ui->priv->box_container),
|
||||
welcome_ui->priv->box_welcome,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
g_timeout_add_seconds(
|
||||
DELAY_SECONDS_AT_LEAST,
|
||||
on_timeout_delay_done,
|
||||
welcome_ui
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
gtk_widget_show_all(
|
||||
welcome_ui->priv->box_container
|
||||
);
|
||||
|
||||
welcome_ui->priv->current_state = next_state;
|
||||
}
|
||||
|
||||
static void wintc_welcome_ui_internal_add(
|
||||
WinTCWelcomeUI* welcome_ui,
|
||||
GtkWidget* widget
|
||||
)
|
||||
{
|
||||
gtk_widget_set_parent(widget, GTK_WIDGET(welcome_ui));
|
||||
|
||||
welcome_ui->priv->child_widgets =
|
||||
g_slist_append(welcome_ui->priv->child_widgets, widget);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void on_self_realized(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
wintc_welcome_ui_change_state(
|
||||
WINTC_WELCOME_UI(self),
|
||||
WINTC_GINA_STATE_STARTING
|
||||
);
|
||||
}
|
||||
|
||||
static void on_logon_session_attempt_complete(
|
||||
WINTC_UNUSED(WinTCGinaLogonSession* logon_session),
|
||||
WinTCGinaResponse response,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(user_data);
|
||||
|
||||
if (response == WINTC_GINA_RESPONSE_OKAY)
|
||||
{
|
||||
wintc_welcome_ui_change_state(
|
||||
welcome_ui,
|
||||
WINTC_GINA_STATE_LAUNCHING
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean on_timeout_delay_done(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(user_data);
|
||||
|
||||
switch (welcome_ui->priv->current_state)
|
||||
{
|
||||
case WINTC_GINA_STATE_STARTING:
|
||||
g_timeout_add_seconds(
|
||||
DELAY_SECONDS_POLL,
|
||||
on_timeout_poll_ready,
|
||||
welcome_ui
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_LAUNCHING:
|
||||
wintc_gina_logon_session_finish(
|
||||
welcome_ui->priv->logon_session
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical("%s", "Invalid state reached for delay.");
|
||||
break;
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean on_timeout_poll_ready(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCWelcomeUI* welcome_ui = WINTC_WELCOME_UI(user_data);
|
||||
|
||||
if (
|
||||
wintc_gina_logon_session_is_available(
|
||||
welcome_ui->priv->logon_session
|
||||
)
|
||||
)
|
||||
{
|
||||
wintc_welcome_ui_change_state(
|
||||
welcome_ui,
|
||||
WINTC_GINA_STATE_PROMPT
|
||||
);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
28
base/logonui/src/welcome/ui.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __WELCOME_UI_H__
|
||||
#define __WELCOME_UI_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCWelcomeUIPrivate WinTCWelcomeUIPrivate;
|
||||
typedef struct _WinTCWelcomeUIClass WinTCWelcomeUIClass;
|
||||
typedef struct _WinTCWelcomeUI WinTCWelcomeUI;
|
||||
|
||||
#define TYPE_WINTC_WELCOME_UI (wintc_welcome_ui_get_type())
|
||||
#define WINTC_WELCOME_UI(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_WELCOME_UI, WinTCWelcomeUI))
|
||||
#define WINTC_WELCOME_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_WELCOME_UI, WinTCWelcomeUI))
|
||||
#define IS_WINTC_WELCOME_UI(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_WELCOME_UI))
|
||||
#define IS_WINTC_WELCOME_UI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_WELCOME_UI))
|
||||
#define WINTC_WELCOME_UI_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_WELCOME_UI))
|
||||
|
||||
GType wintc_welcome_ui_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_welcome_ui_new(void);
|
||||
|
||||
#endif
|
||||
1084
base/logonui/src/welcome/userlist.c
Normal file
31
base/logonui/src/welcome/userlist.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __USERLIST_H__
|
||||
#define __USERLIST_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-msgina.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCWelcomeUserListPrivate WinTCWelcomeUserListPrivate;
|
||||
typedef struct _WinTCWelcomeUserListClass WinTCWelcomeUserListClass;
|
||||
typedef struct _WinTCWelcomeUserList WinTCWelcomeUserList;
|
||||
|
||||
#define TYPE_WINTC_WELCOME_USER_LIST (wintc_welcome_user_list_get_type())
|
||||
#define WINTC_WELCOME_USER_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_WELCOME_USER_LIST, WinTCWelcomeUserList))
|
||||
#define WINTC_WELCOME_USER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_WELCOME_USER_LIST, WinTCWelcomeUserList))
|
||||
#define IS_WINTC_WELCOME_USER_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_WELCOME_USER_LIST))
|
||||
#define IS_WINTC_WELCOME_USER_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_WELCOME_USER_LIST))
|
||||
#define WINTC_WELCOME_USER_LIST_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_WELCOME_USER_LIST))
|
||||
|
||||
GType wintc_welcome_user_list_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_welcome_user_list_new(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
|
||||
#endif
|
||||
224
base/logonui/src/window.c
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comgtk.h>
|
||||
|
||||
#include "window.h"
|
||||
#include "classic/ui.h"
|
||||
#include "welcome/ui.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_PREFER_CLASSIC_LOGON = 1,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCLogonUIWindowPrivate
|
||||
{
|
||||
GtkWidget* login_ui;
|
||||
};
|
||||
|
||||
struct _WinTCLogonUIWindowClass
|
||||
{
|
||||
GtkWindowClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCLogonUIWindow
|
||||
{
|
||||
GtkWindow __parent__;
|
||||
|
||||
WinTCLogonUIWindowPrivate* priv;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_logonui_window_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
|
||||
static gboolean on_window_map_event(
|
||||
GtkWidget* self,
|
||||
GdkEventAny* event,
|
||||
gpointer user_data
|
||||
);
|
||||
static void on_window_realize(
|
||||
GtkWidget* self,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCLogonUIWindow,
|
||||
wintc_logonui_window,
|
||||
GTK_TYPE_WINDOW,
|
||||
G_ADD_PRIVATE(WinTCLogonUIWindow)
|
||||
)
|
||||
|
||||
static void wintc_logonui_window_class_init(
|
||||
WinTCLogonUIWindowClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->set_property = wintc_logonui_window_set_property;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_PREFER_CLASSIC_LOGON,
|
||||
g_param_spec_boolean(
|
||||
"prefer-classic-logon",
|
||||
"PreferClassicLogon",
|
||||
"Prefer to use the classic logon user-interface.",
|
||||
FALSE,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_logonui_window_init(
|
||||
WinTCLogonUIWindow* self
|
||||
)
|
||||
{
|
||||
self->priv = wintc_logonui_window_get_instance_private(self);
|
||||
|
||||
// Set up window
|
||||
//
|
||||
GdkDisplay* display = gdk_display_get_default();
|
||||
GdkRectangle geometry;
|
||||
GdkMonitor* monitor = gdk_display_get_primary_monitor(display);
|
||||
|
||||
gdk_monitor_get_geometry(monitor, &geometry);
|
||||
|
||||
gtk_widget_set_size_request(
|
||||
GTK_WIDGET(self),
|
||||
geometry.width,
|
||||
geometry.height
|
||||
);
|
||||
gtk_window_move(
|
||||
GTK_WINDOW(self),
|
||||
geometry.x,
|
||||
geometry.y
|
||||
);
|
||||
|
||||
// We delay some stuff until realize/map events:
|
||||
// - we do not add the welcome/classic UI widget until we
|
||||
// hit the 'map-event' signal, this ensures that any child
|
||||
// windows are created after this window
|
||||
// - delay cursor / other init until we realize the GDK
|
||||
// resources for the window
|
||||
//
|
||||
g_signal_connect(
|
||||
self,
|
||||
"map-event",
|
||||
G_CALLBACK(on_window_map_event),
|
||||
NULL
|
||||
);
|
||||
g_signal_connect(
|
||||
self,
|
||||
"realize",
|
||||
G_CALLBACK(on_window_realize),
|
||||
NULL
|
||||
);
|
||||
|
||||
//
|
||||
// Welcome/Classic UI is decided/init'd in set_property
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_logonui_window_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCLogonUIWindow* window = WINTC_LOGONUI_WINDOW(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PREFER_CLASSIC_LOGON:
|
||||
if (g_value_get_boolean(value))
|
||||
{
|
||||
window->priv->login_ui =
|
||||
wintc_classic_ui_new();
|
||||
}
|
||||
else
|
||||
{
|
||||
window->priv->login_ui =
|
||||
wintc_welcome_ui_new();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_logonui_window_new()
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
TYPE_WINTC_LOGONUI_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"decorated", FALSE,
|
||||
"resizable", FALSE,
|
||||
"type-hint", GDK_WINDOW_TYPE_HINT_DESKTOP,
|
||||
"prefer-classic-logon", FALSE,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static gboolean on_window_map_event(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(GdkEventAny* event),
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
WinTCLogonUIWindow* window = WINTC_LOGONUI_WINDOW(self);
|
||||
|
||||
gtk_container_add(
|
||||
GTK_CONTAINER(self),
|
||||
window->priv->login_ui
|
||||
);
|
||||
gtk_widget_show_all(window->priv->login_ui);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void on_window_realize(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
gdk_window_set_cursor(
|
||||
gtk_widget_get_window(self),
|
||||
gdk_cursor_new_for_display(
|
||||
gdk_display_get_default(),
|
||||
GDK_LEFT_PTR
|
||||
)
|
||||
);
|
||||
}
|
||||
28
base/logonui/src/window.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __WINDOW_H__
|
||||
#define __WINDOW_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCLogonUIWindowPrivate WinTCLogonUIWindowPrivate;
|
||||
typedef struct _WinTCLogonUIWindowClass WinTCLogonUIWindowClass;
|
||||
typedef struct _WinTCLogonUIWindow WinTCLogonUIWindow;
|
||||
|
||||
#define TYPE_WINTC_LOGONUI_WINDOW (wintc_logonui_window_get_type())
|
||||
#define WINTC_LOGONUI_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_LOGONUI_WINDOW, WinTCLogonUIWindow))
|
||||
#define WINTC_LOGONUI_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_LOGONUI_WINDOW, WinTCLogonUIWindow))
|
||||
#define IS_WINTC_LOGONUI_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_LOGONUI_WINDOW))
|
||||
#define IS_WINTC_LOGONUI_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_LOGONUI_WINDOW))
|
||||
#define WINTC_LOGONUI_WINDOW_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_LOGONUI_WINDOW))
|
||||
|
||||
GType wintc_logonui_window_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_logonui_window_new();
|
||||
|
||||
#endif
|
||||
5
base/logonui/wintc-logonui.desktop
Normal file
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Name=WinTC LogonUI Greeter
|
||||
Comment=This is the Windows Total Conversion logon user interface.
|
||||
Exec=logonui
|
||||
Type=Application
|
||||
@@ -162,7 +162,7 @@ check_deps()
|
||||
#
|
||||
case "${dist_id}" in
|
||||
archpkg)
|
||||
pacman -Q -k "${pkg_name}" >/dev/null 2>&1
|
||||
pacman -Q -i "${pkg_name}" >/dev/null 2>&1
|
||||
;;
|
||||
deb)
|
||||
dpkg -s "${pkg_name}" >/dev/null 2>&1
|
||||
|
||||
@@ -21,6 +21,10 @@ option(
|
||||
|
||||
# Define pre-processor macro for checked builds
|
||||
#
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
|
||||
add_definitions(-DWINTC_CHECKED)
|
||||
endif()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
base/bootvid
|
||||
base/bldtag
|
||||
base/logonui
|
||||
cursors/no-shadow/standard
|
||||
cursors/with-shadow/standard
|
||||
fonts
|
||||
|
||||
@@ -21,14 +21,18 @@ include(../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/resources/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(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_compile_resources()
|
||||
|
||||
add_library(
|
||||
libwintc-comctl
|
||||
src/resources.c
|
||||
src/animctl.c
|
||||
src/animctl.h
|
||||
src/style.c
|
||||
src/style.h
|
||||
)
|
||||
@@ -49,20 +53,26 @@ target_compile_options(
|
||||
target_include_directories(
|
||||
libwintc-comctl
|
||||
SYSTEM
|
||||
PRIVATE ${GDK_PIXBUF_INCLUDE_DIRS}
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
libwintc-comctl
|
||||
PRIVATE ${GDK_PIXBUF_LIBRARY_DIRS}
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
libwintc-comctl
|
||||
PRIVATE ${GDK_PIXBUF_LIBRARIES}
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
bt,rt:gdk-pixbuf2
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
|
||||
@@ -1,10 +1,72 @@
|
||||
#ifndef __WINTC_COMCTL_H__
|
||||
#define __WINTC_COMCTL_H__
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// Animation control
|
||||
//
|
||||
#define WINTC_ANIMATION_INFINITE 0
|
||||
#define WINTC_ANIMATION_NONE 0
|
||||
|
||||
typedef struct _WinTCAnimationPrivate WinTCAnimationPrivate;
|
||||
typedef struct _WinTCAnimationClass WinTCAnimationClass;
|
||||
typedef struct _WinTCAnimation WinTCAnimation;
|
||||
|
||||
#define TYPE_WINTC_ANIMATION (wintc_animation_get_type())
|
||||
#define WINTC_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_ANIMATION, WinTCAnimation))
|
||||
#define WINTC_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_ANIMATION, WinTCAnimation))
|
||||
#define IS_WINTC_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_ANIMATION))
|
||||
#define IS_WINTC_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_ANIMATION))
|
||||
#define WINTC_ANIMATION_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_ANIMATION))
|
||||
|
||||
GType wintc_animation_get_type(void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget* wintc_animation_new(void);
|
||||
|
||||
guint wintc_animation_add_framesheet(
|
||||
WinTCAnimation* anim,
|
||||
GdkPixbuf* framesheet_pixbuf,
|
||||
gint frame_count
|
||||
);
|
||||
guint wintc_animation_add_static(
|
||||
WinTCAnimation* anim,
|
||||
GdkPixbuf* static_pixbuf
|
||||
);
|
||||
guint wintc_animation_get_count(
|
||||
WinTCAnimation* anim
|
||||
);
|
||||
GtkAlign wintc_animation_get_halign(
|
||||
WinTCAnimation* anim
|
||||
);
|
||||
GtkAlign wintc_animation_get_valign(
|
||||
WinTCAnimation* anim
|
||||
);
|
||||
void wintc_animation_play(
|
||||
WinTCAnimation* anim,
|
||||
guint id,
|
||||
gint frame_rate,
|
||||
gint repeats
|
||||
);
|
||||
void wintc_animation_remove(
|
||||
WinTCAnimation* anim,
|
||||
guint id
|
||||
);
|
||||
void wintc_animation_set_halign(
|
||||
WinTCAnimation* anim,
|
||||
GtkAlign align
|
||||
);
|
||||
void wintc_animation_set_valign(
|
||||
WinTCAnimation* anim,
|
||||
GtkAlign align
|
||||
);
|
||||
|
||||
//
|
||||
// Default CSS stuff
|
||||
//
|
||||
#define WINTC_COMCTL_BUTTON_BOX_CLASS "wintc-button-box"
|
||||
#define WINTC_COMCTL_BUTTON_BOX_CSS_CLASS "wintc-button-box"
|
||||
|
||||
void wintc_comctl_install_default_styles(void);
|
||||
|
||||
|
||||
739
shared/comctl/src/animctl.c
Normal file
@@ -0,0 +1,739 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comgtk.h>
|
||||
|
||||
#include "animctl.h"
|
||||
|
||||
#define ONE_SECOND_IN_US 1000000
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
PROP_HALIGN = 1,
|
||||
PROP_VALIGN,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
//
|
||||
// PRIVATE STURCTURE DEFINITIONS
|
||||
//
|
||||
typedef struct _WinTCAnimationData
|
||||
{
|
||||
GdkPixbuf* pixbuf_bmp;
|
||||
cairo_surface_t* surface_bmp;
|
||||
|
||||
gint frame_count;
|
||||
gint frame_height;
|
||||
} WinTCAnimationData;
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCAnimationPrivate
|
||||
{
|
||||
GSList* animations;
|
||||
|
||||
gboolean is_animating;
|
||||
guint tick_id;
|
||||
|
||||
WinTCAnimationData* current_anim;
|
||||
gint current_frame;
|
||||
gint desired_repeats;
|
||||
gint last_frame;
|
||||
gint64 origin_frame_time;
|
||||
gint64 per_frame_time;
|
||||
gint64 playback_total_time;
|
||||
|
||||
GtkAlign halign;
|
||||
GtkAlign valign;
|
||||
};
|
||||
|
||||
struct _WinTCAnimationClass
|
||||
{
|
||||
GtkWidgetClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCAnimation
|
||||
{
|
||||
GtkWidget __parent__;
|
||||
|
||||
WinTCAnimationPrivate* priv;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_animation_finalize(
|
||||
GObject* gobject
|
||||
);
|
||||
static void wintc_animation_get_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
static void wintc_animation_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
);
|
||||
|
||||
static gboolean wintc_animation_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
);
|
||||
static void wintc_animation_get_preferred_height(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
);
|
||||
static void wintc_animation_get_preferred_height_for_width(
|
||||
GtkWidget* widget,
|
||||
gint width,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
);
|
||||
static void wintc_animation_get_preferred_width(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
);
|
||||
static void wintc_animation_get_preferred_width_for_height(
|
||||
GtkWidget* widget,
|
||||
gint height,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
);
|
||||
|
||||
static void free_anim_data(
|
||||
WinTCAnimationData* anim_data
|
||||
);
|
||||
|
||||
static gboolean wintc_animation_step(
|
||||
GtkWidget* widget,
|
||||
GdkFrameClock* frame_clock,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCAnimation,
|
||||
wintc_animation,
|
||||
GTK_TYPE_WIDGET,
|
||||
G_ADD_PRIVATE(WinTCAnimation)
|
||||
)
|
||||
|
||||
static void wintc_animation_class_init(
|
||||
WinTCAnimationClass* klass
|
||||
)
|
||||
{
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = wintc_animation_finalize;
|
||||
object_class->get_property = wintc_animation_get_property;
|
||||
object_class->set_property = wintc_animation_set_property;
|
||||
|
||||
widget_class->draw =
|
||||
wintc_animation_draw;
|
||||
widget_class->get_preferred_height =
|
||||
wintc_animation_get_preferred_height;
|
||||
widget_class->get_preferred_height_for_width =
|
||||
wintc_animation_get_preferred_height_for_width;
|
||||
widget_class->get_preferred_width =
|
||||
wintc_animation_get_preferred_width;
|
||||
widget_class->get_preferred_width_for_height =
|
||||
wintc_animation_get_preferred_width_for_height;
|
||||
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_HALIGN,
|
||||
g_param_spec_enum(
|
||||
"gfx-halign",
|
||||
"GfxHAlign",
|
||||
"The horizontal alignment for drawing.",
|
||||
GTK_TYPE_ALIGN,
|
||||
GTK_ALIGN_CENTER,
|
||||
G_PARAM_WRITABLE
|
||||
)
|
||||
);
|
||||
g_object_class_install_property(
|
||||
object_class,
|
||||
PROP_VALIGN,
|
||||
g_param_spec_enum(
|
||||
"gfx-valign",
|
||||
"GfxVAlign",
|
||||
"The vertical alignment for drawing.",
|
||||
GTK_TYPE_ALIGN,
|
||||
GTK_ALIGN_CENTER,
|
||||
G_PARAM_WRITABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_animation_init(
|
||||
WinTCAnimation* self
|
||||
)
|
||||
{
|
||||
self->priv = wintc_animation_get_instance_private(self);
|
||||
|
||||
gtk_widget_set_has_window(GTK_WIDGET(self), FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_animation_finalize(
|
||||
GObject* gobject
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(gobject);
|
||||
|
||||
g_slist_free_full(
|
||||
anim->priv->animations,
|
||||
(GDestroyNotify) free_anim_data
|
||||
);
|
||||
|
||||
if (anim->priv->tick_id > 0)
|
||||
{
|
||||
gtk_widget_remove_tick_callback(
|
||||
GTK_WIDGET(anim),
|
||||
anim->priv->tick_id
|
||||
);
|
||||
}
|
||||
|
||||
(G_OBJECT_CLASS(wintc_animation_parent_class))->finalize(gobject);
|
||||
}
|
||||
|
||||
static void wintc_animation_get_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HALIGN:
|
||||
g_value_set_enum(value, anim->priv->halign);
|
||||
break;
|
||||
|
||||
case PROP_VALIGN:
|
||||
g_value_set_enum(value, anim->priv->valign);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wintc_animation_set_property(
|
||||
GObject* object,
|
||||
guint prop_id,
|
||||
const GValue* value,
|
||||
GParamSpec* pspec
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HALIGN:
|
||||
anim->priv->halign = g_value_get_enum(value);
|
||||
gtk_widget_queue_draw(GTK_WIDGET(object));
|
||||
break;
|
||||
|
||||
case PROP_VALIGN:
|
||||
anim->priv->valign = g_value_get_enum(value);
|
||||
gtk_widget_queue_draw(GTK_WIDGET(object));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean wintc_animation_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(widget);
|
||||
|
||||
if (anim->priv->current_anim == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Set up to render the graphic
|
||||
//
|
||||
gint graphic_height;
|
||||
gint graphic_width;
|
||||
double y_offset;
|
||||
|
||||
graphic_width =
|
||||
cairo_image_surface_get_width(
|
||||
anim->priv->current_anim->surface_bmp
|
||||
);
|
||||
|
||||
if (anim->priv->current_anim->frame_count > 1)
|
||||
{
|
||||
graphic_height = anim->priv->current_anim->frame_height;
|
||||
y_offset = (graphic_height * anim->priv->current_frame) * -1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
graphic_height =
|
||||
cairo_image_surface_get_height(
|
||||
anim->priv->current_anim->surface_bmp
|
||||
);
|
||||
y_offset = 0.0f;
|
||||
}
|
||||
|
||||
// Calculate where we're drawing...
|
||||
//
|
||||
gint my_height = gtk_widget_get_allocated_height(widget);
|
||||
gint my_width = gtk_widget_get_allocated_width(widget);
|
||||
|
||||
double target_x;
|
||||
double target_y;
|
||||
double target_width = graphic_width;
|
||||
double target_height = graphic_height;
|
||||
double target_scale_w = 1.0f;
|
||||
double target_scale_h = 1.0f;
|
||||
|
||||
switch (anim->priv->halign)
|
||||
{
|
||||
case GTK_ALIGN_END:
|
||||
target_x = (double) (my_width - graphic_width);
|
||||
break;
|
||||
|
||||
case GTK_ALIGN_CENTER:
|
||||
target_x = (double) ((my_width / 2) - (graphic_width / 2));
|
||||
break;
|
||||
|
||||
case GTK_ALIGN_FILL:
|
||||
target_width = my_width;
|
||||
target_scale_w = (double) my_width / (double) graphic_width;
|
||||
// Fall-through
|
||||
|
||||
default:
|
||||
target_x = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (anim->priv->valign)
|
||||
{
|
||||
case GTK_ALIGN_END:
|
||||
target_y = (double) (my_height - graphic_height);
|
||||
break;
|
||||
|
||||
case GTK_ALIGN_CENTER:
|
||||
target_y = (double) ((my_height / 2) - (graphic_height / 2));
|
||||
break;
|
||||
|
||||
case GTK_ALIGN_FILL:
|
||||
target_height = my_height;
|
||||
target_scale_h = (double) my_height / (double) graphic_height;
|
||||
// Fall-through
|
||||
|
||||
default:
|
||||
target_y = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw now
|
||||
//
|
||||
cairo_save(cr);
|
||||
|
||||
cairo_translate(cr, target_x, target_y);
|
||||
|
||||
cairo_rectangle(
|
||||
cr,
|
||||
0.0f,
|
||||
0.0f,
|
||||
(double) target_width,
|
||||
(double) target_height
|
||||
);
|
||||
cairo_clip(cr);
|
||||
|
||||
cairo_scale(cr, target_scale_w, target_scale_h);
|
||||
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
anim->priv->current_anim->surface_bmp,
|
||||
0.0f,
|
||||
y_offset
|
||||
);
|
||||
cairo_pattern_set_extend(
|
||||
cairo_get_source(cr),
|
||||
CAIRO_EXTEND_NONE
|
||||
);
|
||||
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_restore(cr);
|
||||
|
||||
anim->priv->last_frame = anim->priv->current_frame;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void wintc_animation_get_preferred_height(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(widget);
|
||||
gint height = 0;
|
||||
|
||||
if (anim->priv->current_anim != NULL)
|
||||
{
|
||||
if (anim->priv->current_anim->frame_count == 1)
|
||||
{
|
||||
height =
|
||||
cairo_image_surface_get_height(
|
||||
anim->priv->current_anim->surface_bmp
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
height = anim->priv->current_anim->frame_height;
|
||||
}
|
||||
}
|
||||
|
||||
*minimum_height = height;
|
||||
*natural_height = height;
|
||||
}
|
||||
|
||||
static void wintc_animation_get_preferred_height_for_width(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(gint width),
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
)
|
||||
{
|
||||
wintc_animation_get_preferred_height(
|
||||
widget,
|
||||
minimum_height,
|
||||
natural_height
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_animation_get_preferred_width(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(widget);
|
||||
|
||||
if (anim->priv->current_anim == NULL)
|
||||
{
|
||||
minimum_width = 0;
|
||||
natural_width = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
gint width =
|
||||
cairo_image_surface_get_width(
|
||||
anim->priv->current_anim->surface_bmp
|
||||
);
|
||||
|
||||
*minimum_width = width;
|
||||
*natural_width = width;
|
||||
}
|
||||
|
||||
static void wintc_animation_get_preferred_width_for_height(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(gint height),
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
)
|
||||
{
|
||||
wintc_animation_get_preferred_width(
|
||||
widget,
|
||||
minimum_width,
|
||||
natural_width
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_animation_new(void)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
TYPE_WINTC_ANIMATION,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
guint wintc_animation_add_framesheet(
|
||||
WinTCAnimation* anim,
|
||||
GdkPixbuf* framesheet_pixbuf,
|
||||
gint frame_count
|
||||
)
|
||||
{
|
||||
WinTCAnimationData* anim_data = g_new0(WinTCAnimationData, 1);
|
||||
gint height = gdk_pixbuf_get_height(framesheet_pixbuf);
|
||||
|
||||
g_object_ref(framesheet_pixbuf);
|
||||
|
||||
anim_data->pixbuf_bmp = framesheet_pixbuf;
|
||||
anim_data->surface_bmp =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
framesheet_pixbuf,
|
||||
1,
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
|
||||
anim_data->frame_count = frame_count;
|
||||
anim_data->frame_height = height / frame_count;
|
||||
|
||||
anim->priv->animations =
|
||||
g_slist_append(
|
||||
anim->priv->animations,
|
||||
anim_data
|
||||
);
|
||||
|
||||
return wintc_animation_get_count(anim);
|
||||
}
|
||||
|
||||
guint wintc_animation_add_static(
|
||||
WinTCAnimation* anim,
|
||||
GdkPixbuf* static_pixbuf
|
||||
)
|
||||
{
|
||||
WinTCAnimationData* anim_data = g_new0(WinTCAnimationData, 1);
|
||||
|
||||
g_object_ref(static_pixbuf);
|
||||
|
||||
anim_data->pixbuf_bmp = static_pixbuf;
|
||||
anim_data->surface_bmp =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
static_pixbuf,
|
||||
1,
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
|
||||
anim_data->frame_count = 1;
|
||||
anim_data->frame_height = 0;
|
||||
|
||||
anim->priv->animations =
|
||||
g_slist_append(
|
||||
anim->priv->animations,
|
||||
anim_data
|
||||
);
|
||||
|
||||
return wintc_animation_get_count(anim);
|
||||
}
|
||||
|
||||
guint wintc_animation_get_count(
|
||||
WinTCAnimation* anim
|
||||
)
|
||||
{
|
||||
return g_slist_length(anim->priv->animations);
|
||||
}
|
||||
|
||||
GtkAlign wintc_animation_get_halign(
|
||||
WinTCAnimation* anim
|
||||
)
|
||||
{
|
||||
GtkAlign value;
|
||||
|
||||
g_object_get(anim, "gfx-halign", &value, NULL);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
GtkAlign wintc_animation_get_valign(
|
||||
WinTCAnimation* anim
|
||||
)
|
||||
{
|
||||
GtkAlign value;
|
||||
|
||||
g_object_get(anim, "gfx-valign", &value, NULL);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void wintc_animation_play(
|
||||
WinTCAnimation* anim,
|
||||
guint id,
|
||||
gint frame_rate,
|
||||
gint repeats
|
||||
)
|
||||
{
|
||||
// Reset anim state values
|
||||
//
|
||||
anim->priv->is_animating = FALSE;
|
||||
|
||||
anim->priv->current_anim = NULL;
|
||||
anim->priv->current_frame = 0;
|
||||
anim->priv->last_frame = 0;
|
||||
anim->priv->desired_repeats = 0;
|
||||
anim->priv->origin_frame_time = 0;
|
||||
anim->priv->per_frame_time = 0;
|
||||
anim->priv->playback_total_time = 0;
|
||||
|
||||
// Queue a draw regardless of what happens
|
||||
//
|
||||
gtk_widget_queue_draw(GTK_WIDGET(anim));
|
||||
|
||||
// Check we're being asked to actually play anything
|
||||
//
|
||||
if (id > wintc_animation_get_count(anim))
|
||||
{
|
||||
g_warning("WinTCAnimation - attempted to play invalid ID %u", id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == WINTC_ANIMATION_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wahey! We have been asked to play something!
|
||||
//
|
||||
gint real_id = id - 1; // The consumer is given the count rather than index
|
||||
// in the 'add' APIs, so that we can have a special
|
||||
// meaning for 0 (WINTC_ANIMATION_NONE)
|
||||
|
||||
GSList* anim_link = g_slist_nth(
|
||||
anim->priv->animations,
|
||||
real_id
|
||||
);
|
||||
WinTCAnimationData* anim_data = anim_link->data;
|
||||
|
||||
anim->priv->current_anim = anim_data;
|
||||
|
||||
if (
|
||||
anim_data->frame_count > 1 &&
|
||||
frame_rate > 0
|
||||
)
|
||||
{
|
||||
anim->priv->is_animating = TRUE;
|
||||
|
||||
anim->priv->desired_repeats = repeats;
|
||||
anim->priv->origin_frame_time = g_get_monotonic_time();
|
||||
anim->priv->per_frame_time = ONE_SECOND_IN_US / frame_rate;
|
||||
anim->priv->playback_total_time =
|
||||
anim->priv->per_frame_time * anim_data->frame_count;
|
||||
|
||||
if (anim->priv->tick_id == 0)
|
||||
{
|
||||
gtk_widget_add_tick_callback(
|
||||
GTK_WIDGET(anim),
|
||||
(GtkTickCallback) wintc_animation_step,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wintc_animation_remove(
|
||||
WinTCAnimation* anim,
|
||||
guint id
|
||||
)
|
||||
{
|
||||
if (id == 0 || id > wintc_animation_get_count(anim))
|
||||
{
|
||||
g_warning("WinTCAnimation - attempted to remove invalid ID %u", id);
|
||||
return;
|
||||
}
|
||||
|
||||
gint real_id = id - 1;
|
||||
GSList* to_delete = g_slist_nth(anim->priv->animations, real_id);
|
||||
|
||||
free_anim_data(to_delete->data);
|
||||
|
||||
anim->priv->animations =
|
||||
g_slist_delete_link(
|
||||
anim->priv->animations,
|
||||
to_delete
|
||||
);
|
||||
}
|
||||
|
||||
void wintc_animation_set_halign(
|
||||
WinTCAnimation* anim,
|
||||
GtkAlign align
|
||||
)
|
||||
{
|
||||
g_object_set(anim, "gfx-halign", align, NULL);
|
||||
}
|
||||
|
||||
void wintc_animation_set_valign(
|
||||
WinTCAnimation* anim,
|
||||
GtkAlign align
|
||||
)
|
||||
{
|
||||
g_object_set(anim, "gfx-valign", align, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void free_anim_data(
|
||||
WinTCAnimationData* anim_data
|
||||
)
|
||||
{
|
||||
cairo_surface_destroy(anim_data->surface_bmp);
|
||||
g_clear_object(&(anim_data->pixbuf_bmp));
|
||||
g_free(anim_data);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static gboolean wintc_animation_step(
|
||||
GtkWidget* widget,
|
||||
GdkFrameClock* frame_clock,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
WinTCAnimation* anim = WINTC_ANIMATION(widget);
|
||||
|
||||
if (!anim->priv->is_animating)
|
||||
{
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
gint64 frame_time = gdk_frame_clock_get_frame_time(frame_clock);
|
||||
gint64 progress = frame_time - anim->priv->origin_frame_time;
|
||||
gint64 repeat_no = progress / anim->priv->playback_total_time;
|
||||
gint64 within_frame = progress % anim->priv->playback_total_time;
|
||||
gint frame_no = (gint) (within_frame / anim->priv->per_frame_time);
|
||||
|
||||
if (
|
||||
anim->priv->desired_repeats != WINTC_ANIMATION_INFINITE &&
|
||||
anim->priv->desired_repeats < repeat_no
|
||||
)
|
||||
{
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
if (anim->priv->last_frame != frame_no)
|
||||
{
|
||||
gtk_widget_queue_draw(widget);
|
||||
}
|
||||
|
||||
anim->priv->current_frame = frame_no;
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
72
shared/comctl/src/animctl.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef __ANIMCTL_H__
|
||||
#define __ANIMCTL_H__
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// PUBLIC DEFINES
|
||||
//
|
||||
#define WINTC_ANIMATION_INFINITE 0
|
||||
#define WINTC_ANIMATION_NONE 0
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCAnimationPrivate WinTCAnimationPrivate;
|
||||
typedef struct _WinTCAnimationClass WinTCAnimationClass;
|
||||
typedef struct _WinTCAnimation WinTCAnimation;
|
||||
|
||||
#define TYPE_WINTC_ANIMATION (wintc_animation_get_type())
|
||||
#define WINTC_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_ANIMATION, WinTCAnimation))
|
||||
#define WINTC_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_ANIMATION, WinTCAnimation))
|
||||
#define IS_WINTC_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_ANIMATION))
|
||||
#define IS_WINTC_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_ANIMATION))
|
||||
#define WINTC_ANIMATION_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_ANIMATION))
|
||||
|
||||
GType wintc_animation_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_animation_new(void);
|
||||
|
||||
guint wintc_animation_add_framesheet(
|
||||
WinTCAnimation* anim,
|
||||
GdkPixbuf* framesheet_pixbuf,
|
||||
gint frame_count
|
||||
);
|
||||
guint wintc_animation_add_static(
|
||||
WinTCAnimation* anim,
|
||||
GdkPixbuf* static_pixbuf
|
||||
);
|
||||
guint wintc_animation_get_count(
|
||||
WinTCAnimation* anim
|
||||
);
|
||||
GtkAlign wintc_animation_get_halign(
|
||||
WinTCAnimation* anim
|
||||
);
|
||||
GtkAlign wintc_animation_get_valign(
|
||||
WinTCAnimation* anim
|
||||
);
|
||||
void wintc_animation_play(
|
||||
WinTCAnimation* anim,
|
||||
guint id,
|
||||
gint frame_rate,
|
||||
gint repeats
|
||||
);
|
||||
void wintc_animation_remove(
|
||||
WinTCAnimation* anim,
|
||||
guint id
|
||||
);
|
||||
void wintc_animation_set_halign(
|
||||
WinTCAnimation* anim,
|
||||
GtkAlign align
|
||||
);
|
||||
void wintc_animation_set_valign(
|
||||
WinTCAnimation* anim,
|
||||
GtkAlign align
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,10 @@ set(PROJECT_MAINTAINER "Rory Fewell <roryf@oddmatics.uk>")
|
||||
|
||||
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Necessary due to fn ptr casts in marshal.c
|
||||
#
|
||||
set(WINTC_NO_PEDANTIC_COMPILE true)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
include(../../packaging/cmake-inc/common/CMakeLists.txt)
|
||||
@@ -35,6 +39,8 @@ add_library(
|
||||
src/gchar.h
|
||||
src/list.c
|
||||
src/list.h
|
||||
src/marshal.c
|
||||
src/marshal.h
|
||||
src/msgbox.c
|
||||
src/msgbox.h
|
||||
src/profile.c
|
||||
|
||||
@@ -8,7 +8,13 @@
|
||||
// Debugging
|
||||
//
|
||||
#define WINTC_ENVVAR_DEBUG_LOGGING "WINDEBUG"
|
||||
#define WINTC_LOG_DEBUG(...) if (getenv(WINTC_ENVVAR_DEBUG_LOGGING)) { g_message(__VA_ARGS__); }
|
||||
#define WINTC_LOG_USER_DEBUG(...) if (getenv(WINTC_ENVVAR_DEBUG_LOGGING)) { g_message(__VA_ARGS__); }
|
||||
|
||||
#ifdef WINTC_CHECKED
|
||||
#define WINTC_LOG_DEBUG(...) g_message(__VA_ARGS__);
|
||||
#else
|
||||
#define WINTC_LOG_DEBUG(...)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Shorthand
|
||||
@@ -101,6 +107,27 @@ GList* wintc_list_read_from_string(
|
||||
const gchar* str
|
||||
);
|
||||
|
||||
//
|
||||
// Closure Marshals
|
||||
//
|
||||
void wintc_cclosure_marshal_BOOLEAN__VOID(
|
||||
GClosure* closure,
|
||||
GValue* return_value,
|
||||
guint n_param_values,
|
||||
const GValue* param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data
|
||||
);
|
||||
|
||||
void wintc_cclosure_marshal_INT__VOID(
|
||||
GClosure* closure,
|
||||
GValue* return_value,
|
||||
guint n_param_values,
|
||||
const GValue* param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data
|
||||
);
|
||||
|
||||
//
|
||||
// Message Box-related
|
||||
//
|
||||
@@ -208,4 +235,4 @@ void wintc_focus_window(
|
||||
GtkWindow* window
|
||||
);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,7 +1,17 @@
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
// Two variants for debug messaging are provided:
|
||||
// USER_DEBUG is at runtime, intended at end user debugging
|
||||
// DEBUG is compile time, intended for development
|
||||
//
|
||||
#define WINTC_ENVVAR_DEBUG_LOGGING "WINDEBUG"
|
||||
#define WINTC_LOG_DEBUG(...) if (getenv(WINTC_ENVVAR_DEBUG_LOGGING)) { g_message(__VA_ARGS__); }
|
||||
#define WINTC_LOG_USER_DEBUG(...) if (getenv(WINTC_ENVVAR_DEBUG_LOGGING)) { g_message(__VA_ARGS__); }
|
||||
|
||||
#ifdef WINTC_CHECKED
|
||||
#define WINTC_LOG_DEBUG(...) g_message(__VA_ARGS__);
|
||||
#else
|
||||
#define WINTC_LOG_DEBUG(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
96
shared/comgtk/src/marshal.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "marshal.h"
|
||||
#include "shorthand.h"
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
void wintc_cclosure_marshal_BOOLEAN__VOID(
|
||||
GClosure* closure,
|
||||
GValue* return_value,
|
||||
guint n_param_values,
|
||||
const GValue* param_values,
|
||||
WINTC_UNUSED(gpointer invocation_hint),
|
||||
gpointer marshal_data
|
||||
)
|
||||
{
|
||||
typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (
|
||||
gpointer data1,
|
||||
gpointer data2
|
||||
);
|
||||
|
||||
GMarshalFunc_BOOLEAN__VOID callback;
|
||||
GCClosure* cc;
|
||||
gpointer data1;
|
||||
gpointer data2;
|
||||
gboolean v_return;
|
||||
|
||||
cc = (GCClosure*) closure;
|
||||
|
||||
g_return_if_fail(n_param_values == 1);
|
||||
|
||||
if (G_CCLOSURE_SWAP_DATA(closure))
|
||||
{
|
||||
data1 = closure->data;
|
||||
data2 = g_value_peek_pointer(param_values + 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data1 = g_value_peek_pointer(param_values + 0);
|
||||
data2 = closure->data;
|
||||
}
|
||||
|
||||
callback =
|
||||
(GMarshalFunc_BOOLEAN__VOID)
|
||||
(marshal_data ? marshal_data : cc->callback);
|
||||
|
||||
v_return = callback(data1, data2);
|
||||
|
||||
g_value_set_boolean(return_value, v_return);
|
||||
}
|
||||
|
||||
void wintc_cclosure_marshal_INT__VOID(
|
||||
GClosure* closure,
|
||||
GValue* return_value,
|
||||
guint n_param_values,
|
||||
const GValue* param_values,
|
||||
WINTC_UNUSED(gpointer invocation_hint),
|
||||
gpointer marshal_data
|
||||
)
|
||||
{
|
||||
typedef gint (*GMarshalFunc_INT__VOID) (
|
||||
gpointer data1,
|
||||
gpointer data2
|
||||
);
|
||||
|
||||
GMarshalFunc_INT__VOID callback;
|
||||
GCClosure* cc;
|
||||
gpointer data1;
|
||||
gpointer data2;
|
||||
gboolean v_return;
|
||||
|
||||
cc = (GCClosure*) closure;
|
||||
|
||||
g_return_if_fail(n_param_values == 1);
|
||||
|
||||
if (G_CCLOSURE_SWAP_DATA(closure))
|
||||
{
|
||||
data1 = closure->data;
|
||||
data2 = g_value_peek_pointer(param_values + 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
data1 = g_value_peek_pointer(param_values + 0);
|
||||
data2 = closure->data;
|
||||
}
|
||||
|
||||
callback =
|
||||
(GMarshalFunc_INT__VOID)
|
||||
(marshal_data ? marshal_data : cc->callback);
|
||||
|
||||
v_return = callback(data1, data2);
|
||||
|
||||
g_value_set_int(return_value, v_return);
|
||||
}
|
||||
28
shared/comgtk/src/marshal.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __MARSHAL_H__
|
||||
#define __MARSHAL_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
void wintc_cclosure_marshal_BOOLEAN__VOID(
|
||||
GClosure* closure,
|
||||
GValue* return_value,
|
||||
guint n_param_values,
|
||||
const GValue* param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data
|
||||
);
|
||||
|
||||
void wintc_cclosure_marshal_INT__VOID(
|
||||
GClosure* closure,
|
||||
GValue* return_value,
|
||||
guint n_param_values,
|
||||
const GValue* param_values,
|
||||
gpointer invocation_hint,
|
||||
gpointer marshal_data
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +0,0 @@
|
||||
Package: lib@PROJECT_NAME@-@PROJECT_VERSION@
|
||||
Version: @PROJECT_VERSION@
|
||||
Maintainer: Rory Fewell <roryf@oddmatics.uk>
|
||||
Architecture: @ARCH_NAME@
|
||||
Section: free
|
||||
Description: @PROJECT_DESCRIPTION@
|
||||
Depends: @DEB_DEPENDENCIES@
|
||||
@@ -76,7 +76,7 @@ gboolean wintc_launch_command(
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(out_error);
|
||||
|
||||
WINTC_LOG_DEBUG("Launching %s", cmdline);
|
||||
WINTC_LOG_USER_DEBUG("Launching %s", cmdline);
|
||||
|
||||
// Iterate through parsers
|
||||
//
|
||||
@@ -93,7 +93,7 @@ gboolean wintc_launch_command(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("Parse result: %s", real_cmdline);
|
||||
WINTC_LOG_USER_DEBUG("Parse result: %s", real_cmdline);
|
||||
|
||||
wintc_strsteal(&tmp_cmdline, &real_cmdline);
|
||||
|
||||
@@ -104,7 +104,7 @@ gboolean wintc_launch_command(
|
||||
//
|
||||
real_cmdline = tmp_cmdline;
|
||||
|
||||
WINTC_LOG_DEBUG("Parsed command line: %s", real_cmdline);
|
||||
WINTC_LOG_USER_DEBUG("Parsed command line: %s", real_cmdline);
|
||||
|
||||
// Parse the command line into an argument vector
|
||||
//
|
||||
@@ -142,14 +142,14 @@ gboolean wintc_launch_command(
|
||||
|
||||
if (!success)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Failed to launch: %s", error->message);
|
||||
WINTC_LOG_USER_DEBUG("Failed to launch: %s", error->message);
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("Done.");
|
||||
WINTC_LOG_USER_DEBUG("Done.");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -201,7 +201,7 @@ static gboolean parse_file_in_cmdline(
|
||||
g_strcmp0(file_mime, "application/x-sharedlib") != 0
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Not an executable, will look for handler.");
|
||||
WINTC_LOG_USER_DEBUG("Not an executable, will look for handler.");
|
||||
|
||||
handler_entry =
|
||||
wintc_query_mime_handler(
|
||||
@@ -211,7 +211,7 @@ static gboolean parse_file_in_cmdline(
|
||||
|
||||
if (handler_entry == NULL)
|
||||
{
|
||||
WINTC_LOG_DEBUG("I have nothing to handle the file!");
|
||||
WINTC_LOG_USER_DEBUG("I have nothing to handle the file!");
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
WINTC_SAFE_REF_SET(out_cmdline, g_strdup(cmdline));
|
||||
@@ -282,7 +282,7 @@ static gboolean parse_unc_path_in_cmdline(
|
||||
|
||||
if (unc_regex == NULL)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Failed to create the UNC path regex.");
|
||||
WINTC_LOG_USER_DEBUG("Failed to create the UNC path regex.");
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
@@ -292,7 +292,7 @@ static gboolean parse_unc_path_in_cmdline(
|
||||
|
||||
// Examine command line
|
||||
//
|
||||
WINTC_LOG_DEBUG("Checking if %s looks like a UNC path...", cmdline);
|
||||
WINTC_LOG_USER_DEBUG("Checking if %s looks like a UNC path...", cmdline);
|
||||
|
||||
g_regex_match(unc_regex, cmdline, 0, &match_info);
|
||||
|
||||
@@ -302,7 +302,7 @@ static gboolean parse_unc_path_in_cmdline(
|
||||
//
|
||||
if (match_count == 0)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Nope!");
|
||||
WINTC_LOG_USER_DEBUG("Nope!");
|
||||
|
||||
g_match_info_free(match_info);
|
||||
|
||||
@@ -313,7 +313,7 @@ static gboolean parse_unc_path_in_cmdline(
|
||||
|
||||
// Command line IS a UNC path, we need to retrieve the target host and path
|
||||
//
|
||||
WINTC_LOG_DEBUG("Yeah, looks like a UNC path.");
|
||||
WINTC_LOG_USER_DEBUG("Yeah, looks like a UNC path.");
|
||||
|
||||
host = g_strdup(g_match_info_fetch(match_info, 1));
|
||||
|
||||
@@ -329,8 +329,8 @@ static gboolean parse_unc_path_in_cmdline(
|
||||
|
||||
g_match_info_free(match_info);
|
||||
|
||||
// Construct URI (doesn't matter if path is NULL, the func stops at the first
|
||||
// NULL anyway)
|
||||
// Construct URI (doesn't matter if path is NULL, the func stops at the
|
||||
// first NULL anyway)
|
||||
//
|
||||
uri = g_strconcat("smb://", host, path, NULL);
|
||||
|
||||
@@ -376,7 +376,7 @@ static gboolean parse_url_in_cmdline(
|
||||
|
||||
if (url_regex == NULL)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Failed to create the URL regex.");
|
||||
WINTC_LOG_USER_DEBUG("Failed to create the URL regex.");
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
@@ -386,7 +386,7 @@ static gboolean parse_url_in_cmdline(
|
||||
|
||||
// Examine command line
|
||||
//
|
||||
WINTC_LOG_DEBUG("Checking if %s looks like a URL...", cmdline);
|
||||
WINTC_LOG_USER_DEBUG("Checking if %s looks like a URL...", cmdline);
|
||||
|
||||
g_regex_match(url_regex, cmdline, 0, &match_info);
|
||||
|
||||
@@ -394,7 +394,7 @@ static gboolean parse_url_in_cmdline(
|
||||
//
|
||||
if (g_match_info_get_match_count(match_info) == 0)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Nope!");
|
||||
WINTC_LOG_USER_DEBUG("Nope!");
|
||||
|
||||
g_match_info_free(match_info);
|
||||
|
||||
@@ -405,7 +405,7 @@ static gboolean parse_url_in_cmdline(
|
||||
|
||||
// Command line IS a URL, retrieve the scheme, query the handling program...
|
||||
//
|
||||
WINTC_LOG_DEBUG("Yeah, looks like a URL.");
|
||||
WINTC_LOG_USER_DEBUG("Yeah, looks like a URL.");
|
||||
|
||||
uri_scheme = g_match_info_fetch(match_info, 1);
|
||||
mime_type = g_strdup_printf(
|
||||
@@ -421,7 +421,7 @@ static gboolean parse_url_in_cmdline(
|
||||
|
||||
if (handler_entry == NULL)
|
||||
{
|
||||
WINTC_LOG_DEBUG("I have nothing to handle the URL!");
|
||||
WINTC_LOG_USER_DEBUG("I have nothing to handle the URL!");
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
@@ -476,7 +476,7 @@ static gchar** true_shell_parse_argv(
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Failed to parse command line: %s", cmdline);
|
||||
WINTC_LOG_USER_DEBUG("Failed to parse command line: %s", cmdline);
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ gchar* wintc_query_mime_for_file(
|
||||
gint status;
|
||||
gboolean success = FALSE;
|
||||
|
||||
WINTC_LOG_DEBUG("Querying MIME type for: %s", filepath);
|
||||
WINTC_LOG_USER_DEBUG("Querying MIME type for: %s", filepath);
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(out_error);
|
||||
|
||||
@@ -47,7 +47,7 @@ gchar* wintc_query_mime_for_file(
|
||||
{
|
||||
g_strstrip(cmd_output);
|
||||
|
||||
WINTC_LOG_DEBUG("Determined: %s", cmd_output);
|
||||
WINTC_LOG_USER_DEBUG("Determined: %s", cmd_output);
|
||||
|
||||
return cmd_output;
|
||||
}
|
||||
@@ -56,14 +56,14 @@ gchar* wintc_query_mime_for_file(
|
||||
//
|
||||
if (error != NULL)
|
||||
{
|
||||
WINTC_LOG_DEBUG("An error occurred: %s", error->message);
|
||||
WINTC_LOG_USER_DEBUG("An error occurred: %s", error->message);
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("Failed with code %d", status);
|
||||
WINTC_LOG_USER_DEBUG("Failed with code %d", status);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -109,7 +109,7 @@ GDesktopAppInfo* wintc_query_mime_handler(
|
||||
gchar* filename = NULL;
|
||||
gboolean success = FALSE;
|
||||
|
||||
WINTC_LOG_DEBUG("Querying handler for MIME type %s", mime_query);
|
||||
WINTC_LOG_USER_DEBUG("Querying handler for MIME type %s", mime_query);
|
||||
|
||||
WINTC_SAFE_REF_CLEAR(out_error);
|
||||
|
||||
@@ -128,7 +128,7 @@ GDesktopAppInfo* wintc_query_mime_handler(
|
||||
|
||||
if (!success)
|
||||
{
|
||||
WINTC_LOG_DEBUG("Failed to query MIME type: %s", error->message);
|
||||
WINTC_LOG_USER_DEBUG("Failed to query MIME type: %s", error->message);
|
||||
|
||||
g_propagate_error(out_error, error);
|
||||
|
||||
@@ -143,7 +143,7 @@ GDesktopAppInfo* wintc_query_mime_handler(
|
||||
|
||||
if (output_length == 0)
|
||||
{
|
||||
WINTC_LOG_DEBUG("No handler found!");
|
||||
WINTC_LOG_USER_DEBUG("No handler found!");
|
||||
|
||||
g_set_error(
|
||||
out_error,
|
||||
@@ -167,7 +167,7 @@ GDesktopAppInfo* wintc_query_mime_handler(
|
||||
);
|
||||
entry = g_desktop_app_info_new(filename);
|
||||
|
||||
WINTC_LOG_DEBUG("Query returned: %s", filename);
|
||||
WINTC_LOG_USER_DEBUG("Query returned: %s", filename);
|
||||
|
||||
g_free(cmd_output);
|
||||
g_free(filename);
|
||||
@@ -182,7 +182,7 @@ GDesktopAppInfo* wintc_query_mime_handler(
|
||||
mime_query
|
||||
);
|
||||
|
||||
WINTC_LOG_DEBUG("Association found, but the desktop entry doesn't exist.");
|
||||
WINTC_LOG_USER_DEBUG("Association found, but the desktop entry doesn't exist.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
103
shared/msgina/CMakeLists.txt
Normal file
@@ -0,0 +1,103 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(
|
||||
libwintc-msgina
|
||||
VERSION 1.0
|
||||
DESCRIPTION "Windows Total Conversion GINA library."
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
set(PROJECT_ANYARCH false)
|
||||
set(PROJECT_FREESTATUS false)
|
||||
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/libraries/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/resources/CMakeLists.txt)
|
||||
|
||||
wintc_resolve_library(gdk-pixbuf-2.0 GDK_PIXBUF)
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
wintc_resolve_library(gtk+-3.0 GTK3)
|
||||
wintc_resolve_library(liblightdm-gobject-1 LIGHTDM)
|
||||
wintc_resolve_library(wintc-comctl WINTC_COMCTL)
|
||||
wintc_resolve_library(wintc-comgtk WINTC_COMGTK)
|
||||
wintc_resolve_library(wintc-winbrand WINTC_WINBRAND)
|
||||
|
||||
wintc_compile_resources()
|
||||
|
||||
add_library(
|
||||
libwintc-msgina
|
||||
src/resources.c
|
||||
src/authwnd.c
|
||||
src/authwnd.h
|
||||
src/challenge.h
|
||||
src/logon.c
|
||||
src/logon.h
|
||||
src/state.h
|
||||
src/stripctl.c
|
||||
src/stripctl.h
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
libwintc-msgina
|
||||
PROPERTIES
|
||||
PUBLIC_HEADER public/wintc-msgina.h
|
||||
SOVERSION 1
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
libwintc-msgina
|
||||
PRIVATE ${WINTC_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
libwintc-msgina
|
||||
SYSTEM
|
||||
PRIVATE ${GDK_PIXBUF_INCLUDE_DIRS}
|
||||
PRIVATE ${GLIB_INCLUDE_DIRS}
|
||||
PRIVATE ${GTK3_INCLUDE_DIRS}
|
||||
PRIVATE ${LIGHTDM_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_INCLUDE_DIRS}
|
||||
PRIVATE ${WINTC_WINBRAND_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_directories(
|
||||
libwintc-msgina
|
||||
PRIVATE ${GDK_PIXBUF_LIBRARY_DIRS}
|
||||
PRIVATE ${GLIB_LIBRARY_DIRS}
|
||||
PRIVATE ${GTK3_LIBRARY_DIRS}
|
||||
PRIVATE ${LIGHTDM_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARY_DIRS}
|
||||
PRIVATE ${WINTC_WINBRAND_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
libwintc-msgina
|
||||
PRIVATE ${GDK_PIXBUF_LIBRARIES}
|
||||
PRIVATE ${GLIB_LIBRARIES}
|
||||
PRIVATE ${GTK3_LIBRARIES}
|
||||
PRIVATE ${LIGHTDM_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMCTL_LIBRARIES}
|
||||
PRIVATE ${WINTC_COMGTK_LIBRARIES}
|
||||
PRIVATE ${WINTC_WINBRAND_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
wintc_add_pkgconfig_install()
|
||||
|
||||
install(
|
||||
TARGETS libwintc-msgina
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
7
shared/msgina/README.MD
Normal file
@@ -0,0 +1,7 @@
|
||||
# libwintc-msgina
|
||||
This directory contains the source-code for the GINA services (logon/security/auth related functions).
|
||||
|
||||
# Purpose
|
||||
This library provides services related to security. At the moment this includes the APIs for performing user logon (via LightDM), and contains the 'classic' logon dialog.
|
||||
|
||||
In future this should be expanded to handle other forms of logon rather than just simple text based local auth, as well as things like the Windows Security dialog.
|
||||
4
shared/msgina/deps
Normal file
@@ -0,0 +1,4 @@
|
||||
bt,rt:glib2
|
||||
bt,rt:gtk3
|
||||
bt,rt:wintc-comgtk
|
||||
bt,rt:wintc-winbrand
|
||||
77
shared/msgina/public/wintc-msgina.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef __WINTC_MSGINA_H__
|
||||
#define __WINTC_MSGINA_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// Authentication window
|
||||
//
|
||||
typedef struct _WinTCGinaAuthWindowPrivate WinTCGinaAuthWindowPrivate;
|
||||
typedef struct _WinTCGinaAuthWindowClass WinTCGinaAuthWindowClass;
|
||||
typedef struct _WinTCGinaAuthWindow WinTCGinaAuthWindow;
|
||||
|
||||
#define TYPE_WINTC_GINA_AUTH_WINDOW (wintc_gina_auth_window_get_type())
|
||||
#define WINTC_GINA_AUTH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_GINA_AUTH_WINDOW, WinTCGinaAuthWindow))
|
||||
#define WINTC_GINA_AUTH_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_GINA_AUTH_WINDOW, WinTCGinaAuthWindow))
|
||||
#define IS_WINTC_GINA_AUTH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_GINA_AUTH_WINDOW))
|
||||
#define IS_WINTC_GINA_AUTH_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_GINA_AUTH_WINDOW))
|
||||
#define WINTC_GINA_WINDOW_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_GINA_AUTH_WINDOW))
|
||||
|
||||
GType wintc_gina_auth_window_get_type(void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget* wintc_gina_auth_window_new(void);
|
||||
|
||||
//
|
||||
// Challenge auth
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
WINTC_GINA_RESPONSE_OKAY = 0,
|
||||
WINTC_GINA_RESPONSE_FAIL = 1
|
||||
} WinTCGinaResponse;
|
||||
|
||||
//
|
||||
// Logon session
|
||||
//
|
||||
typedef struct _WinTCGinaLogonSessionClass WinTCGinaLogonSessionClass;
|
||||
typedef struct _WinTCGinaLogonSession WinTCGinaLogonSession;
|
||||
|
||||
#define TYPE_WINTC_GINA_LOGON_SESSION (wintc_gina_logon_session_get_type())
|
||||
#define WINTC_GINA_LOGON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_GINA_LOGON_SESSION, WinTCGinaLogonSession))
|
||||
#define WINTC_GINA_LOGON_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_GINA_LOGON_SESSION, WinTCGinaLogonSession))
|
||||
#define IS_WINTC_GINA_LOGON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_GINA_LOGON_SESSION))
|
||||
#define IS_WINTC_GINA_LOGON_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_GINA_LOGON_SESSION))
|
||||
#define WINTC_GINA_LOGON_SESSION_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_GINA_LOGON_SESSION)
|
||||
|
||||
GType wintc_gina_logon_session_get_type(void) G_GNUC_CONST;
|
||||
|
||||
WinTCGinaLogonSession* wintc_gina_logon_session_new(void);
|
||||
|
||||
gboolean wintc_gina_logon_session_establish(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
void wintc_gina_logon_session_finish(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
gboolean wintc_gina_logon_session_is_available(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
void wintc_gina_logon_session_try_logon(
|
||||
WinTCGinaLogonSession* logon_session,
|
||||
const gchar* username,
|
||||
const gchar* password
|
||||
);
|
||||
|
||||
//
|
||||
// State
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
WINTC_GINA_STATE_NONE = 0,
|
||||
WINTC_GINA_STATE_STARTING,
|
||||
WINTC_GINA_STATE_PROMPT,
|
||||
WINTC_GINA_STATE_LAUNCHING
|
||||
} WinTCGinaState;
|
||||
|
||||
#endif
|
||||
631
shared/msgina/src/authwnd.c
Normal file
@@ -0,0 +1,631 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comctl.h>
|
||||
#include <wintc-comgtk.h>
|
||||
#include <wintc-winbrand.h>
|
||||
|
||||
#include "authwnd.h"
|
||||
#include "challenge.h"
|
||||
#include "logon.h"
|
||||
#include "state.h"
|
||||
#include "stripctl.h"
|
||||
|
||||
#define DELAY_SECONDS_AT_LEAST 2
|
||||
#define DELAY_SECONDS_POLL 1
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCGinaAuthWindowPrivate
|
||||
{
|
||||
// Image resources
|
||||
//
|
||||
GdkPixbuf* pixbuf_banner;
|
||||
GdkPixbuf* pixbuf_bannerx;
|
||||
|
||||
// UI
|
||||
//
|
||||
GtkWidget* box_container;
|
||||
|
||||
GtkWidget* box_brand;
|
||||
GtkWidget* box_login;
|
||||
GtkWidget* box_wait;
|
||||
|
||||
GtkWidget* button_submit;
|
||||
GtkWidget* entry_password;
|
||||
GtkWidget* entry_username;
|
||||
|
||||
GtkWidget* strip;
|
||||
|
||||
// State
|
||||
//
|
||||
WinTCGinaState current_state;
|
||||
WinTCGinaLogonSession* logon_session;
|
||||
};
|
||||
|
||||
struct _WinTCGinaAuthWindowClass
|
||||
{
|
||||
GtkWindowClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCGinaAuthWindow
|
||||
{
|
||||
GtkWindow __parent__;
|
||||
|
||||
WinTCGinaAuthWindowPrivate* priv;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_gina_auth_window_finalize(
|
||||
GObject* object
|
||||
);
|
||||
|
||||
static void wintc_gina_auth_window_change_state(
|
||||
WinTCGinaAuthWindow* window,
|
||||
WinTCGinaState next_state
|
||||
);
|
||||
|
||||
static void on_self_realized(
|
||||
GtkWidget* self,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static void on_logon_session_attempt_complete(
|
||||
WinTCGinaLogonSession* logon_session,
|
||||
WinTCGinaResponse response,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static void on_button_submit_clicked(
|
||||
GtkButton* self,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static gboolean on_timeout_delay_done(
|
||||
gpointer user_data
|
||||
);
|
||||
static gboolean on_timeout_poll_ready(
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCGinaAuthWindow,
|
||||
wintc_gina_auth_window,
|
||||
GTK_TYPE_WINDOW,
|
||||
G_ADD_PRIVATE(WinTCGinaAuthWindow)
|
||||
)
|
||||
|
||||
static void wintc_gina_auth_window_class_init(
|
||||
WinTCGinaAuthWindowClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = wintc_gina_auth_window_finalize;
|
||||
|
||||
// Load up styles
|
||||
//
|
||||
GtkCssProvider* css_authwnd = gtk_css_provider_new();
|
||||
|
||||
gtk_css_provider_load_from_resource(
|
||||
css_authwnd,
|
||||
"/uk/oddmatics/wintc/msgina/authwnd.css"
|
||||
);
|
||||
|
||||
gtk_style_context_add_provider_for_screen(
|
||||
gdk_screen_get_default(),
|
||||
GTK_STYLE_PROVIDER(css_authwnd),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_FALLBACK
|
||||
);
|
||||
|
||||
wintc_comctl_install_default_styles();
|
||||
}
|
||||
|
||||
static void wintc_gina_auth_window_init(
|
||||
WinTCGinaAuthWindow* self
|
||||
)
|
||||
{
|
||||
self->priv = wintc_gina_auth_window_get_instance_private(self);
|
||||
|
||||
// Acquire branding pixbufs
|
||||
//
|
||||
GError* err_banner = NULL;
|
||||
GError* err_bannerx = NULL;
|
||||
|
||||
self->priv->pixbuf_banner = wintc_brand_get_brand_pixmap(
|
||||
WINTC_BRAND_PART_BANNER,
|
||||
&err_banner
|
||||
);
|
||||
self->priv->pixbuf_bannerx = wintc_brand_get_brand_pixmap(
|
||||
WINTC_BRAND_PART_BANNER_TALL,
|
||||
&err_bannerx
|
||||
);
|
||||
|
||||
wintc_display_error_and_clear(&err_banner);
|
||||
wintc_display_error_and_clear(&err_bannerx);
|
||||
|
||||
// Set up branding box
|
||||
//
|
||||
GtkWidget* image_brand =
|
||||
gtk_image_new_from_pixbuf(
|
||||
self->priv->pixbuf_bannerx
|
||||
);
|
||||
|
||||
self->priv->box_brand = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
self->priv->strip = wintc_gina_strip_new();
|
||||
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_brand),
|
||||
image_brand,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0
|
||||
);
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_brand),
|
||||
self->priv->strip,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0
|
||||
);
|
||||
|
||||
// Set up 'Please wait...' box
|
||||
//
|
||||
GtkWidget* label_wait = gtk_label_new("Please wait...");
|
||||
|
||||
self->priv->box_wait = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
wintc_widget_add_style_class(
|
||||
self->priv->box_wait,
|
||||
"please-wait"
|
||||
);
|
||||
|
||||
gtk_widget_set_halign(
|
||||
label_wait,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
gtk_widget_set_valign(
|
||||
label_wait,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(self->priv->box_wait),
|
||||
label_wait,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
|
||||
// Set up login box
|
||||
//
|
||||
GtkWidget* box_buttons = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
GtkWidget* grid_login = gtk_grid_new();
|
||||
GtkWidget* label_password = gtk_label_new("Password:");
|
||||
GtkWidget* label_username = gtk_label_new("User name:");
|
||||
|
||||
self->priv->box_login = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
self->priv->button_submit = gtk_button_new_with_label("OK");
|
||||
self->priv->entry_password = gtk_entry_new();
|
||||
self->priv->entry_username = gtk_entry_new();
|
||||
|
||||
wintc_widget_add_style_class(
|
||||
box_buttons,
|
||||
WINTC_COMCTL_BUTTON_BOX_CSS_CLASS
|
||||
);
|
||||
|
||||
wintc_widget_add_style_class(
|
||||
self->priv->box_login,
|
||||
"login"
|
||||
);
|
||||
|
||||
gtk_widget_set_halign(
|
||||
label_password,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
gtk_widget_set_halign(
|
||||
label_username,
|
||||
GTK_ALIGN_START
|
||||
);
|
||||
|
||||
gtk_entry_set_visibility(GTK_ENTRY(self->priv->entry_password), FALSE);
|
||||
|
||||
g_signal_connect(
|
||||
self->priv->button_submit,
|
||||
"clicked",
|
||||
G_CALLBACK(on_button_submit_clicked),
|
||||
self
|
||||
);
|
||||
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(grid_login),
|
||||
label_username,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
);
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(grid_login),
|
||||
self->priv->entry_username,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
);
|
||||
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(grid_login),
|
||||
label_password,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
);
|
||||
gtk_grid_attach(
|
||||
GTK_GRID(grid_login),
|
||||
self->priv->entry_password,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
);
|
||||
|
||||
gtk_box_pack_end(
|
||||
GTK_BOX(box_buttons),
|
||||
self->priv->button_submit,
|
||||
FALSE,
|
||||
FALSE,
|
||||
0
|
||||
);
|
||||
|
||||
gtk_container_add(
|
||||
GTK_CONTAINER(self->priv->box_login),
|
||||
grid_login
|
||||
);
|
||||
gtk_container_add(
|
||||
GTK_CONTAINER(self->priv->box_login),
|
||||
box_buttons
|
||||
);
|
||||
|
||||
// Set up remainder of UI
|
||||
//
|
||||
GtkWidget* header_bar = gtk_header_bar_new();
|
||||
|
||||
self->priv->box_container = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
gtk_header_bar_set_title(
|
||||
GTK_HEADER_BAR(header_bar),
|
||||
"Log On to Windows"
|
||||
);
|
||||
|
||||
gtk_container_add(
|
||||
GTK_CONTAINER(self->priv->box_container),
|
||||
self->priv->box_brand
|
||||
);
|
||||
|
||||
gtk_container_add(
|
||||
GTK_CONTAINER(self),
|
||||
self->priv->box_container
|
||||
);
|
||||
|
||||
gtk_window_set_titlebar(
|
||||
GTK_WINDOW(self),
|
||||
header_bar
|
||||
);
|
||||
|
||||
// Hold additional references to the boxes, so we can add/remove
|
||||
// them ourselves without them getting binned
|
||||
//
|
||||
g_object_ref(self->priv->box_login);
|
||||
g_object_ref(self->priv->box_wait);
|
||||
|
||||
// Connect to realize signal to kick off everything when we're
|
||||
// actually live
|
||||
//
|
||||
g_signal_connect(
|
||||
self,
|
||||
"realize",
|
||||
G_CALLBACK(on_self_realized),
|
||||
NULL
|
||||
);
|
||||
|
||||
// Set initial state
|
||||
//
|
||||
self->priv->current_state = WINTC_GINA_STATE_NONE;
|
||||
self->priv->logon_session = wintc_gina_logon_session_new();
|
||||
|
||||
g_signal_connect(
|
||||
self->priv->logon_session,
|
||||
"attempt-complete",
|
||||
G_CALLBACK(on_logon_session_attempt_complete),
|
||||
self
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_gina_auth_window_finalize(
|
||||
GObject* gobject
|
||||
)
|
||||
{
|
||||
WinTCGinaAuthWindow* window = WINTC_GINA_AUTH_WINDOW(gobject);
|
||||
|
||||
g_clear_object(&(window->priv->pixbuf_banner));
|
||||
g_clear_object(&(window->priv->pixbuf_bannerx));
|
||||
|
||||
// Bin additional references held for the boxes
|
||||
//
|
||||
g_clear_object(&(window->priv->box_login));
|
||||
g_clear_object(&(window->priv->box_wait));
|
||||
|
||||
(G_OBJECT_CLASS(wintc_gina_auth_window_parent_class))->finalize(gobject);
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_gina_auth_window_new(void)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
TYPE_WINTC_GINA_AUTH_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"resizable", FALSE,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE FUNCTIONS
|
||||
//
|
||||
static void wintc_gina_auth_window_change_state(
|
||||
WinTCGinaAuthWindow* window,
|
||||
WinTCGinaState next_state
|
||||
)
|
||||
{
|
||||
// Disable current state, if any
|
||||
//
|
||||
switch (window->priv->current_state)
|
||||
{
|
||||
case WINTC_GINA_STATE_STARTING:
|
||||
case WINTC_GINA_STATE_LAUNCHING:
|
||||
wintc_gina_strip_stop_animating(
|
||||
WINTC_GINA_STRIP(window->priv->strip)
|
||||
);
|
||||
gtk_container_remove(
|
||||
GTK_CONTAINER(window->priv->box_container),
|
||||
window->priv->box_wait
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_PROMPT:
|
||||
gtk_container_remove(
|
||||
GTK_CONTAINER(window->priv->box_container),
|
||||
window->priv->box_login
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Set up new state
|
||||
//
|
||||
switch (next_state)
|
||||
{
|
||||
case WINTC_GINA_STATE_STARTING:
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(window->priv->box_container),
|
||||
window->priv->box_wait,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
wintc_gina_strip_animate(
|
||||
WINTC_GINA_STRIP(window->priv->strip)
|
||||
);
|
||||
wintc_gina_logon_session_establish(
|
||||
window->priv->logon_session
|
||||
);
|
||||
g_timeout_add_seconds(
|
||||
DELAY_SECONDS_AT_LEAST,
|
||||
on_timeout_delay_done,
|
||||
window
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_PROMPT:
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(window->priv->box_container),
|
||||
window->priv->box_login,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_LAUNCHING:
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(window->priv->box_container),
|
||||
window->priv->box_wait,
|
||||
TRUE,
|
||||
TRUE,
|
||||
0
|
||||
);
|
||||
wintc_gina_strip_animate(
|
||||
WINTC_GINA_STRIP(window->priv->strip)
|
||||
);
|
||||
g_timeout_add_seconds(
|
||||
DELAY_SECONDS_AT_LEAST,
|
||||
on_timeout_delay_done,
|
||||
window
|
||||
);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
gtk_widget_show_all(
|
||||
window->priv->box_container
|
||||
);
|
||||
|
||||
window->priv->current_state = next_state;
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void on_self_realized(
|
||||
GtkWidget* self,
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
wintc_gina_auth_window_change_state(
|
||||
WINTC_GINA_AUTH_WINDOW(self),
|
||||
WINTC_GINA_STATE_STARTING
|
||||
);
|
||||
}
|
||||
|
||||
static void on_logon_session_attempt_complete(
|
||||
WINTC_UNUSED(WinTCGinaLogonSession* logon_session),
|
||||
WinTCGinaResponse response,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCGinaAuthWindow* window = WINTC_GINA_AUTH_WINDOW(user_data);
|
||||
|
||||
switch (response)
|
||||
{
|
||||
case WINTC_GINA_RESPONSE_OKAY:
|
||||
wintc_gina_auth_window_change_state(
|
||||
window,
|
||||
WINTC_GINA_STATE_LAUNCHING
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_RESPONSE_FAIL:
|
||||
// FIXME: Prompt for failure
|
||||
gtk_entry_set_text(
|
||||
GTK_ENTRY(window->priv->entry_password),
|
||||
""
|
||||
);
|
||||
gtk_entry_set_text(
|
||||
GTK_ENTRY(window->priv->entry_username),
|
||||
""
|
||||
);
|
||||
|
||||
gtk_widget_set_sensitive(
|
||||
window->priv->button_submit,
|
||||
TRUE
|
||||
);
|
||||
gtk_widget_set_sensitive(
|
||||
window->priv->entry_password,
|
||||
TRUE
|
||||
);
|
||||
gtk_widget_set_sensitive(
|
||||
window->priv->entry_username,
|
||||
TRUE
|
||||
);
|
||||
|
||||
wintc_gina_strip_stop_animating(
|
||||
WINTC_GINA_STRIP(window->priv->strip)
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_button_submit_clicked(
|
||||
WINTC_UNUSED(GtkButton* self),
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCGinaAuthWindow* window = WINTC_GINA_AUTH_WINDOW(user_data);
|
||||
|
||||
gtk_widget_set_sensitive(
|
||||
window->priv->button_submit,
|
||||
FALSE
|
||||
);
|
||||
gtk_widget_set_sensitive(
|
||||
window->priv->entry_password,
|
||||
FALSE
|
||||
);
|
||||
gtk_widget_set_sensitive(
|
||||
window->priv->entry_username,
|
||||
FALSE
|
||||
);
|
||||
|
||||
wintc_gina_strip_animate(
|
||||
WINTC_GINA_STRIP(window->priv->strip)
|
||||
);
|
||||
|
||||
wintc_gina_logon_session_try_logon(
|
||||
window->priv->logon_session,
|
||||
gtk_entry_get_text(GTK_ENTRY(window->priv->entry_username)),
|
||||
gtk_entry_get_text(GTK_ENTRY(window->priv->entry_password))
|
||||
);
|
||||
}
|
||||
|
||||
static gboolean on_timeout_delay_done(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCGinaAuthWindow* window = WINTC_GINA_AUTH_WINDOW(user_data);
|
||||
|
||||
switch (window->priv->current_state)
|
||||
{
|
||||
case WINTC_GINA_STATE_STARTING:
|
||||
g_timeout_add_seconds(
|
||||
DELAY_SECONDS_POLL,
|
||||
on_timeout_poll_ready,
|
||||
window
|
||||
);
|
||||
break;
|
||||
|
||||
case WINTC_GINA_STATE_LAUNCHING:
|
||||
wintc_gina_logon_session_finish(
|
||||
window->priv->logon_session
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical("%s", "Invalid state reached for delay.");
|
||||
break;
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean on_timeout_poll_ready(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCGinaAuthWindow* window = WINTC_GINA_AUTH_WINDOW(user_data);
|
||||
|
||||
if (
|
||||
wintc_gina_logon_session_is_available(
|
||||
window->priv->logon_session
|
||||
)
|
||||
)
|
||||
{
|
||||
wintc_gina_auth_window_change_state(
|
||||
window,
|
||||
WINTC_GINA_STATE_PROMPT
|
||||
);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
28
shared/msgina/src/authwnd.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __AUTHWND_H__
|
||||
#define __AUTHWND_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCGinaAuthWindowPrivate WinTCGinaAuthWindowPrivate;
|
||||
typedef struct _WinTCGinaAuthWindowClass WinTCGinaAuthWindowClass;
|
||||
typedef struct _WinTCGinaAuthWindow WinTCGinaAuthWindow;
|
||||
|
||||
#define TYPE_WINTC_GINA_AUTH_WINDOW (wintc_gina_auth_window_get_type())
|
||||
#define WINTC_GINA_AUTH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_GINA_AUTH_WINDOW, WinTCGinaAuthWindow))
|
||||
#define WINTC_GINA_AUTH_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_GINA_AUTH_WINDOW, WinTCGinaAuthWindow))
|
||||
#define IS_WINTC_GINA_AUTH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_GINA_AUTH_WINDOW))
|
||||
#define IS_WINTC_GINA_AUTH_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_GINA_AUTH_WINDOW))
|
||||
#define WINTC_GINA_WINDOW_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_GINA_AUTH_WINDOW))
|
||||
|
||||
GType wintc_gina_auth_window_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_gina_auth_window_new(void);
|
||||
|
||||
#endif
|
||||
10
shared/msgina/src/challenge.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __CHALLENGE_H__
|
||||
#define __CHALLENGE_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WINTC_GINA_RESPONSE_OKAY = 0,
|
||||
WINTC_GINA_RESPONSE_FAIL = 1
|
||||
} WinTCGinaResponse;
|
||||
|
||||
#endif
|
||||
281
shared/msgina/src/logon.c
Normal file
@@ -0,0 +1,281 @@
|
||||
#include <glib.h>
|
||||
#include <lightdm.h>
|
||||
#include <wintc-comgtk.h>
|
||||
|
||||
#include "challenge.h"
|
||||
#include "logon.h"
|
||||
|
||||
//
|
||||
// PRIVATE ENUMS
|
||||
//
|
||||
enum
|
||||
{
|
||||
SIGNAL_ATTEMPT_COMPLETE = 0,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
//
|
||||
// STATIC DATA
|
||||
//
|
||||
static gint wintc_gina_logon_session_signals[N_SIGNALS] = { 0 };
|
||||
|
||||
//
|
||||
// GLIB OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCGinaLogonSessionClass
|
||||
{
|
||||
GObjectClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCGinaLogonSession
|
||||
{
|
||||
GObject __parent__;
|
||||
|
||||
gboolean auth_complete;
|
||||
gboolean auth_ready;
|
||||
LightDMGreeter* greeter;
|
||||
gchar* response_pwd;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void on_greeter_authentication_complete(
|
||||
LightDMGreeter* greeter,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
static void on_greeter_show_prompt(
|
||||
LightDMGreeter* greeter,
|
||||
gchar* text,
|
||||
WINTC_UNUSED(LightDMPromptType type),
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GLIB TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE(
|
||||
WinTCGinaLogonSession,
|
||||
wintc_gina_logon_session,
|
||||
G_TYPE_OBJECT
|
||||
)
|
||||
|
||||
static void wintc_gina_logon_session_class_init(
|
||||
WinTCGinaLogonSessionClass* klass
|
||||
)
|
||||
{
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
wintc_gina_logon_session_signals[SIGNAL_ATTEMPT_COMPLETE] =
|
||||
g_signal_new(
|
||||
"attempt-complete",
|
||||
G_TYPE_FROM_CLASS(object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__INT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_INT
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_gina_logon_session_init(
|
||||
WinTCGinaLogonSession* self
|
||||
)
|
||||
{
|
||||
self->auth_ready = FALSE;
|
||||
self->greeter = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCGinaLogonSession* wintc_gina_logon_session_new()
|
||||
{
|
||||
return WINTC_GINA_LOGON_SESSION(
|
||||
g_object_new(
|
||||
TYPE_WINTC_GINA_LOGON_SESSION,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
gboolean wintc_gina_logon_session_establish(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("GINA - establish()");
|
||||
|
||||
if (!logon_session->greeter)
|
||||
{
|
||||
WINTC_LOG_DEBUG("GINA - new lightdm greeter");
|
||||
|
||||
logon_session->greeter = lightdm_greeter_new();
|
||||
|
||||
g_signal_connect(
|
||||
logon_session->greeter,
|
||||
"authentication-complete",
|
||||
G_CALLBACK(on_greeter_authentication_complete),
|
||||
logon_session
|
||||
);
|
||||
g_signal_connect(
|
||||
logon_session->greeter,
|
||||
"show-prompt",
|
||||
G_CALLBACK(on_greeter_show_prompt),
|
||||
logon_session
|
||||
);
|
||||
}
|
||||
|
||||
WINTC_LOG_DEBUG("GINA - lightdm connect sync");
|
||||
|
||||
if (
|
||||
!lightdm_greeter_connect_to_daemon_sync(
|
||||
logon_session->greeter,
|
||||
NULL
|
||||
)
|
||||
)
|
||||
{
|
||||
g_critical("%s", "Failed to connect to LightDM daemon.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FIXME: Error handling
|
||||
//
|
||||
lightdm_greeter_authenticate(
|
||||
logon_session->greeter,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wintc_gina_logon_session_finish(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("GINA - finish requested");
|
||||
|
||||
if (!logon_session->auth_complete)
|
||||
{
|
||||
g_warning("%s", "Attempt to complete incomplete logon.");
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Error handling required
|
||||
// FIXME: If this fails, we need to restart auth! The UI
|
||||
// does not handle this either
|
||||
//
|
||||
lightdm_greeter_start_session_sync(
|
||||
logon_session->greeter,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
gboolean wintc_gina_logon_session_is_available(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("GINA - polled");
|
||||
|
||||
return logon_session->auth_ready;
|
||||
}
|
||||
|
||||
void wintc_gina_logon_session_try_logon(
|
||||
WinTCGinaLogonSession* logon_session,
|
||||
const gchar* username,
|
||||
const gchar* password
|
||||
)
|
||||
{
|
||||
WINTC_LOG_DEBUG("GINA - logon attempt requested");
|
||||
|
||||
if (logon_session->auth_complete)
|
||||
{
|
||||
g_warning("%s", "Attempt to logon a second time.");
|
||||
return;
|
||||
}
|
||||
|
||||
logon_session->response_pwd = g_strdup(password);
|
||||
|
||||
// FIXME: Error handling
|
||||
//
|
||||
lightdm_greeter_respond(
|
||||
logon_session->greeter,
|
||||
username,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static void on_greeter_authentication_complete(
|
||||
LightDMGreeter* greeter,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCGinaLogonSession* logon_session =
|
||||
WINTC_GINA_LOGON_SESSION(user_data);
|
||||
|
||||
WINTC_LOG_DEBUG("GINA - lightdm auth complete");
|
||||
|
||||
logon_session->auth_complete =
|
||||
lightdm_greeter_get_is_authenticated(greeter);
|
||||
|
||||
g_signal_emit(
|
||||
logon_session,
|
||||
wintc_gina_logon_session_signals[SIGNAL_ATTEMPT_COMPLETE],
|
||||
0,
|
||||
logon_session->auth_complete ?
|
||||
WINTC_GINA_RESPONSE_OKAY :
|
||||
WINTC_GINA_RESPONSE_FAIL
|
||||
);
|
||||
|
||||
// If the auth failed, have to restart
|
||||
//
|
||||
if (!logon_session->auth_complete)
|
||||
{
|
||||
// FIXME: Error handling
|
||||
//
|
||||
lightdm_greeter_authenticate(greeter, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_greeter_show_prompt(
|
||||
LightDMGreeter* greeter,
|
||||
gchar* text,
|
||||
WINTC_UNUSED(LightDMPromptType type),
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
WinTCGinaLogonSession* logon_session =
|
||||
WINTC_GINA_LOGON_SESSION(user_data);
|
||||
|
||||
WINTC_LOG_DEBUG("GINA - lightdm prompt: %s", text);
|
||||
|
||||
if (g_strcmp0(text, "login:") == 0)
|
||||
{
|
||||
logon_session->auth_ready = TRUE;
|
||||
}
|
||||
else if (g_strcmp0(text, "Password: ") == 0)
|
||||
{
|
||||
// FIXME: Error handling
|
||||
//
|
||||
lightdm_greeter_respond(
|
||||
greeter,
|
||||
logon_session->response_pwd,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_free(logon_session->response_pwd);
|
||||
logon_session->response_pwd = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical("Unknown prompt: %s", text);
|
||||
}
|
||||
}
|
||||
41
shared/msgina/src/logon.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef __LOGON_H__
|
||||
#define __LOGON_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
//
|
||||
// GLIB BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCGinaLogonSessionClass WinTCGinaLogonSessionClass;
|
||||
typedef struct _WinTCGinaLogonSession WinTCGinaLogonSession;
|
||||
|
||||
#define TYPE_WINTC_GINA_LOGON_SESSION (wintc_gina_logon_session_get_type())
|
||||
#define WINTC_GINA_LOGON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_GINA_LOGON_SESSION, WinTCGinaLogonSession))
|
||||
#define WINTC_GINA_LOGON_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_GINA_LOGON_SESSION, WinTCGinaLogonSession))
|
||||
#define IS_WINTC_GINA_LOGON_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_GINA_LOGON_SESSION))
|
||||
#define IS_WINTC_GINA_LOGON_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_GINA_LOGON_SESSION))
|
||||
#define WINTC_GINA_LOGON_SESSION_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_GINA_LOGON_SESSION)
|
||||
|
||||
GType wintc_gina_logon_session_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
WinTCGinaLogonSession* wintc_gina_logon_session_new(void);
|
||||
|
||||
gboolean wintc_gina_logon_session_establish(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
void wintc_gina_logon_session_finish(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
gboolean wintc_gina_logon_session_is_available(
|
||||
WinTCGinaLogonSession* logon_session
|
||||
);
|
||||
void wintc_gina_logon_session_try_logon(
|
||||
WinTCGinaLogonSession* logon_session,
|
||||
const gchar* username,
|
||||
const gchar* password
|
||||
);
|
||||
|
||||
#endif
|
||||
20
shared/msgina/src/res/authwnd.css
Normal file
@@ -0,0 +1,20 @@
|
||||
box.please-wait
|
||||
{
|
||||
margin: 15px 0px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
grid
|
||||
{
|
||||
margin: 15px 0px;
|
||||
}
|
||||
|
||||
grid *
|
||||
{
|
||||
margin: 3px 10px 4px;
|
||||
}
|
||||
|
||||
grid entry
|
||||
{
|
||||
min-width: 240px;
|
||||
}
|
||||
6
shared/msgina/src/res/resources.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/uk/oddmatics/wintc/msgina">
|
||||
<file>authwnd.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
12
shared/msgina/src/state.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef __STATE_H__
|
||||
#define __STATE_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WINTC_GINA_STATE_NONE = 0,
|
||||
WINTC_GINA_STATE_STARTING,
|
||||
WINTC_GINA_STATE_PROMPT,
|
||||
WINTC_GINA_STATE_LAUNCHING
|
||||
} WinTCGinaState;
|
||||
|
||||
#endif
|
||||
316
shared/msgina/src/stripctl.c
Normal file
@@ -0,0 +1,316 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <wintc-comgtk.h>
|
||||
#include <wintc-winbrand.h>
|
||||
|
||||
#include "stripctl.h"
|
||||
|
||||
#define ONE_SECOND_IN_US 1000000
|
||||
|
||||
#define ANIM_RATE_SECONDS 2
|
||||
#define ANIM_RATE_IN_US (ANIM_RATE_SECONDS * ONE_SECOND_IN_US)
|
||||
|
||||
//
|
||||
// GTK OOP CLASS/INSTANCE DEFINITIONS
|
||||
//
|
||||
struct _WinTCGinaStripPrivate
|
||||
{
|
||||
GdkPixbuf* pixbuf_strip;
|
||||
cairo_surface_t* surface_strip;
|
||||
|
||||
gboolean is_animating;
|
||||
gint64 origin_time;
|
||||
};
|
||||
|
||||
struct _WinTCGinaStripClass
|
||||
{
|
||||
GtkWidgetClass __parent__;
|
||||
};
|
||||
|
||||
struct _WinTCGinaStrip
|
||||
{
|
||||
GtkWidget __parent__;
|
||||
|
||||
WinTCGinaStripPrivate* priv;
|
||||
};
|
||||
|
||||
//
|
||||
// FORWARD DECLARATIONS
|
||||
//
|
||||
static void wintc_gina_strip_finalize(
|
||||
GObject* gobject
|
||||
);
|
||||
|
||||
static gboolean wintc_gina_strip_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
);
|
||||
static void wintc_gina_strip_get_preferred_height(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
);
|
||||
static void wintc_gina_strip_get_preferred_height_for_width(
|
||||
GtkWidget* widget,
|
||||
gint width,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
);
|
||||
static void wintc_gina_strip_get_preferred_width(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
);
|
||||
static void wintc_gina_strip_get_preferred_width_for_height(
|
||||
GtkWidget* widget,
|
||||
gint height,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
);
|
||||
|
||||
static gboolean wintc_gina_strip_step(
|
||||
GtkWidget* widget,
|
||||
GdkFrameClock* frame_clock,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
//
|
||||
// GTK TYPE DEFINITIONS & CTORS
|
||||
//
|
||||
G_DEFINE_TYPE_WITH_CODE(
|
||||
WinTCGinaStrip,
|
||||
wintc_gina_strip,
|
||||
GTK_TYPE_WIDGET,
|
||||
G_ADD_PRIVATE(WinTCGinaStrip)
|
||||
)
|
||||
|
||||
static void wintc_gina_strip_class_init(
|
||||
WinTCGinaStripClass* klass
|
||||
)
|
||||
{
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(klass);
|
||||
|
||||
object_class->finalize = wintc_gina_strip_finalize;
|
||||
|
||||
widget_class->draw =
|
||||
wintc_gina_strip_draw;
|
||||
widget_class->get_preferred_height =
|
||||
wintc_gina_strip_get_preferred_height;
|
||||
widget_class->get_preferred_height_for_width =
|
||||
wintc_gina_strip_get_preferred_height_for_width;
|
||||
widget_class->get_preferred_width =
|
||||
wintc_gina_strip_get_preferred_width;
|
||||
widget_class->get_preferred_width_for_height =
|
||||
wintc_gina_strip_get_preferred_width_for_height;
|
||||
}
|
||||
|
||||
static void wintc_gina_strip_init(
|
||||
WinTCGinaStrip* self
|
||||
)
|
||||
{
|
||||
self->priv = wintc_gina_strip_get_instance_private(self);
|
||||
|
||||
gtk_widget_set_has_window(GTK_WIDGET(self), FALSE);
|
||||
|
||||
// Load assets
|
||||
//
|
||||
GError* error = NULL;
|
||||
|
||||
self->priv->pixbuf_strip =
|
||||
wintc_brand_get_brand_pixmap(
|
||||
WINTC_BRAND_PART_STRIP_ANIM,
|
||||
&error
|
||||
);
|
||||
|
||||
// FIXME: Handle error
|
||||
|
||||
self->priv->surface_strip =
|
||||
gdk_cairo_surface_create_from_pixbuf(
|
||||
self->priv->pixbuf_strip,
|
||||
1,
|
||||
NULL // FIXME: Error reporting
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// CLASS VIRTUAL METHODS
|
||||
//
|
||||
static void wintc_gina_strip_finalize(
|
||||
GObject* gobject
|
||||
)
|
||||
{
|
||||
WinTCGinaStrip* strip = WINTC_GINA_STRIP(gobject);
|
||||
|
||||
cairo_surface_destroy(strip->priv->surface_strip);
|
||||
g_clear_object(&(strip->priv->pixbuf_strip));
|
||||
|
||||
(G_OBJECT_CLASS(wintc_gina_strip_parent_class))->finalize(gobject);
|
||||
}
|
||||
|
||||
static gboolean wintc_gina_strip_draw(
|
||||
GtkWidget* widget,
|
||||
cairo_t* cr
|
||||
)
|
||||
{
|
||||
WinTCGinaStrip* strip = WINTC_GINA_STRIP(widget);
|
||||
gdouble x_offset = 0.0f;
|
||||
|
||||
// If animating, work out offset of strip based
|
||||
// on time
|
||||
//
|
||||
if (strip->priv->is_animating)
|
||||
{
|
||||
gint64 current_time = g_get_monotonic_time();
|
||||
gint64 delta = strip->priv->origin_time - current_time;
|
||||
gint64 mod_time = delta % ANIM_RATE_IN_US;
|
||||
gdouble within_pct = (gdouble) mod_time / ANIM_RATE_IN_US;
|
||||
|
||||
gint img_width =
|
||||
cairo_image_surface_get_width(
|
||||
strip->priv->surface_strip
|
||||
);
|
||||
|
||||
x_offset = (gint) (img_width * within_pct);
|
||||
}
|
||||
|
||||
// Paint now
|
||||
//
|
||||
cairo_set_source_surface(
|
||||
cr,
|
||||
strip->priv->surface_strip,
|
||||
x_offset,
|
||||
0.0f
|
||||
);
|
||||
cairo_pattern_set_extend(
|
||||
cairo_get_source(cr),
|
||||
CAIRO_EXTEND_REPEAT
|
||||
);
|
||||
|
||||
cairo_paint(cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void wintc_gina_strip_get_preferred_height(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
)
|
||||
{
|
||||
gint height;
|
||||
WinTCGinaStrip* strip = WINTC_GINA_STRIP(widget);
|
||||
|
||||
height =
|
||||
cairo_image_surface_get_height(
|
||||
strip->priv->surface_strip
|
||||
);
|
||||
|
||||
*minimum_height = height;
|
||||
*natural_height = height;
|
||||
}
|
||||
|
||||
static void wintc_gina_strip_get_preferred_height_for_width(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(gint width),
|
||||
gint* minimum_height,
|
||||
gint* natural_height
|
||||
)
|
||||
{
|
||||
wintc_gina_strip_get_preferred_height(
|
||||
widget,
|
||||
minimum_height,
|
||||
natural_height
|
||||
);
|
||||
}
|
||||
|
||||
static void wintc_gina_strip_get_preferred_width(
|
||||
GtkWidget* widget,
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
)
|
||||
{
|
||||
WinTCGinaStrip* strip = WINTC_GINA_STRIP(widget);
|
||||
gint width;
|
||||
|
||||
width =
|
||||
cairo_image_surface_get_width(
|
||||
strip->priv->surface_strip
|
||||
);
|
||||
|
||||
*minimum_width = width;
|
||||
*natural_width = width;
|
||||
}
|
||||
|
||||
static void wintc_gina_strip_get_preferred_width_for_height(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(gint height),
|
||||
gint* minimum_width,
|
||||
gint* natural_width
|
||||
)
|
||||
{
|
||||
wintc_gina_strip_get_preferred_width(
|
||||
widget,
|
||||
minimum_width,
|
||||
natural_width
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_gina_strip_new(void)
|
||||
{
|
||||
return GTK_WIDGET(
|
||||
g_object_new(
|
||||
TYPE_WINTC_GINA_STRIP,
|
||||
NULL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void wintc_gina_strip_animate(
|
||||
WinTCGinaStrip* strip
|
||||
)
|
||||
{
|
||||
if (strip->priv->is_animating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
strip->priv->is_animating = TRUE;
|
||||
strip->priv->origin_time = g_get_monotonic_time();
|
||||
|
||||
gtk_widget_add_tick_callback(
|
||||
GTK_WIDGET(strip),
|
||||
(GtkTickCallback) wintc_gina_strip_step,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
void wintc_gina_strip_stop_animating(
|
||||
WinTCGinaStrip* strip
|
||||
)
|
||||
{
|
||||
strip->priv->is_animating = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// CALLBACKS
|
||||
//
|
||||
static gboolean wintc_gina_strip_step(
|
||||
GtkWidget* widget,
|
||||
WINTC_UNUSED(GdkFrameClock* frame_clock),
|
||||
WINTC_UNUSED(gpointer user_data)
|
||||
)
|
||||
{
|
||||
WinTCGinaStrip* strip = WINTC_GINA_STRIP(widget);
|
||||
|
||||
gtk_widget_queue_draw(widget);
|
||||
|
||||
return strip->priv->is_animating ?
|
||||
G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
|
||||
}
|
||||
32
shared/msgina/src/stripctl.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef __STRIPCTL_H__
|
||||
#define __STRIPCTL_H__
|
||||
|
||||
//
|
||||
// GTK OOP BOILERPLATE
|
||||
//
|
||||
typedef struct _WinTCGinaStripPrivate WinTCGinaStripPrivate;
|
||||
typedef struct _WinTCGinaStripClass WinTCGinaStripClass;
|
||||
typedef struct _WinTCGinaStrip WinTCGinaStrip;
|
||||
|
||||
#define TYPE_WINTC_GINA_STRIP (wintc_gina_strip_get_type())
|
||||
#define WINTC_GINA_STRIP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_WINTC_GINA_STRIP, WinTCGinaStrip))
|
||||
#define WINTC_GINA_STRIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_WINTC_GINA_STRIP, WinTCGinaStrip))
|
||||
#define IS_WINTC_GINA_STRIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_WINTC_GINA_STRIP))
|
||||
#define IS_WINTC_GINA_STRIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_WINTC_GINA_STRIP))
|
||||
#define WINTC_GINA_STRIP_GET_CLASS(obj) (G_TYPE_CHECK_INSTANCE_GET_CLASS((obj), TYPE_WINTC_GINA_STRIP))
|
||||
|
||||
GType wintc_gina_strip_get_type(void) G_GNUC_CONST;
|
||||
|
||||
//
|
||||
// PUBLIC FUNCTIONS
|
||||
//
|
||||
GtkWidget* wintc_gina_strip_new(void);
|
||||
|
||||
void wintc_gina_strip_animate(
|
||||
WinTCGinaStrip* strip
|
||||
);
|
||||
void wintc_gina_strip_stop_animating(
|
||||
WinTCGinaStrip* strip
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -108,7 +108,8 @@ gboolean init_dll_wnck()
|
||||
p_wnck_window_get_mini_icon == NULL ||
|
||||
p_wnck_window_get_name == NULL ||
|
||||
p_wnck_window_is_skip_tasklist == NULL ||
|
||||
p_wnck_window_minimize == NULL
|
||||
p_wnck_window_minimize == NULL ||
|
||||
p_wnck_window_unminimize == NULL
|
||||
)
|
||||
{
|
||||
g_warning("%s", "libwnck loaded, but not all symbols.");
|
||||
|
||||
@@ -20,6 +20,8 @@ include(../../packaging/cmake-inc/libraries/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/linking/CMakeLists.txt)
|
||||
include(../../packaging/cmake-inc/packaging/CMakeLists.txt)
|
||||
|
||||
set(WINTC_BRAND_DIR ${WINTC_ASSETS_INSTALL_DIR}/brand)
|
||||
|
||||
wintc_resolve_library(gdk-pixbuf-2.0 GDK_PIXBUF)
|
||||
wintc_resolve_library(glib-2.0 GLIB)
|
||||
|
||||
@@ -65,64 +67,50 @@ target_link_libraries(
|
||||
|
||||
# Pick banner based on SKU
|
||||
#
|
||||
if (${WINTC_SKU} MATCHES "^xpclient-(.+)")
|
||||
if (${CMAKE_MATCH_1} STREQUAL "pro")
|
||||
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(WINBRAND_BANNER_NAME x64pro)
|
||||
elseif (
|
||||
${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ia64" OR
|
||||
${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv8"
|
||||
)
|
||||
set(WINBRAND_BANNER_NAME 64bit)
|
||||
else()
|
||||
set(WINBRAND_BANNER_NAME pro)
|
||||
endif()
|
||||
else()
|
||||
set(WINBRAND_BANNER_NAME ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
elseif (${WINTC_SKU} MATCHES "^dnsrv-(.+)")
|
||||
if (
|
||||
${CMAKE_MATCH_1} STREQUAL "sbs" OR
|
||||
${CMAKE_MATCH_1} STREQUAL "web" OR
|
||||
${CMAKE_MATCH_1} STREQUAL "ccs" OR
|
||||
NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64"
|
||||
)
|
||||
set(WINBRAND_BANNER_NAME srv2k3${CMAKE_MATCH_1})
|
||||
else()
|
||||
set(WINBRAND_BANNER_NAME x64srv2k3${CMAKE_MATCH_1})
|
||||
endif()
|
||||
elseif (${WINTC_SKU} MATCHES "^dnsrv_r2-(.+)")
|
||||
set(WINBRAND_BANNER_NAME ${WINTC_SKU})
|
||||
|
||||
if (${WINTC_SKU} STREQUAL "xpclient-pro")
|
||||
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(WINBRAND_BANNER_NAME x64srv2k3r2${CMAKE_MATCH_1})
|
||||
else()
|
||||
set(WINBRAND_BANNER_NAME srv2k3r2${CMAKE_MATCH_1})
|
||||
endif()
|
||||
elseif (${WINTC_SKU} STREQUAL "homesrv")
|
||||
set(WINBRAND_BANNER_NAME homesrv)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"No banner defined for SKU: ${WINTC_SKU}"
|
||||
set(WINBRAND_BANNER_NAME ${WINTC_SKU}_amd64)
|
||||
elseif (
|
||||
${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ia64" OR
|
||||
${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv8"
|
||||
)
|
||||
set(WINBRAND_BANNER_NAME ${WINTC_SKU}_ia64)
|
||||
endif()
|
||||
elseif (${WINTC_SKU} MATCHES "^dnsrv(_r2)?-(.+)")
|
||||
if (${CMAKE_MATCH_2} MATCHES "(dtc|ent|std)")
|
||||
set(WINBRAND_BANNER_NAME ${WINTC_SKU}_amd64)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# Installation
|
||||
#
|
||||
wintc_configure_and_install_packaging()
|
||||
wintc_add_pkgconfig_install()
|
||||
|
||||
install(
|
||||
FILES res/banner-${WINBRAND_BANNER_NAME}.png
|
||||
DESTINATION ${WINTC_ASSETS_INSTALL_DIR}/brand
|
||||
FILES res/banner/${WINBRAND_BANNER_NAME}.png
|
||||
DESTINATION ${WINTC_BRAND_DIR}
|
||||
RENAME banner.png
|
||||
)
|
||||
install(
|
||||
FILES res/strip-xp.png
|
||||
DESTINATION ${WINTC_ASSETS_INSTALL_DIR}/brand
|
||||
RENAME strip.png
|
||||
FILES res/bannerx/${WINBRAND_BANNER_NAME}.png
|
||||
DESTINATION ${WINTC_BRAND_DIR}
|
||||
RENAME bannerx.png
|
||||
)
|
||||
install(
|
||||
FILES res/strip-static.png
|
||||
DESTINATION ${WINTC_BRAND_DIR}
|
||||
)
|
||||
install(
|
||||
FILES res/strip-anim.png
|
||||
DESTINATION ${WINTC_BRAND_DIR}
|
||||
)
|
||||
install(
|
||||
TARGETS libwintc-winbrand
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
)
|
||||
@@ -7,12 +7,17 @@
|
||||
//
|
||||
// Branding banners
|
||||
//
|
||||
GdkPixbuf* wintc_brand_get_banner(
|
||||
GError** error
|
||||
);
|
||||
typedef enum
|
||||
{
|
||||
WINTC_BRAND_PART_BANNER = 0,
|
||||
WINTC_BRAND_PART_BANNER_TALL,
|
||||
WINTC_BRAND_PART_STRIP_STATIC = 10,
|
||||
WINTC_BRAND_PART_STRIP_ANIM
|
||||
} WinTCBrandPart;
|
||||
|
||||
GdkPixbuf* wintc_brand_get_progress_strip(
|
||||
GError** error
|
||||
GdkPixbuf* wintc_brand_get_brand_pixmap(
|
||||
WinTCBrandPart part,
|
||||
GError** error
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |