Exploration: FLTK platform compatible with both Wayland and X11

244 views
Skip to first unread message

Manolo

unread,
Mar 15, 2022, 2:12:22 AM3/15/22
to fltk.coredev
It's possible to  compile both the Wayland and the X11/Xlib driver source files
and to put all of them inside libfltk. With some additional tweaks, the result is
an FLTK library that makes any FLTK app use Wayland when the Wayland compositor
is available, or the X11 server when it's not, without any change to the app or
the library. That puts FLTK apps in the same position as GTK apps in that respect.

That's for test in the wayland branch of my FLTK fork:
(caution: that's a new wayland branch, delete your old one if any)

1) Build with CMake with OPTION_USE_WAYLAND turned on
(please, don't use configure nor OPTION_CAIRO).

2) Run unchanged FLTK apps either with Wayland or with gnome on Xorg.


The code uses this function to determine whether Wayland
or X11 drivers are to be used and sets static member variable
Fl_Wayland_System_Driver::found_wayland accordingly :

Fl_System_Driver *Fl_System_Driver::newSystemDriver()
{
  // is a Wayland connection available ?
  struct wl_display *wl_display = wl_display_connect(NULL);
  if (wl_display) { // Yes, use Wayland drivers
    Fl_Wayland_System_Driver::found_wayland = true;
    fl_display = (Display*)wl_display;
    return new Fl_Wayland_System_Driver();
  }
  return new Fl_X11_System_Driver(); // No, use X11 drivers
}


Then, platform drivers are created for wayland or for X11 as in :

Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
{
  if (Fl_Wayland_System_Driver::found_wayland) return new Fl_Wayland_Window_Driver(w);
  return new Fl_X11_Window_Driver(w);
}

Some rather dirty hacks are required, though, to make everything work,
especially for platform-specific types which normally differ for Wayland
and for X11.
I believe a better solution for that, yet to be defined, is needed.

Mo_Al_

unread,
Mar 15, 2022, 8:13:33 AM3/15/22
to fltk.coredev
From a user's perspective, I would love to see this capability in FLTK apps. Also a way to setenv something like FLTK_BACKEND (à la GDK_BACKEND) which enables changing the driver on application launch.

Bill Spitzak

unread,
Mar 15, 2022, 1:03:52 PM3/15/22
to fltkc...@googlegroups.com
This is a good idea but I think it has to use Cairo for all rendering, and from what I have heard Cairo has to draw into a local image to get acceptable performance.

It would probably be easy to add an environment variable that forces it to use X11 even if Wayland is available. Probably a good idea for testing.


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/afea7bae-6563-4f83-a95a-48ea45ca8022n%40googlegroups.com.

Albrecht Schlosser

unread,
Mar 21, 2022, 3:31:53 PM3/21/22
to fltkc...@googlegroups.com
On 3/15/22 07:12 Manolo wrote:
It's possible to  compile both the Wayland and the X11/Xlib driver source files
and to put all of them inside libfltk. With some additional tweaks, the result is
an FLTK library that makes any FLTK app use Wayland when the Wayland compositor
is available, or the X11 server when it's not, without any change to the app or
the library. That puts FLTK apps in the same position as GTK apps in that respect.

That's for test in the wayland branch of my FLTK fork:
(caution: that's a new wayland branch, delete your old one if any)

...


Some rather dirty hacks are required, though, to make everything work,
especially for platform-specific types which normally differ for Wayland
and for X11.

Wow, yes, I see really dirty hacks. Not really maintainable.


I believe a better solution for that, yet to be defined, is needed.

I agree that we need something better, and I have some thoughts - not backed by any coding or testing yet.


Caution: a very long article follows...


A Hybrid FLTK Library

Yes, I would also be glad to have such an option to make one FLTK library compatible with both X11 and Wayland. I call this a "hybrid" FLTK library.

I am also convinced that we really *NEED* such hybrid FLTK libs because modern Linux distros would "require" this for the same reasons that Gtk applications can do both X11 and Wayland. If a Linux distro has a package of FLTK 1.4 it will also have an executable 'fluid' program. This program must be able to run under X11 and/or Wayland sessions because *users* select under which environment they work (by login and selecting a session type).

I thought about having such a hybrid FLTK lib for a long time for macOS where it would support native macOS (Quartz) and X11 side by side. To make it even more complicated, such a hybrid FLTK lib could also be thought of under Cygwin with Windows (GDI/GDI+) and X11.

The problem with our current 1.4.0 development library is that we still have some platform specific #ifdef / #elif / ... / #else / #endif code in our explicit platform specific files 'FL/platform.H' and 'FL/platform_types.h'. Such constructs rely on the fact that there can always be only one platform type built into the library. This would no longer be true with hybrid FLTK libs and we'd have to change this.


How to solve this dilemma?

It is clear that the definition of platform specific types (typedefs) and global variables with the same name(s) for different platforms is a huge problem (as Manolo wrote) and that very, very dirty hacks would be required to make this work even for the two related platforms X11 and Wayland. It would be absolutely impossible if we wanted to make this work for Quartz/X11 and Windows-GDI/X11 too because X11 would be the common factor of all three hybrid library combinations.

We need another solution that does not define global types and variables. This is not possible in a single step and not completely for the FLTK 1.4.0 release but I believe that we can and should "prepare" this for the new Wayland platform.

Example: We have the global variable fl_display that has different types, depending on the platform:

FL/wayland.H:23:extern struct wl_display *fl_display;
FL/win32.H:62:extern FL_EXPORT HINSTANCE fl_display;
FL/x11.H:40:extern FL_EXPORT Display *fl_display;

The typedef's are somewhere else. We can certainly deal with 'fl_display' internal in the driver code (we can make the typedef in a header file that is used only by the platform driver), but some of these variables are documented in the "Operating System Issues" chapter, like in the X11 section:

The following global variables are set before Fl_Widget::draw() is called, or by Fl_Window::make_current():
extern Display *fl_display;
extern Window fl_window;
...



It is clear that we need to keep this for FLTK 1.4.0, but I believe we can do better with the Wayland port. The key would be to define functions rather than global variables and global typdefs. We can define such functions (pseudo code):

  wl_display *fl_wl_display() { return internal_wl_display; }
  Display *fl_x11_display() { return internal_fl_display; }
  HINSTANCE fl_win_display() { return internal_win_display; }

This code would have to be properly guarded by the platform macros FLTK_USE_X11, FLTK_USE_WAYLAND, etc.

User code that wants to use platform specific code would look like:

#ifdef FLTK_USE_X11
  Display xdisplay = fl_x11_display();
  if (xdisplay) {
    // X11 specific code here
  }
#endif


#ifdef FLTK_USE_WAYLAND
  wl_display wld = fl_wl_display();
  if (wld) {
    // Wayland specific code here
  }
#endif


Note that user code would use the platform specific #ifdef and test whether the current connection is running on X11 or Wayland.

As can be seen in the example above user code would eventually have to be rewritten slightly, but only if the user code uses platform specific code. The majority of cross-platform FLTK applications wouldn't even "notice" on which platform they are running.

Legacy applications

FLTK 1.3.x applications that use X11 specific code must be enabled to run under a hybrid FLTK lib (mostly) unchanged. Those applications must be able to force X11 mode rather than automatically selecting Wayland mode.

The "auto selection" of platforms (in this example X11 vs. Wayland) must be adjustable by two means:

(a) The user (developer) can set an enviroment variable to select the backend (X11 or Wayland) as others suggested before. This is essential particularly for FLTK developers to be able to test both platforms easily.

(b) The program developer might need to add a statement (function call, setting an option) to the beginning of the program (before the display is opened) to force X11 mode if the program requires X11 mode. Environment variables set by the user wouldn't be reliable in this case.

Legacy applications have code similar to the old FLTK 1.3 style:

  #ifdef _WIN32
    // Windows code
  #elif defined(__APPLE__)
    // macOS code
  #else
    // X11 specific code
  #endif

The fact that we supported only these three platforms and didn't have a reliable way to recognize X11 led to such code. This code can work unchanged in a hybrid library if and only if it can be assured that Wayland mode will not be selected, and this can be done by calling a function during initialization as written above.


To make this function call easier and perhaps settable per user (or system) we could use the Fl::option() system to define a new option or something like that. But it could also be a very specific funtion name like fl_disable_wayland() or similar.


What to do in FLTK 1.4?

In FLTK 1.4.0 with Wayland support we must ensure that the "Operating System Issues" are documented in a clean and future proof way and that typedefs and globals are not shared between X11 and Wayland modes. Rather than using the globals fl_display etc. we should define functions to access the platform specific variables and objects as required (see suggestion above).

Note that we *MUST* IMHO do this before FLTK 1.4.0 gets released because we couldn't easily go back once it is documented and published.

Defining new, similar functions for the X11 and other platforms would be optional in FLTK 1.4.0 but could be done as well. The "old interface" with typedefs and globals would be deprecated (for legacy applications) and new applications or those that want to be "hybrid" as well and still use platform specific code would have to use the "new interface".


So far my thoughts but this is probably far from complete. It should be a beginning...

Comments and suggestions appreciated.

melcher....@googlemail.com

unread,
Mar 22, 2022, 7:48:19 AM3/22/22
to fltk.coredev
As for Fluid, I can offer to change Fluid, so it compiles as a pure command line app as well as a GUI app. It already avoids calling any graphics calls, but if it helps the cause, I would implement a pure .fl to .cpp translator.

imacarthur

unread,
Mar 22, 2022, 7:58:48 AM3/22/22
to fltk.coredev
On Tuesday, 22 March 2022 at 11:48:19 UTC Matt wrote:
As for Fluid, I can offer to change Fluid, so it compiles as a pure command line app as well as a GUI app. It already avoids calling any graphics calls, but if it helps the cause, I would implement a pure .fl to .cpp translator.

And if there were such a thing, then Fluid (Fluid-the-GUI) would call that CLI tool (fluid-cli, say) when needed, rather than having any duplication of the .fl to C++ translation logic...

 

melcher....@googlemail.com

unread,
Mar 22, 2022, 8:40:17 AM3/22/22
to fltk.coredev
Probably not, but it would use the same source code for sure to keep things maintainable. Ideally, there would be a static library that reads .fl and outputs .cpp, and two apps, one providing a GUI, and one providing the command line interface, but both using the same library.

It's not a simple task because everything is interwoven in Fluid, but if it would solve issues, I'd be willing to do it.

Manolo

unread,
Mar 22, 2022, 10:42:22 AM3/22/22
to fltk.coredev


Le lundi 21 mars 2022 à 20:31:53 UTC+1, Albrecht Schlosser a écrit :

What to do in FLTK 1.4?

In FLTK 1.4.0 with Wayland support we must ensure that the "Operating System Issues" are documented in a clean and future proof way and that typedefs and globals are not shared between X11 and Wayland modes. Rather than using the globals fl_display etc. we should define functions to access the platform specific variables and objects as required (see suggestion above).

Note that we *MUST* IMHO do this before FLTK 1.4.0 gets released because we couldn't easily go back once it is documented and published.

Defining new, similar functions for the X11 and other platforms would be optional in FLTK 1.4.0 but could be done as well. The "old interface" with typedefs and globals would be deprecated (for legacy applications) and new applications or those that want to be "hybrid" as well and still use platform specific code would have to use the "new interface".


So far my thoughts but this is probably far from complete. It should be a beginning...

Comments and suggestions appreciated.

I appreciate very much this input on this topic because I see it's very important and also complex to solve.

I will look into these proposals and try to implement the beginning for 1.4.0

Albrecht Schlosser

unread,
Mar 22, 2022, 11:14:30 AM3/22/22
to fltkc...@googlegroups.com
Thanks for doing this, but please keep in mind that my suggestions are so far only thoughts and theoretical. We'll need to find out if this theory works and then find a migration path for future versions.

I'll try to look into it further to see if I can improve my ideas, but please go ahead, you may know better than I what to do.

Bill Spitzak

unread,
Mar 22, 2022, 1:26:23 PM3/22/22
to fltkc...@googlegroups.com
I see no reason you cannot use global variables instead of function calls for these pointers.

The variables are there entirely so that other platform-specific code can use them. You should be able to rename them because all the users of them can change the names as well. I would very very much like to get rid of this idea that the platform is supported by virtual functions, and return to a state where it is controlled by ifdefs which can change how fltk functions are implemented, either by using completely diffferent versions of the functions, or ifdefs inside their internals, which is a very useful feature we lost with this virtual function idea. In particluar it  would allow x-only, wayland-only, and the hybrid version to use the same source code.

In addition it is absolutely required that the X11 version be changed to use Cairo rendering. 

--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Albrecht Schlosser

unread,
Mar 22, 2022, 2:59:57 PM3/22/22
to fltkc...@googlegroups.com
On 3/22/22 12:48 'melcher....@googlemail.com' via fltk.coredev wrote:
As for Fluid, I can offer to change Fluid, so it compiles as a pure command line app as well as a GUI app. It already avoids calling any graphics calls, but if it helps the cause, I would implement a pure .fl to .cpp translator.

Sorry, no, that's not the point. There's no reason to do that.

All FLTK GUI apps should behave like Gtk apps do today: if the Wayland compositor is available they should use it, otherwise they fall back to using old X11. On Wayland systems the latter is enabled by running the X server XWayland under Wayland.

Since *users* have the choice to use X11-only login sessions (e.g. on Debian: "Gnome/Xorg") or use a login session with Wayland and X server (KDE/plasma or Gnome/Wayland) the applications should be able do decide what to use on the fly for better desktop integration (for instance using the desktop specific window decorations).

If we didn't supply a "hybrid" FLTK library the (Linux) distributor would have to build the X11-only FLTK lib and all dependent applications would have to use it and thus all FLTK applications would be X11 only. This would also concern users that build their own applications with the distro's FLTK package.

Alternatively the Linux distro could build two different FLTK libraries for apps that support Wayland or those that don't but that qould likey be a maintenance nightmare for the disto managers and I'm afraid they wouldn't want to do that.

The fact that I mentioned fluid was only an example. Building another command-line fluid executable would not help for the interactive (GUI) fluid, would it?

And there are, of course (!), other FLTK applications in the Linux distro and their GUI executables would need such hybrid support.

Examples on a Debian-like Linux distro:

aconnectgui
Depends: libasound2 (>= 1.0.16), libc6 (>= 2.4), libfltk1.1 (>= 1.1.6-6), libgcc-s1 (>= 3.0), libstdc++6 (>= 5)

alsa-tools-gui
Depends: libasound2 (>= 1.0.24.1), libc6 (>= 2.29), libfltk1.1 (>= 1.1.6), libglib2.0-0 (>= 2.35.9), libgtk-3-0 (>= 3.0.0), libgtk2.0-0 (>= 2.8.0), libstdc++6 (>= 5.2)

alsamixergui
Depends: libasound2 (>= 1.0.16), libc6 (>= 2.14), libfltk1.1 (>= 1.1.6-6), libgcc-s1 (>= 3.0), libstdc++6 (>= 5), alsa-utils

ax25-xtools
Depends: libc6 (>= 2.14), libfltk1.3 (>= 1.3.1), libgcc-s1 (>= 3.0), libstdc++6 (>= 5), libx11-6

... (stopped list at letter 'b')

Not to mention packages fltk1.1-games and fltk1.3-games, and pinentry-fltk. ;-)


Side note: as you can see, Debian still supports FLTK 1.1 and 1.3.

Albrecht Schlosser

unread,
Mar 22, 2022, 4:41:59 PM3/22/22
to fltkc...@googlegroups.com
On 3/22/22 18:26 Bill Spitzak wrote:
I see no reason you cannot use global variables instead of function calls for these pointers.

Yes, generally you can use global variables but those used today (one name for all platforms) can't be used further because different platforms require different types. As long as you had only one platform active in the build at any time this was no problem (although it made things sometime very complicated).

I've also seen too often that global variables exposed to user ode make later changes almost impossible. The existing global variables (e.g. fl_display) are also user-writable IIRC. All these points are reasons to use accessor functions instead.


The variables are there entirely so that other platform-specific code can use them. You should be able to rename them because all the users of them can change the names as well.

Yes, we can do this. But if we rename them in one step backwards compatibility is gone. We'd have to keep at least both variable names for some time. Exporting accessor functions to these variables makes sure we have full control (read-only) and we can change the function later if required.


I would very very much like to get rid of this idea that the platform is supported by virtual functions, and return to a state where it is controlled by ifdefs which can change how fltk functions are implemented, either by using completely diffferent versions of the functions, or ifdefs inside their internals, which is a very useful feature we lost with this virtual function idea. In particluar it  would allow x-only, wayland-only, and the hybrid version to use the same source code.

No, it wouldn't. In the classic style you have only one platform enabled during compilation. In the future (with a "hybrid" FLTK lib) we'd have more than one platform concurrently. #if ... #elif ... #elif ... #endif does no longer work. We would have to use #if platform-1 (code1) #endif, #if platform-2 (code2) #endif and both platform-1 and platform-2 expressions (e.g. X11 and Wayland) could be active at the same time.

That said, and as I already wrote before: we made a conscious decision to go away from the #ifdef ... style and use the current driver model. This is not going to be reverted. I'm sorry to say that to you, Bill, but that's a fact. One of the main persons in this decision process was Matthias, and the decision was mainly driven by the fact that the old style wouldn't scale to more platforms (we had three at that time).

Meanwhile we removed some experimental platforms (SDL, Pico, Android) and added Wayland. Note that the removal of the experimental platforms was done in minutes, mainly by removing entire directories and editing the two platform specific header files. It would likely have taken days to remove platform specific code from the old-style #ifdef structure by editing all necessary files. This is modularity that helps to maintain the library. The inverse process to add Wayland was mostly done by adding the Wayland specific driver directories with their own virtual driver methods. The only code that was required to support it was a design decision to split the driver base so we had another Fl_Unix_Driver but that's another point.


In addition it is absolutely required that the X11 version be changed to use Cairo rendering.

This is work in progress and will be done.

PS: Bill, please don't top-post here. It's hard to keep the context.

Bill Spitzak

unread,
Mar 22, 2022, 4:57:25 PM3/22/22
to fltkc...@googlegroups.com
On Tue, Mar 22, 2022 at 1:42 PM Albrecht Schlosser <Albrech...@online.de> wrote:
On 3/22/22 18:26 Bill Spitzak wrote:
I see no reason you cannot use global variables instead of function calls for these pointers.

Yes, generally you can use global variables but those used today (one name for all platforms) can't be used further because different platforms require different types. As long as you had only one platform active in the build at any time this was no problem (although it made things sometime very complicated).

I've also seen too often that global variables exposed to user ode make later changes almost impossible. The existing global variables (e.g. fl_display) are also user-writable IIRC. All these points are reasons to use accessor functions instead.

The current design that attempted to reuse the X11 symbol names for similar symbols in other systems is almost certainly a mistake. In particular it means you don't get a linking error if you attempt to use a different backend than fltk was compiled for. What I propose is renaming the symbols to be different for each platform. I don't think the fact that people can write values to them is very important, and fltk itself has to write the value for these somewhere, leaving another global variable that a user can malicioulsly write over anyway. 

The variables are there entirely so that other platform-specific code can use them. You should be able to rename them because all the users of them can change the names as well.

Yes, we can do this. But if we rename them in one step backwards compatibility is gone. We'd have to keep at least both variable names for some time. Exporting accessor functions to these variables makes sure we have full control (read-only) and we can change the function later if required.

I would very very much like to get rid of this idea that the platform is supported by virtual functions, and return to a state where it is controlled by ifdefs which can change how fltk functions are implemented, either by using completely diffferent versions of the functions, or ifdefs inside their internals, which is a very useful feature we lost with this virtual function idea. In particluar it  would allow x-only, wayland-only, and the hybrid version to use the same source code.

No, it wouldn't. In the classic style you have only one platform enabled during compilation. In the future (with a "hybrid" FLTK lib) we'd have more than one platform concurrently. #if ... #elif ... #elif ... #endif does no longer work. We would have to use #if platform-1 (code1) #endif, #if platform-2 (code2) #endif and both platform-1 and platform-2 expressions (e.g. X11 and Wayland) could be active at the same time.

That said, and as I already wrote before: we made a conscious decision to go away from the #ifdef ... style and use the current driver model. This is not going to be reverted. I'm sorry to say that to you, Bill, but that's a fact. One of the main persons in this decision process was Matthias, and the decision was mainly driven by the fact that the old style wouldn't scale to more platforms (we had three at that time).

I agree the current code structure is necessary, where the implementations each live in their own file. The old fltk scheme basically was the X11 version with ifdefs added to it to patch in alternative versions where needed. Instead this should be done like the fltk 2.0 code, where X11 would be in it's own source file, and ifdefs are almost exclusively used to switch which #include statement is compiled, and all the platform code is in that included file. However that platform code *directly* defines the public fltk function.

Using a virtual function table has the annoying fact that it will link all the code into the program whether it is used or not. But more importantly it puts decisions, such as how to modularize the platform-specific code, into public header files and the fltk binary api. This is not a good idea.


Meanwhile we removed some experimental platforms (SDL, Pico, Android) and added Wayland. Note that the removal of the experimental platforms was done in minutes, mainly by removing entire directories and editing the two platform specific header files. It would likely have taken days to remove platform specific code from the old-style #ifdef structure by editing all necessary files. This is modularity that helps to maintain the library. The inverse process to add Wayland was mostly done by adding the Wayland specific driver directories with their own virtual driver methods. The only code that was required to support it was a design decision to split the driver base so we had another Fl_Unix_Driver but that's another point.

In addition it is absolutely required that the X11 version be changed to use Cairo rendering.

This is work in progress and will be done.

PS: Bill, please don't top-post here. It's hard to keep the context.


On Tue, Mar 22, 2022 at 8:14 AM Albrecht Schlosser <Albrech...@online.de> wrote:
On 3/22/22 15:42 Manolo wrote:
Le lundi 21 mars 2022 à 20:31:53 UTC+1, Albrecht Schlosser a écrit :

What to do in FLTK 1.4?

In FLTK 1.4.0 with Wayland support we must ensure that the "Operating System Issues" are documented in a clean and future proof way and that typedefs and globals are not shared between X11 and Wayland modes. Rather than using the globals fl_display etc. we should define functions to access the platform specific variables and objects as required (see suggestion above).

Note that we *MUST* IMHO do this before FLTK 1.4.0 gets released because we couldn't easily go back once it is documented and published.

Defining new, similar functions for the X11 and other platforms would be optional in FLTK 1.4.0 but could be done as well. The "old interface" with typedefs and globals would be deprecated (for legacy applications) and new applications or those that want to be "hybrid" as well and still use platform specific code would have to use the "new interface".


So far my thoughts but this is probably far from complete. It should be a beginning...

Comments and suggestions appreciated.

I appreciate very much this input on this topic because I see it's very important and also complex to solve.

I will look into these proposals and try to implement the beginning for 1.4.0

Thanks for doing this, but please keep in mind that my suggestions are so far only thoughts and theoretical. We'll need to find out if this theory works and then find a migration path for future versions.

I'll try to look into it further to see if I can improve my ideas, but please go ahead, you may know better than I what to do.


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Albrecht Schlosser

unread,
Mar 22, 2022, 5:41:10 PM3/22/22
to fltkc...@googlegroups.com
On 3/22/22 21:57 Bill Spitzak wrote:

On Tue, Mar 22, 2022 at 1:42 PM Albrecht Schlosser <AlbrechtS...> wrote:
On 3/22/22 18:26 Bill Spitzak wrote:
I see no reason you cannot use global variables instead of function calls for these pointers.

Yes, generally you can use global variables but those used today (one name for all platforms) can't be used further because different platforms require different types. As long as you had only one platform active in the build at any time this was no problem (although it made things sometime very complicated).

I've also seen too often that global variables exposed to user ode make later changes almost impossible. The existing global variables (e.g. fl_display) are also user-writable IIRC. All these points are reasons to use accessor functions instead.

The current design that attempted to reuse the X11 symbol names for similar symbols in other systems is almost certainly a mistake.

I agree. But that mistake was done many years ago (AFAICT before I began using FLTK). At that time the Windows port was already available and I believe the old MacOS 8/9 was also available.


In particular it means you don't get a linking error if you attempt to use a different backend than fltk was compiled for.

These symbols are only defined in user code if the user code includes the platform headers. Most FLTK programs don't do that, and since code compiled for Windows can't be executed on macOS anyway I don't see this particular problem. But I agree that it was a bad decision to do that.


What I propose is renaming the symbols to be different for each platform. I don't think the fact that people can write values to them is very important, and fltk itself has to write the value for these somewhere, leaving another global variable that a user can malicioulsly write over anyway.

Only if it's exposed to the user code as a global variable (unless they use random addresses or a wild pointer). I don't meant that the variables should be write protected by the system -- inaccessible by the compilation would suffice.


The variables are there entirely so that other platform-specific code can use them. You should be able to rename them because all the users of them can change the names as well.

Yes, we can do this. But if we rename them in one step backwards compatibility is gone. We'd have to keep at least both variable names for some time. Exporting accessor functions to these variables makes sure we have full control (read-only) and we can change the function later if required.

I would very very much like to get rid of this idea that the platform is supported by virtual functions, and return to a state where it is controlled by ifdefs which can change how fltk functions are implemented, either by using completely diffferent versions of the functions, or ifdefs inside their internals, which is a very useful feature we lost with this virtual function idea. In particluar it  would allow x-only, wayland-only, and the hybrid version to use the same source code.

No, it wouldn't. In the classic style you have only one platform enabled during compilation. In the future (with a "hybrid" FLTK lib) we'd have more than one platform concurrently. #if ... #elif ... #elif ... #endif does no longer work. We would have to use #if platform-1 (code1) #endif, #if platform-2 (code2) #endif and both platform-1 and platform-2 expressions (e.g. X11 and Wayland) could be active at the same time.

That said, and as I already wrote before: we made a conscious decision to go away from the #ifdef ... style and use the current driver model. This is not going to be reverted. I'm sorry to say that to you, Bill, but that's a fact. One of the main persons in this decision process was Matthias, and the decision was mainly driven by the fact that the old style wouldn't scale to more platforms (we had three at that time).

I agree the current code structure is necessary, where the implementations each live in their own file. The old fltk scheme basically was the X11 version with ifdefs added to it to patch in alternative versions where needed. Instead this should be done like the fltk 2.0 code, where X11 would be in it's own source file, and ifdefs are almost exclusively used to switch which #include statement is compiled, and all the platform code is in that included file. However that platform code *directly* defines the public fltk function.

I'm not aware of the code structure of FLTK 2.0, but I'll take a look into the details when time permits. However, with the concept where "ifdefs are almost exclusively used to switch which #include statement is compiled" you are at the same point again: you can't have two different platforms active (compiled in) at the same time. And the maintenance nightmare that you need to edit the main files to #include another platform when such a platform is added (scalability).


Using a virtual function table has the annoying fact that it will link all the code into the program whether it is used or not.

OK, I see and I agree, point taken.

But this is only true for "driver" code (e.g. graphics output, system specific window handling, etc.), not for platform independent stuff that is compiled as separate files like image types (fltk_images library) and other optional components in their own source files.


But more importantly it puts decisions, such as how to modularize the platform-specific code, into public header files and the fltk binary api. This is not a good idea.

These header files are not "public". All driver header files (except one) are in the src/ directory or its subdirectories and can be changed at any time. Without checking the details, I believe that this wouldn't change the ABI (i.e. the /public/ application binary interface) because these details are not exported.

Manolo

unread,
Mar 29, 2022, 1:27:26 PM3/29/22
to fltk.coredev
Here is a complete proposal for a hybrid Wayland/X11 FLTK library ready for  release with FLTK 1.4,
along the line sketched by Albrecht above.
It's available in branch wayland of

It contains support for an environment variable FLTK_BACKEND to pilot what is used at run-time:
- if FLTK_BACKEND is undefined, the library uses wayland if available and x11 otherwise;
- if FLTK_BACKEND = wayland, the library uses Wayland if possible and exits with error otherwise;
- if FLTK_BACKEND = x11, the library uses X11 even if Wayland is available;
- if FLTK_BACKEND has another value, the library exits with an error message.

It contains also function fl_disable_wayland(), to be called early in main(), to force an app to use
X11 without using the FLTK_BACKEND variable, as Albrecht suggested.

Here is a very detailed (and very long) description of changes, their reason, their impact,
for all platform-dependent types and global variables which are part of the FLTK 1.3 public API.
OLD means the public API of FLTK 1.3; NEW means the public API of FLTK 1.4.

Preparing for hybrid FLTK libraries : handling platform-specific types and global variables

===========================================================
fl_display   

OLD
global variable declared in FL/{X11,win32}.H with a platform-specific type

NEW
functions with platform-specific name and platform-specific return type
Wayland: struct wl_display *fl_wl_display();
X11: Display *fl_x11_display();
Windows: HINSTANCE fl_win32_display();
In the hybrid Wayland/X11 library, exactly one of fl_wl_display() and fl_x11_display()
is not null after fl_open_display().

API compatibility between 1.3 and 1.4 :
Deprecated use of global fl_display still possible with X11 and Windows.
Preferred usage is to call new function according to running platform.

===========================================================
fl_gc    

OLD
global variable declared in FL/{X11,win32,mac}.H with platform-specific type

NEW
New documented functions with platform-specific name and platform-specific return type
X11: GC fl_x11_gc();
Windows: HDC fl_win32_gc();
macOS: CGContextRef fl_mac_gc();
Wayland: similar to struct _cairo *fl_wl_cairo();

API compatibility between 1.3 and 1.4 :
Deprecated use of global variale fl_gc is still possible with X11, macOS and Windows.
Recommended usage is to call the new functions according to running platform.

===========================================================
fl_event_time, fl_screen, fl_visual, fl_colormap, fl_message_window, fl_event_time, Fl_X::set_xid()
                 <==== no change needed

They are X11-specific, and stay that way.

===========================================================
fl_msg, fl_GetDC(HDC), fl_makeDC(HBITMAP)    <==== no change needed

They are Windows-specific, and stay that way.

===========================================================
global variable fl_window and type Window    

OLD
global variable (fl_window) with platform-specific type (Window)
Type is declared in system include (X11) and in FL/{mac,win32}.H (Windows and macOS).
Variable is declared in FL/platform.H : extern FL_EXPORT Window fl_window;

Presence in public FLTK API:
Only in the platform-specific (X11, Windows, macOS) OS interface section.
Global variable fl_window is documented only for X11 and Windows OS interfaces.
Fl_Window *fl_find(Window)
Window fl_xid(const Fl_Window*)
one member of class Fl_X (xid) has type Window
Fl_X* Fl_X::set_xid(Fl_Window*, Window); // only for the X11 platform

NEW
Type of member variable Fl_X::xid is changed from Window to fl_uintptr_t
The hybrid Wayland/X11 library defines both FLTK_USE_WAYLAND (in FL/fl_config.h) and
FLTK_USE_X11 (in FL/wayland.H).

Impact on driver code internal to the FLTK library
* in FLTK 1.3, the call fl_find(fl_window) is used across platforms (in src/fl_read_image.c)
to determine whether function fl_read_image() is called to read from the current window
or the current offscreen buffer.
* in FLTK 1.4 this needs change because the Wayland platform doesn't use the fl_window
global variable. A new virtual member function is added to class Fl_Surface_Device:
  virtual Fl_Image_Surface *as_image_surface();
which returns a non-NULL value only for Fl_Image_Surface objects.
With it, function fl_read_image() uses this test
  if (Fl_Surface_Device::surface()->as_image_surface())
to detect whether to read from the current offscreen buffer.

API compatibility between 1.3 and 1.4 :
Old declarations of the Window type and fl_window global variable remain for compatibility
with platforms X11, Windows and macOS.
The Wayland platform uses neither the type (Window) nor the global variable (fl_window),
but the X11 component of the Wayland/X11 hybrid library uses them.

===========================================================
Fl_Window *fl_find(Window)   

OLD
function with platform-specific argument type (Window), single name (fl_find) and
single implementation in src/Fl.cxx
Declared in FL/platform.H

NEW
New, documented, platform-specific functions with platform-specific name and type of argument:
X11: Fl_Window *fl_x11_find(Window);
Windows: Fl_Window *fl_win32_find(HWND);
macOS: Fl_Window *fl_mac_find(FLWindow *);
Wayland: Fl_Window *fl_wl_find(struct wld_window *);

Implementation (shown for X11, similar for other platforms):
Fl_Window *fl_x11_find(Window xid) {
  return Fl_Window_Driver::find((fl_uintptr_t)xid);
}
Fl_Window* fl_find(Window xid) { // for compatibility with FLTK < 1.4
  return Fl_Window_Driver::find((fl_uintptr_t)xid);
}
Fl_Window *Fl_Window_Driver::find(fl_uintptr_t xid) { // no virtual overrides necessary
// *** code that was in Fl::find() in FLTK 1.3 ***
}

Functions fl_<platform>_find() are put in files
scr/drivers/<platform>/fl_<platform>_platform_init.cxx.
For the hybrid Wayland/X11 library, both fl_wl_find() and fl_x11_find() functions are
in file src/drivers/Wayland/fl_wayland_platform_init.cxx

API compatibility between 1.3 and 1.4 :
Fl_Window* fl_find(Window) remains usable with X11, Windows, macOS.
It's not usable under the Wayland platform because this platform doesn't assign values
to the fl_window global. Only fl_wl_find() is effective.

Platform-specific code in FLTK 1.3 app that did, for example
#include <FL/platform.H>
#if FLTK_USE_X11
 Window xwin = fl_window;
 X11_function_with_Window_typed_argument(xwin);
#endif
remains possible.

===========================================================
class Fl_X  

OLD
Declared in FL/platform.H in a platform-independent way but
contains a member (xid) with platform-specific type (Window).
Documentation states "The interfaces provided by this header file may change
radically in new FLTK releases."

NEW
Declared in FL/platform.H in a platform-independent way and
its member (xid) has platform-independent type (fl_uintptr_t).

Impact on driver code internal to the FLTK library
This requires relatively numerous but simple changes in the FLTK driver code:
* In FLTK 1.3, the whole library is built such that Fl_X::xid has type Window for the X11
platform, or type HWND for Windows.
* To support hybrid libraries, the type of Fl_X::xid no longer matches the specific
type of a window on a given platform. Therefore, driver code for a given
platform which uses Fl_X::xid must cast this member variable to the platform's
type. For example, this code internal to a macOS driver member function :
  Fl_X *x = Fl_X::first;
  FLWindow *cw = x->xid;
needs to add a cast operation:
  FLWindow *cw = (FLWindow*)x->xid;
 
Conversely, this code internal to a Windows driver member function needs change too:
  Fl_Window *window = ...
  HWND xid = ...
  Fl_X::i(window)->xid = xid;
needs to add a cast operation:
  Fl_X::i(window)->xid = (fl_uintptr_t)xid;

API compatibility between 1.3 and 1.4 :
Unchanged use of the xid class member as defined in platform.H.

===========================================================
Window fl_xid(const Fl_Window *)   

OLD
function with platform-specific return type (Window), single name (fl_xid)
and single implementation using Fl_X::xid with platform-specific type.
Implemented inline in FL/platform.H or #define'd to fl_xid_(const Fl_Window *)

NEW
New, documented, platform-specific functions with platform-specific name and
type of returned value:
X11: Window fl_x11_xid(const Fl_Window *win);
Windows: HWND fl_win32_xid(const Fl_Window *win);
macOS: FLWindow *fl_mac_xid(const Fl_Window *win);
Wayland: struct wld_window *fl_wl_xid(const Fl_Window *win);

Implementation (shown for X11, similar for each other platform):
Window fl_x11_xid(const Fl_Window *win) {
  return (Window)Fl_Window_Driver::xid(win);
}
fl_uintptr_t Fl_Window_Driver::xid(const Fl_Window *win) { // no virtual overrides necessary
  Fl_X *flx = win->i;
  return flx ? flx->xid : 0;
}

Functions fl_<platform>_xid() are put in files
scr/drivers/<platform>/fl_<platform>_platform_init.cxx.
For the hybrid Wayland/X11 library, both fl_wl_xid() and fl_x11_xid() functions are
in file src/drivers/Wayland/fl_wayland_platform_init.cxx

API compatibility between 1.3 and 1.4 :
Function Window fl_xid(const Fl_Window*) remains usable with X11, Windows, macOS.
It's preferentially not used under the Wayland platform because there, type Window is
meaningful only for the X11 component of the hybrid Wayland/X11 library.
Function fl_wl_xid() is to be used instead.

Platform-specific code in FLTK 1.3 apps that did, for example
#include <FL/platform.H>
#if FLTK_USE_X11
 Fl_Window *window = ...
 Window xid = fl_xid(window);
 X11_function_with_Window_typed_argument(xid);
#endif
remains supported.

===========================================================
Fl_Offscreen   

OLD
platform-dependent type. Often a pointer, but "unsigned long" for X11 platform.
Presence in public FLTK API:
Fl_Offscreen fl_create_offscreen(int, int);
void fl_copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
void fl_begin_offscreen(Fl_Offscreen b);
void fl_delete_offscreen(Fl_Offscreen);
void fl_rescale_offscreen(Fl_Offscreen &);
Fl_Offscreen Fl_Image_Surface::offscreen();
c'tor: Fl_Image_Surface(int w, int h, int high_res = 0, Fl_Offscreen off = 0);

NEW
single type fl_uintptr_t, can hold either a pointer or unsigned long value.
Documentation of the Fl_Offscreen type gives the exact platform-specific types:
   - X11: Pixmap (== unsigned long)
   - Wayland: struct fl_wld_buffer *
   - Windows: HBITMAP
   - macOS: CGContextRef
   
Impact on driver code internal to the FLTK library
This requires relatively numerous but simple changes in the FLTK driver code:
* In FLTK 1.3, the whole library is built such that Fl_Offscreen == ulong for the X11
platform, or such that Fl_Offscreen == HBITMAP for Windows.
* To support hybrid libraries, the Fl_Offscreen type no longer matches the specific
type an offscreen buffer uses on a given platform. Therefore, driver code for a given
platform which receives an Fl_Offscreen argument must cast this quantity to the platform's
type. For example, this function of the X11 driver :
  void Fl_X11_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
should cast the received Fl_Offscreen argument to call XGetGeometry() :
  XGetGeometry(fl_display, (Pixmap)off, &root, &px, &py, &w, &h, &b, &d);


API compatibility between 1.3 and 1.4 :
The public API allows only this :
FLTK produces an Fl_Offscreen object
FLTK uses it
FLTK deletes it.
Thus, replacing, say, unsigned long by fl_uintptr_t does not break API compatibility.

Platform-specific code in an FLTK 1.3 app could do, for example
#include <FL/platform.H>
#ifdef _WIN32
 Fl_Image_Surface *surf = ...
 Fl_Offscreen off = surf->offscreen();
 win32_function_with_HBITMAP_argument(off);
#endif
This should be changed adding a cast operation::
 HBITMAP off = (HBITMAP)surf->offscreen();


===========================================================
GLContext  

OLD
platform-dependent type. Always a pointer.
Presence in public FLTK API:
   GLContext Fl_Gl_Window::context() const ;
   void Fl_Gl_Window::context(GLContext, int destroy_flag = 0);

NEW
typedef void *GLContext;   (in FL/Fl_Gl_Window.H)
The documentation details exact platform-specific types of the pointed structure:
   - X11: GLXContext
   - Wayland: EGLContext
   - Windows: HGLRC
   - macOS: NSOpenGLContext*
   
New, documented, platform-specific functions:
Windows: HGLRC fl_win32_glcontext(GLContext rc) { return (HGLRC)rc; }
X11: GLXContext fl_x11_glcontext(GLContext rc) { return (GLXContext)rc; }
Wayland: EGLContext fl_wayland_glcontext(GLContext rc) { return (EGLContext)rc; }
macOS: NSOpenGLContext *fl_mac_glcontext(GLContext rc) { return (NSOpenGLContext*)rc; }

API compatibility between 1.3 and 1.4 :
No problem in platform-independent code.

A problem arises for platform-specific code of an app that would do, for example:
#include <FL/platform.H>
#ifdef _WIN32
 Fl_Gl_Window *glwin = ...;
 GLContext glcontext = gl_win->context();
 win32_function_with_HGLRC_argument(glcontext);
#endif
It becomes necessary to use function fl_win32_glcontext() :
 HGLRC glcontext = fl_win32_glcontext( gl_win->context() );


===========================================================
Fl_Bitmask  

OLD
platform-dependent type: always a pointer, except for X11 platform with unsigned long.
Not part of any FLTK public API function or global variable.

NEW
Type Fl_Bitmask is no longer used by FLTK.

API compatibility between 1.3 and 1.4 :
No problem because Fl_Bitmask is not used in the public API.

===========================================================
Fl_Region   

OLD
platform-dependent type. Always a pointer.
Presence in public FLTK API:
 Fl_Region fl_clip_region();
 fl_clip_region(Fl_Region);

NEW
single type: typedef void *Fl_Region;
Documentation details exact platform-specific types of the pointed structure:
   - X11: Region
   - Wayland: struct flWaylandRegion *
   - Windows: HRGN
   - macOS:  struct flCocoaRegion *

API compatibility between 1.3 and 1.4 :
No compatibility problem in platform-independent code because no computation
is performed on Fl_Region variables.

A problem would arise for platform-specific code of an app that would do, for example:
#include <FL/platform.H>
#ifdef _WIN32
 Fl_Region r = fl_clip_region();
 win32_function_with_HRGN_argument(r);
#endif
That should be modified to
 HRGN r = (HRGN)fl_clip_region();


===========================================================
FL_SOCKET, fl_intptr_t and fl_uintptr_t   <=== no change needed

These types are determined by the compiler, so they're the same for any
platform on a given OS ==>  no change needed.

===========================================================
struct dirent   <==== no change needed

This type is always the product of #include <dirent.h> except
for the Windows platform compiled with MSVC.
===> all hybrid library combinations possible without change
except for the combination WIN32+X11 with MSVC.

Something will remain to be done later to support a hybrid Windows/X11 library
built with MSVC.

===========================================================
struct stat  <=== no change needed

This type is defined on all platforms by #include <sys/stat.h>
It remains so.

===========================================================
FL_COMMAND, FL_CONTROL   

Replace
#  define FL_COMMAND    FL_CTRL  
#  define FL_CONTROL    FL_META  
(and the reverse for macOS)
by
extern FL_EXPORT int fl_command_modifier();
extern FL_EXPORT int fl_control_modifier();
#  define FL_COMMAND    fl_command_modifier()
#  define FL_CONTROL    fl_control_modifier()

where functions fl_command_modifier() and fl_control_modifier() return FL_CTRL or
FL_META according to the selected platform.




Gonzalo Garramuño

unread,
Mar 29, 2022, 1:51:18 PM3/29/22
to fltkc...@googlegroups.com


El 29/3/22 a las 14:27, Manolo escribió:
Here is a complete proposal for a hybrid Wayland/X11 FLTK library ready for  release with FLTK 1.4,
along the line sketched by Albrecht above.
It's available in branch wayland of

It contains support for an environment variable FLTK_BACKEND to pilot what is used at run-time:
- if FLTK_BACKEND is undefined, the library uses wayland if available and x11 otherwise;
- if FLTK_BACKEND = wayland, the library uses Wayland if possible and exits with error otherwise;
- if FLTK_BACKEND = x11, the library uses X11 even if Wayland is available;
- if FLTK_BACKEND has another value, the library exits with an error message.

It contains also function fl_disable_wayland(), to be called early in main(), to force an app to use
X11 without using the FLTK_BACKEND variable, as Albrecht suggested.

Great work, Manolo!

Bill Spitzak

unread,
Mar 29, 2022, 2:57:08 PM3/29/22
to fltkc...@googlegroups.com
My main comment is that I think "region" is part of the rendering, and you don't seem to have the Cairo version. It may also be ok to scrap support for regions that are not rectangles.

I also feel that part of this would be to make it use Cairo for both X11 and Wayland, and scrap all xlib drawing and especially any API to get at them. This will also remove the need to have server-side offscreen buffers which are completely obsolete and never used by any other software. Cairo (and Windows and Mac) can draw into local memory buffers and these should be used.

--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Albrecht Schlosser

unread,
Mar 29, 2022, 3:29:31 PM3/29/22
to fltkc...@googlegroups.com
On 3/29/22 19:27 Manolo wrote:
Here is a complete proposal for a hybrid Wayland/X11 FLTK library ready for  release with FLTK 1.4,
along the line sketched by Albrecht above.
It's available in branch wayland of

It contains support for an environment variable FLTK_BACKEND to pilot what is used at run-time:
- if FLTK_BACKEND is undefined, the library uses wayland if available and x11 otherwise;
- if FLTK_BACKEND = wayland, the library uses Wayland if possible and exits with error otherwise;
- if FLTK_BACKEND = x11, the library uses X11 even if Wayland is available;
- if FLTK_BACKEND has another value, the library exits with an error message.

It contains also function fl_disable_wayland(), to be called early in main(), to force an app to use
X11 without using the FLTK_BACKEND variable, as Albrecht suggested.

Here is a very detailed (and very long) description of changes, their reason, their impact,
for all platform-dependent types and global variables which are part of the FLTK 1.3 public API.
OLD means the public API of FLTK 1.3; NEW means the public API of FLTK 1.4.

Manolo, thank you very much for this great work and the informative description. I'll try to look into the details tomorrow (Wed) or on Thursday.

I'm picking only a few statements where I have questions or annotations for my comment(s) below. Everything else looks good and clear so far from reading.


Functions fl_<platform>_find() are put in files
scr/drivers/<platform>/fl_<platform>_platform_init.cxx.
For the hybrid Wayland/X11 library, both fl_wl_find() and fl_x11_find() functions are
in file src/drivers/Wayland/fl_wayland_platform_init.cxx

I'm wondering why these functions are not in separate, i.e. their own per-platform files. However, I did not look at the code yet...

...


Platform-specific code in FLTK 1.3 app that did, for example
#include <FL/platform.H>
#if FLTK_USE_X11
 Window xwin = fl_window;
 X11_function_with_Window_typed_argument(xwin);
#endif
remains possible.

In FLTK 1.3 we didn't have FLTK_USE_X11 yet. As I described before user code would very likely handle the X11 platform in the #else clause which has been a big problem of FLTK up to 1.3.x (IIRC Bill wrote that this was solved for 2.0 as well).

So, what we need to have would be that code like the following would still work:

#if defined(_WIN32)
  ... windows code
#elif defined (__APPLE__)
  ... macOS code
#else
  ... X11 specific code
#endif

Such "legacy programs" would presumably need to call fl_disable_wayland() which would definitely be a (minor) source code change, but then ... would they work w/o other changes if they only used X11 specific code like in 1.3 in the #else clause?

This would be a great achievement for migration from 1.3 to 1.4 while still being able to use a hybrid FLTK library.



FL_SOCKET, fl_intptr_t and fl_uintptr_t   <=== no change needed

The definition of FL_SOCKET and its usage in the public API is a problem of its own, but this has nothing to do with the introduction of Wayland or the hybrid FLTK library, so yes, no change needed here (now).

Everything else looks really good (by reading your description). Great Job!

Manolo

unread,
Mar 30, 2022, 4:02:19 AM3/30/22
to fltk.coredev
Le mardi 29 mars 2022 à 21:29:31 UTC+2, Albrecht Schlosser a écrit :

I'm picking only a few statements where I have questions or annotations for my comment(s) below. Everything else looks good and clear so far from reading.
Functions fl_<platform>_find() are put in files
scr/drivers/<platform>/fl_<platform>_platform_init.cxx.
For the hybrid Wayland/X11 library, both fl_wl_find() and fl_x11_find() functions are
in file src/drivers/Wayland/fl_wayland_platform_init.cxx
I'm wondering why these functions are not in separate, i.e. their own per-platform files. However, I did not look at the code yet...
That's right. I've now moved a bunch of such functions to per-platform driver files.

Platform-specific code in FLTK 1.3 app that did, for example
#include <FL/platform.H>
#if FLTK_USE_X11
 Window xwin = fl_window;
 X11_function_with_Window_typed_argument(xwin);
#endif
remains possible.

In FLTK 1.3 we didn't have FLTK_USE_X11 yet. As I described before user code would very likely handle the X11 platform in the #else clause which has been a big problem of FLTK up to 1.3.x (IIRC Bill wrote that this was solved for 2.0 as well).

So, what we need to have would be that code like the following would still work:

#if defined(_WIN32)
  ... windows code
#elif defined (__APPLE__)
  ... macOS code
#else
  ... X11 specific code
#endif

Such "legacy programs" would presumably need to call fl_disable_wayland() which would definitely be a (minor) source code change, but then ... would they work w/o other changes if they only used X11 specific code like in 1.3 in the #else clause?

This would be a great achievement for migration from 1.3 to 1.4 while still being able to use a hybrid FLTK library.
I've just been lazy to write the full series of #if defined() directives.
The new code is intended to support the old writing without FLTK_USE_X11, because the new wayland.H includes X11/xlib.h.
Pre-existing 1.3 source code should run without change with the hybrid library, activate Wayland if it's present,
but loose in that situation the effects of any X11-specific source code they would contain.
With the single addition of a call to fl_disable_wayland(), it should run just as with an FLTK 1.3 library, but acquire HighDPI support,
as you had planed.  That would also be possible without the fl_disable_wayland() call, setting FLTK_BACKEND=x11.

Manolo

unread,
Mar 30, 2022, 4:48:40 AM3/30/22
to fltk.coredev
Le mardi 29 mars 2022 à 20:57:08 UTC+2, spi...@gmail.com a écrit :
My main comment is that I think "region" is part of the rendering, and you don't seem to have the Cairo version. It may also be ok to scrap support for regions that are not rectangles.
Thanks for this comment. I had not realized the Cairo version of Fl_Region support is missing and will look into that.
 

I also feel that part of this would be to make it use Cairo for both X11 and Wayland, and scrap all xlib drawing and especially any API to get at them. This will also remove the need to have server-side offscreen buffers which are completely obsolete and never used by any other software. Cairo (and Windows and Mac) can draw into local memory buffers and these should be used.
Indeed, the hybrid Wayland/X11 library could use cairo-only rendering for its X11 backend.
Let's see what other developers think.

Lauri Kasanen

unread,
Mar 30, 2022, 10:51:57 AM3/30/22
to fltkc...@googlegroups.com
On Wed, 30 Mar 2022 01:48:40 -0700 (PDT)
Manolo <manol...@gmail.com> wrote:

> Indeed, the hybrid Wayland/X11 library could use cairo-only rendering for
> its X11 backend.
> Let's see what other developers think.

Is it any large maintenance overhead, the X drawing? In the interest of
size, we'd like to keep X drawing available and cairo not mandatory.
(We'd of course also disable wayland)

OTOH if this is for 1.5 which will get released in 10 years, then it
doesn't matter as much. If the releases are going to flow faster, then
I'd request to keep X drawing at least for a couple years with a
deprecation notice before removing it.

- Lauri

imacarthur

unread,
Mar 30, 2022, 11:21:02 AM3/30/22
to fltk.coredev
On Wednesday, 30 March 2022 at 15:51:57 UTC+1 Lauri wrote:
On Wed, 30 Mar 2022 01:48:40 -0700 (PDT)
Manolo wrote:

> Indeed, the hybrid Wayland/X11 library could use cairo-only rendering for
> its X11 backend.
> Let's see what other developers think.

Is it any large maintenance overhead, the X drawing? In the interest of
size, we'd like to keep X drawing available and cairo not mandatory.
(We'd of course also disable wayland)


Lauri makes a fair point - I too have a handful of "embedded" systems running some or other cut-down Linux, and in general they only have X11 as a render option (at least one actually has an xf86 server, albeit now running on arm, but I think that gives a sense of how "old" some of these environments are...)

So losing the X11 backend would not be ideal, though of course I still have 1.3...

<OT>
As something of an aside, talking to one of the board vendors a while back, it became apparent that the next iteration of their SBC would probably not have any X11 server, or indeed anything other than some sort of OpenGL-ES surface (I had the sense that a lot of what is available for them to use is driven by the folks making mobile phones and similar devices, as that drives the volume in the market, and that GL-ES seems popular there, or something. I dunno. I don't know GL-ES, but assume it is not just GL...) 
So, anyway, at that point, I guess I *would* need something else... Can Cairo render directly to GL-ES for me, for example? And what do I do about a WM in that circumstance (if I need one, that is...)
</OT>
 

Lauri Kasanen

unread,
Mar 30, 2022, 11:42:11 AM3/30/22
to fltkc...@googlegroups.com
On Wed, 30 Mar 2022 08:21:02 -0700 (PDT)
imacarthur <imaca...@gmail.com> wrote:

> <OT>
> As something of an aside, talking to one of the board vendors a while back,
> it became apparent that the next iteration of their SBC would probably not
> have any X11 server, or indeed anything other than some sort of OpenGL-ES
> surface (I had the sense that a lot of what is available for them to use is
> driven by the folks making mobile phones and similar devices, as that
> drives the volume in the market, and that GL-ES seems popular there, or
> something. I dunno. I don't know GL-ES, but assume it is not just GL...)
> So, anyway, at that point, I guess I *would* need something else... Can
> Cairo render directly to GL-ES for me, for example? And what do I do about
> a WM in that circumstance (if I need one, that is...)
> </OT>

That does not really matter. You can upload a sw-rendered picture to
that GL-ES surface. Which differs from previous, sw-rendered X11 only
in the upload path.

IOW: it's a very simple matter to adapt X to running on your GLES
board. Probably some dozen lines of code, though would have to be
written by someone who knows X and GLES.

- Lauri

Bill Spitzak

unread,
Mar 30, 2022, 3:25:29 PM3/30/22
to fltkc...@googlegroups.com
If the hybrid version is capable of running at all, it is capable of using Cairo to render into a local image. If you really can't use cairo, this hybrid version will be missing libraries needed to execute and will not work. I think also there will be problems with graphics differences between Cairo and X11 output.


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Albrecht Schlosser

unread,
Mar 30, 2022, 5:27:35 PM3/30/22
to fltkc...@googlegroups.com
On 3/30/22 17:21 imacarthur wrote:
On Wednesday, 30 March 2022 at 15:51:57 UTC+1 Lauri wrote:
On Wed, 30 Mar 2022 01:48:40 -0700 (PDT)
Manolo wrote:

> Indeed, the hybrid Wayland/X11 library could use cairo-only rendering for
> its X11 backend.
> Let's see what other developers think.

I personally think that having the *option* to use Cairo rendering for the X11 backend would be great (and Manolo did already post a prototype) but I never thought of removing the "plain old X11" option for the upcoming FLTK 1.4.x releases.


Is it any large maintenance overhead, the X drawing? In the interest of
size, we'd like to keep X drawing available and cairo not mandatory.
(We'd of course also disable wayland)

FLTK 1.4.0 must be a straight forward step from 1.3.x (currently 1.3.8 which will likely be the last 1.3.x release unless we pick up the few additional commits and make a 1.3.9 final release or we need one for serious bug fixes or whatever).

Therefore 1.4.0 will consequently have to be as much backward compatible (API wise) as possible. All main additional features, for instance Wayland support and Cairo rendering on X11 *must* IMHO be options that can be switched on or off selectively but we need to make a decision about each option's default setting.

I'm thinking about making the release default to the hybrid Wayland/X11 system but then users would still be able to select X11 only. The reason I would like to have this as the default is that I believe that Linux distributions would be "guided" to use the hybrid system automatically (all options == default) which is what we're discussing here. But the final decision about this is to be discussed when it is available.


Lauri makes a fair point - I too have a handful of "embedded" systems running some or other cut-down Linux, and in general they only have X11 as a render option (at least one actually has an xf86 server, albeit now running on arm, but I think that gives a sense of how "old" some of these environments are...)

So losing the X11 backend would not be ideal, though of course I still have 1.3...

I think there's no need to worry about losing the standard X11 backend, at least for the 1.4.x series. There's no real reason to strip it off or replace it. In fact to do that would take much more time and testing than we have to release 1.4.0. Sure, we still need some time. The schedule to release 1.4.0 during April 2022 was probably a bit too optimistic, but anyway: 1.4.0 should be released ASAP and I'm working on it as much as I can do. Having the Wayland port in 1.4 is IMHO worth a delay.

For the near future I hope that we can release more often but I don't think that we should change or remove any options during the 1.4.x release series.

However, I'm also suggesting to make the current Pango option the default on Linux/X11 because it is the best text rendering we can have and it would reduce questions about fonts not rendering asian and other text properly. IIRC this would also be what the Wayland platform uses and would thus give us the most compatibility between the two Linux platforms.

Additionally I could imagine to remove the (mostly 1.x) option to build FLTK w/o Xft which is really ugly from today's point of view that I think we can leave this option to 1.3.x users.

But sorry, this is going OT here, although it's slightly related to the build options of a "hybrid" FLTK library. Too many options make the maintenance much more difficult and I believe it's OK to remove old, probably not often used options in favor of the new (Pango, Cairo, Wayland) variants.

Bill Spitzak

unread,
Mar 30, 2022, 8:28:46 PM3/30/22
to fltkc...@googlegroups.com
I just feel that the joint Wayland/X11 version will be much much easier if the drawing library does not have to change depending on whether Wayland is in use or not. It may still make sense to compile an X11-only version that uses Xlib drawing, just make compiling the Wayland+X11 version cause Cairo to be used for both.


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Manolo

unread,
Mar 31, 2022, 10:07:36 AM3/31/22
to fltk.coredev
It's of course necessary to maintain in FLTK 1.4 an X11-only version of the code.
That's necessary for relatively old systems because Wayland requires recent Linux versions.
That's also necessary for Unix-but-not-Linux systems (e.g., NetBSD, FreeBSD, Darwin) because there's no Wayland outside Linux at this point.

One possibility to be considered could be as follows:

FLTK 1.4 would propose two "platforms" for Unix systems

1) the X11 platform, as it's now in the git repo. It would be usable on a large set of systems, Linux or Unix, old or new, Darwin, Cygwin.

2) a new in 1.4 platform which would be for recent Linux systems only, and would be a hybrid library with Wayland and X11 backends. Both backends would draw with Cairo and use Pango for text.
That would be a merge of the present wayland and display-cairo branches.
Maintainers of the FLTK packages in Linux distributions could be told to consider using this platform for FLTK 1.4 and above.
It would be produced with OPTION_USE_WAYLAND under CMake or with ./configure --enable-wayland

Albrecht Schlosser

unread,
Mar 31, 2022, 12:36:28 PM3/31/22
to fltkc...@googlegroups.com
+1

I believe this is the way to go. As Bill suggested, making the "hybrid"
FLTK library draw with Cairo in both environments (X11 and Wayland)
appears to be the optimal way, particularly because it would (hopefully)
be easier to maintain but also for better compatibility between the X11
and Wayland environments.

One other option I'd like to be considered is the possibility to use the
"classic" X11 platform (i.e. the X11-only FLTK lib) with Cairo as the
drawing interface. This could be a configure/CMake option, I don't think
we'd need both in one X11 only FLTK lib (the default would be X11
drawing as written above).

Bill Spitzak

unread,
Mar 31, 2022, 12:37:29 PM3/31/22
to fltkc...@googlegroups.com
Yes, that is what I think is correct. "Wayland support" pretty much requires "Wayland + X11 support" as Wayland-only is not going to work in too many situations and is a pita for the user if they have to run in both. But absolutely as much code should be shared as possible, which means they should both use Cairo, I would also make X11 draw into a local buffer (not sure how this gets done) as this matches how it works on Wayland, and is much faster.

I'm also wondering if there are tricks that could be used to get the windows positioned using the Xlib api, while using Cairo for everything else.

--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Bill Spitzak

unread,
Mar 31, 2022, 12:39:10 PM3/31/22
to fltkc...@googlegroups.com
I would think if the Wayland+X11+Cairo version is made, it would not be hard to make a (no-Wayland) X11+Cairo version as well.

--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Manolo

unread,
Apr 5, 2022, 9:14:06 AM4/5/22
to fltk.coredev
These things are now available in the wayland branch of my fltk fork

CMake OPTION_USE_WAYLAND produces a hybrid Wayland/X11 library
whose X11 leg draws with Cairo.

The new OPTION_CAIROXLIB produces a X11 library using Cairo to draw
to X11 windows and to offscreen buffers.

OPTION_USE_PANGO produces a X11 library using Xlib to draw and Pango to draw text.

The default run produces a X11 library using Xlib to draw and Xft to draw text.

My proposal would be to use that for FLTK 1.4.
 

Bill Spitzak

unread,
Apr 5, 2022, 3:04:22 PM4/5/22
to fltkc...@googlegroups.com
This sounds like exactly what is needed and wanted. I might change the second option name to OPTION_USE_CAIRO for consistency with the others


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

Ian MacArthur

unread,
Apr 5, 2022, 3:33:46 PM4/5/22
to fltkc...@googlegroups.com
On 5 Apr 2022, at 20:04, Bill Spitzak wrote:
>
> This sounds like exactly what is needed and wanted. I might change the second option name to OPTION_USE_CAIRO for consistency with the others

I think we already have that name used for the switch that enables the Cairo window wrappers, though, so OPTION_CAIROXLIB is probably OK?


Bill Spitzak

unread,
Apr 5, 2022, 4:23:08 PM4/5/22
to fltkc...@googlegroups.com
What are "Cairo window wrappers"?


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.

imacarthur

unread,
Apr 6, 2022, 3:27:47 AM4/6/22
to fltk.coredev
On Tuesday, 5 April 2022 at 21:23:08 UTC+1 Bill wrote:
What are "Cairo window wrappers"?



Though, that said, I think the option I had in mind is actually OPTION_CAIRO rather than OPTION_USE_CAIRO, so I was basically wrong...

And Manolo may have altered some or all of that anyway with the recent work, there's a lot of improvements in the fltk Cairo stuff generally so my "knowledge" of this is probably archaic (i.e. wrong) now and I never much cared for the Cairo integration that we had anyway (such as it was...)

Albrecht Schlosser

unread,
Apr 6, 2022, 12:58:21 PM4/6/22
to fltkc...@googlegroups.com
On 4/5/22 21:04 Bill Spitzak wrote:
This sounds like exactly what is needed and wanted. I might change the second option name to OPTION_USE_CAIRO for consistency with the others

I agree with Bill that OPTION_USE_CAIRO would be a better name for the option to use Cairo drawing ((currently) in Xlib context (only)) [1] as he said, for consistency.

The "other" existing Cairo options 'OPTION_CAIRO' and 'OPTION_CAIROEXT' are the same as these for configure:

  --enable-cairo          use Cairo library
  --enable-cairoext       use FLTK code instrumentation for cairo extended use

which, as Ian said, are used to feature Fl_Cairo_Window (--enable-cairo) and Cairo usage in all window types (--enable-cairoext) if requested on all platforms (not only Unix/X11/Wayland).

We need to keep those because they are useful on all platforms, although the are probably rarely used. I'm not keen on having these configure/CMake options because they can only be used if users build their own FLTK libs (I don't think they would be configured in stock Linux distros, for instance). I would prefer another way to support users that need such Cairo integration (w/o configuring the FLTK library) but that is not going to work in 1.4.0, hence we need to stick with these for now.

Good (better) documentation for these three options ('OPTION_CAIRO', 'OPTION_CAIROEXT', 'OPTION_USE_CAIRO') would be necessary.


[1] I wrote "(currently) in Xlib context (only) because this could be used on other platforms too if we wanted. Although the native (Windows, macOS) drawing would likely be more efficient



On Tue, Apr 5, 2022 at 6:14 AM Manolo <manol...@gmail.com> wrote:


 [...]

Manolo

unread,
Apr 7, 2022, 9:03:59 AM4/7/22
to fltk.coredev
Le mardi 5 avril 2022 à 21:04:22 UTC+2, spi...@gmail.com a écrit :
This sounds like exactly what is needed and wanted. I might change the second option name to OPTION_USE_CAIRO for consistency with the others

I have renamed the option which is now  OPTION_USE_CAIRO and tried to improve the description of Cairo-related options.

This leaves us with 3 cairo-related options :
OPTION_CAIRO             add support for Fl_Cairo_Window
OPTION_CAIROEXT      use FLTK code instrumentation for Cairo extended use
OPTION_USE_CAIRO    all drawing to X11 windows uses Cairo

Since OPTION_CAIRO is really nothing but opening support for class Fl_Cairo_Window, I would propose to rename it
OPTION_FL_CAIRO_WINDOW. OPTION_CAIROEXT could become OPTION_FL_CAIRO_WINDOW_EXT.
This would hopefully improve understanding the difference between the  options.

Comments ?

Lauri Kasanen

unread,
Apr 7, 2022, 10:37:08 AM4/7/22
to fltkc...@googlegroups.com
On Thu, 7 Apr 2022 06:03:59 -0700 (PDT)
Manolo <manol...@gmail.com> wrote:

> OPTION_USE_CAIRO all drawing to X11 windows uses Cairo

OPTION_DRAW_WITH_CAIRO

- Lauri

Albrecht Schlosser

unread,
Apr 9, 2022, 11:46:36 AM4/9/22
to fltkc...@googlegroups.com
On 4/7/22 15:03 Manolo wrote:

I have renamed the option which is now  OPTION_USE_CAIRO and tried to improve the description of Cairo-related options.

This leaves us with 3 cairo-related options :
OPTION_CAIRO             add support for Fl_Cairo_Window
OPTION_CAIROEXT      use FLTK code instrumentation for Cairo extended use
OPTION_USE_CAIRO    all drawing to X11 windows uses Cairo

Since OPTION_CAIRO is really nothing but opening support for class Fl_Cairo_Window, I would propose to rename it
OPTION_FL_CAIRO_WINDOW. OPTION_CAIROEXT could become OPTION_FL_CAIRO_WINDOW_EXT.
This would hopefully improve understanding the difference between the  options.

Comments ?

-1: Please don't do this.

We should leave the old option names as is for backwards compatibility with long standing FLTK 1.3 projects. These names also correspond to similarly named configure options '--enable-cairo' and '--enable-cairoext'. If we changed these names all users (developers) relying on the old names would have to change their build systems.

The explanatory text may be changed but it's important to improve the documentation (currently in README.Cairo.txt only ?) to make clear what these options are doing.

OPTION_CAIRO ('--enable-cairo') is probably the most used option of these two options (if any). We have working examples for this.

OPTION_CAIROEXT ('--enable-cairoext') is probably less known and much less used and thus less important. I believe we don't have example code for this anyway. Maybe nobody uses it.

Reply all
Reply to author
Forward
0 new messages