diff --git a/build/windows/LCUI/LCUI.vcxproj b/build/windows/LCUI/LCUI.vcxproj
index 358465148..6dc910253 100644
--- a/build/windows/LCUI/LCUI.vcxproj
+++ b/build/windows/LCUI/LCUI.vcxproj
@@ -324,6 +324,7 @@
+
@@ -423,6 +424,7 @@
+
diff --git a/build/windows/LCUI/LCUI.vcxproj.filters b/build/windows/LCUI/LCUI.vcxproj.filters
index b7446c0a5..872d6097e 100644
--- a/build/windows/LCUI/LCUI.vcxproj.filters
+++ b/build/windows/LCUI/LCUI.vcxproj.filters
@@ -123,6 +123,9 @@
头文件\LCUI
+
+ 头文件\LCUI
+
头文件\LCUI
@@ -440,6 +443,9 @@
源文件
+
+ 源文件
+
源文件
diff --git a/build/windows/LCUITest/LCUITest.vcxproj b/build/windows/LCUITest/LCUITest.vcxproj
index 700ccf22c..583b83851 100644
--- a/build/windows/LCUITest/LCUITest.vcxproj
+++ b/build/windows/LCUITest/LCUITest.vcxproj
@@ -193,6 +193,7 @@
+
diff --git a/build/windows/LCUITest/LCUITest.vcxproj.filters b/build/windows/LCUITest/LCUITest.vcxproj.filters
index 0d6a10fad..ace6f9966 100644
--- a/build/windows/LCUITest/LCUITest.vcxproj.filters
+++ b/build/windows/LCUITest/LCUITest.vcxproj.filters
@@ -21,6 +21,9 @@
源文件
+
+ 源文件
+
源文件
diff --git a/build/windows/LCUIUWP/LCUIUWP.vcxproj b/build/windows/LCUIUWP/LCUIUWP.vcxproj
index e5d638c88..45b90e081 100644
--- a/build/windows/LCUIUWP/LCUIUWP.vcxproj
+++ b/build/windows/LCUIUWP/LCUIUWP.vcxproj
@@ -69,6 +69,7 @@
+
@@ -162,6 +163,7 @@
+
diff --git a/build/windows/LCUIUWP/LCUIUWP.vcxproj.filters b/build/windows/LCUIUWP/LCUIUWP.vcxproj.filters
index 2414f4b9d..df840d1a7 100644
--- a/build/windows/LCUIUWP/LCUIUWP.vcxproj.filters
+++ b/build/windows/LCUIUWP/LCUIUWP.vcxproj.filters
@@ -111,6 +111,9 @@
头文件\LCUI
+
+ 头文件\LCUI
+
头文件\LCUI
@@ -377,6 +380,9 @@
源文件
+
+ 源文件
+
源文件
diff --git a/include/LCUI/Makefile.am b/include/LCUI/Makefile.am
index 6e736344e..96fab821f 100755
--- a/include/LCUI/Makefile.am
+++ b/include/LCUI/Makefile.am
@@ -4,7 +4,7 @@ SUBDIRS=font draw gui util
# Headers which are installed to support the library
INSTINCLUDES=LCUI.h types.h painter.h display.h graph.h draw.h \
font.h surface.h ime.h input.h thread.h util.h timer.h main.h cursor.h \
-image.h worker.h
+image.h settings.h worker.h
EXTRA_DIST=platform.h \
platform/linux/linux_display.h \
platform/linux/linux_events.h \
diff --git a/include/LCUI/display.h b/include/LCUI/display.h
index 865cd448b..539b231c1 100644
--- a/include/LCUI/display.h
+++ b/include/LCUI/display.h
@@ -116,9 +116,7 @@ LCUI_API size_t LCUIDisplay_Render(void);
/** 呈现渲染后的内容 */
LCUI_API void LCUIDisplay_Present(void);
-LCUI_API void LCUIDisplay_EnablePaintFlashing(LCUI_BOOL enable);
-
- /** 设置显示区域的尺寸,仅在窗口化、全屏模式下有效 */
+/** 设置显示区域的尺寸,仅在窗口化、全屏模式下有效 */
LCUI_API void LCUIDisplay_SetSize(int width, int height);
/** 获取屏幕宽度 */
diff --git a/include/LCUI/main.h b/include/LCUI/main.h
index 4217ca5d4..084db6f32 100644
--- a/include/LCUI/main.h
+++ b/include/LCUI/main.h
@@ -53,6 +53,7 @@ enum LCUI_SysEventType {
LCUI_PAINT,
LCUI_WIDGET,
LCUI_QUIT, /**< 在 LCUI 退出前触发的事件 */
+ LCUI_SETTINGS_CHANGE,
LCUI_USER = 100 /**< 用户事件,可以把这个当成系统事件与用户事件的分界 */
};
@@ -203,7 +204,7 @@ LCUI_API void LCUI_RunFrame(void);
LCUI_API void LCUI_RunFrameWithProfile(LCUI_FrameProfile profile);
- /* 新建一个主循环 */
+/* 新建一个主循环 */
LCUI_API LCUI_MainLoop LCUIMainLoop_New(void);
/* 运行目标循环 */
diff --git a/include/LCUI/settings.h b/include/LCUI/settings.h
new file mode 100644
index 000000000..bd7e820e8
--- /dev/null
+++ b/include/LCUI/settings.h
@@ -0,0 +1,55 @@
+/*
+ * settings.h -- Functions for accessing and modifying global settings.
+ *
+ * Copyright (c) 2020, James Duong All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of LCUI nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LCUI_SETTINGS_H
+#define LCUI_SETTINGS_H
+
+LCUI_BEGIN_HEADER
+
+typedef struct LCUI_SettingsRec_ {
+ int frame_rate_cap;
+ int parallel_rendering_threads;
+ LCUI_BOOL record_profile;
+ LCUI_BOOL fps_meter;
+ LCUI_BOOL paint_flashing;
+} LCUI_SettingsRec, *LCUI_Settings;
+
+/* Initialize settings with the current global settings. */
+LCUI_API void Settings_Init(LCUI_Settings settings);
+
+/* Update global settings with the given input. */
+LCUI_API void LCUI_ApplySettings(LCUI_Settings settings);
+
+/* Reset global settings to their defaults. */
+LCUI_API void LCUI_ResetSettings(void);
+
+LCUI_END_HEADER
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 78c458bec..4c148acd6 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS=foreign
AM_CFLAGS = -I$(abs_top_srcdir)/include $(CODE_COVERAGE_CFLAGS)
LCUI_LDFLAGS = -version-info 2:0:0
-LCUI_SOURCES = graph.c ime.c cursor.c worker.c main.c timer.c painter.c display.c keyboard.c
+LCUI_SOURCES = graph.c ime.c cursor.c worker.c main.c timer.c painter.c display.c keyboard.c settings.c
LCUI_LIBADD = thread/libthread.la util/libutil.la platform/libplatform.la \
image/libimage.la draw/libdraw.la gui/libgui.la font/libfont.la \
font/in-core/libfont_incore.la $(PACKAGE_LIBS)
diff --git a/src/display.c b/src/display.c
index d77a89588..fe67a68bb 100644
--- a/src/display.c
+++ b/src/display.c
@@ -44,6 +44,8 @@
#include
#include
#include
+#include
+#include
#ifdef LCUI_DISPLAY_H
#include LCUI_DISPLAY_H
#endif
@@ -53,16 +55,6 @@
#define DEFAULT_WIDTH 800
#define DEFAULT_HEIGHT 600
-#ifdef USE_OPENMP
-/**
- * Parallel rendering threads
- * We recommend that you set it to half the number of CPU logical cores
- */
-#define PARALLEL_RENDERING_THREADS 4
-#else
-#define PARALLEL_RENDERING_THREADS 1
-#endif
-
typedef struct FlashRectRec_ {
int64_t paint_time;
LCUI_Rect rect;
@@ -85,11 +77,12 @@ typedef struct SurfaceRecordRec_ {
static struct LCUI_DisplayModule {
unsigned width, height;
LCUI_BOOL active;
- LCUI_BOOL enable_paint_flashing;
LCUI_DisplayMode mode;
LinkedList surfaces;
LinkedList rects;
LCUI_DisplayDriver driver;
+ LCUI_SettingsRec settings;
+ int settings_change_handler_id;
} display;
/* clang-format on */
@@ -113,8 +106,13 @@ static void OnDestroySurfaceRecord(void *data)
free(record);
}
+static void OnSettingsChangeEvent(LCUI_SysEvent e, void *arg)
+{
+ Settings_Init(&display.settings);
+}
+
static size_t LCUIDisplay_RenderFlashRect(SurfaceRecord record,
- FlashRect flash_rect)
+ FlashRect flash_rect)
{
size_t count;
int64_t period;
@@ -202,7 +200,8 @@ static void GetRenderingLayerSize(int *width, int *height)
*width = (int)(LCUIDisplay_GetWidth() * scale);
*height = (int)(LCUIDisplay_GetHeight() * scale);
- *height = max(200, *height / PARALLEL_RENDERING_THREADS + 1);
+ *height =
+ max(200, *height / display.settings.parallel_rendering_threads + 1);
}
static void SurfaceRecord_DumpRects(SurfaceRecord record, LinkedList *rects)
@@ -221,12 +220,14 @@ static void SurfaceRecord_DumpRects(SurfaceRecord record, LinkedList *rects)
LCUI_Rect rect;
LCUI_Rect *sub_rect;
DirtyLayer layer;
- DirtyLayerRec layers[PARALLEL_RENDERING_THREADS];
+ DirtyLayerRec *layers;
LinkedListNode *node;
GetRenderingLayerSize(&layer_width, &layer_height);
max_dirty = (int)(0.8 * layer_width * layer_height);
- for (i = 0; i < PARALLEL_RENDERING_THREADS; ++i) {
+ layers = malloc(sizeof(DirtyLayerRec) *
+ display.settings.parallel_rendering_threads);
+ for (i = 0; i < display.settings.parallel_rendering_threads; ++i) {
layer = &layers[i];
layer->diry = 0;
layer->rect.y = i * layer_height;
@@ -238,7 +239,8 @@ static void SurfaceRecord_DumpRects(SurfaceRecord record, LinkedList *rects)
sub_rect = malloc(sizeof(LCUI_Rect));
for (LinkedList_Each(node, &record->rects)) {
rect = *(LCUI_Rect *)node->data;
- for (i = 0; i < PARALLEL_RENDERING_THREADS; ++i) {
+ for (i = 0; i < display.settings.parallel_rendering_threads;
+ ++i) {
layer = &layers[i];
if (layer->diry >= max_dirty) {
continue;
@@ -257,7 +259,7 @@ static void SurfaceRecord_DumpRects(SurfaceRecord record, LinkedList *rects)
}
}
}
- for (i = 0; i < PARALLEL_RENDERING_THREADS; ++i) {
+ for (i = 0; i < display.settings.parallel_rendering_threads; ++i) {
layer = &layers[i];
if (layer->diry >= max_dirty) {
RectList_AddEx(rects, &layer->rect, FALSE);
@@ -268,6 +270,7 @@ static void SurfaceRecord_DumpRects(SurfaceRecord record, LinkedList *rects)
}
RectList_Clear(&record->rects);
free(sub_rect);
+ free(layers);
}
static size_t LCUIDisplay_RenderSurfaceRect(SurfaceRecord record,
@@ -288,7 +291,7 @@ static size_t LCUIDisplay_RenderSurfaceRect(SurfaceRecord record,
omp_get_num_threads(), paint->rect.x, paint->rect.y,
paint->rect.width, paint->rect.height);
count = Widget_Render(record->widget, paint);
- if (display.enable_paint_flashing) {
+ if (display.settings.paint_flashing) {
LCUIDisplay_AppendFlashRects(record, &paint->rect);
}
if (display.mode != LCUI_DMODE_SEAMLESS) {
@@ -622,11 +625,6 @@ int LCUIDisplay_GetMode(void)
return display.mode;
}
-void LCUIDisplay_EnablePaintFlashing(LCUI_BOOL enable)
-{
- display.enable_paint_flashing = enable;
-}
-
/** 设置显示区域的尺寸,仅在窗口化、全屏模式下有效 */
void LCUIDisplay_SetSize(int width, int height)
{
@@ -948,6 +946,10 @@ int LCUI_InitDisplay(LCUI_DisplayDriver driver)
display.active = TRUE;
display.width = DEFAULT_WIDTH;
display.height = DEFAULT_HEIGHT;
+ Settings_Init(&display.settings);
+ display.settings_change_handler_id = LCUI_BindEvent(
+ LCUI_SETTINGS_CHANGE, OnSettingsChangeEvent, NULL, NULL);
+
LinkedList_Init(&display.rects);
LinkedList_Init(&display.surfaces);
if (!display.driver) {
@@ -984,5 +986,7 @@ int LCUI_FreeDisplay(void)
if (display.driver) {
LCUI_DestroyDisplayDriver(display.driver);
}
+ LCUI_UnbindEvent(display.settings_change_handler_id);
+ display.settings_change_handler_id = -1;
return 0;
}
diff --git a/src/main.c b/src/main.c
index 5b4771d02..d93120450 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -42,6 +43,7 @@
#include
#include
#include
+#include
#ifdef LCUI_EVENTS_H
#include LCUI_EVENTS_H
#endif
@@ -107,12 +109,13 @@ static struct LCUI_App {
LCUI_Worker main_worker; /**< 主工作线程 */
LCUI_Worker workers[LCUI_WORKER_NUM]; /**< 普通工作线程 */
int worker_next; /**< 下一个工作线程编号 */
+ LCUI_SettingsRec settings;
+ LCUI_ProfileRec profile;
+ LCUI_FrameProfile frame;
+ int settings_change_handler_id;
} MainApp;
/* clang-format on */
-
-#ifdef DEBUG
-
static void LCUIProfile_Init(LCUI_Profile profile)
{
memset(profile, 0, sizeof(LCUI_ProfileRec));
@@ -153,24 +156,25 @@ static void LCUIProfile_Print(LCUI_Profile profile)
}
}
-static LCUI_FrameProfile LCUIProfile_BeginFrame(LCUI_Profile profile)
+static LCUI_FrameProfile LCUIProfile_BeginFrame(LCUI_Profile profile,
+ LCUI_Settings settings)
{
LCUI_FrameProfile frame;
frame = &profile->frames[profile->frames_count];
- if (profile->frames_count > LCUI_MAX_FRAMES_PER_SEC) {
+ if (profile->frames_count > settings->frame_rate_cap) {
profile->frames_count = 0;
}
memset(frame, 0, sizeof(LCUI_FrameProfileRec));
return frame;
}
-static void LCUIProfile_EndFrame(LCUI_Profile profile)
+static void LCUIProfile_EndFrame(LCUI_Profile profile, LCUI_Settings settings)
{
profile->frames_count += 1;
profile->end_time = clock();
if (profile->end_time - profile->start_time >= CLOCKS_PER_SEC) {
- if (profile->frames_count < LCUI_MAX_FRAMES_PER_SEC / 4) {
+ if (profile->frames_count < settings->frame_rate_cap / 4) {
LCUIProfile_Print(profile);
}
profile->frames_count = 0;
@@ -178,7 +182,11 @@ static void LCUIProfile_EndFrame(LCUI_Profile profile)
}
}
-#endif
+static void OnSettingsChangeEvent(LCUI_SysEvent e, void *arg)
+{
+ Settings_Init(&MainApp.settings);
+ StepTimer_SetFrameLimit(MainApp.timer, MainApp.settings.frame_rate_cap);
+}
void LCUI_RunFrameWithProfile(LCUI_FrameProfile profile)
{
@@ -279,6 +287,9 @@ int LCUI_UnbindEvent(int handler_id)
int LCUI_TriggerEvent(LCUI_SysEvent e, void *arg)
{
+ if (System.state != STATE_ACTIVE) {
+ return -1;
+ }
int ret;
SysEventPackRec pack;
pack.arg = arg;
@@ -385,10 +396,6 @@ LCUI_MainLoop LCUIMainLoop_New(void)
/** 运行目标主循环 */
int LCUIMainLoop_Run(LCUI_MainLoop loop)
{
-#ifdef DEBUG
- LCUI_ProfileRec profile;
- LCUI_FrameProfile frame;
-#endif
LCUI_BOOL at_same_thread = FALSE;
if (loop->state == STATE_RUNNING) {
DEBUG_MSG("error: main-loop already running.\n");
@@ -409,17 +416,17 @@ int LCUIMainLoop_Run(LCUI_MainLoop loop)
}
DEBUG_MSG("loop: %p, enter\n", loop);
MainApp.loop = loop;
-#ifdef DEBUG
- LCUIProfile_Init(&profile);
-#endif
while (loop->state != STATE_EXITED) {
-#ifdef DEBUG
- frame = LCUIProfile_BeginFrame(&profile);
- LCUI_RunFrameWithProfile(frame);
- LCUIProfile_EndFrame(&profile);
-#else
- LCUI_RunFrame();
-#endif
+ if (MainApp.settings.record_profile) {
+ MainApp.frame = LCUIProfile_BeginFrame(
+ &MainApp.profile, &MainApp.settings);
+ LCUI_RunFrameWithProfile(MainApp.frame);
+ LCUIProfile_EndFrame(&MainApp.profile,
+ &MainApp.settings);
+ } else {
+ LCUI_RunFrame();
+ }
+
StepTimer_Remain(MainApp.timer);
/* 如果当前运行的主循环不是自己 */
while (MainApp.loop != loop) {
@@ -466,12 +473,17 @@ void LCUI_InitApp(LCUI_AppDriver app)
LCUICond_Init(&MainApp.loop_changed);
LCUIMutex_Init(&MainApp.loop_mutex);
LinkedList_Init(&MainApp.loops);
+ LCUIProfile_Init(&MainApp.profile);
+ LCUI_ResetSettings();
+ MainApp.settings_change_handler_id = LCUI_BindEvent(
+ LCUI_SETTINGS_CHANGE, OnSettingsChangeEvent, NULL, NULL);
+ Settings_Init(&MainApp.settings);
MainApp.main_worker = LCUIWorker_New();
for (i = 0; i < LCUI_WORKER_NUM; ++i) {
MainApp.workers[i] = LCUIWorker_New();
LCUIWorker_RunAsync(MainApp.workers[i]);
}
- StepTimer_SetFrameLimit(MainApp.timer, LCUI_MAX_FRAMES_PER_SEC);
+ StepTimer_SetFrameLimit(MainApp.timer, MainApp.settings.frame_rate_cap);
if (!app) {
app = LCUI_CreateAppDriver();
if (!app) {
@@ -502,6 +514,8 @@ static void LCUI_FreeApp(void)
LCUI_MainLoop loop;
LinkedListNode *node;
MainApp.active = FALSE;
+ LCUI_UnbindEvent(MainApp.settings_change_handler_id);
+ MainApp.settings_change_handler_id = -1;
for (LinkedList_Each(node, &MainApp.loops)) {
loop = node->data;
LCUIMainLoop_Quit(loop);
diff --git a/src/settings.c b/src/settings.c
new file mode 100644
index 000000000..860bb3914
--- /dev/null
+++ b/src/settings.c
@@ -0,0 +1,69 @@
+/* settings.c -- global settings.
+ *
+ * Copyright (c) 2020, James Duong All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of LCUI nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include
+#include
+#include
+#include
+#include
+
+static LCUI_SettingsRec self;
+
+static void TriggerSettingsChangedEvent(void)
+{
+ LCUI_SysEventRec event = { 0 };
+ event.type = LCUI_SETTINGS_CHANGE;
+ LCUI_TriggerEvent(&event, &self);
+}
+
+/* Initialize settings with the current global settings. */
+void Settings_Init(LCUI_Settings settings)
+{
+ *settings = self;
+}
+
+/* Update global settings with the given input. */
+void LCUI_ApplySettings(LCUI_Settings settings)
+{
+ self = *settings;
+ self.frame_rate_cap = max(self.frame_rate_cap, 1);
+ self.parallel_rendering_threads =
+ max(self.parallel_rendering_threads, 1);
+ TriggerSettingsChangedEvent();
+}
+
+/* Reset global settings to their defaults. */
+void LCUI_ResetSettings(void)
+{
+ self.frame_rate_cap = 120;
+ self.parallel_rendering_threads = 4;
+ self.record_profile = FALSE;
+ self.fps_meter = FALSE;
+ self.paint_flashing = FALSE;
+ TriggerSettingsChangedEvent();
+}
diff --git a/test/Makefile.am b/test/Makefile.am
index 79c100c9c..7e85effdd 100755
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -31,7 +31,8 @@ test_widget_rect.c \
test_widget_opacity.c \
test_widget_event.c \
test_textview_resize.c \
-test_textedit.c
+test_textedit.c \
+test_settings.c
test_LDADD = $(top_builddir)/src/libLCUI.la -lm $(CODE_COVERAGE_LIBS)
diff --git a/test/test.c b/test/test.c
index c1645bf47..fdc474025 100644
--- a/test/test.c
+++ b/test/test.c
@@ -15,6 +15,7 @@ int main(void)
describe("test linkedlist", test_linkedlist);
describe("test string", test_string);
describe("test strpool", test_strpool);
+ describe("test settings", test_settings);
describe("test object", test_object);
describe("test thread", test_thread);
describe("test font load", test_font_load);
diff --git a/test/test.h b/test/test.h
index f7c1e6d7b..8bee6c516 100644
--- a/test/test.h
+++ b/test/test.h
@@ -5,6 +5,7 @@ extern int tests_count;
void test_charset(void);
void test_string(void);
void test_object(void);
+void test_settings(void);
void test_thread(void);
void test_font_load(void);
void test_xml_parser(void);
diff --git a/test/test_settings.c b/test/test_settings.c
new file mode 100644
index 000000000..74ef31d18
--- /dev/null
+++ b/test/test_settings.c
@@ -0,0 +1,124 @@
+#include
+#include
+#include
+#include
+#include
+#include "test.h"
+#include "libtest.h"
+
+static int settings_change_count = 0;
+
+static void on_settings_change(LCUI_SysEvent object, void *data)
+{
+ ++settings_change_count;
+}
+
+static void check_settings_frame_rate_cap(void *arg)
+{
+ char str[256];
+ int fps_limit = *((int *)arg);
+ int fps = LCUI_GetFrameCount();
+
+ sprintf(str, "should work when frame cap is %d (actual %d)", fps_limit,
+ fps);
+ it_b(str, fps <= fps_limit && fps > fps_limit - 2, TRUE);
+ LCUI_Quit();
+}
+
+static void test_default_settings(void)
+{
+ LCUI_SettingsRec settings;
+
+ LCUI_Init();
+ LCUI_ResetSettings();
+ Settings_Init(&settings);
+
+ it_i("check default frame rate cap", settings.frame_rate_cap, 120);
+ it_i("check default parallel rendering threads",
+ settings.parallel_rendering_threads, 4);
+ it_b("check default record profile", settings.record_profile, FALSE);
+ it_b("check default fps meter", settings.fps_meter, FALSE);
+ it_b("check default paint flashing", settings.paint_flashing, FALSE);
+ LCUI_Destroy();
+}
+
+static void test_apply_settings(void)
+{
+ LCUI_SettingsRec settings;
+
+ LCUI_Init();
+ int handler = LCUI_BindEvent(LCUI_SETTINGS_CHANGE, on_settings_change, NULL, NULL);
+
+ settings.frame_rate_cap = 60;
+ settings.parallel_rendering_threads = 2;
+ settings.record_profile = TRUE;
+ settings.fps_meter = TRUE;
+ settings.paint_flashing = TRUE;
+
+ LCUI_ApplySettings(&settings);
+ Settings_Init(&settings);
+ it_i("check frame rate cap", settings.frame_rate_cap, 60);
+ it_i("check parallel rendering threads",
+ settings.parallel_rendering_threads, 2);
+ it_b("check record profile", settings.record_profile, TRUE);
+ it_b("check fps meter", settings.fps_meter, TRUE);
+ it_b("check paint flashing", settings.paint_flashing, TRUE);
+
+ it_i("check settings change count", settings_change_count, 1);
+
+ settings.frame_rate_cap = -1;
+ settings.parallel_rendering_threads = -1;
+
+ LCUI_ApplySettings(&settings);
+ Settings_Init(&settings);
+ it_i("check frame rate cap minimum", settings.frame_rate_cap, 1);
+ it_i("check parallel rendering threads minimum",
+ settings.parallel_rendering_threads, 1);
+ it_i("check settings change count", settings_change_count, 2);
+
+ LCUI_ResetSettings();
+ it_i("check settings change count", settings_change_count, 3);
+ LCUI_UnbindEvent(handler);
+ LCUI_Destroy();
+}
+
+void test_settings_frame_rate_cap(void)
+{
+ LCUI_SettingsRec settings;
+ LCUI_Init();
+ Settings_Init(&settings);
+
+ settings.frame_rate_cap = 30;
+ LCUI_ApplySettings(&settings);
+ LCUI_SetTimeout(1000, check_settings_frame_rate_cap,
+ &settings.frame_rate_cap);
+ LCUI_Main();
+
+ LCUI_Init();
+ settings.frame_rate_cap = 5;
+ LCUI_ApplySettings(&settings);
+ LCUI_SetTimeout(1000, check_settings_frame_rate_cap,
+ &settings.frame_rate_cap);
+ LCUI_Main();
+
+ LCUI_Init();
+ settings.frame_rate_cap = 90;
+ LCUI_ApplySettings(&settings);
+ LCUI_SetTimeout(1000, check_settings_frame_rate_cap,
+ &settings.frame_rate_cap);
+ LCUI_Main();
+
+ LCUI_Init();
+ settings.frame_rate_cap = 25;
+ LCUI_ApplySettings(&settings);
+ LCUI_SetTimeout(1000, check_settings_frame_rate_cap,
+ &settings.frame_rate_cap);
+ LCUI_Main();
+}
+
+void test_settings(void)
+{
+ describe("test default settings", test_default_settings);
+ describe("test apply settings", test_apply_settings);
+ describe("test settings.frame_rate_cap", test_settings_frame_rate_cap);
+}