FLTK logo

Re: [fltk.coredev] Exploration: FLTK platform compatible with both Wayland and X11

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.coredev  ]
 
Previous Message ]New Message | Reply ]Next Message ]

Re: Exploration: FLTK platform compatible with both Wayland and X11 Manolo Mar 29, 2022  
 
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
   https://github.com/ManoloFLTK/fltk

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.




--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/80c2a8fe-e146-4e90-ab2d-74569faa0b51n%40googlegroups.com.
Direct Link to Message ]
 
     
Previous Message ]New Message | Reply ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.