diff --git a/c++/palanteer.h b/c++/palanteer.h
index 174389f..a14d67b 100644
--- a/c++/palanteer.h
+++ b/c++/palanteer.h
@@ -1297,8 +1297,8 @@ class plCliIo {
#if USE_PL==1 || PL_EXPORT==1
// Library version
-#define PALANTEER_VERSION "0.3"
-#define PALANTEER_VERSION_NUM 300 // Monotonic number. 100 per version component. Official release are multiples of 100
+#define PALANTEER_VERSION "0.4.dev1"
+#define PALANTEER_VERSION_NUM 301 // Monotonic number. 100 per version component. Official releases are multiple of 100
// Client-Server protocol version
#define PALANTEER_CLIENT_PROTOCOL_VERSION 1
diff --git a/c++/test/test_instru_configuration.py b/c++/test/test_instru_configuration.py
index c6d2487..3539490 100644
--- a/c++/test/test_instru_configuration.py
+++ b/c++/test/test_instru_configuration.py
@@ -64,7 +64,7 @@ def test_usepl1_nocontrol():
"""Config PL_NOCONTROL=1"""
build_target("testprogram", "USE_PL=1 PL_NOCONTROL=1")
- data_configure_events(CRASH_SPEC+[spec_add_fruit])
+ data_configure_events(CRASH_SPEC + [spec_add_fruit])
try:
launch_testprogram()
CHECK(True, "Connection established")
@@ -88,7 +88,7 @@ def test_usepl1_noevent():
"""Config PL_NOEVENT=1"""
build_target("testprogram", "USE_PL=1 PL_NOEVENT=1")
- data_configure_events(CRASH_SPEC+[spec_add_fruit])
+ data_configure_events(CRASH_SPEC + [spec_add_fruit])
try:
launch_testprogram()
CHECK(True, "Connection established")
@@ -111,7 +111,7 @@ def test_usepl1_noassert():
"""Config PL_NOASSERT=1"""
build_target("testprogram", "USE_PL=1 PL_NOASSERT=1")
- data_configure_events(CRASH_SPEC+[spec_add_fruit])
+ data_configure_events(CRASH_SPEC + [spec_add_fruit])
try:
launch_testprogram(
pass_first_freeze_point=True
diff --git a/docs/more.md.html b/docs/more.md.html
index d618791..4cecc34 100644
--- a/docs/more.md.html
+++ b/docs/more.md.html
@@ -379,10 +379,14 @@
- **Use asserts**
- They greatly speed up the bug investigation by crashing "nicely" close to the inconsistency.
- Their impact on performance is usually low because data is already in the cache/registers so a test is ~1 CPU cycle.
- - Also, if `Palanteer` is used, groups of asserts can be enabled on demand at compile-time, which can greatly speed-up investigations
+ - Also, if `Palanteer` is used, groups of asserts can be enabled on demand at compile-time
- Keep the condition as a simple check, never perform actions inside an assertion as it may be disabled at compile time.
- Never assert on external inputs, as they are not under control.
+- **For time related constant/variable, always include the unit in the name (exemple: `timeout_msec`)**
+ - Such bugs due to confusion on units are so frequent and so easy to avoid...
+ - Mistake on time units are the more representative, but this hint is applicable to all units as soon as there may be some ambiguity
+
- **Use address sanitizers (ASAN)** whenever possible
- It is built-in in `gcc` and `clang`, enabled with a few compilation/linking flags
- The reported issues (uninitialized memory read, leaks...) would be very hard to track without such class of tool.
diff --git a/server/base/bsOs.h b/server/base/bsOs.h
index 39d101c..a3e1c38 100644
--- a/server/base/bsOs.h
+++ b/server/base/bsOs.h
@@ -71,7 +71,7 @@ void osCreateWindow(const char* windowTitle, const char* configName,
bool overrideWindowManager=false);
void osDestroyWindow(void);
void osSetWindowTitle(const bsString& title);
-void osGetWindowSize(int& width, int& height);
+void osGetWindowSize(int& width, int& height, int& dpiWidth, int& dpiHeight);
void osProcessInputs(bsOsHandler* osHandler);
void osHideWindow(void);
void osShowWindow(void);
diff --git a/server/base/bsOsLinux.cpp b/server/base/bsOsLinux.cpp
index ca64c2a..3190d33 100644
--- a/server/base/bsOsLinux.cpp
+++ b/server/base/bsOsLinux.cpp
@@ -67,8 +67,10 @@ static struct {
Cursor noCursor = None;
Cursor defaultCursor = None;
Cursor currentCursor = None;
- int wWidth = -1;
- int wHeight = -1;
+ int wWidth = -1;
+ int wHeight = -1;
+ int dpiWidth = -1;
+ int dpiHeight = -1;
// Character inputs
XIM xInputMethod = 0; // Input method linked to the X display
XIC xInputContext = 0; // Input context used to gete unicode input in our window
@@ -167,13 +169,22 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft,
attr.override_redirect = gGlob.isDirectOverride;
attr.event_mask = StructureNotifyMask | EnterWindowMask | LeaveWindowMask | ExposureMask | ButtonPressMask | PointerMotionMask |
ButtonReleaseMask | OwnerGrabButtonMask | FocusChangeMask | KeyPressMask | KeyReleaseMask;
- int attr_mask = CWBackPixmap | CWColormap | CWBorderPixel| CWEventMask | CWOverrideRedirect ;
- int dWidth = DisplayWidth (gGlob.xDisplay, DefaultScreen(gGlob.xDisplay));
- int dHeight = DisplayHeight(gGlob.xDisplay, DefaultScreen(gGlob.xDisplay));
+ int attr_mask = CWBackPixmap | CWColormap | CWBorderPixel| CWEventMask | CWOverrideRedirect;
+ int defaultScreenId = DefaultScreen(gGlob.xDisplay);
+ int dWidth = DisplayWidth (gGlob.xDisplay, defaultScreenId); // In pixel
+ int dHeight = DisplayHeight (gGlob.xDisplay, defaultScreenId);
+
+ // Compute DPI
+#define COMPUTE_DPI(pix, mm) (int)(9.6*((int)(((double)pix)/((double)mm)*(254./96.)+0.5))) /* Quantize the DPI each 5%, to clean approximated values */
+ int dWidthMm = DisplayWidthMM (gGlob.xDisplay, defaultScreenId); // In millimeter
+ int dHeightMm = DisplayHeightMM(gGlob.xDisplay, defaultScreenId);
+ gGlob.dpiWidth = COMPUTE_DPI(dWidth, dWidthMm);
+ gGlob.dpiHeight = COMPUTE_DPI(dHeight, dHeightMm);
+
int x = (int)(ratioLeft *(float)dWidth);
int y = (int)(ratioTop *(float)dHeight);
- gGlob.wWidth = (int)((ratioRight-ratioLeft)*(float)dWidth);
- gGlob.wHeight = (int)((ratioBottom-ratioTop)*(float)dHeight);
+ gGlob.wWidth = (int)((ratioRight-ratioLeft)*(float)dWidth);
+ gGlob.wHeight = (int)((ratioBottom-ratioTop)*(float)dHeight);
gGlob.windowHandle = XCreateWindow(gGlob.xDisplay, Xroot, x, y, gGlob.wWidth, gGlob.wHeight,
0, visual->depth, InputOutput, visual->visual, attr_mask, &attr);
gGlob.glXWindowHandle = gGlob.windowHandle;
@@ -209,7 +220,7 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft,
gGlob.xInputMethod = XOpenIM(gGlob.xDisplay, NULL, NULL, NULL);
if(gGlob.xInputMethod) {
gGlob.xInputContext = XCreateIC(gGlob.xInputMethod, XNClientWindow, gGlob.glXWindowHandle, XNFocusWindow, gGlob.glXWindowHandle,
- XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL);
+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL);
}
// Create the OpenGL 3.0 context
@@ -272,10 +283,12 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft,
// ===============
void
-osGetWindowSize(int& width, int& height)
+osGetWindowSize(int& width, int& height, int& dpiWidth, int& dpiHeight)
{
- width = gGlob.wWidth;
- height = gGlob.wHeight;
+ width = gGlob.wWidth;
+ height = gGlob.wHeight;
+ dpiWidth = gGlob.dpiWidth;
+ dpiHeight = gGlob.dpiHeight;
}
diff --git a/server/base/bsOsWindows.cpp b/server/base/bsOsWindows.cpp
index 6e29686..08c7829 100644
--- a/server/base/bsOsWindows.cpp
+++ b/server/base/bsOsWindows.cpp
@@ -67,6 +67,8 @@
static struct {
int windowWidth = -1;
int windowHeight = -1;
+ int dpiWidth = 96;
+ int dpiHeight = 96;
HINSTANCE hInstance = 0;
int nCmdShow = -1;
LPTSTR windowClass; // Window Class
@@ -101,6 +103,16 @@ showMessage(LPCWSTR message)
// Forward declaration
static LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+// DPI awareness and getters from Dear Imgui, file backends/imgui_impl_win32.cpp
+#ifndef DPI_ENUMS_DECLARED
+typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
+#endif
+#ifndef _DPI_AWARENESS_CONTEXTS_
+DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3
+#endif
+typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
+
void
osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft, float ratioTop, float ratioRight, float ratioBottom, bool overrideWindowManager)
@@ -112,6 +124,9 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft,
plAssert(ratioLeftgetConfig().getFontSize();
+ ImGui::GetStyle().ScaleAllSizes(_dpiScale);
// @#TODO: set window size & pos from config. And show the window only after that
@@ -465,16 +469,15 @@ vwPlatform::installFont(const void* fontData, int fontDataSize, int fontSize)
bool
vwPlatform::redraw(void)
{
- // Filter out some redraw based on the dirtyness of the state.
- // Due to imgui which requires several frames to handle user events properly, we batch the display.
- // Also we do a "bounce" after a delay, which is needed for some tooltip to appear, even if no user event occurs.
+ // Filter out some redraw based on the dirtiness of the display state.
+ // Dear Imgui requires several frames to handle user events properly, so we display per batch.
+ // Also a "bounce" is required after a delay for some tooltip to appear, even if no user event occurs.
bsUs_t currentTimeUs = bsGetClockUs();
- u64 tmp = _dirtyRedrawCount.load();
+ u64 tmp = _dirtyRedrawCount.load();
int dirtyRedrawCount = (int)(tmp&0xFFFFFFFF);
int bounceCount = (int)((tmp>>32)&0xFFFFFFFF);
- if(dirtyRedrawCount<=0 && // Not a dirty display or...
- !(bounceCount==1 && currentTimeUs-_lastRenderingTimeUs>=BOUNCE_RENDER_GAP_US)) { // not (we need a bounce and waited enough)
- return false; // Nothing to display
+ if(dirtyRedrawCount<=0 && !(bounceCount==1 && currentTimeUs-_lastRenderingTimeUs>=BOUNCE_RENDER_GAP_US)) {
+ return false; // Display is not dirty and it is not a bounce time: nothing to display
}
#define WRITE_DIRTY_COUNT(drc,bc) _dirtyRedrawCount.store((((u64)bc)<<32) | ((u32)(drc&0xFFFFFFFF)))
if(dirtyRedrawCount>=0) {
@@ -492,7 +495,8 @@ vwPlatform::redraw(void)
// Change font, if needed
if(_newFontSizeToInstall>0) {
- installFont(vwGetFontDataRobotoMedium(), vwGetFontDataSizeRobotoMedium(), _newFontSizeToInstall);
+ installFont(vwGetFontDataRobotoMedium(), vwGetFontDataSizeRobotoMedium(),
+ bsRound(_dpiScale*_newFontSizeToInstall));
_newFontSizeToInstall = -1;
}
diff --git a/server/viewer/vwPlatform.h b/server/viewer/vwPlatform.h
index 9ae3ea6..d3a7b60 100644
--- a/server/viewer/vwPlatform.h
+++ b/server/viewer/vwPlatform.h
@@ -87,6 +87,7 @@ class vwPlatform : public bsOsHandler {
// ImGui & OpenGL
int _displayWidth = -1;
int _displayHeight = -1;
+ float _dpiScale = 1.;
bsUs_t _lastUpdateDurationUs = 1; // Update only
bsUs_t _lastRenderingDurationUs = 1; // Update and OpenGL rendering
bsUs_t _lastRenderingTimeUs = 0;
diff --git a/tools/testframework.py b/tools/testframework.py
index 8a90392..9b6aec6 100755
--- a/tools/testframework.py
+++ b/tools/testframework.py
@@ -222,7 +222,10 @@ class _TestFailedError(Exception):
# Public CRASH_SPEC
-CRASH_SPEC = [palanteer_scripting.EvtSpec("CRASH Stacktrace"), palanteer_scripting.EvtSpec(parent="CRASH Stacktrace", events=["*"])]
+CRASH_SPEC = [
+ palanteer_scripting.EvtSpec("CRASH Stacktrace"),
+ palanteer_scripting.EvtSpec(parent="CRASH Stacktrace", events=["*"]),
+]
# Used server port (better if different from the viewer's one)
SERVER_PORT = 59060