| [ Return to Bugs & Features | SVN ⇄ GIT ]
STR #3320
Application: | FLTK Library |
Status: | 1 - Closed w/Resolution |
Priority: | 1 - Request for Enhancement, e.g. asking for a feature |
Scope: | 2 - Specific to an operating system |
Subsystem: | X11 |
Summary: | support for high resolution displays on the X11 platform (application scaling) |
Version: | 1.4-feature |
Created By: | manolo |
Assigned To: | manolo |
Fix Version: | 1.4.0 (SVN: v12823) |
Fix Commit: | 798823f7dc578c2ddef3c97b723d771381fed479 |
Update Notification: | |
Trouble Report Files:
|
#1 | manolo 08:08 Jul 23, 2016 |
| pango+scale.patch 101k | |
|
#2 | manolo 04:40 Jul 26, 2016 |
| pango+scaleV2.patch 107k | |
|
#3 | manolo 00:07 Oct 16, 2016 |
| pango+scaleV4.patch 97k | |
|
#4 | manolo 09:00 Dec 21, 2016 |
| scaling.patch 63k | |
|
#5 | manolo 10:06 Dec 22, 2016 |
| scaling2.patch 66k | |
|
#6 | manolo 09:23 Jan 25, 2017 |
| scaling3.patch 73k | |
|
#7 | manolo 01:47 Jan 26, 2017 |
| scaling4.patch 73k | |
|
#8 | manolo 02:04 Feb 05, 2017 |
| scaling5.patch 91k | |
|
#9 | manolo 11:50 Feb 14, 2017 |
| scaling6.patch 102k | |
|
#10 | chris 08:23 Feb 15, 2017 |
| test_scale_issue1.cxx 1k | |
|
#11 | chris 09:50 Feb 16, 2017 |
| test_scale_issue2.cxx 1k | |
|
#12 | manolo 00:37 Feb 17, 2017 |
| scaling7.patch 104k | |
|
#13 | AlbrechtS 07:33 Feb 18, 2017 |
| scaling7_artifacts_2.5.png 147k | |
|
#14 | manolo 01:05 Feb 19, 2017 |
| scaling8.patch 107k | |
|
#15 | manolo 01:06 Feb 19, 2017 |
| gleam240.png 0.3M | |
|
#16 | AlbrechtS 02:39 Feb 19, 2017 |
| oxy.patch 46k | |
|
#17 | manolo 09:45 Feb 19, 2017 |
| scaling9.patch 103k | |
|
#18 | AlbrechtS 14:11 Feb 19, 2017 |
| GraphicsExpose.patch 1k | |
|
#19 | manolo 06:32 Feb 21, 2017 |
| scaling10.patch 106k | |
|
#20 | AlbrechtS 05:55 Feb 22, 2017 |
| window-truncation.png 53k | |
|
#21 | AlbrechtS 06:09 Feb 22, 2017 |
| displaced_menu_Ubuntu-VM.png 108k | |
|
#22 | AlbrechtS 06:10 Feb 22, 2017 |
| displaced_menu_Cygwin_X.png 60k | |
|
#23 | AlbrechtS 06:17 Feb 22, 2017 |
| large_scaling_display.png 66k | |
|
#24 | manolo 05:36 Feb 27, 2017 |
| scaling11.patch 108k | |
|
#25 | manolo 13:57 Mar 21, 2017 |
| screenscale.patch 145k | |
|
#26 | manolo 23:40 Mar 21, 2017 |
| screenscale2.patch 145k | |
|
#27 | manolo 13:40 Mar 28, 2017 |
| screenscale3.patch 148k | |
|
#28 | manolo 02:13 Mar 31, 2017 |
| screenscale4.patch 152k | |
|
#29 | manolo 10:53 Apr 09, 2017 |
| screenscale5.patch 152k | |
|
#30 | manolo 08:00 Apr 21, 2017 |
| screenscale6.patch 152k | |
|
#31 | chris 23:59 Apr 21, 2017 |
| regression_screenscale6_help_dialog.png 28k | |
|
#32 | manolo 09:59 Apr 24, 2017 |
| screenscale7.patch 155k | |
|
#33 | manolo 10:04 Apr 30, 2017 |
| screenscale8.patch 158k | |
|
#34 | manolo 09:15 May 12, 2017 |
| screenscale+mac+win.patch 198k | |
|
#35 | AlbrechtS 07:13 May 16, 2017 |
| image_scaling_borders.png 43k | |
|
#36 | AlbrechtS 08:35 May 16, 2017 |
| editor_artifacts.png 167k | |
|
#37 | AlbrechtS 16:42 May 16, 2017 |
| offscreen_border_artifacts.png 0.7M | |
|
#38 | manolo 22:40 Jun 08, 2017 |
| scaling_rect.patch 15k | |
|
#39 | manolo 23:49 Jun 09, 2017 |
| menu_at_top.png 132k | |
|
#40 | AlbrechtS 02:04 Jul 22, 2017 |
| scaling_rect_r12346.patch 14k | |
|
#41 | chris 11:55 Jul 28, 2017 |
| read_image_downscaling_bug.cxx 1k | |
|
#42 | manolo 08:45 Nov 05, 2017 |
| scaling_rect_r12544.patch 15k | |
|
#43 | AlbrechtS 12:12 Nov 05, 2017 |
| scaling_rect_r12545.patch 14k | |
Trouble Report Comments:
|
#1 | manolo 08:08 Jul 23, 2016 |
| The attached pango+scale.patch gives to the fltk1.3-porting branch support for high resolution displays for the X11 platform. This is implemented through a new graphics driver class Fl_Scaled_Xlib_Graphics_Driver derived from Fl_Xlib_Graphics_Driver.
An app run using the patched FLTK library will rescale all its graphics (images included) by the ratio between the system's dpi and 192 dpi (this ratio should equal 2 on a high resolution display). The same app run on a "standard" display or a high resolution one will produce graphics of the same sizes, without any source code change.
The patch also allows to use an environment variable called FL_SCALING_FACTOR to control the scale factor for an app before running it (for example set it to 2 and all graphics become twice larger). This is probably a temporary feature to allow testing without a high resolution display at hand.
The patch also incorporates support for the pango library. | |
|
#2 | manolo 14:19 Jul 25, 2016 |
| With the following improved version of function Fl_X11_Screen_Driver::open_display() from file src/Fl_x.cxx the support of HiDPI displays under Ubuntu should be correct:
the new code reads once at run-time the value of the "Scale for menu and title bars" parameter of System Settings/Displays and use that value as scale for all FLTK drawings.
======================================
// define types needed for dynamic lib functions typedef void GSettings, GVariant, GVariantIter; typedef GSettings* (*g_settings_new_ftype)(const char *); typedef GVariant* (*g_settings_get_value_ftype)(GSettings *settings, const char *key); typedef void (*g_variant_get_ftype)(GVariant *value, const char *format_string, ...); typedef bool (*g_variant_iter_loop_ftype)(GVariantIter *iter, const char *format_string, ...); typedef void (*g_variant_iter_free_ftype)(GVariantIter*); typedef void (*g_object_unref_ftype)(GSettings*); typedef void (*g_variant_unref_ftype)(GVariant *value);
static bool ubuntu_scale_factor(float& factor) { // determine whether we run Ubuntu char line[200] = ""; FILE *in = popen("/bin/uname -v", "r"); fgets(line, sizeof(line), in); pclose(in); if (!strstr(line, "Ubuntu")) return false; // open dynamic libs void *glib = dlopen("libglib-2.0.so", RTLD_LAZY); void *gio = dlopen("libgio-2.0.so", RTLD_LAZY); void *gobj = dlopen("libgobject-2.0.so", RTLD_LAZY); if (!glib || !gio || !gobj) return false; // define pters to used functions g_settings_new_ftype g_settings_new_f = (g_settings_new_ftype)dlsym(gio, "g_settings_new"); g_settings_get_value_ftype g_settings_get_value_f = (g_settings_get_value_ftype)dlsym(gio, "g_settings_get_value"); g_variant_get_ftype g_variant_get_f = (g_variant_get_ftype)dlsym(glib, "g_variant_get"); g_variant_iter_loop_ftype g_variant_iter_loop_f = (g_variant_iter_loop_ftype)dlsym(glib, "g_variant_iter_loop"); g_variant_iter_free_ftype g_variant_iter_free_f = (g_variant_iter_free_ftype)dlsym(glib, "g_variant_iter_free"); g_object_unref_ftype g_object_unref_f = (g_object_unref_ftype)dlsym(gobj, "g_object_unref"); g_variant_unref_ftype g_variant_unref_f = (g_variant_unref_ftype)dlsym(glib, "g_variant_unref"); // call dynamic lib functions GSettings *gset = g_settings_new_f("com.ubuntu.user-interface"); GVariant *gvar = g_settings_get_value_f(gset, "scale-factor"); GVariantIter *iter; char *str; int v; g_variant_get_f(gvar, "a{si}", &iter); if (g_variant_iter_loop_f(iter, "{si}", &str, &v)) { factor = v/8.; printf("name=%s value=%d factor=%g\n", str, v, factor); } g_variant_iter_free_f(iter); g_variant_unref_f(gvar); g_object_unref_f(gset); return true; }
void Fl_X11_Screen_Driver::open_display() { if (fl_display) return;
setlocale(LC_CTYPE, ""); XSetLocaleModifiers("@im=");
XSetIOErrorHandler(io_error_handler); XSetErrorHandler(xerror_handler);
Display *d = XOpenDisplay(0); if (!d) Fl::fatal("Can't open display: %s",XDisplayName(0));
fl_open_display(d); // the unique GC used by all X windows GC gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0); Fl_Display_Device::display_device()->driver()->gc(gc); float factor=1; const char *env = getenv("FL_SCALING_FACTOR"); if (env) { sscanf(env, "%f", &factor); } else if (ubuntu_scale_factor(factor)) { ; } else { float hdpi, vdpi; Fl::screen_dpi(hdpi, vdpi); factor = hdpi/96; factor = int(10*factor + 0.5)/10.f; } if (factor != 1) { Fl_Scaled_Xlib_Graphics_Driver *dr = (Fl_Scaled_Xlib_Graphics_Driver*)Fl_Display_Device::display_device()->driver(); dr->pixel_scale(factor); } }
========================================== | |
|
#3 | manolo 05:10 Jul 26, 2016 |
| With attached pango+scaleV2.patch, there is, I believe, a decent HiDPI support under Debian and Ubuntu with gnome.
The gnome scaling value is read once during fl_open_display() and used to scale all FLTK drawing operations. It corresponds to the value of gsettings get org.gnome.desktop.interface scaling-factor on Debian, and of gsettings get com.ubuntu.user-interface scale-factor divided by 8 on Ubuntu.
On other X11 systems, the dpi reported by Fl::screen_dpi() is divided by 96 and the result is used to scale FLTK drawings.
Otherwise, env variable FL_SCALING_FACTOR can be set by the user to a floating number to scale any FLTK apps.
The configure build accepts --enable-pango as an option. The CMake build also can use pango as an option.
Tests on Linux + HiDPI display welcome (has been tested here only through VirtualBox on Apple retina display). | |
|
#4 | manolo 09:08 Dec 21, 2016 |
| Attached file #4 scaling.patch has these features for HiDPI on X11: - relative to FLTK-1.4 with (optional) pango support - no longer uses the FL_SCALING_FACTOR environment variable - reads the gnome scaling factor under Debian, Ubuntu, FreeBSD and applies it to any FLTK app when it starts - added two global shortcuts CTRL-'+' enlarges all drawings and windows by 25% CTRL-'-' shrinks all drawings and windows by 25% (except on German keyboards, the '+' requires SHIFT) | |
|
#5 | manolo 11:56 Dec 21, 2016 |
| Attached file #4 scaling.patch should be slightly modified to be used without pango:
in file src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H, move Region scale_clip(float f); void unscale_clip(Region r2); outside of the #if USE_PANGO/#endif section. | |
|
#6 | manolo 10:07 Dec 22, 2016 |
| Use scaling2.patch that contains several improvements relatively to scaling.patch. | |
|
#7 | manolo 01:48 Jan 26, 2017 |
| Use scaling4.patch that improves the window position after ctrl-+ | |
|
#8 | manolo 02:08 Feb 05, 2017 |
| Use attached scaling5.patch with new class Fl_Scalable_Graphics_Driver. This platform-independent class does all coordinate-scaling tasks and then calls a platform-specific, derived class to do the drawing.
In the future, this class could be reused as is on the WIN32 platform to better support HiDPI than what is currently implemented. | |
|
#9 | chris 02:00 Feb 13, 2017 |
| A related observation with this (otherwise excellent patch, version 5) is, that it is seems notably slower than the unpatched FLTK-1.4 at least in extreme cases. I didn't double check though, but compiling/running a rather graphic intensive (lots of line drawing, image blitting,..) application with this patch (unscaled i.e. with scale 1.) with identic compiler flags shows a considerable slowdown. Can it be achieved somehow, that the unscaled case is unaffected in this respect?
(I have no HDPI display, and am running this patch under Ubuntu 14.04). | |
|
#10 | chris 07:30 Feb 14, 2017 |
| Ok, some figures:
I ran this drawing test program ("drawing_speed.cxx") with and w/o the patch:
#include <FL/fl_draw.H> #include <FL/Fl_Image_Surface.H> #include <cstdio> #include <cassert>
int main( int argc_, char *argv_[] ) { fl_register_images(); Fl_Image_Surface surf( 800, 600 ); surf.set_current(); Fl_Shared_Image *img = Fl_Shared_Image::get("test/pixmaps/porsche.xpm"); assert(img); for ( int i = 0; i < 1000000; i++ ) { fl_color( FL_RED ); fl_line( 0, 0, 800, 600 ); img->draw( 100, 100 ); } }
Without patch:
time ./drawing_speed real 0m14.304s user 0m1.549s sys 0m2.188s
With patch:
time ./drawing_speed com.ubuntu.user-interface scale-factor name=eDP1 value=8 factor=1
(process:11672): GLib-CRITICAL **: g_variant_unref: assertion 'value != NULL' failed
real 0m36.629s user 0m6.393s sys 0m5.613s
So a huge difference!
The *image drawing* is the part, that looses time. One idea: Can it be, that the image does not get cached (or that it gets uncached all the time)? | |
|
#11 | manolo 12:02 Feb 14, 2017 |
| @Chris: it's good you have given a test program. I have seen with it that all time difference results from a single feature of the patched code: use of Fl_Screen_Driver::offscreen_size(Fl_Offscreen, int&, int&) to obtain the width and height of an Fl_Offscreen which is the data cached when drawing images. Under X11, this function makes a roundtrip between the client and the X server. This slows down the test program at each loop iteration.
I have modified the patch to remove this roundtrip and instead to memorize in a new member variable of the image classes the scaling value used when each image is cached.
In my hands (under Mac OS + XQuartz) the patched and unpatched test programs run at the same speeds.
Could you, please, try the attached scaling6.patch on your test program and also on your fullsize program, and report if the speed difference has been reduced? | |
|
#12 | chris 23:53 Feb 14, 2017 |
| Yes, there is no more speed penalty with patch #6.
I am having some other issues with my application, *but only when scaling is on*. I guess it makes some assumptions that are not always valid. I'll try to pin these down to reproducable examples, but this may take some time.. | |
|
#13 | chris 08:22 Feb 15, 2017 |
| Hi Manolo, I have 2 easy to fix issues to start with. If these can be implemented I might see more clearly on other issues that are probably there:
1) I attach a small test program "test_scale_issue1.cxx". The description is included in the comments.
2) You should use rounding for the scaled coordinates/positions. This cleary improves missing dots or lines in non-integer scalings.
As a test I replaced some of the calls in Fl_Graphics_Driver.cxx with rounding versions and saw drawing errors go away in my application.
e.g.:
void Fl_Scalable_Graphics_Driver::rectf(int x, int y, int w, int h) { rectf_unscaled(lround(x * scale_), lround(y * scale_), lround(w * scale_), lround(h * scale_)); } | |
|
#14 | chris 09:02 Feb 15, 2017 |
| Just noticed I posted the file "test_scale_issue1.cxx" in the "wrong" version with Fl_Double_Window commented out. Please change it to use double window. | |
|
#15 | manolo 14:21 Feb 15, 2017 |
| About test_scale_issue1.cxx : With a non-integer scaling value, say 1.5, and considering that both FLTK and X11 use exclusively integer coordinates, there is no way to fill the space with adjacent lines of equal width. My conclusion is that either the application decides to use only integral scaling values, or it paints the space with the adequate color before painting lines. Initializing the space with 0 would give color black. This is not a universally valid solution. For example, white background may be desirable in other situations.
About rounding coordinates to integer values in the patched code: The present code is accurate for scaling values 2 and 3. I don't know at this point if a solution is possible to obtain pixel-accurate drawing for non-integral scaling values. My present feeling is that rounding coordinates would not be enough. The HighDPI displays I know use 2 as scaling value. | |
|
#16 | chris 23:14 Feb 15, 2017 |
| I am testing the patch not from the viewpoint of HDPI displays, but from its added feature of scaling applications in runtime and looking at the effect this has on *already existing* applications. Is this feature only temporary for testing HDPI code or will it remain in the final patch? | |
|
#17 | manolo 01:00 Feb 16, 2017 |
| @Chris: it is extremely helpful that you test accurately the attached patches so we can decide whether to commit this code. Thank you very much for that.
About your question "Is this feature only temporary for testing HDPI code or will it remain in the final patch?" I take this feature to be: non-integer scaling factor. I believe to be in an exploratory phase at this point to determine whether this feature is feasible or not. Your tests are therefore very useful.
HiDPI support achieved under the gnome desktop with Tweak tools ==> Windows ==> Window scaling proposes only 1 or 2 as scaling factor values.
But, with this other route available under Ubuntu System Settings ==> Displays ==> Scale for menu and title bars fractional scaling factor values are possible (e.g., 1.25).
Also, MSWindows allows fractional scaling factor values.
That is why I wanted to explore fractional scaling factor values.
At this point, I believe scaling factor values of 2 or 3 are essentially pixel-accurate with the patch: - line drawings reproduce with squared pixel blocks of size 2 or 3, respectively, single-pixel states obtained at scale 1; - fonts take advantage of the extra resolution - shared images can do also if Fl_Shared_Image::scale() is used. I know fractional scaling factor values create some drawing inaccuracies. I don't know if it's possible to repair that in general, given that both X11 and the FLTK API use only integer coordinates. Your detailed tests and suggestions are useful. | |
|
#18 | AlbrechtS 01:39 Feb 16, 2017 |
| Manolo, thanks for doing all that, and thanks for testing @Chris.
I think that we really need non-integer scaling factors. I'm currently using 175% under Windows and in my Ubuntu VM, but I use the Virtualbox VM's scaling feature in the latter and not the scaling of the underlying Ubuntu. With my hardware resolution 3200x1800 this appears to be a good compromise between usability and scaled, effective resolution (~1828x1028).
WRT ctrl/+ and ctrl/- dynamic runtime scaling I suggest to take a look at Firefox (51.0.1) that displays its scaling factor in the address line. I see the following steps (in %): 30, 50, 67, 80, 90, 100, 110, 120, 133, 150, 170, 200, 240, 300. Chrome has: 25, 33, 50, 67, 75, 80, 90, 100, 110, 125, 150, 175, 200, 250, 300, 400, 500.
Just my 2ct. Sorry, still no time for intensive testing. | |
|
#19 | chris 09:51 Feb 16, 2017 |
| Can you have a look at test_scale_issue2.cxx? Run the program and change the scale during it is running.. | |
|
#20 | manolo 00:40 Feb 17, 2017 |
| Attached scaling7.patch should fix test_scale_issue2.cxx
It also contains an attempt to fix test_scale_issue1.cxx and box drawing in general with fractional scaling factors. This fix still needs testing. | |
|
#21 | chris 11:38 Feb 17, 2017 |
| I can confirm that issue2 is solved in patch #7. Issue 1 works in 1.5 (i think it was only fixed for that scale, right?)
My application now works without flaws in all scales.
There are still issues in redrawing e.g. after moving parts of a window offscreen, best seen with all demos that use Fl_Window (not Fl_Double_Window) e.g. hello, table, subwindow,.. and after some popups or menu buttons.
mandelbrot crashes when scale is set to 0.5. | |
|
#22 | manolo 00:50 Feb 18, 2017 |
| @Chris: I am very glad to read: "My application now works without flaws in all scales."
I can't reproduce these issues. I use Ubuntu through VirtualBox, are they hidden from me? There are still issues in redrawing e.g. after moving parts of a window offscreen, best seen with all demos that use Fl_Window (not Fl_Double_Window) e.g. hello, table, subwindow,.. and after some popups or menu buttons.
This will be fixed with the next uploaded patch: "mandelbrot crashes when scale is set to 0.5." | |
|
#23 | chris 01:35 Feb 18, 2017 |
| @Chris: I am very glad to read: "My application now works without flaws in all scales."
Me to. And it is really astonishing how fast this live scaling works. Nearly now impact on the performance. Great!
I can't reproduce these issues. I use Ubuntu through VirtualBox, are they hidden from me?
I am on Ubuntu 14.04 with "Gnome Session Flashback" and Metacity i.e. an non-compositing WM.
And it can't be a graphics driver issue, I think, because unscaled mode is ok.
I have the same configuration in a VM too, but can't test this now. I'll do this next week if you still can't reproduce. | |
|
#24 | AlbrechtS 07:33 Feb 18, 2017 |
| Test environment: Ubuntu 16.04 in Virtualbox VM on Windows 10, using Cygwin X server on the Windows desktop. The X server runs in the native resolution (3200x1800), so this is a good test environment. The Ubuntu desktop is scaled by Virtualbox (175%), the full desktop resolution is 1824x965 (according to test/fullscreen). Gnome scaling factor is (8 and) 1.0
Test results of scaling7.patch: There are drawing artifacts with non-integral scaling factors and more. See attached file scaling7_artifacts_2.5.png with scaling factor 2.5. Details shown in the image:
(1) Line artifacts in boxes with color gradients. The shown image is with scheme 'oxy' (test) but can be seen with scheme 'gleam' as well. This was to be kinda expected when color gradients are drawn with one line per logical pixel and 1 pixel line width. How are line widths and pixel distances calculated in this case?
(2) Drawing artifacts in the clock displays. The screenshot was taken after ~40 seconds of display time.
(3) Tooltips are leaving an "empty" background when they are removed, see gray rectangle in the upper right part of the image covering partly the top row of "thin box"es. I can see this with all scaling factors (not only non-integral ones) except 1.0. This seems to depend on the WM: it is visible with the Cygwin X server, but not on the desktop (similar to Chris' observations, although I'm also using (non-compositing) WM Metacity. My guess: coordinates of expose events need to be "translated". This would also explain Chris' observation of artifacts when parts of the window are outside the screen and moved back.
Other effects (not visible in the posted image):
(4) Under Cygwin/X server on Windows desktop (not on Ubuntu desktop): when a window gets taller than the desktop height it's truncated - so far, so good. But after reducing the scaling factor the window size is scaled down proportional to the truncated size. The truncated part is lost. This happens obviously with windows that are NOT resizable, for instance test/demo.
(5) I could also see artifacts when scaling a window down after parts of it were truncated (outside the desktop). See also (3) and Chris' comments (issue 1?).
(6) After typing ctrl/+ or ctrl/- I have a tiny cursor in my Cygwin/X server environment, no matter whether I'm scaling up or down and what the scaling factor is. The size is "fixed" again whenever the cursor moves over a widget that changes the cursor (for instance any input widget). This is likely not FLTK's fault though. When the cursor is "tiny" it seems to be the default X cursor in the X server's standard size according to the native resolution. When the cursor changes back to "normal" size this appears to be the normal Windows cursor size (which is scaled by 175%).
(7) Visible in test/cursor: whenever the scaling factor is changed the cursor changes to the default cursor. Example: change cursor to FL_CURSOR_CROSS (works), type ctrl/+: cursor changes back to default. This happens in both the Ubuntu desktop and the Cygwin/X server environment.
(8) GL demo programs glpuzzle and fractals don't scale with ctrl/+ and ctrl/- (gl_overlay does).
I didn't test "everything" yet, but that should be enough for today. Sorry for the long list and many, many thanks! | |
|
#25 | AlbrechtS 08:13 Feb 18, 2017 |
| Technical notes to scaling7.patch:
(1) src/fl_boxtype.cxx: These changes should IMO not be in this patch. I understand the intention, but this would only hide symptoms (not the underlying cause). Generally we should not change any box or other high-level drawing methods (unless they are flawed anyway) because users may have similar methods in their code. If we "fix" high-level box drawing code we won't see issues users may see with their drawing functions that work(ed) w/o the scaling patch. This would imply that all changes for this feature should be in X11 specific code unless we must change some higher level driver code (classes) to support new features. And, of course, we should not try to change the gleam (and oxy) box drawing methods. They are a valuable test environment to see if pixel-exact drawing works with scaling.
(2) src/fl_draw.cxx: is this an unrelated patch that should go into branch-1.4 anyway? If yes, I suggest to commit this to svn and remove it from the patch.
(3) test/offscreen.cxx: see (2).
(4) documentation/src/osissues.dox: see (2). | |
|
#26 | manolo 01:14 Feb 19, 2017 |
| Scaling8.patch should significantly improve gradient drawing with fractional scaling values (see gleam240.png).
There's also a new way to display scaling values.
@Albrecht: I don't understand your test setup. Are virtualbox and Cygwin-X both active? How can the Oxy scheme be selected? | |
|
#27 | AlbrechtS 02:39 Feb 19, 2017 |
| Hi Manolo, thanks for the new patch. I'll try it later today (likely in the evening hours).
> Scaling8.patch should significantly improve gradient > drawing with fractional scaling values (see gleam240.png).
Looks much better! However there are still some artifacts, but obviously you know that.
> There's also a new way to display scaling values.
How?
> I don't understand your test setup. Are virtualbox and Cygwin-X both active?
Yes, they are. Cygwin-X runs on the host (Win10) and I didn't find a way to scale it, hence it uses the native display resolution. I don't know why, but it just happens to be this way. The VM is connected by the Virtualbox network (setup: NAT) so I can start a terminal session from the Windows host to the VM that uses the Cygwin-X display. I can't go into details now (lack of time), but if you have questions I can give details.
> How can the Oxy scheme be selected?
STR #2675 has a patch, but I don't recommend using the patch directly. I have a better one in my local git repository with my new Fl_Scheme(_*) class(es), but that's still work in progress. The attached oxy.patch should apply cleanly to branch-1.4. I don't think there are significant conflicts with your patch. | |
|
#28 | manolo 09:53 Feb 19, 2017 |
| Attached scaling9.patch should fix the color gradient artefacts with the gleam scheme, and also refrains from patching file src/fl_boxtype.cxx.
I can't reproduce "Tooltips are leaving an "empty" background when they are removed". I'm not in a position to fix that, then.
Cursors are drawn by X11, so the scaling factor values don't change them. | |
|
#29 | manolo 10:09 Feb 19, 2017 |
| Could you try to do that around line 1889 of src/Fl_x.cxx that may repair the empty-background-after-tooltip bug ?
Replace this :
case GraphicsExpose: window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); return 1;
by this :
case GraphicsExpose: {float s = Fl_Graphics_Driver::default_driver().scale(); window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x/s, xevent.xexpose.y/s, xevent.xexpose.width/s, xevent.xexpose.height/s);} return 1; | |
|
#30 | AlbrechtS 14:11 Feb 19, 2017 |
| Attached file GraphicsExpose.patch fixes the tooltip issue and all other expose events, for instance if a part of the window was occluded by another window or dragged out of the screen and dragged back in. Please apply on top of scaling9.patch (with patch -p1), or integrate into the next version, please.
This patch is as you proposed, but adds 1 to the width and height - otherwise I could see one pixel wide lines that were left (not redrawn). That additional pixel is necessary due to rounding effects and it doesn't harm if we draw an unnecessary pixel line in case there's no rounding issue. I'm not completely sure though if rounding of the x and y coordinate (downwards) might have the effect that we need 2 (or even more?) additional pixels in the width and height values. Hard to think about that...
BTW: this patch also fixes the blank area that was left after the transitional scaling factor display window disappears if that happened to appear over the window. Yes, I found it, so my question 'How?' is answered. ;-)
That said, the other part of the patch is a great step forward. Awesome, thanks!
I can still see some strange effects, but I need more time to test and report.
Did you manage to install and use the oxy scheme patch?
PS: Just in case ... please keep these patches separate. My work on the Fl_Scheme class changes lots of code of the oxy scheme and all other schemes.
PPS: Thanks for removing and committing the unrelated patches and the changes in fl_boxtype.cxx. | |
|
#31 | manolo 06:43 Feb 21, 2017 |
| With reference to comment #24 above:
Attached scaling10.patch should fix issues 1, 2, 3, and 7
Issues 4 and 5 may also be fixed, but I can't reproduce them, so I'm not sure.
Issue 6 may also be fixed with the fix for #7, but not sure.
Issue 8 is because glut consumes all text input, so ctrl-+ is not seen as a shortcut by FLTK.
There are still a few drawing artefacts, but not many.
@Albrecht: it would also be interesting to test within VirtualBox (without Cygwin-X) with the gnome desktop scaled by a factor 2. All FLTK apps should start correctly scaled without the need to press ctrl-+ | |
|
#32 | chris 07:56 Feb 21, 2017 |
| The scale value "Scale for menu and title bars" parameter of System Settings/Displays is probably not the correct one, at least not with Gnome session flashback active. Changing it has no effect at all on the desktop, perhaps it is used only in Unity.
According to http://askubuntu.com/questions/668749/how-to-set-up-gnome-interface-for-hidpi-screen the value for Gnome is in "org.gnome.desktop.interface scaling-factor".
I tested this by adding code to the gnome_scale_factor() function in Fl_x.cxx, and it works:
schema = "org.gnome.desktop.interface"; if (is_schema_valid(schema, known)) { void *gset = g_settings_new_f(schema); void *gvar = g_settings_get_value_f(gset, "scaling-factor"); void *iter; char str[10], *str2; int v, v2; g_variant_get_f(gvar, "u", &v); gnome_f = v;
printf("org.gnome.desktop.interface scaling_factor name=%s value=%d factor=%g\n", str, v, gnome_f); g_variant_unref_f(gvar); g_object_unref_f(gset); | |
|
#33 | manolo 13:04 Feb 21, 2017 |
| @Chris: thanks for your input about Ubuntu + Gnome session flashback, showing that the scaling factor should be detected differently.
Here is my current understanding:
- under Ubuntu + Gnome session flashback, the factor is changed with gnome-tweak-tool to 1 or 2 and its value is found in "org.gnome.desktop.interface scaling-factor"
- under Ubuntu + default desktop, the factor can be changed in two ways, and both ways can be combined:
1) with gnome-tweak-tool to 1 or 2 and its value is found in "org.gnome.settings-daemon.plugins.xsettings overrides"
2) with System Settings ==> Displays ==> Scale for menu and title bars and its value is found in "gsettings get com.ubuntu.user-interface scale-factor"
Thus, I changed the patch to read all 3 factor values, and to multiply them to get the correct effect.
Why do simple when complex is so nice? | |
|
#34 | AlbrechtS 05:55 Feb 22, 2017 |
| I can confirm WRT comment #24 in scaling10.patch:
Fixed issues: 1, 2, 3, 5, 7.
Issue 4: Window truncation still happens. This is likely a WM + FLTK interaction issue. The WM seems to truncate the window but either doesn't communicate this to FLTK or FLTK doesn't recognize it. In any case, windows that are not resizable should IMO not be truncated (by the WM ?) in this way. Maybe this is a Windows "feature" since the Cygwin X server uses "Windows windows" to display the "X windows". I don't know what we can do about this.
Issue 6: There is still the tiny cursor if the cursor is not changed by FLTK to another one. Maybe we could explicitly change the cursor when a program is started or ... ?
See attached file window-truncation.png for issue #4 and #6 (the tiny cursor is visible in the middle button "Window Tests". To see the truncation effect I had to extend the scaling_values array in Fl_x.cxx:
static float scaling_values[] = {0.5, 2.f/3, 0.8, 0.9, 1, 1.1, 1.2, 4.f/3, 1.5, 1.7, 2, 2.4, 3, 3.75, 5.5, 6.5, 7.5, 9.75};
with values up to 9.75 just for testing. Could you please add these deliberately non-integral values in the next patch version (we can remove them before a final commit, although in my case values > 3 would really be appropriate, maybe up to 5 or 6).
The truncation effect can be seen after enlarging the window so that the physical (scaled) w and/or h are larger than the physical screen resolution. This does not happen on the Ubuntu desktop that allows a window to extend beyond physical screen sizes, and I can move the window around and see that it's intact. | |
|
#35 | AlbrechtS 06:09 Feb 22, 2017 |
| A new issue: displaced menu windows. This appears to happen when a menu window extends beyond the screen limits. I found this with test/unittest's scheme test menu (with the additional oxy scheme).
To reproduce: Use ctrl/+ to scale upwards once or more. Select 'gleam' scheme. Move the window to the top of the screen. Click on the scheme selection menu. Now the menu extends upwards beyond the window and, since the window is at the top of the screen, beyond the top screen limit. Usually this should be caught by the menu display code and corrected, but this doesn't happen (my guess: calculation doesn't take scaling into account?).
The effect on the Ubuntu desktop is benign. Once you move or drag the mouse the menu window is placed properly within screen limits, but that is still not correct.
The effect on my (Cygwin) X server on the Windows host is worse. The menu window is obviously placed at an arbitrary location by Windows. It "moves around" in the typical way like top level windows are placed on windows whenever you close and reopen the menu. I' upload two files: displaced_menu_Ubuntu-VM.png and displaced_menu_Cygwin_X.png.
I didn't test, but I assume this effect can also be seen in test/menubar. | |
|
#36 | AlbrechtS 06:17 Feb 22, 2017 |
| A minor issue: the scaling factor display may not be scaled and positioned "correctly" (for whatever that means). Attached screenshot shows shows the entire Ubuntu desktop when using the scaling factor 975%. This appears a little exaggerated.
I'd like to have the display within the window limits, maybe at the top left corner, in an adequate effective size, if this is possible. | |
|
#37 | AlbrechtS 06:43 Feb 22, 2017 |
| @Manolo, comment #31: Starting FLTK applications with different scaling factors (no matter if in Cygwin/X or Ubuntu desktop) works as expected. Unfortunately both X servers use the same setting 'VGA-1' in my case. Is this something we (you) can change? Can we add, for instance "CYGWIN-X" and use this with an arbitrary scaling factor (like 175% in my case) by using an environment variable FLTK_SCALING_MODE="CYGWIN-X" or something like that?
Original setting:
$ gsettings get com.ubuntu.user-interface scale-factor {'VBOX0': 8, 'VGA-0': 32, 'VGA-1': 8}
Modified with:
$ gsettings set com.ubuntu.user-interface scale-factor "{'VBOX0': 8, 'VGA-0': 32, 'VGA-1': 12}"
... and the program starts with the desired scaling factor 1.5.
$ bin/examples/unittests com.ubuntu.user-interface scale-factor name=VGA-1 value=12 factor=1.5
(process:9817): GLib-CRITICAL **: g_variant_unref: assertion 'value != NULL' failed
PS: do you also see the "GLib-CRITICAL" assertion? There's no such message w/o the scaling patch (tested and verified).
PPS: WRT comment #33: is it really good/correct to multiply all scaling factors? Isn't it more useful to select the "right" scaling factor according to the desktop environment? Reasoning: if I need a scaling factor of 2 and switch desktops, I think that I would have to set _both_ factors (in each different desktop environment) to 2 to be effective. If you multiply them, I'd have an effective scaling factor 4 in FLTK apps, whereas the normal desktop environment(s) would have the scaling factor(s) 2. Note: that's just "thinking aloud", I have no idea how it really works. Maybe Chris can tell... | |
|
#38 | chris 07:51 Feb 22, 2017 |
| Regarding multiplication of scale factors:
I think Albrecht is right here. I can only speak by my limited experience with only Ubuntu 14.04, but Gnome Flashback knows just "its" value and Ubuntu Unity does not use the one from Gnome Flashback (it obviously knows about it, because it resets its to 1).
So you have to choose the "right" one(s).
But how to detect which desktop type is active?
And this is only for Gnome/Unity. What about KDE and others?
My impression is, this could be much effort and will always be uncertain. I liked the initial environment variable approach. Perhaps it could be used at least as an override value for auto-detection (or unknown "systems"). | |
|
#39 | AlbrechtS 10:18 Feb 22, 2017 |
| Something to think about, at least for the final solution:
If I set the Ubuntu scaling factor to 1.25 because that is my default scaling for the Ubuntu desktop, then FLTK applications start with exactly this scaling factor. That's good. Typing ctrl/+ or ctrl/- finds the nearest lower scaling factor in the list of available factors (in this case 1.20) and changes scaling to the next lower or higher factor (110% or 133%, resp.). I can never return to 1.25 again.
I suggest to change this as follows: Read the system scaling factor, whatever this is (here: 1.25) and store it somewhere. Set the internal scaling factor to 1.0, but multiply internally with the system scaling of 1.25. Now, typing ctrl/+ or ctrl/- would advance to 1.10 or 0.90, respectively, but still multiply with the system scaling (1.25) internally. The displayed scaling factor should be 100%, 90%, or 110%, resp., i.e. the "logical scaling factor" based on (multiplied with) the system scaling factor.
The end user would never see "odd" values caused by his personal desktop scaling factor. Note: this would be consistent with firefox (and chrome). The system scaling factor is never shown to the user.
This way we'd always have the initial logical scaling factor 1.0 which is effectively 1.0 * (system scaling factor). No need to search the list for an appropriate scaling factor.
Optional extension (independent of this algorithm to multiply the system scaling factor with the logical scaling factor): Add ctrl/0 key handling to reset to 100% (logical scaling factor). This would always reset to the initial scaling which would be logically 100% but physically in the described case above 125%. The display value would be 100% though. | |
|
#40 | manolo 14:11 Feb 22, 2017 |
| About these remarks in comment 37: 1) is it really good/correct to multiply all scaling factors?
2) Isn't it more useful to select the "right" scaling factor according to the desktop environment?
My current finding is that multiplying all 3 scaling factors is correct because the two variant desktops in question seem to be aware of each other's rescalings: change in one desktop, the change applies to the other desktop too. So the user of two desktops won't be tempted to rescale independently each desktop. Also, the combined scaling value applies to all gnome apps, so if the user would attempt to set two factors to the value 2, he/she would immediately notice all apps (terminal for example) get rescaled by a factor of 4.
About question #2: how can the running app detect the current desktop? No idea. | |
|
#41 | manolo 05:42 Feb 27, 2017 |
| Attached scaling11.patch fixes several of the issues raised : - starting with a >1 scale factor and rescaling relative to it, - going back to the initial scale with ctrl-0, - menu window issue, - truncation of fixed-size windows - FLTK_SCALING_FACTOR environmental variable used when the gnome scale detection procedure does not work. | |
|
#42 | manolo 14:03 Mar 21, 2017 |
| Attached screenscale.patch introduces screen-specific scaling factors. This allows to use a system with several screens of varying DPI. Windows can be moved between screens and adopt the screen-specific scaling.
The gnome settings determine the starting scaling, which can be changed by ctrl-'+'/ctrl-'-'/ctrl-'0' independently for each screen.
If no gnome setting is found, environment variable FLTK_SCALING_FACTOR can be used to set the default scaling value. | |
|
#43 | manolo 23:50 Mar 21, 2017 |
| Attached screenscale2.patch should fix: - problem to build fluid with inline function
- don't multiply gnome settings values
- FLTK_SCALING_FACTOR is given precedence over gnome settings
As for a window that straddles across two displays: Any window is drawn with the scaling factor of the screen where most of the window's surface is located. When the window is moved to another screen, FLTK detects when the surface majority passes to the new screen and schedules a redraw of the window with the new screen's scaling factor for one second later. At that moment, the window is generally entirely on the new window and adopts its new scale. If it's not, it will straddle two screens but with its new scale. | |
|
#44 | chris 11:31 Mar 25, 2017 |
| Some findings:
I tested on Ubuntu 14.04 only with non integral scale factors e.g. 1.5. and used screenscale2.patch, but my findings are not specific to that patch, they are also in previous versions:
1) There are still re-drawing artefacts with *normal* windows (not double buffered windows) as in test/hello.cxx: When moving the window offscreen to the left side of the screen and then back in there can be seen vertical stripes of missing pixels.
I notice that with adding 2 instead of 1 to the expose width/height in Fl_x.cxx/1717:
window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x/s, xevent.xexpose.y/s, xevent.xexpose.width/s + 2, xevent.xexpose.height/s + 2);
these artefacts disappear.
2) test/mandelbrot.cxx has drawing artefacts with the overlay rect when selecting a zoom region.
Looking in the source it can be seen that the overlay rect is implemented by drawing 1 pixel wide images and by saving the overdrawn screen parts using fl_read_image() and restoring them before drawing the overlay rect. For some reason these two operations do not match scale-wise. Could not solve it as I could not figure out if and how fl_read_image() gets scaled, but by poking around in the code I found:
3) Using rounded values of scaled x/y/w/h can improve some things. In this case I was changing Fl_Graphics_Driver::draw_image_rescale() around line 450 in src/Fl_Graphics_Driver.cxx to use rounding:
// Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(W * s, H * s); Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(lround(W * s), lround(H * s)); delete rgb; if (scaled_rgb) { Fl_Region r2 = scale_clip(s); // draw_image_unscaled(scaled_rgb->array, X * s, Y * s, W * s, H * s, depth); draw_image_unscaled(scaled_rgb->array, lround(X * s), lround(Y * s), lround(W * s), lround(H * s), depth);
and noticed the following improvements with mandelbrot.cxx:
- no horizontal stripes (black lines) in the image - scale factors < 1 now also show an image, previously the display was completely black.
2a) Sidenote: in fl_overlay.cxx there is a define USE_XOR that when commented in works better, but the position is not scaled with the patch. | |
|
#45 | manolo 12:58 Mar 26, 2017 |
| @Chris: thanks for your input. I'm using Ubuntu 16.10 in VirtualBox and see no artefact at 150% when moving around the Hello window. I'm no sure what to do at that point. | |
|
#46 | chris 22:47 Mar 26, 2017 |
| I can reproduce it also on Ubuntu 16.04 running in VirtualBox with Metacity.
My session:
echo $DESKTOP_SESSION gnome-flashback-metacity | |
|
#47 | manolo 00:55 Mar 27, 2017 |
| I also have here : echo $DESKTOP_SESSION gnome-flashback-metacity
A difference is I have Ubuntu 16.10
As for VirtualBox, I run 5.1.14 on Mac OS X | |
|
#48 | chris 02:38 Mar 27, 2017 |
| So maybe there were changes/fixes in Metacity after Ubuntu 16.04. VirtualBox can be ruled out because I also get it on a real machine. Don't have an Ubuntu 16.10 setup currently to test with.
As described, this is only on the *LEFT* screen edge.
If you can't reproduce then please ignore. | |
|
#49 | chris 12:35 Mar 27, 2017 |
| I can now reproduce also on Ubuntu 16.10, but not with the default configuration of Metacity. This is what obviously has changed from Ubuntu 16.04 to 16.10: Metacity is now configured as a "compositing manager" by default (unlike in previous versions). So it does offscreen caching on its own and the defect is not visible.
To see it also on Ubuntu 16.10 you have to disable the "compositing-manager" flag of Metacity. This can be done with the dconf-editor (sudo apt install dconf-editor) by going to "org/gnome/metacity" and set the property "compositing-manager" to false. For some reason I get a black desktop background then, but now the drawing artefacts can be seen.
The point then is to use a non-compositing desktop manager. | |
|
#50 | manolo 06:43 Mar 28, 2017 |
| @Chris: I can now reproduce the uncomplete redraw artefact when moving a window out and back in the left screen edge, under Debian Linux 6. I am still unable to exactly decode what goes wrong. I will make this change for now window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x/s,xevent.xexpose.y/s, xevent.xexpose.width/s + ceil(s), xevent.xexpose.height/s + ceil(s)); in the scaling patch (it also requires to include math.h). | |
|
#51 | chris 10:25 Mar 28, 2017 |
| My understanding is that it is simple the result of double rounding down of position and dimension which leads afterwards when the values are "upscaled" again in the draw routines up to 2 pixel difference.
e.g. x=100 w=100 / 1.5 => 66/66 * 1.5 ==> 99,99 i.e. an exposure region at x=99 width 99 instead position 100 width 100.
Would it not be best not to scale the X reported exposure region at all, but to pass it through to the FLTK's drawing routines "asis"? | |
|
#52 | manolo 13:42 Mar 28, 2017 |
| Attached screenscale3.patch contains the fixes suggested at comment #44, with slight improvements. | |
|
#53 | AlbrechtS 02:21 Mar 29, 2017 |
| FYI: Regarding comment #48 and follow-up's: I can confirm the effect noticed by Chris on Ubuntu 14.04 with Metacity (non-compositing), with screenscale2.patch. This effect seems to be gone with screenscale3.patch.
However, I can still see such artifacts with scaling factors < 1.0 (for instance 0.77). These artifacts don't appear with Ubuntu 16.04 (Metacity, compositing), but that was to be expected as Chris found out. | |
|
#54 | AlbrechtS 02:27 Mar 29, 2017 |
| I found two places of suspect code in screenscale2.patch.
#1: src/Fl_Window_Driver.cxx, line #250: +int Fl_Window_Driver::screen_num() { + if (pWindow->parent()) return pWindow->top_window()->driver()->screen_num(); + return Fl::screen_num(x(), y(), w(), y());
----------------------------------------^^^^
should probably read:
+ return Fl::screen_num(x(), y(), w(), h()); ----------------------------------------^^^^
#2: src/Fl_x.cxx:
@@ -1236,18 +1294,23 @@ int fl_handle(const XEvent& thisevent) if (fl_xim_ic && XFilterEvent((XEvent *)&xevent, 0)) return(1); + Fl_X11_Screen_Driver *x11_screen_driver = (Fl_X11_Screen_Driver*)Fl::screen_driver(); #if USE_XRANDR if( XRRUpdateConfiguration_f && xevent.type == randrEventBase + RRScreenChangeNotify) { XRRUpdateConfiguration_f(&xevent); Fl::call_screen_init(); - fl_init_workarea(); +#if USE_XFT + float factor = x11_screen_driver->default_scale_factor(); + for (int screen = 0; screen <= Fl::screen_count(); screen++) + x11_screen_driver->rescale_all_windows_from_screen(screen, factor); Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); +#endif // USE_XFT } -#endif +#endif // USE_XRANDR if (xevent.type == PropertyNotify && xevent.xproperty.atom == fl_NET_WORKAREA) { - fl_init_workarea(); + x11_screen_driver->init_workarea(); } switch (xevent.type) { ================================================================================
This patch appears to *remove* Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); from the code path with (USE_XRANDR AND !USE_XFT).
Was this intended? | |
|
#55 | manolo 07:13 Mar 29, 2017 |
| I believe this code int Fl_Window_Driver::screen_num() { if (pWindow->parent()) return pWindow->top_window()->driver()->screen_num(); return Fl::screen_num(x(), y(), w(), y()); }
is correct because for a subwindow x() and y() are the subwindow's coordinates relatively to their parent window, whereas we need x() and y() to be a position in the screen for Fl::screen_num(x(), y(), w(), y()) to make sense. So, we use the top window's screen number. | |
|
#56 | manolo 07:24 Mar 29, 2017 |
| Regarding comment #53 and the fact such artifacts remain with scaling factors < 1.0 :
I will use this new code that seems to be OK with large and small values of the scaling factor :
int ns = window->driver()->screen_num(); float s = Fl::screen_driver()->scale(ns); int extra = ceil(s); if (extra < 2) extra = 2; window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x/s, xevent.xexpose.y/s, xevent.xexpose.width/s + extra, xevent.xexpose.height/s + extra); | |
|
#57 | chris 09:21 Mar 29, 2017 |
| @Manolo: Regarding #56, did you really find in your tests "extra" values > 2 neccessary to fix artefacts? I tested (with screenscale2.patch) many non scalar scaling factors above 2 up to 5 and never got artefacts (at least not these ones, I got others when moving below screen - but thats another story; or the rather the same in but y direction). So I still uphold my "theory" expressed in #51. And according to that adding just +2 always should suffice. Curious if that is nontheless a wrong assumption.
Regarding screenscale3.path and 2) from #44: I still get artefacts with the overlay rect, smaller ones with 1.5 but massive ones with scales < 1. | |
|
#58 | manolo 09:29 Mar 29, 2017 |
| About comment #55: please, ignore it. I had not read correctly comment #54. The suggestion there is absolutely true. | |
|
#59 | manolo 09:40 Mar 29, 2017 |
| About part 2 of comment #54: yes, I agree the #endif // USE_XFT should be moved one line above.
Thanks for both suggestions. | |
|
#60 | manolo 02:15 Mar 31, 2017 |
| Attached screenscale4.patch fixes the mandelbrot test program also for non-integer scaling factors (without changing the source code of any test program). | |
|
#61 | manolo 10:54 Apr 09, 2017 |
| Attached screenscale5.patch also fixes the checkers test program when moving pieces around with non-integer scaling factors. | |
|
#62 | chris 23:59 Apr 21, 2017 |
| I noted what seems to be a minor regression with clipping with screenscale6.patch, that is present even in unscaled mode. Found coincidentally when using the help_dialog test: When scrolling down to the table with images an artefact (a part of the table) appears below in the window. Attaching a screenshot. | |
|
#63 | manolo 10:00 Apr 24, 2017 |
| The regression identified in comment #62 should disappear with screenscale7.patch | |
|
#64 | manolo 10:06 Apr 30, 2017 |
| Attached screenscale8.patch supports also fractional scaling factors for the Fl_Scroll widget by performing full redraws. | |
|
#65 | manolo 09:16 May 12, 2017 |
| Attached screenscale+mac+win.patch adds some VERY LIMITED support of rescaling and HiDPI support for the MSWindows and Mac OS platforms. At this stage, it's only a proof of feasibility, that needs completion.
On the MSWindows platform: Rescaling support is, at this stage, limited to text drawing: only the 'hello' test program is usable (everything remains usable without rescaling). The patch supports GUI rescaling by ctrl/+/-/0/, detects the current scaling factor of the OS, and responds to changes of this value in real time. The first feature listed above runs on all OS versions. The other two require OS 8.1 or above. In all cases, the text is written using the full resolution of the display. In contrast, with the unpatched FLTK and when the system's scaling factor is > 1, text is written to a buffer that is then graphically expanded and copied to the screen, producing blurred text. The implementation is as recommended at: https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx SetProcessDpiAwareness() is called in fl_open_display() to put the app in PROCESS_PER_MONITOR_DPI_AWARE mode. GetDpiForMonitor() is used to compute the scaling factor value at startup.
On the Mac OS platform: Support for GUI rescaling by command/+/-/0/ is added. Quite a few demo programs are partially usable (device, editor, boxtypes, unittests, …). Since Mac OS uses a true device independent drawing model, support for GUI rescaling is basically obtained adding one statement in Fl_Cocoa_Window_Driver::make_current().
Part of the new code is platform-independent: - support for rescaling by command/+/-/0/; - the driver model gives a platform-independent interface to the detection of the OS scaling factor and the storage of its variable, potentially screen-dependent values; - the Fl_Scalable_Graphics_Driver class is used twice, by the X11 and MSWindows platforms. | |
|
#66 | AlbrechtS 07:13 May 16, 2017 |
| Testing file #33: screenscale8.patch, assuming that this would be the one to commit in branch-1.4 for now.
Observations: Image scaling and borders seem to be off by one at certain scaling factors, for instance 1.10 and 1.20. See attached file image_scaling_borders.png (supposedly file #35). This is a minor issue, but you can see a small (probably 1-pixel wide) gap between the image(s) and the border(s). Posted image is with scaling 1.10, but 1.20 is similar. | |
|
#67 | AlbrechtS 07:16 May 16, 2017 |
| Note: I used test/unittests, "drawing images". | |
|
#68 | AlbrechtS 07:44 May 16, 2017 |
| Unexpected behavior of test/blocks: this demo program obviously uses the '+' key to switch to the next level (I didn't know that, and I didn't check the code). The unexpected behavior is that the program also gets the ctrl/+ key press that adjusts the scaling factor and then also switches to the next level. This can only be observed after the game has been started with the start button.
The question/issue: shouldn't the ctrl/+/-/0 key press be consumed by the scaling feature? In this case (blocks) it would certainly be good not to deliver the ctrl/+ event to the application, but in other cases I don't know what to suggest. It might be useful to use _and_ deliver it anyway to not hide it from the application's key events.
Blocks could be changed to ignore ctrl/+ (i.e. use the '+' key only w/o ctrl being pressed), but in case of other applications this might not be feasible.
Opinions? | |
|
#69 | AlbrechtS 08:07 May 16, 2017 |
| Unexpected behavior of test/offscreen: when changing the scaling factor with ctrl/+/-/0 the offscreen drawing is reset and restarted. This seems to be due to an FL_HIDE event that is seen by the application (tested and verified).
I believe this is necessary to change the scaling factor (is it?), but it may have side effects user applications.
Another side effect is that dialog windows appear to be closed and this may affect applications. Example: run test/ask, wait a few seconds until a popup appears. Recognize the color of the dialog icon with '?'. Then press ctrl/+ to change the scaling. The icon color changes (not always, but at least sometimes [1]), as if the dialog had been answered with the <esc> key. This is a behavior change that can affect applications.
[1] the color change appears if another timeout has been queued in the background which happens every 5 seconds.
Conclusion: There are behavior changes of programs that observe FL_HIDE and FL_SHOW events if the user changes the scaling factor. Should we accept these potential changes and document them? We could document the restriction and recommend not to change the scaling factor too frequently, i.e. only after program start or when really required? | |
|
#70 | AlbrechtS 08:35 May 16, 2017 |
| I can see artifacts on the window border (!) of test/editor when using a scaling factor > 1.0 and resizing the window. You can see these artifacts in the attached image editor_artifacts.png (file #36). Some of the pixels on the right and bottom border seem to be green (from comments), others are black. It looks as if the text rendering can somehow exceed the client area and draw over the window borders. Very strange...
Another observation in the same image is that the beginning '//' on otherwise "empty" lines are truncated on the upper right side. ISTR that this was already reported (maybe by Chris?), but I couldn't find it right now.
Both observations may be related (text measurement). IIRC someone (Chris?) reported that replacing fl_measure() with fl_text_extents() helped to fix at least the 2nd (i.e. '//') issue. But I wonder if calling fl_text_extents() in Fl_Text_Display/Editor might be too expensive and slow text rendering down. | |
|
#71 | chris 09:15 May 16, 2017 |
| Regarding #70 - cut off // in text display: My report is in http://www.fltk.org/str.php?L3364
This is nothing new, has been so "forever". | |
|
#72 | ianmacarthur 09:33 May 16, 2017 |
| Regarding #69: I think we need to document that there may be an issue with FL_SHOW/FL_HIDE events during a "zoom change", but I'm not sure three's much we could do to "fix" it.
For example, if we need to destroy and recreate the context (as I assume happens in the offscreen demo, for example) then I can't really see how we would "preserve" the prior image but somehow resize it to suit the new context. In that case, would we try to rescale the content of the existing offscreen buffer and use that to fill the new buffer initially? That doesn't sound easy.
Similarly with dialog boxes and similar; I guess our best bet might be just to persuade users *not* change zoom factor with the dialogs displayed! :-) | |
|
#73 | AlbrechtS 14:48 May 16, 2017 |
| Regarding #72: Ian, there are two different points we need to check/discuss:
#1: Do we really need to hide and show the window(s) in the first place? Would just resizing the window not be sufficient? I have to admit that I don't know what's going on under the hood (need to check the sources), so this is basically a question to Manolo.
#2: The offline demo was mentioned by me as an example *user* program that changes its behavior when the user types ctrl/+/-/0. So the question is not how we can fix the offline demo program (or the blocks demo, or other programs with open dialogs), rather than how to fix the FLTK core so that user programs are not affected by the changes - if at all possible.
So if we can't avoid hide() and show() then we have to live with the consequences. As you wrote, if we can't change it, we can only document it and ask users to take care when changing the scaling. The new zoom feature is IMO worth much more than we lose because of these small side effects. | |
|
#74 | ianmacarthur 15:21 May 16, 2017 |
| Re: #73 (2) - I imagine (without investigating...) that what happens is something like this.
The offscreen surface is essentially a surface at the native resolution of the display, and what is drawn into that surface persists across updates. Drawing into that surface happens at whatever scale factor is currently set. So if the offscreen is nominally 512x512, and the scale is 2, we actually draw a 1024x1024 surface.
When the scale factor is changed, a new offscreen is created sized to suit at the new scale. But everything that is "stored" in the "old" offscreen is now the "wrong" size, so can not be just copied over.
We can discard it (which seems to be what happens now) or perhaps we could try to resample it to the new size, albeit with some loss of fidelity in the process, potentially?
I'm not keen on trying to resample, though perhaps the user could do that if they needed to? Do not know.
And I may be totally wrong about what is happening here anyway! | |
|
#75 | AlbrechtS 16:35 May 16, 2017 |
| Re: #74: Your description seems to be correct, but it's maybe much simpler. The offscreen demo reacts on FL_HIDE events and destroys the offscreen when it receives an FL_HIDE event. It creates another empty offscreen when needed (i.e. after FL_SHOW). You can see the same effect if you hide and show the window with the WM buttons. So far this behavior is intended. The code is in lines 116-120 of test/offscreen.cxx:
116 if (ev == FL_HIDE && oscr) { 117 fl_delete_offscreen(oscr); 118 oscr = 0; 119 iters = num_iterations + 1; 120 }
However (I apologize if that was clear) this was *not* my point. Maybe my explanation was not clear enough. I'm not interested in how we can fix end user programs because we can't do that. So the question what exactly happens inside test/offscreen is moot.
My point is that the offscreen demo is only one random example of an *end user* program. IMO our new features should not affect end user programs in a way that their behavior is changed, which obviously is the case in this demo (user) program. The existence of FL_HIDE and FL_SHOW events when the user types ctrl/+ is an unexpected behavior (side effect) of the new feature which should be avoided if possible. Other end user programs may suffer from these additional events as well.
Hence we are back to the relevant question: whether we can avoid the FL_HIDE and FL_SHOW events for backwards compatibility without unexpected side effects. | |
|
#76 | AlbrechtS 16:42 May 16, 2017 |
| BTW: while I was testing I found that the offscreen demo also shows artifacts drawn over the window borders (or what appears to be the window borders).
Test scenario: run test/offscreen, scale down to 50% with ctrl/-, then resize the window by dragging the bottom right corner. While dragging, watch the border (or release the mouse to see what happens). Depending on the current size, there is a part of the border that seems to contain offscreen drawing info.
See attached file (#36): http://www.fltk.org/strfiles/3320/offscreen_border_artifacts.png | |
|
#77 | manolo 09:06 May 17, 2017 |
| About comments 73 & 74: what Ian writes is entirely accurate: the pixel size of the offscreen buffer depends on the scaling factor value, so the offscreen buffer needs be changed each time the application window is rescaled. When the app is rescaled, the widths of the lines drawn also vary according to the new scaling factor.
Doing otherwise would require to rescale the offscreen to another width and height. That is possible in itself, but requires that FLTK has a handle to this offscreen, which is not the case. Only the app knows it's working with an offscreen buffer. | |
|
#78 | manolo 09:18 May 17, 2017 |
| About comment #73:
The present code does Fl::screen_driver()->scale(screen, f); window->hide(); window->show(); where f is the new scaling factor and screen is the number of the window-containing screen, to trigger the rescaling of an FLTK window.
This source code is platform-independent and works well on all 3 platforms.
I have tried other ways, but they fail for subwindows. The difficulty is that rescaling is a window resize in drawing units, but changes no value in FLTK units, the only unit that FLTK considers in its resizing algorithm.
If a developer finds another way, that would be excellent. The code part to consider is function Fl_Screen_Driver::rescale_all_windows_from_screen() in file src/Fl_Screen_Driver.cxx | |
|
#79 | manolo 09:46 May 17, 2017 |
| About unwanted side effects of hide()/show() when rescaling windows:
The offscreen program reveals one issue with offscreen buffers. Not all offscreen buffers create problems though. Those associated to images are handled internally by FLTK which recomputes them if needed after a rescale.
We could add an Fl_Offscreen fl_offscreen_rescale(Fl_Offscreen off, float s) convenience function to help users rescale their offscreen buffers?
Another issue: the fl_width() of a character of a fixed-width font is not strictly proportional to the scaling factor, because scaling factors can be non integer whereas FLTK font sizes are always integer. Consequently, an app that multiplies this width by a somewhat large number to compute horizontal offsets will need to recompute it after each window rescale. | |
|
#80 | manolo 10:32 May 18, 2017 |
| I have committed (r.12240) a new function void fl_scale_offscreen(Fl_Offscreen &) that scales an offscreen buffer after the scaling factor value was changed. The offscreen test program calls it, and is able to keep the content of its offscreen drawing across rescale operations.
We could document the usage of this function when dealing with HiDPI and scaling support. | |
|
#81 | manolo 23:00 Jun 08, 2017 |
| Attached file #38 (scaling_rect.patch) is a proposal to fix the issue described here at #66. The point is more generally that there should be no undrawn pixels between fl_rect(x,y,w,h) and fl_rectf(x+1, y+1, w-2, h-2).
The patch does that for all scaling values, and also if fl_loop() is used instead of fl_rect().
Consequently, there are no more undrawn pixels inside rectangles of the "rectangles" and "drawing images" modes of the unittests program, at all scales.
Consequently, rectangles are drawn with sides that can have different widths, to compensate for non-integer coordinates.
@Albrecht: what is the preferable graphical effect: - rectangles with equally wide sides, but undrawn pixels inside - no undrawn pixels, but rectangle sides have variable widths ? | |
|
#82 | manolo 08:39 Jun 09, 2017 |
| About comment #68 and test/blocks:
I believe the problem is in the source code of the test/blocks program. It detects the '+' key only by testing strcmp(Fl::event_text(), "+") == 0 This test is also positive with ctrl-'+'. The test should thus make sure that Fl::event_command()is false. Moreover, when the '+' key is processed, the handle() function returns 0, indicating the key event has not been recognized. Consequently, the key event becomes processed by the event handler in charge of the detection of enlarge/shrink commands.
Overall, I believe this modified form of the source code is necessary: case FL_KEYBOARD: if (!Fl::event_command() && Fl::event_text()) { if (strcmp(Fl::event_text(), "+") == 0) up_level(); return 1; } break;
@Albrecht: what do you think? You wrote "The question/issue: shouldn't the ctrl/+/-/0 key press be consumed by the scaling feature?" I believe the blocks program should consume the '+' key event when it detects it, that is, have the handle() return non-zero, so it does not get sent after to the scaling feature. If the absence of the ctrl modifier is also tested by the blocks program, all things run well because the scaling feature requires this modifier. | |
|
#83 | manolo 23:14 Jun 09, 2017 |
| With r.12255, the window border artefact described at comment #70 should disappear. | |
|
#84 | manolo 23:57 Jun 09, 2017 |
| About comment #35: displaced menu windows. With the present code, I see no effect of scaling, because the menu window behaves equally for scaling factors =1 and >1.
I added a few dummy elements to the schemes menu of test/unittests so it goes above the window top end when the last menu item is selected. With and without rescaling, the menu is positionned equally, as if the window would be taller (see attached #39 menu_at_top.png). This is with Debian. | |
|
#85 | AlbrechtS 02:04 Jul 22, 2017 |
| Uploading new version (#40) of file #38 (scaling_rect.patch) for current svn (r12346). http://www.fltk.org/strfiles/3320/scaling_rect_r12346.patch | |
|
#86 | chris 03:06 Jul 22, 2017 |
| I found there is a minor behaviour regression (compared to FLTK 1.3) caused by manual zooming with Ctrl+ and Ctrl-.
Consider this program:
---------------- #include <FL/Fl.H> #include <FL/Fl_Double_Window.H>
class MainWin : public Fl_Double_Window { public: MainWin( int W_, int H_, const char *l_ = 0 ) : Fl_Double_Window( W_, H_, l_ ), _toolBox( 0 ) { end(); _toolBox = new Fl_Double_Window( 200, 200, "toolbox" ); _toolBox->end(); _toolBox->show(); show(); } virtual void hide() { Fl_Double_Window::hide(); if ( _toolBox ) _toolBox->hide(); } private: Fl_Double_Window *_toolBox; };
int main() { MainWin win( 800, 600, "main" ); return Fl::run(); } ----------------
It tries to hide all windows ('toolBox' here), when the user clicks on the close button of the main window in order to cause an exit. It does so by overriding the hide() method of the main window, in the believe, that only the close button of the main window will trigger this method. I think this is a valid assumption for FLTK 1.3.
Now with FLTK-1.4 the manual zoom currently calls the virtual hide()/show() methods too. The effect on this program is, that the 'toolBox' window gets hidden and won't reappear after the scaling.
I suggest the following patch, that calls only the base class hide()/show() methods:
Index: src/Fl_Window_Driver.cxx =================================================================== --- src/Fl_Window_Driver.cxx (Revision 12346) +++ src/Fl_Window_Driver.cxx (Arbeitskopie) @@ -263,7 +263,7 @@ void Fl_Window_Driver::resize_after_scale_change(int ns, float old_f, float new_f) { int oldx = pWindow->x(), oldy = pWindow->y(); fl_uintptr_t current = current_cursor(); - pWindow->hide(); + pWindow->Fl_Window::hide(); screen_num(ns); pWindow->position(oldx*old_f/new_f, oldy*old_f/new_f); force_position(1); @@ -271,7 +271,7 @@ pWindow->size(pWindow->w() * old_f/new_f, pWindow->h() * old_f/new_f); } Fl_Graphics_Driver::default_driver().scale(new_f); - pWindow->show(); + pWindow->Fl_Window::show(); reuse_cursor(current); reuse_icons(); //extern FILE*LOG;fprintf(LOG,"ns=%d old_f%.2f new_f=%.2f\n",ns,old_f,new_f);fflush(LOG); | |
|
#87 | manolo 03:30 Jul 23, 2017 |
| @chris:
The solution you propose is not possible because Fl_Widget::hide() is a virtual member function with several implementations, in particular, distinct implementations for the Fl_Window and Fl_Double_Window classes. Thus, calling Fl_Window::hide() would be incorrect for an Fl_Double_Window object.
What you should do is provide your main window with a callback function, because the window's callback is what is triggered when the window's close button is clicked, as explained there: http://www.fltk.org/doc-1.3/classFl__Window.html#details
The default window callback calls hide() (as a virtual member function) for the window. Since you want more than that, you just have to implement what you want in a callback function and assign it to your main window. This is a working implementation:
#include <FL/Fl.H> #include <FL/Fl_Double_Window.H>
void mainwin_cb(Fl_Widget *wid, void *data) { bool found; do { found = false; Fl_Window *win = Fl::first_window(); while (win) { Fl::delete_widget(win); found = true; break; win = Fl::next_window(win); } } while(found); }
class MainWin : public Fl_Double_Window { public: MainWin( int W_, int H_, const char *l_ = 0 ) : Fl_Double_Window( W_, H_, l_ ) { end(); _toolBox = new Fl_Double_Window( 200, 200, "toolbox" ); _toolBox->end(); _toolBox->color(FL_BLUE); show(); _toolBox->show(); callback(mainwin_cb); } private: Fl_Double_Window *_toolBox; };
int main() { MainWin win( 600, 400, "main" ); return Fl::run(); } | |
|
#88 | manolo 03:40 Jul 23, 2017 |
| OK, a quite simpler implementation of mainwin_cb is enough:
void mainwin_cb(Fl_Widget *wid, void *data) { Fl_Window *win; while ((win = Fl::first_window()) != NULL) Fl::delete_widget(win); } | |
|
#89 | chris 09:58 Jul 23, 2017 |
| #87: Mainly I wanted to point out, that code working with FLTK 1.3, could get a problem when compiled with FLTK 1.4 and manual zooming is done (as was the case with my code).
You are right, that my proposed solution (though it seemingly works with all test programs), may have problems (what I can see: the deletion of the offscreen is not done with double windows), but those might be solvable by moving more code to the driver class. But I also noticed, there are more such hide()/show() metaphers in the code e.g. Fl_Window_Driver::use_border(), so unless all of these get changed, there were not advantage changing this one.
But on the other side, it is arguable, if overloading hide() with the purpose I used it for, is good practice. Probably not. So looks, as if I got to change my program, the way you outlined it. Thanks. | |
|
#90 | chris 10:00 Jul 23, 2017 |
| By the way: Skimming through source I noticed Fl_Overlay_Window.cxx, line 30 may have the same issue that was fixed in r12339. | |
|
#91 | AlbrechtS 10:38 Jul 23, 2017 |
| Re #86: this is not a trivial issue, and I have several, potentially contradicting "opinions":
(1) I agree that this is a behaviour change (maybe we can call it a regression) WRT FLTK 1.3.4. I would really, really prefer a solution that does not call hide() and show() on all windows, but as long as we don't have such a solution (that also works cross-platform) this may be something we have to live with in FLTK 1.4 and later. We discussed already that we need to document it thoroughly, but we know that there may be impacts on user code.
(2) I agree with Manolo that not calling the virtual method(s) hide() and show() would be wrong, with potentially more, yet unknown, consequences. I remember that we made show() and hide() virtual at some time for a good reason, probably in the development of FLTK 1.3.0 (sorry, too lazy to check now).
(3) I disagree with the assumption that "only the close button of the main window will trigger this method" (hide()). Although it may be valid for your program in this case, the WM may also hide() and show() windows, for instance if you switch desktops or do some other things - although I'm not aware of such a WM, I'm only imagining that this _might_ be possible. Manolo showed the recommended FLTK way to deal with the close button by defining a window callback. This is well documented and should always be followed.
(4) Another way to handle the issue is to also provide a virtual show() method for your example program, like this:
virtual void show() { Fl_Double_Window::show(); if ( _toolBox ) _toolBox->show(); }
A small side effect of this is that the window that gets the focus after ctrl +/- may change, so I can't really recommend this.
Conclusion: I know this is a code change that becomes necessary with the transition from FLTK 1.3 to 1.4 (be the program "correct" or not), and I'd really like to avoid this, but ... go back to (1) ;-) | |
|
#92 | manolo 23:38 Jul 23, 2017 |
| @Chris Re #90: Good catch! It's now fixed in the svn repository (r.12347) | |
|
#93 | manolo 04:04 Jul 25, 2017 |
| Albrecht special: with r12349, branch 1.4 no longer calls Fl_Window::hide() and show() to rescale windows in response to ctrl-+/-/0/ This is now done by a call to Fl_Window::resize(), but requires some tweaking of this function. A new boolean flag has been created, static member variable bool Fl_Window_Driver::in_resize_after_scale_change, that is true if and only if Fl_Window::resize() has been called by Fl_Window_Driver::resize_after_scale_change(). This flag makes Fl_Window::resize() correctly rescale any window. | |
|
#94 | AlbrechtS 05:06 Jul 25, 2017 |
| Re #93: That's great news. Awesome, thank you very much! I'll test ASAP. | |
|
#95 | chris 11:57 Jul 28, 2017 |
| Is there something awry with fl_read_image()? I have posted a program at #41 that shows garbage when scaling down and ultimately crashes when 50% is reached.
(Ubuntu 14.04) | |
|
#96 | manolo 00:42 Jul 29, 2017 |
| Yes indeed. This should be repaired now in the svn repository (r.12365). | |
|
#97 | chris 12:43 Jul 29, 2017 |
| Yes, this works now.
It looks as if src/Fl_Widget_Surface.cxx has the same source pattern at line 162, would it also need a change? | |
|
#98 | manolo 08:22 Jul 30, 2017 |
| Re #97: correct. This is now fixed in the svn repository (r.12366) | |
|
#99 | greg.ercolano 01:27 Nov 04, 2017 |
| Wow, this is amazing!!
I'll be recompiling my apps with 1.4.x this weekend to test.
So far so good.. the only thing I've noticed so far is how tabs vs. spaces indented code appears in Fl_Text_Display/Editor; at the fractional scales between 1 and 2, the columns go out of alignment a bit. And selecting over the text causes the text to wobble.
Looks fine in Fl_Multiline_Input.
So it's probably something /just/ in the Fl_Text_Display code's tabstop calculations. | |
|
#100 | greg.ercolano 14:47 Nov 04, 2017 |
| Augmenting the title of the STR to include the word 'scaling'.. | |
|
#101 | manolo 07:48 Nov 05, 2017 |
| RE: comment #99 This should now be fixed with r.12544. | |
|
#102 | manolo 09:33 Nov 05, 2017 |
| Progress report about STR#3320: Support for high resolution displays on the X11 platform 5 november 2017
The X11 and WIN32 platforms support runtime rescaling of all FLTK-created windows by ctrl-+/-/0 keys.
Nothing new about rescaling for the MacOS platform (but 'retina' displays are fully supported since 1.3.4).
The X11 and WIN32 platforms support screen-specific scaling factors. Consequently, desktops mixing displays of distinct resolutions are well supported. When an FLTK window is moved between screens with different resolution, it gets automatically rescaled (actually, this is done using a 1-second timeout).
Under MSWindows, Debian, Ubuntu, FreeBSD, FLTK attempts to discover the desktop scaling factor at work at application start, and applies this factor. Consequently, FLTK apps run well on HiDPI displays.
If this mechanism fails, the environment variable FLTK_SCALING_FACTOR can be set to indicate the desired scaling factor (example: 1.75).
The all new Ubuntu 17.10 has changed its way of storing the desktop scaling factor, so that the environment variable is needed there. [Wanted: where does Ubuntu 17.10 store this scaling factor value?]
Adjacent horizontal and vertical lines and adjacent rectangles (in FLTK units) are drawn so that there is no undrawn space between them (in graphical units). Consequently, gradients used in FLTK schemes and tiled images work correctly when the scaling factor has a non-integral value.
FLTK apps should generally acquire correct rescalability without source code change with FLTK 1.4. One type of operation does not rescale correctly, though, with non-integral scaling factor values: operations that assume fixed-width characters to have integral widths. Decimal- valued factors create decimal-valued character width (in FLTK units). If this value is truncated to int and multiplied, the resulting value can be far from correct. I have seen this effect in one full-size app. The app was fixed by recomputing the fixed character-width after each scaling operation. This effect is also the ultimate cause of the problem reported at comment #99 (now corrected in svn).
A choice remains to be done between two approaches: 1) use the code of the svn repository 2) apply scaling_rect_r12544.patch (attached file #42)
They differ in how empty rectangles and successive horizontal and vertical lines - with, e.g., fl_xyline (int x, int y, int x1, int y2) - are drawn. In case 2), FLTK makes sure there is no undrawn space between fl_rect(x, y, w, h) and fl_rectf(x+1, y+1, w-2, h-2), or between fl_rect(x, y, w, h) and fl_rect(x-1, y-1, w+2, h+2).
Program test/unittests allows to compare the outcomes of the two approaches:
With 2) no red is visible in the "rectangles" test even with non-integral scaling factor values, and there's no undrawn space between image and box in "drawing images". But "drawing lines" shows that line width depends on line position (resize the window to modify line positions and see varying line widths).
With 1), the segments of broken lines and of empty rectangles have all the same width. But, there's undrawn space when an empty rectangle is nested within a one unit-larger empty rectangle, or filled by a one unit-smaller filled rectangle.
1) and 2) don't differ (and don't matter) when the scaling factor has an integral value (1, 2 or 3). The issue results from the conflict between a graphical system with all-integral values (X11 or WIN32-GDI) and non-integral scaling factor values that ask for drawing at fractional coordinates. | |
|
#103 | AlbrechtS 12:12 Nov 05, 2017 |
| Uploaded file scaling_rect_r12545.patch adjusted to current svn (r12545).
@Manolo: The only difference to scaling_rect_r12544.patch is the omission of the hunk related to documentation/Doxyfile.in that has been updated by me to fix a documentation build warning in out-of-source CMake builds. I also added the two missing excluded files that were added by your r12544 patch, and, btw. sorted the list alphabetically. Please update your working copy before you try to commit...
Thanks for the summary of changes.
I'm pretty sure the mentioned patch is worth being committed. The code is much cleaner and I believe it does what it should do by drawing lines and rectangles "better" for non-integral scaling factors.
+1 for scaling_rect_r12545.patch | |
|
#104 | greg.ercolano 12:37 Nov 05, 2017 |
| Are there user documents the applications can point users to for how to control scaling FLTK apps in e.g. KDE and MS Windows?
I'm kinda new to all this; I take it there's perhaps the scaling value is something the user sets as a window manager option, and that can be polled from the app as a window manager "hint" maybe?
And this "hint" is a single floating point value passed to the app that this STR gets from the window manager, so that when the user sets the scaling value to, say, 150%, the apps always open with that scaling?
I was thinking I should adjust my app's user preferences, which keeps track of things like the user's last resize and position for the window, font/scheme/color preferences, and include this new scaling value, so that if the user uses Ctrl+/Ctrl- to change the size, I can save this value whenever it changes in the app's preferences.
But maybe I shouldn't do that if the window manager keeps track of this? Or does the window manager just recommend a starting value (say 150%), and the user's Ctrl+/Ctrl- actions adjust that value up/down? If so, does the window manager keep track of it for the app, or should our apps keep track of this? | |
|
#105 | AlbrechtS 13:10 Nov 05, 2017 |
| FLTK's internal scaling factor is initialized with the system's (i.e. MS Windows' or under Linux with the desktop environment's) scaling factor. AFAICT there is no user documentation in FLTK that describes how to change the system's scaling factor and there are very different ways to do this. Under MS Windows there's a scaling option somewhere in the display settings (I'm using 175%, for instance), but the different desktops under Linux vary. In my personal Linux VM I don't use the Linux scaling options: the scaling is done by VirtualBox settings. YMMV.
This initial (system) scaling factor can be overriden by the environment variable FLTK_SCALING_FACTOR as Manolo described. This always takes precedence if defined.
The user's changes to the scaling by ctrl/+/-/0 is additional to the initial scaling factor, technically correct it is multiplied with the initial scaling factor to the user gets the impression that the system scaling factor is the default scaling and they can return to the system scaling with ctrl/0.
I wouldn't recommend to save this additional user scaling in a preference w/o asking the user to do so because one may use it only temporary in a specific situation. It can also be wrong to save the user value if the user later changes the system setting because the user setting will be multiplied on top of the changed system scaling value.
That said, I don't think that the application can currently access FLTK's internal/calculated scaling factor. Manolo may know that better (or add an accessor method ?).
To your last question: the WM doesn't know of FLTK's internal scaling. There is only the desktop scaling value that the WM or desktop environment keeps track of. | |
|
#106 | manolo 23:48 Nov 05, 2017 |
| The current scaling factor value is given, in a platform-independent way, by: float Fl_Graphics_Driver::default_driver().scale()
MSWindows sets a default scaling value for each screen of the desktop that depends on the screen size (or size and resolution?). Then, the user can tweak this value using system preferences. Each FLTK app reads these values for each screen at startup and uses them. The app user can further increase/decrease them by ctrl/+/-/, and reset them by ctrl-0.
KDE has a desktop scaling value set using the system preferences mechanism. Unfortunately, I did not find how to get this value from an app. The FLTK_SCALING_FACTOR environment variable gives a workaround.
Gnome also sets a desktop scaling value through system preferences. Until Ubuntu 17.10, it was possible to recover this value through the "gsettings" command (and a corresponding C API). Ubuntu 17.10 changed that. No idea where the value is hidden now. Help wanted for Ubuntu 17.10 and KDE.
It will be useful to write about that in the FLTK doc. | |
|
#107 | manolo 01:37 Nov 06, 2017 |
| Complement to comment #102: Progress report
The current implementation requires to set the preprocessor variable FLTK_HIDPI_SUPPORT to 1 for the new code to be active under the WIN32 platform.
Without that, FLTK apps are so-called DPI-unaware: they run on HiDPI displays because the system expands all their graphical output before putting it on screen. This is the situation as of FLTK 1.3. | |
|
#108 | manolo 07:17 Dec 18, 2017 |
| As of r.12595 (18 dec 2017), the new feature is mostly completely implemented in FLTK 1.4. | |
|
#109 | chris 01:35 Apr 01, 2018 |
| Found by incidence, that there is a drawing artefact with Sliders at scale 200% with scheme gtk+. As this is an integral factor, I wonder how this can happen.
System: Ubuntu 14.04
To reproduce:
test/valuators -s gtk+ Set 200% Move the (red) slider knobs.
They are leaving 1px horizontal and vertical red line artefacts. | |
|
#110 | ianmacarthur 13:51 Apr 01, 2018 |
| Hmm, I'm not seeing that - but I do see errors.
I don't see the red lines Chris describes, but I am seeing artifacts left on the red sliders in the valuators test, in gtk++ mode, at *all* zoom factors, not just 200%.
I do not recall seeing this before - but that probably only means I didn't look properly... | |
|
#111 | AlbrechtS 09:39 Apr 02, 2018 |
| Ian, did you test on Windows? I can confirm artifacts on Windows with all scaling factors greater than 1 (that I tested).
I can also see artifacts on Linux (as Chris reported) with scaling factors > 1.75. These artifacts seem to disappear if I set line_delta_ = 0 for all scaling factors:
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx @@ -93,6 +93,6 @@ void Fl_Xlib_Graphics_Driver::scale(float f) { coordinates by line_delta_ achieves what is wanted until scale_ <= 3.5. */ - line_delta_ = (scale_ > 1.75 ? 1 : 0); + line_delta_ = 0; } #endif } | |
|
#112 | chris 10:07 Apr 02, 2018 |
| > These artifacts seem to disappear if I set line_delta_ = 0 for all > scaling factors:
But this seems not to be the cure, it results in symptom shift only.
e.g.:
- all windows have artefacts at right and bottom edge at 200% - test/tiled_image moved around screen edges gets horizontal stripes at 200% | |
|
#113 | AlbrechtS 10:19 Apr 02, 2018 |
| chris wrote in comment #112: >> These artifacts seem to disappear if I set line_delta_ = 0 for all >> scaling factors: > > But this seems not to be the cure, it results in symptom shift only.
Sure, I was aware of this. I only wanted to mention it to point out that the issue may have something to do with the way line_delta_ is applied to graphics functions. Sorry for the confusion. | |
|
#114 | manolo 05:25 Apr 05, 2018 |
| The drawing artefact with Sliders at scale 200% and with scheme gtk+ should be fixed with r.12821. | |
|
#115 | AlbrechtS 07:46 Feb 08, 2019 |
| Fixed in Git repository.
There has been another update in svn r12823, Git commit 798823f7dc... I updated the revisions accordingly.
I believe it's all done on all platforms and in case someone finds any glitches they can open a new and more specific STR.
Manolo, can we close this STR? | |
|
#116 | manolo 08:25 Feb 08, 2019 |
| Fixed in Git repository.
Support for high resolution is present in FLTK 1.4 for all 3 platforms, really: X11, Windows, macOS. | |
|
#117 | AlbrechtS 05:56 Feb 17, 2019 |
| Test, please ignore. Sorry for the noise. | |
[ Return to Bugs & Features ]
|
| |