summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authormaxim nikonov <maxim.nikonov@hqo.co>2026-02-05 15:21:34 +0500
committermaxim nikonov <maxim.nikonov@hqo.co>2026-02-05 15:21:34 +0500
commitdb214d1145e46d527a46d1fc2519548d2c4d23f1 (patch)
treecf0fd9922e4d54f6beb63888f9b28c8e2a787bdf /src/drivers
parent75fc94d6c71fe686f6dde5b41ad91cba2f6bdd6f (diff)
wip: fork
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H2
-rw-r--r--src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx2
-rw-r--r--src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx2
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H60
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm527
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Pen_Events.mm439
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm455
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H114
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx434
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H168
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx294
-rw-r--r--src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H51
-rw-r--r--src/drivers/Darwin/Fl_Darwin_System_Driver.H85
-rw-r--r--src/drivers/Darwin/Fl_Darwin_System_Driver.cxx339
-rw-r--r--src/drivers/Darwin/fl_macOS_platform_init.cxx59
-rw-r--r--src/drivers/GDI/Fl_Font.H43
-rw-r--r--src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H35
-rw-r--r--src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx95
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.H230
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx322
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx89
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx259
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx678
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx826
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx111
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx320
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx231
-rw-r--r--src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H44
-rw-r--r--src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx169
-rw-r--r--src/drivers/PostScript/Fl_PostScript.cxx8
-rw-r--r--src/drivers/PostScript/Fl_PostScript_image.cxx2
-rw-r--r--src/drivers/Quartz/Fl_Font.H42
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H39
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx71
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H149
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx133
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx65
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx70
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx561
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx284
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx83
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx310
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx98
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H38
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx167
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H34
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx60
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H62
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx486
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H72
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx310
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H40
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx185
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.H193
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx2204
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.H185
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx2191
-rw-r--r--src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx741
-rw-r--r--src/drivers/Wayland/fl_wayland_platform_init.cxx157
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H62
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx472
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx518
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx518
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H104
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx493
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.H124
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx1134
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H131
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx731
-rw-r--r--src/drivers/WinAPI/fl_WinAPI_platform_init.cxx85
-rw-r--r--src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx2
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H2
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx2
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H2
74 files changed, 11 insertions, 19892 deletions
diff --git a/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H b/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
index eee10900d..ca0cf5095 100644
--- a/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
+++ b/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
@@ -23,7 +23,7 @@
#include <FL/Fl_Graphics_Driver.H>
#include "../../Fl_Scalable_Graphics_Driver.H" // Fl_Font_Descriptor
-#include <cairo/cairo.h>
+#include <cairo.h>
typedef struct _PangoLayout PangoLayout;
typedef struct _PangoContext PangoContext;
diff --git a/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx b/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
index 236a677b1..bf2e2d361 100644
--- a/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
+++ b/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
@@ -26,7 +26,7 @@
#include <FL/platform.H>
#include <FL/fl_draw.H>
#include <FL/fl_utf8.h>
-#include <cairo/cairo.h>
+#include <cairo.h>
#include <pango/pangocairo.h>
#if ! PANGO_VERSION_CHECK(1,16,0)
# error "Requires Pango 1.16 or higher"
diff --git a/src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx b/src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx
index ed04d1167..a400460d8 100644
--- a/src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx
+++ b/src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx
@@ -20,7 +20,7 @@
#include "Fl_X11_Cairo_Graphics_Driver.H"
#include <FL/platform.H>
-#include <cairo/cairo.h>
+#include <cairo.h>
#include <pango/pangocairo.h>
#include <stdlib.h>
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
deleted file mode 100644
index d5ba9c21c..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#if HAVE_GL
-#include <FL/platform.H>
-#include "../../Fl_Gl_Window_Driver.H"
-
-class Fl_Gl_Choice;
-#ifdef __OBJC__
- @class NSOpenGLContext;
-#else
- class NSOpenGLContext;
-#endif
-
-class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
- NSOpenGLContext *gl1ctxt; // GL1 context in addition to GL3 context
- friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *);
- Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win);
- float pixels_per_unit() FL_OVERRIDE;
- void before_show(int& need_after) FL_OVERRIDE;
- void after_show() FL_OVERRIDE;
- int mode_(int m, const int *a) FL_OVERRIDE;
- void make_current_before() FL_OVERRIDE;
- void swap_buffers() FL_OVERRIDE;
- void resize(int is_a_resize, int w, int h) FL_OVERRIDE;
- char swap_type() FL_OVERRIDE;
- void swap_interval(int) FL_OVERRIDE;
- int swap_interval() const FL_OVERRIDE;
- Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE;
- GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE;
- void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE;
- void delete_gl_context(GLContext) FL_OVERRIDE;
- void make_overlay_current() FL_OVERRIDE;
- void redraw_overlay() FL_OVERRIDE;
- void gl_start() FL_OVERRIDE;
- char *alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs) FL_OVERRIDE;
- Fl_RGB_Image* capture_gl_rectangle(int x, int y, int w, int h) FL_OVERRIDE;
- bool need_scissor() FL_OVERRIDE { return true; }
- void* GetProcAddress(const char *procName) FL_OVERRIDE;
- void apply_scissor();
- void switch_to_GL1() FL_OVERRIDE;
- void switch_back() FL_OVERRIDE;
-};
-
-
-#endif // HAVE_GL
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm b/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm
deleted file mode 100644
index 561aa2ce5..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm
+++ /dev/null
@@ -1,527 +0,0 @@
-//
-// Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#if HAVE_GL
-#include <FL/platform.H>
-#include <FL/gl.h>
-#include "../../Fl_Gl_Choice.H"
-#include "../../Fl_Screen_Driver.H"
-#include "Fl_Cocoa_Window_Driver.H"
-#include "Fl_Cocoa_Gl_Window_Driver.H"
-#include <FL/Fl_Graphics_Driver.H>
-#include <OpenGL/OpenGL.h>
-#include <FL/Fl_Image_Surface.H>
-#include <dlfcn.h>
-
-#import <Cocoa/Cocoa.h>
-
-/* macOS offers only core contexts when using GL3. This forbids to draw
- FLTK widgets in a GL3-using NSOpenGLContext because these widgets are drawn
- with the GL1-based Fl_OpenGL_Graphics_Driver. The solution implemented here
- is to create an additional NSView and an associated additional NSOpenGLContext
- (gl1ctxt) placed above and sized as the GL3-based window, to set the new
- NSOpenGLContext non opaque and GL1-based, and to draw the FLTK widgets in the
- new view/GL1 context.
- */
-
-// Describes crap needed to create a GLContext.
-class Fl_Cocoa_Gl_Choice : public Fl_Gl_Choice {
- friend class Fl_Cocoa_Gl_Window_Driver;
-private:
- NSOpenGLPixelFormat* pixelformat;
-public:
- Fl_Cocoa_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) {
- pixelformat = NULL;
- }
-};
-
-
-Fl_Cocoa_Gl_Window_Driver::Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) :
- Fl_Gl_Window_Driver(win) {
- gl1ctxt = NULL;
-}
-
-
-Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
-{
- return new Fl_Cocoa_Gl_Window_Driver(w);
-}
-
-
-static NSOpenGLPixelFormat* mode_to_NSOpenGLPixelFormat(int m, const int *alistp)
-{
- NSOpenGLPixelFormatAttribute attribs[32];
- int n = 0;
- // AGL-style code remains commented out for comparison
- if (!alistp) {
- if (m & FL_INDEX) {
- //list[n++] = AGL_BUFFER_SIZE; list[n++] = 8;
- } else {
- //list[n++] = AGL_RGBA;
- //list[n++] = AGL_GREEN_SIZE;
- //list[n++] = (m & FL_RGB8) ? 8 : 1;
- attribs[n++] = NSOpenGLPFAColorSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 32 : 1);
- if (m & FL_ALPHA) {
- //list[n++] = AGL_ALPHA_SIZE;
- attribs[n++] = NSOpenGLPFAAlphaSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 8 : 1);
- }
- if (m & FL_ACCUM) {
- //list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1;
- attribs[n++] = NSOpenGLPFAAccumSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
- if (m & FL_ALPHA) {
- //list[n++] = AGL_ACCUM_ALPHA_SIZE; list[n++] = 1;
- }
- }
- }
- if (m & FL_DOUBLE) {
- //list[n++] = AGL_DOUBLEBUFFER;
- attribs[n++] = NSOpenGLPFADoubleBuffer;
- }
- if (m & FL_DEPTH32) {
- //list[n++] = AGL_DEPTH_SIZE; list[n++] = 32;
- attribs[n++] = NSOpenGLPFADepthSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)32;
- } else if (m & FL_DEPTH) {
- //list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
- attribs[n++] = NSOpenGLPFADepthSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)24;
- }
- if (m & FL_STENCIL) {
- //list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
- attribs[n++] = NSOpenGLPFAStencilSize;
- attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
- }
- if (m & FL_STEREO) {
- //list[n++] = AGL_STEREO;
- attribs[n++] = 6/*NSOpenGLPFAStereo*/;
- }
- if (m & FL_MULTISAMPLE) {
- attribs[n++] = NSOpenGLPFAMultisample; // 10.4
- attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = (NSOpenGLPixelFormatAttribute)1;
- attribs[n++] = NSOpenGLPFASamples; attribs[n++] = (NSOpenGLPixelFormatAttribute)4;
- }
- attribs[n++] = NSOpenGLPFAOpenGLProfile;
- attribs[n++] = (m & FL_OPENGL3) ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy;
- } else {
- while (alistp[n] && n < 30) {
- attribs[n] = (NSOpenGLPixelFormatAttribute)alistp[n];
- n++;
- }
- }
- attribs[n] = (NSOpenGLPixelFormatAttribute)0;
- NSOpenGLPixelFormat *pixform = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
- /*GLint color,alpha,accum,depth;
- [pixform getValues:&color forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0];
- [pixform getValues:&alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0];
- [pixform getValues:&accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:0];
- [pixform getValues:&depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0];
- NSLog(@"color=%d alpha=%d accum=%d depth=%d",color,alpha,accum,depth);*/
- return pixform;
-}
-
-
-Fl_Gl_Choice *Fl_Cocoa_Gl_Window_Driver::find(int m, const int *alistp)
-{
- Fl::screen_driver()->open_display(); // useful when called through gl_start()
- Fl_Cocoa_Gl_Choice *g = (Fl_Cocoa_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp);
- if (g) return g;
- NSOpenGLPixelFormat* fmt = mode_to_NSOpenGLPixelFormat(m, alistp);
- if (!fmt) return 0;
- g = new Fl_Cocoa_Gl_Choice(m, alistp, first);
- first = g;
- g->pixelformat = fmt;
- return g;
-}
-
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-# define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
-#endif
-
-static void remove_gl_context_opacity(NSOpenGLContext *ctx) {
- GLint gl_opacity;
- [ctx getValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
- if (gl_opacity != 0) {
- gl_opacity = 0;
- [ctx setValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
- }
-}
-
-
-static NSOpenGLContext *create_GLcontext_for_window(
- NSOpenGLPixelFormat *pixelformat,
- NSOpenGLContext *shared_ctx, Fl_Window *window)
-{
- NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx];
- if (shared_ctx && !context) context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:nil];
- if (context) {
- NSView *view = [fl_xid(window) contentView];
- [view setWantsBestResolutionOpenGLSurface:(Fl::use_high_res_GL() != 0)];
- [context setView:view];
- if (Fl_Cocoa_Window_Driver::driver(window)->subRect()) {
- remove_gl_context_opacity(context);
- }
- }
- return context;
-}
-
-GLContext Fl_Cocoa_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) {
- GLContext context, shared_ctx = 0;
- if (context_list && nContext) shared_ctx = context_list[0];
- // resets the pile of string textures used to draw strings
- // necessary before the first context is created
- if (!shared_ctx) gl_texture_reset();
- context = create_GLcontext_for_window(((Fl_Cocoa_Gl_Choice*)g)->pixelformat, (NSOpenGLContext*)shared_ctx, window);
- if (!context) return 0;
- add_context(context);
- [(NSOpenGLContext*)context makeCurrentContext];
- glClearColor(0., 0., 0., 1.);
- apply_scissor();
- return (context);
-}
-
-void Fl_Cocoa_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) {
- NSOpenGLContext *current_context = [NSOpenGLContext currentContext];
- if (context != current_context || w != cached_window) {
- cached_window = w;
- [(NSOpenGLContext*)context makeCurrentContext];
- }
-}
-
-void Fl_Cocoa_Gl_Window_Driver::delete_gl_context(GLContext context) {
- NSOpenGLContext *current_context = [NSOpenGLContext currentContext];
- if (current_context == context) {
- cached_window = 0;
- [current_context clearDrawable];
- }
- [(NSOpenGLContext*)context release];
- del_context(context);
- if (gl1ctxt) {
- [[gl1ctxt view] release];
- [gl1ctxt release];
- gl1ctxt = 0;
- }
-}
-
-void Fl_Cocoa_Gl_Window_Driver::make_overlay_current() {
- // this is not very useful, but unfortunately, Apple decided
- // that front buffer drawing can no longer (OS X 10.4) be supported on their platforms.
- if (pWindow->shown()) pWindow->make_current();
-}
-
-void Fl_Cocoa_Gl_Window_Driver::redraw_overlay() {
- pWindow->redraw();
-}
-
-void Fl_Cocoa_Gl_Window_Driver::before_show(int& need_after) {
- need_after = 1;
-}
-
-void Fl_Cocoa_Gl_Window_Driver::after_show() {
- // Makes sure the GL context is created to avoid drawing twice the window when first shown
- pWindow->make_current();
- if ((mode() & FL_OPENGL3) && !gl1ctxt) {
- // Create transparent GL1 scene above the GL3 scene to hold child widgets and/or text
- NSView *view = [fl_mac_xid(pWindow) contentView];
- NSView *gl1view = [[NSView alloc] initWithFrame:[view frame]];
- [gl1view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- static NSOpenGLContext *shared_gl1_ctxt = nil;
- static NSOpenGLPixelFormat *gl1pixelformat = mode_to_NSOpenGLPixelFormat(
- FL_RGB8 | FL_ALPHA | FL_SINGLE, NULL);
- gl1ctxt = [[NSOpenGLContext alloc] initWithFormat:gl1pixelformat shareContext:shared_gl1_ctxt];
- if (!shared_gl1_ctxt) {
- shared_gl1_ctxt = gl1ctxt;
- [shared_gl1_ctxt retain];
- }
- [view addSubview:gl1view];
- if (Fl::use_high_res_GL()) {
- [gl1view setWantsBestResolutionOpenGLSurface:YES];
- }
- [gl1ctxt setView:gl1view];
- remove_gl_context_opacity(gl1ctxt);
- }
-}
-
-float Fl_Cocoa_Gl_Window_Driver::pixels_per_unit()
-{
- int retina = (Fl::use_high_res_GL() && Fl_X::flx(pWindow) &&
- Fl_Cocoa_Window_Driver::driver(pWindow)->mapped_to_retina()) ? 2 : 1;
- return retina * Fl_Graphics_Driver::default_driver().scale();
-}
-
-int Fl_Cocoa_Gl_Window_Driver::mode_(int m, const int *a) {
- if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer,
- // the FL_DOUBLE flag must be set in the mode_ member variable
- const int *aa = a;
- while (*aa) {
- if (*(aa++) ==
- kCGLPFADoubleBuffer
- ) { m |= FL_DOUBLE; break; }
- }
- }
- pWindow->context(0);
- mode( m); alist(a);
- if (pWindow->shown()) {
- g( find(m, a) );
- pWindow->redraw();
- } else {
- g(0);
- }
- return 1;
-}
-
-void Fl_Cocoa_Gl_Window_Driver::make_current_before() {
- // detect if the window was moved between low and high resolution displays
- Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(pWindow);
- if (d->changed_resolution()){
- d->changed_resolution(false);
- pWindow->invalidate();
- [(NSOpenGLContext*)pWindow->context() update];
- }
-}
-
-void Fl_Cocoa_Gl_Window_Driver::swap_buffers() {
- if (overlay() != NULL) {
- // STR# 2944 [1]
- // Save matrixmode/proj/modelview/rasterpos before doing overlay.
- //
- int wo = pWindow->pixel_w(), ho = pWindow->pixel_h();
- GLint matrixmode;
- GLfloat pos[4];
- glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
- glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos
- glMatrixMode(GL_PROJECTION); // save proj/model matrices
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glScalef(2.0f/wo, 2.0f/ho, 1.0f);
- glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window
- glRasterPos2i(0,0); // set glRasterPos to bottom left corner
- {
- // Emulate overlay by doing copypixels
- glReadBuffer(GL_BACK);
- glDrawBuffer(GL_FRONT);
- glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT
- }
- glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(matrixmode);
- glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos
- } else {
- [(NSOpenGLContext*)pWindow->context() flushBuffer];
- }
-}
-
-char Fl_Cocoa_Gl_Window_Driver::swap_type() {return copy;}
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-# define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
-#endif
-
-void Fl_Cocoa_Gl_Window_Driver::swap_interval(int n) {
- GLint interval = (GLint)n;
- NSOpenGLContext* ctx = (NSOpenGLContext*)pWindow->context();
- if (ctx)
- [ctx setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
-}
-
-int Fl_Cocoa_Gl_Window_Driver::swap_interval() const {
- GLint interval = (GLint)-1;
- NSOpenGLContext* ctx = (NSOpenGLContext*)pWindow->context();
- if (ctx)
- [ctx getValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
- return interval;
-}
-
-void Fl_Cocoa_Gl_Window_Driver::resize(int is_a_resize, int w, int h) {
- if (pWindow->shown()) apply_scissor();
- [(NSOpenGLContext*)pWindow->context() update];
- if (gl1ctxt) {
- [gl1ctxt update];
- }
-}
-
-void Fl_Cocoa_Gl_Window_Driver::apply_scissor() {
- if (glIsEnabled(GL_SCISSOR_TEST)) glDisable(GL_SCISSOR_TEST);
- CGRect *extents = Fl_Cocoa_Window_Driver::driver(pWindow)->subRect();
- if (extents) {
- remove_gl_context_opacity((NSOpenGLContext*)pWindow->context());
- GLdouble vals[4];
- glGetDoublev(GL_COLOR_CLEAR_VALUE, vals);
- glClearColor(0., 0., 0., 0.);
- glClear(GL_COLOR_BUFFER_BIT);
- glClearColor(vals[0], vals[1], vals[2], vals[3]);
- float s = pWindow->pixels_per_unit();
- glScissor(s*extents->origin.x, s*extents->origin.y, s*extents->size.width, s*extents->size.height);
-//printf("apply_scissor %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height);
- glEnable(GL_SCISSOR_TEST);
- }
-}
-
-
-/* Some old Apple hardware doesn't implement the GL_EXT_texture_rectangle extension.
- For it, draw_string_legacy_glut() is used to draw text. */
-
-char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs)
-{
- // write str to a bitmap just big enough
- Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
- Fl_Font f=fl_font();
- Fl_Surface_Device::push_current(surf);
- fl_color(FL_WHITE);
- fl_font(f, fs);
- fl_draw(str, n, 0, fl_height() - fl_descent());
- // get the alpha channel only of the bitmap
- char *alpha_buf = new char[w*h], *r = alpha_buf, *q;
- q = (char*)CGBitmapContextGetData((CGContextRef)surf->offscreen());
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- *r++ = *(q+3);
- q += 4;
- }
- }
- Fl_Surface_Device::pop_current();
- delete surf;
- return alpha_buf;
-}
-
-void Fl_Cocoa_Gl_Window_Driver::gl_start() {
- [(NSOpenGLContext*)gl_start_context update];
-}
-
-// convert BGRA to RGB and also exchange top and bottom
-static uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth)
-{
- uchar *newimg = new uchar[3*w*h];
- uchar *to = newimg;
- for (int i = h-1; i >= 0; i--) {
- uchar *from = baseAddress + i * mByteWidth;
- for (int j = 0; j < w; j++, from += 4) {
-#if defined(__ppc__) && __ppc__
- memcpy(to, from + 1, 3);
- to += 3;
-#else
- *(to++) = *(from+2);
- *(to++) = *(from+1);
- *(to++) = *from;
-#endif
- }
- }
- delete[] baseAddress;
- return newimg;
-}
-
-
-static Fl_RGB_Image *cgimage_to_rgb4(CGImageRef img) {
- int w = (int)CGImageGetWidth(img);
- int h = (int)CGImageGetHeight(img);
- CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
- uchar *rgba = new uchar[4 * w * h];
- CGContextRef auxgc = CGBitmapContextCreate(rgba, w, h, 8, 4 * w, cspace,
- kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(cspace);
- CGContextDrawImage(auxgc, CGRectMake(0, 0, w, h), img);
- CGContextRelease(auxgc);
- Fl_RGB_Image *rgb = new Fl_RGB_Image(rgba, w, h, 4);
- rgb->alloc_array = 1;
- return rgb;
-}
-
-
-Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h)
-{
- Fl_Gl_Window* glw = pWindow;
- float factor = glw->pixels_per_unit();
- if (factor != 1) {
- w *= factor; h *= factor; x *= factor; y *= factor;
- }
- NSWindow *nswin = (NSWindow*)fl_mac_xid(pWindow);
- CGImageRef img_full = Fl_Cocoa_Window_Driver::capture_decorated_window_10_5(nswin);
- int bt = [nswin frame].size.height - [[nswin contentView] frame].size.height;
- bt *= (factor / Fl_Graphics_Driver::default_driver().scale());
- CGRect cgr = CGRectMake(x, y + bt, w, h); // add vertical offset to bypass titlebar
- CGImageRef cgimg = CGImageCreateWithImageInRect(img_full, cgr); // 10.4
- CGImageRelease(img_full);
- Fl_RGB_Image *rgb = cgimage_to_rgb4(cgimg);
- CGImageRelease(cgimg);
- return rgb;
- [(NSOpenGLContext*)glw->context() makeCurrentContext];
- // to capture also the overlay and for directGL demo
- [(NSOpenGLContext*)glw->context() flushBuffer];
- // Read OpenGL context pixels directly.
- // For extra safety, save & restore OpenGL states that are changed
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
- glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
- glPixelStorei(GL_PACK_ROW_LENGTH, 0);
- glPixelStorei(GL_PACK_SKIP_ROWS, 0);
- glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
- // Read a block of pixels from the frame buffer
- int mByteWidth = w * 4;
- mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
- uchar *baseAddress = new uchar[mByteWidth * h];
- glReadPixels(x, glw->pixel_h() - (y+h), w, h,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, baseAddress);
- glPopClientAttrib();
- baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth);
- Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w);
- img->alloc_array = 1;
- [(NSOpenGLContext*)glw->context() flushBuffer];
- return img;
-}
-
-
-void* Fl_Cocoa_Gl_Window_Driver::GetProcAddress(const char *procName) {
- return dlsym(RTLD_DEFAULT, procName);
-}
-
-
-FL_EXPORT NSOpenGLContext *fl_mac_glcontext(GLContext rc) {
- return (NSOpenGLContext*)rc;
-}
-
-
-void Fl_Cocoa_Gl_Window_Driver::switch_to_GL1() {
- [gl1ctxt makeCurrentContext];
- glClearColor(0., 0., 0., 0.);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-
-void Fl_Cocoa_Gl_Window_Driver::switch_back() {
- glFlush();
- [(NSOpenGLContext*)pWindow->context() makeCurrentContext];
-}
-
-
-class Fl_Gl_Cocoa_Plugin : public Fl_Cocoa_Plugin {
-public:
- Fl_Gl_Cocoa_Plugin() : Fl_Cocoa_Plugin(name()) { }
- const char *name() FL_OVERRIDE { return "gl.cocoa.fltk.org"; }
- void resize(Fl_Gl_Window *glw, int x, int y, int w, int h) FL_OVERRIDE {
- glw->Fl_Gl_Window::resize(x, y, w, h);
- }
-};
-
-static Fl_Gl_Cocoa_Plugin Gl_Cocoa_Plugin;
-
-#endif // HAVE_GL
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Pen_Events.mm b/src/drivers/Cocoa/Fl_Cocoa_Pen_Events.mm
deleted file mode 100644
index 9c75c7ff2..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Pen_Events.mm
+++ /dev/null
@@ -1,439 +0,0 @@
-//
-// Definition of macOS Cocoa Pen/Tablet event driver.
-//
-// Copyright 2025-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "src/drivers/Base/Fl_Base_Pen_Events.H"
-
-#include <FL/platform.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include "../../Fl_Screen_Driver.H"
-
-#import <Cocoa/Cocoa.h>
-
-
-extern Fl_Window *fl_xmousewin;
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-
-typedef short NSEventSubtype;
-#define NSPointingDeviceTypePen NSPenPointingDevice
-#define NSEventTypeMouseEntered NSMouseEntered
-#define NSEventTypeMouseExited NSMouseExited
-#define NSEventTypeTabletProximity NSTabletProximity
-#define NSEventTypeTabletPoint NSTabletPoint
-#define NSEventSubtypeTabletProximity NSTabletProximityEventSubtype
-#define NSEventSubtypeTabletPoint NSTabletPointEventSubtype
-#define NSEventSubtypeMouseEvent NSMouseEventSubtype
-#define NSEventTypeLeftMouseDown NSLeftMouseDown
-#define NSEventTypeLeftMouseUp NSLeftMouseUp
-#define NSEventTypeLeftMouseDragged NSLeftMouseDragged
-#define NSEventTypeMouseMoved NSMouseMoved
-#define NSEventTypeRightMouseDown NSRightMouseDown
-#define NSEventTypeRightMouseUp NSRightMouseUp
-#define NSEventTypeRightMouseDragged NSRightMouseDragged
-#define NSEventTypeOtherMouseUp NSOtherMouseUp
-#define NSEventTypeOtherMouseDown NSOtherMouseDown
-#define NSEventTypeOtherMouseDragged NSOtherMouseDragged
-#define NSPointingDeviceTypeEraser NSEraserPointingDevice
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-
-static NSPointingDeviceType device_type_ { NSPointingDeviceTypePen };
-
-// The trait list keeps track of traits for every pen ID that appears while
-// handling events.
-// AppKit does not tell us what traits are available per pen or tablet, so
-// we use the first 5 motion events to discover event values that are not
-// the default value, and enter that knowledge into the traits database.
-typedef std::map<int, Fl::Pen::Trait> TraitList;
-static TraitList trait_list_;
-static int trait_countdown_ { 5 };
-static int current_pen_id_ { -1 };
-static Fl::Pen::Trait current_pen_trait_ { Fl::Pen::Trait::DRIVER_AVAILABLE };
-static Fl::Pen::Trait driver_traits_ {
- Fl::Pen::Trait::DRIVER_AVAILABLE | Fl::Pen::Trait::PEN_ID |
- Fl::Pen::Trait::ERASER | Fl::Pen::Trait::PRESSURE |
- Fl::Pen::Trait::BARREL_PRESSURE | Fl::Pen::Trait::TILT_X |
- Fl::Pen::Trait::TILT_Y | Fl::Pen::Trait::TWIST
- // Notably missing: PROXIMITY
-};
-
-// Temporary storage of event data for the driver;
-static Fl::Pen::EventData ev;
-
-
-namespace Fl {
-
-namespace Private {
-
-// Global mouse position at mouse down event
-extern int e_x_down;
-extern int e_y_down;
-
-}; // namespace Private
-
-namespace Pen {
-
-class Cocoa_Driver : public Driver {
-public:
- Cocoa_Driver() = default;
- //virtual void subscribe(Fl_Widget* widget) override;
- //virtual void unsubscribe(Fl_Widget* widget) override;
- //virtual void release() override;
- virtual Trait traits() override { return driver_traits_; }
- virtual Trait pen_traits(int pen_id) override {
- auto it = trait_list_.find(pen_id);
- if (pen_id == 0)
- return current_pen_trait_;
- if (it == trait_list_.end()) {
- return Trait::DRIVER_AVAILABLE;
- } else {
- return it->second;
- }
- }
-};
-
-Cocoa_Driver cocoa_driver;
-Driver& driver = cocoa_driver;
-
-} // namespace Pen
-
-} // namespace Fl
-
-
-using namespace Fl::Pen;
-
-
-/*
- Copy the event state.
- */
-static void copy_state() {
- Fl::Pen::State tr = (Fl::Pen::State)((uint32_t)Fl::Pen::e.state ^ (uint32_t)ev.state);
- Fl::Pen::e = ev;
- Fl::Pen::e.trigger = tr;
- Fl::e_x = (int)ev.x;
- Fl::e_y = (int)ev.y;
- Fl::e_x_root = (int)ev.rx;
- Fl::e_y_root = (int)ev.ry;
-}
-
-/*
- Offset coordinates for subwindows and subsubwindows.
- */
-static void offset_subwindow_event(Fl_Widget *w, double &x, double &y) {
- Fl_Widget *p = w, *q;
- while (p) {
- q = p->parent();
- if (p->as_window() && q) {
- x -= p->x();
- y -= p->y();
- }
- p = q;
- };
-}
-
-/*
- Check if coordinates are within the widget box.
- Coordinates are in top_window space. We iterate up the hierarchy to ensure
- that we handle subwindows correctly.
- */
-static bool event_inside(Fl_Widget *w, double x, double y) {
- offset_subwindow_event(w, x, y);
- if (w->as_window()) {
- return ((x >= 0) && (y >= 0) && (x < w->w()) && (y < w->h()));
- } else {
- return ((x >= w->x()) && (y >= w->y()) && (x < w->x() + w->w()) && (y < w->y() + w->h()));
- }
-}
-
-/*
- Find the widget under the pen event.
- Search the subscriber list for widgets that are inside the same top window,
- are visible, and are within the give coordinates. Subwindow aware.
- */
-static Fl_Widget *find_below_pen(Fl_Window *win, double x, double y) {
- for (auto &sub: subscriber_list_) {
- Fl_Widget *candidate = sub.second->widget();
- if (candidate && (candidate->top_window() == win)) {
- if (candidate->visible() && event_inside(candidate, x, y)) {
- return candidate;
- }
- }
- }
- return nullptr;
-}
-
-/*
- Send the current event and event data to a widget.
- Note: we will get the wrong coordinates if the widget is not a child of
- the current event window (LEAVE events between windows).
- */
-static int pen_send(Fl_Widget *w, int event, State trigger, bool &copied) {
- // Copy most event data only once
- if (!copied) {
- copy_state();
- copied = true;
- }
- // Copy the top_window coordinates again as they may change when w changes
- e.x = ev.x;
- e.y = ev.y;
- offset_subwindow_event(w, e.x, e.y);
- Fl::e_x = e.x;
- Fl::e_y = e.y;
- // Send the event.
- e.trigger = trigger;
- return w->handle(event);
-}
-
-/*
- Send an event to all subscribers.
- */
-static int pen_send_all(int event, State trigger) {
- bool copied = false;
- // use local value because handler may still change ev values
- for (auto &it: subscriber_list_) {
- auto w = it.second->widget();
- if (w)
- pen_send(w, event, trigger, copied);
- }
- return 1;
-}
-
-/*
- Convert the NSEvent button number to Fl::Pen::State,
- */
-static State button_to_trigger(NSInteger button, bool down) {
- switch (button) {
- case 0:
- if ( (ev.state & (State::ERASER_DOWN | State::ERASER_HOVERS)) != State::NONE ) {
- return down ? State::ERASER_DOWN : State::ERASER_HOVERS;
- } else {
- return down ? State::TIP_DOWN : State::TIP_HOVERS;
- }
- case 1: return State::BUTTON0;
- case 2: return State::BUTTON1;
- case 3: return State::BUTTON2;
- case 4: return State::BUTTON3;
- default: return State::NONE;
- }
-}
-
-/*
- Handle events coming from Cocoa.
- `capabilityMask` is useless, because it is vendor defined
- If a modal window is open, AppKit will send window specific events only there.
- */
-bool fl_cocoa_tablet_handler(NSEvent *event, Fl_Window *eventWindow) {
- // Quick access to the main type.
- auto type = [event type];
-
- // There seems nothing useful here. Ignore for now.
- if ((type == NSEventTypeMouseEntered) || (type == NSEventTypeMouseExited)) {
- return false;
- }
-
- // Sort out tablet-only events and mouse plus tablet events.
- bool is_mouse = ((type != NSEventTypeTabletPoint) && (type != NSEventTypeTabletProximity));
-
- // Set the subtype if one is available. Only NSEventSubtypeTabletPoint and
- // NSEventSubtypeTabletProximity matter in this context
- NSEventSubtype subtype = is_mouse ? [event subtype] : NSEventSubtypeMouseEvent;
-
- // Is this a change in proximity event?
- bool is_proximity = ((type == NSEventTypeTabletProximity) || (subtype == NSEventSubtypeTabletProximity));
-
- // Is this a pen pointer event?
- bool is_point = ((type == NSEventTypeTabletPoint) || (subtype == NSEventSubtypeTabletPoint));
-
- // Check if any of the pen down, move, drag, or up events was triggered.
- bool is_down = ((type == NSEventTypeLeftMouseDown) || (type == NSEventTypeRightMouseDown) || (type == NSEventTypeOtherMouseDown));
- bool is_up = ((type == NSEventTypeLeftMouseUp) || (type == NSEventTypeRightMouseUp) || (type == NSEventTypeOtherMouseUp));
- bool is_drag = ((type == NSEventTypeLeftMouseDragged) || (type == NSEventTypeRightMouseDragged) || (type == NSEventTypeOtherMouseDragged));
- bool is_motion = is_drag || (type == NSEventTypeMouseMoved);
-
- // Find out if we can get the pen position
- bool has_position = (eventWindow != nullptr) && (is_up || is_down || is_motion || is_proximity || is_point);
-
- // Event has extended pen data set:
- if (has_position) {
- // Get the position data.
- auto pt = [event locationInWindow];
- double s = Fl::screen_driver()->scale(0);
- ev.x = pt.x/s;
- ev.y = eventWindow->h() - pt.y/s;
- ev.rx = ev.x + eventWindow->x();
- ev.ry = ev.y + eventWindow->y();
- if (!is_proximity) {
- // Get the pressure data.
- ev.pressure = [event pressure];
- ev.barrel_pressure = [event tangentialPressure];
- // Get the tilt
- auto tilt = [event tilt];
- ev.tilt_x = -tilt.x;
- ev.tilt_y = tilt.y;
- // Other stuff
- ev.twist = [event rotation]; // TODO: untested
- // ev.proximity = [event proximity]; // not supported in AppKit
- }
- if (device_type_ == NSPointingDeviceTypeEraser) {
- if ([event buttonMask] & 1)
- ev.state = State::ERASER_DOWN;
- else
- ev.state = State::ERASER_HOVERS;
- } else {
- if ([event buttonMask] & 1)
- ev.state = State::TIP_DOWN;
- else
- ev.state = State::TIP_HOVERS;
- }
- if ([event buttonMask] & 0x0002) ev.state |= State::BUTTON0;
- if ([event buttonMask] & 0x0004) ev.state |= State::BUTTON1;
- if ([event buttonMask] & 0x0008) ev.state |= State::BUTTON2;
- if ([event buttonMask] & 0x0010) ev.state |= State::BUTTON3;
- // printf("0x%08x\n", [event buttonMask]);
- }
- if (is_proximity) {
- ev.pen_id = (int)[event vendorID];
- device_type_ = [event pointingDeviceType];
- }
- if (type == NSEventTypeTabletProximity) {
- if ([event isEnteringProximity]) {
- // Check if this is the first time we see this pen, or if the pen changed
- if (current_pen_id_ != ev.pen_id) {
- current_pen_id_ = ev.pen_id;
- auto it = trait_list_.find(current_pen_id_);
- if (it == trait_list_.end()) { // not found, create a new entry
- trait_list_[current_pen_id_] = Trait::DRIVER_AVAILABLE;
- trait_countdown_ = 5;
- pen_send_all(Fl::Pen::DETECTED, State::NONE);
- // printf("IN RANGE, NEW PEN\n");
- } else {
- pen_send_all(Fl::Pen::CHANGED, State::NONE);
- // printf("IN RANGE, CHANGED PEN\n");
- }
- trait_list_[0] = trait_list_[current_pen_id_]; // set current pen traits
- } else {
- pen_send_all(Fl::Pen::IN_RANGE, State::NONE);
- // printf("IN RANGE\n");
- }
- } else {
- pen_send_all(Fl::Pen::OUT_OF_RANGE, State::NONE);
- // printf("OUT OF RANGE\n");
- }
- }
-
- Fl_Widget *receiver = nullptr;
- bool pushed = false;
- bool event_data_copied = false;
-
- if (has_position) {
- if (trait_countdown_) {
- trait_countdown_--;
- if (ev.tilt_x != 0.0) current_pen_trait_ |= Trait::TILT_X;
- if (ev.tilt_y != 0.0) current_pen_trait_ |= Trait::TILT_Y;
- if (ev.pressure != 1.0) current_pen_trait_ |= Trait::PRESSURE;
- if (ev.barrel_pressure != 0.0) current_pen_trait_ |= Trait::BARREL_PRESSURE;
- if (ev.pen_id != 0) current_pen_trait_ |= Trait::PEN_ID;
- if (ev.twist != 0.0) current_pen_trait_ |= Trait::TWIST;
- //if (ev.proximity != 0) current_pen_trait_ |= Trait::PROXIMITY;
- trait_list_[current_pen_id_] = current_pen_trait_;
- }
- fl_xmousewin = eventWindow;
- if (pushed_ && pushed_->widget() && (Fl::pushed() == pushed_->widget())) {
- receiver = pushed_->widget();
- if (Fl::grab() && (Fl::grab() != receiver->top_window()))
- return 0;
- if (Fl::modal() && (Fl::modal() != receiver->top_window()))
- return 0;
- pushed = true;
- } else {
- if (Fl::grab() && (Fl::grab() != eventWindow))
- return 0;
- if (Fl::modal() && (Fl::modal() != eventWindow))
- return 0;
- auto bpen = below_pen_ ? below_pen_->widget() : nullptr;
- auto bmouse = Fl::belowmouse();
- auto bpen_old = bmouse && (bmouse == bpen) ? bpen : nullptr;
- auto bpen_now = find_below_pen(eventWindow, ev.x, ev.y);
-
- if (bpen_now != bpen_old) {
- if (bpen_old) {
- pen_send(bpen_old, Fl::Pen::LEAVE, State::NONE, event_data_copied);
- }
- below_pen_ = nullptr;
- if (bpen_now) {
- State state = (device_type_ == NSPointingDeviceTypeEraser) ? State::ERASER_HOVERS : State::TIP_HOVERS;
- if (pen_send(bpen_now, Fl::Pen::ENTER, state, event_data_copied)) {
- below_pen_ = subscriber_list_[bpen_now];
- Fl::belowmouse(bpen_now);
- }
- }
- }
-
- receiver = below_pen_ ? below_pen_->widget() : nullptr;
- if (!receiver)
- return 0;
- }
- } else {
- // Proximity events were handled earlier.
- }
-
- if (!receiver)
- return 0;
-
- if (is_down) {
- if (!pushed) {
- pushed_ = subscriber_list_[receiver];
- Fl::pushed(receiver);
- }
- State trigger = button_to_trigger([event buttonNumber], true);
- if ([event buttonNumber] == 0) {
- Fl::e_is_click = 1;
- Fl::Private::e_x_down = (int)ev.x;
- Fl::Private::e_y_down = (int)ev.y;
- if ([event clickCount] > 1)
- Fl::e_clicks++;
- else
- Fl::e_clicks = 0;
- pen_send(receiver, Fl::Pen::TOUCH, trigger, event_data_copied);
- } else {
- pen_send(receiver, Fl::Pen::BUTTON_PUSH, trigger, event_data_copied);
- }
- } else if (is_up) {
- if ( (ev.state & State::ANY_DOWN) == State::NONE ) {
- Fl::pushed(nullptr);
- pushed_ = nullptr;
- }
- State trigger = button_to_trigger([event buttonNumber], true);
- if ([event buttonNumber] == 0)
- pen_send(receiver, Fl::Pen::LIFT, trigger, event_data_copied);
- else
- pen_send(receiver, Fl::Pen::BUTTON_RELEASE, trigger, event_data_copied);
- } else if (is_motion) {
- if ( Fl::e_is_click &&
- ( (fabs((int)ev.x - Fl::Private::e_x_down) > 5) ||
- (fabs((int)ev.y - Fl::Private::e_y_down) > 5) ) )
- Fl::e_is_click = 0;
- if (pushed) {
- pen_send(receiver, Fl::Pen::DRAW, State::NONE, event_data_copied);
- } else {
- pen_send(receiver, Fl::Pen::HOVER, State::NONE, event_data_copied);
- }
- }
- // Always return 1 because at this point, we capture pen events and don't
- // want mouse events anymore!
- return 1;
-}
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
deleted file mode 100644
index a40f1feb4..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
+++ /dev/null
@@ -1,455 +0,0 @@
-//
-// Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/Fl_Paged_Device.H>
-#include <FL/Fl_Printer.H>
-#include "../../Fl_Window_Driver.H"
-#include "../../Fl_Screen_Driver.H"
-#include "../Quartz/Fl_Quartz_Graphics_Driver.H"
-#include "../Darwin/Fl_Darwin_System_Driver.H"
-#include <FL/Fl_PDF_File_Surface.H>
-#include "Fl_Cocoa_Window_Driver.H"
-
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/fl_ask.H>
-#include <FL/fl_draw.H>
-#include <FL/fl_string_functions.h>
-#import <Cocoa/Cocoa.h>
-
-typedef OSStatus (*PMSessionSetDocumentFormatGeneration_type)(
- PMPrintSession printSession,
- CFStringRef docFormat,
- CFArrayRef graphicsContextTypes,
- CFTypeRef options);
-typedef OSStatus (*PMSessionBeginDocumentNoDialog_type)(
- PMPrintSession printSession,
- PMPrintSettings printSettings,
- PMPageFormat pageFormat);
-typedef OSStatus
-(*PMSessionGetGraphicsContext_type)(
- PMPrintSession printSession,
- CFStringRef graphicsContextType,
- void ** graphicsContext);
-
-
-/** Support for printing on the Apple OS X platform */
-class Fl_Cocoa_Printer_Driver : public Fl_Paged_Device {
- friend class Fl_Printer;
-protected:
- float scale_x;
- float scale_y;
- float angle; // rotation angle in radians
- PMPrintSession printSession;
- PMPageFormat pageFormat;
- PMPrintSettings printSettings;
- Fl_Cocoa_Printer_Driver(void);
- int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL) FL_OVERRIDE;
- int begin_page (void) FL_OVERRIDE;
- int printable_rect(int *w, int *h) FL_OVERRIDE;
- void margins(int *left, int *top, int *right, int *bottom) FL_OVERRIDE;
- void origin(int *x, int *y) FL_OVERRIDE;
- void origin(int x, int y) FL_OVERRIDE;
- void scale (float scale_x, float scale_y = 0.) FL_OVERRIDE;
- void rotate(float angle) FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate(void) FL_OVERRIDE;
- int end_page (void) FL_OVERRIDE;
- void end_job (void) FL_OVERRIDE;
- ~Fl_Cocoa_Printer_Driver(void);
-};
-
-
-Fl_Cocoa_Printer_Driver::Fl_Cocoa_Printer_Driver(void)
-{
- x_offset = 0;
- y_offset = 0;
- scale_x = scale_y = 1.;
- driver(new Fl_Quartz_Printer_Graphics_Driver);
-}
-
-Fl_Paged_Device* Fl_Printer::newPrinterDriver(void)
-{
- return new Fl_Cocoa_Printer_Driver();
-}
-
-Fl_Cocoa_Printer_Driver::~Fl_Cocoa_Printer_Driver(void) {
- delete driver();
-}
-
-@interface print_panel_delegate : NSObject
-- (void)printPanelDidEnd:(NSPrintPanel *)printPanel returnCode:(NSInteger)returnCode contextInfo:(NSInteger *)contextInfo;
-@end
-@implementation print_panel_delegate
-- (void)printPanelDidEnd:(NSPrintPanel *)printPanel returnCode:(NSInteger)returnCode contextInfo:(NSInteger *)contextInfo
-{
- *contextInfo = returnCode;
-}
-@end
-
-int Fl_Cocoa_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message)
-//printing using a Quartz graphics context
-//returns 0 iff OK
-{
- OSStatus status = 0;
- fl_open_display();
- Fl_Cocoa_Window_Driver::q_release_context();
- NSPrintInfo *info = [NSPrintInfo sharedPrintInfo];
- NSPrintPanel *panel = [NSPrintPanel printPanel];
- //from 10.5
- [panel setOptions:NSPrintPanelShowsCopies | NSPrintPanelShowsPageRange |
- NSPrintPanelShowsPageSetupAccessory | NSPrintPanelShowsOrientation | NSPrintPanelShowsPaperSize];
- NSInteger retval = -1;
- Fl_Window *top = Fl::first_window();
- NSWindow *main = (top ? (NSWindow*)fl_xid(top->top_window()) : nil);
- if (main) {
- [panel beginSheetWithPrintInfo:info
- modalForWindow:main
- delegate:[[[print_panel_delegate alloc] init] autorelease]
- didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
- contextInfo:&retval];
- while (retval < 0) Fl::wait(100);
- [main makeKeyAndOrderFront:nil];
- } else {
- retval = [panel runModalWithPrintInfo:info]; //from 10.5
- }
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
- const NSInteger NSModalResponseOK = NSOKButton;
-#endif
- if (retval != NSModalResponseOK) return 1;
- printSession = (PMPrintSession)[info PMPrintSession]; //from 10.5
- pageFormat = (PMPageFormat)[info PMPageFormat]; //from 10.5
- printSettings = (PMPrintSettings)[info PMPrintSettings];//from 10.5
- UInt32 from32, to32;
- PMGetFirstPage(printSettings, &from32);
- if (frompage) *frompage = (int)from32;
- PMGetLastPage(printSettings, &to32);
- if (topage) {
- *topage = (int)to32;
- if (*topage > pagecount && pagecount > 0) *topage = pagecount;
- }
- status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4
-
- if (status != noErr) {
- if (perr_message) {
- NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil];
- NSString *s = [nserr localizedDescription];
- if (s) *perr_message = fl_strdup([s UTF8String]);
- }
- return 2;
- }
- y_offset = x_offset = 0;
- return 0;
-}
-
-void Fl_Cocoa_Printer_Driver::margins(int *left, int *top, int *right, int *bottom)
-{
- PMPaper paper;
- PMGetPageFormatPaper(pageFormat, &paper);
- PMOrientation orientation;
- PMGetOrientation(pageFormat, &orientation);
- PMPaperMargins margins;
- PMPaperGetMargins(paper, &margins);
- if(orientation == kPMPortrait) {
- if (left) *left = (int)(margins.left / scale_x + 0.5);
- if (top) *top = (int)(margins.top / scale_y + 0.5);
- if (right) *right = (int)(margins.right / scale_x + 0.5);
- if (bottom) *bottom = (int)(margins.bottom / scale_y + 0.5);
- } else {
- if (left) *left = (int)(margins.top / scale_x + 0.5);
- if (top) *top = (int)(margins.left / scale_y + 0.5);
- if (right) *right = (int)(margins.bottom / scale_x + 0.5);
- if (bottom) *bottom = (int)(margins.right / scale_y + 0.5);
- }
-}
-
-int Fl_Cocoa_Printer_Driver::printable_rect(int *w, int *h)
-//returns 0 iff OK
-{
- OSStatus status;
- PMRect pmRect;
- int x, y;
-
- status = PMGetAdjustedPageRect(pageFormat, &pmRect);
- if (status != noErr) return 1;
-
- x = (int)pmRect.left;
- y = (int)pmRect.top;
- *w = int((int)(pmRect.right - x) / scale_x + 1);
- *h = int((int)(pmRect.bottom - y) / scale_y + 1);
- return 0;
-}
-
-void Fl_Cocoa_Printer_Driver::origin(int x, int y)
-{
- x_offset = x;
- y_offset = y;
- CGContextRef gc = (CGContextRef)driver()->gc();
- CGContextRestoreGState(gc);
- CGContextRestoreGState(gc);
- CGContextSaveGState(gc);
- CGContextScaleCTM(gc, scale_x, scale_y);
- CGContextTranslateCTM(gc, x, y);
- CGContextRotateCTM(gc, angle);
- CGContextSaveGState(gc);
-}
-
-void Fl_Cocoa_Printer_Driver::scale (float s_x, float s_y)
-{
- if (s_y == 0.) s_y = s_x;
- scale_x = s_x;
- scale_y = s_y;
- CGContextRef gc = (CGContextRef)driver()->gc();
- CGContextRestoreGState(gc);
- CGContextRestoreGState(gc);
- CGContextSaveGState(gc);
- CGContextScaleCTM(gc, scale_x, scale_y);
- CGContextRotateCTM(gc, angle);
- x_offset = y_offset = 0;
- CGContextSaveGState(gc);
-}
-
-void Fl_Cocoa_Printer_Driver::rotate (float rot_angle)
-{
- angle = - rot_angle * M_PI / 180.;
- CGContextRef gc = (CGContextRef)driver()->gc();
- CGContextRestoreGState(gc);
- CGContextRestoreGState(gc);
- CGContextSaveGState(gc);
- CGContextScaleCTM(gc, scale_x, scale_y);
- CGContextTranslateCTM(gc, x_offset, y_offset);
- CGContextRotateCTM(gc, angle);
- CGContextSaveGState(gc);
-}
-
-void Fl_Cocoa_Printer_Driver::translate(int x, int y)
-{
- CGContextRef gc = (CGContextRef)driver()->gc();
- CGContextSaveGState(gc);
- CGContextTranslateCTM(gc, x, y );
- CGContextSaveGState(gc);
-}
-
-void Fl_Cocoa_Printer_Driver::untranslate(void)
-{
- CGContextRef gc = (CGContextRef)driver()->gc();
- CGContextRestoreGState(gc);
- CGContextRestoreGState(gc);
-}
-
-int Fl_Cocoa_Printer_Driver::begin_page (void)
-{
- OSStatus status = PMSessionBeginPageNoDialog(printSession, pageFormat, NULL);
- CGContextRef gc;
- status = PMSessionGetCGGraphicsContext(printSession, &gc); // 10.4
- driver()->gc(gc);
- Fl_Surface_Device::push_current(this);
- PMRect pmRect;
- float win_scale_x, win_scale_y;
-
- PMPaper paper;
- PMGetPageFormatPaper(pageFormat, &paper);
- PMPaperMargins margins;
- PMPaperGetMargins(paper, &margins);
- PMOrientation orientation;
- PMGetOrientation(pageFormat, &orientation);
-
- status = PMGetAdjustedPageRect(pageFormat, &pmRect);
- double h = pmRect.bottom - pmRect.top;
- x_offset = 0;
- y_offset = 0;
- angle = 0;
- scale_x = scale_y = 1;
- win_scale_x = win_scale_y = 1;
- if(orientation == kPMPortrait)
- CGContextTranslateCTM(gc, margins.left, margins.bottom + h);
- else
- CGContextTranslateCTM(gc, margins.top, margins.right + h);
- CGContextScaleCTM(gc, win_scale_x, - win_scale_y);
- ((Fl_Quartz_Graphics_Driver*)driver())->quartz_restore_line_style();
- CGContextSetShouldAntialias(gc, false);
- CGContextSaveGState(gc);
- CGContextSaveGState(gc);
- fl_line_style(FL_SOLID);
- fl_window = (FLWindow*)1; // TODO: something better
- fl_clip_region(0);
- return status != noErr;
-}
-
-int Fl_Cocoa_Printer_Driver::end_page (void)
-{
- CGContextRef gc = (CGContextRef)driver()->gc();
- CGContextFlush(gc);
- CGContextRestoreGState(gc);
- CGContextRestoreGState(gc);
- OSStatus status = PMSessionEndPageNoDialog(printSession);
- gc = NULL;
- Fl_Surface_Device::pop_current();
- return status != noErr;
-}
-
-void Fl_Cocoa_Printer_Driver::end_job (void)
-{
- OSStatus status;
-
- status = PMSessionError(printSession);
- if (status != noErr) {
- fl_alert ("PM Session error %d", (int)status);
- }
- PMSessionEndDocumentNoDialog(printSession);
- Fl_Window *w = Fl::first_window();
- if (w) w->show();
-}
-
-void Fl_Cocoa_Printer_Driver::origin(int *x, int *y)
-{
- Fl_Paged_Device::origin(x, y);
-}
-
-
-class Fl_PDF_Cocoa_File_Surface : public Fl_Cocoa_Printer_Driver
-{
-public:
- char *doc_fname;
- Fl_PDF_Cocoa_File_Surface();
- ~Fl_PDF_Cocoa_File_Surface() { if (doc_fname) free(doc_fname); }
- int begin_job(const char *defaultname,
- char **perr_message = NULL);
- int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use
- int begin_document(const char* outname,
- enum Fl_Paged_Device::Page_Format format,
- enum Fl_Paged_Device::Page_Layout layout,
- char **perr_message);
-};
-
-
-Fl_PDF_Cocoa_File_Surface::Fl_PDF_Cocoa_File_Surface() {
- driver(new Fl_Quartz_Graphics_Driver());
- doc_fname = NULL;
-}
-
-
-int Fl_PDF_Cocoa_File_Surface::begin_job(const char* defaultfilename,
- char **perr_message) {
- OSStatus status = 0;
- if (fl_mac_os_version < 100900) return 1;
- Fl_Window *top = Fl::first_window();
- NSWindow *main = (top ? (NSWindow*)fl_xid(top->top_window()) : nil);
- if (!main) return 1;
- Fl_Cocoa_Window_Driver::q_release_context();
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 && defined(__BLOCKS__)
- NSPDFInfo *pdf_info = [[NSPDFInfo alloc] init]; // 10.9
- NSPDFPanel *pdf_panel = [NSPDFPanel panel]; // 10.9
- char buf[FL_PATH_MAX];
- strcpy(buf, defaultfilename);
- fl_filename_setext(buf, sizeof(buf), NULL);
- [pdf_panel setDefaultFileName:[NSString stringWithUTF8String:buf]];
- [pdf_panel setOptions: NSPrintPanelShowsOrientation | NSPrintPanelShowsPaperSize];
- NSInteger retval = -1;
- __block NSInteger complete = -1;
- [pdf_panel beginSheetWithPDFInfo:pdf_info
- modalForWindow:main
- completionHandler:^(NSInteger returnCode) {
- // this block runs after OK or Cancel was triggered in file dialog
- complete = returnCode;
- }
- ];
- while (complete == -1) Fl::wait(100); // loop until end of file dialog
- retval = complete;
- [main makeKeyAndOrderFront:nil];
- if (retval != NSModalResponseOK) return 1;
- NSURL *url = [pdf_info URL];
- doc_fname = fl_strdup([url fileSystemRepresentation]);
- NSPrintInfo *pr_info = [NSPrintInfo sharedPrintInfo];
- [pr_info takeSettingsFromPDFInfo:pdf_info];
- [pdf_info release];
- printSession = (PMPrintSession)[pr_info PMPrintSession];
- printSettings = (PMPrintSettings)[pr_info PMPrintSettings];
- pageFormat = (PMPageFormat)[pr_info PMPageFormat];
- status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4
-#endif
- if (status != noErr) {
- if (perr_message) {
- NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil];
- NSString *s = [nserr localizedDescription];
- if (s) *perr_message = fl_strdup([s UTF8String]);
- }
- free(doc_fname);
- doc_fname = NULL;
- return 2;
- }
- y_offset = x_offset = 0;
- return 0;
-}
-
-
-int Fl_PDF_Cocoa_File_Surface::begin_document(const char* outfname,
- enum Fl_Paged_Device::Page_Format format,
- enum Fl_Paged_Device::Page_Layout layout,
- char **perr_message) {
- OSStatus status = 0;
- fl_open_display();
- if (fl_mac_os_version < 100900) return 1;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
- NSPDFInfo *pdf_info = [[NSPDFInfo alloc] init]; // 10.9
- doc_fname = fl_strdup(outfname);
- NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:doc_fname]];
- [pdf_info setURL:url];
- NSSize psize = {(CGFloat)Fl_Paged_Device::page_formats[format].width, (CGFloat)Fl_Paged_Device::page_formats[format].height};
- [pdf_info setPaperSize:psize];
- [pdf_info setOrientation:(layout == PORTRAIT ? NSPaperOrientationPortrait : NSPaperOrientationLandscape)];
- NSPrintInfo *pr_info = [NSPrintInfo sharedPrintInfo];
- [pr_info takeSettingsFromPDFInfo:pdf_info];
- [pdf_info release];
- printSession = (PMPrintSession)[pr_info PMPrintSession];
- printSettings = (PMPrintSettings)[pr_info PMPrintSettings];
- pageFormat = (PMPageFormat)[pr_info PMPageFormat];
- status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4
-#endif
- if (status != noErr) {
- if (perr_message) {
- NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil];
- NSString *s = [nserr localizedDescription];
- if (s) *perr_message = fl_strdup([s UTF8String]);
- }
- free(doc_fname);
- doc_fname = NULL;
- return 2;
- }
- y_offset = x_offset = 0;
- return 0;
-}
-
-
-Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
- Fl_PDF_Cocoa_File_Surface *surf = new Fl_PDF_Cocoa_File_Surface();
- *pfname = (const char**)&surf->doc_fname;
- return surf;
-}
-
-
-int Fl_PDF_File_Surface::begin_job(const char* defaultfilename,
- char **perr_message) {
- return ((Fl_PDF_Cocoa_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message);
-}
-
-
-int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
- enum Fl_Paged_Device::Page_Format format,
- enum Fl_Paged_Device::Page_Layout layout,
- char **perr_message) {
- return ((Fl_PDF_Cocoa_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message);
-}
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H
deleted file mode 100644
index 9e3d2386a..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H
+++ /dev/null
@@ -1,114 +0,0 @@
-//
-// Definition of Apple Cocoa Screen interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Cocoa_Screen_Driver.H
- \brief Definition of Apple Cocoa Screen interface.
- */
-
-#ifndef FL_COCOA_SCREEN_DRIVER_H
-#define FL_COCOA_SCREEN_DRIVER_H
-
-#include "../../Fl_Screen_Driver.H"
-
-/*
- Move everything here that manages the native screen interface.
-
- There is exactly one screen driver in the system.
-
- - screen configuration and sizes
- - multiple screens
- - native dialog boxes
-*/
-
-
-class Fl_Window;
-class Fl_Input;
-class Fl_RGB_Image;
-#ifdef __OBJC__
-@class NSImage;
-#else
-class NSImage;
-#endif
-
-class Fl_Cocoa_Screen_Driver : public Fl_Screen_Driver
-{
-protected:
- struct XRectangle {int x, y, width, height;};
- XRectangle screens[MAX_SCREENS];
- float dpi_h[MAX_SCREENS];
- float dpi_v[MAX_SCREENS];
- static int insertion_point_x;
- static int insertion_point_y;
- static int insertion_point_height;
- static bool insertion_point_location_is_valid;
-public:
- NSImage *default_icon;
- Fl_Cocoa_Screen_Driver();
- static int next_marked_length; // next length of marked text after current marked text will have been replaced
- static void breakMacEventLoop();
- // --- display management
- // --- screen configuration
- void init() FL_OVERRIDE;
- int x() FL_OVERRIDE;
- int y() FL_OVERRIDE;
- int w() FL_OVERRIDE;
- int h() FL_OVERRIDE;
- void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE;
- void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE;
- // implemented in Fl_cocoa.mm because uses Objective-c
- void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE;
- // --- audible output
- void beep(int type) FL_OVERRIDE;
- // --- global events
- void grab(Fl_Window* win) FL_OVERRIDE;
- // --- global colors
- void get_system_colors() FL_OVERRIDE;
- int has_marked_text() const FL_OVERRIDE;
- static void reset_marked_text();
- static void insertion_point_location(int x, int y, int height);
- static int insertion_point_location(int *px, int *py, int *pheight);
- int dnd(int use_selection) FL_OVERRIDE;
- int compose(int &del) FL_OVERRIDE;
- int input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input) FL_OVERRIDE;
- int get_mouse(int &x, int &y) FL_OVERRIDE;
- void enable_im() FL_OVERRIDE;
- void disable_im() FL_OVERRIDE;
- void open_display_platform() FL_OVERRIDE;
- // --- compute dimensions of an Fl_Offscreen
- void offscreen_size(Fl_Offscreen o, int &width, int &height) FL_OVERRIDE;
-
- APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { return SYSTEMWIDE_APP_SCALING; }
- float scale(int /*nscreen*/) FL_OVERRIDE {return scale_;}
- void scale(int /*nscreen*/, float f) FL_OVERRIDE { scale_ = f;}
- Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE;
- void default_icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE;
- void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE;
- void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE;
- int clipboard_contains(const char *type) FL_OVERRIDE;
- void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) FL_OVERRIDE;
- void reset_spot() FL_OVERRIDE;
- int need_menu_handle_part2() FL_OVERRIDE {return 1;}
- // these 2 are in Fl_get_key_mac.cxx
- int event_key(int) FL_OVERRIDE;
- int get_key(int) FL_OVERRIDE;
-private:
- float scale_;
-};
-
-
-#endif // FL_COCOA_SCREEN_DRIVER_H
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
deleted file mode 100644
index 7eb98b291..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
+++ /dev/null
@@ -1,434 +0,0 @@
-//
-// Definition of Apple Cocoa Screen interface.
-//
-// Copyright 1998-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Cocoa_Screen_Driver.H"
-#include "Fl_Cocoa_Window_Driver.H"
-#include "../Quartz/Fl_Font.H"
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/Fl_Graphics_Driver.H>
-#include <FL/Fl_Input.H>
-#include <FL/fl_ask.H>
-#include <FL/Fl_Image_Surface.H>
-#include <stdio.h>
-
-
-extern "C" void NSBeep(void);
-extern void (*fl_lock_function)();
-extern void (*fl_unlock_function)();
-
-int Fl_Cocoa_Screen_Driver::next_marked_length = 0;
-
-
-// This key table is used for the Darwin system driver. It is defined here
-// "static" and assigned in the constructor to avoid static initialization
-// race conditions. It is used in fl_shortcut.cxx.
-//
-// This table must be in numeric order by fltk (X) keysym number:
-
-Fl_Screen_Driver::Keyname darwin_key_table[] = {
- // v - this column may contain UTF-8 characters
- {' ', "Space"},
- {FL_BackSpace, "⌫"/*"\xe2\x8c\xab"*/}, // U+232B : erase to the left
- {FL_Tab, "⇥"/*"\xe2\x87\xa5"*/}, // U+21E5 rightwards arrow to bar
- {FL_Enter, "↩"/*"\xe2\x86\xa9"*/}, // U+21A9 leftwards arrow with hook
- {FL_Pause, "Pause"},
- {FL_Scroll_Lock, "Scroll_Lock"},
- {FL_Escape, "⎋"/*"\xe2\x8e\x8b"*/}, // U+238B : broken circle with northwest arrow
- {FL_Home, "↖"/*"\xe2\x86\x96"*/}, // U+2196 north west arrow
- {FL_Left, "←"/*"\xe2\x86\x90"*/}, // U+2190 leftwards arrow
- {FL_Up, "↑"/*"\xe2\x86\x91"*/}, // U+2191 upwards arrow
- {FL_Right, "→"/*"\xe2\x86\x92"*/}, // U+2192 rightwards arrow
- {FL_Down, "↓"/*"\xe2\x86\x93"*/}, // U+2193 downwards arrow
- {FL_Page_Up, "⇞"/*"\xe2\x87\x9e"*/}, // U+21DE upwards arrow with double stroke
- {FL_Page_Down, "⇟"/*"\xe2\x87\x9f"*/}, // U+21DF downwards arrow with double stroke
- {FL_End, "↘"/*"\xe2\x86\x98"*/}, // U+2198 south east arrow
- {FL_Print, "Print"},
- {FL_Insert, "Insert"},
- {FL_Menu, "Menu"},
- {FL_Num_Lock, "Num_Lock"},
- {FL_KP_Enter, "⌤"/*"\xe2\x8c\xa4"*/}, // U+2324 up arrow head between two horizontal bars
- {FL_Shift_L, "Shift_L"},
- {FL_Shift_R, "Shift_R"},
- {FL_Control_L, "Control_L"},
- {FL_Control_R, "Control_R"},
- {FL_Caps_Lock, "⇪"/*"\xe2\x87\xaa"*/}, // U+21EA upwards white arrow from bar
- {FL_Meta_L, "Meta_L"},
- {FL_Meta_R, "Meta_R"},
- {FL_Alt_L, "Alt_L"},
- {FL_Alt_R, "Alt_R"},
- {FL_Delete, "⌦"/*"\xe2\x8c\xa6"*/} // U+2326 : erase to the right
-};
-
-
-static Fl_Text_Editor::Key_Binding extra_bindings[] = {
- // Define CMD+key accelerators...
- { 'z', FL_COMMAND, Fl_Text_Editor::kf_undo ,0},
- { 'z', FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_redo ,0},
- { 'x', FL_COMMAND, Fl_Text_Editor::kf_cut ,0},
- { 'c', FL_COMMAND, Fl_Text_Editor::kf_copy ,0},
- { 'v', FL_COMMAND, Fl_Text_Editor::kf_paste ,0},
- { 'a', FL_COMMAND, Fl_Text_Editor::kf_select_all ,0},
- { FL_Left, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0},
- { FL_Right, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0},
- { FL_Up, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0},
- { FL_Down, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0},
- { FL_Left, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0},
- { FL_Right, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0},
- { FL_Up, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0},
- { FL_Down, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0},
- { 0, 0, 0 ,0}
-};
-
-
-Fl_Cocoa_Screen_Driver::Fl_Cocoa_Screen_Driver() {
- text_editor_extra_key_bindings = extra_bindings;
- scale_ = 1.;
- default_icon = nil;
- // initialize key table
- key_table = darwin_key_table;
- key_table_size = sizeof(darwin_key_table)/sizeof(*darwin_key_table);
-}
-
-
-void Fl_Cocoa_Screen_Driver::init()
-{
- open_display();
- CGDirectDisplayID displays[MAX_SCREENS];
- CGDisplayCount count, i;
- CGRect r;
- CGGetActiveDisplayList(MAX_SCREENS, displays, &count);
- for( i = 0; i < count; i++) {
- r = CGDisplayBounds(displays[i]);
- screens[i].x = int(r.origin.x);
- screens[i].y = int(r.origin.y);
- screens[i].width = int(r.size.width);
- screens[i].height = int(r.size.height);
- //fprintf(stderr,"screen %d %dx%dx%dx%d\n",i,screens[i].x,screens[i].y,screens[i].width,screens[i].height);
- if (&CGDisplayScreenSize != NULL) {
- CGSize s = CGDisplayScreenSize(displays[i]); // from 10.3
- dpi_h[i] = screens[i].width / (s.width/25.4);
- dpi_v[i] = screens[i].height / (s.height/25.4);
- } else {
- dpi_h[i] = dpi_v[i] = 75.;
- }
- }
- num_screens = count;
-}
-
-
-void Fl_Cocoa_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n)
-{
- if (num_screens < 0) init();
-
- if ((n < 0) || (n >= num_screens))
- n = 0;
-
- float s = scale(0);
- X = screens[n].x/s;
- Y = screens[n].y/s;
- W = screens[n].width/s;
- H = screens[n].height/s;
-}
-
-
-void Fl_Cocoa_Screen_Driver::screen_dpi(float &h, float &v, int n)
-{
- if (num_screens < 0) init();
- h = v = 0.0f;
-
- if (n >= 0 && n < num_screens) {
- h = dpi_h[n];
- v = dpi_v[n];
- }
-}
-
-
-// Implements fl_beep(). See documentation in src/fl_ask.cxx.
-void Fl_Cocoa_Screen_Driver::beep(int type) {
- switch (type) {
- case FL_BEEP_DEFAULT :
- case FL_BEEP_ERROR :
- NSBeep();
- break;
- default :
- break;
- }
-}
-
-
-extern void fl_fix_focus(); // in Fl.cxx
-
-extern void *fl_capture;
-
-
-void Fl_Cocoa_Screen_Driver::grab(Fl_Window* win)
-{
- if (win) {
- if (!Fl::grab_) {
- fl_capture = (FLWindow*)(Fl_X::flx(Fl::first_window())->xid);
- Fl_Cocoa_Window_Driver::driver(Fl::first_window())->set_key_window();
- }
- Fl::grab_ = win;
- } else {
- if (Fl::grab_) {
- fl_capture = 0;
- Fl::grab_ = 0;
- fl_fix_focus();
- }
- }
-}
-
-
-static void set_selection_color(uchar r, uchar g, uchar b)
-{
- Fl::set_color(FL_SELECTION_COLOR,r,g,b);
-}
-
-
-// MacOS X currently supports two color schemes - Blue and Graphite.
-// Since we aren't emulating the Aqua interface (even if Apple would
-// let us), we use some defaults that are similar to both. The
-// Fl::scheme("plastic") color/box scheme provides a usable Aqua-like
-// look-n-feel...
-void Fl_Cocoa_Screen_Driver::get_system_colors()
-{
- open_display();
-
- Fl_Screen_Driver::get_system_colors();
-
- if (!bg2_set) Fl::background2(0xff, 0xff, 0xff);
- if (!fg_set) Fl::foreground(0, 0, 0);
- if (!bg_set) Fl::background(0xd8, 0xd8, 0xd8);
-
-#if 0
- // this would be the correct code, but it does not run on all versions
- // of OS X. Also, setting a bright selection color would require
- // some updates in Fl_Adjuster and Fl_Help_Browser
- OSStatus err;
- RGBColor c;
- err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, 24, true, &c);
- if (err)
- set_selection_color(0x00, 0x00, 0x80);
- else
- set_selection_color(c.red, c.green, c.blue);
-#else
- set_selection_color(0x00, 0x00, 0x80);
-#endif
-}
-
-
-int Fl_Cocoa_Screen_Driver::has_marked_text() const {
- return 1;
-}
-
-
-int Fl_Cocoa_Screen_Driver::insertion_point_x = 0;
-int Fl_Cocoa_Screen_Driver::insertion_point_y = 0;
-int Fl_Cocoa_Screen_Driver::insertion_point_height = 0;
-bool Fl_Cocoa_Screen_Driver::insertion_point_location_is_valid = false;
-
-void Fl_Cocoa_Screen_Driver::reset_marked_text() {
- Fl::compose_state = 0;
- next_marked_length = 0;
- insertion_point_location_is_valid = false;
-}
-
-// computes window coordinates & height of insertion point
-int Fl_Cocoa_Screen_Driver::insertion_point_location(int *px, int *py, int *pheight)
-// return true if the current coordinates of the insertion point are available
-{
- if ( ! insertion_point_location_is_valid ) return false;
- *px = insertion_point_x;
- *py = insertion_point_y;
- *pheight = insertion_point_height;
- return true;
-}
-
-void Fl_Cocoa_Screen_Driver::insertion_point_location(int x, int y, int height) {
- insertion_point_location_is_valid = true;
- insertion_point_x = x;
- insertion_point_y = y;
- insertion_point_height = height;
-}
-
-int Fl_Cocoa_Screen_Driver::compose(int &del) {
- int condition;
- int has_text_key = Fl::compose_state || Fl::e_keysym <= '~' || Fl::e_keysym == FL_Iso_Key ||
- Fl::e_keysym == FL_JIS_Underscore || Fl::e_keysym == FL_Yen ||
- (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last && Fl::e_keysym != FL_KP_Enter);
- condition = Fl::e_state&(FL_META | FL_CTRL) ||
- (Fl::e_keysym >= FL_Shift_L && Fl::e_keysym <= FL_Alt_R) || // called from flagsChanged
- !has_text_key ;
- if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key
- del = Fl::compose_state;
- Fl::compose_state = next_marked_length;
- return 1;
-}
-
-
-int Fl_Cocoa_Screen_Driver::input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input)
-{
- switch (key) {
- case FL_Delete: {
- if (mods==0) return input->kf_delete_char_right(); // Delete (OSX-HIG,TE,SA,WOX)
- if (mods==FL_CTRL) return input->kf_delete_char_right(); // Ctrl-Delete (??? TE,!SA,!WOX)
- if (mods==FL_ALT) return input->kf_delete_word_right(); // Alt-Delete (OSX-HIG,TE,SA)
- return 0; // ignore other combos, pass to parent
- }
-
- case FL_Left:
- if (mods==0) return input->kf_move_char_left(); // Left (OSX-HIG)
- if (mods==FL_ALT) return input->kf_move_word_left(); // Alt-Left (OSX-HIG)
- if (mods==FL_META) return input->kf_move_sol(); // Meta-Left (OSX-HIG)
- if (mods==FL_CTRL) return input->kf_move_sol(); // Ctrl-Left (TE/SA)
- return 0; // ignore other combos, pass to parent
-
- case FL_Right:
- if (mods==0) return input->kf_move_char_right(); // Right (OSX-HIG)
- if (mods==FL_ALT) return input->kf_move_word_right(); // Alt-Right (OSX-HIG)
- if (mods==FL_META) return input->kf_move_eol(); // Meta-Right (OSX-HIG)
- if (mods==FL_CTRL) return input->kf_move_eol(); // Ctrl-Right (TE/SA)
- return 0; // ignore other combos, pass to parent
-
- case FL_Up:
- if (mods==0) return input->kf_lines_up(1); // Up (OSX-HIG)
- if (mods==FL_CTRL) return input->kf_page_up(); // Ctrl-Up (TE !HIG)
- if (mods==FL_ALT) return input->kf_move_up_and_sol(); // Alt-Up (OSX-HIG)
- if (mods==FL_META) return input->kf_top(); // Meta-Up (OSX-HIG)
- return 0; // ignore other combos, pass to parent
-
- case FL_Down:
- if (mods==0) return input->kf_lines_down(1); // Dn (OSX-HIG)
- if (mods==FL_CTRL) return input->kf_page_down(); // Ctrl-Dn (TE !HIG)
- if (mods==FL_ALT) return input->kf_move_down_and_eol(); // Alt-Dn (OSX-HIG)
- if (mods==FL_META) return input->kf_bottom(); // Meta-Dn (OSX-HIG)
- return 0; // ignore other combos, pass to parent
-
- case FL_Page_Up:
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- // OSX-HIG recommends Alt increase one semantic unit, Meta next higher..
- if (mods==0) return input->kf_page_up(); // PgUp (OSX-HIG)
- if (mods==FL_ALT) return input->kf_page_up(); // Alt-PageUp (OSX-HIG)
- if (mods==FL_META) return input->kf_top(); // Meta-PageUp (OSX-HIG,!TE)
- return 0; // ignore other combos, pass to parent
-
- case FL_Page_Down:
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- // OSX-HIG recommends Alt increase one semantic unit, Meta next higher..
- if (mods==0) return input->kf_page_down(); // PgDn (OSX-HIG)
- if (mods==FL_ALT) return input->kf_page_down(); // Alt-PageDn (OSX-HIG)
- if (mods==FL_META) return input->kf_bottom(); // Meta-PageDn (OSX-HIG,!TE)
- return 0; // ignore other combos, pass to parent
-
- case FL_Home:
- if (mods==0) return input->kf_top(); // Home (OSX-HIG)
- if (mods==FL_ALT) return input->kf_top(); // Alt-Home (???)
- return 0; // ignore other combos, pass to parent
-
- case FL_End:
- if (mods==0) return input->kf_bottom(); // End (OSX-HIG)
- if (mods==FL_ALT) return input->kf_bottom(); // Alt-End (???)
- return 0; // ignore other combos, pass to parent
-
- case FL_BackSpace:
- if (mods==0) return input->kf_delete_char_left(); // Backspace (OSX-HIG)
- if (mods==FL_CTRL) return input->kf_delete_char_left(); // Ctrl-Backspace (TE/SA)
- if (mods==FL_ALT) return input->kf_delete_word_left(); // Alt-Backspace (OSX-HIG)
- if (mods==FL_META) return input->kf_delete_sol(); // Meta-Backspace (OSX-HIG,!TE)
- return 0; // ignore other combos, pass to parent
- }
- return -1;
-}
-
-void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
-{
- width = (int)CGBitmapContextGetWidth((CGContextRef)off);
- height = (int)CGBitmapContextGetHeight((CGContextRef)off);
-}
-
-Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window,
- bool may_capture_subwins, bool *did_capture_subwins)
-{
- int bpp, bpr;
- uchar *base, *p;
- if (!window) { // read from offscreen buffer
- float s = 1;
- CGContextRef src = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc(); // get bitmap context
- base = (uchar *)CGBitmapContextGetData(src); // get data
- if(!base) return NULL;
- int sw = (int)CGBitmapContextGetWidth(src);
- int sh = (int)CGBitmapContextGetHeight(src);
- if( (sw - X < w) || (sh - Y < h) ) return NULL;
- bpr = (int)CGBitmapContextGetBytesPerRow(src);
- bpp = (int)CGBitmapContextGetBitsPerPixel(src)/8;
- Fl_Image_Surface *imgs = (Fl_Image_Surface*)Fl_Surface_Device::surface();
- int fltk_w, fltk_h;
- imgs->printable_rect(&fltk_w, &fltk_h);
- s = sw / float(fltk_w);
- X *= s; Y *= s; w *= s; h *= s;
- if (X + w > sw) w = sw - X;
- if (Y + h > sh) h = sh - Y;
- // Copy the image from the off-screen buffer to the memory buffer.
- int idx, idy; // Current X & Y in image
- uchar *pdst, *psrc;
- p = new uchar[w * h * 4];
- for (idy = Y, pdst = p; idy < h + Y; idy ++) {
- for (idx = 0, psrc = base + idy * bpr + X * bpp; idx < w; idx ++, psrc += bpp, pdst += 4) {
- pdst[0] = psrc[0]; // R
- pdst[1] = psrc[1]; // G
- pdst[2] = psrc[2]; // B
- }
- }
- bpr = 0;
- } else { // read from window
- Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window);
- CGImageRef cgimg = d->CGImage_from_window_rect(X, Y, w, h, may_capture_subwins);
- if (did_capture_subwins) *did_capture_subwins = may_capture_subwins;
- if (!cgimg) {
- return NULL;
- }
- w = (int)CGImageGetWidth(cgimg);
- h = (int)CGImageGetHeight(cgimg);
- Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
- Fl_Surface_Device::push_current(surf);
- ((Fl_Quartz_Graphics_Driver*)fl_graphics_driver)->draw_CGImage(cgimg, 0, 0, w, h, 0, 0, w, h);
- CGContextRef gc = (CGContextRef)fl_graphics_driver->gc();
- w = (int)CGBitmapContextGetWidth(gc);
- h = (int)CGBitmapContextGetHeight(gc);
- bpr = (int)CGBitmapContextGetBytesPerRow(gc);
- bpp = (int)CGBitmapContextGetBitsPerPixel(gc)/8;
- base = (uchar*)CGBitmapContextGetData(gc);
- p = new uchar[bpr * h];
- memcpy(p, base, bpr * h);
- Fl_Surface_Device::pop_current();
- delete surf;
- CFRelease(cgimg);
- }
- Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, 4, bpr);
- rgb->alloc_array = 1;
- return rgb;
-}
-
-void Fl_Cocoa_Screen_Driver::set_spot(int /*font*/, int size, int X, int Y, int /*W*/, int /*H*/, Fl_Window* /*win*/) {
- Fl_Cocoa_Screen_Driver::insertion_point_location(X, Y, size);
-}
-
-void Fl_Cocoa_Screen_Driver::reset_spot() {
- Fl_Cocoa_Screen_Driver::reset_marked_text();
-}
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
deleted file mode 100644
index 358523dbd..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H
+++ /dev/null
@@ -1,168 +0,0 @@
-//
-// Definition of Apple Cocoa window driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2025 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Cocoa_Window_Driver.H
- \brief Definition of Apple Cocoa window driver.
- */
-
-#ifndef FL_COCOA_WINDOW_DRIVER_H
-#define FL_COCOA_WINDOW_DRIVER_H
-
-#include "../../Fl_Window_Driver.H"
-#include <FL/Fl_Plugin.H>
-#include <ApplicationServices/ApplicationServices.h>
-
-class Fl_Image;
-class Fl_Window;
-#ifdef __OBJC__
-@class CALayer;
-@class NSCursor;
-@class NSImage;
-@class FLWindow;
-@class NSOpenGLContext;
-@class NSOpenGLPixelFormat;
-@class NSView;
-@class NSWindow;
-#else
-class CALayer;
-class NSCursor;
-class NSImage;
-class FLWindow;
-class NSOpenGLContext;
-class NSOpenGLPixelFormat;
-class NSView;
-class NSWindow;
-#endif // __OBJC__
-
-/**
- \cond DriverDev
- \addtogroup DriverDeveloper
- \{
- */
-
-/*
- Move everything here that manages the native window interface.
-
- There is one window driver for each Fl_Window. Window drivers manage window
- actions such as resizing, events, decoration, fullscreen modes, etc. . All
- drawing and rendering is managed by the Surface device and the associated
- graphics driver.
-
- - window specific event handling
- - window types and styles, depth, etc.
- - decorations
-
- ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx?
- */
-
-/**
- \}
- \endcond
- */
-
-
-class Fl_Cocoa_Window_Driver : public Fl_Window_Driver
-{
-private:
- struct shape_data_type {
- Fl_Image* shape_; ///< shape image
- CGImageRef mask;
- } *shape_data_;
- void shape_bitmap_(Fl_Image* b);
- void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE;
- CGRect* subRect_; // makes sure subwindow remains inside its parent window
- // stores 3 binary flags: whether window is mapped to retina display; whether resolution just changed;
- // whether window's view received the [FLView view_did_resize] message
- unsigned window_flags_;
-public:
- Fl_Cocoa_Window_Driver(Fl_Window*);
- ~Fl_Cocoa_Window_Driver();
- static inline Fl_Cocoa_Window_Driver* driver(const Fl_Window *w) {return (Fl_Cocoa_Window_Driver*)Fl_Window_Driver::driver(w);}
- CGContextRef gc; // graphics context
- NSCursor *cursor;
- static void q_release_context(Fl_Cocoa_Window_Driver *x = 0); // free all resources associated with gc
- static CGImageRef capture_decorated_window_10_5(NSWindow *nswin);
- void set_key_window();
- bool mapped_to_retina(); // is window mapped to retina display?
- void mapped_to_retina(bool); // sets whether window is mapped to retina display
- bool changed_resolution(); // did window just moved to display with another resolution?
- void changed_resolution(bool);// sets whether window just moved to display with another resolution
- bool view_resized(); // did window's view receive [FLView view_did_resize] message?
- void view_resized(bool b); // sets whether window's view received [FLView view_did_resize] message
- bool through_resize(); // did Fl_Window::resize() run already
- void through_resize(bool b); // set whether Fl_Window::resize() run already
- CGRect* subRect() { return subRect_; } // getter
- void subRect(CGRect *r) { subRect_ = r; } // setter
- static void destroy(FLWindow*);
- CGImageRef CGImage_from_window_rect(int x, int y, int w, int h, bool capture_subwins = true);
-
- // --- window data
- int decorated_w() FL_OVERRIDE;
- int decorated_h() FL_OVERRIDE;
- const Fl_Image* shape() FL_OVERRIDE;
-
- // --- window management
- void makeWindow() FL_OVERRIDE;
- void take_focus() FL_OVERRIDE;
- void flush() FL_OVERRIDE;
- void flush_overlay() FL_OVERRIDE;
- void draw_begin() FL_OVERRIDE;
- void draw_end() FL_OVERRIDE;
- void make_current() FL_OVERRIDE;
- void label(const char *name, const char *mininame) FL_OVERRIDE;
- void show() FL_OVERRIDE;
- void resize(int X,int Y,int W,int H) FL_OVERRIDE;
- void hide() FL_OVERRIDE;
- void map() FL_OVERRIDE;
- void unmap() FL_OVERRIDE;
- void fullscreen_on() FL_OVERRIDE;
- void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE;
- void fullscreen_screens(bool on_off) FL_OVERRIDE;
- void maximize() FL_OVERRIDE;
- void un_maximize() FL_OVERRIDE;
- void use_border() FL_OVERRIDE;
- void size_range() FL_OVERRIDE;
- void iconize() FL_OVERRIDE;
- void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE;
- // --- window cursor stuff
- int set_cursor(Fl_Cursor) FL_OVERRIDE;
- int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE;
-
- void shape(const Fl_Image* img) FL_OVERRIDE;
- // next 4 are in Fl_cocoa.mm because they use Objective-c
- void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE;
- void wait_for_expose() FL_OVERRIDE;
- void draw_titlebar_to_context(CGContextRef gc, int w, int h);
- int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE;
-
- //icons
- void icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE;
- NSImage *icon_image;
-
- fl_uintptr_t os_id() FL_OVERRIDE;
-};
-
-class Fl_Cocoa_Plugin : public Fl_Plugin {
-public:
- Fl_Cocoa_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { }
- virtual const char *klass() { return "fltk:cocoa"; }
- virtual const char *name() = 0;
- virtual void resize(Fl_Gl_Window *glw, int x, int y, int w, int h) = 0;
-};
-
-#endif // FL_COCOA_WINDOW_DRIVER_H
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
deleted file mode 100644
index 55d1bea32..000000000
--- a/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
+++ /dev/null
@@ -1,294 +0,0 @@
-//
-// Definition of Apple Cocoa window driver.
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_Cocoa_Window_Driver.H"
-#include "../../Fl_Screen_Driver.H"
-#include "../Quartz/Fl_Quartz_Graphics_Driver.H"
-#include <FL/Fl_Double_Window.H>
-#include <FL/Fl_Overlay_Window.H>
-#include <FL/Fl_Image_Surface.H>
-#include <FL/fl_draw.H>
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <math.h>
-
-
-Fl_Cocoa_Window_Driver::Fl_Cocoa_Window_Driver(Fl_Window *win)
-: Fl_Window_Driver(win)
-{
- cursor = nil;
- window_flags_ = 0;
- icon_image = NULL;
- screen_num_ = 0;
- shape_data_ = NULL;
-}
-
-
-void Fl_Cocoa_Window_Driver::take_focus()
-{
- set_key_window();
-}
-
-
-void Fl_Cocoa_Window_Driver::flush_overlay()
-{
- Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
- int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY) | (overlay() == oWindow);
- pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
-
- if (!oWindow->shown()) return;
- pWindow->make_current(); // make sure fl_gc is non-zero
- if (!other_xid) {
- other_xid = new Fl_Image_Surface(oWindow->w(), oWindow->h(), 1);
- oWindow->clear_damage(FL_DAMAGE_ALL);
- }
- if (oWindow->damage() & ~FL_DAMAGE_EXPOSE) {
- Fl_X *myi = Fl_X::flx(pWindow);
- fl_clip_region(myi->region); myi->region = 0;
- Fl_Surface_Device::push_current(other_xid);
- draw();
- Fl_Surface_Device::pop_current();
- }
- if (erase_overlay) fl_clip_region(0);
- fl_copy_offscreen(0, 0, oWindow->w(), oWindow->h(), other_xid->offscreen(), 0, 0);
- if (overlay() == oWindow) oWindow->draw_overlay();
-}
-
-
-void Fl_Cocoa_Window_Driver::draw_begin()
-{
- if (!Fl_Surface_Device::surface()->driver()->has_feature(Fl_Graphics_Driver::NATIVE)) return;
- CGContextRef my_gc = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc();
- if (shape_data_) {
- if (shape_data_->mask) {
- CGContextClipToMask(my_gc, CGRectMake(0,0,w(),h()), shape_data_->mask); // requires Mac OS 10.4
- }
- CGContextSaveGState(my_gc);
- }
-}
-
-
-void Fl_Cocoa_Window_Driver::draw_end()
-{
- if (Fl_Surface_Device::surface()->driver()->has_feature(Fl_Graphics_Driver::NATIVE)) {
- CGContextRef my_gc = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc();
- if (shape_data_) CGContextRestoreGState(my_gc);
- }
-}
-
-
-
-static void MyProviderReleaseData (void *info, const void *data, size_t size) {
- delete[] (uchar*)data;
-}
-
-// bitwise inversion of all 4-bit quantities
-static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
-
-static inline uchar swap_byte(const uchar b) {
- // reverse the order of bits of byte b: 1->8 becomes 8->1
- return (swapped[b & 0xF] << 4) | swapped[b >> 4];
-}
-
-
-void Fl_Cocoa_Window_Driver::shape_bitmap_(Fl_Image* b) {
- shape_data_->shape_ = b;
- if (b) {
- // complement mask bits and perform bitwise inversion of all bytes and also reverse top and bottom
- int bytes_per_row = (b->w() + 7)/8;
- uchar *from = new uchar[bytes_per_row * b->h()];
- for (int i = 0; i < b->h(); i++) {
- uchar *p = (uchar*)(*b->data()) + bytes_per_row * i;
- uchar *last = p + bytes_per_row;
- uchar *q = from + (b->h() - 1 - i) * bytes_per_row;
- while (p < last) {
- *q++ = swap_byte(~*p++);
- }
- }
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, bytes_per_row * b->h(), MyProviderReleaseData);
- shape_data_->mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false);
- CFRelease(provider);
- }
-}
-
-
-void Fl_Cocoa_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
- int i, d = img->d(), w = img->w(), h = img->h();
- shape_data_->shape_ = img;
- if (shape_data_->shape_) {
- // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits
- int bytes_per_row = w * d;
- uchar *from = new uchar[w * h];
- for ( i = 0; i < h; i++) {
- uchar *p = (uchar*)(*img->data()) + bytes_per_row * i + offset;
- uchar *last = p + bytes_per_row;
- uchar *q = from + (h - 1 - i) * w;
- while (p < last) {
- if (d == 3) {
- unsigned u = *p++;
- u += *p++;
- u += *p++;
- *q++ = ~(u/3);
- }
- else {
- *q++ = ~(*p);
- p += d;
- }
- }
- }
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData);
- shape_data_->mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
- CFRelease(provider);
- }
-}
-
-
-void Fl_Cocoa_Window_Driver::shape(const Fl_Image* img) {
- if (shape_data_) {
- if (shape_data_->mask) { CGImageRelease(shape_data_->mask); }
- }
- else {
- shape_data_ = new shape_data_type;
- }
- memset(shape_data_, 0, sizeof(shape_data_type));
- int d = img->d();
- if (d && img->count() >= 2) {
- shape_pixmap_((Fl_Image*)img);
- shape_data_->shape_ = (Fl_Image*)img;
- }
- else if (d == 0) shape_bitmap_((Fl_Image*)img);
- else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
- else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
- pWindow->border(false);
-}
-
-
-void Fl_Cocoa_Window_Driver::hide() {
- Fl_X* ip = Fl_X::flx(pWindow);
- // MacOS X manages a single pointer per application. Make sure that hiding
- // a toplevel window will not leave us with some random pointer shape, or
- // worst case, an invisible pointer
- if (ip && !parent()) pWindow->cursor(FL_CURSOR_DEFAULT);
- if ( hide_common() ) return;
- q_release_context(this);
- if ( ip->xid == (fl_uintptr_t)fl_window )
- fl_window = 0;
- if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
- destroy((FLWindow*)ip->xid);
- delete subRect();
- delete ip;
-}
-
-
-int Fl_Cocoa_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data)
-{
- if ( (src_x < 0) || (src_y < 0) )
- return 1;
- if ( (src_x+src_w > pWindow->w()) || (src_y+src_h > pWindow->h()) )
- return 1;
- CGImageRef img = CGImage_from_window_rect(src_x, src_y, src_w, src_h);
- if (!img)
- return 1;
- // the current surface is generally the display, but is an Fl_Image_Surface when scrolling an Fl_Overlay_Window
- Fl_Quartz_Graphics_Driver *qgd = (Fl_Quartz_Graphics_Driver*)Fl_Surface_Device::surface()->driver();
- float s = qgd->scale();
- qgd->draw_CGImage(img, dest_x, dest_y, (int)lround(s*src_w), (int)lround(s*src_h), 0, 0, src_w, src_h);
- CFRelease(img);
- return 0;
-}
-
-static const unsigned mapped_mask = 1;
-static const unsigned changed_mask = 2;
-static const unsigned view_resized_mask = 4;
-static const unsigned through_resize_mask = 8;
-
-bool Fl_Cocoa_Window_Driver::mapped_to_retina() {
- return window_flags_ & mapped_mask;
-}
-
-void Fl_Cocoa_Window_Driver::mapped_to_retina(bool b) {
- if (b) window_flags_ |= mapped_mask;
- else window_flags_ &= ~mapped_mask;
-}
-
-bool Fl_Cocoa_Window_Driver::changed_resolution() {
- return window_flags_ & changed_mask;
-}
-
-void Fl_Cocoa_Window_Driver::changed_resolution(bool b) {
- if (b) window_flags_ |= changed_mask;
- else window_flags_ &= ~changed_mask;
-}
-
-bool Fl_Cocoa_Window_Driver::view_resized() {
- return window_flags_ & view_resized_mask;
-}
-
-void Fl_Cocoa_Window_Driver::view_resized(bool b) {
- if (b) window_flags_ |= view_resized_mask;
- else window_flags_ &= ~view_resized_mask;
-}
-
-bool Fl_Cocoa_Window_Driver::through_resize() {
- return window_flags_ & through_resize_mask;
-}
-
-void Fl_Cocoa_Window_Driver::through_resize(bool b) {
- if (b) window_flags_ |= through_resize_mask;
- else window_flags_ &= ~through_resize_mask;
-}
-
-const Fl_Image* Fl_Cocoa_Window_Driver::shape() {
- return shape_data_ ? shape_data_->shape_ : NULL;
-}
-
-/* Returns images of the capture of the window title-bar.
- On the Mac OS platform, left, bottom and right are returned NULL; top is returned with depth 4.
- */
-void Fl_Cocoa_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right)
-{
- top = left = bottom = right = NULL;
- int htop, hleft, hright, hbottom;
- Fl_Cocoa_Window_Driver::decoration_sizes(&htop, &hleft, &hright, &hbottom);
- if (htop == 0) return; // when window is fullscreen
- CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
- float s = Fl::screen_driver()->scale(screen_num());
- int scaled_w = int(w() * s);
- const int factor = (mapped_to_retina() ? 2 : 1);
- int data_w = factor * scaled_w, data_h = factor * htop;
- uchar *rgba = new uchar[4 * data_w * data_h];
- CGContextRef auxgc = CGBitmapContextCreate(rgba, data_w, data_h, 8, 4 * data_w, cspace, kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(cspace);
- CGContextClearRect(auxgc, CGRectMake(0,0,data_w,data_h));
- CGContextScaleCTM(auxgc, factor, factor);
- draw_titlebar_to_context(auxgc, scaled_w, htop);
- top = new Fl_RGB_Image(rgba, data_w, data_h, 4);
- top->alloc_array = 1;
- top->scale(w(),htop, s <1 ? 0 : 1, 1);
- CGContextRelease(auxgc);
-}
-
-
-FLWindow *fl_mac_xid(const Fl_Window *win) {
- return (FLWindow*)Fl_Window_Driver::xid(win);
-}
-
-
-Fl_Window *fl_mac_find(FLWindow *xid) {
- return Fl_Window_Driver::find((fl_uintptr_t)xid);
-}
diff --git a/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H b/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H
deleted file mode 100644
index 2de8bde64..000000000
--- a/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Definition of class Fl_MacOS_Sys_Menu_Bar_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2017 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef Fl_MacOS_Sys_Menu_Bar_Driver_H
-#define Fl_MacOS_Sys_Menu_Bar_Driver_H
-
-#include "../../Fl_Sys_Menu_Bar_Driver.H"
-
-class Fl_MacOS_Sys_Menu_Bar_Driver : public Fl_Sys_Menu_Bar_Driver {
-public:
- Fl_Menu_Item *window_menu_items;
- int first_window_menu_item;
- Fl_MacOS_Sys_Menu_Bar_Driver();
- virtual ~Fl_MacOS_Sys_Menu_Bar_Driver();
- void update() FL_OVERRIDE;
- void draw() FL_OVERRIDE;
- void about(Fl_Callback *cb, void *data) FL_OVERRIDE;
- int add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) FL_OVERRIDE;
- int add(const char* str) FL_OVERRIDE;
- int insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) FL_OVERRIDE;
- void menu(const Fl_Menu_Item *m) FL_OVERRIDE;
- void shortcut (int i, int s) FL_OVERRIDE;
- void setonly (Fl_Menu_Item *item) FL_OVERRIDE;
- void clear() FL_OVERRIDE;
- int clear_submenu(int index) FL_OVERRIDE;
- void remove(int index) FL_OVERRIDE;
- void replace(int index, const char *name) FL_OVERRIDE;
- void mode(int i, int fl) FL_OVERRIDE;
- void create_window_menu() FL_OVERRIDE;
- void new_window(Fl_Window *win);
- void remove_window(Fl_Window *win);
- void rename_window(Fl_Window *win);
- static Fl_MacOS_Sys_Menu_Bar_Driver* driver();
- void play_menu(const Fl_Menu_Item *) FL_OVERRIDE;
-};
-
-
-#endif /* Fl_MacOS_Sys_Menu_Bar_Driver_H */
diff --git a/src/drivers/Darwin/Fl_Darwin_System_Driver.H b/src/drivers/Darwin/Fl_Darwin_System_Driver.H
deleted file mode 100644
index 7dd0ae6da..000000000
--- a/src/drivers/Darwin/Fl_Darwin_System_Driver.H
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// Definition of Apple Darwin system driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2021 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Darwin_System_Driver.H
- \brief Definition of Apple Darwin system driver.
- */
-
-#ifndef FL_DARWIN_SYSTEM_DRIVER_H
-#define FL_DARWIN_SYSTEM_DRIVER_H
-
-#include "../Posix/Fl_Posix_System_Driver.H"
-#include <stdlib.h>
-#include <unistd.h>
-
-/*
- Move everything here that manages the system interface.
-
- There is exactly one system driver.
-
- - filename and pathname management
- - directory and file access
- - system time and system timer
- - multithreading
- */
-
-class Fl_Darwin_System_Driver : public Fl_Posix_System_Driver
-{
-public:
- Fl_Darwin_System_Driver();
- int single_arg(const char *arg) FL_OVERRIDE;
- int arg_and_value(const char *name, const char *value) FL_OVERRIDE;
- int clocale_vprintf(FILE *output, const char *format, va_list args) FL_OVERRIDE;
- int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) FL_OVERRIDE;
- int clocale_vsscanf(const char *input, const char *format, va_list args) FL_OVERRIDE;
- static void *get_carbon_function(const char *name);
- static int calc_mac_os_version(); // computes the fl_mac_os_version global variable
- static unsigned short *compute_macKeyLookUp();
-
- int filename_list(const char *d, dirent ***list,
- int (*sort)(struct dirent **, struct dirent **),
- char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE;
- int open_uri(const char *uri, char *msg, int msglen) FL_OVERRIDE;
- int need_test_shortcut_extra() FL_OVERRIDE {return 1;}
- int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) FL_OVERRIDE;
- void newUUID(char *uuidBuffer) FL_OVERRIDE;
- char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
- const char *application) FL_OVERRIDE;
- const char *local_to_latin1(const char *t, int n) FL_OVERRIDE;
- const char *latin1_to_local(const char *t, int n) FL_OVERRIDE;
- const char *local_to_mac_roman(const char *t, int n) FL_OVERRIDE;
- const char *mac_roman_to_local(const char *t, int n) FL_OVERRIDE;
- void tree_draw_expando_button(int x, int y, bool state, bool active) FL_OVERRIDE;
- int tree_connector_style() FL_OVERRIDE;
- const char *filename_name(const char *buf) FL_OVERRIDE;
- void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE;
- void add_fd(int fd, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE;
- void remove_fd(int, int when) FL_OVERRIDE;
- void remove_fd(int) FL_OVERRIDE;
- void open_callback(void (*)(const char *)) FL_OVERRIDE;
- const char *shift_name() FL_OVERRIDE;
- const char *meta_name() FL_OVERRIDE;
- const char *alt_name() FL_OVERRIDE;
- const char *control_name() FL_OVERRIDE;
- Fl_Sys_Menu_Bar_Driver *sys_menu_bar_driver() FL_OVERRIDE;
- double wait(double time_to_wait) FL_OVERRIDE;
- int ready() FL_OVERRIDE;
- int filename_relative(char *to, int tolen, const char *dest_dir, const char *base_dir) FL_OVERRIDE;
-};
-
-#endif // FL_DARWIN_SYSTEM_DRIVER_H
diff --git a/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx b/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
deleted file mode 100644
index c11a95f94..000000000
--- a/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
+++ /dev/null
@@ -1,339 +0,0 @@
-//
-// Definition of Apple Darwin system driver.
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Darwin_System_Driver.H"
-#include "../Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H"
-#include <FL/Fl.H>
-#include <FL/Fl_File_Browser.H>
-#include <FL/Fl_Tree_Prefs.H>
-#include <FL/Fl_Pixmap.H>
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-#include "../../flstring.h"
-#include <string.h>
-#include <xlocale.h> // 10.4
-#include <locale.h>
-#include <stdio.h>
-#include <dlfcn.h>
-#include <pwd.h>
-#include <sys/param.h>
-#include <sys/ucred.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-
-const char *Fl_Darwin_System_Driver::shift_name() {
- return "⇧\\"; // "\xe2\x87\xa7\\"; // U+21E7 (upwards white arrow)
-}
-const char *Fl_Darwin_System_Driver::meta_name() {
- return "⌘\\"; // "\xe2\x8c\x98\\"; // U+2318 (place of interest sign)
-}
-const char *Fl_Darwin_System_Driver::alt_name() {
- return "⌥\\"; // "\xe2\x8c\xa5\\"; // U+2325 (option key)
-}
-const char *Fl_Darwin_System_Driver::control_name() {
- return "⌃\\"; // "\xe2\x8c\x83\\"; // U+2303 (up arrowhead)
-}
-
-Fl_Darwin_System_Driver::Fl_Darwin_System_Driver() : Fl_Posix_System_Driver() {
- if (fl_mac_os_version == 0) fl_mac_os_version = calc_mac_os_version();
- command_key = FL_META;
- control_key = FL_CTRL;
-}
-
-int Fl_Darwin_System_Driver::single_arg(const char *arg) {
- // The Finder application in MacOS X passes the "-psn_N_NNNNN" option to all apps.
- return (strncmp(arg, "psn_", 4) == 0);
-}
-
-int Fl_Darwin_System_Driver::arg_and_value(const char *name, const char *value) {
- // Xcode in MacOS X may pass "-NSDocumentRevisionsDebugMode YES"
- return strcmp(name, "NSDocumentRevisionsDebugMode") == 0;
-}
-
-static locale_t postscript_locale = NULL;
-
-int Fl_Darwin_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) {
- if (!postscript_locale)
- postscript_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
- return vfprintf_l(output, postscript_locale, format, args); // 10.4
-}
-
-int Fl_Darwin_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) {
- if (!postscript_locale)
- postscript_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
- return vsnprintf_l(output, output_size, postscript_locale, format, args); // 10.4
-}
-
-int Fl_Darwin_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) {
- if (!postscript_locale)
- postscript_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
- return vsscanf_l(input, postscript_locale, format, args); // 10.4
-}
-
-
-// Returns the address of a Carbon function after dynamically loading the Carbon library if needed.
-void *Fl_Darwin_System_Driver::get_carbon_function(const char *function_name) {
- static void *carbon = ::dlopen("/System/Library/Frameworks/Carbon.framework/Carbon", RTLD_LAZY);
- return (carbon ? dlsym(carbon, function_name) : NULL);
-}
-
-int Fl_Darwin_System_Driver::filename_list(const char *d, dirent ***list,
- int (*sort)(struct dirent **, struct dirent **),
- char *errmsg, int errmsg_sz) {
- int dirlen;
- char *dirloc;
- // Assume that locale encoding is no less dense than UTF-8
- dirlen = (int)strlen(d);
- dirloc = (char *)d;
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- int n = scandir(dirloc, list, 0, (int(*)(const struct dirent**,const struct dirent**))sort);
-# else
- int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort);
-# endif
- if (n==-1) {
- if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno));
- return -1;
- }
- // convert every filename to UTF-8, and append a '/' to all
- // filenames that are directories
- int i;
- char *fullname = (char*)malloc(dirlen+FL_PATH_MAX+3); // Add enough extra for two /'s and a nul
- // Use memcpy for speed since we already know the length of the string...
- memcpy(fullname, d, dirlen+1);
- char *name = fullname + dirlen;
- if (name!=fullname && name[-1]!='/') *name++ = '/';
- for (i=0; i<n; i++) {
- int newlen;
- dirent *de = (*list)[i];
- int len = (int)strlen(de->d_name);
- newlen = len;
- dirent *newde = (dirent*)malloc(de->d_name - (char*)de + newlen + 2); // Add space for a / and a nul
- // Conversion to UTF-8
- memcpy(newde, de, de->d_name - (char*)de);
- strcpy(newde->d_name, de->d_name);
- // Check if dir (checks done on "old" name as we need to interact with
- // the underlying OS)
- if (de->d_name[len-1]!='/' && len<=FL_PATH_MAX) {
- // Use memcpy for speed since we already know the length of the string...
- memcpy(name, de->d_name, len+1);
- if (fl_filename_isdir(fullname)) {
- char *dst = newde->d_name + newlen;
- *dst++ = '/';
- *dst = 0;
- }
- }
- free(de);
- (*list)[i] = newde;
- }
- free(fullname);
- return n;
-}
-
-
-int Fl_Darwin_System_Driver::open_uri(const char *uri, char *msg, int msglen)
-{
- char *argv[3]; // Command-line arguments
- argv[0] = (char*)"open";
- argv[1] = (char*)uri;
- argv[2] = (char*)0;
- if (msg) snprintf(msg, msglen, "open %s", uri);
- return run_program("/usr/bin/open", argv, msg, msglen) != 0;
-}
-
-int Fl_Darwin_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon)
-{
- // MacOS X and Darwin use getfsstat() system call...
- int numfs; // Number of file systems
- struct statfs *fs; // Buffer for file system info
- int num_files = 0;
-
- // We always have the root filesystem.
- browser->add("/", icon);
-
- // Get the mounted filesystems...
- numfs = getfsstat(NULL, 0, MNT_NOWAIT);
- if (numfs > 0) {
- // We have file systems, get them...
- fs = new struct statfs[numfs];
- getfsstat(fs, sizeof(struct statfs) * numfs, MNT_NOWAIT);
-
- // Add filesystems to the list...
- for (int i = 0; i < numfs; i ++) {
- // Ignore "/", "/dev", and "/.vol"...
- if (fs[i].f_mntonname[1] && strcmp(fs[i].f_mntonname, "/dev") &&
- strcmp(fs[i].f_mntonname, "/.vol")) {
- snprintf(filename, lname, "%s/", fs[i].f_mntonname);
- browser->add(filename, icon);
- }
- num_files ++;
- }
-
- // Free the memory used for the file system info array...
- delete[] fs;
- }
- return num_files;
-}
-
-void Fl_Darwin_System_Driver::newUUID(char *uuidBuffer)
-{
- CFUUIDRef theUUID = CFUUIDCreate(NULL);
- CFUUIDBytes b = CFUUIDGetUUIDBytes(theUUID);
- snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7,
- b.byte8, b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15);
- CFRelease(theUUID);
-}
-
-/*
- * returns pointer to the filename, or null if name ends with ':'
- */
-const char *Fl_Darwin_System_Driver::filename_name( const char *name )
-{
- const char *p, *q;
- if (!name) return (0);
- for ( p = q = name ; *p ; ) {
- if ( ( p[0] == ':' ) && ( p[1] == ':' ) ) {
- q = p+2;
- p++;
- }
- else if (p[0] == '/') {
- q = p + 1;
- }
- p++;
- }
- return q;
-}
-
-// These function assume a western code page. If you need to support
-// scripts that are not part of this code page, you might want to
-// take a look at FLTK2, which uses utf8 for text encoding.
-//
-// By keeping these conversion tables in their own module, they will not
-// be statically linked (by a smart linker) unless actually used.
-//
-// On MS-Windows, nothing need to be converted. We simply return the
-// original pointer.
-//
-// Most X11 implementations seem to default to Latin-1 as a code since it
-// is a superset of ISO 8859-1, the original Western codepage on X11.
-//
-// Apple's OS X however renders text in MacRoman for western settings. The
-// lookup tables below will convert all common character codes and replace
-// unknown characters with an upside-down question mark.
-
-// This table converts Windows-1252/Latin 1 into MacRoman encoding
-static uchar latin2roman[128] = {
-0xdb, 0xc0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, 0xf6, 0xe4, 0xc0, 0xdc, 0xce, 0xc0, 0xc0, 0xc0,
-0xc0, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, 0xf7, 0xaa, 0xc0, 0xdd, 0xcf, 0xc0, 0xc0, 0xd9,
-0xca, 0xc1, 0xa2, 0xa3, 0xc0, 0xb4, 0xc0, 0xa4, 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xc0, 0xa8, 0xf8,
-0xa1, 0xb1, 0xc0, 0xc0, 0xab, 0xb5, 0xa6, 0xe1, 0xfc, 0xc0, 0xbc, 0xc8, 0xc0, 0xc0, 0xc0, 0xc0,
-0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec,
-0xc0, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xc0, 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xc0, 0xc0, 0xa7,
-0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
-0xc0, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xc0, 0xc0, 0xd8
-};
-
-// This table converts MacRoman into Windows-1252/Latin 1
-static uchar roman2latin[128] = {
-0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
-0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
-0x86, 0xb0, 0xa2, 0xa3, 0xa7, 0x95, 0xb6, 0xdf, 0xae, 0xa9, 0x99, 0xb4, 0xa8, 0xbf, 0xc6, 0xd8,
-0xbf, 0xb1, 0xbf, 0xbf, 0xa5, 0xb5, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xaa, 0xba, 0xbf, 0xe6, 0xf8,
-0xbf, 0xa1, 0xac, 0xbf, 0x83, 0xbf, 0xbf, 0xab, 0xbb, 0x85, 0xa0, 0xc0, 0xc3, 0xd5, 0x8c, 0x9c,
-0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xf7, 0xbf, 0xff, 0x9f, 0xbf, 0x80, 0x8b, 0x9b, 0xbf, 0xbf,
-0x87, 0xb7, 0x82, 0x84, 0x89, 0xc2, 0xca, 0xc1, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
-0xbf, 0xd2, 0xda, 0xdb, 0xd9, 0xbf, 0x88, 0x98, 0xaf, 0xbf, 0xbf, 0xbf, 0xb8, 0xbf, 0xbf, 0xbf
-};
-
-static char *buf = 0;
-static int n_buf = 0;
-
-const char *Fl_Darwin_System_Driver::latin1_to_local(const char *t, int n)
-{
- if (n==-1) n = (int)strlen(t);
- if (n<=n_buf) {
- n_buf = (n + 257) & 0x7fffff00;
- if (buf) free(buf);
- buf = (char*)malloc(n_buf);
- }
- const uchar *src = (const uchar*)t;
- uchar *dst = (uchar*)buf;
- for ( ; n>0; n--) {
- uchar c = *src++;
- if (c>127)
- *dst = latin2roman[c-128];
- else
- *dst = c;
- }
- //*dst = 0; // this would be wrong!
- return buf;
-}
-
-const char *Fl_Darwin_System_Driver::local_to_latin1(const char *t, int n)
-{
- if (n==-1) n = (int)strlen(t);
- if (n<=n_buf) {
- n_buf = (n + 257) & 0x7fffff00;
- if (buf) free(buf);
- buf = (char*)malloc(n_buf);
- }
- const uchar *src = (const uchar*)t;
- uchar *dst = (uchar*)buf;
- for ( ; n>0; n--) {
- uchar c = *src++;
- if (c>127)
- *dst++ = roman2latin[c-128];
- else
- *dst++ = c;
- }
- //*dst = 0; // this would be wrong
- return buf;
-}
-
-// On Mac OS X, nothing need to be converted. We simply return the
-// original pointer.
-const char *Fl_Darwin_System_Driver::mac_roman_to_local(const char *t, int)
-{
- return t;
-}
-
-// On Mac OS X, nothing need to be converted. We simply return the
-// original pointer.
-const char *Fl_Darwin_System_Driver::local_to_mac_roman(const char *t, int)
-{
- return t;
-}
-
-Fl_Sys_Menu_Bar_Driver *Fl_Darwin_System_Driver::sys_menu_bar_driver()
-{
- return Fl_MacOS_Sys_Menu_Bar_Driver::driver();
-}
-
-// Draw Mac-specific Fl_Tree open/close icons
-void Fl_Darwin_System_Driver::tree_draw_expando_button(int x, int y, bool state, bool active) {
- fl_color(active ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR);
- if(state) fl_polygon(x + 3, y, x + 3, y + 11, x + 8, y + 5); // right arrow: ▶
- else fl_polygon(x, y + 3, x + 11, y + 3, x + 5, y + 8); // down arrow: ▼
-}
-int Fl_Darwin_System_Driver::tree_connector_style() {
- return FL_TREE_CONNECTOR_NONE;
-}
-
-
-int Fl_Darwin_System_Driver::filename_relative(char *to, int tolen, const char *dest_dir, const char *base_dir) {
- return Fl_System_Driver::filename_relative_(to, tolen, dest_dir, base_dir, false);
-}
diff --git a/src/drivers/Darwin/fl_macOS_platform_init.cxx b/src/drivers/Darwin/fl_macOS_platform_init.cxx
deleted file mode 100644
index fc18e90db..000000000
--- a/src/drivers/Darwin/fl_macOS_platform_init.cxx
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// macOS-specific code to initialize macOS support.
-//
-// Copyright 2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include "../Quartz/Fl_Quartz_Copy_Surface_Driver.H"
-#include "../Quartz/Fl_Quartz_Graphics_Driver.H"
-#include "../Cocoa/Fl_Cocoa_Screen_Driver.H"
-#include "../Darwin/Fl_Darwin_System_Driver.H"
-#include "../Cocoa/Fl_Cocoa_Window_Driver.H"
-#include "../Quartz/Fl_Quartz_Image_Surface_Driver.H"
-
-
-Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h)
-{
- return new Fl_Quartz_Copy_Surface_Driver(w, h);
-}
-
-
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
- return new Fl_Quartz_Graphics_Driver();
-}
-
-
-Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver()
-{
- return new Fl_Cocoa_Screen_Driver();
-}
-
-
-Fl_System_Driver *Fl_System_Driver::newSystemDriver()
-{
- return new Fl_Darwin_System_Driver();
-}
-
-
-Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
-{
- return new Fl_Cocoa_Window_Driver(w);
-}
-
-
-Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off)
-{
- return new Fl_Quartz_Image_Surface_Driver(w, h, high_res, off);
-}
diff --git a/src/drivers/GDI/Fl_Font.H b/src/drivers/GDI/Fl_Font.H
deleted file mode 100644
index 3e8b1296f..000000000
--- a/src/drivers/GDI/Fl_Font.H
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Font definitions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// Two internal fltk data structures:
-//
-// Fl_Fontdesc: an entry into the fl_font() table. There is one of these
-// for each fltk font number.
-//
-#ifndef FL_FONT_
-#define FL_FONT_
-
-#include <config.h>
-#include "../../Fl_Scalable_Graphics_Driver.H"
-
-class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor {
-public:
- HFONT fid;
- int *width[64];
- TEXTMETRIC metr;
- int angle;
- FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size);
-# if HAVE_GL
- char glok[64];
-# endif // HAVE_GL
- virtual FL_EXPORT ~Fl_GDI_Font_Descriptor();
-};
-
-extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
-
-#endif
diff --git a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H
deleted file mode 100644
index 7eae4c2bc..000000000
--- a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_GDI_COPY_SURFACE_DRIVER_H
-#define FL_GDI_COPY_SURFACE_DRIVER_H
-
-#include <FL/Fl_Copy_Surface.H>
-#include <FL/platform.H>
-
-class Fl_GDI_Copy_Surface_Driver : public Fl_Copy_Surface_Driver {
- friend class Fl_Copy_Surface_Driver;
-protected:
- HDC oldgc;
- HDC gc;
- Fl_GDI_Copy_Surface_Driver(int w, int h);
- ~Fl_GDI_Copy_Surface_Driver();
- void set_current() FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate() FL_OVERRIDE;
-};
-
-#endif // FL_GDI_COPY_SURFACE_DRIVER_H
diff --git a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
deleted file mode 100644
index c44c0a77b..000000000
--- a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#include "Fl_GDI_Copy_Surface_Driver.H"
-#include <FL/platform.H>
-#include "Fl_GDI_Graphics_Driver.H"
-#include "../WinAPI/Fl_WinAPI_Screen_Driver.H"
-#include <FL/Fl_Image_Surface.H>
-#include <windows.h>
-
-
-Fl_GDI_Copy_Surface_Driver::Fl_GDI_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
- driver(Fl_Graphics_Driver::newMainGraphicsDriver());
- oldgc = (HDC)Fl_Surface_Device::surface()->driver()->gc();
- // exact computation of factor from screen units to EnhMetaFile units (0.01 mm)
- HDC hdc = GetDC(NULL);
- int hmm = GetDeviceCaps(hdc, HORZSIZE);
- int hdots = GetDeviceCaps(hdc, HORZRES);
- int vmm = GetDeviceCaps(hdc, VERTSIZE);
- int vdots = GetDeviceCaps(hdc, VERTRES);
- ReleaseDC(NULL, hdc);
- float factorw = (100.f * hmm) / hdots;
- float factorh = (100.f * vmm) / vdots;
- // Global display scaling factor: 1, 1.25, 1.5, 1.75, etc...
- float scaling = Fl_Graphics_Driver::default_driver().scale();
- driver()->scale(scaling);
- RECT rect; rect.left = 0; rect.top = 0; rect.right = (LONG)((w*scaling) * factorw); rect.bottom = (LONG)((h*scaling) * factorh);
- gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
- if (gc != NULL) {
- SetTextAlign(gc, TA_BASELINE|TA_LEFT);
- SetBkMode(gc, TRANSPARENT);
- }
-}
-
-
-Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() {
- if (oldgc == (HDC)Fl_Surface_Device::surface()->driver()->gc()) oldgc = NULL;
- HENHMETAFILE hmf = CloseEnhMetaFile (gc);
- if ( hmf != NULL ) {
- if ( OpenClipboard (NULL) ){
- EmptyClipboard ();
- // put first the vectorial form of the graphics in the clipboard
- SetClipboardData (CF_ENHMETAFILE, hmf);
- // then put a BITMAP version of the graphics in the clipboard
- float scaling = driver()->scale();
- int W = Fl_Scalable_Graphics_Driver::floor(width, scaling), H = Fl_Scalable_Graphics_Driver::floor(height, scaling);
- RECT rect = {0, 0, W, H};
- Fl_Image_Surface *surf = new Fl_Image_Surface(W, H);
- Fl_Surface_Device::push_current(surf);
- fl_color(FL_WHITE); // draw white background
- fl_rectf(0, 0, W, H);
- PlayEnhMetaFile((HDC)surf->driver()->gc(), hmf, &rect); // draw metafile to offscreen buffer
- SetClipboardData(CF_BITMAP, (HBITMAP)surf->offscreen());
- Fl_Surface_Device::pop_current();
- delete surf;
-
- CloseClipboard ();
- }
- DeleteEnhMetaFile(hmf);
- }
- DeleteDC(gc);
- Fl_Surface_Device::surface()->driver()->gc(oldgc);
- delete driver();
-}
-
-
-void Fl_GDI_Copy_Surface_Driver::set_current() {
- driver()->gc(gc);
- fl_window = (HWND)1;
- Fl_Surface_Device::set_current();
-}
-
-
-void Fl_GDI_Copy_Surface_Driver::translate(int x, int y) {
- ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y);
-}
-
-
-void Fl_GDI_Copy_Surface_Driver::untranslate() {
- ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all();
-}
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
deleted file mode 100644
index 336fa1ebc..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
+++ /dev/null
@@ -1,230 +0,0 @@
-//
-// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_GDI_Graphics_Driver.H
- \brief Definition of Windows GDI graphics driver.
- */
-
-#ifndef FL_GDI_GRAPHICS_DRIVER_H
-#define FL_GDI_GRAPHICS_DRIVER_H
-
-#include "../../Fl_Scalable_Graphics_Driver.H"
-#include <windows.h>
-#include <stdlib.h>
-#include <config.h>
-
-#if USE_GDIPLUS
-# if defined(_MSC_VER)
-# include <objidl.h>
-# else
-# include <wtypes.h> // for PROPID needed with gcc 4.9.0 but not with 4.9.3
-# endif
-# include <gdiplus.h>
-#endif
-
-/**
- \brief The Windows-specific graphics driver class.
-
- This class is implemented only on the Windows platform.
-*/
-class Fl_GDI_Graphics_Driver : public Fl_Scalable_Graphics_Driver {
-private:
- BOOL alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch);
- int depth; // to support translation
- POINT *origins; // to support translation
- void set_current_() FL_OVERRIDE;
- void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_fixed(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void make_unused_color_(unsigned char &r, unsigned char &g, unsigned char &b, int color_count, void **data) FL_OVERRIDE;
-protected:
- void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void cache(Fl_RGB_Image *rgb) FL_OVERRIDE;
- HDC gc_;
- int numcount;
- int counts[20];
- uchar *mask_bitmap_;
- uchar **mask_bitmap() FL_OVERRIDE {return &mask_bitmap_;}
- POINT *long_point;
- int style_;
-public:
- Fl_GDI_Graphics_Driver();
- ~Fl_GDI_Graphics_Driver() FL_OVERRIDE;
- int has_feature(driver_feature mask) FL_OVERRIDE { return mask & NATIVE; }
- char can_do_alpha_blending() FL_OVERRIDE;
- void gc(void *ctxt) FL_OVERRIDE { gc_ = (HDC)ctxt; global_gc(); }
- void *gc() FL_OVERRIDE {return gc_;}
-
- // --- bitmap stuff
- static HBITMAP create_bitmask(int w, int h, const uchar *array); // NOT virtual
- static HBITMAP calc_HBITMAP_mask(Fl_RGB_Image *mask);
- void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE;
- HBITMAP create_alphamask(int w, int h, int d, int ld, const uchar *array);
- void draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE;
- void draw_unscaled(int angle, const char *str, int n, int x, int y) FL_OVERRIDE;
- void rtl_draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE;
- void font_unscaled(Fl_Font face, Fl_Fontsize size) FL_OVERRIDE;
- void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) FL_OVERRIDE;
- void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) FL_OVERRIDE;
- void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) FL_OVERRIDE;
- void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) FL_OVERRIDE;
- void cache(Fl_Pixmap *img) FL_OVERRIDE;
- void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE;
- void cache(Fl_Bitmap *img) FL_OVERRIDE;
- void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE;
- double width_unscaled(const char *str, int n) FL_OVERRIDE;
- double width_unscaled(unsigned int c) FL_OVERRIDE;
- void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE;
- int height_unscaled() FL_OVERRIDE;
- int descent_unscaled() FL_OVERRIDE;
- Fl_Fontsize size_unscaled() FL_OVERRIDE;
-#if ! defined(FL_DOXYGEN)
- void copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy);
-#endif
- void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) FL_OVERRIDE;
- void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) FL_OVERRIDE;
- Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE;
- void XDestroyRegion(Fl_Region r) FL_OVERRIDE;
- void translate_all(int x, int y);
- void untranslate_all(void);
- static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr);
- void scale(float f) FL_OVERRIDE;
- float scale() {return Fl_Graphics_Driver::scale();}
-protected:
- void transformed_vertex0(float x, float y) FL_OVERRIDE;
- void fixloop() FL_OVERRIDE;
- void point(int x, int y) FL_OVERRIDE;
- void focus_rect(int x, int y, int w, int h) FL_OVERRIDE;
- void rect_unscaled(int x, int y, int w, int h) FL_OVERRIDE;
- void rectf_unscaled(int x, int y, int w, int h) FL_OVERRIDE;
-#if USE_COLORMAP
- void colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) FL_OVERRIDE;
-#endif
- void line_unscaled(int x, int y, int x1, int y1) FL_OVERRIDE;
- void line_unscaled(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void xyline_unscaled(int x, int y, int x1) FL_OVERRIDE;
- void yxline_unscaled(int x, int y, int y1) FL_OVERRIDE;
- void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE;
- void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE;
- // --- clipping
- void push_clip(int x, int y, int w, int h) FL_OVERRIDE;
- int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE;
- int not_clipped(int x, int y, int w, int h) FL_OVERRIDE;
- void restore_clip() FL_OVERRIDE;
- Fl_Region scale_clip(float f) FL_OVERRIDE;
- // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
- void begin_complex_polygon() FL_OVERRIDE;
- void end_points() FL_OVERRIDE;
- void end_line() FL_OVERRIDE;
- void end_loop() FL_OVERRIDE;
- void end_polygon() FL_OVERRIDE;
- void end_complex_polygon() FL_OVERRIDE;
- void gap() FL_OVERRIDE;
- void ellipse_unscaled(double xt, double yt, double rx, double ry) FL_OVERRIDE;
- void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE;
- void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE;
- void line_style_unscaled(int style, int width, char* dashes) FL_OVERRIDE;
- void color(Fl_Color c) FL_OVERRIDE;
- Fl_Color color() FL_OVERRIDE { return color_; }
- void color(uchar r, uchar g, uchar b) FL_OVERRIDE;
- void set_color(Fl_Color i, unsigned int c) FL_OVERRIDE;
- void free_color(Fl_Color i, int overlay) FL_OVERRIDE;
- Fl_Font set_fonts(const char *name) FL_OVERRIDE;
- int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE;
- const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE;
- const char *font_name(int num) FL_OVERRIDE;
- void font_name(int num, const char *name) FL_OVERRIDE;
- void global_gc() FL_OVERRIDE;
- void overlay_rect(int x, int y, int w , int h) FL_OVERRIDE;
- void cache_size(Fl_Image *img, int &width, int &height) FL_OVERRIDE;
- void* change_pen_width(int width) FL_OVERRIDE;
- void reset_pen_width(void *data) FL_OVERRIDE;
-};
-
-
-/**
- The graphics driver used when printing on Windows.
-
- This class is implemented only on the Windows platform.
- It is extremely similar to Fl_GDI_Graphics_Driver.
-*/
-class Fl_GDI_Printer_Graphics_Driver : public Fl_GDI_Graphics_Driver {
-private:
- typedef BOOL (WINAPI* transparent_f_type) (HDC,int,int,int,int,HDC,int,int,int,int,UINT);
- transparent_f_type TransparentBlt();
-public:
- int has_feature(driver_feature mask) FL_OVERRIDE { return mask & (NATIVE | PRINTER); }
- void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) FL_OVERRIDE;
-};
-
-#if USE_GDIPLUS
-
-class Fl_GDIplus_Graphics_Driver : public Fl_GDI_Graphics_Driver {
- friend class Fl_Graphics_Driver;
-private:
- Gdiplus::Color gdiplus_color_;
- Gdiplus::Pen *pen_;
- Gdiplus::SolidBrush *brush_;
- // The code below ensures that a connection to GDIplus is only made once, and that the
- // matching connection shutdown is also done exactly once.
- enum {
- STATE_CLOSED = 0, // no connection, token is invalid
- STATE_STARTUP, // attempt to start up, avoid recursions for whatever reason
- STATE_OPEN, // connection was successful and the token is valid
- STATE_SHUTDOWN // shutting down the gdi connection, avoid possible recursion
- };
- static int gdiplus_state_; // reflect the state of the GDIplus driver connection
- static ULONG_PTR gdiplus_token_; // the token that GDIplus gives to us
-public:
- Fl_GDIplus_Graphics_Driver();
- virtual ~Fl_GDIplus_Graphics_Driver();
- bool active;
- static void shutdown(void);
- void color(Fl_Color c) FL_OVERRIDE;
- Fl_Color color() FL_OVERRIDE { return color_; }
- void color(uchar r, uchar g, uchar b) FL_OVERRIDE;
- void line(int x, int y, int x1, int y1) FL_OVERRIDE;
- void line(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE;
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE;
- void line_style(int style, int width, char* dashes) FL_OVERRIDE;
- void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE;
- void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE;
- void draw_circle(int x, int y, int d, Fl_Color c) FL_OVERRIDE;
- void transformed_vertex(double xf, double yf) FL_OVERRIDE;
- void vertex(double x,double y) FL_OVERRIDE;
- void end_points() FL_OVERRIDE;
- void end_line() FL_OVERRIDE;
- void end_loop() FL_OVERRIDE;
- void end_polygon() FL_OVERRIDE;
- void end_complex_polygon() FL_OVERRIDE;
- void circle(double x, double y, double r) FL_OVERRIDE;
- void antialias(int state) FL_OVERRIDE;
- int antialias() FL_OVERRIDE;
-};
-
-#endif // USE_GDIPLUS
-
-#endif // FL_GDI_GRAPHICS_DRIVER_H
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
deleted file mode 100644
index 97b3244d1..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
+++ /dev/null
@@ -1,322 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_GDI_Graphics_Driver.H"
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-#include "../../Fl_Screen_Driver.H"
-#include "Fl_Font.H"
-
-#if USE_GDIPLUS
-
-Fl_GDIplus_Graphics_Driver::Fl_GDIplus_Graphics_Driver() : Fl_GDI_Graphics_Driver() {
- if (!fl_current_xmap) color(FL_BLACK);
- pen_ = new Gdiplus::Pen(gdiplus_color_, 1);
- pen_->SetLineJoin(Gdiplus::LineJoinRound);
- pen_->SetStartCap(Gdiplus::LineCapFlat);
- pen_->SetEndCap(Gdiplus::LineCapFlat);
- brush_ = new Gdiplus::SolidBrush(gdiplus_color_);
- active = true;
-}
-
-Fl_GDIplus_Graphics_Driver::~Fl_GDIplus_Graphics_Driver() {
- delete pen_;
- delete brush_;
-}
-
-void Fl_GDIplus_Graphics_Driver::antialias(int state) {
- active = state;
-}
-
-int Fl_GDIplus_Graphics_Driver::antialias() {
- return active;
-}
-
-void Fl_GDIplus_Graphics_Driver::draw_circle(int x, int y, int d, Fl_Color c) {
- Fl_Graphics_Driver::draw_circle(x, y, d, c);
-}
-
-int Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED;
-ULONG_PTR Fl_GDIplus_Graphics_Driver::gdiplus_token_ = 0;
-
-void Fl_GDIplus_Graphics_Driver::shutdown() {
- if (gdiplus_state_ == STATE_OPEN) {
- gdiplus_state_ = STATE_SHUTDOWN;
- Gdiplus::GdiplusShutdown(Fl_GDIplus_Graphics_Driver::gdiplus_token_);
- gdiplus_token_ = 0;
- gdiplus_state_ = STATE_CLOSED;
- } else if (gdiplus_state_ == STATE_CLOSED) {
-// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called, but driver is closed.");
- } else if (gdiplus_state_ == STATE_SHUTDOWN) {
-// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called recursively.");
- } else if (gdiplus_state_ == STATE_STARTUP) {
-// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called while driver is starting up.");
- }
-}
-#endif
-
-// Code used to switch output to an off-screen window. See macros in
-// win32.H which save the old state in local variables.
-
-typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION;
-typedef BOOL (WINAPI* fl_alpha_blend_func)
-(HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION);
-static fl_alpha_blend_func fl_alpha_blend = NULL;
-static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
-
-/* Reference to the current device context
- For back-compatibility only. The preferred procedure to get this reference is
- Fl_Surface_Device::surface()->driver()->gc().
- */
-HDC fl_gc = 0;
-
-
-HDC fl_win32_gc() { return fl_gc; }
-
-
-Fl_GDI_Graphics_Driver::Fl_GDI_Graphics_Driver() {
- mask_bitmap_ = NULL;
- gc_ = NULL;
- long_point = NULL;
- depth = -1;
- origins = NULL;
- style_ = FL_SOLID;
-}
-
-Fl_GDI_Graphics_Driver::~Fl_GDI_Graphics_Driver() {
- if (long_point) free(long_point);
- delete[] origins;
-}
-
-void Fl_GDI_Graphics_Driver::global_gc()
-{
- fl_gc = (HDC)gc();
-}
-
-/*
- * This function checks if the version of Windows that we
- * curently run on supports alpha blending for bitmap transfers
- * and finds the required function if so.
- */
-char Fl_GDI_Graphics_Driver::can_do_alpha_blending() {
- static char been_here = 0;
- static char can_do = 0;
- // do this test only once
- if (been_here) return can_do;
- been_here = 1;
- // load the library that implements alpha blending
- HMODULE hMod = LoadLibrary("MSIMG32.DLL");
- // give up if that doesn't exist (Win95?)
- if (!hMod) return 0;
- // now find the blending function inside that dll
- fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend");
- // give up if we can't find it (Win95)
- if (!fl_alpha_blend) return 0;
- // we have the call, but does our display support alpha blending?
- // get the desktop's device context
- HDC dc = GetDC(0L);
- if (!dc) return 0;
- // check the device capabilities flags. However GetDeviceCaps
- // does not return anything useful, so we have to do it manually:
-
- HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1);
- HDC new_gc = CreateCompatibleDC(dc);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, bm);
- /*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101);
- BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc);
- RestoreDC(new_gc, save);
- DeleteDC(new_gc);
- DeleteObject(bm);
- ReleaseDC(0L, dc);
-
- if (alpha_ok) can_do = 1;
- return can_do;
-}
-
-HDC fl_makeDC(HBITMAP bitmap) {
- HDC new_gc = CreateCompatibleDC((HDC)Fl_Graphics_Driver::default_driver().gc());
- SetTextAlign(new_gc, TA_BASELINE|TA_LEFT);
- SetBkMode(new_gc, TRANSPARENT);
-#if USE_COLORMAP
- if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE);
-#endif
- SelectObject(new_gc, bitmap);
- return new_gc;
-}
-
-void Fl_GDI_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) {
- x = int(x * scale()); y = int(y * scale()); w = int(w * scale()); h = int(h * scale());
- srcx = int(srcx * scale()); srcy = int(srcy * scale());
- if (srcx < 0) {w += srcx; x -= srcx; srcx = 0;}
- if (srcy < 0) {h += srcy; y -= srcy; srcy = 0;}
- int off_width, off_height;
- Fl::screen_driver()->offscreen_size(bitmap, off_width, off_height);
- if (srcx + w >= off_width) {w = off_width - srcx;}
- if (srcy + h >= off_height) {h = off_height - srcy;}
- if (w <= 0 || h <= 0) return;
- HDC new_gc = CreateCompatibleDC(gc_);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, (HBITMAP)bitmap);
- BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
- RestoreDC(new_gc, save);
- DeleteDC(new_gc);
-}
-
-void Fl_GDI_Printer_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) {
- Fl_Graphics_Driver::copy_offscreen(x, y, w, h, bitmap, srcx, srcy);
-}
-
-BOOL Fl_GDI_Graphics_Driver::alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch) {
- return fl_alpha_blend(gc_, x, y, w, h, src_gc, srcx, srcy, srcw, srch, blendfunc);
-}
-
-#if ! defined(FL_DOXYGEN)
-void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
- HDC new_gc = CreateCompatibleDC(gc_);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, bitmap);
- BOOL alpha_ok = 0;
- // first try to alpha blend
- if ( fl_can_do_alpha_blending() ) {
- alpha_ok = alpha_blend_(x, y, w, h, new_gc, srcx, srcy, w, h);
- }
- // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1
- if (!alpha_ok) {
- BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
- }
- RestoreDC(new_gc, save);
- DeleteDC(new_gc);
-}
-
-void Fl_GDI_Graphics_Driver::translate_all(int x, int y) {
- const int stack_height = 10;
- if (depth == -1) {
- origins = new POINT[stack_height];
- depth = 0;
- }
- if (depth >= stack_height) {
- Fl::warning("Fl_Copy/Image_Surface: translate stack overflow!");
- depth = stack_height - 1;
- }
- GetWindowOrgEx((HDC)gc(), origins+depth);
- SetWindowOrgEx((HDC)gc(), int(origins[depth].x - x*scale()), int(origins[depth].y - y*scale()), NULL);
- depth++;
-}
-
-void Fl_GDI_Graphics_Driver::untranslate_all() {
- if (depth > 0) depth--;
- SetWindowOrgEx((HDC)gc(), origins[depth].x, origins[depth].y, NULL);
-}
-#endif
-
-void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
- HRGN R = (HRGN)XRectangleRegion(X, Y, W, H);
- CombineRgn((HRGN)r, (HRGN)r, R, RGN_OR);
- XDestroyRegion(R);
-}
-
-void Fl_GDI_Graphics_Driver::transformed_vertex0(float x, float y) {
- if (!n || x != long_point[n-1].x || y != long_point[n-1].y) {
- if (n >= p_size) {
- p_size = long_point ? 2*p_size : 16;
- long_point = (POINT*)realloc((void*)long_point, p_size*sizeof(*long_point));
- }
- long_point[n].x = LONG(x);
- long_point[n].y = LONG(y);
- n++;
- }
-}
-
-void Fl_GDI_Graphics_Driver::fixloop() { // remove equal points from closed path
- while (n>2 && long_point[n-1].x == long_point[0].x && long_point[n-1].y == long_point[0].y) n--;
-}
-
-Fl_Region Fl_GDI_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
- if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) return CreateRectRgn(x,y,x+w,y+h);
- // because rotation may apply, the rectangle becomes a polygon in device coords
- POINT pt[4] = { {x, y}, {x + w, y}, {x + w, y + h}, {x, y + h} };
- LPtoDP((HDC)fl_graphics_driver->gc(), pt, 4);
- return CreatePolygonRgn(pt, 4, ALTERNATE);
-}
-
-void Fl_GDI_Graphics_Driver::XDestroyRegion(Fl_Region r) {
- DeleteObject((HRGN)r);
-}
-
-
-void Fl_GDI_Graphics_Driver::scale(float f) {
- if (f != scale()) {
- size_ = 0;
- Fl_Graphics_Driver::scale(f);
- color(FL_BLACK);
- line_style(FL_SOLID); // scale also default line width
- }
-}
-
-
-/* Rescale region r with factor f and returns the scaled region.
- Region r is returned unchanged if r is null or f is 1.
- */
-HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr) {
- if (r && f != 1) {
- DWORD size = GetRegionData(r, 0, NULL);
- RGNDATA *pdata = (RGNDATA*)malloc(size);
- GetRegionData(r, size, pdata);
- POINT pt = {0, 0};
- if (dr && dr->depth >= 1) { // account for translation
- GetWindowOrgEx((HDC)dr->gc(), &pt);
- pt.x = int(pt.x * (f - 1));
- pt.y = int(pt.y * (f - 1));
- }
- RECT *rects = (RECT*)&(pdata->Buffer);
- for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
- int x = Fl_Scalable_Graphics_Driver::floor(rects[i].left, f) + pt.x;
- int y = Fl_Scalable_Graphics_Driver::floor(rects[i].top, f) + pt.y;
- RECT R2;
- R2.left = x;
- R2.top = y;
- R2.right = Fl_Scalable_Graphics_Driver::floor(rects[i].right, f) + pt.x - x + R2.left;
- R2.bottom = Fl_Scalable_Graphics_Driver::floor(rects[i].bottom, f) + pt.y - y + R2.top;
- rects[i] = R2;
- }
- r = ExtCreateRegion(NULL, size, pdata);
- free(pdata);
- }
- return r;
-}
-
-
-Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
- HRGN r = (HRGN)rstack[rstackptr];
- HRGN r2 = scale_region(r, f, this);
- return (r == r2 ? NULL : (rstack[rstackptr] = r2, r));
-}
-
-void Fl_GDI_Graphics_Driver::set_current_() {
- restore_clip();
-}
-
-void Fl_GDI_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height)
-{
- float s = scale();
- width = (s == int(s) ? width * int(s) : floor(width+1));
- height = (s == int(s) ? height * int(s) : floor(height+1));
- cache_size_finalize(img, width, height);
-}
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
deleted file mode 100644
index 0c1e90064..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_GDI_Graphics_Driver_arci.cxx
- \brief Utility functions for drawing circles using integers
-*/
-
-// "integer" circle drawing functions. These draw the limited
-// circle types provided by X and NT graphics. The advantage of
-// these is that small ones draw quite nicely (probably due to stored
-// hand-drawn bitmaps of small circles!) and may be implemented by
-// hardware and thus are fast.
-
-#include "Fl_GDI_Graphics_Driver.H"
-
-#include <FL/math.h>
-#include <FL/platform.H>
-
-void Fl_GDI_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) {
- if (w <= 0 || h <= 0) return;
- w++; h++;
- int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) );
- int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) );
- int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) );
- int yb = int( y+h/2-int(h*sin(a2/180.0*M_PI)) );
- if (fabs(a1 - a2) < 90) {
- if (xa == xb && ya == yb) SetPixel(gc_, xa, ya, fl_RGB());
- else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb);
- } else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb);
-}
-
-void Fl_GDI_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) {
- if (w <= 0 || h <= 0) return;
- if (a1 == a2) return;
- x++; y++; w--; h--;
- if (scale() >= 3) {x++; y++; w-=2; h-=2;}
- int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) );
- int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) );
- int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) );
- int yb = int( y+h/2-int(h*sin(a2/180.0*M_PI)) );
- SelectObject(gc_, fl_brush());
- if (fabs(a1 - a2) < 90) {
- if (xa == xb && ya == yb) {
- MoveToEx(gc_, int(x+w/2), int(y+h/2), 0L);
- LineTo(gc_, xa, ya);
- SetPixel(gc_, xa, ya, fl_RGB());
- } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb);
- } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb);
-}
-
-#if USE_GDIPLUS
-
-void Fl_GDIplus_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) {
- if (w <= 0 || h <= 0) return;
- if (!active) return Fl_GDI_Graphics_Driver::arc_unscaled(x, y, w, h, a1, a2);
- Gdiplus::Graphics graphics_(gc_);
- pen_->SetColor(gdiplus_color_);
- Gdiplus::REAL oldw = pen_->GetWidth();
- Gdiplus::REAL new_w = (line_width_ <= scale() ? 1 : line_width_) * scale();
- pen_->SetWidth(new_w);
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.DrawArc(pen_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2));
- pen_->SetWidth(oldw);
-}
-
-void Fl_GDIplus_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) {
- if (w <= 0 || h <= 0) return;
- if (!active) return Fl_GDI_Graphics_Driver::pie_unscaled(x, y, w, h, a1, a2);
- Gdiplus::Graphics graphics_(gc_);
- brush_->SetColor(gdiplus_color_);
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.FillPie(brush_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2));
-}
-
-#endif
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx
deleted file mode 100644
index c05a255d0..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx
+++ /dev/null
@@ -1,259 +0,0 @@
-//
-// MSWidnows' GDI color functions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// The fltk "colormap". This allows ui colors to be stored in 8-bit
-// locations, and provides a level of indirection so that global color
-// changes can be made. Not to be confused with the X colormap, which
-// I try to hide completely.
-
-#include "Fl_GDI_Graphics_Driver.H"
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-
-// FIXME: all the global functions in this file should probably be protected
-// members of the driver class. Starting with 1.4 we will allow multiple drivers
-// to co-exist, creating conflicts with multipe mapping.
-
-// FIXME: maybe we can forget about color mapping and assume RGB?
-// FIXME: ... but for now we still have it ...
-extern unsigned fl_cmap[256]; // defined in fl_color.cxx
-
-// Translations to win32 data structures:
-Fl_XMap fl_xmap[256];
-
-Fl_XMap* fl_current_xmap;
-
-HPALETTE fl_palette;
-static HGDIOBJ tmppen=0;
-static HPEN savepen=0;
-
-void fl_cleanup_pens(void) {
- for (int i=0; i<256; i++) {
- if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen);
- }
-}
-
-void fl_save_pen(void) {
- if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0);
- savepen = (HPEN)SelectObject((HDC)fl_graphics_driver->gc(), tmppen);
-}
-
-void fl_restore_pen(void) {
- if (savepen) SelectObject((HDC)fl_graphics_driver->gc(), savepen);
- DeleteObject(tmppen);
- tmppen = 0;
- savepen = 0;
-}
-
-static void clear_xmap(Fl_XMap& xmap) {
- if (xmap.pen) {
- HDC gc = (HDC)fl_graphics_driver->gc();
- HGDIOBJ tmppen = GetStockObject(BLACK_PEN);
- HGDIOBJ oldpen = SelectObject(gc, tmppen); // Push out the current pen of the gc
- if(oldpen != xmap.pen) SelectObject(gc, oldpen); // Put it back if it is not the one we are about to delete
- DeleteObject((HGDIOBJ)(xmap.pen));
- xmap.pen = 0;
- xmap.brush = -1;
- }
-}
-
-static void set_xmap(Fl_XMap& xmap, COLORREF c, int lw) {
- xmap.rgb = c;
- if (xmap.pen) {
- HDC gc = (HDC)fl_graphics_driver->gc();
- HGDIOBJ oldpen = SelectObject(gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one
- if (oldpen != xmap.pen)SelectObject(gc,oldpen); // if old one not xmap.pen, need to put it back
- DeleteObject(xmap.pen); // delete pen
- }
-// xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen
- LOGBRUSH penbrush = {BS_SOLID, xmap.rgb, 0};
- xmap.pen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, lw, &penbrush, 0, 0);
- xmap.pwidth = lw;
- xmap.brush = -1;
-}
-
-void Fl_GDI_Graphics_Driver::color(Fl_Color i) {
- if (i & 0xffffff00) {
- unsigned rgb = (unsigned)i;
- color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
- } else {
- Fl_Graphics_Driver::color(i);
- Fl_XMap &xmap = fl_xmap[i];
- int tw = line_width_ ? line_width_ : int(scale()); if (!tw) tw = 1;
- if (!xmap.pen || xmap.pwidth != tw) {
-#if USE_COLORMAP
- if (fl_palette) {
- set_xmap(xmap, PALETTEINDEX(i), tw);
- } else {
-#endif
- unsigned c = fl_cmap[i];
- set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)), tw);
-#if USE_COLORMAP
- }
-#endif
- }
- fl_current_xmap = &xmap;
- SelectObject(gc_, (HGDIOBJ)(xmap.pen));
- }
-}
-
-void Fl_GDI_Graphics_Driver::color(uchar r, uchar g, uchar b) {
- static Fl_XMap xmap;
- COLORREF c = RGB(r,g,b);
- Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
- int tw = line_width_ ? line_width_ : int(scale()); if (!tw) tw = 1;
- if (!xmap.pen || c != xmap.rgb || tw != xmap.pwidth) {
- clear_xmap(xmap);
- set_xmap(xmap, c, tw);
- }
- fl_current_xmap = &xmap;
- SelectObject(gc_, (HGDIOBJ)(xmap.pen));
-}
-
-HBRUSH fl_brush() {
- return fl_brush_action(0);
-}
-
-HBRUSH fl_brush_action(int action) {
- Fl_XMap *xmap = fl_current_xmap;
- HDC gc = (HDC)fl_graphics_driver->gc();
- // Wonko: we use some statistics to cache only a limited number
- // of brushes:
-#define FL_N_BRUSH 16
- static struct Fl_Brush {
- HBRUSH brush;
- unsigned short usage;
- Fl_XMap* backref;
- } brushes[FL_N_BRUSH];
-
- if (action) {
- SelectObject(gc, GetStockObject(BLACK_BRUSH)); // Load stock object
- for (int i=0; i<FL_N_BRUSH; i++) {
- if (brushes[i].brush)
- DeleteObject(brushes[i].brush); // delete all brushes in array
- }
- return NULL;
- }
-
- int i = xmap->brush; // find the associated brush
- if (i != -1) { // if the brush was allready allocated
- if (brushes[i].brush == NULL) goto CREATE_BRUSH;
- if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
- for (int j=0; j<FL_N_BRUSH; j++) {
- if (brushes[j].usage>16000)
- brushes[j].usage -= 16000;
- else
- brushes[j].usage = 0;
- }
- }
- return brushes[i].brush;
- } else {
- int umin = 32000, imin = 0;
- for (i=0; i<FL_N_BRUSH; i++) {
- if (brushes[i].brush == NULL) goto CREATE_BRUSH;
- if (brushes[i].usage<umin) {
- umin = brushes[i].usage;
- imin = i;
- }
- }
- i = imin;
- HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH); // get a stock brush
- HGDIOBJ oldbrush = SelectObject(gc,tmpbrush); // load in into current context
- if (oldbrush != brushes[i].brush) SelectObject(gc,oldbrush); // reload old one
- DeleteObject(brushes[i].brush); // delete the one in list
- brushes[i].brush = NULL;
- brushes[i].backref->brush = -1;
- }
-CREATE_BRUSH:
- brushes[i].brush = CreateSolidBrush(xmap->rgb);
- brushes[i].usage = 0;
- brushes[i].backref = xmap;
- xmap->brush = i;
- return brushes[i].brush;
-}
-
-void Fl_GDI_Graphics_Driver::free_color(Fl_Color i, int overlay) {
- if (overlay) return; // do something about GL overlay?
- clear_xmap(fl_xmap[i]);
-}
-
-void Fl_GDI_Graphics_Driver::set_color(Fl_Color i, unsigned c) {
- if (fl_cmap[i] != c) {
- clear_xmap(fl_xmap[i]);
- fl_cmap[i] = c;
- }
-}
-
-#if USE_COLORMAP
-
-// 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
-// Thanks to Michael Sweet @ Easy Software Products for this
-
-HPALETTE
-fl_select_palette(void)
-{
- static char beenhere;
- HDC gc = (HDC)fl_graphics_driver->gc();
- if (!beenhere) {
- beenhere = 1;
-
- int nColors = GetDeviceCaps(gc, SIZEPALETTE);
- if (nColors <= 0 || nColors > 256) return NULL;
- // this will try to work on < 256 color screens, but will probably
- // come out quite badly.
-
- // I lamely try to get this variable-sized object allocated on stack:
- ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
- LOGPALETTE *pPal = (LOGPALETTE*)foo;
-
- pPal->palVersion = 0x300;
- pPal->palNumEntries = nColors;
-
- // Build 256 colors from the standard FLTK colormap...
-
- for (int i = 0; i < nColors; i ++) {
- pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255;
- pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
- pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255;
- pPal->palPalEntry[i].peFlags = 0;
- };
-
- // Create the palette:
- fl_palette = CreatePalette(pPal);
- }
- if (fl_palette) {
- SelectPalette(gc, fl_palette, FALSE);
- RealizePalette(gc);
- }
- return fl_palette;
-}
-
-#endif
-
-#if USE_GDIPLUS
-void Fl_GDIplus_Graphics_Driver::color(uchar r, uchar g, uchar b) {
- Fl_GDI_Graphics_Driver::color(r, g, b);
- gdiplus_color_.SetFromCOLORREF(fl_RGB());
-}
-
-void Fl_GDIplus_Graphics_Driver::color(Fl_Color i) {
- Fl_GDI_Graphics_Driver::color(i);
- gdiplus_color_.SetFromCOLORREF(fl_RGB());
-}
-#endif // USE_GDIPLUS
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
deleted file mode 100644
index 49111f10e..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
+++ /dev/null
@@ -1,678 +0,0 @@
-//
-// Windows font utilities for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-
-#ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-#endif
-/* We require Windows 2000 features such as GetGlyphIndices */
-#if !defined(WINVER) || (WINVER < 0x0500)
-# ifdef WINVER
-# undef WINVER
-# endif
-# define WINVER 0x0500
-#endif
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
-# ifdef _WIN32_WINNT
-# undef _WIN32_WINNT
-# endif
-# define _WIN32_WINNT 0x0500
-#endif
-
-// Select fonts from the FLTK font table.
-#include "Fl_GDI_Graphics_Driver.H"
-#include "../../flstring.h"
-#include <FL/Fl.H>
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-#include "Fl_Font.H"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <FL/fl_string_functions.h>
-
-// This function fills in the FLTK font table with all the fonts that
-// are found on the X server. It tries to place the fonts into families
-// and to sort them so the first 4 in a family are normal, bold, italic,
-// and bold italic.
-#include <FL/fl_utf8.h>
-#ifdef __CYGWIN__
-# include <wchar.h>
-#endif
-
-// Bug: older versions calculated the value for *ap as a side effect of
-// making the name, and then forgot about it. To avoid having to change
-// the header files I decided to store this value in the last character
-// of the font name array.
-#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1
-
-// turn a stored font name into a pretty name:
-const char* Fl_GDI_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
- Fl_Fontdesc *f = fl_fonts + fnum;
- if (!f->fontname[0]) {
- const char* p = f->name;
- if (!p || !*p) {if (ap) *ap = 0; return "";}
- int type;
- switch (*p) {
- case 'B': type = FL_BOLD; break;
- case 'I': type = FL_ITALIC; break;
- case 'P': type = FL_BOLD | FL_ITALIC; break;
- default: type = 0; break;
- }
- strlcpy(f->fontname, p+1, ENDOFBUFFER);
- if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER);
- if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER);
- f->fontname[ENDOFBUFFER] = (char)type;
- }
- if (ap) *ap = f->fontname[ENDOFBUFFER];
- return f->fontname;
-}
-
-static int fl_free_font = FL_FREE_FONT;
-
-// helper function for `enumcbw()` to avoid code repetition
-// input:
-// ft: font "type", i.e. ' ', 'B', 'I', or 'P'
-// fn: font name whose first byte is overwritten and then stored
-
-static void set_font_name(const char ft, char *fn) {
- fn[0] = ft;
- Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(fn));
-}
-
-// Callback for EnumFontFamiliesW():
-// return 1 to continue, 0 to stop enumeration
-
-static int CALLBACK
-enumcbw(CONST LOGFONTW *lpelf,
- CONST TEXTMETRICW * /* lpntm */,
- DWORD /* FontType */,
- LPARAM p) {
- if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1;
- char *fn = nullptr; // FLTK font name
- unsigned lw = (unsigned)wcslen(lpelf->lfFaceName);
- unsigned dstlen = fl_utf8fromwc(fn, 0, (wchar_t*)lpelf->lfFaceName, lw); // measure the string
- fn = (char*)malloc((size_t)dstlen + 2); // "?" + name + NUL
- if (!fn) return 1;
- fn[0] = ' ';
- dstlen = fl_utf8fromwc(fn+1, dstlen+1, (wchar_t*)lpelf->lfFaceName, lw); // convert the string
- fn[dstlen + 1] = 0;
- // skip if it is one of our built-in fonts
- for (int i = 0; i < FL_FREE_FONT; i++) {
- if (!strcmp(Fl::get_font_name((Fl_Font)i), fn+1)) {
- free(fn);
- return 1;
- }
- }
- set_font_name(' ', fn);
- if (lpelf->lfWeight <= 400)
- set_font_name('B', fn);
- set_font_name('I', fn);
- if (lpelf->lfWeight <= 400)
- set_font_name('P', fn);
- free(fn);
- return 1;
-} /* enumcbw */
-
-Fl_Font Fl_GDI_Graphics_Driver::set_fonts(const char* xstarname) {
- HDC gc = (HDC)fl_graphics_driver->gc();
- if (fl_free_font == FL_FREE_FONT) {// if not already been called
- if (!gc) gc = fl_GetDC(0);
-
- EnumFontFamiliesW(gc, NULL, (FONTENUMPROCW)enumcbw, xstarname != 0);
-
- }
- return (Fl_Font)fl_free_font;
-}
-
-
-static int nbSize;
-static int cyPerInch;
-static int sizes[128];
-static int CALLBACK
-
-EnumSizeCbW(CONST LOGFONTW * /*lpelf*/,
- CONST TEXTMETRICW *lpntm,
- DWORD fontType,
- LPARAM /*p*/) {
- if ((fontType & RASTER_FONTTYPE) == 0) {
- sizes[0] = 0;
- nbSize = 1;
-
- // Scalable font
- return 0;
- }
-
- int add = lpntm->tmHeight - lpntm->tmInternalLeading;
- add = MulDiv(add, 72, cyPerInch);
-
- int start = 0;
- while ((start < nbSize) && (sizes[start] < add)) {
- start++;
- }
-
- if ((start < nbSize) && (sizes[start] == add)) {
- return 1;
- }
-
- for (int i=nbSize; i>start; i--) sizes[i] = sizes[i - 1];
-
- sizes[start] = add;
- nbSize++;
-
- // Stop enum if buffer overflow
- return nbSize < 128;
-}
-
-
-int Fl_GDI_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
- nbSize = 0;
- Fl_Fontdesc *s = fl_fonts+fnum;
- if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
-
- HDC gc = (HDC)fl_graphics_driver->gc();
- if (!gc) gc = fl_GetDC(0);
- cyPerInch = GetDeviceCaps(gc, LOGPIXELSY);
- if (cyPerInch < 1) cyPerInch = 1;
-
-// int l = fl_utf_nb_char((unsigned char*)s->name+1, strlen(s->name+1));
-// unsigned short *b = (unsigned short*) malloc((l + 1) * sizeof(short));
-// fl_utf2unicode((unsigned char*)s->name+1, l, (wchar_t*)b);
- const char *nm = (const char*)s->name+1;
- size_t len = strlen(s->name+1);
- unsigned l = fl_utf8toUtf16(nm, (unsigned) len, NULL, 0); // Pass NULL to query length required
- unsigned short *b = (unsigned short*) malloc((l + 1) * sizeof(short));
- l = fl_utf8toUtf16(nm, (unsigned) len, b, (l+1)); // Now do the conversion
- b[l] = 0;
- EnumFontFamiliesW(gc, (WCHAR*)b, (FONTENUMPROCW)EnumSizeCbW, 0);
- free(b);
-
- sizep = sizes;
- return nbSize;
-}
-
-const char *Fl_GDI_Graphics_Driver::font_name(int num) {
- return fl_fonts[num].name;
-}
-
-void Fl_GDI_Graphics_Driver::font_name(int num, const char *name) {
- Fl_Fontdesc *s = fl_fonts + num;
- if (s->name) {
- if (!strcmp(s->name, name)) {s->name = name; return;}
- for (Fl_Font_Descriptor* f = s->first; f;) {
- Fl_Font_Descriptor* n = f->next; delete f; f = n;
- }
- s->first = 0;
- }
- s->name = name;
- s->fontname[0] = 0;
- s->first = 0;
-}
-
-
-static int fl_angle_ = 0;
-// Unicode string buffer
-static unsigned short *wstr = NULL;
-static int wstr_len = 0;
-
-#ifndef FL_DOXYGEN
-Fl_GDI_Font_Descriptor::Fl_GDI_Font_Descriptor(const char* name, Fl_Fontsize fsize) : Fl_Font_Descriptor(name,fsize) {
- int weight = FW_NORMAL;
- int italic = 0;
- switch (*name++) {
- case 'I': italic = 1; break;
- case 'P': italic = 1;
- case 'B': weight = FW_BOLD; break;
- case ' ': break;
- default: name--;
- }
- int wn = fl_utf8toUtf16(name, (unsigned int)strlen(name), wstr, wstr_len);
- if (wn >= wstr_len) {
- wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
- wstr_len = wn + 1;
- wn = fl_utf8toUtf16(name, (unsigned int)strlen(name), wstr, wstr_len);
- }
-
- fid = CreateFontW(
- -fsize, // negative makes it use "char size"
- 0, // logical average character width
- fl_angle_*10, // angle of escapement
- fl_angle_*10, // base-line orientation angle
- weight,
- italic,
- FALSE, // underline attribute flag
- FALSE, // strikeout attribute flag
- DEFAULT_CHARSET, // character set identifier
- OUT_DEFAULT_PRECIS, // output precision
- CLIP_DEFAULT_PRECIS,// clipping precision
- DEFAULT_QUALITY, // output quality
- DEFAULT_PITCH, // pitch and family
- (LPCWSTR)wstr // pointer to typeface name string
- );
- angle = fl_angle_;
- HDC gc = (HDC)fl_graphics_driver->gc();
- if (!gc) gc = fl_GetDC(0);
- SelectObject(gc, fid);
- GetTextMetrics(gc, &metr);
-// BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar);
-// ...would be the right call, but is not implemented into Window95! (WinNT?)
- //GetCharWidth(fl_gc, 0, 255, width);
- int i;
- memset(width, 0, 64 * sizeof(int*));
-#if HAVE_GL
- for (i = 0; i < 64; i++) glok[i] = 0;
-#endif
- size = fsize;
-}
-
-Fl_GDI_Font_Descriptor::~Fl_GDI_Font_Descriptor() {
-#if HAVE_GL
-// Delete list created by gl_draw(). This is not done by this code
-// as it will link in GL unnecessarily. There should be some kind
-// of "free" routine pointer, or a subclass?
-#endif
- if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
- DeleteObject(fid);
- for (int i = 0; i < 64; i++) {
- if ( width[i] ) free(width[i]);
- }
-}
-
-////////////////////////////////////////////////////////////////
-
-// WARNING: if you add to this table, you must redefine FL_FREE_FONT
-// in Enumerations.H & recompile!!
-static Fl_Fontdesc built_in_table[] = {
- {" Microsoft Sans Serif"},
- {"BMicrosoft Sans Serif"},
- {"IMicrosoft Sans Serif"},
- {"PMicrosoft Sans Serif"},
-{" Courier New"},
-{"BCourier New"},
-{"ICourier New"},
-{"PCourier New"},
-{" Times New Roman"},
-{"BTimes New Roman"},
-{"ITimes New Roman"},
-{"PTimes New Roman"},
-{" Symbol"},
-{" Terminal"},
-{"BTerminal"},
-{" Wingdings"},
-};
-
-Fl_Fontdesc* fl_fonts = built_in_table;
-
-static Fl_GDI_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) {
- Fl_Fontdesc* s = fl_fonts+fnum;
- if (!s->name) s = fl_fonts; // use 0 if fnum undefined
- Fl_GDI_Font_Descriptor* f;
- for (f = (Fl_GDI_Font_Descriptor*)s->first; f; f = (Fl_GDI_Font_Descriptor*)f->next)
- if (f->size == size && f->angle == angle) return f;
- f = new Fl_GDI_Font_Descriptor(s->name, size);
- f->next = s->first;
- s->first = f;
- return f;
-}
-
-////////////////////////////////////////////////////////////////
-// Public interface:
-
-static void fl_font(Fl_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
- if (fnum==-1) { // just make sure that we will load a new font next time
- fl_angle_ = 0;
- driver->Fl_Graphics_Driver::font(0, 0);
- return;
- }
- if (fnum == driver->Fl_Graphics_Driver::font() && size == ((Fl_GDI_Graphics_Driver*)driver)->size_unscaled() && angle == fl_angle_) return;
- fl_angle_ = angle;
- driver->Fl_Graphics_Driver::font(fnum, size);
- driver->font_descriptor( find(fnum, size, angle) );
-}
-
-void Fl_GDI_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
- fl_font(this, fnum, size, 0);
-}
-
-int Fl_GDI_Graphics_Driver::height_unscaled() {
- Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
- if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
- else return -1;
-}
-
-int Fl_GDI_Graphics_Driver::descent_unscaled() {
- Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
- if (fl_fontsize) return fl_fontsize->metr.tmDescent;
- else return -1;
-}
-
-Fl_Fontsize Fl_GDI_Graphics_Driver::size_unscaled() {
- if (font_descriptor()) return size_;
- return -1;
-}
-
-double Fl_GDI_Graphics_Driver::width_unscaled(const char* c, int n) {
- if (n == 0) return 0;
- int len1 = fl_utf8len1(*c);
- if (n > len1 && len1 > 0) { // a text with several codepoints: compute its typographical width
- int wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
- if (wn >= wstr_len) {
- wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
- wstr_len = wn + 1;
- wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
- }
- HDC gc2 = gc_;
- HWND hWnd;
- if (!gc2) {
- hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL;
- gc2 = GetDC(hWnd);
- }
- SelectObject(gc2, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
- SIZE s;
- GetTextExtentPoint32W(gc2, (WCHAR*)wstr, wn, &s);
- if (gc2 && gc2 != gc_) ReleaseDC(hWnd, gc2);
- return (double)s.cx;
- }
- int i = 0;
- if (!font_descriptor()) return -1.0;
- double w = 0.0;
- char *end = (char *)&c[n];
- while (i < n) {
- unsigned int ucs;
- int l;
- ucs = fl_utf8decode((const char*)(c + i), end, &l);
-// if (l < 1) l = 1;
- i += l;
- if (!fl_nonspacing(ucs)) {
- w += width_unscaled(ucs);
- }
- }
- return w;
-}
-
-double Fl_GDI_Graphics_Driver::width_unscaled(unsigned int c) {
- Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
- unsigned int r;
- SIZE s;
- // Special Case Handling of Unicode points over U+FFFF.
- // The logic (below) computes a lookup table for char widths
- // on-the-fly, but the table only covers codepoints up to
- // U+FFFF, which covers the basic multilingual plane, but
- // not any higher plane, or glyphs that require surrogate-pairs
- // to encode them in WinXX, which is UTF16.
- // This code assumes that these glyphs are rarely used and simply
- // measures them explicitly if they occur - This will be slow...
- if(c > 0x0000FFFF) { // UTF16 surrogate pair is needed
- if (!gc_) { // We have no valid gc, so nothing to measure - bail out
- return 0.0;
- }
- int cc; // cell count
- unsigned short u16[4]; // Array for UTF16 representation of c
- // Creates a UTF16 string from a UCS code point.
- cc = fl_ucs_to_Utf16(c, u16, 4);
- // Make sure the current font is selected before we make the measurement
- SelectObject(gc_, fl_fontsize->fid);
- // measure the glyph width
- GetTextExtentPoint32W(gc_, (WCHAR*)u16, cc, &s);
- return (double)s.cx;
- }
- // else - this falls through to the lookup-table for glyph widths
- // in the basic multilingual plane
- r = (c & 0xFC00) >> 10;
- if (!fl_fontsize->width[r]) {
- fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400);
- for (int i = 0; i < 0x0400; i++) fl_fontsize->width[r][i] = -1;
- } else {
- if ( fl_fontsize->width[r][c&0x03FF] >= 0 ) { // already cached
- return (double) fl_fontsize->width[r][c & 0x03FF];
- }
- }
- unsigned short ii = r * 0x400;
- // The following code makes a best effort attempt to obtain a valid fl_gc.
- // If no fl_gc is available at the time we call fl_width(), then we first
- // try to obtain a gc from the first fltk window.
- // If that is null then we attempt to obtain the gc from the current screen
- // using (GetDC(NULL)).
- // This should resolve STR #2086
- HDC gc2 = gc_;
- HWND hWnd = 0;
- if (!gc2) { // We have no valid gc, try and obtain one
- // Use our first fltk window, or fallback to using the screen via GetDC(NULL)
- hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL;
- gc2 = GetDC(hWnd);
- }
- if (!gc2) Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!");
- SelectObject(gc2, fl_fontsize->fid);
- ii += c &0x03FF;
- GetTextExtentPoint32W(gc2, (WCHAR*)&ii, 1, &s);
- fl_fontsize->width[r][c&0x03FF] = s.cx;
- if (gc2 && gc2 != gc_) ReleaseDC(hWnd, gc2);
- return (double) fl_fontsize->width[r][c & 0x03FF];
-}
-
-/* Add function pointer to allow us to access GetGlyphIndicesW on systems that have it,
- * without crashing on systems that do not. */
-/* DWORD WINAPI GetGlyphIndicesW(HDC,LPCWSTR,int,LPWORD,DWORD) */
-typedef DWORD (WINAPI* fl_GetGlyphIndices_func)(HDC,LPCWSTR,int,LPWORD,DWORD);
-
-static fl_GetGlyphIndices_func fl_GetGlyphIndices = NULL; // used to hold a proc pointer for GetGlyphIndicesW
-static int have_loaded_GetGlyphIndices = 0; // Set this non-zero once we have tried to load GetGlyphIndices
-
-// Function that tries to dynamically load GetGlyphIndicesW at runtime
-static void GetGlyphIndices_init() {
- // Since not all versions of Windows include GetGlyphIndicesW support,
- // we do a run-time check for the required function.
- HMODULE hMod = GetModuleHandle("GDI32.DLL");
- if (hMod) {
- // check that GetGlyphIndicesW is available
- fl_GetGlyphIndices = (fl_GetGlyphIndices_func)GetProcAddress(hMod, "GetGlyphIndicesW");
- }
- have_loaded_GetGlyphIndices = -1; // set this non-zero when we have attempted to load GetGlyphIndicesW
-} // GetGlyphIndices_init function
-
-static void on_printer_extents_update(int &dx, int &dy, int &w, int &h, HDC gc)
-// converts text extents from device coords to logical coords
-{
- POINT pt[3] = { {0, 0}, {dx, dy}, {dx+w, dy+h} };
- DPtoLP(gc, pt, 3);
- w = pt[2].x - pt[1].x;
- h = pt[2].y - pt[1].y;
- dx = pt[1].x - pt[0].x;
- dy = pt[1].y - pt[0].y;
-}
-
-// if printer context, extents shd be converted to logical coords
-#define EXTENTS_UPDATE(x,y,w,h,gc) \
- if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { \
- on_printer_extents_update(x,y,w,h,gc); \
- }
-
-// Function to determine the extent of the "inked" area of the glyphs in a string
-void Fl_GDI_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
-
- Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
- if (!fl_fontsize) { // no valid font, nothing to measure
- w = 0; h = 0;
- dx = dy = 0;
- return;
- }
-
- static unsigned short *ext_buff = NULL; // UTF-16 converted version of input UTF-8 string
- static WORD *w_buff = NULL; // glyph indices array
- static unsigned wc_len = 0; // current string buffer dimensions
- static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; // identity mat for GetGlyphOutlineW
- GLYPHMETRICS metrics;
- int maxw = 0, maxh = 0, dh;
- int minx = 0, miny = -999999;
- unsigned len = 0, idx = 0;
- HWND hWnd = 0;
- HDC gc2 = gc_; // local copy of current gc - make a copy in case we change it...
- int has_surrogates; // will be set if the string contains surrogate pairs
-
- // Have we loaded the GetGlyphIndicesW function yet?
- if (have_loaded_GetGlyphIndices == 0) {
- GetGlyphIndices_init();
- }
- // Do we have a usable GetGlyphIndices function?
- if(!fl_GetGlyphIndices) goto exit_error; // No GetGlyphIndices function, use fallback mechanism instead
-
- // The following code makes a best effort attempt to obtain a valid fl_gc.
- // See description in fl_width() above for an explanation.
- if (!gc2) { // We have no valid gc, try and obtain one
- // Use our first fltk window, or fallback to using the screen via GetDC(NULL)
- hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL;
- gc2 = GetDC(hWnd);
- }
- if (!gc2) goto exit_error; // no valid gc, attempt to use fallback measure
-
- // now convert the string to WCHAR and measure it
- len = fl_utf8toUtf16(c, n, ext_buff, wc_len);
- if(len >= wc_len) {
- if(ext_buff) {delete [] ext_buff;}
- if(w_buff) {delete [] w_buff;}
- wc_len = len + 64;
- ext_buff = new unsigned short[wc_len];
- w_buff = new WORD[wc_len];
- len = fl_utf8toUtf16(c, n, ext_buff, wc_len);
- }
- SelectObject(gc2, fl_fontsize->fid);
-
- // Are there surrogate-pairs in this string? If so GetGlyphIndicesW will fail
- // since it can only handle the BMP range.
- // We ideally want to use GetGlyphIndicesW, as it is the Right Thing, but it
- // only works for the BMP, so we leverage GetCharacterPlacementW instead, which
- // is not ideal, but works adequately well, and does handle surrogate pairs.
- has_surrogates = 0;
- for(unsigned ll = 0; ll < len; ll++) {
- if((ext_buff[ll] >= 0xD800) && (ext_buff[ll] < 0xE000)) {
- has_surrogates = -1;
- break;
- }
- }
- if (has_surrogates) {
- // GetGlyphIndices will not work - use GetCharacterPlacementW() instead
- GCP_RESULTSW gcp_res;
- memset(w_buff, 0, (sizeof(WORD) * wc_len));
- memset(&gcp_res, 0, sizeof(GCP_RESULTSW));
- gcp_res.lpGlyphs = (LPWSTR)w_buff;
- gcp_res.nGlyphs = wc_len;
- gcp_res.lStructSize = sizeof(gcp_res);
-
- DWORD dr = GetCharacterPlacementW(gc2, (WCHAR*)ext_buff, len, 0, &gcp_res, GCP_GLYPHSHAPE);
- if(dr) {
- len = gcp_res.nGlyphs;
- } else goto exit_error;
- } else {
- if (fl_GetGlyphIndices(gc_, (WCHAR*)ext_buff, len, w_buff, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) {
- // some error occurred here - just return fl_measure values
- goto exit_error;
- }
- }
-
- // now we have the glyph array we measure each glyph in turn...
- for(idx = 0; idx < len; idx++){
- if (GetGlyphOutlineW (gc2, w_buff[idx], GGO_METRICS | GGO_GLYPH_INDEX,
- &metrics, 0, NULL, &matrix) == GDI_ERROR) {
- goto exit_error;
- }
- maxw += metrics.gmCellIncX;
- if(idx == 0) minx = metrics.gmptGlyphOrigin.x;
- dh = metrics.gmBlackBoxY - metrics.gmptGlyphOrigin.y;
- if(dh > maxh) maxh = dh;
- if(miny < metrics.gmptGlyphOrigin.y) miny = metrics.gmptGlyphOrigin.y;
- }
- // for the last cell, we only want the bounding X-extent, not the glyphs increment step
- maxw = maxw - metrics.gmCellIncX + metrics.gmBlackBoxX + metrics.gmptGlyphOrigin.x;
- w = maxw - minx;
- h = maxh + miny;
- dx = minx;
- dy = -miny;
- EXTENTS_UPDATE(dx, dy, w, h, gc_);
- return; // normal exit
-
-exit_error:
- // some error here - just return fl_measure values
- w = (int)width(c, n);
- h = height_unscaled();
- dx = 0;
- dy = descent_unscaled() - h;
- EXTENTS_UPDATE(dx, dy, w, h, gc_);
- return;
-} // fl_text_extents
-
-void Fl_GDI_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y) {
- COLORREF oldColor = SetTextColor(gc_, fl_RGB());
- // avoid crash if no font has been set yet
- if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
- SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
- int wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
- if(wn >= wstr_len) {
- wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
- wstr_len = wn + 1;
- wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
- }
- TextOutW(gc_, x, y, (WCHAR*)wstr, wn);
- SetTextColor(gc_, oldColor); // restore initial state
-}
-
-void Fl_GDI_Graphics_Driver::draw_unscaled(int angle, const char* str, int n, int x, int y) {
- fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), angle);
- int wn = 0; // count of UTF16 cells to render full string
- COLORREF oldColor = SetTextColor(gc_, fl_RGB());
- SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
- wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
- if(wn >= wstr_len) { // Array too small
- wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
- wstr_len = wn + 1;
- wn = fl_utf8toUtf16(str, n, wstr, wstr_len); // respin the translation
- }
- TextOutW(gc_, x, y, (WCHAR*)wstr, wn);
- SetTextColor(gc_, oldColor);
- fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), 0);
-}
-
-void Fl_GDI_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
- int wn;
- wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
- if(wn >= wstr_len) {
- wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
- wstr_len = wn + 1;
- wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
- }
-
- COLORREF oldColor = SetTextColor(gc_, fl_RGB());
- SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
-#ifdef RTL_CHAR_BY_CHAR
- int i = 0;
- int lx = 0;
- while (i < wn) { // output char by char is very bad for Arabic but coherent with fl_width()
- lx = (int) width(wstr[i]);
- x -= lx;
- TextOutW(gc_, x, y, (WCHAR*)wstr + i, 1);
- if (fl_nonspacing(wstr[i])) {
- x += lx;
- }
- i++;
- }
-#else
- UINT old_align = SetTextAlign(gc_, TA_RIGHT | TA_RTLREADING);
- TextOutW(gc_, x, y - height_unscaled() + descent_unscaled(), (WCHAR*)wstr, wn);
- SetTextAlign(gc_, old_align);
-#endif
- SetTextColor(gc_, oldColor);
-}
-#endif
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
deleted file mode 100644
index 3a8e70689..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ /dev/null
@@ -1,826 +0,0 @@
-//
-// Windows image drawing code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2024 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// I hope a simple and portable method of drawing color and monochrome
-// images. To keep this simple, only a single storage type is
-// supported: 8 bit unsigned data, byte order RGB, and pixels are
-// stored packed into rows with the origin at the top-left. It is
-// possible to alter the size of pixels with the "delta" argument, to
-// add alpha or other information per pixel. It is also possible to
-// change the origin and direction of the image data by messing with
-// the "delta" and "linedelta", making them negative, though this may
-// defeat some of the shortcuts in translating the image for X.
-
-// Unbelievably (since it conflicts with how most PC software works)
-// Micro$oft picked a bottom-up and BGR storage format for their
-// DIB images. I'm pretty certain there is a way around this, but
-// I can't find any other than the brute-force method of drawing
-// each line as a separate image. This may also need to be done
-// if the delta is any amount other than 1, 3, or 4.
-
-////////////////////////////////////////////////////////////////
-
-#include <config.h>
-#include "Fl_GDI_Graphics_Driver.H"
-#include "../WinAPI/Fl_WinAPI_System_Driver.H"
-#include <FL/Fl.H>
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-#include <FL/Fl_Image_Surface.H>
-
-#define MAXBUFFER 0x40000 // 256k
-
-void fl_release_dc(HWND, HDC); // from Fl_win32.cxx
-
-#if USE_COLORMAP
-
-// error-diffusion dither into the FLTK colormap
-static void dither(uchar* to, const uchar* from, int w, int delta) {
- static int ri, gi, bi, dir;
- int r=ri, g=gi, b=bi;
- int d, td;
- if (dir) {
- dir = 0;
- from = from+(w-1)*delta;
- to = to+(w-1);
- d = -delta;
- td = -1;
- } else {
- dir = 1;
- d = delta;
- td = 1;
- }
- for (; w--; from += d, to += td) {
- r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255;
- int rr = r*FL_NUM_RED/256;
- r -= rr*255/(FL_NUM_RED-1);
- g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255;
- int gg = g*FL_NUM_GREEN/256;
- g -= gg*255/(FL_NUM_GREEN-1);
- b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255;
- int bb = b*FL_NUM_BLUE/256;
- b -= bb*255/(FL_NUM_BLUE-1);
- *to = uchar(FL_COLOR_CUBE+(bb*FL_NUM_RED+rr)*FL_NUM_GREEN+gg);
- }
- ri = r; gi = g; bi = b;
-}
-
-// error-diffusion dither into the FLTK colormap
-static void monodither(uchar* to, const uchar* from, int w, int delta) {
- static int ri,dir;
- int r=ri;
- int d, td;
- if (dir) {
- dir = 0;
- from = from+(w-1)*delta;
- to = to+(w-1);
- d = -delta;
- td = -1;
- } else {
- dir = 1;
- d = delta;
- td = 1;
- }
- for (; w--; from += d, to += td) {
- r += *from; if (r < 0) r = 0; else if (r>255) r = 255;
- int rr = r*FL_NUM_GRAY/256;
- r -= rr*255/(FL_NUM_GRAY-1);
- *to = uchar(FL_GRAY_RAMP+rr);
- }
- ri = r;
-}
-
-#endif // USE_COLORMAP
-
-static int fl_abs(int v) { return v<0 ? -v : v; }
-
-static void innards(const uchar *buf, int X, int Y, int W, int H,
- int delta, int linedelta, int depth,
- Fl_Draw_Image_Cb cb, void* userdata, HDC gc)
-{
- char indexed = 0;
-
-#if USE_COLORMAP
- indexed = (fl_palette != 0);
-#endif
-
- if (depth==0) depth = 3;
- if (indexed || !fl_can_do_alpha_blending())
- depth = (depth-1)|1;
-
- if (!linedelta) linedelta = W*fl_abs(delta);
-
- int x = 0, y = 0, w = 0, h = 0;
- fl_clip_box(X, Y, W, H, x, y, w, h);
- if (w<=0 || h<=0) return;
- if (buf) buf += (x-X)*delta + (y-Y)*linedelta;
-
- // bmibuffer: BITMAPINFOHEADER + 256 colors (RGBQUAD) + 1 (rounding effects ?)
- static U32 bmibuffer[sizeof(BITMAPINFOHEADER)/4 + 257];
- BITMAPINFO *bmi = (BITMAPINFO*)bmibuffer;
- if (!bmi->bmiHeader.biSize) {
- bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi->bmiHeader.biPlanes = 1;
- bmi->bmiHeader.biCompression = BI_RGB;
- bmi->bmiHeader.biXPelsPerMeter = 0;
- bmi->bmiHeader.biYPelsPerMeter = 0;
- bmi->bmiHeader.biClrUsed = 0;
- bmi->bmiHeader.biClrImportant = 0;
- }
-#if USE_COLORMAP
- if (indexed) {
- for (short i=0; i<256; i++) {
- *((short*)(bmi->bmiColors)+i) = i;
- }
- } else
-#endif
- if (depth<3) {
- RGBQUAD *bmi_colors = &(bmi->bmiColors[0]); // use pointer to suppress warning (STR #3199)
- for (int i=0; i<256; i++) {
- bmi_colors[i].rgbBlue = (uchar)i; // = bmi->bmiColors[i]
- bmi_colors[i].rgbGreen = (uchar)i;
- bmi_colors[i].rgbRed = (uchar)i;
- bmi_colors[i].rgbReserved = (uchar)0; // must be zero
- }
- }
- bmi->bmiHeader.biWidth = w;
-#if USE_COLORMAP
- bmi->bmiHeader.biBitCount = indexed ? 8 : depth*8;
- int pixelsize = indexed ? 1 : depth;
-#else
- bmi->bmiHeader.biBitCount = depth*8;
- int pixelsize = depth;
-#endif
- if (depth==2) { // special case: gray with alpha
- bmi->bmiHeader.biBitCount = 32;
- pixelsize = 4;
- }
- int linesize = (pixelsize*w+3)&~3;
-
- static U32* buffer;
- static long buffer_size;
- int blocking = h;
- {
- int size = linesize * h;
- // when printing, don't limit buffer size not to get a crash in StretchDIBits
- if (size > MAXBUFFER && !fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) {
- size = MAXBUFFER;
- blocking = MAXBUFFER / linesize;
- }
- if (size > buffer_size) {
- delete[] buffer;
- buffer_size = size;
- buffer = new U32[(size + 3) / 4];
- }
- }
- bmi->bmiHeader.biHeight = blocking;
- static U32* line_buffer;
- if (!buf) {
- int size = W*delta;
- static int line_buf_size;
- if (size > line_buf_size) {
- delete[] line_buffer;
- line_buf_size = size;
- line_buffer = new U32[(size+3)/4];
- }
- }
- for (int j=0; j<h; ) {
- int k;
- for (k = 0; j<h && k<blocking; k++, j++) {
- const uchar* from;
- if (!buf) { // run the converter:
- cb(userdata, x-X, y-Y+j, w, (uchar*)line_buffer);
- from = (uchar*)line_buffer;
- } else {
- from = buf;
- buf += linedelta;
- }
- uchar *to = (uchar*)buffer+(blocking-k-1)*linesize;
-#if USE_COLORMAP
- if (indexed) {
- if (depth<3)
- monodither(to, from, w, delta);
- else
- dither(to, from, w, delta);
- } else
-#endif
- {
- int i;
- switch (depth) {
- case 1:
- for (i=w; i--; from += delta) *to++ = *from;
- break;
- case 2:
- for (i=w; i--; from += delta, to += 4) {
- uchar a = from[1];
- uchar gray = (from[0]*a)>>8;
- to[0] = gray;
- to[1] = gray;
- to[2] = gray;
- to[3] = a;
- }
- break;
- case 3:
- for (i=w; i--; from += delta, to += 3) {
- uchar r = from[0];
- to[0] = from[2];
- to[1] = from[1];
- to[2] = r;
- }
- break;
- case 4:
- for (i=w; i--; from += delta, to += 4) {
- uchar a = from[3];
- uchar r = from[0];
- to[0] = (from[2]*a)>>8;
- to[1] = (from[1]*a)>>8;
- to[2] = (r*a)>>8;
- to[3] = from[3];
- }
- break;
- }
- }
- } // for (k = 0; j<h && k<blocking ...)
-
- if (fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) {
- // if print context, device and logical units are not equal, so SetDIBitsToDevice
- // does not do the expected job, whereas StretchDIBits does it.
- StretchDIBits(gc, x, y+j-k, w, k, 0, 0, w, k,
- (LPSTR)((uchar*)buffer+(blocking-k)*linesize),
- bmi,
-#if USE_COLORMAP
- indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS
-#else
- DIB_RGB_COLORS
-#endif
- , SRCCOPY );
- delete[] buffer;
- buffer = NULL;
- buffer_size = 0;
- }
- else {
- SetDIBitsToDevice(gc, x, y+j-k, w, k, 0, 0, 0, k,
- (LPSTR)((uchar*)buffer+(blocking-k)*linesize),
- bmi,
-#if USE_COLORMAP
- indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS
-#else
- DIB_RGB_COLORS
-#endif
- );
- }
- } // for (int j=0; j<h; )
-}
-
-void Fl_GDI_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
- if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
- d ^= FL_IMAGE_WITH_ALPHA;
- innards(buf,x,y,w,h,d,l,fl_abs(d),0,0, gc_);
- } else {
- innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0, gc_);
- }
-}
-
-void Fl_GDI_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data,
- int x, int y, int w, int h,int d) {
- if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
- d ^= FL_IMAGE_WITH_ALPHA;
- innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data, gc_);
- } else {
- innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data, gc_);
- }
-}
-
-void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
- if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
- d ^= FL_IMAGE_WITH_ALPHA;
- innards(buf,x,y,w,h,d,l,1,0,0, gc_);
- } else {
- innards(buf,x,y,w,h,d,l,1,0,0, gc_);
- }
-}
-
-void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data,
- int x, int y, int w, int h,int d) {
- if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
- d ^= FL_IMAGE_WITH_ALPHA;
- innards(0,x,y,w,h,d,0,1,cb,data, gc_);
- } else {
- innards(0,x,y,w,h,d,0,1,cb,data, gc_);
- }
-}
-
-#if USE_COLORMAP
-void Fl_GDI_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
- // use the error diffusion dithering code to produce a much nicer block:
- if (fl_palette) {
- uchar c[3];
- c[0] = r; c[1] = g; c[2] = b;
- innards(c, floor(x), floor(y), floor(x + w) - floor(x), floor(y + h) - floor(y),
- 0,0,0,0,0, (HDC)gc());
- return;
- }
- Fl_Graphics_Driver::colored_rectf(x, y, w, h, r, g, b);
-}
-#endif
-
-// Create an N-bit bitmap for masking...
-HBITMAP Fl_GDI_Graphics_Driver::create_bitmask(int w, int h, const uchar *data) {
- // this won't work when the user changes display mode during run or
- // has two screens with different depths
- HBITMAP bm;
- static uchar hiNibble[16] =
- { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 };
- static uchar loNibble[16] =
- { 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
- 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f };
- HDC current_gc = (HDC)Fl_Surface_Device::surface()->driver()->gc();
- int np = GetDeviceCaps(current_gc, PLANES); //: was always one on sample machines
- int bpp = GetDeviceCaps(current_gc, BITSPIXEL);//: 1,4,8,16,24,32 and more odd stuff?
- int Bpr = (bpp*w+7)/8; //: bytes per row
- int pad = Bpr&1, w1 = (w+7)/8, shr = ((w-1)&7)+1;
- if (bpp==4) shr = (shr+1)/2;
- uchar *newarray = new uchar[(Bpr+pad)*h];
- uchar *dst = newarray;
- const uchar *src = data;
-
- for (int i=0; i<h; i++) {
- // This is slooow, but we do it only once per pixmap
- for (int j=w1; j>0; j--) {
- uchar b = *src++;
- if (bpp==1) {
- *dst++ = (uchar)( hiNibble[b&15] ) | ( loNibble[(b>>4)&15] );
- } else if (bpp==4) {
- for (int k=(j==1)?shr:4; k>0; k--) {
- *dst++ = (uchar)("\377\360\017\000"[b&3]);
- b = b >> 2;
- }
- } else {
- for (int k=(j==1)?shr:8; k>0; k--) {
- if (b&1) {
- *dst++=0;
- if (bpp>8) *dst++=0;
- if (bpp>16) *dst++=0;
- if (bpp>24) *dst++=0;
- } else {
- *dst++=0xff;
- if (bpp>8) *dst++=0xff;
- if (bpp>16) *dst++=0xff;
- if (bpp>24) *dst++=0xff;
- }
-
- b = b >> 1;
- }
- }
- }
-
- dst += pad;
- }
-
- bm = CreateBitmap(w, h, np, bpp, newarray);
- delete[] newarray;
-
- return bm;
-}
-
-void Fl_GDI_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) {
- DeleteObject((HGDIOBJ)bm);
-}
-
-void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) {
- X = this->floor(X);
- Y = this->floor(Y);
- cache_size(bm, W, H);
- cx = this->floor(cx); cy = this->floor(cy);
-
- HDC tempdc = CreateCompatibleDC(gc_);
- int save = SaveDC(tempdc);
- SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm));
- SelectObject(gc_, fl_brush());
- // secret bitblt code found in old Windows reference manual:
- BitBlt(gc_, X, Y, W, H, tempdc, cx, cy, 0xE20746L);
- RestoreDC(tempdc, save);
- DeleteDC(tempdc);
-}
-
-Fl_GDI_Printer_Graphics_Driver::transparent_f_type Fl_GDI_Printer_Graphics_Driver::TransparentBlt() {
- HMODULE hMod;
- static transparent_f_type fpter = ( (hMod = LoadLibrary("MSIMG32.DLL")) ?
- (transparent_f_type)GetProcAddress(hMod, "TransparentBlt") : NULL
- );
- return fpter;
-}
-
-void Fl_GDI_Printer_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
- return;
- }
- transparent_f_type fl_TransparentBlt = TransparentBlt();
- if (!fl_TransparentBlt) {
- Fl_Graphics_Driver::draw_bitmap(bm, X, Y, W, H, cx, cy);
- return;
- }
- bool recache = false;
- if (*id(bm)) {
- int *pw, *ph;
- cache_w_h(bm, pw, ph);
- recache = (*pw != bm->data_w() || *ph != bm->data_h());
- }
- if (recache || !*id(bm)) {
- bm->uncache();
- cache(bm);
- }
- HDC tempdc;
- int save;
- // algorithm for bitmap output to Fl_GDI_Printer
- Fl_Color save_c = fl_color(); // save bitmap's desired color
- uchar r, g, b;
- Fl::get_color(save_c, r, g, b);
- r = 255-r;
- g = 255-g;
- b = 255-b;
- Fl_Color background = fl_rgb_color(r, g, b); // a color very different from the bitmap's
- Fl_Image_Surface *img_surf = new Fl_Image_Surface(bm->data_w(), bm->data_h());
- Fl_Surface_Device::push_current(img_surf);
- fl_color(background);
- fl_rectf(0,0, bm->data_w(), bm->data_h()); // use this color as offscreen background
- fl_color(save_c); // back to bitmap's color
- HDC off_gc = (HDC)fl_graphics_driver->gc();
- tempdc = CreateCompatibleDC(off_gc);
- save = SaveDC(tempdc);
- SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm));
- SelectObject(off_gc, fl_brush()); // use bitmap's desired color
- BitBlt(off_gc, 0, 0, bm->data_w(), bm->data_h(), tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen
- Fl_Surface_Device::pop_current();
- SelectObject(tempdc, (HGDIOBJ)img_surf->offscreen()); // use offscreen data
- // draw it to printer context with background color as transparent
- float scaleW = bm->data_w()/float(bm->w());
- float scaleH = bm->data_h()/float(bm->h());
- fl_TransparentBlt(gc_, X, Y, W, H, tempdc,
- int(cx * scaleW), int(cy * scaleH), int(W * scaleW), int(H * scaleH), RGB(r, g, b) );
- delete img_surf;
- RestoreDC(tempdc, save);
- DeleteDC(tempdc);
- if (recache) bm->uncache();
-}
-
-
-// Create a 1-bit mask used for alpha blending
-HBITMAP Fl_GDI_Graphics_Driver::create_alphamask(int w, int h, int d, int ld, const uchar *array) {
- HBITMAP bm;
- int bmw = (w + 7) / 8;
- uchar *bitmap = new uchar[bmw * h];
- uchar *bitptr, bit;
- const uchar *dataptr;
- int x, y;
- static uchar dither[16][16] = { // Simple 16x16 Floyd dither
- { 0, 128, 32, 160, 8, 136, 40, 168,
- 2, 130, 34, 162, 10, 138, 42, 170 },
- { 192, 64, 224, 96, 200, 72, 232, 104,
- 194, 66, 226, 98, 202, 74, 234, 106 },
- { 48, 176, 16, 144, 56, 184, 24, 152,
- 50, 178, 18, 146, 58, 186, 26, 154 },
- { 240, 112, 208, 80, 248, 120, 216, 88,
- 242, 114, 210, 82, 250, 122, 218, 90 },
- { 12, 140, 44, 172, 4, 132, 36, 164,
- 14, 142, 46, 174, 6, 134, 38, 166 },
- { 204, 76, 236, 108, 196, 68, 228, 100,
- 206, 78, 238, 110, 198, 70, 230, 102 },
- { 60, 188, 28, 156, 52, 180, 20, 148,
- 62, 190, 30, 158, 54, 182, 22, 150 },
- { 252, 124, 220, 92, 244, 116, 212, 84,
- 254, 126, 222, 94, 246, 118, 214, 86 },
- { 3, 131, 35, 163, 11, 139, 43, 171,
- 1, 129, 33, 161, 9, 137, 41, 169 },
- { 195, 67, 227, 99, 203, 75, 235, 107,
- 193, 65, 225, 97, 201, 73, 233, 105 },
- { 51, 179, 19, 147, 59, 187, 27, 155,
- 49, 177, 17, 145, 57, 185, 25, 153 },
- { 243, 115, 211, 83, 251, 123, 219, 91,
- 241, 113, 209, 81, 249, 121, 217, 89 },
- { 15, 143, 47, 175, 7, 135, 39, 167,
- 13, 141, 45, 173, 5, 133, 37, 165 },
- { 207, 79, 239, 111, 199, 71, 231, 103,
- 205, 77, 237, 109, 197, 69, 229, 101 },
- { 63, 191, 31, 159, 55, 183, 23, 151,
- 61, 189, 29, 157, 53, 181, 21, 149 },
- { 254, 127, 223, 95, 247, 119, 215, 87,
- 253, 125, 221, 93, 245, 117, 213, 85 }
- };
-
- // Generate a 1-bit "screen door" alpha mask; not always pretty, but
- // definitely fast... In the future we may be able to support things
- // like the RENDER extension in XFree86, when available, to provide
- // true RGBA-blended rendering. See:
- //
- // http://www.xfree86.org/~keithp/render/protocol.html
- //
- // for more info on XRender...
- //
- memset(bitmap, 0, bmw * h);
-
- for (dataptr = array + d - 1, y = 0; y < h; y ++, dataptr += ld)
- for (bitptr = bitmap + y * bmw, bit = 1, x = 0; x < w; x ++, dataptr += d) {
- if (*dataptr > dither[x & 15][y & 15])
- *bitptr |= bit;
- if (bit < 128) bit <<= 1;
- else {
- bit = 1;
- bitptr ++;
- }
- }
-
- bm = create_bitmask(w, h, bitmap);
- delete[] bitmap;
-
- return bm;
-}
-
-
-void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img)
-{
- Fl_Image_Surface *surface = new Fl_Image_Surface(img->data_w(), img->data_h());
- Fl_Surface_Device::push_current(surface);
- if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) {
- fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
- } else {
- fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d(), img->ld());
- if (img->d() == 2 || img->d() == 4) {
- *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)create_alphamask(img->data_w(), img->data_h(), img->d(), img->ld(), img->array);
- }
- }
- Fl_Surface_Device::pop_current();
- Fl_Offscreen offs = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surface);
- int *pw, *ph;
- cache_w_h(img, pw, ph);
- *pw = img->data_w();
- *ph = img->data_h();
- *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)offs;
-}
-
-
-void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
- X = this->floor(X);
- Y = this->floor(Y);
- cache_size(img, W, H);
- cx = this->floor(cx); cy = this->floor(cy);
- if (W + cx > img->data_w()) W = img->data_w() - cx;
- if (H + cy > img->data_h()) H = img->data_h() - cy;
- if (!*Fl_Graphics_Driver::id(img)) {
- cache(img);
- }
- if (*Fl_Graphics_Driver::mask(img)) {
- HDC new_gc = CreateCompatibleDC(gc_);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, (void*)*Fl_Graphics_Driver::mask(img));
- BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCAND);
- SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(img));
- BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCPAINT);
- RestoreDC(new_gc,save);
- DeleteDC(new_gc);
- } else if (img->d()==2 || img->d()==4) {
- copy_offscreen_with_alpha(X, Y, W, H, (HBITMAP)*Fl_Graphics_Driver::id(img), cx, cy);
- } else {
- copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy);
- }
-}
-
-
-void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) {
- if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) {
- return;
- }
- if ((rgb->d() % 2) == 0 && !fl_can_do_alpha_blending()) {
- Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy);
- return;
- }
- if (!*Fl_Graphics_Driver::id(rgb)) {
- cache(rgb);
- }
- push_clip(XP, YP, WP, HP);
- XP -= cx; YP -= cy;
- WP = rgb->w(); HP = rgb->h();
- cache_size(rgb, WP, HP);
- HDC new_gc = CreateCompatibleDC(gc_);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb));
- if ( (rgb->d() % 2) == 0 ) {
- alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h());
- } else {
- SetStretchBltMode(gc_, (Fl_Image::scaling_algorithm() == FL_RGB_SCALING_BILINEAR ? HALFTONE : BLACKONWHITE));
- StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY);
- }
- RestoreDC(new_gc, save);
- DeleteDC(new_gc);
- pop_clip();
-}
-
-
-void Fl_GDI_Printer_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) {
- if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) {
- return;
- }
- XFORM old_tr, tr;
- GetWorldTransform(gc_, &old_tr); // storing old transform
- tr.eM11 = float(rgb->w())/float(rgb->data_w());
- tr.eM22 = float(rgb->h())/float(rgb->data_h());
- tr.eM12 = tr.eM21 = 0;
- tr.eDx = float(XP);
- tr.eDy = float(YP);
- ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY);
- if (*id(rgb)) {
- int *pw, *ph;
- cache_w_h(rgb, pw, ph);
- if ( *pw != rgb->data_w() || *ph != rgb->data_h()) rgb->uncache();
- }
- if (!*id(rgb)) cache(rgb);
- draw_fixed(rgb, 0, 0, int(WP / tr.eM11), int(HP / tr.eM22), int(cx / tr.eM11), int(cy / tr.eM22));
- SetWorldTransform(gc_, &old_tr);
-}
-
-
-void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
-{
- if (id_) {
- DeleteObject((HBITMAP)id_);
- id_ = 0;
- }
-
- if (mask_) {
- delete_bitmask(mask_);
- mask_ = 0;
- }
-}
-
-// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing...
-static HBITMAP fl_create_bitmap(int w, int h, const uchar *data) {
- // we need to pad the lines out to words & swap the bits
- // in each byte.
- int w1 = (w + 7) / 8;
- int w2 = ((w + 15) / 16) * 2;
- uchar* newarray = new uchar[w2*h];
- const uchar* src = data;
- uchar* dest = newarray;
- HBITMAP bm;
- static uchar reverse[16] = /* Bit reversal lookup table */
- { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee,
- 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
-
- for (int y = 0; y < h; y++) {
- for (int n = 0; n < w1; n++, src++)
- *dest++ = (uchar)((reverse[*src & 0x0f] & 0xf0) |
- (reverse[(*src >> 4) & 0x0f] & 0x0f));
- dest += w2 - w1;
- }
-
- bm = CreateBitmap(w, h, 1, 1, newarray);
-
- delete[] newarray;
-
- return bm;
-}
-
-void Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) {
- int *pw, *ph;
- cache_w_h(bm, pw, ph);
- *pw = bm->data_w();
- *ph = bm->data_h();
- *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)fl_create_bitmap(bm->data_w(), bm->data_h(), bm->array);
-}
-
-void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) {
- X = this->floor(X);
- Y = this->floor(Y);
- cache_size(pxm, W, H);
- cx = this->floor(cx); cy = this->floor(cy);
- Fl_Region r2 = scale_clip(scale());
- if (*Fl_Graphics_Driver::mask(pxm)) {
- HDC new_gc = CreateCompatibleDC(gc_);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, (void*)*Fl_Graphics_Driver::mask(pxm));
- BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCAND);
- SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm));
- BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCPAINT);
- RestoreDC(new_gc,save);
- DeleteDC(new_gc);
- } else {
- float s = scale(); Fl_Graphics_Driver::scale(1);
- copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy);
- Fl_Graphics_Driver::scale(s);
- }
- unscale_clip(r2);
-}
-
-/* ===== Implementation note about how Fl_Pixmap objects get printed under Windows =====
- Fl_Pixmap objects are printed with the print-specific Fl_GDI_Printer_Graphics_Driver
- which uses the TransparentBlt() system function that can scale the image and treat one
- of its colors as transparent.
- Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *,...) sets need_pixmap_bg_color,
- a static class variable, to 1 and recaches the image. This calls fl_convert_pixmap()
- that checks the value of need_pixmap_bg_color. When this value is not 0, fl_convert_pixmap
- runs in a way that memorizes the list of all colors in the pixmap, computes
- a color absent from this list, uses it for the transparent pixels of the pixmap and puts
- this color value in need_pixmap_bg_color. As a result, the transparent areas of the image
- are correcty handled by the printing operation. Variable need_pixmap_bg_color is ultimately
- reset to 0.
- Fl_GDI_Graphics_Driver::make_unused_color_() which does the color computation mentioned
- above is implemented in file src/fl_draw_pixmap.cxx
- */
-void Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return;
- transparent_f_type fl_TransparentBlt = TransparentBlt();
- if (fl_TransparentBlt) {
- need_pixmap_bg_color = 1;
- pxm->uncache();
- cache(pxm);
- HDC new_gc = CreateCompatibleDC(gc_);
- int save = SaveDC(new_gc);
- SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm));
- // print all of offscreen but its parts in background color
- float scaleW = pxm->data_w()/float(pxm->w());
- float scaleH = pxm->data_h()/float(pxm->h());
- fl_TransparentBlt(gc_, X, Y, W, H, new_gc,
- int(cx * scaleW), int(cy * scaleH), int(W * scaleW), int(H * scaleH), need_pixmap_bg_color );
- RestoreDC(new_gc,save);
- DeleteDC(new_gc);
- need_pixmap_bg_color = 0;
- }
- else {
- copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy);
- }
-}
-
-// Makes an RGB triplet different from all the colors used in the pixmap
-// and computes Fl_Graphics_Driver::need_pixmap_bg_color from this triplet
-void Fl_GDI_Graphics_Driver::make_unused_color_(uchar &r, uchar &g, uchar &b, int color_count, void **data) {
- typedef struct { uchar r; uchar g; uchar b; } UsedColor;
- UsedColor *used_colors = *(UsedColor**)data;
- int i;
- r = 2; g = 3; b = 4;
- while (1) {
- for ( i=0; i<color_count; i++ )
- if ( used_colors[i].r == r &&
- used_colors[i].g == g &&
- used_colors[i].b == b )
- break;
- if (i >= color_count) {
- free((void*)used_colors);
- *(UsedColor**)data = NULL;
- need_pixmap_bg_color = RGB(r, g, b);
- return;
- }
- if (r < 255) {
- r++;
- } else {
- r = 0;
- if (g < 255) {
- g++;
- } else {
- g = 0;
- b++;
- }
- }
- }
-}
-
-void Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img) {
- Fl_Image_Surface *surf = new Fl_Image_Surface(img->data_w(), img->data_h());
- Fl_Surface_Device::push_current(surf);
- uchar **pbitmap = surf->driver()->mask_bitmap();
- *pbitmap = (uchar*)1;// will instruct fl_draw_pixmap() to compute the image's mask
- fl_draw_pixmap(img->data(), 0, 0, FL_BLACK);
- uchar *bitmap = *pbitmap;
- if (bitmap) {
- *Fl_Graphics_Driver::mask(img) =
- (fl_uintptr_t)create_bitmask(img->data_w(), img->data_h(), bitmap);
- delete[] bitmap;
- }
- *pbitmap = 0;
- Fl_Surface_Device::pop_current();
- Fl_Offscreen id = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf);
- int *pw, *ph;
- cache_w_h(img, pw, ph);
- *pw = img->data_w();
- *ph = img->data_h();
- *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)id;
-}
-
-void Fl_GDI_Graphics_Driver::uncache_pixmap(fl_uintptr_t offscreen) {
- DeleteObject((HBITMAP)offscreen);
-}
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
deleted file mode 100644
index 9d086f353..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
+++ /dev/null
@@ -1,111 +0,0 @@
-//
-// Line style code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_GDI_Graphics_Driver_line_style.cxx
-
- \brief Line style drawing utility for Windows (GDI) platform.
-*/
-
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-
-#include "Fl_GDI_Graphics_Driver.H"
-
-
-void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) {
-
- // According to Bill, the "default" cap and join should be the
- // "fastest" mode supported for the platform. I don't know why
- // they should be different (same graphics cards, etc., right?) MRS
-
- static const DWORD Cap[4] = {PS_ENDCAP_FLAT, PS_ENDCAP_FLAT, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE};
- static const DWORD Join[4] = {PS_JOIN_ROUND, PS_JOIN_MITER, PS_JOIN_ROUND, PS_JOIN_BEVEL};
-
- int s1 = PS_GEOMETRIC | Cap[(style>>8)&3] | Join[(style>>12)&3];
- DWORD a[16];
- int n = 0;
- if (dashes && dashes[0]) {
- s1 |= PS_USERSTYLE;
- for (n = 0; n < 16 && *dashes; n++) a[n] = *dashes++;
- } else {
- s1 |= style & 0xff; // allow them to pass any low 8 bits for style
- }
- if ((style || n) && !width) width = int(scale()); // fix cards that do nothing for 0?
- if (!width) width = 1;
- if (!fl_current_xmap) color(FL_BLACK);
- LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()?
- HPEN newpen = ExtCreatePen(s1, width, &penbrush, n, n ? a : 0);
- if (!newpen) {
- Fl::error("fl_line_style(): Could not create GDI pen object.");
- return;
- }
- HPEN oldpen = (HPEN)SelectObject(gc_, newpen);
- DeleteObject(oldpen);
- DeleteObject(fl_current_xmap->pen);
- fl_current_xmap->pen = newpen;
- style_ = style;
-}
-
-#if USE_GDIPLUS
-
-void Fl_GDIplus_Graphics_Driver::line_style(int style, int width, char* dashes) {
- if (!active) return Fl_Scalable_Graphics_Driver::line_style(style, width, dashes);
- int gdi_width = (width ? width : 1);
- pen_->SetWidth(Gdiplus::REAL(gdi_width));
- int standard_dash = style & 0x7;
- if (standard_dash == FL_DASH )
- pen_->SetDashStyle(Gdiplus::DashStyleDash);
- else if (standard_dash == FL_DOT )
- pen_->SetDashStyle(Gdiplus::DashStyleDot);
- else if (standard_dash == FL_DASHDOT )
- pen_->SetDashStyle(Gdiplus::DashStyleDashDot);
- else if (standard_dash == FL_DASHDOTDOT )
- pen_->SetDashStyle(Gdiplus::DashStyleDashDotDot);
- else if(!dashes || !*dashes)
- pen_->SetDashStyle(Gdiplus::DashStyleSolid);
-
- if (style & FL_CAP_ROUND ) {
- pen_->SetStartCap(Gdiplus::LineCapRound);
- pen_->SetEndCap(Gdiplus::LineCapRound);
- } else if (style & FL_CAP_SQUARE ) {
- pen_->SetStartCap(Gdiplus::LineCapSquare);
- pen_->SetEndCap(Gdiplus::LineCapSquare);
- } else {
- pen_->SetStartCap(Gdiplus::LineCapFlat);
- pen_->SetEndCap(Gdiplus::LineCapFlat);
- }
-
- if (style & FL_JOIN_MITER ) {
- pen_->SetLineJoin(Gdiplus::LineJoinMiter);
- } else if (style & FL_JOIN_BEVEL ) {
- pen_->SetLineJoin(Gdiplus::LineJoinBevel);
- } else {
- pen_->SetLineJoin(Gdiplus::LineJoinRound);
- }
-
- if (dashes && *dashes) {
- int n = 0; while (dashes[n]) n++;
- Gdiplus::REAL *gdi_dashes = new Gdiplus::REAL[n];
- for (int i = 0; i < n; i++) gdi_dashes[i] = dashes[i]/float(gdi_width);
- pen_->SetDashPattern(gdi_dashes, n);
- delete[] gdi_dashes;
- }
- Fl_Scalable_Graphics_Driver::line_style(style, width, dashes);
-}
-
-#endif
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
deleted file mode 100644
index a86242e12..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
+++ /dev/null
@@ -1,320 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-/**
- \file Fl_GDI_Graphics_Driver_rect.cxx
- \brief Windows GDI specific line and polygon drawing with integer coordinates.
- */
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/Fl_Widget.H>
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-
-#include "Fl_GDI_Graphics_Driver.H"
-
-
-// --- line and polygon drawing with integer coordinates
-
-void Fl_GDI_Graphics_Driver::point(int x, int y) {
- rectf(x, y, 1, 1);
-}
-
-void Fl_GDI_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
- // make pen have a one-pixel width
- line_style_unscaled( (color()==FL_WHITE?FL_SOLID:FL_DOT), 1, NULL);
- int right = this->floor(x+w-1), bottom = this->floor(y+h-1);
- x = this->floor(x); y = this->floor(y);
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, right, y);
- LineTo(gc_, right, bottom);
- LineTo(gc_, x, bottom);
- LineTo(gc_, x, y);
-}
-
-void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) {
- // Windows 95/98/ME do not implement the dotted line style, so draw
- // every other pixel around the focus area...
- w = floor(x+w-1) - floor(x) + 1;
- h = floor(y+h-1) - floor(y) + 1;
- x = floor(x); y = floor(y);
- int i=1, xx, yy;
- COLORREF c = fl_RGB();
- for (xx = 0; xx < w; xx++, i++) if (i & 1) SetPixel(gc_, x+xx, y, c);
- for (yy = 0; yy < h; yy++, i++) if (i & 1) SetPixel(gc_, x+w, y+yy, c);
- for (xx = w; xx > 0; xx--, i++) if (i & 1) SetPixel(gc_, x+xx, y+h, c);
- for (yy = h; yy > 0; yy--, i++) if (i & 1) SetPixel(gc_, x, y+yy, c);
-}
-
-void Fl_GDI_Graphics_Driver::rect_unscaled(int x, int y, int w, int h) {
- if (is_solid_ && line_width_ > 1) {
- line_style_unscaled(FL_CAP_SQUARE, line_width_, 0); // see issue #1052
- }
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x+w, y);
- if (is_solid_ && line_width_ <= 1) LineTo(gc_, x+w, y+h+1); // see issue #1052
- LineTo(gc_, x+w, y+h);
- LineTo(gc_, x, y+h);
- LineTo(gc_, x, y);
- if (is_solid_ && line_width_ > 1) {
- line_style_unscaled(style_, line_width_, 0);
- }
-}
-
-void Fl_GDI_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) {
- RECT rect;
- rect.left = x; rect.top = y;
- rect.right = (x + w); rect.bottom = (y + h);
- FillRect(gc_, &rect, fl_brush());
-}
-
-void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) {
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x1, y1);
- SetPixel(gc_, x1, y1, fl_RGB());
-}
-
-void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x1, y1);
- LineTo(gc_, x2, y2);
- SetPixel(gc_, x2, y2, fl_RGB());
-}
-
-void* Fl_GDI_Graphics_Driver::change_pen_width(int width) { // set the width of the pen, return previous pen
- LOGBRUSH penbrush = {BS_SOLID, fl_RGB(), 0};
- HPEN newpen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, width, &penbrush, 0, 0);
- return SelectObject(gc_, newpen);
-}
-
-void Fl_GDI_Graphics_Driver::reset_pen_width(void *data) {
- DeleteObject(SelectObject(gc_, (HPEN)data));
-}
-
-void Fl_GDI_Graphics_Driver::xyline_unscaled(int x, int y, int x1) {
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x1+1 , y);
-}
-
-void Fl_GDI_Graphics_Driver::yxline_unscaled(int x, int y, int y1) {
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x, y1+1);
-}
-
-void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x1, y1);
- LineTo(gc_, x2, y2);
- LineTo(gc_, x, y);
-}
-
-void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
- MoveToEx(gc_, x, y, 0L);
- LineTo(gc_, x1, y1);
- LineTo(gc_, x2, y2);
- LineTo(gc_, x3, y3);
- LineTo(gc_, x, y);
-}
-
-void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
- POINT p[3];
- p[0].x = x; p[0].y = y;
- p[1].x = x1; p[1].y = y1;
- p[2].x = x2; p[2].y = y2;
- SelectObject(gc_, fl_brush());
- Polygon(gc_, p, 3);
-}
-
-void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
- POINT p[4];
- p[0].x = x; p[0].y = y;
- p[1].x = x1; p[1].y = y1;
- p[2].x = x2; p[2].y = y2;
- p[3].x = x3; p[3].y = y3;
- SelectObject(gc_, fl_brush());
- Polygon(gc_, p, 4);
-}
-
-// --- clipping
-
-void Fl_GDI_Graphics_Driver::push_clip(int x, int y, int w, int h) {
- HRGN r;
- if (w > 0 && h > 0) {
- r = (HRGN)XRectangleRegion(x,y,w,h);
- HRGN current = (HRGN)rstack[rstackptr];
- if (current) {
- CombineRgn(r,r,current,RGN_AND);
- }
- } else { // make empty clip region:
- r = CreateRectRgn(0,0,0,0);
- }
- if (rstackptr < region_stack_max) rstack[++rstackptr] = r;
- else Fl::warning("Fl_GDI_Graphics_Driver::push_clip: clip stack overflow!\n");
- fl_restore_clip();
-}
-
-int Fl_GDI_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
- X = x; Y = y; W = w; H = h;
- HRGN r = (HRGN)rstack[rstackptr];
- if (!r) return 0;
- // The win32 API makes no distinction between partial and complete
- // intersection, so we have to check for partial intersection ourselves.
- // However, given that the regions may be composite, we have to do
- // some voodoo stuff...
- HRGN rr = (HRGN)XRectangleRegion(x,y,w,h);
- HRGN temp = CreateRectRgn(0,0,0,0);
- int ret;
- if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint
- W = H = 0;
- ret = 2;
- } else if (EqualRgn(temp, rr)) { // complete
- ret = 0;
- } else { // partial intersection
- RECT rect;
- GetRgnBox(temp, &rect);
- if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if print context, convert coords from device to logical
- POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} };
- DPtoLP(gc_, pt, 2);
- X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y;
- }
- else {
- X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
- }
- ret = 1;
- }
- DeleteObject(temp);
- DeleteObject(rr);
- return ret;
-}
-
-int Fl_GDI_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
- if (x+w <= 0 || y+h <= 0) return 0;
- HRGN r = (HRGN)rstack[rstackptr];
- if (!r) return 1;
- RECT rect;
- if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // in case of print context, convert coords from logical to device
- POINT pt[2] = { {x, y}, {x + w, y + h} };
- LPtoDP(gc_, pt, 2);
- rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y;
- } else {
- rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
- }
- return RectInRegion(r,&rect);
-}
-
-void Fl_GDI_Graphics_Driver::restore_clip() {
- fl_clip_state_number++;
- if (gc_) {
- HRGN r = NULL;
- if (rstack[rstackptr]) r = (HRGN)scale_clip(scale());
- SelectClipRgn(gc_, (HRGN)rstack[rstackptr]); // if region is NULL, clip is automatically cleared
- if (r) unscale_clip(r);
- }
-}
-
-#if USE_GDIPLUS
-
-void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1) {
- if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1);
- bool AA = !(x == x1 || y == y1);
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- pen_->SetColor(gdiplus_color_);
- if (AA) graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.DrawLine(pen_, x, y, x1, y1);
-}
-
-void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
- if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1, x2, y2);
- line(x, y, x1, y1);
- line(x1, y1, x2, y2);
-}
-
-void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
- if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2);
- Gdiplus::GraphicsPath path;
- Gdiplus::Point gdi2_p[3] = {Gdiplus::Point(x0, y0), Gdiplus::Point(x1, y1), Gdiplus::Point(x2, y2)};
- path.AddLines(gdi2_p, 3);
- path.CloseFigure();
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- pen_->SetColor(gdiplus_color_);
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.DrawPath(pen_, &path);
-}
-
-#define fl_min(a,b) (a < b ? a : b)
-#define fl_max(a,b) (a > b ? a : b)
-void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
- if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) ||
- (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { // rectangular loop
- int left = fl_min(x0, fl_min(x1, fl_min(x2, x3)));
- int right = fl_max(x0, fl_max(x1, fl_max(x2, x3)));
- int top = fl_min(y0, fl_min(y1, fl_min(y2, y3)));
- int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3)));
- rect(left, top, right-left+1, bottom-top+1);
- } else {
- if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2, x3, y3);
- Gdiplus::GraphicsPath path;
- Gdiplus::PointF gdi2_p[4] = {Gdiplus::PointF(x0+1-line_width_/2.f, y0+1-line_width_/2.f), Gdiplus::PointF(x1+1-line_width_/2.f, y1+1-line_width_/2.f), Gdiplus::PointF(x2+1-line_width_/2.f, y2+1-line_width_/2.f), Gdiplus::PointF(x3+1-line_width_/2.f, y3+1-line_width_/2.f)};
- path.AddLines(gdi2_p, 4);
- path.CloseFigure();
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- pen_->SetColor(gdiplus_color_);
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.DrawPath(pen_, &path);
- }
-}
-
-void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
- if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2);
- Gdiplus::GraphicsPath path;
- path.AddLine(x0, y0, x1, y1);
- path.AddLine(x1, y1, x2, y2);
- path.CloseFigure();
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- brush_->SetColor(gdiplus_color_);
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.FillPath(brush_, &path);
-}
-
-void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
- if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) ||
- (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) {
- int left = fl_min(x0, fl_min(x1, fl_min(x2, x3)));
- int right = fl_max(x0, fl_max(x1, fl_max(x2, x3)));
- int top = fl_min(y0, fl_min(y1, fl_min(y2, y3)));
- int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3)));
- rectf(left, top, right-left, bottom-top);
- } else {
- if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2, x3, y3);
- Gdiplus::GraphicsPath path;
- path.AddLine(x0, y0, x1, y1);
- path.AddLine(x1, y1, x2, y2);
- path.AddLine(x2, y2, x3, y3);
- path.CloseFigure();
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- brush_->SetColor(gdiplus_color_);
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- graphics_.FillPath(brush_, &path);
- }
-}
-#endif
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
deleted file mode 100644
index e469bb11b..000000000
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
+++ /dev/null
@@ -1,231 +0,0 @@
-//
-// Portable drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_GDI_Graphics_Driver_vertex.cxx
-
- \brief Portable drawing code for drawing arbitrary shapes with
- simple 2D transformations, implemented for Windows GDI.
-*/
-
-#include "Fl_GDI_Graphics_Driver.H"
-
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-#include <FL/math.h>
-
-
-void Fl_GDI_Graphics_Driver::end_points() {
- for (int i=0; i<n; i++) SetPixel(gc_, long_point[i].x, long_point[i].y, fl_RGB());
-}
-
-void Fl_GDI_Graphics_Driver::end_line() {
- if (n < 2) {
- end_points();
- return;
- }
- if (n>1) Polyline(gc_, long_point, n);
-}
-
-void Fl_GDI_Graphics_Driver::end_loop() {
- fixloop();
- if (n>2) transformed_vertex0(float(long_point[0].x), float(long_point[0].y));
- end_line();
-}
-
-void Fl_GDI_Graphics_Driver::end_polygon() {
- fixloop();
- if (n < 3) {
- end_line();
- return;
- }
- if (n>2) {
- SelectObject(gc_, fl_brush());
- Polygon(gc_, long_point, n);
- }
-}
-
-void Fl_GDI_Graphics_Driver::begin_complex_polygon() {
- Fl_Graphics_Driver::begin_complex_polygon();
- numcount = 0;
-}
-
-void Fl_GDI_Graphics_Driver::gap() {
- while (n>gap_+2 && long_point[n-1].x == long_point[gap_].x && long_point[n-1].y == long_point[gap_].y) n--;
- if (n > gap_+2) {
- transformed_vertex0(float(long_point[gap_].x), float(long_point[gap_].y));
- counts[numcount++] = n-gap_;
- gap_ = n;
- } else {
- n = gap_;
- }
-}
-
-void Fl_GDI_Graphics_Driver::end_complex_polygon() {
- gap();
- if (n < 3) {
- end_line();
- return;
- }
- if (n>2) {
- SelectObject(gc_, fl_brush());
- PolyPolygon(gc_, long_point, counts, numcount);
- }
-}
-
-void Fl_GDI_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {
- int llx = (int)rint(xt-rx);
- int w = (int)rint(xt+rx)-llx;
- int lly = (int)rint(yt-ry);
- int h = (int)rint(yt+ry)-lly;
-
- if (what==POLYGON) {
- SelectObject(gc_, fl_brush());
- Pie(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0);
- } else
- Arc(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0);
-}
-
-#if USE_GDIPLUS
-
-void Fl_GDIplus_Graphics_Driver::transformed_vertex(double xf, double yf) {
- if (!active) return Fl_Scalable_Graphics_Driver::transformed_vertex(xf, yf);
- transformed_vertex0(float(xf) , float(yf) );
-}
-
-void Fl_GDIplus_Graphics_Driver::vertex(double x,double y) {
- if (!active) return Fl_Scalable_Graphics_Driver::vertex(x, y);
- transformed_vertex0(float(x*m.a + y*m.c + m.x) , float(x*m.b + y*m.d + m.y) );
-}
-
-void Fl_GDIplus_Graphics_Driver::end_points() {
- if (!active) return Fl_GDI_Graphics_Driver::end_points();
- for (int i = 0; i < n; i++) point(long_point[i].x, long_point[i].y);
-}
-
-void Fl_GDIplus_Graphics_Driver::end_line() {
- if (!active) return Fl_GDI_Graphics_Driver::end_line();
- if (n < 2) {
- end_points();
- return;
- }
- if (n>1) {
- Gdiplus::GraphicsPath path;
- Gdiplus::Point *gdi2_p = new Gdiplus::Point[n];
- for (int i = 0; i < n; i++) {
- gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y);
- }
- path.AddLines(gdi2_p, n);
- delete[] gdi2_p;
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- pen_->SetColor(gdiplus_color_);
- graphics_.DrawPath(pen_, &path);
- }
-}
-
-void Fl_GDIplus_Graphics_Driver::end_loop() {
- if (!active) return Fl_GDI_Graphics_Driver::end_loop();
- fixloop();
- if (n >= 2) {
- Gdiplus::GraphicsPath path;
- Gdiplus::Point *gdi2_p = new Gdiplus::Point[n];
- for (int i = 0; i < n; i++) {
- gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y);
- }
- path.AddLines(gdi2_p, n);
- path.CloseFigure();
- delete[] gdi2_p;
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- pen_->SetColor(gdiplus_color_);
- graphics_.DrawPath(pen_, &path);
- }
-}
-
-void Fl_GDIplus_Graphics_Driver::end_polygon() {
- if (!active) return Fl_GDI_Graphics_Driver::end_polygon();
- fixloop();
- if (n < 3) {
- end_line();
- return;
- }
- if (n>2) {
- Gdiplus::GraphicsPath path;
- Gdiplus::Point *gdi2_p = new Gdiplus::Point[n];
- for (int i = 0; i < n; i++) {
- gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y);
- }
- path.AddPolygon(gdi2_p, n);
- delete[] gdi2_p;
- path.CloseFigure();
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- brush_->SetColor(gdiplus_color_);
- graphics_.FillPath(brush_, &path);
- }
-}
-
-void Fl_GDIplus_Graphics_Driver::end_complex_polygon() {
- if (!active) return Fl_GDI_Graphics_Driver::end_complex_polygon();
- gap();
- if (n < 3) {
- end_line();
- return;
- }
- if (n>2) {
- Gdiplus::GraphicsPath path;
- Gdiplus::Point *gdi2_p = new Gdiplus::Point[n];
- for (int i = 0; i < n; i++) {
- gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y);
- }
- path.AddPolygon(gdi2_p, n);
- delete[] gdi2_p;
- path.CloseFigure();
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- brush_->SetColor(gdiplus_color_);
- graphics_.FillPath(brush_, &path);
- }
-}
-
-void Fl_GDIplus_Graphics_Driver::circle(double x, double y, double r) {
- if (!active) return Fl_Scalable_Graphics_Driver::circle(x, y, r);
- double xt = transform_x(x,y);
- double yt = transform_y(x,y);
- double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
- double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
- int llx = (int)rint(xt-rx);
- int w = (int)rint(xt+rx)-llx;
- int lly = (int)rint(yt-ry);
- int h = (int)rint(yt+ry)-lly;
- Gdiplus::Graphics graphics_(gc_);
- graphics_.ScaleTransform(scale(), scale());
- graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
- if (what==POLYGON) {
- brush_->SetColor(gdiplus_color_);
- graphics_.FillPie(brush_, llx, lly, w, h, 0, 360);
- } else {
- pen_->SetColor(gdiplus_color_);
- graphics_.DrawArc(pen_, llx, lly, w, h, 0, 360);
- }
-}
-#endif
-
diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H
deleted file mode 100644
index 129a4ecbc..000000000
--- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_GDI_IMAGE_SURFACE_DRIVER_H
-#define FL_GDI_IMAGE_SURFACE_DRIVER_H
-
-#include <FL/Fl_Image_Surface.H>
-#include <FL/Fl_RGB_Image.H>
-#include <FL/platform.H>
-
-class Fl_GDI_Image_Surface_Driver : public Fl_Image_Surface_Driver {
- void end_current() FL_OVERRIDE;
-public:
- HWND pre_window;
- int _savedc;
- void mask(const Fl_RGB_Image *) FL_OVERRIDE;
- struct shape_data_type {
- HBITMAP background;
- uchar *vBits;
- Fl_RGB_Image* mask;
- } *shape_data_;
- Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off);
- ~Fl_GDI_Image_Surface_Driver();
- void set_current() FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate() FL_OVERRIDE;
- Fl_RGB_Image *image() FL_OVERRIDE;
- POINT origin;
-};
-
-#endif // FL_GDI_IMAGE_SURFACE_DRIVER_H
diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
deleted file mode 100644
index a14524ee2..000000000
--- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
+++ /dev/null
@@ -1,169 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include "Fl_GDI_Graphics_Driver.H"
-#include "../WinAPI/Fl_WinAPI_Screen_Driver.H"
-#include "Fl_GDI_Image_Surface_Driver.H"
-#include <FL/platform.H>
-#include <FL/Fl_Bitmap.H>
-#include <windows.h>
-
-
-Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
- Fl_Display_Device::display_device(); // make sure fl_graphics_driver was initialized
- float d = fl_graphics_driver->scale();
- if (!off && d != 1 && high_res) {
- w = int(w*d);
- h = int(h*d);
- }
- HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc();
- offscreen = off ? off : (Fl_Offscreen)CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h);
- if (!offscreen) offscreen = (Fl_Offscreen)CreateCompatibleBitmap(fl_GetDC(0), w, h);
- driver(Fl_Graphics_Driver::newMainGraphicsDriver());
- if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d);
- origin.x = origin.y = 0;
- shape_data_ = NULL;
-}
-
-
-Fl_GDI_Image_Surface_Driver::~Fl_GDI_Image_Surface_Driver() {
- if (shape_data_ && shape_data_->background) {
- DeleteObject(shape_data_->background);
- delete shape_data_->mask;
- free(shape_data_);
- }
- if (offscreen && !external_offscreen) DeleteObject((HBITMAP)offscreen);
- delete driver();
-}
-
-
-void Fl_GDI_Image_Surface_Driver::set_current() {
- HDC gc = fl_makeDC((HBITMAP)offscreen);
- driver()->gc(gc);
- SetWindowOrgEx(gc, origin.x, origin.y, NULL);
- Fl_Surface_Device::set_current();
- pre_window = fl_window;
- _savedc = SaveDC(gc);
- fl_window=(HWND)offscreen;
-}
-
-
-void Fl_GDI_Image_Surface_Driver::translate(int x, int y) {
- ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y);
-}
-
-
-void Fl_GDI_Image_Surface_Driver::untranslate() {
- ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all();
-}
-
-
-Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image()
-{
- if (shape_data_ && shape_data_->background) {
- // get the offscreen size in pixels
- HDC gc = fl_makeDC((HBITMAP)offscreen);
- BITMAPINFO bmi;
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 0;
- bmi.bmiHeader.biSizeImage = 0;
- GetDIBits(gc, (HBITMAP)offscreen, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
- int W = bmi.bmiHeader.biWidth;
- int H = bmi.bmiHeader.biHeight;
- int line_size = ((3*W+3)/4) * 4;
-
- // read bits of main offscreen
- uchar *dib_src = new uchar[line_size * H];
- bmi.bmiHeader.biWidth = W;
- bmi.bmiHeader.biHeight = H;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biBitCount = 24;
- GetDIBits(gc, (HBITMAP)offscreen, 0, H,
- dib_src, &bmi, DIB_RGB_COLORS);
-
- // draw above the secondary offscreen the main offscreen masked by shape_data_->mask
- GdiFlush();
- Fl_Image_Surface_Driver::copy_with_mask(shape_data_->mask, shape_data_->vBits, dib_src, ((3*W+3)/4) * 4, true);
- delete shape_data_->mask;
- delete[] dib_src;
-
- // write bits of main offscreen
- SetDIBits(gc, (HBITMAP)offscreen, 0, H, shape_data_->vBits, &bmi, DIB_RGB_COLORS);
- DeleteDC(gc);
- DeleteObject(shape_data_->background);
- shape_data_->background = NULL;
- free(shape_data_);
- shape_data_ = NULL;
- }
- Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height, 0);
- return image;
-}
-
-
-void Fl_GDI_Image_Surface_Driver::end_current()
-{
- HDC gc = (HDC)driver()->gc();
- GetWindowOrgEx(gc, &origin);
- RestoreDC(gc, _savedc);
- DeleteDC(gc);
- fl_window = pre_window;
- Fl_Surface_Device::end_current();
-}
-
-
-void Fl_GDI_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) {
- shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type));
- // get the offscreen size in pixels
- HDC gc = fl_makeDC((HBITMAP)offscreen);
- BITMAPINFO bmi;
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 0;
- bmi.bmiHeader.biSizeImage = 0;
-
- GetDIBits(gc, (HBITMAP)offscreen, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
- int W = bmi.bmiHeader.biWidth;
- int H = bmi.bmiHeader.biHeight;
-
- shape_data_->mask = Fl_Image_Surface_Driver::RGB3_to_RGB1(mask, W, H);
-
- // duplicate current offscreen content to new offscreen
- int line_size = ((3*W+3)/4) * 4;
- uchar *dib = new uchar[line_size * H]; // create temporary buffer to read DIB
- bmi.bmiHeader.biWidth = W;
- bmi.bmiHeader.biHeight = H;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biBitCount = 24;
-
- GetDIBits(gc, (HBITMAP)offscreen, 0, H, dib, &bmi, DIB_RGB_COLORS);
-
- HDC background_gc = CreateCompatibleDC(gc);
- shape_data_->background =
- CreateDIBSection(background_gc, &bmi, DIB_RGB_COLORS,
- (void**)&shape_data_->vBits, NULL, 0);
- if (!shape_data_->background) {
- Fl::error("CreateDIBSection error=%lu", GetLastError());
- }
- memcpy(shape_data_->vBits, dib, H * line_size);
- delete[] dib;
- DeleteDC(background_gc);
- DeleteDC(gc);
-}
-
diff --git a/src/drivers/PostScript/Fl_PostScript.cxx b/src/drivers/PostScript/Fl_PostScript.cxx
index 324d1c6f9..9cece371d 100644
--- a/src/drivers/PostScript/Fl_PostScript.cxx
+++ b/src/drivers/PostScript/Fl_PostScript.cxx
@@ -38,8 +38,8 @@
#if USE_PANGO
#include <FL/math.h> // for M_PI
#include <pango/pangocairo.h>
-#include <cairo/cairo-ps.h>
-#include <cairo/cairo-pdf.h>
+#include <cairo-ps.h>
+#include <cairo-pdf.h>
#include <FL/Fl_Preferences.H>
# if ! PANGO_VERSION_CHECK(1,10,0)
# error "Requires Pango 1.10 or higher"
@@ -1470,7 +1470,7 @@ void Fl_PostScript_Graphics_Driver::ps_untranslate(void)
fprintf(output, "GR GR\n");
}
-#if defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND)
+#if defined(FLTK_USE_X11)
Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
*pfname = NULL;
@@ -1492,7 +1492,7 @@ int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
return begin_job(NULL, perr_message);
}
-#endif // defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND)
+#endif // defined(FLTK_USE_X11)
# else // USE_PANGO
diff --git a/src/drivers/PostScript/Fl_PostScript_image.cxx b/src/drivers/PostScript/Fl_PostScript_image.cxx
index 9b5fe1668..ebb91cf03 100644
--- a/src/drivers/PostScript/Fl_PostScript_image.cxx
+++ b/src/drivers/PostScript/Fl_PostScript_image.cxx
@@ -26,7 +26,7 @@
#include <string.h> // memcpy()
#if USE_PANGO
-# include <cairo/cairo.h>
+# include <cairo.h>
#else
# include <stdio.h> // fprintf()
#endif
diff --git a/src/drivers/Quartz/Fl_Font.H b/src/drivers/Quartz/Fl_Font.H
deleted file mode 100644
index f1a710eea..000000000
--- a/src/drivers/Quartz/Fl_Font.H
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Font definitions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// Two internal fltk data structures:
-//
-// Fl_Fontdesc: an entry into the fl_font() table. There is one of these
-// for each fltk font number.
-//
-#ifndef FL_FONT_
-#define FL_FONT_
-
-#include <config.h>
-#include "Fl_Quartz_Graphics_Driver.H"
-#include "../../Fl_Scalable_Graphics_Driver.H" // Fl_Font_Descriptor
-#include <ApplicationServices/ApplicationServices.h>
-
-class Fl_Quartz_Font_Descriptor : public Fl_Font_Descriptor {
-public:
- Fl_Quartz_Font_Descriptor(const char* fontname, Fl_Fontsize size);
- virtual FL_EXPORT ~Fl_Quartz_Font_Descriptor();
- CTFontRef fontref;
- // the unicode span is divided in 512 blocks of 128 characters
- float *width[512]; // array of arrays of character widths
- short q_width;
-};
-
-extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
-
-#endif
diff --git a/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H b/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H
deleted file mode 100644
index 8ef586624..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Definition of Apple Quartz graphics driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2016 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#ifndef Fl_Quartz_Copy_Surface_Driver_H
-#define Fl_Quartz_Copy_Surface_Driver_H
-
-#include <FL/Fl_Copy_Surface.H>
-#include <FL/platform.H>
-
-class Fl_Quartz_Copy_Surface_Driver : public Fl_Copy_Surface_Driver {
- friend class Fl_Copy_Surface_Driver;
-protected:
- CFMutableDataRef pdfdata;
- CGContextRef gc;
- static size_t MyPutBytes(void* info, const void* buffer, size_t count);
- Fl_Quartz_Copy_Surface_Driver(int w, int h);
- // implemented in Fl_cocoa.mm because uses Objective-c
- ~Fl_Quartz_Copy_Surface_Driver();
- void set_current() FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate() FL_OVERRIDE;
-};
-
-#endif /* Fl_Quartz_Copy_Surface_Driver_H */
diff --git a/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
deleted file mode 100644
index 77ecdaa0a..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2019 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/Fl_Copy_Surface.H>
-#include <FL/platform.H>
-#include "Fl_Quartz_Graphics_Driver.H"
-#include "Fl_Quartz_Copy_Surface_Driver.H"
-#include "../Cocoa/Fl_Cocoa_Window_Driver.H"
-
-
-Fl_Quartz_Copy_Surface_Driver::Fl_Quartz_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
- driver(new Fl_Quartz_Printer_Graphics_Driver);
- pdfdata = CFDataCreateMutable(NULL, 0);
- CGDataConsumerRef myconsumer;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
- if (&CGDataConsumerCreateWithCFData != NULL) {
- myconsumer = CGDataConsumerCreateWithCFData(pdfdata); // 10.4
- }
- else
-#endif
- {
- static CGDataConsumerCallbacks callbacks = { Fl_Quartz_Copy_Surface_Driver::MyPutBytes, NULL };
- myconsumer = CGDataConsumerCreate((void*) pdfdata, &callbacks);
- }
- float d = fl_graphics_driver->scale();
- CGRect bounds = CGRectMake(0, 0, w * d, h * d);
- gc = CGPDFContextCreate(myconsumer, &bounds, NULL);
- CGDataConsumerRelease(myconsumer);
- if (gc) {
- CGContextBeginPage(gc, &bounds);
- CGContextScaleCTM(gc, d, -d);
- CGContextTranslateCTM(gc, 0.5, -h + 0.5);
- CGContextSaveGState(gc);
- }
-}
-
-void Fl_Quartz_Copy_Surface_Driver::set_current() {
- driver()->gc(gc);
- fl_window = (FLWindow*)1;
- Fl_Surface_Device::set_current();
-}
-
-size_t Fl_Quartz_Copy_Surface_Driver::MyPutBytes(void* info, const void* buffer, size_t count)
-{
- CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count);
- return count;
-}
-
-void Fl_Quartz_Copy_Surface_Driver::translate(int x, int y) {
- CGContextRestoreGState(gc);
- CGContextSaveGState(gc);
- CGContextTranslateCTM(gc, x, y);
- CGContextSaveGState(gc);
-}
-
-void Fl_Quartz_Copy_Surface_Driver::untranslate() {
- CGContextRestoreGState(gc);
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
deleted file mode 100644
index 0afc7369e..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
+++ /dev/null
@@ -1,149 +0,0 @@
-//
-// Definition of Apple Quartz graphics driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Quartz_Graphics_Driver.H
- \brief Definition of Apple Quartz graphics driver.
- */
-
-#ifndef FL_QUARTZ_GRAPHICS_DRIVER_H
-#define FL_QUARTZ_GRAPHICS_DRIVER_H
-
-#include <FL/platform.H>
-#include <FL/Fl_Graphics_Driver.H>
-#include <ApplicationServices/ApplicationServices.h>
-
-struct Fl_Fontdesc;
-class Fl_Quartz_Font_Descriptor;
-
-/**
- \brief The Mac OS X-specific graphics class.
-
- This class is implemented only on the Mac OS X platform.
- */
-class Fl_Quartz_Graphics_Driver : public Fl_Graphics_Driver {
- friend class Fl_Cocoa_Printer_Driver;
- friend class Fl_Quartz_Font_Descriptor;
-protected:
- CGContextRef gc_;
- bool high_resolution_;
- float quartz_line_width_;
- CGLineCap quartz_line_cap_;
- CGLineJoin quartz_line_join_;
- CGFloat *quartz_line_pattern;
- int quartz_line_pattern_size;
- void cache_size(Fl_Image* img, int &width, int &height) FL_OVERRIDE;
-public:
- Fl_Quartz_Graphics_Driver();
- int has_feature(driver_feature mask) FL_OVERRIDE { return mask & NATIVE; }
- void gc(void *ctxt) FL_OVERRIDE { gc_ = (CGContextRef)ctxt; global_gc(); }
- void *gc() FL_OVERRIDE {return gc_;}
- char can_do_alpha_blending() FL_OVERRIDE;
-
- // --- bitmap stuff
- static CGImageRef create_bitmask(int w, int h, const uchar *array); // NOT virtual
- void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE;
- void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_bitmap(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE;
- void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) FL_OVERRIDE;
- void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) FL_OVERRIDE;
- void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) FL_OVERRIDE;
- void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) FL_OVERRIDE;
- void cache(Fl_Pixmap *img) FL_OVERRIDE;
- void cache(Fl_Bitmap *img) FL_OVERRIDE;
- void cache(Fl_RGB_Image *img) FL_OVERRIDE;
- void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE;
- void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) FL_OVERRIDE;
- void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh);
- static CGRect fl_cgrectmake_cocoa(int x, int y, int w, int h);
- void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) FL_OVERRIDE;
- Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE;
- void XDestroyRegion(Fl_Region r) FL_OVERRIDE;
- void high_resolution(bool b) { high_resolution_ = b; }
-protected:
- void point(int x, int y) FL_OVERRIDE;
- void rect(int x, int y, int w, int h) FL_OVERRIDE;
- void focus_rect(int x, int y, int w, int h) FL_OVERRIDE;
- void rectf(int x, int y, int w, int h) FL_OVERRIDE;
- void line(int x, int y, int x1, int y1) FL_OVERRIDE;
- void line(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void xyline(int x, int y, int x1) FL_OVERRIDE;
- void xyline(int x, int y, int x1, int y2) FL_OVERRIDE;
- void xyline(int x, int y, int x1, int y2, int x3) FL_OVERRIDE;
- void yxline(int x, int y, int y1) FL_OVERRIDE;
- void yxline(int x, int y, int y1, int x2) FL_OVERRIDE;
- void yxline(int x, int y, int y1, int x2, int y3) FL_OVERRIDE;
- void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE;
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE;
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE;
- // --- clipping
- void push_clip(int x, int y, int w, int h) FL_OVERRIDE;
- int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE;
- int not_clipped(int x, int y, int w, int h) FL_OVERRIDE;
- void restore_clip() FL_OVERRIDE;
- void end_points() FL_OVERRIDE;
- void end_line() FL_OVERRIDE;
- void end_polygon() FL_OVERRIDE;
- void end_complex_polygon() FL_OVERRIDE;
- void circle(double x, double y, double r) FL_OVERRIDE;
- void arc(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE;
- void pie(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE;
- void line_style(int style, int width=0, char* dashes=0) FL_OVERRIDE;
- void color(Fl_Color c) FL_OVERRIDE;
- Fl_Color color() FL_OVERRIDE { return color_; }
- void color(uchar r, uchar g, uchar b) FL_OVERRIDE;
- void draw(const char *str, int n, int x, int y) FL_OVERRIDE;
- void draw(const char *str, int n, float x, float y) FL_OVERRIDE;
- void draw(int angle, const char *str, int n, int x, int y) FL_OVERRIDE;
- double width(const UniChar* txt, int n);
- void rtl_draw(const char *str, int n, int x, int y) FL_OVERRIDE;
- void font(Fl_Font face, Fl_Fontsize fsize) FL_OVERRIDE;
- double width(const char *str, int n) FL_OVERRIDE;
- double width(unsigned int c) FL_OVERRIDE;
- int height() FL_OVERRIDE;
- int descent() FL_OVERRIDE;
- virtual bool high_resolution() { return high_resolution_; }
- void global_gc() FL_OVERRIDE;
- void quartz_restore_line_style();
- inline Fl_Quartz_Font_Descriptor *valid_font_descriptor();
- const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE;
- int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE;
- const char *font_name(int num) FL_OVERRIDE;
- void font_name(int num, const char *name) FL_OVERRIDE;
- Fl_Fontdesc* calc_fl_fonts(void) FL_OVERRIDE;
-
- void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE;
- Fl_Font set_fonts(const char* xstarname) FL_OVERRIDE;
- void set_fontname_in_fontdesc(Fl_Fontdesc *f);
- void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE;
-
- void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
- void overlay_rect(int x, int y, int w , int h) FL_OVERRIDE;
- float override_scale() FL_OVERRIDE;
- void restore_scale(float) FL_OVERRIDE;
- void antialias(int state) FL_OVERRIDE;
- int antialias() FL_OVERRIDE;
-};
-
-class Fl_Quartz_Printer_Graphics_Driver : public Fl_Quartz_Graphics_Driver {
-public:
- int has_feature(driver_feature mask) FL_OVERRIDE { return mask & (NATIVE | PRINTER); }
-};
-
-#endif // FL_QUARTZ_GRAPHICS_DRIVER_H
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
deleted file mode 100644
index 21c5eda4c..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
+++ /dev/null
@@ -1,133 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#include "Fl_Quartz_Graphics_Driver.H"
-#include "../Darwin/Fl_Darwin_System_Driver.H"
-#include "../Cocoa/Fl_Cocoa_Screen_Driver.H"
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-#include <FL/Fl_Image_Surface.H>
-
-
-void Fl_Quartz_Graphics_Driver::antialias(int state) {
-}
-
-int Fl_Quartz_Graphics_Driver::antialias() {
- return 1;
-}
-
-Fl_Quartz_Graphics_Driver::Fl_Quartz_Graphics_Driver() : Fl_Graphics_Driver(), gc_(NULL) {
- quartz_line_width_ = 1.f;
- quartz_line_cap_ = kCGLineCapButt;
- quartz_line_join_ = kCGLineJoinMiter;
- quartz_line_pattern = 0;
- quartz_line_pattern_size = 0;
- high_resolution_ = false;
-}
-
-char Fl_Quartz_Graphics_Driver::can_do_alpha_blending() {
- return 1;
-}
-
-static void bmProviderRelease (void *src, const void *data, size_t size) {
- CFIndex count = CFGetRetainCount(src);
- CFRelease(src);
- if(count == 1) free((void*)data);
-}
-
-/* Reference to the current CGContext
- For back-compatibility only. The preferred procedure to get this reference is
- Fl_Surface_Device::surface()->driver()->gc().
- */
-CGContextRef fl_gc = 0;
-
-void Fl_Quartz_Graphics_Driver::global_gc()
-{
- fl_gc = (CGContextRef)gc();
-}
-
-
-CGContextRef fl_mac_gc() { return fl_gc; }
-
-
-void Fl_Quartz_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) {
- // draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface
- CGContextRef src = (CGContextRef)osrc;
- int sw = (int)CGBitmapContextGetWidth(src);
- int sh = (int)CGBitmapContextGetHeight(src);
- CGImageRef img;
- img = CGBitmapContextCreateImage(src); // requires 10.4
- CGAffineTransform at = CGContextGetCTM(src);
- float s = at.a;
- draw_CGImage(img, x, y, w, h, srcx, srcy, sw/s, sh/s);
- CGImageRelease(img);
-}
-
-// so a CGRect matches exactly what is denoted x,y,w,h for clipping purposes
-CGRect Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(int x, int y, int w, int h) {
- return CGRectMake(x - 0.5, y - 0.5, w, h);
-}
-
-void Fl_Quartz_Graphics_Driver::add_rectangle_to_region(Fl_Region r_, int X, int Y, int W, int H) {
- struct flCocoaRegion *r = (struct flCocoaRegion*)r_;
- CGRect arg = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(X, Y, W, H);
- int j; // don't add a rectangle totally inside the Fl_Region
- for(j = 0; j < r->count; j++) {
- if(CGRectContainsRect(r->rects[j], arg)) break;
- }
- if( j >= r->count) {
- r->rects = (CGRect*)realloc(r->rects, (++(r->count)) * sizeof(CGRect));
- r->rects[r->count - 1] = arg;
- }
-}
-
-Fl_Region Fl_Quartz_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
- struct flCocoaRegion* R = (struct flCocoaRegion*)malloc(sizeof(struct flCocoaRegion));
- R->count = 1;
- R->rects = (CGRect *)malloc(sizeof(CGRect));
- *(R->rects) = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(x, y, w, h);
- return R;
-}
-
-void Fl_Quartz_Graphics_Driver::XDestroyRegion(Fl_Region r_) {
- if (r_) {
- struct flCocoaRegion *r = (struct flCocoaRegion*)r_;
- free(r->rects);
- free(r);
- }
-}
-
-void Fl_Quartz_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) {
- width *= 2 * scale();
- height *= 2 * scale();
-}
-
-float Fl_Quartz_Graphics_Driver::override_scale() {
- float s = scale();
- if (s != 1.f && Fl_Display_Device::display_device()->is_current()) {
- CGContextScaleCTM(gc_, 1./s, 1./s);
- Fl_Graphics_Driver::scale(1);
- }
- return s;
-}
-
-void Fl_Quartz_Graphics_Driver::restore_scale(float s) {
- if (s != 1.f && Fl_Display_Device::display_device()->is_current()) {
- CGContextScaleCTM(gc_, s, s);
- Fl_Graphics_Driver::scale(s);
- }
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx
deleted file mode 100644
index 4163de685..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Quartz_Graphics_Driver.H"
-#include <FL/platform.H>
-
-/**
- \file quartz_arci.cxx
- \brief Utility functions for drawing circles using integers
-*/
-
-void Fl_Quartz_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
- if (w <= 0 || h <= 0) return;
- a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI;
- float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f;
- CGContextSetShouldAntialias(gc_, true);
- if (w!=h) {
- CGContextSaveGState(gc_);
- CGContextTranslateCTM(gc_, cx, cy);
- CGContextScaleCTM(gc_, w-1.0f, h-1.0f);
- CGContextAddArc(gc_, 0, 0, 0.5, a1, a2, 1);
- CGContextRestoreGState(gc_);
- } else {
- float r = (w+h)*0.25f-0.5f;
- CGContextAddArc(gc_, cx, cy, r, a1, a2, 1);
- }
- CGContextStrokePath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
- if (w <= 0 || h <= 0) return;
- a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI;
- float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f;
- CGContextSetShouldAntialias(gc_, true);
- if (w!=h) {
- CGContextSaveGState(gc_);
- CGContextTranslateCTM(gc_, cx, cy);
- CGContextScaleCTM(gc_, w, h);
- CGContextAddArc(gc_, 0, 0, 0.5, a1, a2, 1);
- CGContextAddLineToPoint(gc_, 0, 0);
- CGContextClosePath(gc_);
- CGContextRestoreGState(gc_);
- } else {
- float r = (w+h)*0.25f;
- CGContextAddArc(gc_, cx, cy, r, a1, a2, 1);
- CGContextAddLineToPoint(gc_, cx, cy);
- CGContextClosePath(gc_);
- }
- CGContextFillPath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx
deleted file mode 100644
index 9d31f8573..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// MacOS color functions for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// The fltk "colormap". This allows ui colors to be stored in 8-bit
-// locations, and provides a level of indirection so that global color
-// changes can be made. Not to be confused with the X colormap, which
-// I try to hide completely.
-
-// matt: Neither Quartz nor Quickdraw support colormaps in this implementation
-// matt: Quartz support done
-
-#include "Fl_Quartz_Graphics_Driver.H"
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-
-extern unsigned fl_cmap[256]; // defined in fl_color.cxx
-
-void Fl_Quartz_Graphics_Driver::color(Fl_Color i) {
- Fl_Graphics_Driver::color(i);
- uchar r, g, b;
- float fa = 1.0f;
- if (i & 0xFFFFFF00) {
- // translate rgb colors into color index
- r = i>>24;
- g = i>>16;
- b = i>> 8;
- } else {
- // translate index into rgb:
- unsigned c = fl_cmap[i];
- c = c ^ 0x000000ff; // trick to restore the color's correct alpha value
- r = c>>24;
- g = c>>16;
- b = c>> 8;
- uchar a = c & 0xff;
- //printf("i=%d rgb=%u,%u,%u a=%u\n",i,r,g,b,a);
- fa = a/255.0f;
- }
- if (!gc_) return; // no context yet? We will assign the color later.
- float fr = r/255.0f;
- float fg = g/255.0f;
- float fb = b/255.0f;
- CGContextSetRGBFillColor(gc_, fr, fg, fb, fa);
- CGContextSetRGBStrokeColor(gc_, fr, fg, fb, fa);
-}
-
-void Fl_Quartz_Graphics_Driver::color(uchar r, uchar g, uchar b) {
- Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
- float fr = r/255.0f;
- float fg = g/255.0f;
- float fb = b/255.0f;
- if (!gc_) return; // no context yet? We will assign the color later.
- CGContextSetRGBFillColor(gc_, fr, fg, fb, 1.0f);
- CGContextSetRGBStrokeColor(gc_, fr, fg, fb, 1.0f);
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx
deleted file mode 100644
index d373c1768..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx
+++ /dev/null
@@ -1,561 +0,0 @@
-//
-// MacOS font selection routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Quartz_Graphics_Driver.H"
-#include "Fl_Font.H"
-#include <math.h>
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/fl_utf8.h> // for fl_utf8toUtf16()
-#include <FL/fl_string_functions.h> // fl_strdup()
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
-const NSUInteger kCTFontOrientationHorizontal = kCTFontHorizontalOrientation;
-#endif
-
-Fl_Fontdesc* fl_fonts = NULL;
-
-static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
-
-static int fl_free_font = FL_FREE_FONT;
-
-
-static CFMutableDictionaryRef attributes = NULL;
-
-static Fl_Fontdesc built_in_table_PS[] = { // PostScript font names preferred when Mac OS ≥ 10.5
- {"ArialMT"},
- {"Arial-BoldMT"},
- {"Arial-ItalicMT"},
- {"Arial-BoldItalicMT"},
- {"Courier"},
- {"Courier-Bold"},
- {"Courier-Oblique"},
- {"Courier-BoldOblique"},
- {"TimesNewRomanPSMT"},
- {"TimesNewRomanPS-BoldMT"},
- {"TimesNewRomanPS-ItalicMT"},
- {"TimesNewRomanPS-BoldItalicMT"},
- {"Symbol"},
- {"Monaco"},
- {"AndaleMono"}, // there is no bold Monaco font on standard Mac
- {"ZapfDingbatsITC"}
-};
-
-
-// Bug: older versions calculated the value for *ap as a side effect of
-// making the name, and then forgot about it. To avoid having to change
-// the header files I decided to store this value in the last character
-// of the font name array.
-#define ENDOFBUFFER sizeof(fl_fonts->fontname)-1
-
-// turn a stored font name into a pretty name:
-const char* Fl_Quartz_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
- if (!fl_fonts) fl_fonts = calc_fl_fonts();
- Fl_Fontdesc *f = fl_fonts + fnum;
- if (!f->fontname[0]) {
- this->set_fontname_in_fontdesc(f);
- const char* thisFont = f->name;
- if (!thisFont || !*thisFont) {if (ap) *ap = 0; return "";}
- int type = 0;
- if (strstr(f->name, "Bold")) type |= FL_BOLD;
- if (strstr(f->name, "Italic") || strstr(f->name, "Oblique")) type |= FL_ITALIC;
- f->fontname[ENDOFBUFFER] = (char)type;
- }
- if (ap) *ap = f->fontname[ENDOFBUFFER];
- return f->fontname;
-}
-
-
-int Fl_Quartz_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
- static int array[128];
- if (!fl_fonts) fl_fonts = calc_fl_fonts();
- Fl_Fontdesc *s = fl_fonts+fnum;
- if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
- int cnt = 0;
-
- // ATS supports all font size
- array[0] = 0;
- sizep = array;
- cnt = 1;
-
- return cnt;
-}
-
-Fl_Quartz_Font_Descriptor::Fl_Quartz_Font_Descriptor(const char* name, Fl_Fontsize Size) : Fl_Font_Descriptor(name, Size) {
- fontref = NULL;
- Fl_Quartz_Graphics_Driver *driver = (Fl_Quartz_Graphics_Driver*)&Fl_Graphics_Driver::default_driver();
- driver->descriptor_init(name, size, this);
-}
-
-
-Fl_Quartz_Font_Descriptor::~Fl_Quartz_Font_Descriptor() {
-/*
-#if HAVE_GL
- // ++ todo: remove OpenGL font allocations
-// Delete list created by gl_draw(). This is not done by this code
-// as it will link in GL unnecessarily. There should be some kind
-// of "free" routine pointer, or a subclass?
-#endif
- */
- if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
- if (fontref) {
- CFRelease(fontref);
- for (unsigned i = 0; i < sizeof(width)/sizeof(float*); i++) {
- if (width[i]) free(width[i]);
- }
- }
-}
-
-
-static UniChar *utfWbuf = 0;
-static unsigned utfWlen = 0;
-
-static UniChar *mac_Utf8_to_Utf16(const char *txt, int len, int *new_len)
-{
- unsigned wlen = fl_utf8toUtf16(txt, len, (unsigned short*)utfWbuf, utfWlen);
- if (wlen >= utfWlen)
- {
- utfWlen = wlen + 100;
- if (utfWbuf) free(utfWbuf);
- utfWbuf = (UniChar*)malloc((utfWlen)*sizeof(UniChar));
- wlen = fl_utf8toUtf16(txt, len, (unsigned short*)utfWbuf, utfWlen);
- }
- *new_len = wlen;
- return utfWbuf;
-}
-
-
-static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) {
- if (!fl_fonts) fl_fonts = Fl_Graphics_Driver::default_driver().calc_fl_fonts();
- Fl_Fontdesc* s = fl_fonts+fnum;
- if (!s->name) s = fl_fonts; // use 0 if fnum undefined
- Fl_Font_Descriptor* f;
- for (f = s->first; f; f = f->next)
- if (f->size == size) return f;
- f = new Fl_Quartz_Font_Descriptor(s->name, size);
- f->next = s->first;
- s->first = f;
- return f;
-}
-
-
-void Fl_Quartz_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
- if (fnum == -1) {
- Fl_Graphics_Driver::font(0, 0);
- return;
- }
- Fl_Graphics_Driver::font(fnum, size);
- font_descriptor( find(fnum, size) );
-}
-
-Fl_Quartz_Font_Descriptor *Fl_Quartz_Graphics_Driver::valid_font_descriptor() {
- // avoid a crash if no font has been selected by user yet
- if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
- return (Fl_Quartz_Font_Descriptor*)font_descriptor();
-}
-
-int Fl_Quartz_Graphics_Driver::height() {
- Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
- return fl_fontsize->ascent + fl_fontsize->descent;
-}
-
-int Fl_Quartz_Graphics_Driver::descent() {
- Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
- return fl_fontsize->descent + 1;
-}
-
-void Fl_Quartz_Graphics_Driver::draw(const char* str, int n, int x, int y) {
- draw(str, n, (float)x, y+0.5f);
-}
-
-void Fl_Quartz_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
- CGContextSaveGState(gc_);
- CGContextTranslateCTM(gc_, x, y);
- CGContextRotateCTM(gc_, - angle*(M_PI/180) );
- draw(str, n, 0, 0);
- CGContextRestoreGState(gc_);
-}
-
-void Fl_Quartz_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
- int dx, dy, w, h;
- text_extents(c, n, dx, dy, w, h);
- draw(c, n, x - w - dx, y);
-}
-
-double Fl_Quartz_Graphics_Driver::width(const char* txt, int n) {
- if (n == 0) return 0;
- int len1 = fl_utf8len1(*txt);
- if (len1 > 0 && n > len1) { // a text with several codepoints: compute its typographical width
- CFStringRef str = CFStringCreateWithBytes(NULL, (const UInt8*)txt, n, kCFStringEncodingUTF8, false);
- if (str) {
- CFDictionarySetValue(attributes, kCTFontAttributeName, valid_font_descriptor()->fontref);
- CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str, attributes);
- CFRelease(str);
- CTLineRef ctline = CTLineCreateWithAttributedString(mastr);
- CFRelease(mastr);
- double d = CTLineGetTypographicBounds(ctline, NULL, NULL, NULL);
- CFRelease(ctline);
- return d;
- }
- }
- int wc_len = n;
- UniChar *uniStr = mac_Utf8_to_Utf16(txt, n, &wc_len);
- return width(uniStr, wc_len);
-}
-
-double Fl_Quartz_Graphics_Driver::width(unsigned int wc) {
- UniChar utf16[3];
- int l = 1;
- if (wc <= 0xFFFF) {
- *utf16 = wc;
- }
- else {
- l = (int)fl_ucs_to_Utf16(wc, utf16, 3);
- }
- return width(utf16, l);
-}
-
-void Fl_Quartz_Graphics_Driver::set_fontname_in_fontdesc(Fl_Fontdesc *f) {
- CFStringRef cfname = CFStringCreateWithCString(NULL, f->name, kCFStringEncodingUTF8);
- CTFontRef ctfont = cfname ? CTFontCreateWithName(cfname, 0, NULL) : NULL;
- if (cfname) { CFRelease(cfname); cfname = NULL; }
- if (ctfont) {
- cfname = CTFontCopyFullName(ctfont);
- CFRelease(ctfont);
- if (cfname) {
- CFStringGetCString(cfname, f->fontname, ENDOFBUFFER, kCFStringEncodingUTF8);
- CFRelease(cfname);
- }
- }
- if (!cfname) strlcpy(f->fontname, f->name, ENDOFBUFFER);
-}
-
-const char *Fl_Quartz_Graphics_Driver::font_name(int num) {
- if (!fl_fonts) fl_fonts = calc_fl_fonts();
- return fl_fonts[num].name;
-}
-
-void Fl_Quartz_Graphics_Driver::font_name(int num, const char *name) {
- Fl_Fontdesc *s = fl_fonts + num;
- if (s->name) {
- if (!strcmp(s->name, name)) {s->name = name; return;}
- for (Fl_Font_Descriptor* f = s->first; f;) {
- Fl_Font_Descriptor* n = f->next; delete f; f = n;
- }
- s->first = 0;
- }
- s->name = name;
- s->fontname[0] = 0;
- s->first = 0;
-}
-
-
-Fl_Fontdesc* Fl_Quartz_Graphics_Driver::calc_fl_fonts(void)
-{
- return built_in_table_PS;
-}
-
-
-void Fl_Quartz_Graphics_Driver::descriptor_init(const char* name,
- Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d)
-{
- CFStringRef str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
- d->fontref = CTFontCreateWithName(str, size, NULL);
- CGGlyph glyph[2];
- const UniChar A[2]={'W','.'};
- CTFontGetGlyphsForCharacters(d->fontref, A, glyph, 2);
- CGSize advances[2];
- double w;
- CTFontGetAdvancesForGlyphs(d->fontref, kCTFontOrientationHorizontal, glyph, advances, 2);
- w = advances[0].width;
- if ( fabs(advances[0].width - advances[1].width) < 1E-2 ) {//this is a fixed-width font
- // slightly rescale fixed-width fonts so the character width has an integral value
- CFRelease(d->fontref);
- CGFloat fsize = size / ( w/floor(w + 0.5) );
- d->fontref = CTFontCreateWithName(str, fsize, NULL);
- w = CTFontGetAdvancesForGlyphs(d->fontref, kCTFontOrientationHorizontal, glyph, NULL, 1);
- }
- CFRelease(str);
- d->ascent = (short)(CTFontGetAscent(d->fontref) + 0.5);
- d->descent = (short)(CTFontGetDescent(d->fontref) + 0.5);
- d->q_width = w + 0.5;
- for (unsigned i = 0; i < sizeof(d->width)/sizeof(float*); i++) d->width[i] = NULL;
- if (!attributes) {
- static CFNumberRef zero_ref;
- float zero = 0.;
- zero_ref = CFNumberCreate(NULL, kCFNumberFloat32Type, &zero);
- // deactivate kerning for all fonts, so that string width = sum of character widths
- // which allows fast fl_width() implementation.
- attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
- 3,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue (attributes, kCTKernAttributeName, zero_ref);
- }
- if (d->ascent == 0) { // this may happen with some third party fonts
- CFDictionarySetValue (attributes, kCTFontAttributeName, d->fontref);
- CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("Wj"), attributes);
- CTLineRef ctline = CTLineCreateWithAttributedString(mastr);
- CFRelease(mastr);
- CGFloat fascent, fdescent;
- CTLineGetTypographicBounds(ctline, &fascent, &fdescent, NULL);
- CFRelease(ctline);
- d->ascent = (short)(fascent + 0.5);
- d->descent = (short)(fdescent + 0.5);
- }
-}
-
-// returns width of a pair of UniChar's in the surrogate range
-static CGFloat surrogate_width(const UniChar *txt, Fl_Quartz_Font_Descriptor *fl_fontsize)
-{
- CTFontRef font2 = fl_fontsize->fontref;
- bool must_release = false;
- CGGlyph glyphs[2];
- bool b = CTFontGetGlyphsForCharacters(font2, txt, glyphs, 2);
- CGSize a;
- if(!b) { // the current font doesn't contain this char
- CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, txt, 2, kCFAllocatorNull);
- // find a font that contains it
- font2 = CTFontCreateForString(font2, str, CFRangeMake(0,2));
- must_release = true;
- CFRelease(str);
- b = CTFontGetGlyphsForCharacters(font2, txt, glyphs, 2);
- }
- if (b) CTFontGetAdvancesForGlyphs(font2, kCTFontOrientationHorizontal, glyphs, &a, 1);
- else a.width = fl_fontsize->q_width;
- if(must_release) CFRelease(font2);
- return a.width;
-}
-
-static CGFloat variation_selector_width(CFStringRef str16, Fl_Quartz_Font_Descriptor *fl_fontsize)
-{
- CGFloat retval;
- CFDictionarySetValue(attributes, kCTFontAttributeName, fl_fontsize->fontref);
- CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes);
- CTLineRef ctline = CTLineCreateWithAttributedString(mastr);
- CFRelease(mastr);
- retval = CTLineGetOffsetForStringIndex(ctline, 2, NULL);
- CFRelease(ctline);
- return retval;
-}
-
-double Fl_Quartz_Graphics_Driver::width(const UniChar* txt, int n)
-{
- double retval = 0;
- UniChar uni;
- int i;
- Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
- for (i = 0; i < n; i++) { // loop over txt
- uni = txt[i];
- if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range
- retval += surrogate_width(&txt[i], fl_fontsize);
- i++; // because a pair of UniChar's represent a single character
- continue;
- }
- if (i+1 < n && txt[i+1] >= 0xFE00 && txt[i+1] <= 0xFE0F) { // handles variation selectors
- CFStringRef substr = CFStringCreateWithCharacters(NULL, txt + i, 2);
- retval += variation_selector_width(substr, fl_fontsize);
- CFRelease(substr);
- i++;
- continue;
- }
- const int block = 0x10000 / (sizeof(fl_fontsize->width)/sizeof(float*)); // block size
- // r: index of the character block containing uni
- unsigned int r = uni >> 7; // change 7 if sizeof(width) is changed
- if (!fl_fontsize->width[r]) { // this character block has not been hit yet
- //fprintf(stderr,"r=%d size=%d name=%s\n",r,fl_fontsize->size,fl_fonts[fl_font()].name);
- // allocate memory to hold width of each character in the block
- fl_fontsize->width[r] = (float*) malloc(sizeof(float) * block);
- UniChar ii = r * block;
- CGSize advance_size;
- CGGlyph glyph;
- for (int j = 0; j < block; j++) { // loop over the block
- // ii spans all characters of this block
- bool b = CTFontGetGlyphsForCharacters(fl_fontsize->fontref, &ii, &glyph, 1);
- if (b)
- CTFontGetAdvancesForGlyphs(fl_fontsize->fontref, kCTFontOrientationHorizontal, &glyph, &advance_size, 1);
- else
- advance_size.width = -1e9; // calculate this later
- // the width of one character of this block of characters
- fl_fontsize->width[r][j] = advance_size.width;
- ii++;
- }
- }
- // sum the widths of all characters of txt
- double wdt = fl_fontsize->width[r][uni & (block-1)];
- if (wdt == -1e9) {
- CGSize advance_size;
- CGGlyph glyph;
- CTFontRef font2 = fl_fontsize->fontref;
- bool must_release = false;
- bool b = CTFontGetGlyphsForCharacters(font2, &uni, &glyph, 1);
- if (!b) { // the current font doesn't contain this char
- CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, &uni, 1, kCFAllocatorNull);
- // find a font that contains it
- font2 = CTFontCreateForString(font2, str, CFRangeMake(0,1));
- must_release = true;
- CFRelease(str);
- b = CTFontGetGlyphsForCharacters(font2, &uni, &glyph, 1);
- }
- if (b) CTFontGetAdvancesForGlyphs(font2, kCTFontOrientationHorizontal, &glyph, &advance_size, 1);
- else advance_size.width = 0.;
- // the width of the 'uni' character
- wdt = fl_fontsize->width[r][uni & (block-1)] = advance_size.width;
- if (must_release) CFRelease(font2);
- }
- retval += wdt;
- }
- return retval;
-}
-
-
-// text extent calculation
-void Fl_Quartz_Graphics_Driver::text_extents(const char *str8, int n,
- int &dx, int &dy, int &w, int &h) {
- Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
- UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n);
- CFStringRef str16 = CFStringCreateWithCharactersNoCopy(NULL, txt, n, kCFAllocatorNull);
- CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref);
- CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes);
- CFRelease(str16);
- CTLineRef ctline = CTLineCreateWithAttributedString(mastr);
- CFRelease(mastr);
- CGContextSetTextPosition(gc_, 0, 0);
- CGContextSetShouldAntialias(gc_, true);
- CGRect rect = CTLineGetImageBounds(ctline, gc_);
- CGContextSetShouldAntialias(gc_, false);
- CFRelease(ctline);
- dx = floor(rect.origin.x + 0.5);
- dy = floor(- rect.origin.y - rect.size.height + 0.5);
- w = rect.size.width + 0.5;
- h = rect.size.height + 0.5;
-}
-
-
-static CGColorRef flcolortocgcolor(Fl_Color i)
-{
- uchar r, g, b;
- Fl::get_color(i, r, g, b);
- CGFloat components[4] = {r/255.0f, g/255.0f, b/255.0f, 1.};
- static CGColorSpaceRef cspace = NULL;
- if (cspace == NULL) {
- cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
- }
- return CGColorCreate(cspace, components);
-}
-
-void Fl_Quartz_Graphics_Driver::draw(const char *str, int n, float x, float y)
-{
- Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
- // convert to UTF-16 first
- UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n);
- CGContextRef gc = (CGContextRef)this->gc();
- CFMutableStringRef str16 = CFStringCreateMutableWithExternalCharactersNoCopy(NULL, uniStr, n, n, kCFAllocatorNull);
- if (str16 == NULL) return; // shd not happen
- CGColorRef color = flcolortocgcolor(this->color());
- CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref);
- CFDictionarySetValue (attributes, kCTForegroundColorAttributeName, color);
- CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes);
- CFRelease(str16);
- CFRelease(color);
- CTLineRef ctline = CTLineCreateWithAttributedString(mastr);
- CFRelease(mastr);
- CGContextSetTextMatrix(gc, font_mx);
- CGContextSetTextPosition(gc, x, y);
- CGContextSetShouldAntialias(gc, true);
- CTLineDraw(ctline, gc);
- CGContextSetShouldAntialias(gc, false);
- CFRelease(ctline);
-}
-
-// Skip over bold/italic/oblique qualifiers part of PostScript font names
-// Example:
-// input: '-Regular_Light-Condensed'
-// return: '_Light-Condensed'
-//
-static char *skip(char *p, int& derived)
-{
- // 0 5 10
- // | | |
- if (strncmp(p, "-BoldItalic", 11) == 0) { p += 11; derived = 3; }
- else if (strncmp(p, "-BoldOblique", 12) == 0) { p += 12; derived = 3; }
- else if (strncmp(p, "-Bold", 5) == 0) { p += 5; derived = 1; }
- else if (strncmp(p, "-Italic", 7) == 0) { p += 7; derived = 2; }
- else if (strncmp(p, "-Oblique", 8) == 0) { p += 8; derived = 2; }
- else if (strncmp(p, "-Regular", 8) == 0) { p += 8; }
- else if (strncmp(p, "-Roman", 6) == 0) { p += 6; }
- return p;
-}
-
-static int name_compare(const void *a, const void *b)
-{
- /* Compare PostScript font names.
- First compare font family names ignoring bold, italic and oblique qualifiers.
- When families are identical, order them according to regular, bold, italic, bolditalic.
- */
- char *n1 = *(char**)a;
- char *n2 = *(char**)b;
- int derived1 = 0;
- int derived2 = 0;
- while (true) {
- if (*n1 == '-') n1 = skip(n1, derived1);
- if (*n2 == '-') n2 = skip(n2, derived2);
- if (*n1 < *n2) return -1;
- if (*n1 > *n2) return +1;
- if (*n1 == 0) {
- return derived1 - derived2;
- }
- n1++; n2++;
- }
-}
-
-Fl_Font Fl_Quartz_Graphics_Driver::set_fonts(const char* xstarname)
-{
-#pragma unused ( xstarname )
- if (fl_free_font > FL_FREE_FONT) return (Fl_Font)fl_free_font; // if already called
-
- int value[1] = {1};
- CFDictionaryRef dict = CFDictionaryCreate(NULL,
- (const void **)kCTFontCollectionRemoveDuplicatesOption,
- (const void **)&value, 1, NULL, NULL);
- CTFontCollectionRef fcref = CTFontCollectionCreateFromAvailableFonts(dict);
- CFRelease(dict);
- CFArrayRef arrayref = CTFontCollectionCreateMatchingFontDescriptors(fcref);
- CFRelease(fcref);
- CFIndex count = CFArrayGetCount(arrayref);
- CFIndex i;
- char **tabfontnames = new char*[count];
- for (i = 0; i < count; i++) {
- CTFontDescriptorRef fdesc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(arrayref, i);
- CTFontRef font = CTFontCreateWithFontDescriptor(fdesc, 0., NULL);
- CFStringRef cfname = CTFontCopyPostScriptName(font);
- CFRelease(font);
- CFDataRef cfdata = CFStringCreateExternalRepresentation(NULL, cfname, kCFStringEncodingUTF8, '?');
- CFIndex l = CFDataGetLength(cfdata);
- tabfontnames[i] = (char*)malloc(l+1); // never free'ed
- memcpy(tabfontnames[i], CFDataGetBytePtr(cfdata), l);
- tabfontnames[i][l] = 0;
- CFRelease(cfdata);
- CFRelease(cfname);
- }
- CFRelease(arrayref);
- qsort(tabfontnames, count, sizeof(char*), name_compare);
- for (i = 0; i < count; i++) {
- Fl::set_font((Fl_Font)(fl_free_font++), tabfontnames[i]);
- }
- delete[] tabfontnames;
- return (Fl_Font)fl_free_font;
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
deleted file mode 100644
index 932ef7d82..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
+++ /dev/null
@@ -1,284 +0,0 @@
-//
-// MacOS image drawing code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#include "Fl_Quartz_Graphics_Driver.H"
-#include <FL/Fl.H>
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-#include <FL/Fl_Image_Surface.H>
-
-#define MAXBUFFER 0x40000 // 256k
-
-static void dataReleaseCB(void *info, const void *data, size_t size)
-{
- delete[] (uchar *)data;
-}
-
-/*
- draw an image based on the input parameters
-
- buf: image source data
- X, Y: position (in buffer?!)
- W, H: size of picture (in pixel?)
- delta: distance from pixel to pixel in buf in bytes
- linedelta: distance from line to line in buf in bytes
- mono: if set, pixel is one byte - if zero, pixel is 3 byte
- cb: callback to copy image data into (RGB?) buffer
- buf: pointer to first byte in image source
- x, y: position in buffer
- w: width (in bytes?)
- dst: destination buffer
- userdata: ?
- */
-static void innards(const uchar *buf, int X, int Y, int W, int H,
- int delta, int linedelta, int mono,
- Fl_Draw_Image_Cb cb, void* userdata, CGContextRef gc, Fl_Quartz_Graphics_Driver *driver)
-{
- if (!linedelta) linedelta = W*abs(delta);
-
- uchar *tmpBuf = 0;
- if (!cb) {
- if (delta < 0) buf -= (W-1)*(-delta);
- if (linedelta < 0) buf -= (H-1)*abs(linedelta);
- }
- const void *array = buf;
- if (cb || driver->has_feature(Fl_Quartz_Graphics_Driver::PRINTER)) {
- tmpBuf = new uchar[ H*W*abs(delta) ];
- if (cb) {
- for (int i=0; i<H; i++) {
- cb(userdata, 0, i, W, tmpBuf+i*W*abs(delta));
- }
- } else {
- uchar *p = tmpBuf;
- for (int i=0; i<H; i++) {
- memcpy(p, buf+i*abs(linedelta), W*abs(delta));
- p += W*abs(delta);
- }
- }
- array = (void*)tmpBuf;
- linedelta = W*abs(delta);
- }
- // create an image context
- CGColorSpaceRef lut = 0;
- if (abs(delta)<=2)
- lut = CGColorSpaceCreateDeviceGray();
- else
- lut = CGColorSpaceCreateDeviceRGB();
- // a release callback is necessary when the gc is a print context because the image data
- // must be kept until the page is closed. Thus tmpBuf can't be deleted here. It's too early.
- CGDataProviderRef src = CGDataProviderCreateWithData( 0L, array, abs(linedelta)*H,
- tmpBuf ? dataReleaseCB : NULL
- );
- CGImageRef img = CGImageCreate( W, H, 8, 8*abs(delta), abs(linedelta),
- lut, abs(delta)&1?kCGImageAlphaNone:kCGImageAlphaLast,
- src, 0L, false, kCGRenderingIntentDefault);
- CGColorSpaceRelease(lut);
- CGDataProviderRelease(src);
- // draw the image into the destination context
- if (img) {
- CGContextSaveGState(gc);
- CGContextTranslateCTM(gc, X, Y);
- if (linedelta < 0) {
- CGContextTranslateCTM(gc, 0, H-1);
- CGContextScaleCTM(gc, 1, -1);
- }
- if (delta < 0) {
- CGContextTranslateCTM(gc, W-1, 0);
- CGContextScaleCTM(gc, -1, 1);
- }
- driver->draw_CGImage(img, 0,0,W,H, 0,0,W,H);
- CGImageRelease(img);
- CGContextRestoreGState(gc);
- }
-}
-
-void Fl_Quartz_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
- d &= ~FL_IMAGE_WITH_ALPHA;
- innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0,gc_,this);
-}
-void Fl_Quartz_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
- int x, int y, int w, int h,int d) {
- innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data,gc_,this);
-}
-void Fl_Quartz_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
- innards(buf,x,y,w,h,d,l,1,0,0,gc_,this);
-}
-void Fl_Quartz_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
- int x, int y, int w, int h,int d) {
- innards(0,x,y,w,h,d,0,1,cb,data,gc_,this);
-}
-
-
-void Fl_Quartz_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (!bm->array) {
- draw_empty(bm, XP, YP);
- return;
- }
- if (start_image(bm, XP,YP,WP,HP,cx,cy,X,Y,W,H)) return;
- if (!*id(bm))
- cache(bm);
-
- if (*Fl_Graphics_Driver::id(bm) && gc_) {
- draw_CGImage((CGImageRef)*Fl_Graphics_Driver::id(bm), X,Y,W,H, cx, cy, bm->w(), bm->h());
- }
-}
-
-void Fl_Quartz_Graphics_Driver::cache(Fl_RGB_Image *rgb) {
- CGColorSpaceRef lut = rgb->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
- int ld = rgb->ld();
- if (!ld) ld = rgb->data_w() * rgb->d();
- CGDataProviderRef src;
- if ( has_feature(PRINTER) ) {
- // When printing or copying to clipboard, the data at rgb->array are used when
- // the PDF page is completed, that is, after return from this function.
- // At that stage, the rgb object has possibly been deleted. It is therefore necessary
- // to use a copy of rgb->array. The mask_ member of rgb
- // is used to avoid repeating the copy operation if rgb is drawn again.
- // The CGImage data provider deletes the copy at the latest of these two events:
- // deletion of rgb, and completion of the PDF page where rgb was drawn.
- size_t total = ld * rgb->data_h();
- uchar *copy = new uchar[total];
- memcpy(copy, rgb->array, total);
- src = CGDataProviderCreateWithData(NULL, copy, total, dataReleaseCB);
- *Fl_Graphics_Driver::mask(rgb) = 1;
- } else {
- // the CGImage data provider must not release the image data.
- src = CGDataProviderCreateWithData(NULL, rgb->array, ld * rgb->data_h(), NULL);
- }
- CGImageRef cgimg = CGImageCreate(rgb->data_w(), rgb->data_h(), 8, rgb->d()*8, ld,
- lut, (rgb->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast,
- src, 0L, false, kCGRenderingIntentDefault);
- *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)cgimg;
- CGColorSpaceRelease(lut);
- CGDataProviderRelease(src);
-}
-
-void Fl_Quartz_Graphics_Driver::draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- // Don't draw an empty image...
- if (!img->d() || !img->array) {
- Fl_Graphics_Driver::draw_empty(img, XP, YP);
- return;
- }
- if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
- return;
- }
- CGImageRef cgimg = (CGImageRef)*Fl_Graphics_Driver::id(img);
- if (cgimg && has_feature(PRINTER) && !*Fl_Graphics_Driver::mask(img)) {
- CGImageRelease(cgimg);
- *Fl_Graphics_Driver::id(img) = 0;
- cgimg = NULL;
- }
- if (!cgimg) {
- cache(img);
- cgimg = (CGImageRef)*Fl_Graphics_Driver::id(img);
- }
- if (cgimg && gc_) {
- draw_CGImage(cgimg, X,Y,W,H, cx,cy, img->w(), img->h());
- }
-}
-
-void Fl_Quartz_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (!pxm->data() || !pxm->w()) {
- draw_empty(pxm, XP, YP);
- return;
- }
- if ( start_image(pxm, XP,YP,WP,HP,cx,cy,X,Y,W,H) ) return;
- if (!*id(pxm)) {
- cache(pxm);
- }
-
- CGImageRef cgimg = (CGImageRef)*Fl_Graphics_Driver::id(pxm);
- draw_CGImage(cgimg, X,Y,W,H, cx,cy, pxm->w(), pxm->h());
-}
-
-CGImageRef Fl_Quartz_Graphics_Driver::create_bitmask(int w, int h, const uchar *array) {
- static uchar reverse[16] = /* Bit reversal lookup table */
- { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee,
- 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
- int rowBytes = (w+7)>>3 ;
- uchar *bmask = new uchar[rowBytes*h];
- uchar *dst = bmask;
- const uchar *src = array;
- for ( int i=rowBytes*h; i>0; i--,src++ ) {
- *dst++ = ((reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f))^0xff;
- }
- CGDataProviderRef srcp = CGDataProviderCreateWithData( NULL, bmask, rowBytes*h, dataReleaseCB);
- CGImageRef id_ = CGImageMaskCreate( w, h, 1, 1, rowBytes, srcp, 0L, false);
- CGDataProviderRelease(srcp);
- return id_;
-}
-
-void Fl_Quartz_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) {
- if (bm) CGImageRelease((CGImageRef)bm);
-}
-
-void Fl_Quartz_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) {
- if (id_) {
- CGImageRelease((CGImageRef)id_);
- id_ = 0;
- mask_ = 0;
- }
-}
-
-void Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap *bm) {
- *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)create_bitmask(bm->data_w(), bm->data_h(), bm->array);
-}
-
-
-static void pmProviderRelease (void *ctxt, const void *data, size_t size) {
- CFRelease(ctxt);
-}
-
-void Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img) {
- Fl_Image_Surface *surf = new Fl_Image_Surface(img->data_w(), img->data_h());
- Fl_Surface_Device::push_current(surf);
- fl_draw_pixmap(img->data(), 0, 0, FL_BLACK);
- Fl_Surface_Device::pop_current();
- CGContextRef src = (CGContextRef)Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf);
- void *cgdata = CGBitmapContextGetData(src);
- int sw = (int)CGBitmapContextGetWidth(src);
- int sh = (int)CGBitmapContextGetHeight(src);
- CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(src);
- CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
- CGDataProviderRef src_bytes = CGDataProviderCreateWithData(src, cgdata, sw*sh*4, pmProviderRelease);
- CGImageRef cgimg = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, alpha,
- src_bytes, 0L, false, kCGRenderingIntentDefault);
- CGColorSpaceRelease(lut);
- CGDataProviderRelease(src_bytes);
- *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg;
-}
-
-void Fl_Quartz_Graphics_Driver::draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh)
-{
- CGRect rect = CGRectMake(x, y, w, h);
- CGContextSaveGState(gc_);
- CGContextClipToRect(gc_, CGRectOffset(rect, -0.5, -0.5 ));
- // move graphics context to origin of vertically reversed image
- // The 0.5 here cancels the 0.5 offset present in Quartz graphics contexts.
- // Thus, image and surface pixels are in phase.
- CGContextTranslateCTM(gc_, rect.origin.x - srcx - 0.5, rect.origin.y - srcy + sh - 0.5);
- CGContextScaleCTM(gc_, 1, -1);
- CGContextDrawImage(gc_, CGRectMake(0, 0, sw, sh), cgimg);
- CGContextRestoreGState(gc_);
-}
-
-void Fl_Quartz_Graphics_Driver::uncache_pixmap(fl_uintptr_t pixmap_ref) {
- CGImageRelease((CGImageRef)pixmap_ref);
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx
deleted file mode 100644
index 6a63ae483..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Line style code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-
-
-/**
- \file quartz_line_style.cxx
- \brief Line style drawing utility hiding different platforms.
-*/
-
-#include "Fl_Quartz_Graphics_Driver.H"
-
-void Fl_Quartz_Graphics_Driver::quartz_restore_line_style() {
- CGContextSetLineWidth(gc_, quartz_line_width_);
- CGContextSetLineCap(gc_, quartz_line_cap_);
- CGContextSetLineJoin(gc_, quartz_line_join_);
- CGContextSetLineDash(gc_, 0, quartz_line_pattern, quartz_line_pattern_size);
-}
-
-void Fl_Quartz_Graphics_Driver::line_style(int style, int width, char* dashes) {
-
- static CGLineCap Cap[4] = { kCGLineCapButt, kCGLineCapButt,
- kCGLineCapRound, kCGLineCapSquare };
- static CGLineJoin Join[4] = { kCGLineJoinMiter, kCGLineJoinMiter,
- kCGLineJoinRound, kCGLineJoinBevel };
- if (width<1) width = 1;
- quartz_line_width_ = (float)width;
- quartz_line_cap_ = Cap[(style>>8)&3];
- // when printing kCGLineCapSquare seems better for solid lines
- if ( Fl_Surface_Device::surface() != Fl_Display_Device::display_device()
- && style == FL_SOLID && dashes == NULL )
- {
- quartz_line_cap_ = kCGLineCapSquare;
- }
- quartz_line_join_ = Join[(style>>12)&3];
- char *d = dashes;
- static CGFloat pattern[16];
- if (d && *d) {
- CGFloat *pDst = pattern;
- while (*d) { *pDst++ = (float)*d++; }
- quartz_line_pattern = pattern;
- quartz_line_pattern_size = (int)(d-dashes);
- } else if (style & 0xff) {
- char dash, dot, gap;
- // adjust lengths to account for cap:
- if (style & 0x200) {
- dash = char(2*width);
- dot = 1;
- gap = char(2*width-1);
- } else {
- dash = char(3*width);
- dot = gap = char(width);
- }
- CGFloat *pDst = pattern;
- switch (style & 0xff) {
- case FL_DASH: *pDst++ = dash; *pDst++ = gap; break;
- case FL_DOT: *pDst++ = dot; *pDst++ = gap; break;
- case FL_DASHDOT: *pDst++ = dash; *pDst++ = gap; *pDst++ = dot; *pDst++ = gap; break;
- case FL_DASHDOTDOT: *pDst++ = dash; *pDst++ = gap; *pDst++ = dot; *pDst++ = gap; *pDst++ = dot; *pDst++ = gap; break;
- }
- quartz_line_pattern_size = (int)(pDst-pattern);
- quartz_line_pattern = pattern;
- } else {
- quartz_line_pattern = 0;
- quartz_line_pattern_size = 0;
- }
- quartz_restore_line_style();
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx
deleted file mode 100644
index 234853ad6..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx
+++ /dev/null
@@ -1,310 +0,0 @@
-//
-// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2018 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <math.h>
-
-
-/**
- \file quartz_rect.cxx
- \brief Apple Quartz specific line and polygon drawing with integer coordinates.
-*/
-
-
-#include "Fl_Quartz_Graphics_Driver.H"
-
-
-// --- line and polygon drawing with integer coordinates
-
-void Fl_Quartz_Graphics_Driver::point(int x, int y) {
- CGContextFillRect(gc_, CGRectMake(x - 0.5, y - 0.5, 1, 1) );
-}
-
-void Fl_Quartz_Graphics_Driver::rect(int x, int y, int w, int h) {
- if (w<=0 || h<=0) return;
- double offset = (quartz_line_width_ >= 2 ? quartz_line_width_/4 : 0);
- CGRect rect = CGRectMake(x - offset, y - offset, w-1, h-1);
- CGContextStrokeRect(gc_, rect);
-}
-
-void Fl_Quartz_Graphics_Driver::focus_rect(int x, int y, int w, int h)
-{
- CGContextSaveGState(gc_);
- float s = scale();
- CGContextScaleCTM(gc_, 1/s, 1/s);
- CGFloat lw = (s >= 1 ? floor(s) : 1);
- CGContextSetLineWidth(gc_, lw);
- CGFloat dots[2] = {lw, lw};
- CGContextSetLineDash(gc_, 0, dots, 2);
- CGContextStrokeRect(gc_, CGRectMake(x*s, y*s, (w-1)*s, (h-1)*s));
- CGContextRestoreGState(gc_);
-}
-
-void Fl_Quartz_Graphics_Driver::rectf(int x, int y, int w, int h) {
- if (w<=0 || h<=0) return;
- CGRect rect = CGRectMake(x - 0.5, y - 0.5, w , h);
- CGContextFillRect(gc_, rect);
-}
-
-void Fl_Quartz_Graphics_Driver::line(int x, int y, int x1, int y1) {
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y1);
- CGContextStrokePath(gc_);
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y1);
- CGContextAddLineToPoint(gc_, x2, y2);
- CGContextStrokePath(gc_);
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1) {
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y);
- CGContextStrokePath(gc_);
- if (high_resolution() || scale()>=2) {
- /* On retina displays, all xyline() and yxline() functions produce lines that are half-unit
- (or one pixel) too short at both ends. This is corrected by filling at both ends rectangles
- of size one unit by line-width.
- */
- CGContextFillRect(gc_, CGRectMake(x-0.5 , y - quartz_line_width_/2, 1 , quartz_line_width_));
- CGContextFillRect(gc_, CGRectMake(x1-0.5 , y - quartz_line_width_/2, 1 , quartz_line_width_));
- }
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y);
- CGContextAddLineToPoint(gc_, x1, y2);
- CGContextStrokePath(gc_);
- if (high_resolution() || scale()>=2) {
- CGContextFillRect(gc_, CGRectMake(x-0.5, y - quartz_line_width_/2, 1 , quartz_line_width_));
- CGContextFillRect(gc_, CGRectMake(x1 - quartz_line_width_/2, y2-0.5, quartz_line_width_, 1));
- }
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y);
- CGContextAddLineToPoint(gc_, x1, y2);
- CGContextAddLineToPoint(gc_, x3, y2);
- CGContextStrokePath(gc_);
- if (high_resolution() || scale()>=2) {
- CGContextFillRect(gc_, CGRectMake(x-0.5, y - quartz_line_width_/2, 1 , quartz_line_width_));
- CGContextFillRect(gc_, CGRectMake(x3-0.5, y2 - quartz_line_width_/2, 1 , quartz_line_width_));
- }
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1) {
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x, y1);
- CGContextStrokePath(gc_);
- if (high_resolution() || scale()>=2) {
- CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1));
- CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y1-0.5, quartz_line_width_, 1));
- }
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x, y1);
- CGContextAddLineToPoint(gc_, x2, y1);
- CGContextStrokePath(gc_);
- if (high_resolution() || scale()>=2) {
- CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1));
- CGContextFillRect(gc_, CGRectMake(x2-0.5, y1 - quartz_line_width_/2, 1 , quartz_line_width_));
- }
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x, y1);
- CGContextAddLineToPoint(gc_, x2, y1);
- CGContextAddLineToPoint(gc_, x2, y3);
- CGContextStrokePath(gc_);
- if (high_resolution() || scale()>=2) {
- CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1));
- CGContextFillRect(gc_, CGRectMake(x2 - quartz_line_width_/2, y3-0.5, quartz_line_width_, 1));
- }
- if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) {
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y1);
- CGContextAddLineToPoint(gc_, x2, y2);
- CGContextClosePath(gc_);
- CGContextStrokePath(gc_);
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y1);
- CGContextAddLineToPoint(gc_, x2, y2);
- CGContextAddLineToPoint(gc_, x3, y3);
- CGContextClosePath(gc_);
- CGContextStrokePath(gc_);
- if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
- float s = scale(); if (s < 2) s = 0;
- CGContextSetLineWidth(gc_, 0.05);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x+w-1 +s/8, y);
- CGContextAddLineToPoint(gc_, x+w-1 +s/8, y+h-1 -s/8);
- CGContextAddLineToPoint(gc_, x, y+h-1 -s/8);
- CGContextClosePath(gc_);
- CGContextStrokePath(gc_);
- CGContextSetLineWidth(gc_, quartz_line_width_);
-}
-
-void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
- CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y1);
- CGContextAddLineToPoint(gc_, x2, y2);
- CGContextClosePath(gc_);
- CGContextFillPath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
- CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, x, y);
- CGContextAddLineToPoint(gc_, x1, y1);
- CGContextAddLineToPoint(gc_, x2, y2);
- CGContextAddLineToPoint(gc_, x3, y3);
- CGContextClosePath(gc_);
- CGContextFillPath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
-
-// --- clipping
-
-// intersects current and x,y,w,h rectangle and returns result as a new Fl_Region
-static Fl_Region intersect_region_and_rect(Fl_Region current_, int x,int y,int w, int h)
-{
- if (current_ == NULL) return Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h);
- struct flCocoaRegion* current = (struct flCocoaRegion*)current_;
- CGRect r = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(x, y, w, h);
- struct flCocoaRegion* outr = (struct flCocoaRegion*)malloc(sizeof(struct flCocoaRegion));
- outr->count = current->count;
- outr->rects =(CGRect*)malloc(outr->count * sizeof(CGRect));
- int j = 0;
- for(int i = 0; i < current->count; i++) {
- CGRect test = CGRectIntersection(current->rects[i], r);
- if (!CGRectIsEmpty(test)) outr->rects[j++] = test;
- }
- if (j) {
- outr->count = j;
- outr->rects = (CGRect*)realloc(outr->rects, outr->count * sizeof(CGRect));
- }
- else {
- Fl_Graphics_Driver::default_driver().XDestroyRegion(outr);
- outr = (struct flCocoaRegion*)Fl_Graphics_Driver::default_driver().XRectangleRegion(0,0,0,0);
- }
- return outr;
-}
-
-
-void Fl_Quartz_Graphics_Driver::push_clip(int x, int y, int w, int h) {
- Fl_Region r;
- if (w > 0 && h > 0) {
- r = XRectangleRegion(x,y,w,h);
- Fl_Region current = rstack[rstackptr];
- if (current) {
- XDestroyRegion(r);
- r = intersect_region_and_rect(current, x,y,w,h);
- }
- } else { // make empty clip region:
- r = XRectangleRegion(0,0,0,0);
- }
- if (rstackptr < region_stack_max) rstack[++rstackptr] = r;
- else Fl::warning("Fl_Quartz_Graphics_Driver::push_clip: clip stack overflow!\n");
- restore_clip();
-}
-
-int Fl_Quartz_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
- X = x; Y = y; W = w; H = h;
- struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr];
- if (!r) return 0;
- CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
- CGRect u = CGRectMake(0,0,0,0);
- CGRect test;
- for (int i = 0; i < r->count; i++) {
- test = CGRectIntersection(r->rects[i], arg);
- if ( !CGRectIsEmpty(test) ) {
- if(CGRectIsEmpty(u)) u = test;
- else u = CGRectUnion(u, test);
- }
- }
- X = int(u.origin.x + 0.5); // reverse offset introduced by fl_cgrectmake_cocoa()
- Y = int(u.origin.y + 0.5);
- W = int(u.size.width + 0.5); // round to nearest integer
- H = int(u.size.height + 0.5);
- if (CGRectIsEmpty(u)) W = H = 0;
- return !CGRectEqualToRect(arg, u);
-}
-
-int Fl_Quartz_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
- if (x+w <= 0 || y+h <= 0) return 0;
- struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr];
- if (!r) return 1;
- CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
- for (int i = 0; i < r->count; i++) {
- CGRect test = CGRectIntersection(r->rects[i], arg);
- if (!CGRectIsEmpty(test)) return 1;
- }
- return 0;
-}
-
-void Fl_Quartz_Graphics_Driver::restore_clip() {
- fl_clip_state_number++;
- struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr];
- if ( fl_window || gc_ ) { // clipping for a true window or an offscreen buffer
- if (gc_) {
- CGContextRestoreGState(gc_);
- CGContextSaveGState(gc_);
- }
- color(color());
- quartz_restore_line_style();
- if (r) { //apply program clip
- CGContextClipToRects(gc_, r->rects, r->count);
- }
- }
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx
deleted file mode 100644
index 16c6c6c29..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx
+++ /dev/null
@@ -1,98 +0,0 @@
-//
-// Portable drawing routines for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file quartz_vertex.cxx
- \brief Portable drawing code for drawing arbitrary shapes with
- simple 2D transformations, implemented for OS X Quartz.
-*/
-
-#include "Fl_Quartz_Graphics_Driver.H"
-
-#include <FL/fl_draw.H>
-#include <FL/platform.H>
-#include <FL/math.h>
-
-
-void Fl_Quartz_Graphics_Driver::end_points() {
- for (int i = 0; i < n; i++) {
- point(xpoint[i].x, xpoint[i].y);
- }
-}
-
-void Fl_Quartz_Graphics_Driver::end_line() {
- if (n < 2) {
- end_points();
- return;
- }
- if (n<=1) return;
- CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, xpoint[0].x, xpoint[0].y);
- for (int i=1; i<n; i++)
- CGContextAddLineToPoint(gc_, xpoint[i].x, xpoint[i].y);
- CGContextStrokePath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::end_polygon() {
- fixloop();
- if (n < 3) {
- end_line();
- return;
- }
- if (n<=1) return;
- CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, xpoint[0].x, xpoint[0].y);
- for (int i=1; i<n; i++)
- CGContextAddLineToPoint(gc_, xpoint[i].x, xpoint[i].y);
- CGContextClosePath(gc_);
- CGContextFillPath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::end_complex_polygon() {
- gap();
- if (n < 3) {
- end_line();
- return;
- }
- if (n<=1) return;
- CGContextSetShouldAntialias(gc_, true);
- CGContextMoveToPoint(gc_, xpoint[0].x, xpoint[0].y);
- for (int i=1; i<n; i++)
- CGContextAddLineToPoint(gc_, xpoint[i].x, xpoint[i].y);
- CGContextClosePath(gc_);
- CGContextFillPath(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
-
-void Fl_Quartz_Graphics_Driver::circle(double x, double y,double r) {
- double xt = transform_x(x,y);
- double yt = transform_y(x,y);
- double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
- double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
- int llx = (int)rint(xt-rx);
- int w = (int)rint(xt+rx)-llx;
- int lly = (int)rint(yt-ry);
- int h = (int)rint(yt+ry)-lly;
-
- // Quartz warning: circle won't scale to current matrix!
- // Last argument must be 0 (counter-clockwise) or it draws nothing under __LP64__ !!!!
- CGContextSetShouldAntialias(gc_, true);
- CGContextAddArc(gc_, xt, yt, (w+h)*0.25f, 0, 2.0f*M_PI, 0);
- (what == POLYGON ? CGContextFillPath : CGContextStrokePath)(gc_);
- CGContextSetShouldAntialias(gc_, false);
-}
diff --git a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
deleted file mode 100644
index 3849ea4df..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_QUARTZ_IMAGE_SURFACE_DRIVER_H
-#define FL_QUARTZ_IMAGE_SURFACE_DRIVER_H
-
-#include <FL/Fl_Image_Surface.H>
-#include <FL/platform.H>
-
-class Fl_Quartz_Image_Surface_Driver : public Fl_Image_Surface_Driver {
-private:
- CGImageRef mask_;
- void mask(const Fl_RGB_Image *) FL_OVERRIDE;
- void end_current() FL_OVERRIDE;
-public:
- FLWindow *pre_window;
- Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off);
- ~Fl_Quartz_Image_Surface_Driver();
- void set_current() FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate() FL_OVERRIDE;
- Fl_RGB_Image *image() FL_OVERRIDE;
-};
-
-#endif // FL_QUARTZ_IMAGE_SURFACE_DRIVER_H
diff --git a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
deleted file mode 100644
index 4615ba475..000000000
--- a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/platform.H>
-#include <FL/fl_draw.H>
-#include "Fl_Quartz_Image_Surface_Driver.H"
-#include "Fl_Quartz_Graphics_Driver.H"
-#include "../Cocoa/Fl_Cocoa_Window_Driver.H"
-#include <ApplicationServices/ApplicationServices.h>
-
-
-Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
- mask_ = NULL;
- int W = w, H = h;
- float s = 1;
- if (high_res) {
- s = Fl_Graphics_Driver::default_driver().scale();
- Fl_Window *cw = Fl::first_window();
- Fl_Cocoa_Window_Driver *dr = cw ? Fl_Cocoa_Window_Driver::driver(cw) : NULL;
- if (dr && dr->mapped_to_retina()) s *= 2;
- W *= s; H *= s;
- }
- CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
- offscreen = off ? off : (Fl_Offscreen)CGBitmapContextCreate(calloc(W*H,4), W, H, 8, W*4, lut, kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(lut);
- driver(new Fl_Quartz_Graphics_Driver);
- CGContextTranslateCTM((CGContextRef)offscreen, 0.5*s, -0.5*s); // as when drawing to a window
- if (high_res) {
- CGContextScaleCTM((CGContextRef)offscreen, s, s);
- driver()->scale(s);
- }
- CGContextSetShouldAntialias((CGContextRef)offscreen, false);
- CGContextTranslateCTM((CGContextRef)offscreen, 0, height);
- CGContextScaleCTM((CGContextRef)offscreen, 1.0f, -1.0f);
- CGContextSaveGState((CGContextRef)offscreen);
- CGContextSetRGBFillColor((CGContextRef)offscreen, 1, 1, 1, 0);
- CGContextFillRect((CGContextRef)offscreen, CGRectMake(0,0,w,h));
-}
-
-Fl_Quartz_Image_Surface_Driver::~Fl_Quartz_Image_Surface_Driver() {
- if (mask_) {
- CGImageRelease(mask_);
- }
- if (offscreen) CGContextRestoreGState((CGContextRef)offscreen);
- if (offscreen && !external_offscreen) {
- void *data = CGBitmapContextGetData((CGContextRef)offscreen);
- free(data);
- CGContextRelease((CGContextRef)offscreen);
- }
- delete driver();
-}
-
-
-void Fl_Quartz_Image_Surface_Driver::set_current() {
- Fl_Surface_Device::set_current();
- pre_window = fl_window;
- driver()->gc((CGContextRef)offscreen);
- fl_window = 0;
- ((Fl_Quartz_Graphics_Driver*)driver())->high_resolution( CGBitmapContextGetWidth((CGContextRef)offscreen) > (size_t)width );
- if (mask_) {
- int W, H;
- printable_rect(&W, &H);
- CGContextSaveGState((CGContextRef)offscreen);
- CGContextClipToMask((CGContextRef)offscreen, CGRectMake(0,0,W,H), mask_); // 10.4
- CGContextSaveGState((CGContextRef)offscreen);
- }
-}
-
-void Fl_Quartz_Image_Surface_Driver::translate(int x, int y) {
- CGContextRestoreGState((CGContextRef)offscreen);
- CGContextSaveGState((CGContextRef)offscreen);
- CGContextTranslateCTM((CGContextRef)offscreen, x, y);
- CGContextSaveGState((CGContextRef)offscreen);
-}
-
-void Fl_Quartz_Image_Surface_Driver::untranslate() {
- CGContextRestoreGState((CGContextRef)offscreen);
-}
-
-Fl_RGB_Image* Fl_Quartz_Image_Surface_Driver::image()
-{
- CGContextFlush((CGContextRef)offscreen);
- if (mask_) {
- CGContextRestoreGState((CGContextRef)offscreen);
- CGImageRelease(mask_);
- mask_ = NULL;
- }
- int W = (int)CGBitmapContextGetWidth((CGContextRef)offscreen);
- int H = (int)CGBitmapContextGetHeight((CGContextRef)offscreen);
- int bpr = (int)CGBitmapContextGetBytesPerRow((CGContextRef)offscreen);
- int bpp = (int)CGBitmapContextGetBitsPerPixel((CGContextRef)offscreen)/8;
- uchar *base = (uchar*)CGBitmapContextGetData((CGContextRef)offscreen);
- int idx, idy;
- uchar *pdst, *psrc;
- unsigned char *data = new uchar[W * H * 3];
- for (idy = 0, pdst = data; idy < H; idy ++) {
- for (idx = 0, psrc = base + idy * bpr; idx < W; idx ++, psrc += bpp, pdst += 3) {
- pdst[0] = psrc[0]; // R
- pdst[1] = psrc[1]; // G
- pdst[2] = psrc[2]; // B
- }
- }
- Fl_RGB_Image *image = new Fl_RGB_Image(data, W, H);
- image->alloc_array = 1;
- return image;
-}
-
-void Fl_Quartz_Image_Surface_Driver::end_current()
-{
- if (mask_) {
- CGContextRestoreGState((CGContextRef)offscreen);
- CGContextRestoreGState((CGContextRef)offscreen);
- }
- fl_window = pre_window;
- Fl_Surface_Device::end_current();
-}
-
-
-static void MyProviderReleaseData (void *info, const void *data, size_t size) {
- delete[] (uchar*)data;
-}
-
-
-void Fl_Quartz_Image_Surface_Driver::mask(const Fl_RGB_Image *img) {
- if (!&CGContextClipToMask) return;
- int W = (int)CGBitmapContextGetWidth((CGContextRef)offscreen);
- int H = (int)CGBitmapContextGetHeight((CGContextRef)offscreen);
- bool using_copy = false;
- if (W != img->data_w() || H != img->data_h()) {
- Fl_RGB_Image *copy = (Fl_RGB_Image*)img->copy(W, H);
- img = copy;
- using_copy = true;
- }
-
- int i, d = img->d(), w = img->data_w(), h = img->data_h();
- // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits
- int bytes_per_row = (img->ld() ? img->ld() : w * d);
- uchar *from = new uchar[w * h];
- for ( i = 0; i < h; i++) {
- const uchar *p = img->array + bytes_per_row * i;
- const uchar *last = p + bytes_per_row;
- uchar *q = from + (h - 1 - i) * w;
- while (p < last) {
- unsigned u = *p++;
- u += *p++;
- u += *p++;
- *q++ = ~(u/3);
- }
- }
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData);
- mask_ = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false);
- CFRelease(provider);
- if (using_copy) delete img;
-}
diff --git a/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H b/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H
deleted file mode 100644
index e10a801ce..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_WAYLAND_COPY_SURFACE_DRIVER_H
-#define FL_WAYLAND_COPY_SURFACE_DRIVER_H
-
-#include <FL/Fl_Copy_Surface.H>
-#include <FL/Fl_Image_Surface.H>
-
-class Fl_Wayland_Copy_Surface_Driver : public Fl_Copy_Surface_Driver {
- friend class Fl_Copy_Surface_Driver;
- Fl_Image_Surface *img_surf;
-protected:
- Fl_Wayland_Copy_Surface_Driver(int w, int h);
- ~Fl_Wayland_Copy_Surface_Driver();
- void set_current() FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate() FL_OVERRIDE;
-};
-
-#endif // FL_WAYLAND_COPY_SURFACE_DRIVER_H
diff --git a/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx
deleted file mode 100644
index 043114781..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Wayland_Copy_Surface_Driver.H"
-#include <FL/Fl_Image_Surface.H>
-#include "Fl_Wayland_Graphics_Driver.H"
-#include "Fl_Wayland_Screen_Driver.H"
-#include "Fl_Wayland_Window_Driver.H"
-
-
-Fl_Wayland_Copy_Surface_Driver::Fl_Wayland_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
- float os_scale = Fl_Graphics_Driver::default_driver().scale();
- int d = 1;
- if (Fl::first_window()) {
- d = Fl_Wayland_Window_Driver::driver(Fl::first_window())->wld_scale();
- }
- img_surf = new Fl_Image_Surface(int(w * os_scale) * d, int(h * os_scale) * d);
- driver(img_surf->driver());
- driver()->scale(d * os_scale);
-}
-
-
-Fl_Wayland_Copy_Surface_Driver::~Fl_Wayland_Copy_Surface_Driver() {
- Fl_RGB_Image *rgb = img_surf->image();
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- scr_driver->copy_image(rgb->array, rgb->data_w(), rgb->data_h());
- delete rgb;
- delete img_surf;
- driver(NULL);
-}
-
-
-void Fl_Wayland_Copy_Surface_Driver::set_current() {
- Fl_Surface_Device::set_current();
- Fl_Cairo_Graphics_Driver *dr = (Fl_Cairo_Graphics_Driver*)driver();
- if (!dr->cr()) dr->set_cairo((cairo_t*)img_surf->offscreen());
-}
-
-
-void Fl_Wayland_Copy_Surface_Driver::translate(int x, int y) {
- ((Fl_Wayland_Graphics_Driver*)driver())->ps_translate(x, y);
-}
-
-
-void Fl_Wayland_Copy_Surface_Driver::untranslate() {
- ((Fl_Wayland_Graphics_Driver*)driver())->ps_untranslate();
-}
diff --git a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H
deleted file mode 100644
index ad67c01bf..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_WAYLAND_GL_WINDOW_DRIVER_H
-#define FL_WAYLAND_GL_WINDOW_DRIVER_H
-
-#include <config.h>
-#if HAVE_GL
-#include "../../Fl_Gl_Window_Driver.H"
-#include <wayland-egl.h>
-#include <EGL/egl.h>
-#include <FL/gl.h>
-
-
-class Fl_Wayland_Gl_Window_Driver : public Fl_Gl_Window_Driver {
- friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *);
- friend class Fl_Wayland_Gl_Plugin;
-private:
- static EGLDisplay egl_display;
- struct wl_egl_window *egl_window;
- EGLSurface egl_surface;
- bool need_swap;
- Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win);
- float pixels_per_unit() FL_OVERRIDE;
- void make_current_before() FL_OVERRIDE;
- int mode_(int m, const int *a) FL_OVERRIDE;
- void swap_buffers() FL_OVERRIDE;
- void resize(int is_a_resize, int w, int h) FL_OVERRIDE;
- char swap_type() FL_OVERRIDE;
- void swap_interval(int) FL_OVERRIDE;
- int swap_interval() const FL_OVERRIDE;
- Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE;
- GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE;
- void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE;
- void delete_gl_context(GLContext) FL_OVERRIDE;
- void make_overlay_current() FL_OVERRIDE;
- void redraw_overlay() FL_OVERRIDE;
- void gl_start() FL_OVERRIDE;
- void gl_visual(Fl_Gl_Choice *c) FL_OVERRIDE;
- void init();
- void* GetProcAddress(const char *procName) FL_OVERRIDE;
-public:
- static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time);
- //virtual bool need_scissor() { return true; } // CONTROL_LEAKING_SUB_GL_WINDOWS
- //void apply_scissor(); // CONTROL_LEAKING_SUB_GL_WINDOWS
-};
-
-#endif // HAVE_GL
-#endif // FL_WAYLAND_GL_WINDOW_DRIVER_H
diff --git a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
deleted file mode 100644
index d20b941b7..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
+++ /dev/null
@@ -1,486 +0,0 @@
-//
-// Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#if HAVE_GL
-#include <FL/platform.H>
-#include <FL/Fl_Image_Surface.H>
-#include "../../Fl_Gl_Choice.H"
-#include "Fl_Wayland_Window_Driver.H"
-#include "Fl_Wayland_Graphics_Driver.H"
-#include "Fl_Wayland_Gl_Window_Driver.H"
-#include "../Posix/Fl_Posix_System_Driver.H"
-#ifdef FLTK_USE_X11
-# include "../X11/Fl_X11_Gl_Window_Driver.H"
-#endif
-#include <wayland-egl.h>
-#include <EGL/egl.h>
-#include <FL/gl.h>
-
-/* Implementation notes about OpenGL drawing on the Wayland platform
-
-* After eglCreateWindowSurface() with attributes {EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, EGL_NONE},
-eglQueryContext() reports that EGL_RENDER_BUFFER equals EGL_BACK_BUFFER.
-This experiment suggests that the platform only supports double-buffer drawing.
-Consequently, FL_DOUBLE is enforced in all Fl_Gl_Window::mode_ values under Wayland.
-
-* Commented out code marked with CONTROL_LEAKING_SUB_GL_WINDOWS aims to prevent
- sub GL windows from leaking out from their parent by making leaking parts fully transparent.
- This code is commented out because it requires the FL_ALPHA flag to be on
- which not all client applications do.
-*/
-
-// Describes crap needed to create a GLContext.
-class Fl_Wayland_Gl_Choice : public Fl_Gl_Choice {
- friend class Fl_Wayland_Gl_Window_Driver;
-private:
- EGLConfig egl_conf;
-public:
- Fl_Wayland_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) {
- egl_conf = 0;
- }
-};
-
-
-struct gl_start_support { // to support use of gl_start / gl_finish
- struct wl_surface *surface;
- struct wl_subsurface *subsurface;
- struct wl_egl_window *egl_window;
- EGLSurface egl_surface;
-};
-
-
-static EGLConfig wld_egl_conf = NULL;
-static EGLint swap_interval_ = 1;
-static EGLint max_swap_interval = 1000;
-static EGLint min_swap_interval = 0;
-
-
-EGLDisplay Fl_Wayland_Gl_Window_Driver::egl_display = EGL_NO_DISPLAY;
-
-
-Fl_Wayland_Gl_Window_Driver::Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win) :
- Fl_Gl_Window_Driver(win) {
- if (egl_display == EGL_NO_DISPLAY) init();
- egl_window = NULL;
- egl_surface = NULL;
- need_swap = false;
-}
-
-
-Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
-{
-#ifdef FLTK_USE_X11
- if (!Fl_Wayland_Screen_Driver::wl_display) return new Fl_X11_Gl_Window_Driver(w);
-#endif
- return new Fl_Wayland_Gl_Window_Driver(w);
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::init() {
- EGLint major, minor;
-
- if (!fl_wl_display()) fl_open_display();
- egl_display = eglGetDisplay((EGLNativeDisplayType) fl_wl_display());
- if (egl_display == EGL_NO_DISPLAY) {
- Fl::fatal("Can't create egl display\n");
- }
-
- if (eglInitialize(egl_display, &major, &minor) != EGL_TRUE) {
- Fl::fatal("Can't initialise egl display\n");
- }
- //printf("EGL major: %d, minor %d\n", major, minor);
- //eglGetConfigs(egl_display, NULL, 0, &configs_count);
- //printf("EGL has %d configs\n", configs_count);
- eglBindAPI(EGL_OPENGL_API);
-}
-
-
-Fl_Gl_Choice *Fl_Wayland_Gl_Window_Driver::find(int m, const int *alistp)
-{
- m |= FL_DOUBLE;
- //if (pWindow->parent()) m |= FL_ALPHA; // CONTROL_LEAKING_SUB_GL_WINDOWS
- Fl_Wayland_Gl_Choice *g = (Fl_Wayland_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(
- m, alistp);
- if (g) return g;
-
- EGLint n;
- EGLint config_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
- EGL_DEPTH_SIZE, 0, // set at 11
- EGL_SAMPLE_BUFFERS, 0, // set at 13
- EGL_STENCIL_SIZE, 0, // set at 15
- EGL_ALPHA_SIZE, 0, // set at 17
- EGL_NONE
- };
-
- if (m & FL_DEPTH32)
- config_attribs[11] = 32; // request at least 32 bits
- else if (m & FL_DEPTH)
- config_attribs[11] = 1; // accept any size
-
- if (m & FL_MULTISAMPLE) config_attribs[13] = 1;
- if (m & FL_STENCIL) config_attribs[15] = 1;
- if (m & FL_ALPHA) config_attribs[17] = (m & FL_RGB8) ? 8 : 1;
-
- g = new Fl_Wayland_Gl_Choice(m, alistp, first);
- eglChooseConfig(egl_display, config_attribs, &(g->egl_conf), 1, &n);
- if (n == 0 && (m & FL_MULTISAMPLE)) {
- config_attribs[13] = 0;
- eglChooseConfig(egl_display, config_attribs, &(g->egl_conf), 1, &n);
- }
- if (n == 0) {
- Fl::fatal("failed to choose an EGL config\n");
- }
-
- eglGetConfigAttrib(egl_display, g->egl_conf, EGL_MAX_SWAP_INTERVAL, &max_swap_interval);
- eglGetConfigAttrib(egl_display, g->egl_conf, EGL_MIN_SWAP_INTERVAL, &min_swap_interval);
-
- first = g;
- return g;
-}
-
-
-GLContext Fl_Wayland_Gl_Window_Driver::create_gl_context(Fl_Window* window,
- const Fl_Gl_Choice* g) {
- GLContext shared_ctx = 0;
- if (context_list && nContext) shared_ctx = context_list[0];
-
- static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- GLContext ctx = (GLContext)eglCreateContext(egl_display,
- ((Fl_Wayland_Gl_Choice*)g)->egl_conf,
- (shared_ctx ? (EGLContext)shared_ctx : EGL_NO_CONTEXT),
- context_attribs);
-//fprintf(stderr, "eglCreateContext=%p shared_ctx=%p\n", ctx, shared_ctx);
- if (ctx) {
- add_context(ctx);
- /* CONTROL_LEAKING_SUB_GL_WINDOWS
- if (egl_surface) {
- eglMakeCurrent(egl_display, egl_surface, egl_surface, (EGLContext)ctx);
- glClearColor(0., 0., 0., 1.); // set opaque black as starting background color
- apply_scissor();
- }*/
- }
- return ctx;
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) {
- struct wld_window *win = fl_wl_xid(w);
- if (!win) return;
- Fl_Wayland_Window_Driver *dr = Fl_Wayland_Window_Driver::driver(w);
- EGLSurface target_egl_surface = NULL;
- if (egl_surface) target_egl_surface = egl_surface;
- else if (dr->gl_start_support_) target_egl_surface = dr->gl_start_support_->egl_surface;
- if (!target_egl_surface) { // useful for gl_start()
- dr->gl_start_support_ = new struct gl_start_support;
- float s = Fl::screen_scale(w->screen_num());
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- // the GL scene will be a transparent subsurface above the cairo-drawn surface
- dr->gl_start_support_->surface =
- wl_compositor_create_surface(scr_driver->wl_compositor);
- dr->gl_start_support_->subsurface = wl_subcompositor_get_subsurface(
- scr_driver->wl_subcompositor, dr->gl_start_support_->surface, win->wl_surface);
- wl_subsurface_set_position(dr->gl_start_support_->subsurface, w->x() * s, w->y() * s);
- wl_subsurface_place_above(dr->gl_start_support_->subsurface, win->wl_surface);
- dr->gl_start_support_->egl_window = wl_egl_window_create(
- dr->gl_start_support_->surface, w->w() * s, w->h() * s);
- target_egl_surface = dr->gl_start_support_->egl_surface = eglCreateWindowSurface(
- egl_display, wld_egl_conf, dr->gl_start_support_->egl_window, NULL);
- }
- GLContext current_context = eglGetCurrentContext();
- if (context != current_context || w != cached_window) {
- cached_window = w;
- if (eglMakeCurrent(egl_display, target_egl_surface, target_egl_surface,
- (EGLContext)context)) {
-//fprintf(stderr, "EGLContext %p made current\n", context);
- } else {
- Fl::error("eglMakeCurrent() failed\n");
- }
- }
- if (!(mode() & FL_ALPHA)) { // useful at least for Linux on MacBook hardware
- GLfloat vals[4];
- glGetFloatv(GL_COLOR_CLEAR_VALUE, vals);
- if (vals[3] == 0.) glClearColor(vals[0], vals[1], vals[2], 1.);
- }
-}
-
-/* CONTROL_LEAKING_SUB_GL_WINDOWS
-void Fl_Wayland_Gl_Window_Driver::apply_scissor() {
- cairo_rectangle_int_t *extents = Fl_Wayland_Window_Driver::driver(pWindow)->subRect();
- if (extents) {
- glDisable(GL_SCISSOR_TEST);
- GLdouble vals[4];
- glGetDoublev(GL_COLOR_CLEAR_VALUE, vals);
- glClearColor(0., 0., 0., 0.);
- glClear(GL_COLOR_BUFFER_BIT);
- glClearColor(vals[0], vals[1], vals[2], vals[3]);
- float s = pWindow->pixels_per_unit();
- glScissor(s*extents->x, s*extents->y, s*extents->width, s*extents->height);
-//printf("apply_scissor %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height);
- glEnable(GL_SCISSOR_TEST);
- }
-}*/
-
-
-void Fl_Wayland_Gl_Window_Driver::delete_gl_context(GLContext context) {
- GLContext current_context = eglGetCurrentContext();
- if (current_context == context) {
- cached_window = 0;
- }
- if (current_context == (EGLContext)context) {
- eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- }
- eglDestroyContext(egl_display, (EGLContext)context);
- eglDestroySurface(egl_display, egl_surface);
- egl_surface = NULL;
- wl_egl_window_destroy(egl_window);
- egl_window = NULL;
- del_context(context);
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::make_overlay_current() {
- glDrawBuffer(GL_FRONT);
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::redraw_overlay() {
- pWindow->redraw();
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::make_current_before() {
- if (!egl_window) {
- struct wld_window *win = fl_wl_xid(pWindow);
- struct wl_surface *surface = win->wl_surface;
- int W = pWindow->pixel_w();
- int H = pWindow->pixel_h();
- int scale = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale();
- egl_window = wl_egl_window_create(surface, (W/scale)*scale, (H/scale)*scale);
- if (egl_window == EGL_NO_SURFACE) {
- Fl::fatal("Can't create egl window with wl_egl_window_create()\n");
- }
- Fl_Wayland_Gl_Choice *g = (Fl_Wayland_Gl_Choice*)this->g();
- egl_surface = eglCreateWindowSurface(egl_display, g->egl_conf, egl_window, NULL);
- wl_surface_set_buffer_scale(surface, scale);
- if (mode() & FL_ALPHA) wl_surface_set_opaque_region(surface, NULL);
- // Tested apps: shape, glpuzzle, cube, fractals, gl_overlay, fullscreen, unittests,
- // OpenGL3-glut-test, OpenGL3test.
- // Tested wayland compositors: mutter, kde-plasma, weston, sway on FreeBSD.
- if (pWindow->parent()) win = fl_wl_xid(pWindow->top_window());
- while (wl_list_empty(&win->outputs)) wl_display_dispatch(fl_wl_display());
- }
-}
-
-
-float Fl_Wayland_Gl_Window_Driver::pixels_per_unit()
-{
- int ns = pWindow->screen_num();
- int wld_scale = (pWindow->shown() ?
- Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale() : 1);
- return wld_scale * Fl::screen_driver()->scale(ns);
-}
-
-
-int Fl_Wayland_Gl_Window_Driver::mode_(int m, const int *a) {
- mode(m | FL_DOUBLE);
- return 1;
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
- Fl_Wayland_Gl_Window_Driver *gl_dr = (Fl_Wayland_Gl_Window_Driver *)data;
- wl_callback_destroy(cb);
- struct wld_window *window = fl_wl_xid(gl_dr->pWindow);
- window->frame_cb = NULL;
- if (gl_dr->need_swap) {
- eglSwapBuffers(Fl_Wayland_Gl_Window_Driver::egl_display, gl_dr->egl_surface);
- gl_dr->need_swap = false;
- }
-}
-
-
-static const struct wl_callback_listener surface_frame_listener = {
- .done = Fl_Wayland_Gl_Window_Driver::surface_frame_done,
-};
-
-
-void Fl_Wayland_Gl_Window_Driver::swap_buffers() {
- if (overlay()) {
- static bool overlay_buffer = true;
- int wo = pWindow->pixel_w(), ho = pWindow->pixel_h();
- GLint matrixmode;
- GLfloat pos[4];
- glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
- glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos
- glMatrixMode(GL_PROJECTION); // save proj/model matrices
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glScalef(2.0f/wo, 2.0f/ho, 1.0f);
- glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of window
- glRasterPos2i(0,0); // set glRasterPos to bottom left corner
- {
- // Emulate overlay by doing copypixels
- glReadBuffer(overlay_buffer?GL_BACK:GL_FRONT);
- glDrawBuffer(overlay_buffer?GL_FRONT:GL_BACK);
- overlay_buffer = ! overlay_buffer;
- glCopyPixels(0, 0, wo, ho, GL_COLOR);
- }
- glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(matrixmode);
- glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos
- if (!overlay_buffer) return; // don't call eglSwapBuffers until overlay has been drawn
- }
-
- if (egl_surface) {
- Fl_Window *parent = pWindow->parent() ? pWindow->window() : NULL;
- struct wld_window *parent_xid = parent ? fl_wl_xid(parent) : NULL;
- if (parent_xid) { // issue #967
- struct wld_window *xid = fl_wl_xid(pWindow);
- if (xid->frame_cb) {
- need_swap = true;
- return;
- }
- if (!parent_xid->frame_cb) {
- xid->frame_cb = wl_surface_frame(xid->wl_surface);
- wl_callback_add_listener(xid->frame_cb, &surface_frame_listener, this);
- }
- }
- eglSwapBuffers(Fl_Wayland_Gl_Window_Driver::egl_display, egl_surface);
- need_swap = false;
- }
-}
-
-
-class Fl_Wayland_Gl_Plugin : public Fl_Wayland_Plugin {
-public:
- Fl_Wayland_Gl_Plugin() : Fl_Wayland_Plugin(name()) { }
- const char *name() FL_OVERRIDE { return "gl.wayland.fltk.org"; }
- void do_swap(Fl_Window *w) FL_OVERRIDE {
- Fl_Gl_Window_Driver *gldr = Fl_Gl_Window_Driver::driver(w->as_gl_window());
- if (gldr->overlay() == w) gldr->swap_buffers();
- }
- void invalidate(Fl_Window *w) FL_OVERRIDE {
- w->as_gl_window()->valid(0);
- }
- void terminate() FL_OVERRIDE {
- if (Fl_Wayland_Gl_Window_Driver::egl_display != EGL_NO_DISPLAY) {
- eglTerminate(Fl_Wayland_Gl_Window_Driver::egl_display);
- }
- }
- void destroy(struct gl_start_support *gl_start_support_) FL_OVERRIDE {
- eglDestroySurface(Fl_Wayland_Gl_Window_Driver::egl_display,
- gl_start_support_->egl_surface);
- wl_egl_window_destroy(gl_start_support_->egl_window);
- wl_subsurface_destroy(gl_start_support_->subsurface);
- wl_surface_destroy(gl_start_support_->surface);
- delete gl_start_support_;
- }
-};
-
-
-static Fl_Wayland_Gl_Plugin Gl_Overlay_Plugin;
-
-
-/* CONTROL_LEAKING_SUB_GL_WINDOWS
-static void delayed_scissor(Fl_Wayland_Gl_Window_Driver *dr) {
- dr->apply_scissor();
-}*/
-
-
-void Fl_Wayland_Gl_Window_Driver::resize(int is_a_resize, int W, int H) {
- if (!egl_window) return;
- float f = Fl::screen_scale(pWindow->screen_num());
- int s = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale();
- W = int(W * f) * s; // W, H must be multiples of int s
- H = int(H * f) * s;
- int W2, H2;
- wl_egl_window_get_attached_size(egl_window, &W2, &H2);
- if (W2 != W || H2 != H) {
- struct wld_window *xid = fl_wl_xid(pWindow);
- if (xid->kind == Fl_Wayland_Window_Driver::DECORATED && !xid->frame_cb) {
- xid->frame_cb = wl_surface_frame(xid->wl_surface);
- wl_callback_add_listener(xid->frame_cb,
- Fl_Wayland_Graphics_Driver::p_surface_frame_listener, xid);
- }
- wl_egl_window_resize(egl_window, W, H, 0, 0);
- wl_surface_set_buffer_scale(xid->wl_surface, s);
- }
- /* CONTROL_LEAKING_SUB_GL_WINDOWS
- if (Fl_Wayland_Window_Driver::driver(pWindow)->subRect()) {
- pWindow->redraw();
- Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_scissor, this);
- }*/
-}
-
-
-char Fl_Wayland_Gl_Window_Driver::swap_type() {
- return copy;
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) {
- Fl_Gl_Window_Driver::gl_visual(c);
- wld_egl_conf = ((Fl_Wayland_Gl_Choice*)c)->egl_conf;
-}
-
-
-void Fl_Wayland_Gl_Window_Driver::gl_start() {
- float f = Fl::screen_scale(Fl_Window::current()->screen_num());
- int W = Fl_Window::current()->w() * f;
- int H = Fl_Window::current()->h() * f;
- int W2, H2;
- Fl_Wayland_Window_Driver *dr = Fl_Wayland_Window_Driver::driver(Fl_Window::current());
- wl_egl_window_get_attached_size(dr->gl_start_support_->egl_window, &W2, &H2);
- if (W2 != W || H2 != H) {
- wl_egl_window_resize(dr->gl_start_support_->egl_window, W, H, 0, 0);
- }
- glClearColor(0., 0., 0., 0.);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void Fl_Wayland_Gl_Window_Driver::swap_interval(int interval) {
- if (interval < min_swap_interval) interval = min_swap_interval;
- if (interval > max_swap_interval) interval = max_swap_interval;
- if (egl_display && eglSwapInterval(egl_display, interval))
- swap_interval_ = interval;
- // printf("swap_interval_=%d\n",swap_interval_);
-}
-
-
-int Fl_Wayland_Gl_Window_Driver::swap_interval() const {
- return swap_interval_;
-}
-
-
-void* Fl_Wayland_Gl_Window_Driver::GetProcAddress(const char *procName) {
- return Fl_Posix_System_Driver::dlopen_or_dlsym(NULL, procName);
-}
-
-
-FL_EXPORT EGLContext fl_wl_glcontext(GLContext rc) { return (EGLContext)rc; }
-
-#endif // HAVE_GL
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
deleted file mode 100644
index ac8786a47..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Definition of class Fl_Wayland_Graphics_Driver.
-//
-// Copyright 2021-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Wayland_Graphics_Driver.H
- \brief Definition of Wayland graphics driver.
- */
-
-#ifndef FL_WAYLAND_GRAPHICS_DRIVER_H
-#define FL_WAYLAND_GRAPHICS_DRIVER_H
-
-#include "../Cairo/Fl_Cairo_Graphics_Driver.H"
-#include <stdint.h> // for uint32_t
-#include <wayland-client.h> // for wl_list
-
-
-class Fl_Wayland_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
-public:
- struct draw_buffer {
- unsigned char *buffer;
- cairo_t *cairo_;
- size_t data_size; // of wl_buffer and buffer
- int stride;
- int width;
- };
- struct wld_buffer {
- struct draw_buffer draw_buffer;
- struct wl_list link; // links all buffers from the same wl_shm_pool
- struct wl_buffer *wl_buffer;
- void *data;
- struct wl_shm_pool *shm_pool;
- bool draw_buffer_needs_commit;
- bool in_use; // true while being committed
- bool released; // true after buffer_release() was called
- };
- struct wld_shm_pool_data { // one record attached to each wl_shm_pool object
- char *pool_memory; // start of mmap'ed memory encapsulated by the wl_shm_pool
- size_t pool_size; // size of encapsulated memory
- struct wl_list buffers; // to list of fl_wld_buffer's from this pool
- };
- static const uint32_t wld_format;
- static struct wl_shm_pool *current_pool;
- static FL_EXPORT const struct wl_callback_listener *p_surface_frame_listener;
- void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc,
- int srcx, int srcy) FL_OVERRIDE;
- void cache_size(Fl_Image *img, int &width, int &height) FL_OVERRIDE;
- static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true);
- static void create_shm_buffer(wld_buffer *buffer);
- static void buffer_release(struct wld_window *window);
- static void buffer_commit(struct wld_window *window, cairo_region_t *r = NULL);
- static void cairo_init(struct draw_buffer *buffer, int width, int height, int stride,
- cairo_format_t format);
- // used by class Fl_Wayland_Gl_Window_Driver
- static FL_EXPORT struct draw_buffer *offscreen_buffer(Fl_Offscreen);
- static const cairo_user_data_key_t key;
- static Fl_Image_Surface *custom_offscreen(int w, int h, struct wld_buffer **buffer);
-};
-
-#endif // FL_WAYLAND_GRAPHICS_DRIVER_H
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
deleted file mode 100644
index 5c9539a8c..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
+++ /dev/null
@@ -1,310 +0,0 @@
-//
-// Implementation of the Wayland graphics driver.
-//
-// Copyright 2021-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Wayland_Graphics_Driver.H"
-#include "Fl_Wayland_Screen_Driver.H"
-#include "Fl_Wayland_Window_Driver.H"
-#include <FL/Fl_Image_Surface.H>
-#include <sys/mman.h>
-#include <unistd.h> // for close()
-#include <errno.h>
-#include <string.h> // for strerror()
-#include <cairo/cairo.h>
-
-extern "C" {
-# include "../../../libdecor/src/os-compatibility.h" // for libdecor_os_create_anonymous_file()
-}
-
-// used by create_shm_buffer and do_buffer_release
-struct wl_shm_pool *Fl_Wayland_Graphics_Driver::current_pool = NULL;
-
-
-static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *);
-
-
-static void buffer_release_listener(void *user_data, struct wl_buffer *wl_buffer)
-{
- struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer =
- (struct Fl_Wayland_Graphics_Driver::wld_buffer*)user_data;
- buffer->in_use = false;
- if (buffer->released) do_buffer_release(buffer);
-}
-
-
-static const struct wl_buffer_listener buffer_listener = {
- buffer_release_listener
-};
-
-
-void Fl_Wayland_Graphics_Driver::create_shm_buffer(Fl_Wayland_Graphics_Driver::wld_buffer *buffer) {
- int width = buffer->draw_buffer.width;
- int stride = buffer->draw_buffer.stride;
- int height = buffer->draw_buffer.data_size / stride;
- const size_t default_pool_size = 10000000; // larger pools are possible if needed
- int chunk_offset = 0; // offset to start of available memory in pool
- struct wld_shm_pool_data *pool_data = current_pool ? // data record attached to current pool
- (struct wld_shm_pool_data *)wl_shm_pool_get_user_data(current_pool) : NULL;
- size_t pool_size = current_pool ? pool_data->pool_size : default_pool_size; // current pool size
- if (current_pool && !wl_list_empty(&pool_data->buffers)) {
- // last wld_buffer created from current pool
- struct wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link);
- chunk_offset = ((char*)record->data - pool_data->pool_memory) +
- record->draw_buffer.data_size;
- }
- if (!current_pool || chunk_offset + buffer->draw_buffer.data_size > pool_size) {
- // if true, a new pool is needed
- if (current_pool && wl_list_empty(&pool_data->buffers)) {
- wl_shm_pool_destroy(current_pool);
- /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);
-// printf("create_shm_buffer munmap(%p)->%d\n", pool_data->pool_memory, err);
- free(pool_data);
- }
- chunk_offset = 0;
- pool_size = default_pool_size;
- if (buffer->draw_buffer.data_size > pool_size)
- pool_size = 2 * buffer->draw_buffer.data_size; // a larger pool is needed
- int fd = libdecor_os_create_anonymous_file(pool_size);
- if (fd < 0) {
- Fl::fatal("libdecor_os_create_anonymous_file failed: %s\n", strerror(errno));
- }
- pool_data = (struct wld_shm_pool_data*)calloc(1, sizeof(struct wld_shm_pool_data));
- pool_data->pool_memory = (char*)mmap(NULL, pool_size, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
- if (pool_data->pool_memory == MAP_FAILED) {
- close(fd);
- Fl::fatal("mmap failed: %s\n", strerror(errno));
- }
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- current_pool = wl_shm_create_pool(scr_driver->wl_shm, fd, (int32_t)pool_size);
- close(fd); // does not prevent the mmap'ed memory from being used
- //printf("wl_shm_create_pool %p size=%lu\n",pool_data->pool_memory , pool_size);
- pool_data->pool_size = pool_size;
- wl_list_init(&pool_data->buffers);
- wl_shm_pool_set_user_data(current_pool, pool_data);
- }
- buffer->wl_buffer = wl_shm_pool_create_buffer(current_pool, chunk_offset,
- width, height, stride, wld_format);
- wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer);
- // add this buffer to head of list of current pool's buffers
- wl_list_insert(&pool_data->buffers, &buffer->link);
- buffer->shm_pool = current_pool;
- buffer->data = (void*)(pool_data->pool_memory + chunk_offset);
-//fprintf(stderr, "last=%p chunk_offset=%d ", pool_data->buffers.next, chunk_offset);
-//fprintf(stderr, "create_shm_buffer: %dx%d = %d\n", width, height, size);
-}
-
-
-struct Fl_Wayland_Graphics_Driver::wld_buffer *
- Fl_Wayland_Graphics_Driver::create_wld_buffer(int width, int height, bool with_shm) {
- struct wld_buffer *buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer));
- int stride = cairo_format_stride_for_width(cairo_format, width);
- cairo_init(&buffer->draw_buffer, width, height, stride, cairo_format);
- buffer->draw_buffer_needs_commit = true;
- if (with_shm) create_shm_buffer(buffer);
- return buffer;
-}
-
-
-// used to support both normal and progressive drawing and for top-level GL windows
-static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
- struct wld_window *window = (struct wld_window *)data;
- wl_callback_destroy(cb);
- window->frame_cb = NULL;
- if (window->buffer && window->buffer->draw_buffer_needs_commit) {
- Fl_Wayland_Graphics_Driver::buffer_commit(window);
- }
-}
-
-
-static const struct wl_callback_listener surface_frame_listener = {
- .done = surface_frame_done,
-};
-
-
-const struct wl_callback_listener *Fl_Wayland_Graphics_Driver::p_surface_frame_listener =
- &surface_frame_listener;
-
-
-// copy pixels in region r from the Cairo surface to the Wayland buffer
-static void copy_region(struct wld_window *window, cairo_region_t *r) {
- struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = window->buffer;
- float f = Fl::screen_scale(window->fl_win->screen_num());
- int d = Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale();
- int count = cairo_region_num_rectangles(r);
- cairo_rectangle_int_t rect;
- for (int i = 0; i < count; i++) {
- cairo_region_get_rectangle(r, i, &rect);
- int left = d * int(rect.x * f);
- int top = d * int(rect.y * f);
- int right = d * ceil((rect.x + rect.width) * f);
- if (right > d * int(window->fl_win->w() * f)) right = d * int(window->fl_win->w() * f);
- int width = right - left;
- int bottom = d * ceil((rect.y + rect.height) * f);
- if (bottom > d * int(window->fl_win->h() * f)) bottom = d * int(window->fl_win->h() * f);
- int height = bottom - top;
- int offset = top * buffer->draw_buffer.stride + 4 * left;
- int W4 = 4 * width;
- for (int l = 0; l < height; l++) {
- if (offset + W4 >= (int)buffer->draw_buffer.data_size) {
- W4 = buffer->draw_buffer.data_size - offset;
- if (W4 <= 0) break;
- }
- memcpy((uchar*)buffer->data + offset, buffer->draw_buffer.buffer + offset, W4);
- offset += buffer->draw_buffer.stride;
- }
- wl_surface_damage_buffer(window->wl_surface, left, top, width, height);
- }
-}
-
-
-void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, cairo_region_t *r)
-{
- if (!window->buffer->wl_buffer) create_shm_buffer(window->buffer);
- cairo_surface_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_);
- cairo_surface_flush(surf);
- if (r) copy_region(window, r);
- else {
- memcpy(window->buffer->data, window->buffer->draw_buffer.buffer,
- window->buffer->draw_buffer.data_size);
- wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000);
- }
- window->buffer->in_use = true;
- wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0);
- wl_surface_set_buffer_scale( window->wl_surface,
- Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale() );
- if (!window->covered) { // see issue #878
- window->frame_cb = wl_surface_frame(window->wl_surface);
- wl_callback_add_listener(window->frame_cb, p_surface_frame_listener, window);
- }
- wl_surface_commit(window->wl_surface);
- window->buffer->draw_buffer_needs_commit = false;
-}
-
-
-void Fl_Wayland_Graphics_Driver::cairo_init(struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer,
- int width, int height, int stride,
- cairo_format_t format) {
- buffer->data_size = stride * height;
- buffer->stride = stride;
- buffer->buffer = new uchar[buffer->data_size];
- buffer->width = width;
- cairo_surface_t *surf = cairo_image_surface_create_for_data(buffer->buffer, format,
- width, height, stride);
- if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) {
- Fl::fatal("Can't create Cairo surface with cairo_image_surface_create_for_data()\n");
- return;
- }
- buffer->cairo_ = cairo_create(surf);
- cairo_status_t err;
- if ((err = cairo_status(buffer->cairo_)) != CAIRO_STATUS_SUCCESS) {
- Fl::fatal("Cairo error during cairo_create() %s\n", cairo_status_to_string(err));
- return;
- }
- cairo_surface_destroy(surf);
- memset(buffer->buffer, 0, buffer->data_size); // useful for transparent windows
- cairo_set_source_rgba(buffer->cairo_, .0, .0, .0, 1.0); // Black default color
- cairo_save(buffer->cairo_);
-}
-
-
-// runs when buffer->in_use is false and buffer->released is true
-static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer) {
- struct wl_shm_pool *my_pool = buffer->shm_pool;
- if (buffer->wl_buffer) {
- struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data *pool_data =
- (struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data*)
- wl_shm_pool_get_user_data(my_pool);
- wl_buffer_destroy(buffer->wl_buffer);
- // remove wld_buffer from list of pool's buffers
- wl_list_remove(&buffer->link);
- if (wl_list_empty(&pool_data->buffers) && my_pool != Fl_Wayland_Graphics_Driver::current_pool) {
- // all buffers from pool are gone
- wl_shm_pool_destroy(my_pool);
- /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);
- //printf("do_buffer_release munmap(%p)->%d\n", pool_data->pool_memory, err);
- free(pool_data);
- }
- }
- free(buffer);
-}
-
-
-void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window)
-{
- if (window->buffer && !window->buffer->released) {
- window->buffer->released = true;
- if (window->frame_cb) { wl_callback_destroy(window->frame_cb); window->frame_cb = NULL; }
- delete[] window->buffer->draw_buffer.buffer;
- window->buffer->draw_buffer.buffer = NULL;
- cairo_destroy(window->buffer->draw_buffer.cairo_);
- if (!window->buffer->in_use) do_buffer_release(window->buffer);
- window->buffer = NULL;
- }
-}
-
-
-// this refers to the same memory layout for pixel data as does CAIRO_FORMAT_ARGB32
-const uint32_t Fl_Wayland_Graphics_Driver::wld_format = WL_SHM_FORMAT_ARGB8888;
-
-
-void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h,
- Fl_Offscreen src, int srcx, int srcy) {
- // draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of
- // the graphics driver's surface
- cairo_matrix_t matrix;
- cairo_get_matrix(cairo_, &matrix);
- double s = matrix.xx;
- cairo_save(cairo_);
- cairo_rectangle(cairo_, x - 0.5, y - 0.5, w, h);
- cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE);
- cairo_clip(cairo_);
- cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT);
- cairo_surface_t *surf = cairo_get_target((cairo_t *)src);
- cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
- cairo_set_source(cairo_, pat);
- cairo_matrix_init_scale(&matrix, s, s);
- cairo_matrix_translate(&matrix, -(x - srcx), -(y - srcy));
- cairo_pattern_set_matrix(pat, &matrix);
- cairo_paint(cairo_);
- cairo_pattern_destroy(pat);
- cairo_restore(cairo_);
- surface_needs_commit();
-}
-
-
-const cairo_user_data_key_t Fl_Wayland_Graphics_Driver::key = {};
-
-
-struct Fl_Wayland_Graphics_Driver::draw_buffer*
-Fl_Wayland_Graphics_Driver::offscreen_buffer(Fl_Offscreen offscreen) {
- return (struct draw_buffer*)cairo_get_user_data((cairo_t*)offscreen, &key);
-}
-
-
-Fl_Image_Surface *Fl_Wayland_Graphics_Driver::custom_offscreen(int w, int h,
- struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off) {
- struct wld_buffer *off = create_wld_buffer(w, h);
- *p_off = off;
- cairo_set_user_data(off->draw_buffer.cairo_, &key, &off->draw_buffer, NULL);
- return new Fl_Image_Surface(w, h, 0, (Fl_Offscreen)off->draw_buffer.cairo_);
-}
-
-
-void Fl_Wayland_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) {
- Fl_Graphics_Driver::cache_size(img, width, height);
- width *= wld_scale;
- height *= wld_scale;
-}
diff --git a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H b/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H
deleted file mode 100644
index ae32ac3df..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_WAYLAND_IMAGE_SURFACE_DRIVER_H
-#define FL_WAYLAND_IMAGE_SURFACE_DRIVER_H
-
-#include <FL/Fl_Image_Surface.H>
-
-class Fl_Wayland_Image_Surface_Driver : public Fl_Image_Surface_Driver {
- void end_current() FL_OVERRIDE;
- struct wld_window *pre_window;
-public:
- Fl_Wayland_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off);
- ~Fl_Wayland_Image_Surface_Driver();
- void mask(const Fl_RGB_Image *) FL_OVERRIDE;
- struct shape_data_type {
- double scale;
- cairo_pattern_t *mask_pattern_;
- cairo_t *bg_cr;
- } *shape_data_;
- void set_current() FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate() FL_OVERRIDE;
- Fl_RGB_Image *image() FL_OVERRIDE;
-};
-
-#endif // FL_WAYLAND_IMAGE_SURFACE_DRIVER_H
diff --git a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx
deleted file mode 100644
index ec9c56cb7..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx
+++ /dev/null
@@ -1,185 +0,0 @@
-//
-// Draw-to-image code for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/platform.H>
-#include "Fl_Wayland_Graphics_Driver.H"
-#include "Fl_Wayland_Window_Driver.H"
-#include "Fl_Wayland_Image_Surface_Driver.H"
-
-
-Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h,
- int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
- shape_data_ = NULL;
- float s = 1;
- int d = 1;
- if (!off) {
- fl_open_display();
- if (Fl::first_window()) {
- d = Fl_Wayland_Window_Driver::driver(Fl::first_window())->wld_scale();
- }
- s = Fl_Graphics_Driver::default_driver().scale();
- if (d*s != 1 && high_res) {
- w = int(w * s) * d;
- h = int(h * s) * d;
- }
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ =
- (struct Fl_Wayland_Graphics_Driver::draw_buffer*)calloc(1,
- sizeof(struct Fl_Wayland_Graphics_Driver::draw_buffer));
- Fl_Wayland_Graphics_Driver::cairo_init(off_, w, h,
- cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w), CAIRO_FORMAT_RGB24);
- offscreen = (Fl_Offscreen)off_->cairo_;
- cairo_set_user_data(off_->cairo_, &Fl_Wayland_Graphics_Driver::key, off_, NULL);
- if (d*s != 1 && high_res) cairo_scale((cairo_t*)offscreen, d*s, d*s);
- }
- driver(new Fl_Wayland_Graphics_Driver());
- if (d*s != 1 && high_res) driver()->scale(d*s);
-}
-
-
-Fl_Wayland_Image_Surface_Driver::~Fl_Wayland_Image_Surface_Driver() {
- if (shape_data_) {
- cairo_surface_t *surf;
- cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf);
- unsigned char *bits = cairo_image_surface_get_data(surf);
- cairo_pattern_destroy(shape_data_->mask_pattern_);
- delete[] bits;
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ =
- Fl_Wayland_Graphics_Driver::offscreen_buffer((Fl_Offscreen)shape_data_->bg_cr);
- delete[] off_->buffer;
- free(off_);
- cairo_destroy(shape_data_->bg_cr);
- free(shape_data_);
- }
- if (offscreen && !external_offscreen) {
- struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer =
- Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen);
- cairo_destroy((cairo_t *)offscreen);
- delete[] buffer->buffer;
- free(buffer);
- }
- delete driver();
-}
-
-
-void Fl_Wayland_Image_Surface_Driver::set_current() {
- Fl_Surface_Device::set_current();
- Fl_Cairo_Graphics_Driver *dr = (Fl_Cairo_Graphics_Driver*)driver();
- if (!dr->cr()) dr->set_cairo((cairo_t*)offscreen);
- pre_window = Fl_Wayland_Window_Driver::wld_window;
- Fl_Wayland_Window_Driver::wld_window = NULL;
- fl_window = 0;
-}
-
-
-void Fl_Wayland_Image_Surface_Driver::end_current() {
- cairo_surface_t *surf = cairo_get_target((cairo_t*)offscreen);
- cairo_surface_flush(surf);
- Fl_Wayland_Window_Driver::wld_window = pre_window;
- fl_window = (Window)pre_window;
- Fl_Surface_Device::end_current();
-}
-
-
-void Fl_Wayland_Image_Surface_Driver::translate(int x, int y) {
- ((Fl_Wayland_Graphics_Driver*)driver())->ps_translate(x, y);
-}
-
-
-void Fl_Wayland_Image_Surface_Driver::untranslate() {
- ((Fl_Wayland_Graphics_Driver*)driver())->ps_untranslate();
-}
-
-
-Fl_RGB_Image* Fl_Wayland_Image_Surface_Driver::image() {
- if (shape_data_ && shape_data_->mask_pattern_) {
- // draw above the secondary offscreen the main offscreen masked by mask_pattern_
- cairo_t *c = ((Fl_Cairo_Graphics_Driver*)driver())->cr();
- cairo_pattern_t *paint_pattern = cairo_pattern_create_for_surface(cairo_get_target(c));
- cairo_set_source(shape_data_->bg_cr, paint_pattern);
- cairo_mask(shape_data_->bg_cr, shape_data_->mask_pattern_);
- cairo_pattern_destroy(paint_pattern);
- // copy secondary offscreen to the main offscreen
- cairo_pattern_t *pat = cairo_pattern_create_for_surface(cairo_get_target(shape_data_->bg_cr));
- cairo_scale(c, shape_data_->scale, shape_data_->scale);
- cairo_set_source(c, pat),
- cairo_paint(c);
- cairo_pattern_destroy(pat);
- // delete secondary offscreen
- cairo_surface_t *surf;
- cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf);
- unsigned char *bits = cairo_image_surface_get_data(surf);
- cairo_pattern_destroy(shape_data_->mask_pattern_);
- delete[] bits;
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ =
- Fl_Wayland_Graphics_Driver::offscreen_buffer((Fl_Offscreen)shape_data_->bg_cr);
- delete[] off_->buffer;
- free(off_);
- cairo_destroy(shape_data_->bg_cr);
- free(shape_data_);
- shape_data_ = NULL;
- }
-
- // Convert depth-4 image in draw_buffer to a depth-3 image while exchanging R and B colors
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf =
- Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen);
- int height = int(off_buf->data_size / off_buf->stride);
- uchar *rgb = new uchar[off_buf->width * height * 3];
- uchar *p = rgb;
- uchar *q;
- for (int j = 0; j < height; j++) {
- q = off_buf->buffer + j*off_buf->stride;
- for (int i = 0; i < off_buf->width; i++) { // exchange R and B colors, transmit G
- *p = *(q+2);
- *(p+1) = *(q+1);
- *(p+2) = *q;
- p += 3; q += 4;
- }
- }
- Fl_RGB_Image *image = new Fl_RGB_Image(rgb, off_buf->width, height, 3);
- image->alloc_array = 1;
- return image;
-}
-
-
-void Fl_Wayland_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) {
- bool using_copy = false;
- shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type));
- int W, H;
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf =
- Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen);
- W = off_buf->width;
- H = (int)(off_buf->data_size / off_buf->stride);
- if (W != mask->data_w() || H != mask->data_h()) {
- Fl_RGB_Image *copy = (Fl_RGB_Image*)mask->copy(W, H);
- mask = copy;
- using_copy = true;
- }
- shape_data_->mask_pattern_ = Fl_Cairo_Graphics_Driver::calc_cairo_mask(mask);
- //duplicate current offscreen content to new cairo_t* shape_data_->bg_cr
- int width, height;
- printable_rect(&width, &height);
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ =
- (struct Fl_Wayland_Graphics_Driver::draw_buffer*)calloc(1,
- sizeof(struct Fl_Wayland_Graphics_Driver::draw_buffer));
- Fl_Wayland_Graphics_Driver::cairo_init(off_, W, H,
- cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, W),
- CAIRO_FORMAT_RGB24);
- cairo_set_user_data(off_->cairo_, &Fl_Wayland_Graphics_Driver::key, off_, NULL);
- shape_data_->bg_cr = off_->cairo_;
- memcpy(off_->buffer, off_buf->buffer, off_buf->data_size);
- shape_data_->scale = double(width) / W;
- if (using_copy) delete mask;
-}
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
deleted file mode 100644
index 83efd79a3..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
+++ /dev/null
@@ -1,193 +0,0 @@
-//
-// Definition of the Wayland Screen interface
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Wayland_Screen_Driver.H
- \brief Definition of Wayland Screen interface
- */
-
-#ifndef FL_WAYLAND_SCREEN_DRIVER_H
-#define FL_WAYLAND_SCREEN_DRIVER_H
-
-#include <config.h>
-#include "../Unix/Fl_Unix_Screen_Driver.H"
-#include <wayland-client.h>
-
-class Fl_Window;
-
-class Fl_Wayland_Screen_Driver : public Fl_Unix_Screen_Driver
-{
-private:
- static int insertion_point_x;
- static int insertion_point_y;
- static int insertion_point_width;
- static int insertion_point_height;
- static bool insertion_point_location_is_valid;
-public:
-// type definitions
- typedef enum {unspecified, MUTTER, WESTON, KWIN, OWL, WAYFIRE} compositor_name;
- struct seat {
- struct wl_seat *wl_seat;
- struct wl_pointer *wl_pointer;
- struct wl_keyboard *wl_keyboard;
- uint32_t keyboard_enter_serial;
- struct wl_surface *keyboard_surface;
- struct wl_list pointer_outputs;
- struct wl_cursor_theme *cursor_theme;
- struct wl_cursor *default_cursor;
- struct wl_surface *cursor_surface;
- struct wl_surface *pointer_focus;
- int pointer_scale;
- uint32_t serial;
- uint32_t pointer_enter_serial;
- struct wl_data_device_manager *data_device_manager;
- struct wl_data_device *data_device;
- struct wl_data_source *data_source;
- struct xkb_state *xkb_state;
- struct xkb_context *xkb_context;
- struct xkb_keymap *xkb_keymap;
- struct xkb_compose_state *xkb_compose_state;
- char *name;
- struct zwp_text_input_v3 *text_input;
- struct gtk_shell1 *gtk_shell;
- };
- struct output { // one record for each screen
- uint32_t id;
- int x, y; // logical position of screen
- int pixel_width; // in pixels
- int pixel_height; // in pixels
- int width; // in pixels, account for fractional scaling
- int height; // in pixels, account for fractional scaling
- float dpi;
- struct wl_output *wl_output;
- int wld_scale; // Wayland scale factor
- float gui_scale; // FLTK scale factor
- bool done;
- struct wl_list link;
- };
- enum cursor_shapes {arrow = 0, wait, insert, hand, help, cross, move,
- north, south, west, east, north_south, west_east, south_west, south_east, north_east, north_west, nesw, nwse};
- static const int cursor_count = nwse + 1; // nber of elements of 'enum cursor_shapes'
-
-// static member variables
- static FL_EXPORT struct wl_display *wl_display;
- static const struct wl_data_device_listener *p_data_device_listener;
- // next length of marked text after current marked text will have been replaced
- static int next_marked_length;
- static compositor_name compositor; // identifies the used Wayland compositor
-
-// static member functions
- static void insertion_point_location(int x, int y, int height);
- static bool insertion_point_location(int *px, int *py, int *pwidth, int *pheight);
- static bool own_output(struct wl_output *output);
- static void do_set_cursor(struct Fl_Wayland_Screen_Driver::seat *,
- struct wl_cursor *wl_cursor = NULL, Fl_Cursor c = FL_CURSOR_NONE);
-// member variables
- struct wl_cursor *xc_cursor[cursor_count]; // one for each element of enum cursor_shapes
- struct wl_registry *wl_registry;
- struct wl_compositor *wl_compositor;
- struct wl_subcompositor *wl_subcompositor;
- struct wl_shm *wl_shm;
- struct seat *seat;
- struct wl_list outputs; // linked list of struct output records for all screens in system
- struct libdecor *libdecor_context;
- struct xdg_wm_base *xdg_wm_base;
- struct zwp_text_input_manager_v3 *text_input_base;
-#if HAVE_XDG_DIALOG
- struct xdg_wm_dialog_v1 *xdg_wm_dialog;
-#endif
-#if HAVE_CURSOR_SHAPE
- struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager;
- struct wp_cursor_shape_device_v1 *wp_cursor_shape_device;
-#endif
-
-// constructor
- Fl_Wayland_Screen_Driver();
-
-// overridden functions from parent class Fl_Screen_Driver
- APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { return PER_SCREEN_APP_SCALING; }
- float scale(int n) FL_OVERRIDE;
- void scale(int n, float f) FL_OVERRIDE;
- // --- screen configuration
- void init() FL_OVERRIDE;
- int x() FL_OVERRIDE;
- int y() FL_OVERRIDE;
- int w() FL_OVERRIDE;
- int h() FL_OVERRIDE;
- void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE;
- void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE;
- void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE;
- // --- audible output
- void beep(int type) FL_OVERRIDE;
- // --- global events
- void flush() FL_OVERRIDE;
- void grab(Fl_Window* win) FL_OVERRIDE;
- // --- global colors
- void get_system_colors() FL_OVERRIDE;
- // this one is in fl_wayland_clipboard_dnd.cxx
- int dnd(int unused) FL_OVERRIDE;
- int compose(int &del) FL_OVERRIDE;
- void compose_reset() FL_OVERRIDE;
- Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win,
- bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE;
- int get_mouse(int &x, int &y) FL_OVERRIDE;
- void open_display_platform() FL_OVERRIDE;
- void close_display() FL_OVERRIDE;
- void display(const char *d) FL_OVERRIDE;
- // --- compute dimensions of an Fl_Offscreen
- void offscreen_size(Fl_Offscreen o, int &width, int &height) FL_OVERRIDE;
- int has_marked_text() const FL_OVERRIDE;
- // --- clipboard operations
- // this one is in fl_wayland_clipboard_dnd.cxx
- void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE;
- // this one is in fl_wayland_clipboard_dnd.cxx
- void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE;
- // this one is in fl_wayland_clipboard_dnd.cxx
- int clipboard_contains(const char *type) FL_OVERRIDE;
- void set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win) FL_OVERRIDE;
- void reset_spot() FL_OVERRIDE;
- void *control_maximize_button(void *data) FL_OVERRIDE;
- int event_key(int k) FL_OVERRIDE;
- int get_key(int k) FL_OVERRIDE;
- void enable_im() FL_OVERRIDE;
- void disable_im() FL_OVERRIDE;
- bool screen_boundaries_known() FL_OVERRIDE { return false; }
- float base_scale(int numscreen) FL_OVERRIDE;
-
- // overridden functions from parent class Fl_Unix_Screen_Driver
- int poll_or_select_with_delay(double time_to_wait) FL_OVERRIDE;
- int poll_or_select() FL_OVERRIDE;
-
-// Wayland-specific member functions
- void screen_count_set(int count) {num_screens = count;}
- int screen_count_get() {return num_screens;}
- void reset_cursor();
- // this one is in fl_wayland_clipboard_dnd.cxx
- void copy_image(const unsigned char* data, int W, int H);
- void init_workarea();
- void set_cursor();
- struct wl_cursor *default_cursor();
- void default_cursor(struct wl_cursor *cursor);
- struct wl_cursor *cache_cursor(const char *cursor_name);
- uint32_t get_serial();
- struct wl_seat *get_wl_seat();
- char *get_seat_name();
- struct xkb_keymap *get_xkb_keymap();
-};
-
-
-#endif // FL_WAYLAND_SCREEN_DRIVER_H
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
deleted file mode 100644
index 9199f3a5f..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
+++ /dev/null
@@ -1,2204 +0,0 @@
-//
-// Implementation of Wayland Screen interface
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "Fl_Wayland_Screen_Driver.H"
-#include "Fl_Wayland_Window_Driver.H"
-#include "Fl_Wayland_Graphics_Driver.H"
-#include "../../Fl_Scalable_Graphics_Driver.H"
-#include <wayland-cursor.h>
-#include "../../../libdecor/build/fl_libdecor.h"
-#include "xdg-shell-client-protocol.h"
-#include "../Posix/Fl_Posix_System_Driver.H"
-#include <FL/Fl.H>
-#include <FL/Fl_Image_Surface.H>
-#include <FL/platform.H>
-#include <FL/fl_ask.H>
-#include <FL/filename.H>
-#include <vector>
-#include "../../print_button.h"
-#include <dlfcn.h>
-#include <linux/input.h>
-#include <stdlib.h>
-#include <xkbcommon/xkbcommon.h>
-#include <xkbcommon/xkbcommon-compose.h>
-#include "text-input-client-protocol.h"
-#include "gtk-shell-client-protocol.h"
-#if HAVE_XDG_DIALOG
-# include "xdg-dialog-client-protocol.h"
-#endif
-#if HAVE_CURSOR_SHAPE
-# include "cursor-shape-client-protocol.h"
-#endif
-#include <assert.h>
-#include <sys/mman.h>
-#include <poll.h>
-#include <errno.h>
-#include <string.h> // for strerror()
-#include <map>
-extern "C" {
- bool libdecor_get_cursor_settings(char **theme, int *size);
- bool fl_is_surface_from_GTK_titlebar (struct wl_surface *surface, struct libdecor_frame *frame,
- bool *using_GTK);
-}
-
-// set this to 1 for keyboard debug output, 0 for no debug output
-#define DEBUG_KEYBOARD 0
-
-#define fl_max(a,b) ((a) > (b) ? (a) : (b))
-#define fl_min(a,b) ((a) < (b) ? (a) : (b))
-
-struct pointer_output {
- Fl_Wayland_Screen_Driver::output* output;
- struct wl_list link;
-};
-
-/* Implementation note:
-
-- About CSD and SSD :
- * Mutter and Weston use CSD (client-side decoration) which means that libdecor.so draws all window
- titlebars and responds to resize, minimization and maximization events.
- * KWin uses SSD (server-side decoration) which means the OS draws titlebars according to its own rules
- and triggers resize, minimization and maximization events.
-
-- Function registry_handle_global() runs within fl_open_display() and sets public static variable
- Fl_Wayland_Screen_Driver::compositor to either Fl_Wayland_Screen_Driver::MUTTER, ::WESTON, or ::KWIN.
-
-- Specific operations for WESTON:
- * When a libdecor-framed window is minimized under Weston, the frame remains on display. To avoid
- that, function libdecor_frame_set_minimized() is modified so it turns off the frame's visibility, with
- function libdecor_frame_set_visibility(), when the window is minimized. That's implemented in file
- libdecor/build/fl_libdecor.c. The modified libdecor_frame_set_minimized() function, part of libdecor.so,
- needs access to variable Fl_Wayland_Screen_Driver::compositor, part of libfltk.a. This is achieved
- calling FLTK function fl_libdecor_using_weston() which returns whether the running compositor
- is Weston. This Weston bug has been corrected in Weston version 10. Thus, this special processing
- is not performed when Weston version is ≥ 10.
-
-- Support of Fl_Window::border(int) :
- FLTK uses libdecor_frame_set_visibility() to show or hide a toplevel window's frame. This doesn't work
- with KWin which uses Server-Side Decoration. In that case, FLTK hides and re-shows the window to toggle
- between presence and absence of a window's frame.
-*/
-
-
-static std::vector<int> key_vector; // used by Fl_Wayland_Screen_Driver::event_key()
-static struct wl_surface *gtk_shell_surface = NULL;
-
-Fl_Wayland_Screen_Driver::compositor_name Fl_Wayland_Screen_Driver::compositor =
- Fl_Wayland_Screen_Driver::unspecified;
-
-
-extern "C" {
- bool fl_libdecor_using_weston(void) {
- return Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::WESTON;
- }
-}
-
-
-static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
-{
- xdg_wm_base_pong(xdg_wm_base, serial);
-}
-
-
-static const struct xdg_wm_base_listener xdg_wm_base_listener = {
- .ping = xdg_wm_base_ping,
-};
-
-
-// these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx
-extern const char *fl_fg;
-extern const char *fl_bg;
-extern const char *fl_bg2;
-// end of extern additions workaround
-
-
-void Fl_Wayland_Screen_Driver::do_set_cursor(
- struct Fl_Wayland_Screen_Driver::seat *seat, struct wl_cursor *wl_cursor, Fl_Cursor cursor) {
- /*
- wl_cursor: when non-NULL means a custom cursor;
- when NULL:
- - with "Cursor shape" protocol, cursor is meaningful if != FL_CURSOR_NONE;
- - with old-school cursors, seat->default_cursor gives the desired cursor.
- cursor: used with "Cursor shape" protocol for enumerated cursor shape, otherwise equal to FL_CURSOR_NONE
- */
- struct wl_cursor_image *image;
- struct wl_buffer *buffer;
- const int scale = seat->pointer_scale;
-
-#if HAVE_CURSOR_SHAPE
- static std::map<int, int> cursor_shape_map = {
- {FL_CURSOR_DEFAULT, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT },
- {FL_CURSOR_ARROW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT },
- {FL_CURSOR_CROSS, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR },
- {FL_CURSOR_WAIT, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT },
- {FL_CURSOR_INSERT, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT },
- {FL_CURSOR_HAND, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB },
- {FL_CURSOR_HELP, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP },
- {FL_CURSOR_MOVE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE },
- {FL_CURSOR_N, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE },
- {FL_CURSOR_E, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE },
- {FL_CURSOR_W, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE },
- {FL_CURSOR_S, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE },
- {FL_CURSOR_NS, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE },
- {FL_CURSOR_WE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE },
- {FL_CURSOR_SW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE },
- {FL_CURSOR_SE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE },
- {FL_CURSOR_NE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE },
- {FL_CURSOR_NW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE },
- {FL_CURSOR_NESW, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE },
- {FL_CURSOR_NWSE, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE }
- };
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->wp_cursor_shape_device && !wl_cursor) {
- if (cursor != FL_CURSOR_NONE) wp_cursor_shape_device_v1_set_shape(
- scr_driver->wp_cursor_shape_device, seat->pointer_enter_serial, cursor_shape_map[cursor]);
- return;
- }
-#endif
-
- if ((!seat->cursor_theme && !wl_cursor) || !seat->wl_pointer)
- return;
-
- if (!wl_cursor) wl_cursor = seat->default_cursor;
- image = wl_cursor->images[0];
- buffer = wl_cursor_image_get_buffer(image);
- wl_pointer_set_cursor(seat->wl_pointer, seat->pointer_enter_serial,
- seat->cursor_surface,
- image->hotspot_x / scale,
- image->hotspot_y / scale);
- wl_surface_attach(seat->cursor_surface, buffer, 0, 0);
- wl_surface_set_buffer_scale(seat->cursor_surface, scale);
- wl_surface_damage_buffer(seat->cursor_surface, 0, 0,
- image->width, image->height);
- wl_surface_commit(seat->cursor_surface);
-}
-
-
-static uint32_t ptime;
-static uint32_t wld_event_time;
-static int px, py;
-
-
-static void set_event_xy(Fl_Window *win) {
- // turn off is_click if enough time or mouse movement has passed:
- if (abs(Fl::e_x_root-px)+abs(Fl::e_y_root-py) > 3 ||
- wld_event_time >= ptime+1000) {
- Fl::e_is_click = 0;
-//fprintf(stderr, "Fl::e_is_click = 0\n");
- }
-}
-
-
-// if this is same event as last && is_click, increment click count:
-static inline void checkdouble() {
- if (Fl::e_is_click == Fl::e_keysym) {
- Fl::e_clicks++;
-//fprintf(stderr, "Fl::e_clicks = %d\n", Fl::e_clicks);
- } else {
- Fl::e_clicks = 0;
- Fl::e_is_click = Fl::e_keysym;
-//fprintf(stderr, "Fl::e_is_click = %d\n", Fl::e_is_click);
- }
- px = Fl::e_x_root;
- py = Fl::e_y_root;
- ptime = wld_event_time;
-}
-
-
-struct wl_display *Fl_Wayland_Screen_Driver::wl_display = NULL;
-
-
-static Fl_Window *event_coords_from_surface(struct wl_surface *surface,
- wl_fixed_t surface_x, wl_fixed_t surface_y) {
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
- if (!win) return NULL;
- int delta_x = 0, delta_y = 0;
- while (win->parent()) {
- delta_x += win->x();
- delta_y += win->y();
- win = win->window();
- }
- float f = Fl::screen_scale(win->screen_num());
- Fl::e_x = wl_fixed_to_int(surface_x) / f + delta_x;
- Fl::e_x_root = Fl::e_x + win->x();
- Fl::e_y = wl_fixed_to_int(surface_y) / f + delta_y;
- int *poffset = Fl_Window_Driver::menu_offset_y(win);
- if (poffset) Fl::e_y -= *poffset;
- Fl::e_y_root = Fl::e_y + win->y();
- return win;
-}
-
-static Fl_Window *need_leave = NULL;
-
-static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
- struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
- struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data;
- Fl_Window *win = event_coords_from_surface(surface, surface_x, surface_y);
- static bool using_GTK = seat->gtk_shell &&
- (gtk_shell1_get_version(seat->gtk_shell) >= GTK_SURFACE1_TITLEBAR_GESTURE_SINCE_VERSION);
- if (!win && using_GTK) {
- // check whether surface is the headerbar of a GTK-decorated window
- Fl_X *xp = Fl_X::first;
- while (xp && using_GTK) { // all mapped windows
- struct wld_window *xid = (struct wld_window*)xp->xid;
- if (xid->kind == Fl_Wayland_Window_Driver::DECORATED &&
- fl_is_surface_from_GTK_titlebar(surface, xid->frame, &using_GTK)) {
- gtk_shell_surface = surface;
- break;
- }
- xp = xp->next;
- }
- }
- if (!win) return;
- //fprintf(stderr, "pointer_enter window=%p\n", Fl_Wayland_Window_Driver::surface_to_window(surface));
- seat->pointer_focus = surface;
- // use custom cursor if present
- struct wl_cursor *cursor =
- fl_wl_xid(win)->custom_cursor ? fl_wl_xid(win)->custom_cursor->wl_cursor : NULL;
- seat->serial = serial;
- seat->pointer_enter_serial = serial;
- Fl_Wayland_Screen_Driver::do_set_cursor(seat, cursor, Fl_Wayland_Window_Driver::driver(win)->standard_cursor());
- set_event_xy(win);
- need_leave = NULL;
- win = Fl_Wayland_Window_Driver::surface_to_window(surface);
- // Caution: with an Fl_Tooltip this call can hide the window being entered (#1317)
- if (!win->parent()) Fl::handle(FL_ENTER, win);
-}
-
-
-static void pointer_leave(void *data, struct wl_pointer *wl_pointer,
- uint32_t serial, struct wl_surface *surface) {
- struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data;
- if (seat->pointer_focus == surface) seat->pointer_focus = NULL;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
- gtk_shell_surface = NULL;
- if (win) {
- //fprintf(stderr, "pointer_leave window=%p [%s]\n", win, (win->parent()?"sub":"top"));
- set_event_xy(win);
- need_leave = win->top_window(); // we leave a sub or toplevel window
- wl_display_roundtrip(fl_wl_display()); // pointer_enter to other win, if applicable, will run
- if (need_leave) { // we really left the sub-or-top win and did not enter another
- extern Fl_Window *fl_xmousewin;
- fl_xmousewin = 0;
- Fl::handle(FL_LEAVE, need_leave);
- }
- }
-}
-
-
-static void pointer_motion(void *data, struct wl_pointer *wl_pointer,
- uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- Fl_Window *win = event_coords_from_surface(seat->pointer_focus, surface_x, surface_y);
- if (!win) return;
- if (Fl::grab() && !Fl::grab()->menu_window() && Fl::grab() != win) {
- // If there's an active, non-menu grab() and the pointer is in a window other than
- // the grab(), make e_x_root too large to be in any window
- Fl::e_x_root = 1000000;
- }
- else if (Fl_Window_Driver::menu_parent(NULL) && // any kind of menu is active now, and
- !win->menu_window() && // we enter a non-menu window
- win != Fl_Window_Driver::menu_parent(NULL) // that's not the window below the menu
- ) {
- Fl::e_x_root = 1000000; // make it too large to be in any window
- }
-//fprintf(stderr, "FL_MOVE on win=%p to x:%dx%d root:%dx%d\n", win, Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root);
- wld_event_time = time;
- set_event_xy(win);
- Fl::handle(FL_MOVE, win);
-}
-
-
-//#include <FL/names.h>
-static void pointer_button(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- uint32_t time,
- uint32_t button,
- uint32_t state)
-{
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- if (gtk_shell_surface && state == WL_POINTER_BUTTON_STATE_PRESSED &&
- button == BTN_MIDDLE) {
- struct gtk_surface1 *gtk_surface = gtk_shell1_get_gtk_surface(seat->gtk_shell,gtk_shell_surface);
- gtk_surface1_titlebar_gesture(gtk_surface, serial, seat->wl_seat,
- GTK_SURFACE1_GESTURE_MIDDLE_CLICK);
- gtk_surface1_release(gtk_surface); // very necessary
- return;
- }
- seat->serial = serial;
- int event = 0;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(seat->pointer_focus);
- if (!win) return;
- win = win->top_window();
- wld_event_time = time;
- int b = 0;
- // Fl::e_state &= ~FL_BUTTONS; // DO NOT reset the mouse button state!
- if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
- if (button == BTN_LEFT) { Fl::e_state |= FL_BUTTON1; b = 1; }
- else if (button == BTN_RIGHT) { Fl::e_state |= FL_BUTTON3; b = 3; }
- else if (button == BTN_MIDDLE) { Fl::e_state |= FL_BUTTON2; b = 2; }
- else if (button == BTN_BACK) { Fl::e_state |= FL_BUTTON4; b = 4; } // ?
- else if (button == BTN_SIDE) { Fl::e_state |= FL_BUTTON4; b = 4; } // OK: Debian 12
- else if (button == BTN_FORWARD) { Fl::e_state |= FL_BUTTON5; b = 5; } // ?
- else if (button == BTN_EXTRA) { Fl::e_state |= FL_BUTTON5; b = 5; } // OK: Debian 12
- } else { // must be WL_POINTER_BUTTON_STATE_RELEASED
- if (button == BTN_LEFT) { Fl::e_state &= ~FL_BUTTON1; b = 1; }
- else if (button == BTN_RIGHT) { Fl::e_state &= ~FL_BUTTON3; b = 3; }
- else if (button == BTN_MIDDLE) { Fl::e_state &= ~FL_BUTTON2; b = 2; }
- else if (button == BTN_BACK) { Fl::e_state &= ~FL_BUTTON4; b = 4; } // ?
- else if (button == BTN_SIDE) { Fl::e_state &= ~FL_BUTTON4; b = 4; } // OK: Debian 12
- else if (button == BTN_FORWARD) { Fl::e_state &= ~FL_BUTTON5; b = 5; } // ?
- else if (button == BTN_EXTRA) { Fl::e_state &= ~FL_BUTTON5; b = 5; } // OK: Debian 12
- }
- Fl::e_keysym = FL_Button + b;
- Fl::e_dx = Fl::e_dy = 0;
-
- set_event_xy(win);
- if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
- event = FL_PUSH;
- checkdouble();
- } else if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
- event = FL_RELEASE;
- }
- // fprintf(stderr, "%s %s\n", fl_eventnames[event], win->label() ? win->label():"[]");
- Fl::handle(event, win);
-}
-
-
-static void pointer_axis(void *data, struct wl_pointer *wl_pointer,
- uint32_t time, uint32_t axis, wl_fixed_t value) {
- struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(seat->pointer_focus);
- if (!win) return;
- wld_event_time = time;
- int delta = wl_fixed_to_int(value);
- if (abs(delta) >= 10) delta /= 10;
- // fprintf(stderr, "FL_MOUSEWHEEL: %c delta=%d\n", axis==WL_POINTER_AXIS_HORIZONTAL_SCROLL?'H':'V', delta);
- // allow both horizontal and vertical movements to be processed by the widget
- if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
- if (Fl::event_shift()) { // shift key pressed: send vertical mousewheel event
- Fl::e_dx = 0;
- Fl::e_dy = delta;
- } else { // shift key not pressed (normal behavior): send horizontal mousewheel event
- Fl::e_dx = delta;
- Fl::e_dy = 0;
- }
- Fl::handle(FL_MOUSEWHEEL, win->top_window());
- }
- if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
- if (Fl::event_shift()) { // shift key pressed: send horizontal mousewheel event
- Fl::e_dx = delta;
- Fl::e_dy = 0;
- } else {// shift key not pressed (normal behavior): send vertical mousewheel event
- Fl::e_dx = 0;
- Fl::e_dy = delta;
- }
- Fl::handle(FL_MOUSEWHEEL, win->top_window());
- }
-}
-
-
-static struct wl_pointer_listener pointer_listener = {
- pointer_enter,
- pointer_leave,
- pointer_motion,
- pointer_button,
- pointer_axis
-};
-
-
-static const char *proxy_tag = "FLTK for Wayland";
-
-
-bool Fl_Wayland_Screen_Driver::own_output(struct wl_output *output)
-{
- return wl_proxy_get_tag((struct wl_proxy *)output) == &proxy_tag;
-}
-
-
-static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat);
-
-
-static void try_update_cursor(struct Fl_Wayland_Screen_Driver::seat *seat) {
- if (wl_list_empty(&seat->pointer_outputs)) return;
- struct pointer_output *pointer_output;
- int scale = 1;
-
- wl_list_for_each(pointer_output, &seat->pointer_outputs, link) {
- scale = fl_max(scale, pointer_output->output->wld_scale);
- }
-
- if (scale != seat->pointer_scale) {
- seat->pointer_scale = scale;
- init_cursors(seat);
- Fl_Wayland_Screen_Driver::do_set_cursor(seat);
- }
-}
-
-
-static void output_scale(void *data, struct wl_output *wl_output, int32_t factor);
-
-
-static void cursor_surface_enter(void *data,
- struct wl_surface *wl_surface, struct wl_output *wl_output) {
- // Runs when the seat's cursor_surface enters a display
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- struct pointer_output *pointer_output;
-
- if (!Fl_Wayland_Screen_Driver::own_output(wl_output))
- return;
-
- pointer_output = (struct pointer_output *)calloc(1, sizeof(struct pointer_output));
- pointer_output->output =
- (Fl_Wayland_Screen_Driver::output *)wl_output_get_user_data(wl_output);
-//fprintf(stderr, "cursor_surface_enter: wl_output_get_user_data(%p)=%p\n", wl_output, pointer_output->output);
- wl_list_insert(&seat->pointer_outputs, &pointer_output->link);
- try_update_cursor(seat);
- Fl_Wayland_Screen_Driver::output *output =
- (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output);
- output_scale(output, wl_output, output->wld_scale); // rescale custom cursors
- // maintain custom or standard window cursor
- Fl_Window *win = Fl::first_window();
- if (win) {
- Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(win);
- struct wld_window *xid = fl_wl_xid(win);
- if (xid->custom_cursor) Fl_Wayland_Screen_Driver::do_set_cursor(seat, xid->custom_cursor->wl_cursor);
- else if (driver->cursor_default()) driver->set_cursor(driver->cursor_default());
- else win->cursor(driver->standard_cursor());
- }
-}
-
-
-static void cursor_surface_leave(void *data, struct wl_surface *wl_surface,
- struct wl_output *wl_output) {
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- struct pointer_output *pointer_output, *tmp;
- wl_list_for_each_safe(pointer_output, tmp, &seat->pointer_outputs, link) {
- if (pointer_output->output->wl_output == wl_output) {
- wl_list_remove(&pointer_output->link);
- free(pointer_output);
- }
- }
- try_update_cursor(seat);
- // maintain custom window cursor
- Fl_Window *win = Fl::first_window();
- if (win) {
- struct wld_window *xid = fl_wl_xid(win);
- if (xid->custom_cursor) Fl_Wayland_Screen_Driver::do_set_cursor(seat, xid->custom_cursor->wl_cursor);
- }
-}
-
-
-static struct wl_surface_listener cursor_surface_listener = {
- cursor_surface_enter,
- cursor_surface_leave,
-};
-
-
-static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (!seat->cursor_surface) {
- seat->cursor_surface = wl_compositor_create_surface(scr_driver->wl_compositor);
- wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat);
- }
-#if HAVE_CURSOR_SHAPE
- if (scr_driver->wp_cursor_shape_manager) return;
-#endif
-
- char *name;
- int size;
- struct wl_cursor_theme *theme;
-
- if (!libdecor_get_cursor_settings(&name, &size)) {
- name = NULL;
- size = 24;
- }
- size *= seat->pointer_scale;
- theme = wl_cursor_theme_load(name, size, scr_driver->wl_shm);
- free(name);
- if (theme != NULL) {
- if (seat->cursor_theme) {
- // caution to destroy theme because Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor) caches used cursors
- scr_driver->reset_cursor();
- wl_cursor_theme_destroy(seat->cursor_theme);
- }
- seat->cursor_theme = theme;
- }
- if (seat->cursor_theme) {
- seat->default_cursor = scr_driver->xc_cursor[Fl_Wayland_Screen_Driver::arrow] =
- wl_cursor_theme_get_cursor(seat->cursor_theme, "left_ptr");
- }
-}
-
-
-static void wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
- uint32_t format, int32_t fd, uint32_t size) {
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
-
- char *map_shm = (char*)mmap(NULL, size, PROT_READ,
- wl_keyboard_get_version(wl_keyboard) >= 7 ? MAP_PRIVATE : MAP_SHARED, fd, 0);
- assert(map_shm != MAP_FAILED);
-
- struct xkb_keymap *xkb_keymap = xkb_keymap_new_from_string(seat->xkb_context, map_shm,
- XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
- munmap(map_shm, size);
- close(fd);
- if (xkb_keymap) {
- struct xkb_state *xkb_state = xkb_state_new(xkb_keymap);
- xkb_keymap_unref(seat->xkb_keymap);
- if (seat->xkb_state) xkb_state_unref(seat->xkb_state);
- seat->xkb_keymap = xkb_keymap;
- seat->xkb_state = xkb_state;
- }
-}
-
-
-static int search_int_vector(std::vector<int>& v, int val) {
- for (unsigned pos = 0; pos < v.size(); pos++) {
- if (v[pos] == val) return pos;
- }
- return -1;
-}
-
-
-static void remove_int_vector(std::vector<int>& v, int val) {
- int pos = search_int_vector(v, val);
- if (pos < 0) return;
- v.erase(v.begin()+pos);
-}
-
-
-static int process_wld_key(struct xkb_state *xkb_state, uint32_t key,
- uint32_t *p_keycode, xkb_keysym_t *p_sym) {
- uint32_t keycode = key + 8;
- xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, keycode);
- if (sym == 0xfe20) sym = FL_Tab;
- if (sym == 0xffeb) sym = FL_Meta_L; // repair value libxkb gives for FL_Meta_L
- if (sym == 0xffec) sym = FL_Meta_R; // repair value libxkb gives for FL_Meta_R
- if (sym >= 'A' && sym <= 'Z') sym += 32; // replace uppercase by lowercase letter
- int for_key_vector = sym; // for support of Fl::event_key(int)
- // special processing for number keys == keycodes 10-19 :
- if (keycode >= 10 && keycode <= 18) {
- for_key_vector = '1' + (keycode - 10);
- } else if (keycode == 19) {
- for_key_vector = '0';
- }
- if (p_keycode) *p_keycode = keycode;
- if (p_sym) *p_sym = sym;
- return for_key_vector;
-}
-
-
-static uint32_t last_keydown_serial = 0; // serial of last keydown event
-
-
-static void wl_keyboard_enter(void *data, struct wl_keyboard *wl_keyboard,
- uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
-//fprintf(stderr, "keyboard enter fl_win=%p; keys pressed are: ", Fl_Wayland_Window_Driver::surface_to_window(surface));
- key_vector.clear();
- // Replace wl_array_for_each(p, keys) rejected by C++
- for (uint32_t *p = (uint32_t *)(keys)->data;
- (const char *) p < ((const char *) (keys)->data + (keys)->size);
- (p)++) {
- int for_key_vector = process_wld_key(seat->xkb_state, *p, NULL, NULL);
-//fprintf(stderr, "%d ", for_key_vector);
- if (search_int_vector(key_vector, for_key_vector) < 0) {
- key_vector.push_back(for_key_vector);
- }
- }
-//fprintf(stderr, "\n");
- seat->keyboard_surface = surface;
- seat->keyboard_enter_serial = serial;
- last_keydown_serial = 0;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
- if (win) {
- Fl::handle(FL_FOCUS, win);
- fl_wl_find(fl_wl_xid(win));
- }
-}
-
-
-struct key_repeat_data_t {
- uint32_t serial;
- Fl_Window *window;
-};
-
-#define KEY_REPEAT_DELAY 0.5 // sec
-#define KEY_REPEAT_INTERVAL 0.05 // sec
-
-
-static void key_repeat_timer_cb(key_repeat_data_t *key_repeat_data) {
- if (last_keydown_serial == key_repeat_data->serial) {
- Fl::handle(FL_KEYDOWN, key_repeat_data->window);
- Fl::add_timeout(KEY_REPEAT_INTERVAL, (Fl_Timeout_Handler)key_repeat_timer_cb, key_repeat_data);
- }
- else delete key_repeat_data;
-}
-
-
-int Fl_Wayland_Screen_Driver::next_marked_length = 0;
-
-
-int Fl_Wayland_Screen_Driver::has_marked_text() const {
- return 1;
-}
-
-
-int Fl_Wayland_Screen_Driver::insertion_point_x = 0;
-int Fl_Wayland_Screen_Driver::insertion_point_y = 0;
-int Fl_Wayland_Screen_Driver::insertion_point_width = 0;
-int Fl_Wayland_Screen_Driver::insertion_point_height = 0;
-bool Fl_Wayland_Screen_Driver::insertion_point_location_is_valid = false;
-
-static int previous_cursor_x = 0, previous_cursor_y = 0, previous_cursor_h = 0;
-static uint32_t commit_serial = 0;
-static char *current_pre_edit = NULL;
-static char *pending_pre_edit = NULL;
-static char *pending_commit = NULL;
-
-
-static void send_commit(struct zwp_text_input_v3 *zwp_text_input_v3) {
- zwp_text_input_v3_commit(zwp_text_input_v3);
- commit_serial++;
-}
-
-
-// inform TIM about location of the insertion point, and memorize this info.
-void Fl_Wayland_Screen_Driver::insertion_point_location(int x, int y, int height) {
-//printf("insertion_point_location %dx%d\n",x,y);
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->seat->text_input /*&& !current_pre_edit*/ &&
- (x != previous_cursor_x || y != previous_cursor_y || height != previous_cursor_h)) {
- previous_cursor_x = x;
- previous_cursor_y = y;
- previous_cursor_h = height;
- if (Fl::focus()) {
- Fl_Widget *focuswin = Fl::focus()->window();
- while (focuswin && focuswin->parent()) {
- x += focuswin->x(); y += focuswin->y();
- focuswin = focuswin->window();
- }
- }
- float s = fl_graphics_driver->scale();
- insertion_point_location_is_valid = true;
- insertion_point_x = s*x;
- insertion_point_y = s*(y-height);
- insertion_point_width = s*5;
- insertion_point_height = s*height;
- if (zwp_text_input_v3_get_user_data(scr_driver->seat->text_input) ) {
- zwp_text_input_v3_set_cursor_rectangle(scr_driver->seat->text_input,
- insertion_point_x, insertion_point_y,
- insertion_point_width, insertion_point_height);
- send_commit(scr_driver->seat->text_input);
- }
- }
-}
-
-
-// computes window coordinates & size of insertion point
-bool Fl_Wayland_Screen_Driver::insertion_point_location(int *px, int *py,
- int *pwidth, int *pheight) {
- // return true if the current coordinates and size of the insertion point are available
- if ( ! insertion_point_location_is_valid ) return false;
- *px = insertion_point_x;
- *py = insertion_point_y;
- *pwidth = insertion_point_width;
- *pheight = insertion_point_height;
- return true;
-}
-
-
-int Fl_Wayland_Screen_Driver::compose(int& del) {
- unsigned char ascii = (unsigned char)Fl::e_text[0];
- // letter+modifier key
- int condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && ascii < 128 ;
- // pressing modifier key
- // FL_Shift_L, FL_Shift_R, FL_Control_L, FL_Control_R, FL_Caps_Lock
- // FL_Meta_L, FL_Meta_R, FL_Alt_L, FL_Alt_R
- condition |= ((Fl::e_keysym >= FL_Shift_L && Fl::e_keysym <= FL_Alt_R) ||
- Fl::e_keysym == FL_Alt_Gr);
- // FL_Home FL_Left FL_Up FL_Right FL_Down FL_Page_Up FL_Page_Down FL_End
- // FL_Print FL_Insert FL_Menu FL_Help and more
- condition |= (Fl::e_keysym >= FL_Home && Fl::e_keysym <= FL_Num_Lock);
- condition |= (Fl::e_keysym >= FL_F && Fl::e_keysym <= FL_F_Last);
- condition |= Fl::e_keysym == FL_Tab || Fl::e_keysym == FL_Scroll_Lock || Fl::e_keysym == FL_Pause;
-//fprintf(stderr, "compose: condition=%d e_state=%x ascii=%d\n", condition, Fl::e_state, ascii);
- if (condition) { del = 0; return 0;}
-//fprintf(stderr, "compose: del=%d compose_state=%d next_marked_length=%d \n", del, Fl::compose_state, next_marked_length);
- del = Fl::compose_state;
- Fl::compose_state = next_marked_length;
- // no-underlined-text && (ascii non-printable || ascii == delete)
- if (ascii && (!Fl::compose_state) && (ascii <= 31 || ascii == 127)) { del = 0; return 0; }
- return 1;
-}
-
-
-void Fl_Wayland_Screen_Driver::compose_reset() {
- if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
- Fl::compose_state = 0;
- next_marked_length = 0;
- if (seat->xkb_compose_state) xkb_compose_state_reset(seat->xkb_compose_state);
-}
-
-
-struct dead_key_struct {
- xkb_keysym_t keysym; // the keysym obtained when hitting a dead key
- const char *marked_text; // the temporary text to display for that dead key
-};
-
-
-static dead_key_struct dead_keys[] = {
- {XKB_KEY_dead_grave, "`"},
- {XKB_KEY_dead_acute, "´"},
- {XKB_KEY_dead_circumflex, "^"},
- {XKB_KEY_dead_tilde, "~"},
- {XKB_KEY_dead_macron, "¯"},
- {XKB_KEY_dead_breve, "˘"},
- {XKB_KEY_dead_abovedot, "˙"},
- {XKB_KEY_dead_diaeresis, "¨"},
- {XKB_KEY_dead_abovering, "˚"},
- {XKB_KEY_dead_doubleacute, "˝"},
- {XKB_KEY_dead_caron, "ˇ"},
- {XKB_KEY_dead_cedilla, "¸"},
- {XKB_KEY_dead_ogonek, "˛"},
- {XKB_KEY_dead_iota, "ι"},
- {XKB_KEY_dead_doublegrave, " ̏"},
-};
-
-
-const int dead_key_count = sizeof(dead_keys)/sizeof(struct dead_key_struct);
-
-static void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
- uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- seat->serial = serial;
- static char buf[128];
- uint32_t keycode;
- xkb_keysym_t sym;
- int for_key_vector = process_wld_key(seat->xkb_state, key, &keycode, &sym);
-#if (DEBUG_KEYBOARD)
- xkb_keysym_get_name(sym, buf, sizeof(buf));
- const char *action = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? "press" : "release");
- fprintf(stderr, "wl_keyboard_key: key %s: sym: %-12s(%d) code:%u fl_win=%p, ",
- action, buf, sym, keycode,
- Fl_Wayland_Window_Driver::surface_to_window(seat->keyboard_surface));
-#endif
- xkb_state_key_get_utf8(seat->xkb_state, keycode, buf, sizeof(buf));
-#if (DEBUG_KEYBOARD)
- fprintf(stderr, "utf8: '%s' e_length=%d [%d]\n", buf, (int)strlen(buf), *buf);
-#endif
- Fl::e_keysym = Fl::e_original_keysym = for_key_vector;
- if (!(Fl::e_state & FL_NUM_LOCK) && sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete) {
- // compute e_keysym and e_original_keysym for keypad number keys and '.|,' when NumLock is off
- static const int table[11] = {FL_Home /* 7 */, FL_Left /* 4 */, FL_Up /* 8 */,
- FL_Right /* 6 */, FL_Down /* 2 */, FL_Page_Up /* 9 */,
- FL_Page_Down /* 3 */, FL_End /* 1 */, 0xff0b /* 5 */,
- FL_Insert /* 0 */, FL_Delete /* .|, */};
- static const int table_original[11] = {0xffb7 /* 7 */, 0xffb4 /* 4 */, 0xffb8 /* 8 */,
- 0xffb6 /* 6 */, 0xffb2 /* 2 */, 0xffb9 /* 9 */,
- 0xffb3 /* 3 */, 0xffb1 /* 1 */, 0xffb5 /* 5 */,
- 0xffb0 /* 0 */, 0xffac /* .|, */};
- Fl::e_keysym = table[sym - XKB_KEY_KP_Home];
- Fl::e_original_keysym = table_original[sym - XKB_KEY_KP_Home];
- for_key_vector = Fl::e_original_keysym;
- }
-#if (DEBUG_KEYBOARD)
- fprintf(stderr, "wl_keyboard_key: e_keysym=%x e_original_keysym=%x\n", Fl::e_keysym, Fl::e_original_keysym);
-#endif
- if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- if (search_int_vector(key_vector, for_key_vector) < 0) {
- key_vector.push_back(for_key_vector);
- }
- } else {
- last_keydown_serial = 0;
- remove_int_vector(key_vector, for_key_vector);
- }
- Fl::e_text = buf;
- Fl::e_length = (int)strlen(buf);
- // Process dead keys and compose sequences :
- enum xkb_compose_status status = XKB_COMPOSE_NOTHING;
- // This part is useful only if the compositor doesn't support protocol text-input-unstable-v3
- if (seat->xkb_compose_state && state == WL_KEYBOARD_KEY_STATE_PRESSED &&
- !(sym >= FL_Shift_L && sym <= FL_Alt_R) && sym != XKB_KEY_ISO_Level3_Shift) {
- xkb_compose_state_feed(seat->xkb_compose_state, sym);
- status = xkb_compose_state_get_status(seat->xkb_compose_state);
- if (status == XKB_COMPOSE_COMPOSING) {
- if (Fl::e_length == 0) { // dead keys produce e_length = 0
- int i;
- for (i = 0; i < dead_key_count; i++) {
- if (dead_keys[i].keysym == sym) break;
- }
- if (i < dead_key_count) strcpy(buf, dead_keys[i].marked_text);
- else buf[0] = 0;
- Fl::e_length = (int)strlen(buf);
- Fl::compose_state = 0;
- }
- Fl_Wayland_Screen_Driver::next_marked_length = Fl::e_length;
- } else if (status == XKB_COMPOSE_COMPOSED) {
- Fl::e_length = xkb_compose_state_get_utf8(seat->xkb_compose_state, buf, sizeof(buf));
- Fl::compose_state = Fl_Wayland_Screen_Driver::next_marked_length;
- Fl_Wayland_Screen_Driver::next_marked_length = 0;
- } else if (status == XKB_COMPOSE_CANCELLED) {
- Fl::e_length = 0;
- Fl::compose_state = Fl_Wayland_Screen_Driver::next_marked_length;
- Fl_Wayland_Screen_Driver::next_marked_length = 0;
- }
-//fprintf(stderr, "xkb_compose_status=%d ctxt=%p state=%p l=%d[%s]\n", status, seat->xkb_context, seat->xkb_compose_state, Fl::e_length, buf);
- }
- // end of part used only without text-input-unstable-v3
-
- wld_event_time = time;
- int event = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? FL_KEYDOWN : FL_KEYUP);
- // Send event to focus-containing top window as defined by FLTK,
- // otherwise send it to Wayland-defined focus window
- Fl_Window *win = ( Fl::focus() ? Fl::focus()->top_window() :
- Fl_Wayland_Window_Driver::surface_to_window(seat->keyboard_surface) );
- if (win) {
- set_event_xy(win);
- Fl::e_is_click = 0;
- Fl::handle(event, win);
- }
- if (event == FL_KEYDOWN && status == XKB_COMPOSE_NOTHING &&
- !(sym >= FL_Shift_L && sym <= FL_Alt_R)) {
- // Handling of key repeats :
- // Use serial argument rather than time to detect repeated keys because
- // serial value changes at each key up or down in all tested OS and compositors,
- // whereas time value changes in Ubuntu24.04 KDE/Plasma 5.27.11 and Ubuntu22.04 KDE/Plasma 5.24.7
- // but not in Debian-testing KDE/Plasma 5.27.10.
- // Unexplained difference in behaviors of KDE/Plasma compositor:
- // Consider KDE settings -> input -> keyboard -> when a key is held: repeat/do nothing.
- // This setting (repeat) has key-down wayland events repeated when key is held under Debian/KDE
- // but not under Ubuntu/KDE !
- key_repeat_data_t *key_repeat_data = new key_repeat_data_t;
- key_repeat_data->serial = serial;
- key_repeat_data->window = win;
- last_keydown_serial = serial;
- Fl::add_timeout(KEY_REPEAT_DELAY, (Fl_Timeout_Handler)key_repeat_timer_cb,
- key_repeat_data);
- }
-}
-
-
-static void wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard,
- uint32_t serial, struct wl_surface *surface) {
- struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data;
-//fprintf(stderr, "keyboard leave fl_win=%p\n", Fl_Wayland_Window_Driver::surface_to_window(surface));
- seat->keyboard_surface = NULL;
- last_keydown_serial = 0;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
- if (!win && Fl::focus()) win = Fl::focus()->top_window();
- if (win) Fl::handle(FL_UNFOCUS, win);
- key_vector.clear();
-}
-
-
-static void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
- uint32_t serial, uint32_t mods_depressed,
- uint32_t mods_latched, uint32_t mods_locked,
- uint32_t group) {
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- xkb_state_update_mask(seat->xkb_state, mods_depressed, mods_latched, mods_locked,
- 0, 0, group);
- Fl::e_state &= ~(FL_SHIFT+FL_CTRL+FL_ALT+FL_META+FL_CAPS_LOCK+FL_NUM_LOCK);
- if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_SHIFT,
- XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_SHIFT;
- if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_CTRL,
- XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_CTRL;
- if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_ALT,
- XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_ALT;
- if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_LOGO,
- XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_META;
- if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_LOCKED)) Fl::e_state |= FL_CAPS_LOCK;
- if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_NUM,
- XKB_STATE_MODS_LOCKED)) Fl::e_state |= FL_NUM_LOCK;
-//fprintf(stderr, "mods_depressed=%u Fl::e_state=%X\n", mods_depressed, Fl::e_state);
-}
-
-
-static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay)
-{
- // wl_keyboard is version 3 under Debian, but that event isn't sent until version 4
-}
-
-
-static const struct wl_keyboard_listener wl_keyboard_listener = {
- .keymap = wl_keyboard_keymap,
- .enter = wl_keyboard_enter,
- .leave = wl_keyboard_leave,
- .key = wl_keyboard_key,
- .modifiers = wl_keyboard_modifiers,
- .repeat_info = wl_keyboard_repeat_info,
-};
-
-
-void text_input_enter(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
- struct wl_surface *surface) {
-//puts("text_input_enter");
- zwp_text_input_v3_set_user_data(zwp_text_input_v3, surface);
- zwp_text_input_v3_enable(zwp_text_input_v3);
- zwp_text_input_v3_set_content_type(zwp_text_input_v3, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL);
- int x, y, width, height;
- if (Fl_Wayland_Screen_Driver::insertion_point_location(&x, &y, &width, &height)) {
- zwp_text_input_v3_set_cursor_rectangle(zwp_text_input_v3, x, y, width, height);
- }
- send_commit(zwp_text_input_v3);
-}
-
-
-void text_input_leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
- struct wl_surface *surface) {
-//puts("text_input_leave");
- zwp_text_input_v3_disable(zwp_text_input_v3);
- zwp_text_input_v3_set_user_data(zwp_text_input_v3, NULL);
- send_commit(zwp_text_input_v3);
- free(pending_pre_edit); pending_pre_edit = NULL;
- free(current_pre_edit); current_pre_edit = NULL;
- free(pending_commit); pending_commit = NULL;
-}
-
-
-static void send_text_to_fltk(const char *text, bool is_marked, struct wl_surface *current_surface) {
-//printf("send_text_to_fltk(%s, %d)\n",text,is_marked);
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(current_surface);
- Fl::e_text = text ? (char*)text : (char*)"";
- Fl::e_length = text ? (int)strlen(text) : 0;
- Fl::e_keysym = 'a'; // fake a simple key
- set_event_xy(win);
- Fl::e_is_click = 0;
- if (is_marked) { // goes to widget as marked text
- Fl_Wayland_Screen_Driver::next_marked_length = Fl::e_length;
- Fl::handle(FL_KEYDOWN, win);
- } else if (text) {
- Fl_Wayland_Screen_Driver::next_marked_length = 0;
- Fl::handle(FL_KEYDOWN, win);
- Fl::compose_state = 0;
- } else {
- Fl_Wayland_Screen_Driver::next_marked_length = 0;
- Fl::handle(FL_KEYDOWN, win);
- }
-}
-
-
-void text_input_preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
- const char *text, int32_t cursor_begin, int32_t cursor_end) {
-//printf("text_input_preedit_string %s cursor_begin=%d cursor_end=%d\n",text, cursor_begin, cursor_end);
- free(pending_pre_edit);
- pending_pre_edit = text ? strdup(text) : NULL;
-}
-
-
-void text_input_commit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
- const char *text) {
-//printf("text_input_commit_string %s\n",text);
- free(pending_commit);
- pending_commit = (text ? strdup(text) : NULL);
-}
-
-
-void text_input_delete_surrounding_text(void *data,
- struct zwp_text_input_v3 *zwp_text_input_v3,
- uint32_t before_length, uint32_t after_length) {
- fprintf(stderr, "delete_surrounding_text before=%d adfter=%d\n",
- before_length,after_length);
-}
-
-
-void text_input_done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
- uint32_t serial) {
-//puts("text_input_done");
- struct wl_surface *current_surface = (struct wl_surface*)data;
- const bool bad_event = (serial != commit_serial);
- if ((pending_pre_edit == NULL && current_pre_edit == NULL) ||
- (pending_pre_edit && current_pre_edit && strcmp(pending_pre_edit, current_pre_edit) == 0)) {
- free(pending_pre_edit); pending_pre_edit = NULL;
- } else {
- free(current_pre_edit);
- current_pre_edit = pending_pre_edit;
- pending_pre_edit = NULL;
- if (current_pre_edit) {
- send_text_to_fltk(current_pre_edit, !bad_event, current_surface);
- } else {
- send_text_to_fltk(NULL, false, current_surface);
- }
- }
- if (pending_commit) {
- send_text_to_fltk(pending_commit, false, current_surface);
- free(pending_commit); pending_commit = NULL;
- }
-}
-
-
-static const struct zwp_text_input_v3_listener text_input_listener = {
- .enter = text_input_enter,
- .leave = text_input_leave,
- .preedit_string = text_input_preedit_string,
- .commit_string = text_input_commit_string,
- .delete_surrounding_text = text_input_delete_surrounding_text,
- .done = text_input_done,
-};
-
-
-void Fl_Wayland_Screen_Driver::enable_im() {
- if (text_input_base && !seat->text_input) {
- seat->text_input = zwp_text_input_manager_v3_get_text_input(text_input_base,
- seat->wl_seat);
- //printf("seat->text_input=%p\n",seat->text_input);
- zwp_text_input_v3_add_listener(seat->text_input, &text_input_listener, NULL);
- }
-}
-
-
-void Fl_Wayland_Screen_Driver::disable_im() {
- if (seat->text_input) {
- zwp_text_input_v3_disable(seat->text_input);
- zwp_text_input_v3_commit(seat->text_input);
- zwp_text_input_v3_destroy(seat->text_input);
- seat->text_input = NULL;
- free(pending_pre_edit); pending_pre_edit = NULL;
- free(current_pre_edit); current_pre_edit = NULL;
- free(pending_commit); pending_commit = NULL;
- }
-}
-
-
-static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
-{
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- struct Fl_Wayland_Screen_Driver::seat *seat =
- (struct Fl_Wayland_Screen_Driver::seat*)data;
- if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer) {
- seat->wl_pointer = wl_seat_get_pointer(wl_seat);
- wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
- seat->pointer_scale = 1;
-#if HAVE_CURSOR_SHAPE
- if (scr_driver->wp_cursor_shape_manager) {
- scr_driver->wp_cursor_shape_device =
- wp_cursor_shape_manager_v1_get_pointer(scr_driver->wp_cursor_shape_manager, seat->wl_pointer);
- }
-#endif // HAVE_CURSOR_SHAPE
- init_cursors(seat);
- } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer) {
- wl_pointer_release(seat->wl_pointer);
- seat->wl_pointer = NULL;
- }
-
- bool have_keyboard = seat->xkb_context && (capabilities & WL_SEAT_CAPABILITY_KEYBOARD);
- if (have_keyboard && seat->wl_keyboard == NULL) {
- seat->wl_keyboard = wl_seat_get_keyboard(wl_seat);
- wl_keyboard_add_listener(seat->wl_keyboard,
- &wl_keyboard_listener, seat);
-//fprintf(stderr, "wl_keyboard version=%d\n", wl_keyboard_get_version(seat->wl_keyboard));
-
- } else if (!have_keyboard && seat->wl_keyboard != NULL) {
- wl_keyboard_release(seat->wl_keyboard);
- seat->wl_keyboard = NULL;
- }
- scr_driver->enable_im();
-}
-
-
-static void seat_name(void *data, struct wl_seat *wl_seat, const char *name) {
- struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data;
- seat->name = strdup(name);
-}
-
-
-static struct wl_seat_listener seat_listener = {
- seat_capabilities,
- seat_name
-};
-
-
-static void output_geometry(void *data,
- struct wl_output *wl_output,
- int32_t x,
- int32_t y,
- int32_t physical_width,
- int32_t physical_height,
- int32_t subpixel,
- const char *make,
- const char *model,
- int32_t transform)
-{
- //fprintf(stderr, "output_geometry: x=%d y=%d physical=%dx%d\n",x,y,physical_width,physical_height);
- Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
- output->x = int(x);
- output->y = int(y);
- output->dpi = 96; // to elaborate
-}
-
-
-static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
- int32_t width, int32_t height, int32_t refresh)
-{
- Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
- output->pixel_width = int(width);
- output->pixel_height = int(height);
- output->width = output->pixel_width; // until further notice
- output->height = output->pixel_height;
-//fprintf(stderr, "output_mode: [%p]=%dx%d\n",output->wl_output,width,height);
-}
-
-
-static void output_done(void *data, struct wl_output *wl_output)
-{
- // Runs at startup and when desktop scale factor is changed or screen added
- Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
-//fprintf(stderr, "output_done output=%p\n",output);
- Fl_X *xp = Fl_X::first;
- while (xp) { // all mapped windows
- struct wld_window *win = (struct wld_window*)xp->xid;
- Fl_Window *W = win->fl_win;
- if (win->buffer || W->as_gl_window()) {
- if (W->as_gl_window()) {
- wl_surface_set_buffer_scale(win->wl_surface, output->wld_scale);
- Fl_Window_Driver::driver(W)->is_a_rescale(true);
- W->resize(W->x(), W->y(), W->w(), W->h());
- Fl_Window_Driver::driver(W)->is_a_rescale(false);
- } else {
- Fl_Wayland_Graphics_Driver::buffer_release(win);
- }
- W->redraw();
- Fl_Window_Driver::driver(W)->flush();
- }
- xp = xp->next;
- }
- output->done = true;
-
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->screen_count_get() > 0) { // true when output_done runs after initial screen dectection
- scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
- scr_driver->init_workarea();
- }
-}
-
-
-static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) {
- Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
- output->wld_scale = factor;
-//fprintf(stderr,"output_scale: wl_output=%p factor=%d\n",wl_output, factor);
- // rescale cursors of windows that map here and have a custom cursor
- Fl_Window *win = Fl::first_window();
- while (win) {
- struct wld_window *xid = fl_wl_xid(win);
- struct Fl_Wayland_Window_Driver::surface_output *s_output;
- // get 1st screen where window appears
- s_output = wl_container_of(xid->outputs.next, s_output, link);
- if (xid->custom_cursor && output == s_output->output) {
- Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(win);
- driver->set_cursor_4args(xid->custom_cursor->rgb,
- xid->custom_cursor->hotx, xid->custom_cursor->hoty, false);
- };
- win = Fl::next_window(win);
- }
-}
-
-
-static struct wl_output_listener output_listener = {
- output_geometry,
- output_mode,
- output_done,
- output_scale
-};
-
-
-struct pair_bool {
- bool found_gtk_shell;
- bool found_wf_shell;
-};
-
-
-// Notice: adding use of unstable protocol "XDG output" would allow FLTK to be notified
-// in real time of changes to the relative location of multiple displays;
-// with the present code, that information is received at startup only.
-static void registry_handle_global(void *user_data, struct wl_registry *wl_registry,
- uint32_t id, const char *interface, uint32_t version) {
-//fprintf(stderr, "interface=%s version=%u\n", interface, version);
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (strcmp(interface, "wl_compositor") == 0) {
- if (version < 4) {
- Fl::fatal("wl_compositor version >= 4 required");
- }
- scr_driver->wl_compositor = (struct wl_compositor*)wl_registry_bind(wl_registry,
- id, &wl_compositor_interface, 4);
-
- } else if (strcmp(interface, "wl_subcompositor") == 0) {
- scr_driver->wl_subcompositor = (struct wl_subcompositor*)wl_registry_bind(wl_registry,
- id, &wl_subcompositor_interface, 1);
-
- } else if (strcmp(interface, "wl_shm") == 0) {
- scr_driver->wl_shm = (struct wl_shm*)wl_registry_bind(wl_registry,
- id, &wl_shm_interface, 1);
-
- } else if (strcmp(interface, "wl_seat") == 0) {
- if (version < 3) {
- Fl::fatal("%s version 3 required but only version %i is available\n",
- interface, version);
- }
- if (!scr_driver->seat) scr_driver->seat =
- (struct Fl_Wayland_Screen_Driver::seat*)calloc(1,
- sizeof(struct Fl_Wayland_Screen_Driver::seat));
-//fprintf(stderr, "registry_handle_global: seat=%p\n", scr_driver->seat);
- wl_list_init(&scr_driver->seat->pointer_outputs);
- scr_driver->seat->wl_seat = (wl_seat*)wl_registry_bind(wl_registry, id,
- &wl_seat_interface, 3);
- scr_driver->seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- if (scr_driver->seat->xkb_context) {
- const char *locale = getenv("LC_ALL");
- if (!locale || !*locale)
- locale = getenv("LC_CTYPE");
- if (!locale || !*locale)
- locale = getenv("LANG");
- if (!locale || !*locale)
- locale = "C";
- struct xkb_compose_table *table =
- xkb_compose_table_new_from_locale(scr_driver->seat->xkb_context, locale,
- XKB_COMPOSE_COMPILE_NO_FLAGS);
- if (table) {
- scr_driver->seat->xkb_compose_state =
- xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS);
- }
- }
- wl_seat_add_listener(scr_driver->seat->wl_seat, &seat_listener, scr_driver->seat);
- if (scr_driver->seat->data_device_manager) {
- scr_driver->seat->data_device =
- wl_data_device_manager_get_data_device(scr_driver->seat->data_device_manager,
- scr_driver->seat->wl_seat);
- wl_data_device_add_listener(scr_driver->seat->data_device,
- Fl_Wayland_Screen_Driver::p_data_device_listener, NULL);
- }
-
- } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
- if (!scr_driver->seat) scr_driver->seat =
- (struct Fl_Wayland_Screen_Driver::seat*)calloc(1,
- sizeof(struct Fl_Wayland_Screen_Driver::seat));
- scr_driver->seat->data_device_manager =
- (struct wl_data_device_manager*)wl_registry_bind(wl_registry, id,
- &wl_data_device_manager_interface,
- fl_min(version, 3));
- if (scr_driver->seat->wl_seat) {
- scr_driver->seat->data_device =
- wl_data_device_manager_get_data_device(scr_driver->seat->data_device_manager,
- scr_driver->seat->wl_seat);
- wl_data_device_add_listener(scr_driver->seat->data_device,
- Fl_Wayland_Screen_Driver::p_data_device_listener, NULL);
- }
-//fprintf(stderr, "registry_handle_global: %s\n", interface);
-
- } else if (strcmp(interface, "wl_output") == 0) {
- if (version < 2) {
- Fl::fatal("%s version 2 required but only version %i is available\n",
- interface, version);
- }
- Fl_Wayland_Screen_Driver::output *output =
- (Fl_Wayland_Screen_Driver::output*)calloc(1, sizeof *output);
- output->id = id;
- output->wld_scale = 1;
-#ifdef WL_OUTPUT_RELEASE_SINCE_VERSION
- const int used_version = WL_OUTPUT_RELEASE_SINCE_VERSION;
-#else
- const int used_version = 2;
-#endif
- output->wl_output = (struct wl_output*)wl_registry_bind(wl_registry,
- id, &wl_output_interface, fl_min(used_version, version));
- output->gui_scale = 1.f;
- wl_proxy_set_tag((struct wl_proxy *) output->wl_output, &proxy_tag);
- wl_output_add_listener(output->wl_output, &output_listener, output);
- // Put new screen in list of screens, but make sure it's not in list already
- // which may occur after having removed a screen.
- bool found = false;
- Fl_Wayland_Screen_Driver::output *elt;
- wl_list_for_each(elt, &scr_driver->outputs, link) {
- if (elt == output) found = true;
- }
- if (!found) { // add to end of the linked list of displays
- struct wl_list *e = &scr_driver->outputs;
- while (e->next != &scr_driver->outputs) e = e->next; // move e to end of linked list
- wl_list_insert(e, &output->link);
- }
-//fprintf(stderr, "wl_output: id=%d wl_output=%p \n", id, output->wl_output);
-
- } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
-//fprintf(stderr, "registry_handle_global interface=%s\n", interface);
- scr_driver->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(wl_registry, id,
- &xdg_wm_base_interface, 1);
- xdg_wm_base_add_listener(scr_driver->xdg_wm_base, &xdg_wm_base_listener, NULL);
- } else if (strstr(interface, "wf_shell_manager")) {
- ((pair_bool*)user_data)->found_wf_shell = true;
- } else if (strcmp(interface, "gtk_shell1") == 0) {
- ((pair_bool*)user_data)->found_gtk_shell = true;
- //fprintf(stderr, "Running the Mutter compositor\n");
- scr_driver->seat->gtk_shell = (struct gtk_shell1*)wl_registry_bind(wl_registry, id,
- &gtk_shell1_interface, version);
- } else if (strcmp(interface, "weston_desktop_shell") == 0) {
- Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::WESTON;
- //fprintf(stderr, "Running the Weston compositor\n");
- } else if (strcmp(interface, "org_kde_plasma_shell") == 0) {
- Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::KWIN;
- //fprintf(stderr, "Running the KWin compositor\n");
- } else if (strncmp(interface, "zowl_mach_ipc", 13) == 0) {
- Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::OWL;
- //fprintf(stderr, "Running the Owl compositor\n");
- if (wl_list_length(&scr_driver->outputs) == 0) {
- Fl_Wayland_Screen_Driver::output *output =
- (Fl_Wayland_Screen_Driver::output*)calloc(1, sizeof *output);
- output->id = 1;
- output->wld_scale = 1;
- output->gui_scale = 1.f;
- output->width = 1440; output->height = 900;
- output->pixel_width = 1440; output->pixel_height = 900;
- output->done = true;
- wl_list_insert(&(scr_driver->outputs), &output->link);
- scr_driver->screen_count_set(1);
- }
- } else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
- scr_driver->text_input_base = (struct zwp_text_input_manager_v3 *)
- wl_registry_bind(wl_registry, id, &zwp_text_input_manager_v3_interface, 1);
-//printf("scr_driver->text_input_base=%p version=%d\n",scr_driver->text_input_base,version);
-#if HAVE_XDG_DIALOG
- } else if (strcmp(interface, xdg_wm_dialog_v1_interface.name) == 0) {
- scr_driver->xdg_wm_dialog = (struct xdg_wm_dialog_v1 *)
- wl_registry_bind(wl_registry, id, &xdg_wm_dialog_v1_interface, 1);
-#endif // HAVE_XDG_DIALOG
-#if HAVE_CURSOR_SHAPE
- } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
- scr_driver->wp_cursor_shape_manager = (struct wp_cursor_shape_manager_v1 *)
- wl_registry_bind(wl_registry, id, &wp_cursor_shape_manager_v1_interface, 1);
-#endif // HAVE_CURSOR_SHAPE
- }
-}
-
-
-static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
- Fl_Wayland_Screen_Driver::output *output;
-//fprintf(stderr, "registry_handle_global_remove data=%p id=%u\n", data, name);
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- bool has_removed_screen = false;
- wl_list_for_each(output, &(scr_driver->outputs), link) { // all screens
- if (output->id == name) { // the screen being removed
- wl_list_remove(&output->link);
- wl_output_destroy(output->wl_output);
- free(output);
- has_removed_screen = true;
- break;
- }
- }
- if (has_removed_screen) {
- scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
- scr_driver->init_workarea();
- }
-}
-
-
-static const struct wl_registry_listener registry_listener = {
- registry_handle_global,
- registry_handle_global_remove
-};
-
-
-static void wayland_socket_callback(int fd, struct wl_display *display)
-{
- if (wl_display_prepare_read(display) == -1) {
- wl_display_dispatch_pending(display);
- return;
- }
- wl_display_flush(display);
- struct pollfd fds = (struct pollfd) { fd, POLLIN, 0 };
- if (poll(&fds, 1, 0) <= 0) {
- wl_display_cancel_read(display);
- return;
- }
- if (fds.revents & (POLLERR | POLLHUP)) {
- wl_display_cancel_read(display);
- goto fatal;
- }
- if (wl_display_read_events(display) == -1)
- goto fatal;
- if (wl_display_dispatch_pending(display) == -1)
- goto fatal;
- return;
-fatal:
- if (wl_display_get_error(display) == EPROTO) {
- const struct wl_interface *interface;
- int code = wl_display_get_protocol_error(display, &interface, NULL);
- Fl::fatal("Fatal error %d in Wayland protocol: %s",
- code, (interface ? interface->name : "unknown") );
- } else {
- Fl::fatal("Fatal error while communicating with Wayland server: %s",
- strerror(errno));
- }
-}
-
-
-Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Unix_Screen_Driver() {
- libdecor_context = NULL;
- seat = NULL;
- text_input_base = NULL;
- reset_cursor();
- wl_registry = NULL;
-#if HAVE_XDG_DIALOG
- xdg_wm_dialog = NULL;
-#endif
-#if HAVE_CURSOR_SHAPE
- wp_cursor_shape_manager = NULL;
- wp_cursor_shape_device = NULL;
-#endif
-}
-
-
-static void sync_done(void *data, struct wl_callback *cb, uint32_t time) {
- // runs after all calls to registry_handle_global()
- *(struct wl_callback **)data = NULL;
- wl_callback_destroy(cb);
- // keep processing until output_done() has run for each screen
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &scr_driver->outputs, link) { // each screen of the system
- while (!output->done) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
- }
- // Now all screens have been initialized
- scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
- struct pair_bool *pair = (struct pair_bool*)wl_registry_get_user_data(scr_driver->wl_registry);
- if (pair->found_gtk_shell || pair->found_wf_shell) {
- Fl_Wayland_Screen_Driver::compositor = (pair->found_wf_shell ?
- Fl_Wayland_Screen_Driver::WAYFIRE : Fl_Wayland_Screen_Driver::MUTTER);
- }
- if (scr_driver->seat) {
-#if HAVE_CURSOR_SHAPE
- if (!scr_driver->wp_cursor_shape_manager)
-#endif
- try_update_cursor(scr_driver->seat);
- }
- if (Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::OWL) scr_driver->init_workarea();
-}
-
-
-static const struct wl_callback_listener sync_listener = {
- sync_done
-};
-
-
-static void do_atexit() {
- if (Fl_Wayland_Screen_Driver::wl_display) {
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
- }
-}
-
-
-void Fl_Wayland_Screen_Driver::open_display_platform() {
- static bool beenHereDoneThat = false;
- if (beenHereDoneThat)
- return;
-
- beenHereDoneThat = true;
-
- if (!wl_display) {
- wl_display = wl_display_connect(NULL);
- if (!wl_display) {
- Fl::fatal("No Wayland connection\n");
- }
- }
- //puts("Using Wayland backend");
- wl_list_init(&outputs);
-
- wl_registry = wl_display_get_registry(wl_display);
- struct pair_bool pair = {false, false};
- wl_registry_add_listener(wl_registry, &registry_listener, &pair);
- struct wl_callback *registry_cb = wl_display_sync(wl_display);
- wl_callback_add_listener(registry_cb, &sync_listener, &registry_cb);
- while (registry_cb) wl_display_dispatch(wl_display);
- Fl::add_fd(wl_display_get_fd(wl_display), FL_READ, (Fl_FD_Handler)wayland_socket_callback,
- wl_display);
- fl_create_print_window();
- /* This is useful to avoid crash of the Wayland compositor after
- FLTK apps terminate in certain situations:
- - gnome-shell version < 44 (e.g. version 42.9)
- - focus set to "follow-mouse"
- See issue #821 for details.
- */
- atexit(do_atexit);
-}
-
-
-void Fl_Wayland_Screen_Driver::close_display() {
- if (!Fl_Wayland_Screen_Driver::wl_display) return;
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
- if (text_input_base) {
- disable_im();
- zwp_text_input_manager_v3_destroy(text_input_base);
- text_input_base = NULL;
- }
- while (wl_list_length(&outputs) > 0) {
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &outputs, link) {
- wl_list_remove(&output->link);
- screen_count_set( wl_list_length(&outputs) );
- if (output->wl_output) {
-#ifdef WL_OUTPUT_RELEASE_SINCE_VERSION
- if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
- wl_output_release(output->wl_output);
- else
-#endif
- wl_output_destroy(output->wl_output);
- }
- free(output);
- break;
- }
- }
- wl_subcompositor_destroy(wl_subcompositor); wl_subcompositor = NULL;
- wl_surface_destroy(seat->cursor_surface); seat->cursor_surface = NULL;
- if (seat->cursor_theme) {
- wl_cursor_theme_destroy(seat->cursor_theme);
- seat->cursor_theme = NULL;
- }
- wl_compositor_destroy(wl_compositor); wl_compositor = NULL;
- // wl_shm-related data
- if (Fl_Wayland_Graphics_Driver::current_pool) {
- struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data *pool_data =
- (struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data*)
- wl_shm_pool_get_user_data(Fl_Wayland_Graphics_Driver::current_pool);
- wl_shm_pool_destroy(Fl_Wayland_Graphics_Driver::current_pool);
- Fl_Wayland_Graphics_Driver::current_pool = NULL;
- /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size);
- //printf("close_display munmap(%p)->%d\n", pool_data->pool_memory, err);
- free(pool_data);
- }
- wl_shm_destroy(wl_shm); wl_shm = NULL;
- if (seat->wl_keyboard) {
- if (seat->xkb_state) {
- xkb_state_unref(seat->xkb_state);
- seat->xkb_state = NULL;
- }
- if (seat->xkb_keymap) {
- xkb_keymap_unref(seat->xkb_keymap);
- seat->xkb_keymap = NULL;
- }
- wl_keyboard_destroy(seat->wl_keyboard);
- seat->wl_keyboard = NULL;
- }
- wl_pointer_destroy(seat->wl_pointer); seat->wl_pointer = NULL;
- if (seat->xkb_compose_state) {
- xkb_compose_state_unref(seat->xkb_compose_state);
- seat->xkb_compose_state = NULL;
- }
- if (seat->xkb_context) {
- xkb_context_unref(seat->xkb_context);
- seat->xkb_context = NULL;
- }
- if (seat->data_source) {
- wl_data_source_destroy(seat->data_source);
- seat->data_source = NULL;
- }
- wl_data_device_destroy(seat->data_device); seat->data_device = NULL;
- wl_data_device_manager_destroy(seat->data_device_manager);
- seat->data_device_manager = NULL;
- wl_seat_destroy(seat->wl_seat); seat->wl_seat = NULL;
- if (seat->name) free(seat->name);
- free(seat); seat = NULL;
- if (libdecor_context) {
- libdecor_unref(libdecor_context);
- libdecor_context = NULL;
- }
- xdg_wm_base_destroy(xdg_wm_base); xdg_wm_base = NULL;
- Fl_Wayland_Plugin *plugin = Fl_Wayland_Window_Driver::gl_plugin();
- if (plugin) plugin->terminate();
-#if HAVE_XDG_DIALOG
- if (xdg_wm_dialog) {
- xdg_wm_dialog_v1_destroy(xdg_wm_dialog);
- xdg_wm_dialog = NULL;
- }
-#endif // HAVE_XDG_DIALOG
-#if HAVE_CURSOR_SHAPE
- if (wp_cursor_shape_device ) {
- wp_cursor_shape_device_v1_destroy(wp_cursor_shape_device);
- wp_cursor_shape_device = NULL;
- }
- if (wp_cursor_shape_manager ) {
- wp_cursor_shape_manager_v1_destroy(wp_cursor_shape_manager);
- wp_cursor_shape_manager = NULL;
- }
-#endif // HAVE_CURSOR_SHAPE
-
- Fl::remove_fd(wl_display_get_fd(Fl_Wayland_Screen_Driver::wl_display));
- wl_registry_destroy(wl_registry); wl_registry = NULL;
- wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display);
- Fl_Wayland_Screen_Driver::wl_display = NULL;
- delete Fl_Display_Device::display_device()->driver();
- delete Fl_Display_Device::display_device();
- delete Fl::system_driver();
- delete this;
-}
-
-
-struct configure_s { int W, H; uint32_t state; };
-
-static void xdg_toplevel_configure(void *v, struct xdg_toplevel *xdg_toplevel,
- int32_t width, int32_t height, struct wl_array *states)
-{
- struct configure_s *data = (struct configure_s*)v;
- data->W = width;
- data->H = height;
- data->state = (width && height && states ? *(uint32_t *)(states->data) : 0);
-}
-
-static const struct xdg_toplevel_listener xdg_toplevel_listener = {
- .configure = xdg_toplevel_configure,
-};
-
-
-static bool compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output,
- int& Wfullscreen, int& Hfullscreen,
- int& Wworkarea, int& Hworkarea) {
- if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::unspecified) {
- Wfullscreen = 0;
- return false;
- }
- bool found_workarea = false;
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- struct wl_surface *wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor);
- wl_surface_set_opaque_region(wl_surface, NULL);
- struct xdg_surface *xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, wl_surface);
- struct xdg_toplevel *xdg_toplevel = xdg_surface_get_toplevel(xdg_surface);
- struct configure_s data = {0, 0, 0};
- xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, &data);
- xdg_toplevel_set_fullscreen(xdg_toplevel, output->wl_output);
- wl_surface_commit(wl_surface); // necessary under KWin
- while (data.state != XDG_TOPLEVEL_STATE_FULLSCREEN)
- wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
- Wfullscreen = data.W;
- Hfullscreen = data.H;
- if (Wfullscreen && Hfullscreen && wl_list_length(&scr_driver->outputs) == 1) {
- struct wl_surface *wl_surface2 = wl_compositor_create_surface(scr_driver->wl_compositor);
- struct xdg_surface *xdg_surface2 = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, wl_surface2);
- struct xdg_toplevel *xdg_toplevel2 = xdg_surface_get_toplevel(xdg_surface2);
- struct configure_s data2 = {0, 0, 0};
- xdg_toplevel_add_listener(xdg_toplevel2, &xdg_toplevel_listener, &data2);
- xdg_toplevel_set_parent(xdg_toplevel2, xdg_toplevel);
- xdg_toplevel_set_maximized(xdg_toplevel2);
- wl_surface_commit(wl_surface2); // necessary under KWin
- while (data2.state != XDG_TOPLEVEL_STATE_MAXIMIZED)
- wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
- Wworkarea = data2.W;
- Hworkarea = data2.H;
- xdg_toplevel_destroy(xdg_toplevel2);
- xdg_surface_destroy(xdg_surface2);
- wl_surface_destroy(wl_surface2);
- if (Wworkarea == Wfullscreen && Hworkarea < Hfullscreen && Hworkarea > Hfullscreen - 80)
- found_workarea = true;
- if (Hworkarea == Hfullscreen && Wworkarea < Wfullscreen && Wworkarea > Wfullscreen - 80)
- found_workarea = true;
- } else {
- Wworkarea = Wfullscreen;
- Hworkarea = Hfullscreen;
- }
- xdg_toplevel_destroy(xdg_toplevel);
- xdg_surface_destroy(xdg_surface);
- wl_surface_destroy(wl_surface);
- /*int fractional_scale = int(100 * (output->pixel_width / float(Wfullscreen)));
- printf("fullscreen=%dx%d workarea=%dx%d fractional_scale=%d%% wld_s=%d\n",
- Wfullscreen,Hfullscreen,Wworkarea,Hworkarea,fractional_scale,output->wld_scale);*/
- return found_workarea;
-}
-
-static int workarea_xywh[4] = { -1, -1, -1, -1 };
-
-
-/* Implementation note about computing work area and about handling fractional scaling.
-
- FLTK computes 2 pairs of (WxH) values for each display:
- 1) (pixel_width x pixel_height) gives the size in pixel of a display. It's unchanged by
- any scaling applied by the compositor; it's assigned by function output_mode().
- 2) (width x height) gives the size in pixels of a buffer that would fully cover the display.
- When the active scaling is non-fractional, these equations hold:
- pixel_width = width = wld_scale * configured-width-of-fullscreen-window
- pixel_height = height = wld_scale * configured-height-of-fullscreen-window
-
- When fractional scaling is active, buffers received from client are scaled down
- by the compositor and mapped to screen. These equations hold:
- pixel_width < width = wld_scale * configured-width-of-fullscreen-window
- pixel_height < height = wld_scale * configured-height-of-fullscreen-window
-
- One way for a client to discover that fractional scaling is active on a given display
- is to ask for a fullscreen window on that display, get its configured size and compare
- it to that display's pixel size. That's what function compute_full_and_maximized_areas() does.
-
- One way for a client to discover the work area size of a display is to get the configured size
- of a maximized window on that display. FLTK didn't find a way to control in general
- on what display the compositor puts a maximized window. Therefore, FLTK computes an exact
- work area size only when the system contains a single display. We create first a fullscreen
- window on the display and then we create a maximized window made a child of the
- fullscreen one and record its configured size. That's also done by function
- compute_full_and_maximized_areas().
- */
-
-void Fl_Wayland_Screen_Driver::init_workarea()
-{
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); // important after screen removal
- bool need_init_workarea = true;
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &outputs, link) {
- int Wfullscreen, Hfullscreen, Wworkarea, Hworkarea;
- bool found_workarea = compute_full_and_maximized_areas(output, Wfullscreen, Hfullscreen, Wworkarea, Hworkarea);
- if (Wfullscreen && Hfullscreen) { // skip sway which puts 0 there
- output->width = Wfullscreen * output->wld_scale; // pixels
- output->height = Hfullscreen * output->wld_scale; // pixels
- if (found_workarea) {
- workarea_xywh[0] = output->x; // pixels
- workarea_xywh[1] = output->y; // pixels
- workarea_xywh[2] = Wworkarea * output->wld_scale; // pixels
- workarea_xywh[3] = Hworkarea * output->wld_scale; // pixels
- need_init_workarea = false;
- }
- }
- }
- if (need_init_workarea) {
- screen_xywh(workarea_xywh[0], workarea_xywh[1], workarea_xywh[2], workarea_xywh[3], 0);
- }
- Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
-}
-
-
-int Fl_Wayland_Screen_Driver::x() {
- if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &outputs, link) {
- break;
- }
- return workarea_xywh[0] / (output->gui_scale * output->wld_scale);
-}
-
-
-int Fl_Wayland_Screen_Driver::y() {
- if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &outputs, link) {
- break;
- }
- return workarea_xywh[1] / (output->gui_scale * output->wld_scale);
-}
-
-
-int Fl_Wayland_Screen_Driver::w() {
- if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &outputs, link) {
- break;
- }
- return workarea_xywh[2] / (output->gui_scale * output->wld_scale);
-}
-
-
-int Fl_Wayland_Screen_Driver::h() {
- if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &outputs, link) {
- break;
- }
- return workarea_xywh[3] / (output->gui_scale * output->wld_scale);
-}
-
-
-void Fl_Wayland_Screen_Driver::init() {
- if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
-}
-
-
-void Fl_Wayland_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n)
-{
- if (num_screens < 0) init();
- if (n < 0 || n >= num_screens) n = 0;
- if (n == 0) { // for the main screen, these return the work area
- X = Fl::x();
- Y = Fl::y();
- W = Fl::w();
- H = Fl::h();
- } else { // for other screens, work area is full screen,
- screen_xywh(X, Y, W, H, n);
- }
-}
-
-
-void Fl_Wayland_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n)
-{
- if (num_screens < 0) init();
-
- if ((n < 0) || (n >= num_screens))
- n = 0;
-
- if (num_screens > 0) {
- Fl_Wayland_Screen_Driver::output *output;
- int i = 0;
- wl_list_for_each(output, &outputs, link) {
- if (i++ == n) { // n'th screen of the system
- float s = output->gui_scale * output->wld_scale;
- X = output->x / s;
- Y = output->y / s;
- W = output->width / s;
- H = output->height / s;
- break;
- }
- }
- }
-}
-
-
-void Fl_Wayland_Screen_Driver::screen_dpi(float &h, float &v, int n)
-{
- if (num_screens < 0) init();
- h = v = 0.0f;
-
- if (n >= 0 && n < num_screens) {
- Fl_Wayland_Screen_Driver::output *output;
- int i = 0;
- wl_list_for_each(output, &outputs, link) {
- if (i++ == n) { // n'th screen of the system
- h = output->dpi;
- v = output->dpi;
- break;
- }
- }
- }
-}
-
-
-// Implements fl_beep(). See documentation in src/fl_ask.cxx.
-void Fl_Wayland_Screen_Driver::beep(int type)
-{
- fprintf(stderr, "\007");
-}
-
-
-void Fl_Wayland_Screen_Driver::flush()
-{
- if (Fl_Wayland_Screen_Driver::wl_display) {
- wl_display_flush(Fl_Wayland_Screen_Driver::wl_display);
- }
-}
-
-
-extern void fl_fix_focus(); // in Fl.cxx
-
-
-void Fl_Wayland_Screen_Driver::grab(Fl_Window* win)
-{
- if (win) {
- if (!Fl::grab()) {
- }
- Fl::grab_ = win; // FIXME: Fl::grab_ "should be private", but we need
- // a way to *set* the variable from the driver!
- } else {
- if (Fl::grab()) {
- // We must keep the grab in the non-EWMH fullscreen case
- Fl::grab_ = 0; // FIXME: Fl::grab_ "should be private", but we need
- // a way to *set* the variable from the driver!
- fl_fix_focus();
- }
- }
-}
-
-
-static void set_selection_color(uchar r, uchar g, uchar b)
-{
- Fl::set_color(FL_SELECTION_COLOR,r,g,b);
-}
-
-
-static void getsyscolor(const char *key1, const char* key2, const char *arg,
- const char *defarg, void (*func)(uchar,uchar,uchar)) {
- uchar r, g, b;
- if (!arg) arg = defarg;
- if (!Fl::screen_driver()->parse_color(arg, r, g, b))
- Fl::error("Unknown color: %s", arg);
- else
- func(r, g, b);
-}
-
-
-void Fl_Wayland_Screen_Driver::get_system_colors()
-{
- open_display();
- const char* key1 = 0;
- if (Fl::first_window()) key1 = Fl::first_window()->xclass();
- if (!key1) key1 = "fltk";
- if (!bg2_set)
- getsyscolor("Text","background", fl_bg2, "#ffffff", Fl::background2);
- if (!fg_set)
- getsyscolor(key1, "foreground", fl_fg, "#000000", Fl::foreground);
- if (!bg_set)
- getsyscolor(key1, "background", fl_bg, "#c0c0c0", Fl::background);
- getsyscolor("Text", "selectBackground", 0, "#000080", set_selection_color);
-}
-
-
-Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h,
- Fl_Window *win,
- bool ignore, bool *p_ignore) {
- struct wld_window* xid = win ? fl_wl_xid(win) : NULL;
- if (win && (!xid || !xid->buffer)) return NULL;
- struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer;
- if (win) buffer = &xid->buffer->draw_buffer;
- else {
- Fl_Image_Surface_Driver *dr = (Fl_Image_Surface_Driver*)Fl_Surface_Device::surface();
- buffer = Fl_Wayland_Graphics_Driver::offscreen_buffer(
- dr->image_surface()->offscreen());
- }
- float s = win ?
- Fl_Wayland_Window_Driver::driver(win)->wld_scale() * scale(win->screen_num()) :
- Fl_Surface_Device::surface()->driver()->scale();
- int Xs, Ys, ws, hs;
- if (s == 1) {
- Xs = X; Ys = Y; ws = w; hs = h;
- } else {
- Xs = Fl_Scalable_Graphics_Driver::floor(X, s);
- Ys = Fl_Scalable_Graphics_Driver::floor(Y, s);
- ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Xs;
- hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Ys;
- }
- if (ws == 0 || hs == 0) return NULL;
- uchar *data = new uchar[ws * hs * 3];
- uchar *p = data, *q;
- for (int j = 0; j < hs; j++) {
- q = buffer->buffer + (j+Ys) * buffer->stride + 4 * Xs;
- for (int i = 0; i < ws; i++) {
- *p++ = *(q+2); // R
- *p++ = *(q+1); // G
- *p++ = *q; // B
- q += 4;
- }
- }
- Fl_RGB_Image *rgb = new Fl_RGB_Image(data, ws, hs, 3);
- rgb->alloc_array = 1;
- return rgb;
-}
-
-
-void Fl_Wayland_Screen_Driver::offscreen_size(Fl_Offscreen off_, int &width, int &height)
-{
- struct Fl_Wayland_Graphics_Driver::draw_buffer *off = Fl_Wayland_Graphics_Driver::offscreen_buffer(off_);
- width = off->width;
- height = off->data_size / off->stride;
-}
-
-
-float Fl_Wayland_Screen_Driver::scale(int n) {
- Fl_Wayland_Screen_Driver::output *output;
- int i = 0;
- wl_list_for_each(output, &outputs, link) {
- if (i++ == n) break;
- }
- return output->gui_scale;
-}
-
-
-void Fl_Wayland_Screen_Driver::scale(int n, float f) {
- Fl_Wayland_Screen_Driver::output *output;
- int i = 0;
- wl_list_for_each(output, &outputs, link) {
- if (i++ == n) {
- output->gui_scale = f;
- return;
- }
- }
-}
-
-
-void Fl_Wayland_Screen_Driver::set_cursor() {
- do_set_cursor(seat);
-}
-
-
-struct wl_cursor *Fl_Wayland_Screen_Driver::default_cursor() {
- return seat->default_cursor;
-}
-
-
-void Fl_Wayland_Screen_Driver::default_cursor(struct wl_cursor *cursor) {
- seat->default_cursor = cursor;
- do_set_cursor(seat);
-}
-
-
-struct wl_cursor *Fl_Wayland_Screen_Driver::cache_cursor(const char *cursor_name) {
- return wl_cursor_theme_get_cursor(seat->cursor_theme, cursor_name);
-}
-
-
-void Fl_Wayland_Screen_Driver::reset_cursor() {
- for (int i = 0; i < cursor_count; i++) xc_cursor[i] = NULL;
-}
-
-
-uint32_t Fl_Wayland_Screen_Driver::get_serial() {
- return seat->serial;
-}
-
-
-struct wl_seat*Fl_Wayland_Screen_Driver::get_wl_seat() {
- return seat->wl_seat;
-}
-
-
-char *Fl_Wayland_Screen_Driver::get_seat_name() {
- return seat->name;
-}
-
-
-struct xkb_keymap *Fl_Wayland_Screen_Driver::get_xkb_keymap() {
- return seat->xkb_keymap;
-}
-
-
-int Fl_Wayland_Screen_Driver::get_mouse(int &xx, int &yy) {
- open_display();
- xx = Fl::e_x_root; yy = Fl::e_y_root;
- if (!seat->pointer_focus) return 0;
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(seat->pointer_focus);
- if (!win) return 0;
- int snum = Fl_Window_Driver::driver(win)->screen_num();
-//printf("get_mouse(%dx%d)->%d\n", xx, yy, snum);
- return snum;
-}
-
-
-void Fl_Wayland_Screen_Driver::set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win) {
- Fl_Wayland_Screen_Driver::insertion_point_location(x, y, height);
-}
-
-
-void Fl_Wayland_Screen_Driver::reset_spot() {
- Fl::compose_state = 0;
- Fl_Wayland_Screen_Driver::next_marked_length = 0;
- Fl_Wayland_Screen_Driver::insertion_point_location_is_valid = false;
-}
-
-
-void Fl_Wayland_Screen_Driver::display(const char *d)
-{
- if (d && !wl_registry) { // if display was opened, it's too late
- if (wl_display) {
- // only the wl_display_connect() call was done, redo it because the target
- // Wayland compositor may be different
- wl_display_disconnect(wl_display);
- }
- wl_display = wl_display_connect(d);
- if (!wl_display) {
- fprintf(stderr, "Error: '%s' is not an active Wayland socket\n", d);
- exit(1);
- }
- }
-}
-
-
-void *Fl_Wayland_Screen_Driver::control_maximize_button(void *data) {
- // The code below aims at removing the calling window's fullscreen button
- // while dialog runs. Unfortunately, it doesn't work with some X11 window managers
- // (e.g., KDE, xfce) because the button goes away but doesn't come back,
- // so we move this code to a virtual member function.
- // Noticeably, this code works OK under Wayland.
- struct win_dims {
- Fl_Widget_Tracker *tracker;
- int minw, minh, maxw, maxh;
- struct win_dims *next;
- };
-
- if (!data) { // this call turns each decorated window's maximize button off
- struct win_dims *first_dim = NULL;
- // consider all bordered, top-level FLTK windows
- Fl_Window *win = Fl::first_window();
- while (win) {
- if (!win->parent() && win->border() &&
- !( ((struct wld_window*)Fl_X::flx(win)->xid)->state &
- LIBDECOR_WINDOW_STATE_MAXIMIZED) ) {
- win_dims *dim = new win_dims;
- dim->tracker = new Fl_Widget_Tracker(win);
- win->get_size_range(&dim->minw, &dim->minh, &dim->maxw, &dim->maxh, NULL, NULL, NULL);
- //make win un-resizable
- win->size_range(win->w(), win->h(), win->w(), win->h());
- dim->next = first_dim;
- first_dim = dim;
- }
- win = Fl::next_window(win);
- }
- return first_dim;
- } else { // this call returns each decorated window's maximize button to its previous state
- win_dims *first_dim = (win_dims *)data;
- while (first_dim) {
- win_dims *dim = first_dim;
- //give back win its resizing parameters
- if (dim->tracker->exists()) {
- Fl_Window *win = (Fl_Window*)dim->tracker->widget();
- win->size_range(dim->minw, dim->minh, dim->maxw, dim->maxh);
- }
- first_dim = dim->next;
- delete dim->tracker;
- delete dim;
- }
- return NULL;
- }
-}
-
-
-int Fl_Wayland_Screen_Driver::poll_or_select_with_delay(double time_to_wait) {
- if (wl_display_dispatch_pending(wl_display) > 0) return 1;
- return Fl_Unix_Screen_Driver::poll_or_select_with_delay(time_to_wait);
-}
-
-
-// like Fl_Wayland_Screen_Driver::poll_or_select_with_delay(0.0) except no callbacks are done:
-int Fl_Wayland_Screen_Driver::poll_or_select() {
- int ret = wl_display_prepare_read(wl_display);
- if (ret == 0) wl_display_cancel_read(wl_display);
- else return 1;
- return Fl_Unix_Screen_Driver::poll_or_select();
-}
-
-
-int Fl_Wayland_Screen_Driver::event_key(int k) {
- if (k >= 'A' && k <= 'Z') k += 32;
- return (search_int_vector(key_vector, k) >= 0);
-}
-
-
-int Fl_Wayland_Screen_Driver::get_key(int k) {
- return event_key(k);
-}
-
-
-float Fl_Wayland_Screen_Driver::base_scale(int numscreen) {
- const char *p;
- float factor = 1;
- if ((p = fl_getenv("FLTK_SCALING_FACTOR"))) {
- sscanf(p, "%f", &factor);
- }
- return factor;
-}
-
-
-struct wl_display *fl_wl_display() {
- return Fl_Wayland_Screen_Driver::wl_display;
-}
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
deleted file mode 100644
index c5c1bee50..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
+++ /dev/null
@@ -1,185 +0,0 @@
-//
-// Definition of Wayland window driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2025 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_Wayland_Window_Driver.H
- \brief Definition of Wayland window driver.
- */
-
-#ifndef FL_WAYLAND_WINDOW_DRIVER_H
-#define FL_WAYLAND_WINDOW_DRIVER_H
-
-#include <config.h>
-#include "../../Fl_Window_Driver.H"
-#include <FL/Fl_Plugin.H>
-#include "Fl_Wayland_Screen_Driver.H"
-#include "Fl_Wayland_Graphics_Driver.H"
-
-
-/*
- Move everything here that manages the native window interface.
-
- There is one window driver for each Fl_Window. Window drivers manage window
- actions such as resizing, events, decoration, fullscreen modes, etc. . All
- drawing and rendering is managed by the Surface device and the associated
- graphics driver.
-
- - window specific event handling
- - window types and styles, depth, etc.
- - decorations
- */
-
-typedef struct _cairo_pattern cairo_pattern_t;
-typedef struct _cairo_rectangle_int cairo_rectangle_int_t;
-class Fl_Wayland_Plugin;
-
-
-class Fl_Wayland_Window_Driver : public Fl_Window_Driver
-{
- friend class Fl_Wayland_Gl_Window_Driver;
-private:
- struct shape_data_type {
- int lw_; ///< width of shape image
- int lh_; ///< height of shape image
- Fl_Image* shape_; ///< shape image
- cairo_pattern_t *mask_pattern_;
- } *shape_data_;
- bool can_expand_outside_parent_; // specially to allow window docking (#987)
- cairo_rectangle_int_t *subRect_; // makes sure subwindow remains inside its parent window
- static bool in_flush_; // useful for progressive window drawing
- Fl_Cursor standard_cursor_; // window's standard custom kind
- struct gl_start_support *gl_start_support_; // for support of gl_start/gl_finish
- bool is_popup_window_;
-public:
- inline Fl_Cursor standard_cursor() { return standard_cursor_; }
- bool in_handle_configure; // distinguish OS and user window resize
-
- struct surface_output { // for linked list of displays where a surface maps
- struct Fl_Wayland_Screen_Driver::output *output;
- struct wl_list link;
- };
- struct custom_cursor {
- struct wl_cursor *wl_cursor;
- const Fl_RGB_Image *rgb;
- int hotx, hoty;
- };
- static void delete_cursor(struct custom_cursor *custom, bool delete_rgb = true);
- void decorated_win_size(int &w, int &h);
- void shape_bitmap_(Fl_Image* b);
- void shape_alpha_(Fl_Image* img, int offset) override;
- FL_EXPORT int wld_scale(); // used by class Fl_Wayland_Gl_Window_Driver
- cairo_rectangle_int_t *subRect() { return subRect_; } // getter
- void subRect(cairo_rectangle_int_t *r); // setter
- void checkSubwindowFrame();
- enum kind {DECORATED, SUBWINDOW, POPUP, UNFRAMED};
- struct xdg_toplevel *xdg_toplevel();
- Fl_Wayland_Window_Driver(Fl_Window*);
- virtual ~Fl_Wayland_Window_Driver();
- static struct wld_window *wld_window;
- static Fl_Window *surface_to_window(struct wl_surface *);
-
- static inline Fl_Wayland_Window_Driver* driver(const Fl_Window *w) {
- return (Fl_Wayland_Window_Driver*)Fl_Window_Driver::driver(w);
- }
- static Fl_Wayland_Plugin *gl_plugin();
-
- // --- window data
- int decorated_w() override;
- int decorated_h() override;
- const Fl_Image* shape() override;
-
- // --- window management
- void makeWindow() override;
- void take_focus() override;
- void flush() override;
- void flush_overlay() override;
- void draw_end() override;
- void make_current() override;
- void show() override;
- void resize(int X,int Y,int W,int H) override;
- void label(const char *name, const char *mininame) override;
- void hide() override;
- void map() override;
- void unmap() override;
- void fullscreen_on() override;
- void fullscreen_off(int X, int Y, int W, int H) override;
- void maximize() override;
- void un_maximize() override;
- void use_border() override;
- void size_range() override;
- void iconize() override;
- void decoration_sizes(int *top, int *left, int *right, int *bottom) override;
- // --- window cursor stuff
- int set_cursor(Fl_Cursor) override;
- int set_cursor(const Fl_RGB_Image*, int, int) override;
- int set_cursor_4args(const Fl_RGB_Image*, int, int, bool);
-
- void shape(const Fl_Image* img) override;
- void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left,
- Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) override;
- int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
- void (*draw_area)(void*, int,int,int,int), void* data) override;
- void wait_for_expose() override;
- // menu-related stuff
- void reposition_menu_window(int x, int y) override;
- void menu_window_area(int &X, int &Y, int &W, int &H, int nscreen = -1) override;
- static bool new_popup; // to support tall menu buttons
- bool process_menu_or_tooltip(struct wld_window *);
- static Fl_Window *previous_floatingtitle; // to support floating menuwindow w/ title
- void allow_expand_outside_parent() override { can_expand_outside_parent_ = true; }
-};
-
-
-struct wld_window {
- Fl_Window *fl_win;
- struct wl_list outputs; // linked list of displays where part or whole of window maps
- struct wl_surface *wl_surface;
- struct wl_callback *frame_cb;
- struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer;
- struct xdg_surface *xdg_surface;
- union { // for each value of kind
- struct libdecor_frame *frame;
- struct wl_subsurface *subsurface;
- struct xdg_popup *xdg_popup;
- struct xdg_toplevel *xdg_toplevel;
- };
- // non-null when using custom cursor
- struct Fl_Wayland_Window_Driver::custom_cursor *custom_cursor;
-#if HAVE_XDG_DIALOG
- struct xdg_dialog_v1 *xdg_dialog;
-#endif
- enum Fl_Wayland_Window_Driver::kind kind;
- int configured_width;
- int configured_height;
- int floating_width;
- int floating_height;
- int state;
- bool covered; // specially for Mutter and issue #878
-};
-
-
-class Fl_Wayland_Plugin : public Fl_Plugin {
-public:
- Fl_Wayland_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { }
- virtual const char *klass() { return "wayland.fltk.org"; }
- virtual const char *name() = 0;
- virtual void do_swap(Fl_Window*) = 0;
- virtual void invalidate(Fl_Window*) = 0;
- virtual void terminate() = 0;
- virtual void destroy(struct gl_start_support *) = 0;
-};
-
-#endif // FL_WAYLAND_WINDOW_DRIVER_H
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
deleted file mode 100644
index 0495fb7bc..000000000
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ /dev/null
@@ -1,2191 +0,0 @@
-//
-// Implementation of the Wayland window driver.
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/platform.H>
-#include "Fl_Wayland_Window_Driver.H"
-#include "Fl_Wayland_Screen_Driver.H"
-#include "Fl_Wayland_Graphics_Driver.H"
-#include <FL/filename.H>
-#include <wayland-cursor.h>
-#include "../../../libdecor/build/fl_libdecor.h"
-#include "xdg-shell-client-protocol.h"
-#include "gtk-shell-client-protocol.h"
-#if HAVE_XDG_DIALOG
-# include "xdg-dialog-client-protocol.h"
-#endif
-#include <pango/pangocairo.h>
-#include <FL/Fl_Overlay_Window.H>
-#include <FL/Fl_Tooltip.H>
-#include <FL/fl_draw.H>
-#include <FL/fl_ask.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Image_Surface.H>
-#include <FL/Fl_Menu_Button.H>
-#include <string.h>
-#include <math.h> // for ceil()
-#include <sys/types.h> // for pid_t
-#include <unistd.h> // for getpid()
-
-struct cursor_image { // as in wayland-cursor.c of the Wayland project source code
- struct wl_cursor_image image;
- struct wl_cursor_theme *theme;
- struct wl_buffer *buffer;
- int offset; /* data offset of this image in the shm pool */
-};
-
-extern "C" {
-# include "../../../libdecor/src/libdecor-plugin.h"
- uchar *fl_libdecor_titlebar_buffer(struct libdecor_frame *frame, int *w, int *h, int *stride);
-}
-
-#define fl_max(a,b) ((a) > (b) ? (a) : (b))
-#define fl_min(a,b) ((a) < (b) ? (a) : (b))
-
-#if !defined(FLTK_USE_X11)
-Window fl_window = 0;
-#endif
-
-
-struct wld_window *Fl_Wayland_Window_Driver::wld_window = NULL;
-bool Fl_Wayland_Window_Driver::new_popup = false; // to support tall menu buttons
-// A menutitle to be mapped later as the child of a menuwindow
-Fl_Window *Fl_Wayland_Window_Driver::previous_floatingtitle = NULL;
-
-
-Fl_Wayland_Window_Driver::Fl_Wayland_Window_Driver(Fl_Window *win) : Fl_Window_Driver(win)
-{
- shape_data_ = NULL;
- standard_cursor_ = FL_CURSOR_DEFAULT;
- in_handle_configure = false;
- screen_num_ = -1;
- gl_start_support_ = NULL;
- subRect_ = NULL;
- is_popup_window_ = false;
- can_expand_outside_parent_ = false;
-}
-
-
-void Fl_Wayland_Window_Driver::delete_cursor(
- struct Fl_Wayland_Window_Driver::custom_cursor *custom, bool delete_rgb) {
- struct wl_cursor *wl_cursor = custom->wl_cursor;
- struct cursor_image *new_image = (struct cursor_image*)wl_cursor->images[0];
- struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen =
- (struct Fl_Wayland_Graphics_Driver::wld_buffer *)
- wl_buffer_get_user_data(new_image->buffer);
- struct wld_window fake_xid;
- memset(&fake_xid, 0, sizeof(fake_xid));
- fake_xid.buffer = offscreen;
- Fl_Wayland_Graphics_Driver::buffer_release(&fake_xid);
- free(new_image);
- free(wl_cursor->images);
- free(wl_cursor->name);
- free(wl_cursor);
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->default_cursor() == wl_cursor) {
- scr_driver->default_cursor(scr_driver->xc_cursor[Fl_Wayland_Screen_Driver::arrow]);
- }
- if (delete_rgb) delete custom->rgb;
- delete custom;
-}
-
-
-Fl_Wayland_Window_Driver::~Fl_Wayland_Window_Driver()
-{
- if (shape_data_) {
- cairo_surface_t *surface;
- cairo_pattern_get_surface(shape_data_->mask_pattern_, &surface);
- uchar *data = cairo_image_surface_get_data(surface);
- cairo_pattern_destroy(shape_data_->mask_pattern_);
- delete[] data;
- delete shape_data_;
- }
- if (subRect_) delete subRect_;
- if (gl_start_support_) { // occurs only if gl_start/gl_finish was used
- gl_plugin()->destroy(gl_start_support_);
- }
-}
-
-
-void Fl_Wayland_Window_Driver::decorated_win_size(int &w, int &h)
-{
- Fl_Window *win = pWindow;
- w = win->w();
- h = win->h();
- if (!win->shown() || win->parent() || !win->border() || !win->visible()) return;
- int X, titlebar_height;
- libdecor_frame_translate_coordinate(fl_wl_xid(win)->frame, 0, 0, &X, &titlebar_height);
-//printf("titlebar_height=%d\n",titlebar_height);
- h = win->h() + ceil(titlebar_height / Fl::screen_scale(win->screen_num()));
-}
-
-
-int Fl_Wayland_Window_Driver::decorated_h()
-{
- int w, h;
- decorated_win_size(w, h);
- return h;
-}
-
-
-int Fl_Wayland_Window_Driver::decorated_w()
-{
- int w, h;
- decorated_win_size(w, h);
- return w;
-}
-
-
-struct xdg_toplevel *Fl_Wayland_Window_Driver::xdg_toplevel() {
- struct wld_window * w = fl_wl_xid(pWindow);
- struct xdg_toplevel *top = NULL;
- if (w->kind == DECORATED) top = libdecor_frame_get_xdg_toplevel(w->frame);
- else if (w->kind == UNFRAMED) top = w->xdg_toplevel;
- return top;
-}
-
-
-void Fl_Wayland_Window_Driver::take_focus()
-{
- struct wld_window *w = fl_wl_xid(pWindow);
- if (w) {
- Fl_Window *old_first = Fl::first_window();
- struct wld_window *first_xid = (old_first ? fl_wl_xid(old_first->top_window()) : NULL);
- if (first_xid && first_xid != w && xdg_toplevel()) {
- // this will move the target window to the front
- Fl_Wayland_Window_Driver *top_dr =
- Fl_Wayland_Window_Driver::driver(old_first->top_window());
- xdg_toplevel_set_parent(xdg_toplevel(), top_dr->xdg_toplevel());
- // this will remove the parent-child relationship
- xdg_toplevel_set_parent(xdg_toplevel(), NULL);
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
- }
- // this sets the first window
- fl_wl_find(w);
- }
-}
-
-
-void Fl_Wayland_Window_Driver::flush_overlay()
-{
- if (!shown()) return;
- Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
- int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY) | (overlay() == oWindow);
- pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
- pWindow->make_current();
- if (!other_xid) {
- other_xid = new Fl_Image_Surface(oWindow->w(), oWindow->h(), 1);
- oWindow->clear_damage(FL_DAMAGE_ALL);
- }
- if (oWindow->damage() & ~FL_DAMAGE_EXPOSE) {
- Fl_X *myi = Fl_X::flx(pWindow);
- fl_clip_region(myi->region); myi->region = 0;
- Fl_Surface_Device::push_current(other_xid);
- draw();
- Fl_Surface_Device::pop_current();
- }
- if (erase_overlay) fl_clip_region(0);
- if (other_xid) {
- struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer =
- Fl_Wayland_Graphics_Driver::offscreen_buffer(other_xid->offscreen());
- struct wld_window *xid = fl_wl_xid(pWindow);
- struct Fl_Wayland_Graphics_Driver::wld_buffer *wbuffer = xid->buffer;
- if (wbuffer->draw_buffer.data_size != buffer->data_size) {
- fl_copy_offscreen(0, 0, oWindow->w(), oWindow->h(), other_xid->offscreen(), 0, 0);
- } else {
- memcpy(wbuffer->draw_buffer.buffer, buffer->buffer, wbuffer->draw_buffer.data_size);
- }
- }
- if (overlay() == oWindow) oWindow->draw_overlay();
-}
-
-
-const Fl_Image* Fl_Wayland_Window_Driver::shape() {
- return shape_data_ ? shape_data_->shape_ : NULL;
-}
-
-
-void Fl_Wayland_Window_Driver::shape_bitmap_(Fl_Image* b) {
- shape_data_->mask_pattern_ = Fl_Cairo_Graphics_Driver::bitmap_to_pattern(
- (Fl_Bitmap*)b, true, NULL);
- shape_data_->shape_ = b;
- shape_data_->lw_ = b->data_w();
- shape_data_->lh_ = b->data_h();
-}
-
-
-void Fl_Wayland_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
- int i, j, d = img->d(), w = img->data_w(), h = img->data_h();
- int bytesperrow = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w);
- unsigned u;
- uchar byte, onebit;
- // build a CAIRO_FORMAT_A1 surface covering the non-fully transparent/black part of the image
- uchar* bits = new uchar[h*bytesperrow]; // to store the surface data
- const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of pixels
- for (i = 0; i < h; i++) {
- uchar *p = (uchar*)bits + i * bytesperrow;
- byte = 0;
- onebit = 1;
- for (j = 0; j < w; j++) {
- if (d == 3) {
- u = *alpha;
- u += *(alpha+1);
- u += *(alpha+2);
- }
- else u = *alpha;
- if (u > 0) { // if the pixel is not fully transparent/black
- byte |= onebit; // turn on the corresponding bit of the bitmap
- }
- onebit = onebit << 1; // move the single set bit one position to the left
- if (onebit == 0 || j == w-1) {
- onebit = 1;
- *p++ = ~byte; // store in bitmap one pack of bits, complemented
- byte = 0;
- }
- alpha += d; // point to alpha value of next img pixel
- }
- }
- cairo_surface_t *mask_surf = cairo_image_surface_create_for_data(bits, CAIRO_FORMAT_A1,
- w, h, bytesperrow);
- shape_data_->mask_pattern_ = cairo_pattern_create_for_surface(mask_surf);
- cairo_surface_destroy(mask_surf);
- shape_data_->shape_ = img;
- shape_data_->lw_ = w;
- shape_data_->lh_ = h;
-}
-
-
-void Fl_Wayland_Window_Driver::shape(const Fl_Image* img) {
- if (shape_data_) {
- if (shape_data_->mask_pattern_) {
- cairo_surface_t *surface;
- cairo_pattern_get_surface(shape_data_->mask_pattern_, &surface);
- uchar *data = cairo_image_surface_get_data(surface);
- cairo_pattern_destroy(shape_data_->mask_pattern_);
- delete[] data;
- }
- }
- else {
- shape_data_ = new shape_data_type;
- }
- memset(shape_data_, 0, sizeof(shape_data_type));
- pWindow->border(false);
- int d = img->d();
- if (d && img->count() >= 2) {
- shape_pixmap_((Fl_Image*)img);
- shape_data_->shape_ = (Fl_Image*)img;
- }
- else if (d == 0) shape_bitmap_((Fl_Image*)img);
- else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
- else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
-}
-
-
-void Fl_Wayland_Window_Driver::draw_end()
-{
- if (shape_data_ && shape_data_->mask_pattern_) {
- Fl_Wayland_Graphics_Driver *gr_dr = (Fl_Wayland_Graphics_Driver*)fl_graphics_driver;
- cairo_t *cr = gr_dr->cr();
- cairo_matrix_t matrix;
- cairo_matrix_init_scale(&matrix, double(shape_data_->lw_) / (pWindow->w() + 1),
- double(shape_data_->lh_) / (pWindow->h() + 1) );
- cairo_matrix_translate(&matrix, 1, 1);
- cairo_pattern_set_matrix(shape_data_->mask_pattern_, &matrix);
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_mask(cr, shape_data_->mask_pattern_);
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- }
-}
-
-
-/* Returns images of the captures of the window title-bar, and the left, bottom and right window borders
- (or NULL if a particular border is absent).
- Returned images can be deleted after use. Their depth and size may be platform-dependent.
- The top and bottom images extend from left of the left border to right of the right border.
- */
-void Fl_Wayland_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top,
- Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right)
-{
- top = left = bottom = right = NULL;
- if (pWindow->decorated_h() == h()) return;
- int htop = pWindow->decorated_h() - pWindow->h();
- struct wld_window *wwin = fl_wl_xid(pWindow);
- int width, height, stride;
- uchar *cairo_data = fl_libdecor_titlebar_buffer(wwin->frame, &width, &height, &stride);
- if (!cairo_data) return;
- uchar *data = new uchar[width * height * 4];
- uchar *p = data;
- for (int j = 0; j < height; j++) {
- uchar *q = cairo_data + j * stride;
- for (int i = 0; i < width; i++) {
- *p++ = *(q+2); // R
- *p++ = *(q+1); // G
- *p++ = *q; // B
- *p++ = *(q+3); // A
- q += 4;
- }
- }
- top = new Fl_RGB_Image(data, width, height, 4);
- top->alloc_array = 1;
- top->scale(pWindow->w(), htop);
-}
-
-
-// make drawing go into this window (called by subclass flush() impl.)
-void Fl_Wayland_Window_Driver::make_current() {
- if (!shown()) {
- static const char err_message[] = "Fl_Window::make_current(), but window is not shown().";
- fl_alert(err_message);
- Fl::fatal(err_message);
- }
-
- struct wld_window *window = fl_wl_xid(pWindow);
- if (window->buffer) {
- ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag(
- &window->buffer->draw_buffer_needs_commit);
- }
-
- // to support progressive drawing
- if ( (!Fl_Wayland_Window_Driver::in_flush_) && window->buffer && (!window->frame_cb) &&
- (!wait_for_expose_value) ) {
- Fl_Wayland_Graphics_Driver::buffer_commit(window);
- }
-
- Fl_Wayland_Window_Driver::wld_window = window;
- fl_window = (Window)window;
- float f = Fl::screen_scale(pWindow->screen_num());
- int wld_s = wld_scale();
- if (!window->buffer) {
- window->buffer = Fl_Wayland_Graphics_Driver::create_wld_buffer(
- int(pWindow->w() * f) * wld_s, int(pWindow->h() * f) * wld_s, false);
- ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag(
- &window->buffer->draw_buffer_needs_commit);
- }
- ((Fl_Wayland_Graphics_Driver*)fl_graphics_driver)->set_cairo(
- window->buffer->draw_buffer.cairo_, f * wld_s);
- ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->wld_scale = wld_s;
- int *poffset = Fl_Window_Driver::menu_offset_y(pWindow);
- if (poffset) { // for tall menu windows under KWIN to offset drawing inside window
- cairo_translate(window->buffer->draw_buffer.cairo_, 0, *poffset);
- }
- cairo_rectangle_int_t *extents = subRect();
- if (extents) { // make damage-to-buffer not to leak outside parent
- Fl_Region clip_region = fl_graphics_driver->XRectangleRegion(extents->x, extents->y,
- extents->width, extents->height);
-//printf("make_current: %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height);
- Fl_X::flx(pWindow)->region = clip_region;
- }
- else fl_graphics_driver->clip_region(0);
-
-#ifdef FLTK_HAVE_CAIROEXT
- // update the cairo_t context
- if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow);
-#endif
-}
-
-
-void Fl_Wayland_Window_Driver::flush() {
- if (!pWindow->damage()) return;
- if (pWindow->as_gl_window()) {
- int W = pWindow->w();
- int H = pWindow->h();
- float scale = fl_graphics_driver->scale();
- Fl_Wayland_Window_Driver::in_flush_ = true;
- Fl_Window_Driver::flush();
- Fl_Wayland_Window_Driver::in_flush_ = false;
- gl_plugin()->do_swap(pWindow); // useful only for GL win with overlay
- if (scale != fl_graphics_driver->scale() || W != pWindow->w() || H != pWindow->h()) {
- gl_plugin()->invalidate(pWindow);
- }
- return;
- }
- struct wld_window *window = fl_wl_xid(pWindow);
- if (!window || !window->configured_width) return;
-
- Fl_X *ip = Fl_X::flx(pWindow);
- cairo_region_t* r = (cairo_region_t*)ip->region;
- if (!window->buffer || pWindow->as_overlay_window()) r = NULL;
-
- Fl_Wayland_Window_Driver::in_flush_ = true;
- Fl_Window_Driver::flush();
- Fl_Wayland_Window_Driver::in_flush_ = false;
- if (!window->frame_cb) Fl_Wayland_Graphics_Driver::buffer_commit(window, r);
-}
-
-
-void Fl_Wayland_Window_Driver::show() {
- if (!shown()) {
- fl_open_display();
- makeWindow();
- } else {
- // Wayland itself gives no way to programmatically unminimize a minimized window
- Fl::handle(FL_SHOW, pWindow);
- }
-}
-
-
-static void popup_done(void *data, struct xdg_popup *xdg_popup);
-
-
-static void destroy_surface_caution_pointer_focus(struct wl_surface *surface,
- struct Fl_Wayland_Screen_Driver::seat *seat) {
- if (seat->pointer_focus == surface) seat->pointer_focus = NULL;
- if (seat->keyboard_surface == surface) seat->keyboard_surface = NULL;
- wl_surface_destroy(surface);
-}
-
-
-void Fl_Wayland_Window_Driver::hide() {
- if (pWindow == Fl_Screen_Driver::transient_scale_parent) {
- // Delete also the running transient scale window
- // because the transient is a popup and MUST be deleted
- // before its parent.
- Fl::remove_timeout(Fl_Screen_Driver::del_transient_window);
- Fl_Screen_Driver::del_transient_window(NULL);
- }
- Fl_X* ip = Fl_X::flx(pWindow);
- if (hide_common()) return;
- if (ip->region) {
- Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
- ip->region = 0;
- }
- screen_num_ = -1;
- struct wld_window *wld_win = (struct wld_window*)ip->xid;
- if (wld_win) { // this test makes sure ip->xid has not been destroyed already
- Fl_Wayland_Graphics_Driver::buffer_release(wld_win);
- if (wld_win->kind == SUBWINDOW && wld_win->subsurface) {
- wl_subsurface_destroy(wld_win->subsurface);
- wld_win->subsurface = NULL;
- }
-#if HAVE_XDG_DIALOG
- if (wld_win->xdg_dialog) {
- xdg_dialog_v1_destroy(wld_win->xdg_dialog);
- wld_win->xdg_dialog = NULL;
- }
-#endif
- if (wld_win->kind == DECORATED) {
- libdecor_frame_unref(wld_win->frame);
- wld_win->frame = NULL;
- wld_win->xdg_surface = NULL;
- } else {
- if (wld_win->kind == POPUP && wld_win->xdg_popup) {
- popup_done(xdg_popup_get_user_data(wld_win->xdg_popup), wld_win->xdg_popup);
- wld_win->xdg_popup = NULL;
- }
- if (wld_win->kind == UNFRAMED && wld_win->xdg_toplevel) {
- xdg_toplevel_destroy(wld_win->xdg_toplevel);
- wld_win->xdg_toplevel = NULL;
- }
- if (wld_win->xdg_surface) {
- xdg_surface_destroy(wld_win->xdg_surface);
- wld_win->xdg_surface = NULL;
- }
- }
- if (wld_win->custom_cursor) delete_cursor(wld_win->custom_cursor);
- if (wld_win->wl_surface) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- destroy_surface_caution_pointer_focus(wld_win->wl_surface, scr_driver->seat);
- wld_win->wl_surface = NULL;
- }
- while (!wl_list_empty(&wld_win->outputs)) { // remove from screens where it belongs
- struct surface_output *s_output;
- s_output = wl_container_of(wld_win->outputs.next, s_output, link);
- wl_list_remove(&s_output->link);
- free(s_output);
- }
- if (Fl_Wayland_Window_Driver::wld_window == wld_win) {
- Fl_Wayland_Window_Driver::wld_window = NULL;
- }
- if (wld_win->frame_cb) wl_callback_destroy(wld_win->frame_cb); // useful for GL subwins
- free(wld_win);
- }
- delete ip;
-}
-
-
-void Fl_Wayland_Window_Driver::map() {
- Fl_X* ip = Fl_X::flx(pWindow);
- struct wld_window *wl_win = (struct wld_window*)ip->xid;
- if (wl_win->kind == SUBWINDOW && !wl_win->subsurface) {
- struct wld_window *parent = fl_wl_xid(pWindow->window());
- if (parent) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- wl_win->subsurface = wl_subcompositor_get_subsurface(scr_driver->wl_subcompositor,
- wl_win->wl_surface, parent->wl_surface);
- float f = Fl::screen_scale(pWindow->top_window()->screen_num());
- wl_subsurface_set_position(wl_win->subsurface, pWindow->x() * f, pWindow->y() * f);
- wl_subsurface_set_desync(wl_win->subsurface); // important
- wl_subsurface_place_above(wl_win->subsurface, parent->wl_surface);
- wl_win->configured_width = pWindow->w();
- wl_win->configured_height = pWindow->h();
- wait_for_expose_value = 0;
- pWindow->redraw();
- }
- }
-}
-
-
-void Fl_Wayland_Window_Driver::unmap() {
- Fl_X* ip = Fl_X::flx(pWindow);
- struct wld_window *wl_win = (struct wld_window*)ip->xid;
- if (wl_win->kind == SUBWINDOW && wl_win->wl_surface) {
- wl_surface_attach(wl_win->wl_surface, NULL, 0, 0);
- Fl_Wayland_Graphics_Driver::buffer_release(wl_win);
- wl_subsurface_destroy(wl_win->subsurface);
- wl_win->subsurface = NULL;
- }
-}
-
-
-void Fl_Wayland_Window_Driver::size_range() {
- if (shown()) {
- Fl_X* ip = Fl_X::flx(pWindow);
- struct wld_window *wl_win = (struct wld_window*)ip->xid;
- float f = Fl::screen_scale(pWindow->screen_num());
- int minw, minh, maxw, maxh;
- pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL);
- if (wl_win->kind == DECORATED && wl_win->frame) {
- int X,Y,W,H;
- Fl::screen_work_area(X,Y,W,H, Fl::screen_num(x(),y(),w(),h()));
- if (maxw && maxw < W && maxh && maxh < H) {
- libdecor_frame_unset_capabilities(wl_win->frame, LIBDECOR_ACTION_FULLSCREEN);
- } else {
- libdecor_frame_set_capabilities(wl_win->frame, LIBDECOR_ACTION_FULLSCREEN);
- }
- if (maxw && maxh && (minw >= maxw || minh >= maxh)) {
- libdecor_frame_unset_capabilities(wl_win->frame, LIBDECOR_ACTION_RESIZE);
- } else {
- libdecor_frame_set_capabilities(wl_win->frame, LIBDECOR_ACTION_RESIZE);
- }
- libdecor_frame_set_min_content_size(wl_win->frame, minw*f, minh*f);
- libdecor_frame_set_max_content_size(wl_win->frame, maxw*f, maxh*f);
- if (xdg_toplevel()) {
- struct libdecor_state *state = libdecor_state_new(int(w() * f), int(h() * f));
- libdecor_frame_commit(wl_win->frame, state, NULL);
- libdecor_state_free(state);
- }
- } else if (wl_win->kind == UNFRAMED && wl_win->xdg_toplevel) {
- xdg_toplevel_set_min_size(wl_win->xdg_toplevel, minw*f, minh*f);
- if (maxw && maxh)
- xdg_toplevel_set_max_size(wl_win->xdg_toplevel, maxw*f, maxh*f);
- }
- }
-}
-
-
-void Fl_Wayland_Window_Driver::iconize() {
- Fl_X* ip = Fl_X::flx(pWindow);
- struct wld_window *wl_win = (struct wld_window*)ip->xid;
- if (wl_win->kind == DECORATED) {
- libdecor_frame_set_minimized(wl_win->frame);
- if (xdg_toplevel_get_version(xdg_toplevel()) < 6) {
- Fl::handle(FL_HIDE, pWindow);
- }
- }
- else if (wl_win->kind == UNFRAMED && wl_win->xdg_toplevel) xdg_toplevel_set_minimized(wl_win->xdg_toplevel);
-}
-
-
-void Fl_Wayland_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom)
-{
- struct wld_window *xid = (struct wld_window*)fl_xid(pWindow);
- if (xid && xid->kind == DECORATED) {
- libdecor_frame_translate_coordinate(xid->frame, 0, 0, left, top);
- *right = *left;
- *bottom = 0;
- } else {
- Fl_Window_Driver::decoration_sizes(top, left, right, bottom);
- }
-}
-
-
-int Fl_Wayland_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h,
- int dest_x, int dest_y,
- void (*draw_area)(void*, int,int,int,int), void* data)
-{
- struct wld_window * xid = fl_wl_xid(pWindow);
- struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = xid->buffer;
- float s = wld_scale() * fl_graphics_driver->scale();
- if (s != 1) {
- src_x = src_x * s;
- src_y = src_y * s;
- src_w = src_w * s;
- src_h = src_h * s;
- dest_x = dest_x * s;
- dest_y = dest_y * s;
- }
- if (src_x == dest_x) { // vertical scroll
- int i, to, step;
- if (src_y > dest_y) {
- i = 0; to = src_h; step = 1;
- } else {
- i = src_h - 1; to = -1; step = -1;
- }
- while (i != to) {
- memcpy(
- buffer->draw_buffer.buffer + (dest_y + i) * buffer->draw_buffer.stride + 4 * dest_x,
- buffer->draw_buffer.buffer + (src_y + i) * buffer->draw_buffer.stride + 4 * src_x,
- 4 * src_w);
- i += step;
- }
- } else { // horizontal scroll
- int i, to, step;
- if (src_x > dest_x) {
- i = 0; to = src_h; step = 1;
- } else {
- i = src_h - 1; to = -1; step = -1;
- }
- while (i != to) {
- memmove(
- buffer->draw_buffer.buffer + (src_y + i) * buffer->draw_buffer.stride + 4 * dest_x,
- buffer->draw_buffer.buffer + (src_y + i) * buffer->draw_buffer.stride + 4 * src_x,
- 4 * src_w);
- i += step;
- }
- }
- return 0;
-}
-
-
-static void handle_error(struct libdecor *libdecor_context, enum libdecor_error error, const char *message)
-{
- Fl::fatal("Caught error (%d): %s\n", error, message);
-}
-
-
-static struct libdecor_interface libdecor_iface = {
- .error = handle_error,
-};
-
-
-
-static void delayed_rescale(Fl_Window *win) {
- Fl_Window_Driver::driver(win)->is_a_rescale(true);
- win->size(win->w(), win->h());
- Fl_Window_Driver::driver(win)->is_a_rescale(false);
-}
-
-
-void change_scale(Fl_Wayland_Screen_Driver::output *output, struct wld_window *window,
- float pre_scale) {
- Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
- if (!window->fl_win->parent()) {
- // for top-level, set its screen number when the 1st screen for this surface changes
- Fl_Wayland_Screen_Driver::output *running_output;
- Fl_Wayland_Screen_Driver *scr_dr = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- int i = 0;
- wl_list_for_each(running_output, &scr_dr->outputs, link) { // each screen of the system
- if (running_output == output) { // we've found our screen of the system
- win_driver->screen_num(i);
- break;
- }
- i++;
- }
- }
- float post_scale = Fl::screen_scale(win_driver->screen_num()) * output->wld_scale;
-//printf("pre_scale=%.1f post_scale=%.1f\n", pre_scale, post_scale);
- if (post_scale != pre_scale) {
- if (window->kind == Fl_Wayland_Window_Driver::POPUP) {
- Fl_Wayland_Graphics_Driver::buffer_release(window);
- window->fl_win->redraw();
- } else {
- // delaying the rescaling is necessary to set first the window's size_range according to the new screen
- Fl::add_timeout(0, (Fl_Timeout_Handler)delayed_rescale, window->fl_win);
- }
- }
-}
-
-
-static void surface_enter(void *data, struct wl_surface *wl_surface,
- struct wl_output *wl_output) {
- struct wld_window *window = (struct wld_window*)data;
-
- if (!Fl_Wayland_Screen_Driver::own_output(wl_output))
- return;
-
- Fl_Wayland_Screen_Driver::output *output =
- (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output);
- if (output == NULL)
- return;
-
- bool list_was_empty = wl_list_empty(&window->outputs);
- struct Fl_Wayland_Window_Driver::surface_output *surface_output =
- (struct Fl_Wayland_Window_Driver::surface_output*)malloc(
- sizeof(struct Fl_Wayland_Window_Driver::surface_output));
- surface_output->output = output;
- // add to end of the linked list of displays of this surface
- struct wl_list *e = &window->outputs;
- while (e->next != &window->outputs) e = e->next; // move e to end of linked list
- wl_list_insert(e, &surface_output->link);
-//printf("window %p enters screen id=%d length=%d\n", window->fl_win, output->id, wl_list_length(&window->outputs));
- if (list_was_empty && !window->fl_win->parent()) {
- change_scale(output, window, 0);
- }
-}
-
-
-static void surface_leave(void *data, struct wl_surface *wl_surface,
- struct wl_output *wl_output) {
- if (!Fl_Wayland_Screen_Driver::own_output(wl_output))
- return;
- struct wld_window *window = (struct wld_window*)data;
- Fl_Wayland_Screen_Driver::output *output =
- (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output);
- Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
- float pre_scale = Fl::screen_scale(win_driver->screen_num()) * win_driver->wld_scale();
- struct Fl_Wayland_Window_Driver::surface_output *s_output;
- int count = 0;
- wl_list_for_each(s_output, &window->outputs, link) {
- count++;
- if (s_output->output == output) {
- wl_list_remove(&s_output->link);
- free(s_output);
-//printf("window %p leaves screen id=%d length=%d\n", window->fl_win, output->id, wl_list_length(&window->outputs));
- break;
- }
- }
- if (count == 1 && !wl_list_empty(&window->outputs) && !window->fl_win->parent()) {
- s_output = wl_container_of(window->outputs.next, s_output, link);
- change_scale(s_output->output, window, pre_scale);
- }
-}
-
-
-static struct wl_surface_listener surface_listener = {
- surface_enter,
- surface_leave,
-};
-
-
-Fl_Window *Fl_Wayland_Window_Driver::surface_to_window(struct wl_surface *surface) {
- if (surface) {
- if (wl_proxy_get_listener((struct wl_proxy *)surface) == &surface_listener) {
- return ((struct wld_window *)wl_surface_get_user_data(surface))->fl_win;
- }
- }
- return NULL;
-}
-
-
-static struct Fl_Wayland_Screen_Driver::output *screen_num_to_output(int num_screen) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- int i = 0;
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &(scr_driver->outputs), link) { // all screens of the system
- if (i++ == num_screen) return output;
- }
- return NULL;
-}
-
-
-#define LIBDECOR_MR131 1 // this means libdecor does not include MR!131 yet
-
-#ifdef LIBDECOR_MR131
-/* === Beginning of hack that would become un-needed if libdecor accepted MR!131 === */
-
-// true while the GUI is interactively resizing a decorated window
-static bool in_decorated_window_resizing = false;
-
-
-// libdecor's configure cb function for xdg_toplevel objects
-static void (*decor_xdg_toplevel_configure)(void*, struct xdg_toplevel *, int32_t,
- int32_t, struct wl_array *);
-
-
-static void fltk_xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel,
- int32_t width, int32_t height,
- struct wl_array *states) {
- uint32_t *p;
- in_decorated_window_resizing = false;
- // Replace wl_array_for_each(p, states) rejected by C++
- for (p = (uint32_t *)(states)->data;
- (const char *) p < ((const char *) (states)->data + (states)->size);
- (p)++) {
- if (*p == XDG_TOPLEVEL_STATE_RESIZING) {
- in_decorated_window_resizing = true;
- break;
- }
- }
- decor_xdg_toplevel_configure(user_data, xdg_toplevel, width, height, states);
-}
-
-
-struct wl_object { // copied from wayland-private.h
- const struct wl_interface *interface;
- const void *implementation;
- uint32_t id;
-};
-
-
-// replace libdecor's toplevel configure cb by FLTK's
-static void use_FLTK_toplevel_configure_cb(struct libdecor_frame *frame) {
- struct wl_object *object = (struct wl_object *)libdecor_frame_get_xdg_toplevel(frame);
- static struct xdg_toplevel_listener *fltk_listener = NULL;
- if (!fltk_listener) {
- struct xdg_toplevel_listener *decor_listener = (struct xdg_toplevel_listener*)
- object->implementation;
- fltk_listener = (struct xdg_toplevel_listener*)
- malloc(sizeof(struct xdg_toplevel_listener));
- // initialize FLTK's listener with libdecor's values
- *fltk_listener = *decor_listener;
- // memorize libdecor's toplevel configure cb
- decor_xdg_toplevel_configure = decor_listener->configure;
- // replace libdecor's toplevel configure cb by FLTK's
- fltk_listener->configure = fltk_xdg_toplevel_configure;
- }
- // replace the toplevel listener by a copy whose configure member is FLTK's
- object->implementation = fltk_listener;
-}
-
-/* === End of hack that would become un-needed if libdecor accepted MR!131 === */
-#endif // LIBDECOR_MR131
-
-
-// does win entirely cover its parent ?
-static void does_window_cover_parent(Fl_Window *win) {
- Fl_Window *parent = win->window();
- fl_wl_xid(parent)->covered = (win->x() <= 0 && win->y() <= 0 &&
- win->w() >= parent->w() && win->h() >= parent->h());
-}
-
-
-// recursively explore all shown subwindows in a window and call f for each
-static void scan_subwindows(Fl_Group *g, void (*f)(Fl_Window *)) {
- for (int i = 0; i < g->children(); i++) {
- Fl_Widget *o = g->child(i);
- if (o->as_window()) {
- if (!o->as_window()->shown()) continue;
- f(o->as_window());
- }
- if (o->as_group()) scan_subwindows(o->as_group(), f);
- }
-}
-
-// Generate FL_APP_ACTIVATE and FL_APP_DEACTIVATE events
-static bool app_has_active_window = false;
-
-// If a window is deactivated, check after a short delay if any other window has
-// become active. If not, send an FL_APP_DEACTIVATE event.
-static void deferred_check_app_deactivate(void*) {
- if (!app_has_active_window) return;
- app_has_active_window = false;
- // Check all FLTK windows to see if any are still active
- for (Fl_Window *w = Fl::first_window(); w; w = Fl::next_window(w)) {
- if (w->visible_r()) {
- struct wld_window* xid = fl_wl_xid(w);
- if (xid && (xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
- app_has_active_window = true;
- break;
- }
- }
- }
- if (!app_has_active_window) Fl::handle(FL_APP_DEACTIVATE, nullptr);
-}
-
-static void handle_configure(struct libdecor_frame *frame,
- struct libdecor_configuration *configuration, void *user_data)
-{
- struct wld_window *window = (struct wld_window*)user_data;
- if (!window->wl_surface) return;
- int width, height;
- enum libdecor_window_state window_state;
- struct libdecor_state *state;
- Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(window->fl_win);
- // true exactly for the 1st run of handle_configure() for this window
- bool is_1st_run = (window->xdg_surface == 0);
- // true exactly for the 2nd run of handle_configure() for this window
- bool is_2nd_run = (window->xdg_surface != 0 && driver->wait_for_expose_value);
- float f = Fl::screen_scale(window->fl_win->screen_num());
-
- if (!window->xdg_surface) window->xdg_surface = libdecor_frame_get_xdg_surface(frame);
-
-#ifdef LIBDECOR_MR131
- if (is_1st_run) use_FLTK_toplevel_configure_cb(frame);
-#endif
- struct wl_output *wl_output = NULL;
- if (window->fl_win->fullscreen_active()) {
- if (!(window->state & LIBDECOR_WINDOW_STATE_FULLSCREEN)) {
- if (Fl_Window_Driver::driver(window->fl_win)->force_position()) {
- struct Fl_Wayland_Screen_Driver::output *output =
- screen_num_to_output(window->fl_win->screen_num());
- if (output) wl_output = output->wl_output;
- }
- libdecor_frame_set_fullscreen(window->frame, wl_output);
- }
- } else if (driver->show_iconic()) {
- libdecor_frame_set_minimized(window->frame);
- driver->show_iconic(0);
- }
- if (!libdecor_configuration_get_window_state(configuration, &window_state))
- window_state = LIBDECOR_WINDOW_STATE_NONE;
- if ((window->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) &&
- !(window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) && !window->fl_win->border()) {
- // necessary so Mutter correctly positions borderless window back from fullscreen
- window->fl_win->redraw();
- }
- window->state = window_state;
-
- // Weston, KWin, and some old versions of Mutter, on purpose, don't set the
- // window width x height when xdg_toplevel_configure runs twice
- // during resizable window creation
- // (see https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/6).
- // Consequently, libdecor_configuration_get_content_size() may return false twice.
- // Weston and KWin, at least, don't change the window size asked by the client application
- // which is available here in floating_{width,height}.
- if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
- if (is_2nd_run) {
- width = window->floating_width;
- height = window->floating_height;
- if (!driver->is_resizable()) {
- libdecor_frame_set_min_content_size(frame, width, height);
- libdecor_frame_set_max_content_size(frame, width, height);
- }
- } else { width = height = 0; }
- }
- if (is_2nd_run && Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::MUTTER) {
- scan_subwindows(window->fl_win, does_window_cover_parent); // issue #878
- }
-
- if (window->fl_win->fullscreen_active() &&
- Fl_Window_Driver::driver(window->fl_win)->force_position()) {
- int X, Y, W, H;
- Fl::screen_xywh(X, Y, W, H, window->fl_win->screen_num());
- width = W * f; height = H * f;
- }
-
- if (width == 0) {
- width = window->floating_width;
- height = window->floating_height;
- //fprintf(stderr,"handle_configure: using floating %dx%d\n",width,height);
- }
-
-#ifndef LIBDECOR_MR131
- bool in_decorated_window_resizing = (window->state & LIBDECOR_WINDOW_STATE_RESIZING);
-#endif
- bool condition = in_decorated_window_resizing;
- if (condition) { // see issue #878
- condition = (window->covered ? (window->buffer && window->buffer->in_use) : (window->frame_cb != NULL));
- }
- if (condition) {
- // Skip resizing & redrawing. The last resize request won't be skipped because
- // LIBDECOR_WINDOW_STATE_RESIZING will be off or cb will be NULL then.
- return;
- }
-
- driver->in_handle_configure = true;
- window->fl_win->resize(0, 0, ceil(width / f), ceil(height / f));
- driver->in_handle_configure = false;
- if (wl_output) window->fl_win->redraw();
- window->configured_width = ceil(width / f);
- window->configured_height = ceil(height / f);
- if (is_2nd_run) driver->wait_for_expose_value = 0;
-//fprintf(stderr, "handle_configure fl_win=%p size:%dx%d state=%x wait_for_expose_value=%d is_2nd_run=%d\n", window->fl_win, width,height,window_state,driver->wait_for_expose_value, is_2nd_run);
-
- // When no window is active, and one window gets activated, generate an FL_APP_ACTIVATE event
- if (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) {
- if (!app_has_active_window) {
- app_has_active_window = true;
- Fl::handle(FL_APP_ACTIVATE, nullptr);
- }
-
- if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::WESTON) {
- // After click on titlebar, weston calls wl_keyboard_enter() for a
- // titlebar-related surface that FLTK can't identify, so we send FL_FOCUS here.
- Fl::handle(FL_FOCUS, window->fl_win);
- }
- if (!window->fl_win->border()) libdecor_frame_set_visibility(window->frame, false);
- else if (!libdecor_frame_is_visible(window->frame)) {
- libdecor_frame_set_visibility(window->frame, true);
- } else if (!window->fl_win->visible()) {
- Fl::handle(FL_SHOW, window->fl_win); // useful when un-minimizing
- }
- } else if (window_state & LIBDECOR_WINDOW_STATE_SUSPENDED) { // window is minimized
- Fl::handle(FL_HIDE, window->fl_win);
- }
-
- // When a window gets deactivated and there are no other active windows,
- // generate an FL_APP_DEACTIVATE event
- if ( ((window_state & LIBDECOR_WINDOW_STATE_ACTIVE) == 0) && app_has_active_window) {
- Fl::add_timeout(0.1, deferred_check_app_deactivate, nullptr);
- }
-
- if (window->fl_win->border())
- driver->is_maximized(window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED);
- if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) state = libdecor_state_new(width,
- height);
- else state = libdecor_state_new(int(ceil(width/f)*f), int(ceil(height/f)*f));
- libdecor_frame_commit(frame, state, configuration);
- if (libdecor_frame_is_floating(frame)) { // store floating dimensions
- window->floating_width = int(ceil(width/f)*f);
- window->floating_height = int(ceil(height/f)*f);
- //fprintf(stderr,"set floating_width+height %dx%d\n",width,height);
- }
- libdecor_state_free(state);
-
- driver->flush();
- if (Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::WESTON || !is_1st_run) {
- window->fl_win->clear_damage();
- }
-}
-
-
-void Fl_Wayland_Window_Driver::wait_for_expose()
-{
- Fl_Window_Driver::wait_for_expose();
- struct wld_window * xid = fl_wl_xid(pWindow);
- if (!xid) return;
- if (pWindow->fullscreen_active()) {
- if (xid->kind == DECORATED) {
- while (!(xid->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) ||
- !(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
- wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
- }
- } else if (xid->kind == UNFRAMED) {
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
- }
- } else if (xid->kind == DECORATED) {
- // necessary for the windowfocus demo program with recent Wayland versions
- if (!(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
- wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
- }
- }
-}
-
-
-static void delayed_close(Fl_Window *win) {
- Fl::remove_check((Fl_Timeout_Handler)delayed_close, win);
- Fl::handle(FL_CLOSE, win);
-}
-
-
-static void handle_close(struct libdecor_frame *frame, void *user_data)
-{ // runs when the close button of a window titlebar is pushed
- // or after "Quit" of the application menu
- // or after the Kill command of Sway
- Fl_Window* win = ((struct wld_window*)user_data)->fl_win;
- int X, Y;
- libdecor_frame_translate_coordinate(frame, 0, 0, &X, &Y);
- if (Y == 0) Fl::handle(FL_CLOSE, win);
- else {
- // the close window attempt is delayed because libdecor
- // uses the frame after return from this function
- Fl::add_check((Fl_Timeout_Handler)delayed_close, win);
- }
-}
-
-
-static void handle_commit(struct libdecor_frame *frame, void *user_data)
-{
- struct wld_window* wl_win = (struct wld_window*)user_data;
- if (wl_win->wl_surface) wl_surface_commit(wl_win->wl_surface);
-}
-
-
-static void handle_dismiss_popup(struct libdecor_frame *frame, const char *seat_name, void *user_data)
-{
-}
-
-
-static struct libdecor_frame_interface libdecor_frame_iface = {
- handle_configure,
- handle_close,
- handle_commit,
- handle_dismiss_popup,
-};
-
-
-static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
-{
- // runs for borderless windows and popup (menu,tooltip) windows
- struct wld_window *window = (struct wld_window*)data;
- xdg_surface_ack_configure(xdg_surface, serial);
-//fprintf(stderr, "xdg_surface_configure: surface=%p\n", window->wl_surface);
-
- if (window->fl_win->w() != window->configured_width ||
- window->fl_win->h() != window->configured_height) {
- if (window->buffer) {
- Fl_Wayland_Graphics_Driver::buffer_release(window);
- }
- }
- window->configured_width = window->fl_win->w();
- window->configured_height = window->fl_win->h();
- Fl_Window_Driver::driver(window->fl_win)->flush();
- window->fl_win->clear_damage();
-}
-
-
-static const struct xdg_surface_listener xdg_surface_listener = {
- .configure = xdg_surface_configure,
-};
-
-
-static bool parse_states_fullscreen(struct wl_array *states)
-{
- uint32_t *p;
- // Replace wl_array_for_each(p, states) rejected by C++
- for (p = (uint32_t *)(states)->data;
- (const char *) p < ((const char *) (states)->data + (states)->size);
- (p)++) {
- if (*p == XDG_TOPLEVEL_STATE_FULLSCREEN) return true;
- }
- return false;
-}
-
-
-static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
- int32_t width, int32_t height, struct wl_array *states)
-{
- // runs for borderless top-level windows
- // under Weston: width & height are 0 during both calls, except if fullscreen
- struct wld_window *window = (struct wld_window*)data;
-//fprintf(stderr, "xdg_toplevel_configure: surface=%p size: %dx%d\n", window->wl_surface, width, height);
- if (window->fl_win->fullscreen_active() && !parse_states_fullscreen(states)) {
- struct wl_output *wl_output = NULL;
- if (Fl_Window_Driver::driver(window->fl_win)->force_position()) {
- struct Fl_Wayland_Screen_Driver::output *output =
- screen_num_to_output(window->fl_win->screen_num());
- if (output) wl_output = output->wl_output;
- }
- xdg_toplevel_set_fullscreen(xdg_toplevel, wl_output);
- if (wl_output) {
- int X, Y;
- Fl::screen_xywh(X, Y, width, height, window->fl_win->screen_num());
- }
- }
- if (window->configured_width) {
- Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0;
- }
- float f = Fl::screen_scale(window->fl_win->screen_num());
- if (width == 0 || height == 0) {
- width = window->fl_win->w() * f;
- height = window->fl_win->h() * f;
- }
- window->fl_win->size(ceil(width / f), ceil(height / f));
- if (window->buffer && (ceil(width / f) != window->configured_width ||
- ceil(height / f) != window->configured_height)) {
- Fl_Wayland_Graphics_Driver::buffer_release(window);
- }
- window->configured_width = ceil(width / f);
- window->configured_height = ceil(height / f);
-}
-
-
-static void xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel)
-{
-}
-
-
-static const struct xdg_toplevel_listener xdg_toplevel_listener = {
- .configure = xdg_toplevel_configure,
- .close = xdg_toplevel_close,
-};
-
-
-struct win_positioner {
- struct wld_window *window;
- int x, y;
- Fl_Window *child_popup;
-};
-
-
-static void popup_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y,
- int32_t width, int32_t height) {
- struct win_positioner *win_pos = (struct win_positioner *)data;
- struct wld_window *window = win_pos->window;
-//printf("popup_configure %p asked:%dx%d got:%dx%d\n",window->fl_win, win_pos->x,win_pos->y, x,y);
- Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0;
- int HH;
- Fl_Window_Driver::menu_parent(&HH);
- if (window->fl_win->h() > HH && y != win_pos->y) { // A menu taller than the display
- // Under KWin, height is set to the display height or less: we ignore that.
- window->state = (y - win_pos->y);
- // make selected item visible, if there's one
- Fl_Window_Driver::scroll_to_selected_item(window->fl_win);
- }
- if (Fl_Window_Driver::current_menu_button && !Fl_Window_Driver::menu_leftorigin(window->fl_win)) {
- int X, Y;
- Fl_Window_Driver::current_menu_button->top_window_offset(X, Y);
- if (y < Y) {
- Fl_Window *win = window->fl_win;
- win->Fl_Widget::resize(win->x(), Y - win->h(), win->w(), win->h());
- }
- }
-}
-
-
-static struct xdg_popup *mem_grabbing_popup = NULL;
-
-
-static void popup_done(void *data, struct xdg_popup *xdg_popup) {
- struct win_positioner *win_pos = (struct win_positioner *)data;
- struct wld_window *window = win_pos->window;
-//fprintf(stderr, "popup_done: popup=%p data=%p xid=%p fl_win=%p\n", xdg_popup, data, window, window->fl_win);
- if (win_pos->child_popup) win_pos->child_popup->hide();
- xdg_popup_destroy(xdg_popup);
- delete win_pos;
- // The sway compositor calls popup_done directly and hides the menu
- // when the app looses focus.
- // Thus, we hide the window so FLTK and Wayland are in matching states.
- window->xdg_popup = NULL;
- window->fl_win->hide();
- if (mem_grabbing_popup == xdg_popup) {
- mem_grabbing_popup = NULL;
- }
-}
-
-
-static const struct xdg_popup_listener popup_listener = {
- .configure = popup_configure,
- .popup_done = popup_done,
-};
-
-
-bool Fl_Wayland_Window_Driver::in_flush_ = false;
-
-
-static const char *get_prog_name() {
- pid_t pid = getpid();
- char fname[100];
- snprintf(fname, 100, "/proc/%u/cmdline", pid);
- FILE *in = fopen(fname, "r");
- if (in) {
- static char line[200];
- const char *p = fgets(line, sizeof(line), in);
- fclose(in);
- p = strrchr(line, '/'); if (!p) p = line; else p++;
- return p;
- }
- return "unknown";
-}
-
-
-/* Implementation note about menu windows under Wayland.
- Wayland offers a way to position popup windows such as menu windows using constraints.
- Each popup is located relatively to a parent window which can be a popup itself and
- MUST overlap or at least touch this parent.
- Constraints determine how a popup is positioned relatively to a defined area (called
- the anchor rectangle) of its parent popup/window and what happens when this position
- would place the popup all or partly outside the display.
- In contrast, FLTK computes the adequate positions of menu windows in the display using
- knowledge about the display size and the location of the window in the display, and then
- maps them at these positions.
- These 2 logics are quite different because Wayland hides the position of windows inside the
- display, whereas FLTK uses the location of windows inside the display to position popups.
- Let's call "source window" the non-popup window above which all popups are mapped.
- The approach implemented here is two-fold.
- 1) If a menu window is not taller than the display, use Wayland constraints to position it.
- Wayland imposes that the first constructed popup must overlap or touch the source window.
- Other popups can be placed below, above, at right, or at left of a previous popup which
- allows them to expand outside the source window, while constraints can ensure they won't
- extend outside the display.
- 2) A menu window taller than the display is initially mapped with the constraint to
- begin at the top border of the display. This allows FLTK to know the distance between
- the source window and the display top. FLTK can later reposition the same tall popup,
- without the constraint not to go beyond the display top, at the exact position so that
- the desired series of menu items appear in the visible part of the tall popup.
-
- In case 1) above, the values that represent the display bounds are given very
- large values. That's done by member function Fl_Wayland_Window_Driver::menu_window_area().
- Consequently, FLTK computes an initial layout of future popups relatively to
- the source window as if it was mapped on an infinitely large display. Then, the location
- of the first popup to be mapped is modified if necessary so it overlaps or touches the
- source window. Finally, other popups are located using Wayland logic below, above or to the
- right of previous popups. Wayland constraints mechanism also allows a popup tentatively
- placed below a previous one to be flipped above it if that prevents the popup from expanding
- beyond display limits. This is used to unfold menu bar menus below or above the menu bar.
- After each popup is created and scheduled for being mapped on display by function
- process_menu_or_tooltip(), makeWindow() calls Fl_Window::wait_for_expose() so its constrained
- position is known before computing the position of the next popup. This ensures each
- popup is correctly placed relatively to its parent.
-
- Groups of popups containing a menutitle, the associated menuwindow, and optionally
- a submenu window and that don't belong to an Fl_Menu_Bar are mapped in a different order:
- the menuwindow is mapped first, and the menutitle is mapped second above it as a child popup.
- Fl_Window_Driver::is_floating_title() detects when such a menutitle is created,
- static member variable previous_floatingtitle is assigned the value of this menutitle, and
- the menutitle is mapped only after the menuwindow has been mapped, as a child of it.
- This positions better the popup group in the display relatively to where the popup
- was created.
-
- In case 2) above, a tall popup is mapped with XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y
- which puts its top at the display top border. The Wayland system then calls the
- popup_configure() callback function with the x,y coordinates of the top left corner
- where the popup is mapped relatively to an anchor point in the source window.
- The difference between the asked window position and the effective position is stored
- in the state member variable of the tall popup's struct wld_window. This information
- allows FLTK to compute the distance between the source window top and the display top border.
- Function Fl_Wayland_Window_Driver::menu_window_area() sets the top of the display to
- a value such that function Fl_Wayland_Window_Driver::reposition_menu_window(), called by
- menuwindow::autoscroll(int n), ensures that menu item #n is visible. Static boolean member
- variable Fl_Wayland_Window_Driver::new_popup is useful to position tall menuwindows created
- by an Fl_Menu_Button or Fl_Choice. It is set to true when any menu popup is created.
- It is used each time menu_window_area() runs for a particular Fl_Menu_Button or Fl_Choice,
- and is reset to false after its first use. This allows menu_window_area() to give the top of
- the display an adequate value the first time and to keep this value next times it runs.
- Fl_Window_Driver::scroll_to_selected_item() scrolls the tall popup so its selected
- item, when there's one, is visible immediately after the tall popup is mapped on display.
- */
-
-
-bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_window) {
- // a menu window or tooltip
- new_window->kind = Fl_Wayland_Window_Driver::POPUP;
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (Fl_Window_Driver::is_floating_title(pWindow)) {
- previous_floatingtitle = pWindow;
- return true;
- }
- new_window->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base,
- new_window->wl_surface);
- xdg_surface_add_listener(new_window->xdg_surface, &xdg_surface_listener, new_window);
- Fl_Wayland_Window_Driver::new_popup = true;
- Fl_Window *menu_origin = NULL;
- if (pWindow->menu_window()) {
- menu_origin = Fl_Window_Driver::menu_leftorigin(pWindow);
- if (!menu_origin && !previous_floatingtitle) menu_origin =
- Fl_Window_Driver::menu_title(pWindow);
- }
- Fl_Widget *target = (pWindow->tooltip_window() ? Fl_Tooltip::current() : NULL);
- if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display &&
- Fl_Screen_Driver::transient_scale_parent) {
- target = Fl_Screen_Driver::transient_scale_parent;
- }
- if (!target) target = Fl_Window_Driver::menu_parent();
- if (!target) target = Fl::belowmouse();
- if (!target) target = Fl::first_window();
- Fl_Window *parent_win = target->top_window();
- while (parent_win && parent_win->menu_window() && driver(parent_win)->popup_window()) {
- parent_win = Fl::next_window(parent_win);
- }
- Fl_Window *origin_win = (menu_origin ? menu_origin : parent_win);
- struct wld_window * parent_xid = fl_wl_xid(origin_win);
- struct xdg_surface *parent_xdg = parent_xid->xdg_surface;
- float f = Fl::screen_scale(parent_win->screen_num());
- //fprintf(stderr, "menu parent_win=%p pos:%dx%d size:%dx%d\n", parent_win, pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h());
-//printf("window=%p menutitle=%p bartitle=%d leftorigin=%p y=%d\n", pWindow, Fl_Window_Driver::menu_title(pWindow), Fl_Window_Driver::menu_bartitle(pWindow), Fl_Window_Driver::menu_leftorigin(pWindow), pWindow->y());
- struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base);
- //xdg_positioner_get_version(positioner) <== gives 1 under Debian and Sway
- int popup_x, popup_y;
- if (Fl_Window_Driver::current_menu_button && !Fl_Window_Driver::menu_leftorigin(pWindow)) {
- int X, Y;
- Fl_Window_Driver::current_menu_button->top_window_offset(X, Y);
- xdg_positioner_set_anchor_rect(positioner, X * f, Y * f,
- Fl_Window_Driver::current_menu_button->w() * f,
- Fl_Window_Driver::current_menu_button->h() * f);
- popup_x = X * f;
- popup_y = 0;
- if (parent_xid->kind == Fl_Wayland_Window_Driver::DECORATED && !origin_win->fullscreen_active())
- libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y,
- &popup_x, &popup_y);
- } else if (Fl_Window_Driver::menu_title(pWindow) && Fl_Window_Driver::menu_bartitle(pWindow)) {
- xdg_positioner_set_anchor_rect(positioner, 0, 0,
- Fl_Window_Driver::menu_title(pWindow)->w() * f,
- Fl_Window_Driver::menu_title(pWindow)->h() * f);
- popup_x = 0;
- popup_y = Fl_Window_Driver::menu_title(pWindow)->h() * f;
- } else {
- popup_x = pWindow->x() * f; popup_y = pWindow->y() * f;
- if (popup_x + pWindow->w() * f < 0) popup_x = - pWindow->w() * f;
- if (menu_origin) {
- popup_x -= menu_origin->x() * f;
- popup_y -= menu_origin->y() * f;
- }
- if (popup_x >= origin_win->w() * f) popup_x = origin_win->w() * f - 1;
- if (!Fl_Window_Driver::menu_title(pWindow) && !Fl_Window_Driver::menu_bartitle(pWindow) &&
- !Fl_Window_Driver::menu_leftorigin(pWindow)) {
- // prevent first popup from going above the permissible source window
- popup_y = fl_max(popup_y, - pWindow->h() * f);
- }
- if (parent_xid->kind == Fl_Wayland_Window_Driver::DECORATED && !origin_win->fullscreen_active())
- libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y,
- &popup_x, &popup_y);
- xdg_positioner_set_anchor_rect(positioner, popup_x, 0, 1, 1);
- popup_y++;
- }
- int positioner_H = pWindow->h();
- if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::KWIN) {
- // Under KWIN, limiting the height of the positioner to the work area height
- // results in tall popup windows starting at the top of the screen, what we want.
- // Unfortunately, we know the work area height exactly only for single-screen systems,
- // otherwise FLTK returns work area height == screen height. In that case we estimate
- // work area height ≈ screen height - 44.
- int V, work_area_H, screen_H;
- Fl::screen_work_area(V, V, V, work_area_H, origin_win->screen_num());
- Fl::screen_xywh(V, V, V, screen_H, origin_win->screen_num());
- if (work_area_H == screen_H) work_area_H -= 44;
- if (positioner_H > work_area_H) positioner_H = work_area_H;
- }
- xdg_positioner_set_size(positioner, pWindow->w() * f , positioner_H * f );
- xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT);
- xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
- // prevent menuwindow from expanding beyond display limits
- int constraint = 0;
- int top_menubar = pWindow->y() -
- (Fl_Window_Driver::menu_bartitle(pWindow) && Fl_Window_Driver::menu_title(pWindow) ?
- Fl_Window_Driver::menu_title(pWindow)->h() : 0);
- if ( !(parent_win->fullscreen_active() &&
- Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::MUTTER &&
- ((!Fl_Window_Driver::menu_title(pWindow) && !Fl_Window_Driver::menu_leftorigin(pWindow)) ||
- Fl_Window_Driver::menu_bartitle(pWindow)) && top_menubar < 10 &&
- !Fl_Window_Driver::current_menu_button)
- ) {
- // Condition above is only to bypass Mutter bug for fullscreen windows (see #1061)
- constraint |= (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
- if ((Fl_Window_Driver::current_menu_button || Fl_Window_Driver::menu_bartitle(pWindow)) &&
- !Fl_Window_Driver::menu_leftorigin(pWindow)) {
- constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
- }
- xdg_positioner_set_constraint_adjustment(positioner, constraint);
- }
- if (!(Fl_Window_Driver::menu_title(pWindow) && Fl_Window_Driver::menu_bartitle(pWindow))) {
- xdg_positioner_set_offset(positioner, 0, popup_y);
- }
- new_window->xdg_popup = xdg_surface_get_popup(new_window->xdg_surface,
- parent_xdg, positioner);
- struct win_positioner *win_pos = new struct win_positioner;
- win_pos->window = new_window;
- win_pos->x = popup_x;
- win_pos->y = popup_y;
- win_pos->child_popup = NULL;
-//printf("create xdg_popup=%p data=%p xid=%p fl_win=%p\n",new_window->xdg_popup,win_pos,new_window,new_window->fl_win);
- xdg_positioner_destroy(positioner);
- xdg_popup_add_listener(new_window->xdg_popup, &popup_listener, win_pos);
- if (!mem_grabbing_popup) {
- mem_grabbing_popup = new_window->xdg_popup;
- //xdg_popup_grab(new_window->xdg_popup, scr_driver->get_wl_seat(), scr_driver->get_serial());
- //libdecor_frame_popup_grab(parent_xid->frame, scr_driver->get_seat_name());
- }
- wl_surface_commit(new_window->wl_surface);
- // put it on same screen as parent_win
- this->screen_num(parent_win->screen_num());
- return false;
-}
-
-
-void Fl_Wayland_Window_Driver::makeWindow()
-{
- Fl_Group::current(0); // get rid of very common user bug: forgot end()
- struct wld_window *new_window;
- bool is_floatingtitle = false;
- wait_for_expose_value = 1;
-
- if (pWindow->parent() && !pWindow->window()) return;
- if (pWindow->parent() && !pWindow->window()->shown()) return;
-
- if (!pWindow->parent() && !popup_window()) {
- x(0); y(0); // toplevel, non-popup windows must have origin at 0,0
- }
- new_window = (struct wld_window *)calloc(1, sizeof *new_window);
- new_window->fl_win = pWindow;
- wl_list_init(&new_window->outputs);
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
-
- new_window->wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor);
-//printf("makeWindow:%p %s %s\n", pWindow, pWindow->parent()?"SUB":"", pWindow->as_gl_window()?"GL":"");
- wl_surface_add_listener(new_window->wl_surface, &surface_listener, new_window);
-
- if (!shape()) { // rectangular FLTK windows are opaque
- struct wl_region *opaque = wl_compositor_create_region(scr_driver->wl_compositor);
- wl_region_add(opaque, 0, 0, 1000000, 1000000);
- wl_surface_set_opaque_region(new_window->wl_surface, opaque);
- wl_region_destroy(opaque);
- }
-
- if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display &&
- Fl::first_window()) {
- // put transient scale win at center of top window by making it a tooltip of top
- Fl_Screen_Driver::transient_scale_parent = Fl::first_window();
- pWindow->set_tooltip_window();
- set_popup_window();
- pWindow->position(
- (Fl_Screen_Driver::transient_scale_parent->w() - pWindow->w())/2 ,
- (Fl_Screen_Driver::transient_scale_parent->h() - pWindow->h())/2);
- }
-
- if (popup_window()) { // a menu window or tooltip
- is_floatingtitle = process_menu_or_tooltip(new_window);
-
- } else if (pWindow->border() && !pWindow->parent() ) { // a decorated window
- new_window->kind = DECORATED;
- if (!scr_driver->libdecor_context)
- scr_driver->libdecor_context = libdecor_new(Fl_Wayland_Screen_Driver::wl_display,
- &libdecor_iface);
- new_window->frame = libdecor_decorate(scr_driver->libdecor_context, new_window->wl_surface,
- &libdecor_frame_iface, new_window);
- // appears in the Gnome desktop menu bar
- libdecor_frame_set_app_id(new_window->frame, get_prog_name());
- libdecor_frame_set_title(new_window->frame, pWindow->label()?pWindow->label():"");
- if (!is_resizable()) {
- libdecor_frame_unset_capabilities(new_window->frame, LIBDECOR_ACTION_RESIZE);
- libdecor_frame_unset_capabilities(new_window->frame, LIBDECOR_ACTION_FULLSCREEN);
- }
- libdecor_frame_map(new_window->frame);
- float f = Fl::screen_scale(pWindow->screen_num());
- new_window->floating_width = pWindow->w() * f;
- new_window->floating_height = pWindow->h() * f;
-
- } else if (pWindow->parent()) { // for subwindows (GL or non-GL)
- new_window->kind = SUBWINDOW;
- struct wld_window *parent = fl_wl_xid(pWindow->window());
- new_window->subsurface = wl_subcompositor_get_subsurface(scr_driver->wl_subcompositor,
- new_window->wl_surface,
- parent->wl_surface);
-//fprintf(stderr, "makeWindow: subsurface=%p\n", new_window->subsurface);
- float f = Fl::screen_scale(pWindow->top_window()->screen_num());
- wl_subsurface_set_position(new_window->subsurface, pWindow->x() * f, pWindow->y() * f);
- wl_subsurface_set_desync(new_window->subsurface); // important
- // Next 5 statements ensure the subsurface will be mapped because:
- // "The effect of adding a sub-surface becomes visible on the next time
- // the state of the parent surface is applied."
- new_window->configured_width = pWindow->w();
- new_window->configured_height = pWindow->h();
- if (!pWindow->as_gl_window()) {
- parent->fl_win->wait_for_expose();
- wl_surface_commit(parent->wl_surface);
- }
- wait_for_expose_value = 0;
- pWindow->border(0);
- checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
-
- } else { // a window without decoration
- new_window->kind = UNFRAMED;
- new_window->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base,
- new_window->wl_surface);
-//fprintf(stderr, "makeWindow: xdg_wm_base_get_xdg_surface=%p\n", new_window->xdg_surface);
- xdg_surface_add_listener(new_window->xdg_surface, &xdg_surface_listener, new_window);
- new_window->xdg_toplevel = xdg_surface_get_toplevel(new_window->xdg_surface);
- xdg_toplevel_add_listener(new_window->xdg_toplevel, &xdg_toplevel_listener, new_window);
- if (pWindow->label()) xdg_toplevel_set_title(new_window->xdg_toplevel, pWindow->label());
- wl_surface_commit(new_window->wl_surface);
- pWindow->border(0);
- }
-
- Fl_Window *old_first = Fl::first_window();
- struct wld_window * first_xid = (old_first ? fl_wl_xid(old_first) : NULL);
- Fl_X *xp = new Fl_X;
- xp->xid = (fl_uintptr_t)new_window;
- other_xid = 0;
- xp->w = pWindow;
- flx(xp);
- xp->region = 0;
- if (!pWindow->parent()) {
- xp->next = Fl_X::first;
- Fl_X::first = xp;
- } else if (Fl_X::first) {
- xp->next = Fl_X::first->next;
- Fl_X::first->next = xp;
- } else {
- xp->next = NULL;
- Fl_X::first = xp;
- }
-
- if (pWindow->modal() || pWindow->non_modal()) {
- if (pWindow->modal()) Fl::modal_ = pWindow;
- if (new_window->kind == DECORATED && first_xid && first_xid->kind == DECORATED) {
- if (first_xid->frame) libdecor_frame_set_parent(new_window->frame, first_xid->frame);
- } else if (new_window->kind == UNFRAMED && new_window->xdg_toplevel && first_xid) {
- Fl_Wayland_Window_Driver *top_dr = Fl_Wayland_Window_Driver::driver(first_xid->fl_win);
- if (top_dr->xdg_toplevel()) xdg_toplevel_set_parent(new_window->xdg_toplevel,
- top_dr->xdg_toplevel());
- }
- if (new_window->kind == DECORATED || new_window->kind == UNFRAMED) {
-#if HAVE_XDG_DIALOG
- if (scr_driver->xdg_wm_dialog) {
- new_window->xdg_dialog = xdg_wm_dialog_v1_get_xdg_dialog(scr_driver->xdg_wm_dialog, xdg_toplevel());
- if (pWindow->modal()) xdg_dialog_v1_set_modal(new_window->xdg_dialog);
- } else
-#endif
- if (scr_driver->seat->gtk_shell && pWindow->modal()) {
- // Useful to position modal windows above their parent with "gnome-shell --version" ≤ 45.2,
- // useless but harmless with "gnome-shell --version" ≥ 46.0.
- struct gtk_surface1 *gtk_surface = gtk_shell1_get_gtk_surface(scr_driver->seat->gtk_shell,
- new_window->wl_surface);
- gtk_surface1_set_modal(gtk_surface);
- if (gtk_surface1_get_version(gtk_surface) >= GTK_SURFACE1_RELEASE_SINCE_VERSION)
- gtk_surface1_release(gtk_surface); // very necessary
- else
- gtk_surface1_destroy(gtk_surface);
- }
- }
- }
-
- size_range();
- pWindow->set_visible();
- int old_event = Fl::e_number;
- pWindow->redraw();
- pWindow->handle(Fl::e_number = FL_SHOW); // get child windows to appear
- Fl::e_number = old_event;
- if (pWindow->menu_window() && popup_window() && !is_floatingtitle) {
- // make sure each menu window is mapped with its constraints before mapping next popup
- pWindow->wait_for_expose();
- if (previous_floatingtitle) { // a menuwindow with a menutitle
- //puts("previous_floatingtitle");
- int HH;
- Fl_Window_Driver::menu_parent(&HH);
- if (pWindow->h() > HH) {
- // a tall menuwindow with a menutitle: don't create the menutitle at all
- // and undo what has been created/allocated before
- struct wld_window *xid = fl_wl_xid(previous_floatingtitle);
- destroy_surface_caution_pointer_focus(xid->wl_surface, scr_driver->seat);
- free(xid);
- Fl_Window_Driver::driver(previous_floatingtitle)->hide_common();
- previous_floatingtitle = NULL;
- return;
- }
- // map the menutitle popup now as child of pWindow
- struct wld_window *xid = fl_wl_xid(previous_floatingtitle);
- xid->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, xid->wl_surface);
- xdg_surface_add_listener(xid->xdg_surface, &xdg_surface_listener, xid);
- struct xdg_positioner *positioner =
- xdg_wm_base_create_positioner(scr_driver->xdg_wm_base);
- xdg_positioner_set_anchor_rect(positioner, 0, 0, 1, 1);
- int snum = Fl_Window_Driver::menu_parent()->screen_num();
- float f = Fl::screen_scale(snum);
- // put it on same screen as parent menu
- Fl_Window_Driver::driver(previous_floatingtitle)->screen_num(snum);
- xdg_positioner_set_size(positioner, previous_floatingtitle->w() * f ,
- previous_floatingtitle->h() * f );
- xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
- xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_TOP_RIGHT);
- xid->xdg_popup = xdg_surface_get_popup(xid->xdg_surface, new_window->xdg_surface,
- positioner);
- xdg_positioner_destroy(positioner);
- struct win_positioner *win_pos = new struct win_positioner;
- win_pos->window = xid;
- win_pos->x = 0;
- win_pos->y = 0;
- win_pos->child_popup = NULL;
- xdg_popup_add_listener(xid->xdg_popup, &popup_listener, win_pos);
- wl_surface_commit(xid->wl_surface);
- struct win_positioner *parent_win_pos =
- (struct win_positioner*)xdg_popup_get_user_data(new_window->xdg_popup);
- parent_win_pos->child_popup = previous_floatingtitle;
- previous_floatingtitle = NULL;
- }
- }
- if (pWindow->fullscreen_active()) Fl::handle(FL_FULLSCREEN, pWindow);
-}
-
-
-int Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor c) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow);
-#if HAVE_CURSOR_SHAPE
- if (scr_driver->wp_cursor_shape_device) {
- if (xid->custom_cursor) {
- delete_cursor(xid->custom_cursor);
- xid->custom_cursor = NULL;
- }
- if (c == FL_CURSOR_NONE) return 0;
- standard_cursor_ = c;
- Fl_Wayland_Screen_Driver::do_set_cursor(scr_driver->seat, NULL, c);
- return 1;
- }
-#endif // HAVE_CURSOR_SHAPE
- if (!scr_driver->seat->cursor_theme) return 1;
- // Cursor names are the files of directory /usr/share/icons/XXXX/cursors/
- // where XXXX is the name of the current 'cursor theme'.
- static struct cursor_file_struct {
- Fl_Cursor c;
- const char *fname;
- Fl_Wayland_Screen_Driver::cursor_shapes wld_c;
- } cursor_file_array[] = {
- {FL_CURSOR_ARROW, "left_ptr", Fl_Wayland_Screen_Driver::arrow },
- {FL_CURSOR_CROSS, "cross", Fl_Wayland_Screen_Driver::cross },
- {FL_CURSOR_WAIT, "watch", Fl_Wayland_Screen_Driver::wait },
- {FL_CURSOR_INSERT, "xterm", Fl_Wayland_Screen_Driver::insert },
- {FL_CURSOR_HAND, "hand1", Fl_Wayland_Screen_Driver::hand },
- {FL_CURSOR_HELP, "help", Fl_Wayland_Screen_Driver::help },
- {FL_CURSOR_MOVE, "move", Fl_Wayland_Screen_Driver::move },
- {FL_CURSOR_N, "top_side", Fl_Wayland_Screen_Driver::north },
- {FL_CURSOR_E, "right_side", Fl_Wayland_Screen_Driver::east },
- {FL_CURSOR_W, "left_side", Fl_Wayland_Screen_Driver::west },
- {FL_CURSOR_S, "bottom_side", Fl_Wayland_Screen_Driver::south },
- {FL_CURSOR_NS, "sb_v_double_arrow", Fl_Wayland_Screen_Driver::north_south },
- {FL_CURSOR_WE, "sb_h_double_arrow", Fl_Wayland_Screen_Driver::west_east },
- {FL_CURSOR_SW, "bottom_left_corner", Fl_Wayland_Screen_Driver::south_west },
- {FL_CURSOR_SE, "bottom_right_corner", Fl_Wayland_Screen_Driver::south_east },
- {FL_CURSOR_NE, "top_right_corner", Fl_Wayland_Screen_Driver::north_east },
- {FL_CURSOR_NW, "top_left_corner", Fl_Wayland_Screen_Driver::north_west },
- {FL_CURSOR_NESW, "fd_double_arrow", Fl_Wayland_Screen_Driver::nesw },
- {FL_CURSOR_NWSE, "bd_double_arrow", Fl_Wayland_Screen_Driver::nwse }
- };
-
- int found = -1;
- for (unsigned i = 0; i < sizeof(cursor_file_array) / sizeof(struct cursor_file_struct); i++) {
- if (cursor_file_array[i].c == c) {
- found = cursor_file_array[i].wld_c;
- if (!scr_driver->xc_cursor[found]) scr_driver->xc_cursor[found] =
- scr_driver->cache_cursor(cursor_file_array[i].fname);
- if (scr_driver->xc_cursor[found]) {
- scr_driver->default_cursor(scr_driver->xc_cursor[found]);
- }
- break;
- }
- }
- if (found < 0 || !scr_driver->xc_cursor[found]) return 0;
-
- if (xid->custom_cursor) {
- delete_cursor(xid->custom_cursor);
- xid->custom_cursor = NULL;
- }
- standard_cursor_ = c;
- scr_driver->set_cursor();
- return 1;
-}
-
-
-void Fl_Wayland_Window_Driver::use_border() {
- if (!shown() || pWindow->parent()) return;
- pWindow->wait_for_expose(); // useful for border(0) just after show()
- struct libdecor_frame *frame = fl_wl_xid(pWindow)->frame;
- if (frame && Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::KWIN) {
- if (fl_wl_xid(pWindow)->kind == DECORATED) {
- libdecor_frame_set_visibility(frame, pWindow->border());
- } else {
- pWindow->hide();
- pWindow->show();
- }
- pWindow->redraw();
- } else {
- Fl_Window_Driver::use_border();
- }
-}
-
-
-/* Change an existing window to fullscreen */
-void Fl_Wayland_Window_Driver::fullscreen_on() {
- int top, bottom, left, right;
-
- top = fullscreen_screen_top();
- bottom = fullscreen_screen_bottom();
- left = fullscreen_screen_left();
- right = fullscreen_screen_right();
-
- if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
- top = screen_num();
- bottom = top;
- left = top;
- right = top;
- }
- pWindow->wait_for_expose(); // make sure ->xdg_toplevel is initialized
- if (xdg_toplevel()) {
- xdg_toplevel_set_fullscreen(xdg_toplevel(), NULL);
- pWindow->_set_fullscreen();
- Fl::handle(FL_FULLSCREEN, pWindow);
- }
-}
-
-
-void Fl_Wayland_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
- pWindow->hide();
- pWindow->_clear_fullscreen();
- // avoid being called with W=H=0 in suboptimal scenario of #1299
- if (!W) W = w();
- if (!H) H = h();
- pWindow->resize(X, Y, W, H);
- pWindow->show();
- Fl::handle(FL_FULLSCREEN, pWindow);
-}
-
-
-void Fl_Wayland_Window_Driver::label(const char *name, const char *iname) {
- if (shown() && !parent() && fl_wl_xid(pWindow)->kind == DECORATED) {
- if (!name) name = "";
- if (!iname) iname = fl_filename_name(name);
- libdecor_frame_set_title(fl_wl_xid(pWindow)->frame, name);
- }
-}
-
-
-int Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int hoty) {
- int retval = set_cursor_4args(rgb, hotx, hoty, true);
- if (retval) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow);
- Fl_Wayland_Screen_Driver::do_set_cursor(scr_driver->seat, xid->custom_cursor->wl_cursor);
- }
- return retval;
-}
-
-
-int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx, int hoty,
- bool keep_copy) {
- if (keep_copy) {
- if (rgb->as_svg_image()) {
- int scale = wld_scale();
- Fl_RGB_Image *svg = (Fl_RGB_Image*)rgb->copy(rgb->w() * scale, rgb->h() * scale);
- svg->normalize();
- svg->scale(rgb->w(), rgb->h(), 0, 1);
- rgb = svg;
- } else {
- int ld = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
- uchar *data = new uchar[ld * rgb->data_h()];
- memcpy(data, rgb->array, ld * rgb->data_h());
- Fl_RGB_Image *rgb2 = new Fl_RGB_Image(data, rgb->data_w(), rgb->data_h(), rgb->d(), rgb->ld());
- rgb2->alloc_array = 1;
- rgb2->scale(rgb->w(), rgb->h(), 0, 1);
- rgb = rgb2;
- }
- }
-// build a new wl_cursor and its image
- struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow);
- struct wl_cursor *new_cursor = (struct wl_cursor*)malloc(sizeof(struct wl_cursor));
- struct cursor_image *new_image = (struct cursor_image*)calloc(1,
- sizeof(struct cursor_image));
- int scale = wld_scale();
- new_image->image.width = rgb->w() * scale;
- new_image->image.height = rgb->h() * scale;
- new_image->image.hotspot_x = hotx * scale;
- new_image->image.hotspot_y = hoty * scale;
- new_image->image.delay = 0;
- new_image->offset = 0;
- //create a Wayland buffer and have it used as an image of the new cursor
- struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen;
- Fl_Image_Surface *img_surf = Fl_Wayland_Graphics_Driver::custom_offscreen(
- new_image->image.width, new_image->image.height, &offscreen);
- new_image->buffer = offscreen->wl_buffer;
- wl_buffer_set_user_data(new_image->buffer, offscreen);
- new_cursor->image_count = 1;
- new_cursor->images = (struct wl_cursor_image**)malloc(sizeof(struct wl_cursor_image*));
- new_cursor->images[0] = (struct wl_cursor_image*)new_image;
- new_cursor->name = strdup("custom cursor");
- // draw the rgb image to the cursor's drawing buffer
- Fl_Surface_Device::push_current(img_surf);
- Fl_Wayland_Graphics_Driver *driver = (Fl_Wayland_Graphics_Driver*)img_surf->driver();
- cairo_scale(driver->cr(), scale, scale);
- ((Fl_RGB_Image*)rgb)->draw(0, 0);
- Fl_Surface_Device::pop_current();
- delete img_surf;
- memcpy(offscreen->data, offscreen->draw_buffer.buffer, offscreen->draw_buffer.data_size);
- // delete the previous custom cursor, if there was one,
- // and keep its Fl_RGB_Image if appropriate
- if (xid->custom_cursor) delete_cursor(xid->custom_cursor, keep_copy);
- //have this new cursor used
- xid->custom_cursor = new custom_cursor;
- xid->custom_cursor->wl_cursor = new_cursor;
- xid->custom_cursor->rgb = rgb;
- xid->custom_cursor->hotx = hotx;
- xid->custom_cursor->hoty = hoty;
- return 1;
-}
-
-
-void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
- static int depth = 0;
- struct wld_window *fl_win = fl_wl_xid(pWindow);
- if (fl_win && fl_win->kind == DECORATED && !xdg_toplevel()) {
- pWindow->wait_for_expose();
- }
- int is_a_move = (X != x() || Y != y());
- bool true_rescale = Fl_Window::is_a_rescale();
- float f = fl_win ? Fl::screen_scale(pWindow->screen_num()) : 1;
- if (fl_win && fl_win->buffer) {
- int scale = wld_scale();
- int stride = cairo_format_stride_for_width(
- Fl_Cairo_Graphics_Driver::cairo_format, int(W * f) * scale );
- size_t bsize = stride * int(H * f) * scale;
- true_rescale = (bsize != fl_win->buffer->draw_buffer.data_size);
- }
- int is_a_resize = (W != w() || H != h() || true_rescale);
- if (is_a_move) force_position(1);
- else if (!is_a_resize && !is_a_move) return;
- depth++;
- if (shown() && !(parent() || popup_window())) {
- X = Y = 0;
- }
- Fl_Window *parent = this->parent() ? pWindow->window() : NULL;
- struct wld_window *parent_xid = parent ? fl_wl_xid(parent) : NULL;
-//printf("resize[%p] %dx%d is_a_resize=%d is_a_move=%d depth=%d parent_xid->frame_cb=%p\n", pWindow,W,H,is_a_resize,is_a_move,depth, (parent_xid?parent_xid->frame_cb:0) );
- if (depth == 1 && fl_win && parent_xid && parent_xid->frame_cb && can_expand_outside_parent_) {
- // When moving or resizing a subwindow independently from its parent while the parent window
- // is being redrawn, the processing depends on whether the moved/resize window
- // is a draggable-subwindow. For a draggable subwindow having can_expand_outside_parent_ != 0,
- // skip the X,Y,W,H tuple to process only tuples received when parent window is ready.
- // This smoothes the movement of the draggable subwindow.
- // Process regular subwindows normally.
- depth--;
- return;
- }
- if (is_a_resize) {
- if (pWindow->parent()) {
- if (W < 1) W = 1;
- if (H < 1) H = 1;
- }
- pWindow->Fl_Group::resize(X,Y,W,H);
- //fprintf(stderr, "resize: win=%p to %dx%d\n", pWindow, W, H);
- if (shown()) {pWindow->redraw();}
- } else {
- x(X); y(Y);
- //fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y);
- }
- if (!fl_win) {
- depth--;
- return;
- }
-
- if (is_a_resize) {
- if (pWindow->as_overlay_window() && other_xid) {
- destroy_double_buffer();
- }
- if (fl_win->kind == DECORATED) { // a decorated window
- if (fl_win->buffer) {
- Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
- }
- fl_win->configured_width = W;
- fl_win->configured_height = H;
- if (!in_handle_configure && xdg_toplevel()) {
- if (Fl_Window::is_a_rescale()) size_range();
- struct libdecor_state *state = libdecor_state_new(int(W * f), int(H * f));
- // necessary only if resize is initiated by prog
- libdecor_frame_commit(fl_win->frame, state, NULL);
- libdecor_state_free(state);
- if (libdecor_frame_is_floating(fl_win->frame)) {
- fl_win->floating_width = int(W*f);
- fl_win->floating_height = int(H*f);
- }
- }
- } else if (fl_win->kind == SUBWINDOW && fl_win->subsurface) { // a subwindow
- wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
- if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
- fl_win->configured_width = W;
- fl_win->configured_height = H;
- } else if (fl_win->xdg_surface) { // a window without border
- if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win);
- fl_win->configured_width = W;
- fl_win->configured_height = H;
- W *= f; H *= f;
- xdg_surface_set_window_geometry(fl_win->xdg_surface, 0, 0, W, H);
- //printf("xdg_surface_set_window_geometry: %dx%d\n",W, H);
- }
- } else if (!in_handle_configure && xdg_toplevel() && Fl::e_state == FL_BUTTON1) {
- // Wayland doesn't provide a way for the app to set the window position on screen.
- // This is functional when the move is mouse-driven.
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- xdg_toplevel_move(xdg_toplevel(), scr_driver->seat->wl_seat, scr_driver->seat->serial);
- Fl::pushed(NULL);
- Fl::e_state = 0;
- }
-
- if (parent_xid) {
- if (depth > 1) {
- if (fl_win->subsurface) {
- wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
- wl_surface_commit(parent_xid->wl_surface);
- }
- } else if (parent_xid->buffer && is_a_move) {
- if (fl_win->subsurface) wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f);
- if (!parent_xid->buffer->wl_buffer || parent_xid->buffer->draw_buffer_needs_commit) {
- if (!parent_xid->frame_cb) Fl_Wayland_Graphics_Driver::buffer_commit(parent_xid);
- else wl_surface_commit(parent_xid->wl_surface);
- } else {
- if (!parent_xid->frame_cb) {
- // Use the frame callback mechanism applied to the object's parent window
- parent_xid->frame_cb = wl_surface_frame(parent_xid->wl_surface);
- wl_callback_add_listener(parent_xid->frame_cb,
- Fl_Wayland_Graphics_Driver::p_surface_frame_listener, parent_xid);
- }
- wl_surface_commit(parent_xid->wl_surface);
- }
- }
- checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
- }
- depth--;
-}
-
-
-static void crect_intersect(cairo_rectangle_int_t *to, cairo_rectangle_int_t *with) {
- int x = fl_max(to->x, with->x);
- to->width = fl_min(to->x + to->width, with->x + with->width) - x;
- if (to->width < 0) to->width = 0;
- int y = fl_max(to->y, with->y);
- to->height = fl_min(to->y + to->height, with->y + with->height) - y;
- if (to->height < 0) to->height = 0;
- to->x = x;
- to->y = y;
-}
-
-
-static bool crect_equal(cairo_rectangle_int_t *to, cairo_rectangle_int_t *with) {
- return (to->x == with->x && to->y == with->y && to->width == with->width &&
- to->height == with->height);
-}
-
-
-void Fl_Wayland_Window_Driver::checkSubwindowFrame() {
- if (!pWindow->parent() || can_expand_outside_parent_) return;
- // make sure this subwindow doesn't leak out of its parent window
- Fl_Window *from = pWindow, *parent;
- cairo_rectangle_int_t full = {0, 0, pWindow->w(), pWindow->h()}; // full subwindow area
- cairo_rectangle_int_t srect = full; // will become new subwindow clip
- int fromx = 0, fromy = 0;
- while ((parent = from->window()) != NULL) { // loop over all parent windows
- fromx -= from->x(); // parent origin in subwindow's coordinates
- fromy -= from->y();
- cairo_rectangle_int_t prect = {fromx, fromy, parent->w(), parent->h()};
- crect_intersect(&srect, &prect); // area of subwindow inside its parent
- from = parent;
- }
- cairo_rectangle_int_t *r = subRect();
- // current subwindow clip
- cairo_rectangle_int_t current_clip = (r ? *r : full);
- if (!crect_equal(&srect, &current_clip)) { // if new clip differs from current clip
- if (crect_equal(&srect, &full)) r = NULL;
- else {
- r = &srect;
- if (r->width == 0 || r->height == 0) {
- r = NULL;
- }
- }
- subRect(r);
- }
-}
-
-
-void Fl_Wayland_Window_Driver::subRect(cairo_rectangle_int_t *r) {
- if (subRect_) delete subRect_;
- cairo_rectangle_int_t *r2 = NULL;
- if (r) {
- r2 = new cairo_rectangle_int_t;
- *r2 = *r;
- }
- subRect_ = r2;
-}
-
-
-void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) {
- if (y == pWindow->y()) return;
- // The top of the tall popup window was positioned at the top of the screen
- // Instead of sliding up the popup window on the display, we slide up the
- // drawing inside the fixed popup via member variable offset_y of the
- // menuwindow class, and we redraw the popup content.
- // It's also useful to make such tall popup window transparent.
- *Fl_Window_Driver::menu_offset_y(pWindow) += (y - pWindow->y());
- struct wld_window *xid = fl_wl_xid(pWindow);
- wl_surface_set_opaque_region(xid->wl_surface, NULL);
- if (xid->buffer) memset(xid->buffer->draw_buffer.buffer, 0,
- xid->buffer->draw_buffer.data_size);
- //printf("offset_y=%d\n", *Fl_Window_Driver::menu_offset_y(pWindow));
- this->y(y);
- pWindow->redraw();
-}
-
-
-void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int nscreen) {
- int HH;
- Fl_Window *parent = Fl_Window_Driver::menu_parent(&HH);
- if (parent) {
- if (pWindow->menu_window() && popup_window() && pWindow->h() > HH) {
- // tall menu: set top (Y) and bottom (Y+H) bounds relatively to reference window
- int ih = Fl_Window_Driver::menu_itemheight(pWindow);
- X = -50000;
- W = 1000000;
- H = HH - 2 * ih;
- Fl_Window *origin = Fl_Window_Driver::menu_leftorigin(pWindow);
- if (origin) { // has left parent
- int selected = fl_max(Fl_Window_Driver::menu_selected(origin), 0);
- Y = origin->y() + (selected + 0.5) * ih;
- } else if (!Fl_Window_Driver::menu_bartitle(pWindow)) { // tall menu button
- static int y_offset = 0;
- if (new_popup) {
- y_offset = pWindow->y()- ih;
- new_popup = false;
- }
- Y = 1.5 * ih + y_offset;
- } else { // has a menutitle
- Y = 1.5 * ih;
- }
- } else { // position the menu window by wayland constraints
- X = -50000;
- Y = -50000;
- W = 1000000;
- H = 1000000;
- }
- //printf("menu_window_area: %dx%d - %dx%d\n",X,Y,W,H);
- } else Fl_Window_Driver::menu_window_area(X, Y, W, H, nscreen);
-}
-
-
-int Fl_Wayland_Window_Driver::wld_scale() {
- Fl_X *flx = Fl_X::flx(pWindow);
- struct wld_window *xid = (flx ? (struct wld_window *)flx->xid : NULL);
- if (!xid || wl_list_empty(&xid->outputs)) {
- int scale = 1;
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- Fl_Wayland_Screen_Driver::output *output;
- wl_list_for_each(output, &(scr_driver->outputs), link) {
- scale = fl_max(scale, output->wld_scale);
- }
- return scale;
- }
- struct surface_output *s_output;
- s_output = wl_container_of(xid->outputs.next, s_output, link);
- return s_output->output->wld_scale;
-}
-
-
-FL_EXPORT struct wl_surface *fl_wl_surface(struct wld_window *xid) {
- return xid->wl_surface;
-}
-
-
-cairo_t *fl_wl_gc() {
- return ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->cr();
-}
-
-
-Fl_Window *fl_wl_find(struct wld_window *xid) {
- return Fl_Window_Driver::find((fl_uintptr_t)xid);
-}
-
-
-struct wld_window *fl_wl_xid(const Fl_Window *win) {
- return (struct wld_window *)Fl_Window_Driver::xid(win);
-}
-
-
-struct wl_compositor *fl_wl_compositor() {
- Fl_Wayland_Screen_Driver *screen_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- return screen_driver->wl_compositor;
-}
-
-
-int fl_wl_buffer_scale(Fl_Window *window) {
- return Fl_Wayland_Window_Driver::driver(window)->wld_scale();
-}
-
-
-Fl_Wayland_Plugin *Fl_Wayland_Window_Driver::gl_plugin() {
- static Fl_Wayland_Plugin *plugin = NULL;
- if (!plugin) {
- Fl_Plugin_Manager pm("wayland.fltk.org");
- plugin = (Fl_Wayland_Plugin*)pm.plugin("gl.wayland.fltk.org");
- }
- return plugin;
-}
-
-
-void Fl_Wayland_Window_Driver::maximize() {
- struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid;
- if (xid->kind == DECORATED) libdecor_frame_set_maximized(xid->frame);
- else Fl_Window_Driver::maximize();
-}
-
-
-void Fl_Wayland_Window_Driver::un_maximize() {
- struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid;
- if (xid->kind == DECORATED) libdecor_frame_unset_maximized(xid->frame);
- else Fl_Window_Driver::un_maximize();
-}
diff --git a/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx b/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx
deleted file mode 100644
index 12c525c46..000000000
--- a/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx
+++ /dev/null
@@ -1,741 +0,0 @@
-//
-// Wayland-specific code for clipboard and drag-n-drop support.
-//
-// Copyright 1998-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#if !defined(FL_DOXYGEN)
-
-# include <FL/Fl.H>
-# include <FL/platform.H>
-# include <FL/Fl_Window.H>
-# include <FL/Fl_Shared_Image.H>
-# include <FL/Fl_Image_Surface.H>
-# include "Fl_Wayland_Screen_Driver.H"
-# include "Fl_Wayland_Window_Driver.H"
-# include "../Unix/Fl_Unix_System_Driver.H"
-# include "Fl_Wayland_Graphics_Driver.H"
-# include "../../flstring.h" // includes <string.h>
-
-# include <errno.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <map>
-
-
-////////////////////////////////////////////////////////////////
-// Code used for copy and paste and DnD into the program:
-
-static char *fl_selection_buffer[2];
-static int fl_selection_length[2];
-static const char * fl_selection_type[2];
-static int fl_selection_buffer_length[2];
-static char fl_i_own_selection[2] = {0,0};
-static struct wl_data_offer *fl_selection_offer = NULL;
-// The MIME type Wayland uses for text-containing clipboard:
-static const char wld_plain_text_clipboard[] = "text/plain;charset=utf-8";
-
-
-int Fl_Wayland_Screen_Driver::clipboard_contains(const char *type)
-{
- return fl_selection_type[1] == type;
-}
-
-
-struct data_source_write_struct {
- size_t rest;
- char *from;
-};
-
-void write_data_source_cb(FL_SOCKET fd, data_source_write_struct *data) {
- while (data->rest) {
- ssize_t n = write(fd, data->from, data->rest);
- if (n == -1) {
- if (errno == EAGAIN) return;
- Fl::error("write_data_source_cb: error while writing clipboard data\n");
- break;
- }
- data->from += n;
- data->rest -= n;
- }
- Fl::remove_fd(fd, FL_WRITE);
- delete data;
- close(fd);
-}
-
-
-static void data_source_handle_send(void *data, struct wl_data_source *source,
- const char *mime_type, int fd) {
- fl_intptr_t rank = (fl_intptr_t)data;
-//fprintf(stderr, "data_source_handle_send: %s fd=%d l=%d\n", mime_type, fd, fl_selection_length[1]);
- if (((!strcmp(mime_type, wld_plain_text_clipboard) || !strcmp(mime_type, "text/plain")) &&
- fl_selection_type[rank] == Fl::clipboard_plain_text)
- ||
- (!strcmp(mime_type, "image/bmp") && fl_selection_type[rank] == Fl::clipboard_image) ) {
- data_source_write_struct *write_data = new data_source_write_struct;
- write_data->rest = fl_selection_length[rank];
- write_data->from = fl_selection_buffer[rank];
- Fl::add_fd(fd, FL_WRITE, (Fl_FD_Handler)write_data_source_cb, write_data);
- } else {
- //Fl::error("Destination client requested unsupported MIME type: %s\n", mime_type);
- close(fd);
- }
-}
-
-
-static Fl_Window *fl_dnd_target_window = 0;
-static wl_surface *fl_dnd_target_surface = 0;
-static bool doing_dnd = false; // true when DnD is in action
-static wl_surface *dnd_icon = NULL; // non null when DnD uses text as cursor
-static wl_cursor* save_cursor = NULL; // non null when DnD uses "dnd-copy" cursor
-
-
-static void data_source_handle_cancelled(void *data, struct wl_data_source *source) {
- // An application has replaced the clipboard contents or DnD finished
- wl_data_source_destroy(source);
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->seat->data_source == source) scr_driver->seat->data_source = NULL;
- doing_dnd = false;
- if (dnd_icon) {
- struct Fl_Wayland_Graphics_Driver::wld_buffer *off =
- (struct Fl_Wayland_Graphics_Driver::wld_buffer *)
- wl_surface_get_user_data(dnd_icon);
- struct wld_window fake_window;
- memset(&fake_window, 0, sizeof(fake_window));
- fake_window.buffer = off;
- Fl_Wayland_Graphics_Driver::buffer_release(&fake_window);
- wl_surface_destroy(dnd_icon);
- dnd_icon = NULL;
- }
- fl_i_own_selection[1] = 0;
- if (data == 0) { // at end of DnD
- if (save_cursor) {
- scr_driver->default_cursor(save_cursor);
- scr_driver->set_cursor();
- save_cursor = NULL;
- }
- if (fl_dnd_target_window) {
- Fl::handle(FL_RELEASE, fl_dnd_target_window);
- fl_dnd_target_window = 0;
- }
- Fl::pushed(0);
- }
-}
-
-
-static void data_source_handle_target(void *data, struct wl_data_source *source, const char *mime_type) {
- if (!Fl::pushed()) {
- data_source_handle_cancelled(data, source);
- return;
- }
- if (mime_type != NULL) {
- //printf("Destination would accept MIME type if dropped: %s\n", mime_type);
- } else {
- //printf("Destination would reject if dropped\n");
- }
-}
-
-
-static uint32_t last_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
-
-
-static void data_source_handle_action(void *data, struct wl_data_source *source,
- uint32_t dnd_action) {
- last_dnd_action = dnd_action;
- switch (dnd_action) {
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
- //printf("Destination would perform a copy action if dropped\n");
- break;
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
- //printf("Destination would reject the drag if dropped\n");
- break;
- }
-}
-
-
-static void data_source_handle_dnd_drop_performed(void *data, struct wl_data_source *source) {
- //printf("Drop performed\n");
-}
-
-
-static void data_source_handle_dnd_finished(void *data, struct wl_data_source *source) {
- switch (last_dnd_action) {
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
- //printf("Destination has accepted the drop with a move action\n");
- break;
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
- //printf("Destination has accepted the drop with a copy action\n");
- break;
- }
-}
-
-
-static const struct wl_data_source_listener data_source_listener = {
- .target = data_source_handle_target,
- .send = data_source_handle_send,
- .cancelled = data_source_handle_cancelled,
- .dnd_drop_performed = data_source_handle_dnd_drop_performed,
- .dnd_finished = data_source_handle_dnd_finished,
- .action = data_source_handle_action,
-};
-
-
-static struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen_from_text(const char *text,
- int scale) {
- const char *p, *q;
- int width = 0, height, w2, ltext = strlen(text);
- fl_font(FL_HELVETICA, 10 * scale);
- p = text;
- int nl = 0;
- while(nl < 20 && (q=strchr(p, '\n')) != NULL) {
- nl++;
- w2 = int(fl_width(p, q - p));
- if (w2 > width) width = w2;
- p = q + 1;
- }
- if (nl < 20 && text[ ltext - 1] != '\n') {
- nl++;
- w2 = int(fl_width(p));
- if (w2 > width) width = w2;
- }
- if (width > 300*scale) width = 300*scale;
- height = nl * fl_height() + 3;
- width += 6;
- width = ceil(width/float(scale)) * scale; // these must be multiples of scale
- height = ceil(height/float(scale)) * scale;
- struct Fl_Wayland_Graphics_Driver::wld_buffer *off;
- Fl_Image_Surface *surf = Fl_Wayland_Graphics_Driver::custom_offscreen(
- width, height, &off);
- Fl_Surface_Device::push_current(surf);
- p = text;
- fl_font(FL_HELVETICA, 10 * scale);
- int y = fl_height();
- while (nl > 0) {
- q = strchr(p, '\n');
- if (q) {
- fl_draw(p, q - p, 3, y);
- } else {
- fl_draw(p, 3, y);
- break;
- }
- y += fl_height();
- p = q + 1;
- nl--;
- }
- Fl_Surface_Device::pop_current();
- delete surf;
- cairo_surface_flush( cairo_get_target(off->draw_buffer.cairo_) );
- memcpy(off->data, off->draw_buffer.buffer, off->draw_buffer.data_size);
- return off;
-}
-
-
-int Fl_Wayland_Screen_Driver::dnd(int use_selection) {
- Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
-
- struct wl_data_source *source =
- wl_data_device_manager_create_data_source(scr_driver->seat->data_device_manager);
- // we transmit the adequate value of index in fl_selection_buffer[index]
- wl_data_source_add_listener(source, &data_source_listener, (void*)0);
- wl_data_source_offer(source, wld_plain_text_clipboard);
- wl_data_source_set_actions(source, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
- struct Fl_Wayland_Graphics_Driver::wld_buffer *off = NULL;
- int s = 1;
- if (use_selection) {
- // use the text as dragging icon
- Fl_Widget *current = Fl::pushed() ? Fl::pushed() : Fl::first_window();
- s = Fl_Wayland_Window_Driver::driver(current->top_window())->wld_scale();
- off = (struct Fl_Wayland_Graphics_Driver::wld_buffer *)offscreen_from_text(fl_selection_buffer[0], s);
- dnd_icon = wl_compositor_create_surface(scr_driver->wl_compositor);
- } else dnd_icon = NULL;
- doing_dnd = true;
- wl_data_device_start_drag(scr_driver->seat->data_device, source,
- scr_driver->seat->pointer_focus, dnd_icon,
- scr_driver->seat->serial);
- if (use_selection) {
- wl_surface_attach(dnd_icon, off->wl_buffer, 0, 0);
- wl_surface_set_buffer_scale(dnd_icon, s);
- wl_surface_damage(dnd_icon, 0, 0, 10000, 10000);
- wl_surface_commit(dnd_icon);
- wl_surface_set_user_data(dnd_icon, off);
- } else {
- static struct wl_cursor *dnd_cursor = scr_driver->cache_cursor("dnd-copy");
- if (dnd_cursor) {
- save_cursor = scr_driver->default_cursor();
- scr_driver->default_cursor(dnd_cursor);
- scr_driver->set_cursor();
- } else save_cursor = NULL;
- }
- return 1;
-}
-
-
-struct compare_utf8 { // used as key_comp member of following map object
- bool operator()(const char *a, const char *b) const { return strcmp(a, b) < 0; }
-};
-
-// map: for each clipboard mime-type FLTK has interest in, give FLTK clipboard type and priority.
-// A mime-type with higher priority for same FLTK clipboard type is preferred.
-typedef struct { const char * const fltk_type; int priority; } type_prio_struct;
-static std::map<const char * const, type_prio_struct, compare_utf8> clipboard_mimetypes_map {
-// mime-type FLTK-clipboard-type priority
- {"image/png", {Fl::clipboard_image, 1} },
- {"image/bmp", {Fl::clipboard_image, 2} },
- {"text/plain", {Fl::clipboard_plain_text, 1} },
- {"text/uri-list", {Fl::clipboard_plain_text, 2} },
- {"UTF8_STRING", {Fl::clipboard_plain_text, 3} },
- {wld_plain_text_clipboard, {Fl::clipboard_plain_text, 4} },
-};
-
-// map: for each FLTK-clipboard-type, give current preferred mime-type and priority
-typedef struct { const char *mime_type; int priority; } mime_prio_struct;
-static std::map<const char * const, mime_prio_struct> clipboard_kinds_map {
-// FLTK-clipboard-type current mime-type current highest priority
- {Fl::clipboard_image, {NULL, 0} },
- {Fl::clipboard_plain_text, {NULL, 0} },
-};
-
-
-static void data_offer_handle_offer(void *data, struct wl_data_offer *offer,
- const char *mime_type) {
- // runs when app becomes active once for each offered clipboard type
-//fprintf(stderr, "Clipboard offer=%p supports MIME type: %s\n", offer, mime_type);
- std::map<const char*const, type_prio_struct, compare_utf8>::iterator iter_mime =
- clipboard_mimetypes_map.find(mime_type);
- if (iter_mime == clipboard_mimetypes_map.end()) return; // FLTK doesn't handle this mime_type
- std::map<const char*const, mime_prio_struct>::iterator iter_kind =
- clipboard_kinds_map.find(iter_mime->second.fltk_type);
- if (iter_mime->second.priority > iter_kind->second.priority) { // found mime-type with higher priority
- iter_kind->second.priority = iter_mime->second.priority;
- iter_kind->second.mime_type = iter_mime->first;
- fl_selection_type[1] = iter_kind->first;
-//fprintf(stderr,"mime_type=%s priority=%d [%s]\n",iter_kind->second.mime_type, iter_kind->second.priority, fl_selection_type[1]);
- }
-}
-
-
-static void data_offer_handle_source_actions(void *data, struct wl_data_offer *offer,
- uint32_t actions) {
- if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
- //printf("Drag supports the copy action\n");
- }
-}
-
-
-static void data_offer_handle_action(void *data, struct wl_data_offer *offer,
- uint32_t dnd_action) {
- switch (dnd_action) {
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
- //printf("A move action would be performed if dropped\n");
- break;
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
- //printf("A copy action would be performed if dropped\n");
- break;
- case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
- //printf("The drag would be rejected if dropped\n");
- break;
- }
-}
-
-
-static const struct wl_data_offer_listener data_offer_listener = {
- .offer = data_offer_handle_offer,
- .source_actions = data_offer_handle_source_actions,
- .action = data_offer_handle_action,
-};
-
-
-static void data_device_handle_data_offer(void *data, struct wl_data_device *data_device,
- struct wl_data_offer *offer) {
- // An application has created a new data source
-//fprintf(stderr, "data_device_handle_data_offer offer=%p\n", offer);
- fl_selection_type[1] = NULL;
- wl_data_offer_add_listener(offer, &data_offer_listener, NULL);
- // reset current best mime-type and priority
- std::map<const char*const, mime_prio_struct>::iterator iter = clipboard_kinds_map.begin();
- while (iter != clipboard_kinds_map.end()) {
- iter->second.mime_type = NULL;
- iter->second.priority = 0;
- iter++;
- }
-}
-
-
-static void data_device_handle_selection(void *data, struct wl_data_device *data_device,
- struct wl_data_offer *offer) {
- // An application has set the clipboard contents. W
-//fprintf(stderr, "data_device_handle_selection\n");
- if (fl_selection_offer) wl_data_offer_destroy(fl_selection_offer);
- fl_selection_offer = offer;
-//if (offer == NULL) fprintf(stderr, "Clipboard is empty\n");
-}
-
-
-// Gets from the system the clipboard or dnd text and puts it in fl_selection_buffer[1]
-// which is enlarged if necessary.
-static void get_clipboard_or_dragged_text(struct wl_data_offer *offer) {
- int fds[2];
- char *from;
- if (pipe(fds)) return;
- // preferred mime-type for the text clipboard type
- const char *type = clipboard_kinds_map[Fl::clipboard_plain_text].mime_type;
- wl_data_offer_receive(offer, type, fds[1]);
- close(fds[1]);
- wl_display_flush(Fl_Wayland_Screen_Driver::wl_display);
- // read in fl_selection_buffer
- char *to = fl_selection_buffer[1];
- ssize_t rest = fl_selection_buffer_length[1];
- while (rest) {
- ssize_t n = read(fds[0], to, rest);
- if (n <= 0) {
- close(fds[0]);
- fl_selection_length[1] = to - fl_selection_buffer[1];
- fl_selection_buffer[1][ fl_selection_length[1] ] = 0;
- goto way_out;
- }
- n = Fl_Screen_Driver::convert_crlf(to, n);
- to += n;
- rest -= n;
- }
- // compute size of unread clipboard data
- rest = fl_selection_buffer_length[1];
- while (true) {
- char buf[1000];
- ssize_t n = read(fds[0], buf, sizeof(buf));
- if (n <= 0) {
- close(fds[0]);
- break;
- }
- rest += n;
- }
-//fprintf(stderr, "get_clipboard_or_dragged_text: size=%ld\n", rest);
- // read full clipboard data
- if (pipe(fds)) goto way_out;
- wl_data_offer_receive(offer, type, fds[1]);
- close(fds[1]);
- wl_display_flush(Fl_Wayland_Screen_Driver::wl_display);
- if (rest+1 > fl_selection_buffer_length[1]) {
- delete[] fl_selection_buffer[1];
- fl_selection_buffer[1] = new char[rest+1000+1];
- fl_selection_buffer_length[1] = rest+1000;
- }
- from = fl_selection_buffer[1];
- while (rest > 0) {
- ssize_t n = read(fds[0], from, rest);
- if (n <= 0) break;
- n = Fl_Screen_Driver::convert_crlf(from, n);
- from += n;
- rest -= n;
- }
- close(fds[0]);
- fl_selection_length[1] = from - fl_selection_buffer[1];
- fl_selection_buffer[1][fl_selection_length[1]] = 0;
-way_out:
- if (strcmp(type, "text/uri-list") == 0) {
- fl_decode_uri(fl_selection_buffer[1]); // decode encoded bytes
- char *p = fl_selection_buffer[1];
- while (*p) { // remove prefixes
- if (strncmp(p, "file://", 7) == 0) {
- memmove(p, p+7, strlen(p+7)+1);
- }
- p = strchr(p, '\n');
- if (!p) break;
- if (*++p == 0) *(p-1) = 0; // remove last '\n'
- }
- fl_selection_length[1] = strlen(fl_selection_buffer[1]);
- }
- Fl::e_clipboard_type = Fl::clipboard_plain_text;
-}
-
-
-static struct wl_data_offer *current_drag_offer = NULL;
-static uint32_t fl_dnd_serial;
-
-
-static void data_device_handle_enter(void *data, struct wl_data_device *data_device,
- uint32_t serial, struct wl_surface *surface,
- wl_fixed_t x, wl_fixed_t y,
- struct wl_data_offer *offer) {
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface);
-//printf("Drag entered our surface %p(win=%p) at %dx%d\n", surface, win, wl_fixed_to_int(x), wl_fixed_to_int(y));
- if (win) {
- fl_dnd_target_surface = surface;
- float f = Fl::screen_scale(win->screen_num());
- Fl::e_x = wl_fixed_to_int(x) / f;
- Fl::e_y = wl_fixed_to_int(y) / f;
- while (win->parent()) {
- Fl::e_x += win->x();
- Fl::e_y += win->y();
- win = win->window();
- }
- fl_dnd_target_window = win;
- Fl::e_x_root = Fl::e_x + fl_dnd_target_window->x();
- Fl::e_y_root = Fl::e_y + fl_dnd_target_window->y();
- Fl::handle(FL_DND_ENTER, fl_dnd_target_window);
- current_drag_offer = offer;
- fl_dnd_serial = serial;
- } else fl_dnd_target_window = NULL; // we enter a non-FLTK window (titlebar, shade)
- uint32_t supported_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
- uint32_t preferred_action = supported_actions;
- wl_data_offer_set_actions(offer, supported_actions, preferred_action);
-}
-
-
-static void data_device_handle_motion(void *data, struct wl_data_device *data_device,
- uint32_t time, wl_fixed_t x, wl_fixed_t y) {
- if (!current_drag_offer) return;
-//printf("data_device_handle_motion fl_dnd_target_window=%p\n", fl_dnd_target_window);
- int ret = 0;
- if (fl_dnd_target_window) {
- float f = Fl::screen_scale(fl_dnd_target_window->screen_num());
- Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(fl_dnd_target_surface);
- Fl::e_x = wl_fixed_to_int(x) / f;
- Fl::e_y = wl_fixed_to_int(y) / f;
- while (win->parent()) {
- Fl::e_x += win->x();
- Fl::e_y += win->y();
- win = win->window();
- }
- Fl::e_x_root = Fl::e_x + fl_dnd_target_window->x();
- Fl::e_y_root = Fl::e_y + fl_dnd_target_window->y();
- ret = Fl::handle(FL_DND_DRAG, fl_dnd_target_window);
- if (Fl::belowmouse()) Fl::belowmouse()->take_focus();
- }
- uint32_t supported_actions = ret && (Fl::pushed() || !doing_dnd) ?
- WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY : WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
- uint32_t preferred_action = supported_actions;
- wl_data_offer_set_actions(current_drag_offer, supported_actions, preferred_action);
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
- if (ret && current_drag_offer) wl_data_offer_accept(current_drag_offer, fl_dnd_serial, "text/plain");
-}
-
-
-static void data_device_handle_leave(void *data, struct wl_data_device *data_device) {
- //printf("Drag left our surface\n");
- if (current_drag_offer) Fl::handle(FL_DND_LEAVE, fl_dnd_target_window);
-}
-
-
-static void data_device_handle_drop(void *data, struct wl_data_device *data_device) {
- if (!current_drag_offer) return;
- Fl::handle(FL_ENTER, fl_dnd_target_window); // useful to set the belowmouse widget
- int ret = Fl::handle(FL_DND_RELEASE, fl_dnd_target_window);
-//printf("data_device_handle_drop ret=%d doing_dnd=%d\n", ret, doing_dnd);
-
- if (!ret) {
- wl_data_offer_destroy(current_drag_offer);
- current_drag_offer = NULL;
- return;
- }
-
- if (doing_dnd) {
- Fl::e_text = fl_selection_buffer[0];
- Fl::e_length = fl_selection_length[0];
- } else {
- get_clipboard_or_dragged_text(current_drag_offer);
- Fl::e_text = fl_selection_buffer[1];
- Fl::e_length = fl_selection_length[1];
- }
- int old_event = Fl::e_number;
- Fl::belowmouse()->handle(Fl::e_number = FL_PASTE);
- Fl::e_number = old_event;
-
- wl_data_offer_finish(current_drag_offer);
- wl_data_offer_destroy(current_drag_offer);
- current_drag_offer = NULL;
-}
-
-
-static const struct wl_data_device_listener data_device_listener = {
- .data_offer = data_device_handle_data_offer,
- .enter = data_device_handle_enter,
- .leave = data_device_handle_leave,
- .motion = data_device_handle_motion,
- .drop = data_device_handle_drop,
- .selection = data_device_handle_selection,
-};
-
-
-const struct wl_data_device_listener *Fl_Wayland_Screen_Driver::p_data_device_listener =
- &data_device_listener;
-
-
-// Reads from the clipboard an image which can be in image/bmp or image/png MIME type.
-// Returns 0 if OK, != 0 if error.
-static int get_clipboard_image(struct wl_data_offer *offer) {
- int fds[2];
- if (pipe(fds)) return 1;
- // preferred mime-type for the image clipboard type
- const char *type = clipboard_kinds_map[Fl::clipboard_image].mime_type;
- wl_data_offer_receive(offer, type, fds[1]);
- close(fds[1]);
- wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display);
- if (strcmp(type, "image/png") == 0) {
- char tmp_fname[21];
- Fl_Shared_Image *shared = 0;
- strcpy(tmp_fname, "/tmp/clipboardXXXXXX");
- int fd = mkstemp(tmp_fname);
- if (fd >= 0) {
- while (true) {
- char buf[10000];
- ssize_t n = read(fds[0], buf, sizeof(buf));
- if (n <= 0) break;
- n = write(fd, buf, n);
- }
- close(fd);
- shared = Fl_Shared_Image::get(tmp_fname);
- fl_unlink(tmp_fname);
- }
- close(fds[0]);
- if (!shared) return 1;
- int ld = shared->ld() ? shared->ld() : shared->w() * shared->d();
- uchar *rgb = new uchar[shared->w() * shared->h() * shared->d()];
- memcpy(rgb, shared->data()[0], ld * shared->h() );
- Fl_RGB_Image *image = new Fl_RGB_Image(rgb, shared->w(), shared->h(), shared->d(),
- shared->ld());
- shared->release();
- image->alloc_array = 1;
- Fl::e_clipboard_data = (void*)image;
- } else { // process image/bmp
- uchar buf[54];
- size_t rest = 1;
- char *bmp = NULL;
- ssize_t n = read(fds[0], buf, sizeof(buf)); // read size info of the BMP image
- if (n == sizeof(buf)) {
- int w, h; // size of the BMP image
- Fl_Unix_System_Driver::read_int(buf + 18, w);
- Fl_Unix_System_Driver::read_int(buf + 22, h);
- // the number of bytes per row of BMP image, rounded up to multiple of 4
- int R = ((3*w+3)/4) * 4;
- bmp = new char[R * h + 54];
- memcpy(bmp, buf, 54);
- char *from = bmp + 54;
- rest = R * h;
- while (rest) {
- ssize_t n = read(fds[0], from, rest);
- if (n <= 0) break;
- from += n;
- rest -= n;
- }
-//fprintf(stderr, "get_clipboard_image: image/bmp %dx%d rest=%lu\n", w,h,rest);
- }
- close(fds[0]);
- if (!rest) Fl::e_clipboard_data = Fl_Unix_System_Driver::own_bmp_to_RGB(bmp);
- delete[] bmp;
- if (rest) return 1;
- }
- Fl::e_clipboard_type = Fl::clipboard_image;
- return 0;
-}
-
-
-void Fl_Wayland_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const char *type) {
- if (clipboard != 1) return;
- if (fl_i_own_selection[1]) {
- // We already have it, do it quickly without compositor.
- if (type == Fl::clipboard_plain_text && fl_selection_type[1] == type) {
- Fl::e_text = fl_selection_buffer[1];
- Fl::e_length = fl_selection_length[1];
- if (!Fl::e_text) Fl::e_text = (char *)"";
- } else if (type == Fl::clipboard_image && fl_selection_type[1] == type) {
- Fl::e_clipboard_data = Fl_Unix_System_Driver::own_bmp_to_RGB(fl_selection_buffer[1]);
- Fl::e_clipboard_type = Fl::clipboard_image;
- } else return;
- receiver.handle(FL_PASTE);
- return;
- }
- // otherwise get the compositor to return it:
- if (!fl_selection_offer) return;
- if (type == Fl::clipboard_plain_text && clipboard_contains(Fl::clipboard_plain_text)) {
- get_clipboard_or_dragged_text(fl_selection_offer);
- Fl::e_text = fl_selection_buffer[1];
- Fl::e_length = fl_selection_length[1];
- receiver.handle(FL_PASTE);
- } else if (type == Fl::clipboard_image && clipboard_contains(Fl::clipboard_image)) {
- if (get_clipboard_image(fl_selection_offer)) return;
- struct wld_window * xid = fl_wl_xid(receiver.top_window());
- if (xid) {
- int s = Fl_Wayland_Window_Driver::driver(receiver.top_window())->wld_scale();
- if ( s > 1) {
- Fl_RGB_Image *rgb = (Fl_RGB_Image*)Fl::e_clipboard_data;
- rgb->scale(rgb->data_w() / s, rgb->data_h() / s);
- }
- }
- int done = receiver.handle(FL_PASTE);
- Fl::e_clipboard_type = "";
- if (done == 0) {
- delete (Fl_RGB_Image*)Fl::e_clipboard_data;
- Fl::e_clipboard_data = NULL;
- }
- }
-}
-
-
-void Fl_Wayland_Screen_Driver::copy(const char *stuff, int len, int clipboard,
- const char *type) {
- if (!stuff || len < 0) return;
-
- if (clipboard >= 2)
- clipboard = 1; // Only on X11 do multiple clipboards make sense.
-
- if (len+1 > fl_selection_buffer_length[clipboard]) {
- delete[] fl_selection_buffer[clipboard];
- fl_selection_buffer[clipboard] = new char[len+100];
- fl_selection_buffer_length[clipboard] = len+100;
- }
- memcpy(fl_selection_buffer[clipboard], stuff, len);
- fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
- fl_selection_length[clipboard] = len;
- fl_i_own_selection[clipboard] = 1;
- fl_selection_type[clipboard] = Fl::clipboard_plain_text;
- if (clipboard == 1) {
- if (seat->data_source) wl_data_source_destroy(seat->data_source);
- seat->data_source = wl_data_device_manager_create_data_source(seat->data_device_manager);
- // we transmit the adequate value of index in fl_selection_buffer[index]
- wl_data_source_add_listener(seat->data_source, &data_source_listener, (void*)1);
- wl_data_source_offer(seat->data_source, wld_plain_text_clipboard);
- wl_data_device_set_selection(seat->data_device,
- seat->data_source,
- seat->keyboard_enter_serial);
-//fprintf(stderr, "wl_data_device_set_selection len=%d to %d\n", len, clipboard);
- }
-}
-
-
-// takes a raw RGB image and puts it in the copy/paste buffer
-void Fl_Wayland_Screen_Driver::copy_image(const unsigned char *data, int W, int H){
- if (!data || W <= 0 || H <= 0) return;
- delete[] fl_selection_buffer[1];
- fl_selection_buffer[1] =
- (char *)Fl_Unix_System_Driver::create_bmp(data,W,H,&fl_selection_length[1]);
- fl_selection_buffer_length[1] = fl_selection_length[1];
- fl_i_own_selection[1] = 1;
- fl_selection_type[1] = Fl::clipboard_image;
- if (seat->data_source) wl_data_source_destroy(seat->data_source);
- seat->data_source = wl_data_device_manager_create_data_source(seat->data_device_manager);
- // we transmit the adequate value of index in fl_selection_buffer[index]
- wl_data_source_add_listener(seat->data_source, &data_source_listener, (void*)1);
- wl_data_source_offer(seat->data_source, "image/bmp");
- wl_data_device_set_selection(seat->data_device, seat->data_source,
- seat->keyboard_enter_serial);
-//fprintf(stderr, "copy_image: len=%d\n", fl_selection_length[1]);
-}
-
-////////////////////////////////////////////////////////////////
-// Code for tracking clipboard changes:
-
-// is that possible with Wayland ?
-
-////////////////////////////////////////////////////////////////
-
-#endif // !defined(FL_DOXYGEN)
diff --git a/src/drivers/Wayland/fl_wayland_platform_init.cxx b/src/drivers/Wayland/fl_wayland_platform_init.cxx
deleted file mode 100644
index 4c4477740..000000000
--- a/src/drivers/Wayland/fl_wayland_platform_init.cxx
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// Wayland-specific code to initialize wayland support.
-//
-// Copyright 2022-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <FL/fl_config.h>
-#include "Fl_Wayland_Copy_Surface_Driver.H"
-#include "Fl_Wayland_Graphics_Driver.H"
-#include "Fl_Wayland_Screen_Driver.H"
-#include "../Unix/Fl_Unix_System_Driver.H"
-#include "Fl_Wayland_Window_Driver.H"
-#include "Fl_Wayland_Image_Surface_Driver.H"
-#include "../Base/Fl_Base_Pen_Events.H"
-#ifdef FLTK_USE_X11
-# include "../Xlib/Fl_Xlib_Copy_Surface_Driver.H"
-# include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H"
-# include "../X11/Fl_X11_Screen_Driver.H"
-# include "../X11/Fl_X11_Window_Driver.H"
-# include "../Xlib/Fl_Xlib_Image_Surface_Driver.H"
-#endif
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-
-#ifdef FLTK_USE_X11
-
-static bool attempt_wayland() {
- if (Fl_Wayland_Screen_Driver::wl_display) return true;
- static bool first = true;
- static bool disable_wl = false;
- if (first) { // get the value if it exists and cache it
- void *sym = Fl_Posix_System_Driver::dlopen_or_dlsym(NULL, "fl_disable_wayland");
- if (sym) {
- disable_wl = *(bool *)sym;
- // printf("fl_disable_wayland = %s\n", disable_wl ? "true" : "false");
- }
- first = false;
- }
- if (disable_wl)
- return false;
- const char *backend = ::getenv("FLTK_BACKEND");
- // fprintf(stderr, "FLTK_BACKEND='%s'\n", backend ? backend : "");
- if (backend && strcmp(backend, "x11") == 0) {
- return false;
- }
-
- if (backend && strcmp(backend, "wayland") == 0) {
- Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL);
- if (!Fl_Wayland_Screen_Driver::wl_display) {
- fprintf(stderr, "Error: no Wayland connection available, FLTK_BACKEND='wayland'\n");
- exit(1);
- }
- return true;
- }
-
- if (!backend) {
- // env var XDG_RUNTIME_DIR is required for Wayland
- const char *xdgrt = ::getenv("XDG_RUNTIME_DIR");
- if (xdgrt) {
- // is a Wayland connection available ?
- Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL);
- if (Fl_Wayland_Screen_Driver::wl_display) { // Yes, use Wayland drivers
- // puts("using wayland");
- return true;
- }
- }
- // no Wayland connection or environment variable XDG_RUNTIME_DIR not set,
- // falling back to X11
- return false;
- }
-
- fprintf(stderr, "Error: unexpected value of FLTK_BACKEND: '%s'\n", backend);
- exit(1);
- return false;
-}
-
-#endif // FLTK_USE_X11
-
-
-Fl_System_Driver *Fl_System_Driver::newSystemDriver() {
- return new Fl_Unix_System_Driver();
-}
-
-
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() {
-#ifdef FLTK_USE_X11
- if (!attempt_wayland()) return new Fl_X11_Cairo_Graphics_Driver();
-#endif
- return new Fl_Wayland_Graphics_Driver();
-}
-
-
-Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) {
-#ifdef FLTK_USE_X11
- if (!Fl_Wayland_Screen_Driver::wl_display) return new Fl_Xlib_Copy_Surface_Driver(w, h);
-#endif
- return new Fl_Wayland_Copy_Surface_Driver(w, h);
-}
-
-
-Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() {
- if (!Fl_Screen_Driver::system_driver) Fl::system_driver();
-#ifdef FLTK_USE_X11
- if (attempt_wayland()) {
- return new Fl_Wayland_Screen_Driver();
- }
-
- Fl_X11_Screen_Driver *d = new Fl_X11_Screen_Driver();
- for (int i = 0; i < MAX_SCREENS; i++) d->screens[i].scale = 1;
- d->current_xft_dpi = 0.; // means the value of the Xft.dpi resource is still unknown
- return d;
-#else
- return new Fl_Wayland_Screen_Driver();
-#endif
-}
-
-
-Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
-{
-#ifdef FLTK_USE_X11
- if (!attempt_wayland()) return new Fl_X11_Window_Driver(w);
-#endif
- return new Fl_Wayland_Window_Driver(w);
-}
-
-
-Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off)
-{
-#ifdef FLTK_USE_X11
- if (!attempt_wayland())
- return new Fl_Xlib_Image_Surface_Driver(w, h, high_res, off);
-#endif
- return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off);
-}
-
-#if defined(FLTK_HAVE_PEN_SUPPORT)
-
-namespace Fl {
-namespace Pen {
-Driver default_driver;
-Driver& driver = default_driver;
-} // namespace Pen
-} // namespace Fl
-
-#endif // FLTK_HAVE_PEN_SUPPORT
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H
deleted file mode 100644
index 2958fe6e5..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021-2023 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#ifndef FL_WINAPI_GL_WINDOW_DRIVER_H
-#define FL_WINAPI_GL_WINDOW_DRIVER_H
-
-#include <config.h>
-#if HAVE_GL
-#include <FL/platform.H>
-#include "../../Fl_Gl_Window_Driver.H"
-#include <FL/gl.h>
-
-class Fl_WinAPI_Gl_Window_Driver : public Fl_Gl_Window_Driver {
- friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *);
- Fl_WinAPI_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
- float pixels_per_unit() FL_OVERRIDE;
- int mode_(int m, const int *a) FL_OVERRIDE;
- void make_current_after() FL_OVERRIDE;
- void swap_buffers() FL_OVERRIDE;
- void swap_interval(int) FL_OVERRIDE;
- int swap_interval() const FL_OVERRIDE;
- void invalidate() FL_OVERRIDE {}
- int flush_begin(char& valid_f) FL_OVERRIDE;
- Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE;
- GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE;
- GLContext do_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g,
- int layer);
- void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE;
- void delete_gl_context(GLContext) FL_OVERRIDE;
- void make_overlay_current() FL_OVERRIDE;
- void redraw_overlay() FL_OVERRIDE;
- void* GetProcAddress(const char *procName) FL_OVERRIDE;
- void draw_string_legacy(const char* str, int n) FL_OVERRIDE;
- void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) FL_OVERRIDE;
- void get_list(Fl_Font_Descriptor *fd, int r) FL_OVERRIDE;
- int genlistsize() FL_OVERRIDE;
- void switch_to_GL1() FL_OVERRIDE;
- void switch_back() FL_OVERRIDE;
-#if HAVE_GL_OVERLAY
- void gl_hide_before(void *& overlay) FL_OVERRIDE;
- int can_do_overlay() FL_OVERRIDE;
- int overlay_color(Fl_Color i) FL_OVERRIDE;
- void make_overlay(void*&overlay) FL_OVERRIDE;
-#endif
-};
-
-#endif // HAVE_GL
-
-#endif // FL_WINAPI_GL_WINDOW_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx
deleted file mode 100644
index 8e199b09c..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx
+++ /dev/null
@@ -1,472 +0,0 @@
-//
-// Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2021-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#if HAVE_GL
-#include <FL/platform.H>
-#include "../../Fl_Screen_Driver.H"
-#include <FL/gl.h>
-#include "Fl_WinAPI_Gl_Window_Driver.H"
-#include "../../Fl_Gl_Choice.H"
-#include "Fl_WinAPI_Window_Driver.H"
-#include "../GDI/Fl_Font.H"
-extern void fl_save_dc(HWND, HDC);
-
-#ifndef GL_CURRENT_PROGRAM
-# define GL_CURRENT_PROGRAM 0x8B8D // from glew.h
-#endif
-
-// STR #3119: select pixel format with composition support
-// ... and no more than 32 color bits (8 bits/color)
-// Ref: PixelFormatDescriptor Object
-// https://msdn.microsoft.com/en-us/library/cc231189.aspx
-#if !defined(PFD_SUPPORT_COMPOSITION)
-# define PFD_SUPPORT_COMPOSITION (0x8000)
-#endif
-
-#define DEBUG_PFD (0) // 1 = PFD selection debug output, 0 = no debug output
-
-
-// Describes crap needed to create a GLContext.
-class Fl_WinAPI_Gl_Choice : public Fl_Gl_Choice {
- friend class Fl_WinAPI_Gl_Window_Driver;
-private:
- int pixelformat; // the visual to use
- PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing
-public:
- Fl_WinAPI_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) {
- pixelformat = 0;
- }
-};
-
-
-Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
-{
- return new Fl_WinAPI_Gl_Window_Driver(w);
-}
-
-
-Fl_Gl_Choice *Fl_WinAPI_Gl_Window_Driver::find(int m, const int *alistp)
-{
- Fl_WinAPI_Gl_Choice *g = (Fl_WinAPI_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp);
- if (g) return g;
-
- // Replacement for ChoosePixelFormat() that finds one with an overlay if possible:
- HDC gc = (HDC)(fl_graphics_driver ? fl_graphics_driver->gc() : 0);
- if (!gc) gc = fl_GetDC(0);
- int pixelformat = 0;
- PIXELFORMATDESCRIPTOR chosen_pfd;
- for (int i = 1; ; i++) {
- PIXELFORMATDESCRIPTOR pfd;
- if (!DescribePixelFormat(gc, i, sizeof(pfd), &pfd)) break;
- // continue if it does not satisfy our requirements:
- if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue;
- if (pfd.iPixelType != ((m&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue;
- if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue;
- if ((m & FL_ACCUM) && !pfd.cAccumBits) continue;
- if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue;
- if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue;
- // Skipt his descriptor if we want a depth buffer, but this one has none
- if ((m & FL_DEPTH) && !pfd.cDepthBits) continue;
- // Skipt his descriptor if we want a 32 bit depth buffer, but this one has less or none
- if ((m & FL_DEPTH32) && pfd.cDepthBits < 32) continue;
- if ((m & FL_STENCIL) && !pfd.cStencilBits) continue;
-
-#if DEBUG_PFD
- printf("pfd #%d supports composition: %s\n", i, (pfd.dwFlags & PFD_SUPPORT_COMPOSITION) ? "yes" : "no");
- printf(" ... & PFD_GENERIC_FORMAT: %s\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) ? "generic" : "accelerated");
- printf(" ... Overlay Planes : %d\n", pfd.bReserved & 15);
- printf(" ... Color & Depth : %d, %d\n", pfd.cColorBits, pfd.cDepthBits);
- if (pixelformat)
- printf(" current pixelformat : %d\n", pixelformat);
- fflush(stdout);
-#endif // DEBUG_PFD
-
- // see if better than the one we have already:
- if (pixelformat) {
- // offering non-generic rendering is better (read: hardware acceleration)
- if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) &&
- (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue;
- // offering overlay is better:
- else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {}
- // otherwise prefer a format that supports composition (STR #3119)
- else if ((chosen_pfd.dwFlags & PFD_SUPPORT_COMPOSITION) &&
- !(pfd.dwFlags & PFD_SUPPORT_COMPOSITION)) continue;
- // otherwise more bit planes is better, but no more than 32 (8 bits per channel):
- else if (pfd.cColorBits > 32 || chosen_pfd.cColorBits > pfd.cColorBits) continue;
- else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue;
- }
- pixelformat = i;
- chosen_pfd = pfd;
- }
-
-#if DEBUG_PFD
- static int bb = 0;
- if (!bb) {
- bb = 1;
- printf("PFD_SUPPORT_COMPOSITION = 0x%x\n", PFD_SUPPORT_COMPOSITION);
- }
- printf("Chosen pixel format is %d\n", pixelformat);
- printf("Color bits = %d, Depth bits = %d\n", chosen_pfd.cColorBits, chosen_pfd.cDepthBits);
- printf("Pixel format supports composition: %s\n", (chosen_pfd.dwFlags & PFD_SUPPORT_COMPOSITION) ? "yes" : "no");
- fflush(stdout);
-#endif // DEBUG_PFD
-
- if (!pixelformat) return 0;
-
- g = new Fl_WinAPI_Gl_Choice(m, alistp, first);
- first = g;
-
- g->pixelformat = pixelformat;
- g->pfd = chosen_pfd;
-
- return g;
-}
-
-
-GLContext Fl_WinAPI_Gl_Window_Driver::do_create_gl_context(Fl_Window* window,
- const Fl_Gl_Choice* g, int layer)
-{
- Fl_X* i = Fl_X::flx(window);
- HDC hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc;
- if (!hdc) {
- hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc = GetDCEx((HWND)i->xid, 0, DCX_CACHE);
- fl_save_dc((HWND)i->xid, hdc);
- SetPixelFormat(hdc, ((Fl_WinAPI_Gl_Choice*)g)->pixelformat, (PIXELFORMATDESCRIPTOR*)(&((Fl_WinAPI_Gl_Choice*)g)->pfd));
-# if USE_COLORMAP
- if (fl_palette) SelectPalette(hdc, fl_palette, FALSE);
-# endif
- }
- GLContext context = layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc);
- if (context) {
- if (context_list && nContext)
- wglShareLists((HGLRC)context_list[0], (HGLRC)context);
- add_context(context);
- }
- return context;
-}
-
-
-GLContext Fl_WinAPI_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g)
-{
- return do_create_gl_context(window, g, 0);
-}
-
-void Fl_WinAPI_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) {
- GLContext current_context = wglGetCurrentContext();
- if (context != current_context || w != cached_window) {
- cached_window = w;
- wglMakeCurrent(Fl_WinAPI_Window_Driver::driver(w)->private_dc, (HGLRC)context);
- }
-}
-
-void Fl_WinAPI_Gl_Window_Driver::delete_gl_context(GLContext context) {
- GLContext current_context = wglGetCurrentContext();
- if (current_context == context) {
- cached_window = 0;
- wglMakeCurrent(0, 0);
- }
- wglDeleteContext((HGLRC)context);
- del_context(context);
-}
-
-
-void Fl_WinAPI_Gl_Window_Driver::make_overlay_current() {
-#if HAVE_GL_OVERLAY
- if (overlay() != this) {
- set_gl_context(pWindow, (GLContext)overlay());
- // if (fl_overlay_depth)
- // wglRealizeLayerPalette(Fl_X::flx(this)->private_dc, 1, TRUE);
- } else
-#endif
- glDrawBuffer(GL_FRONT);
-}
-
-void Fl_WinAPI_Gl_Window_Driver::redraw_overlay() {
- pWindow->damage(FL_DAMAGE_OVERLAY);
-}
-
-#if HAVE_GL_OVERLAY
-
-// Methods on Fl_Gl_Window_driver that create an overlay window.
-
-// Under win32 another GLX context is created to draw into the overlay
-// and it is stored in the "overlay" pointer.
-
-// If overlay hardware is unavailable, the overlay is
-// "faked" by drawing into the main layers. This is indicated by
-// setting overlay == this.
-
-//static COLORREF *palette;
-static int fl_overlay_depth = 0;
-
-void Fl_WinAPI_Gl_Window_Driver::gl_hide_before(void *& overlay) {
- if (overlay && overlay != pWindow) {
- delete_gl_context((GLContext)overlay);
- overlay = 0;
- }
-}
-
-void Fl_WinAPI_Gl_Window_Driver::make_overlay(void*&overlay) {
- if (overlay) return;
-
- GLContext context = do_create_gl_context(pWindow, g(), 1);
- if (!context) {overlay = pWindow; return;} // fake the overlay
-
- HDC hdc = Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc;
- overlay = context;
- LAYERPLANEDESCRIPTOR pfd;
- wglDescribeLayerPlane(hdc, g()->pixelformat, 1, sizeof(pfd), &pfd);
- if (!pfd.iPixelType) {
- ; // full-color overlay
- } else {
- fl_overlay_depth = pfd.cColorBits; // used by gl_color()
- if (fl_overlay_depth > 8) fl_overlay_depth = 8;
- COLORREF palette[256];
- int n = (1<<fl_overlay_depth)-1;
- // copy all colors except #0 into the overlay palette:
- for (int i = 0; i <= n; i++) {
- uchar r,g,b; Fl::get_color((Fl_Color)i,r,g,b);
- palette[i] = RGB(r,g,b);
- }
- // always provide black & white in the last 2 pixels:
- if (fl_overlay_depth < 8) {
- palette[n-1] = RGB(0,0,0);
- palette[n] = RGB(255,255,255);
- }
- // and use it:
- wglSetLayerPaletteEntries(hdc, 1, 1, n, palette+1);
- wglRealizeLayerPalette(hdc, 1, TRUE);
- }
- pWindow->valid(0);
- return;
-}
-
-int Fl_WinAPI_Gl_Window_Driver::can_do_overlay() {
- if (!g()) {
- g( find(mode(), alist()) );
- if (!g()) return 0;
- }
- return (g()->pfd.bReserved & 15) != 0;
-}
-
-int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) {
- if (Fl_Xlib_Graphics_Driver::fl_overlay && fl_overlay_depth) {
- if (fl_overlay_depth < 8) {
- // only black & white produce the expected colors. This could
- // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx
- int size = 1<<fl_overlay_depth;
- if (!i) glIndexi(size-2);
- else if (i >= size-2) glIndexi(size-1);
- else glIndexi(i);
- } else {
- glIndexi(i ? i : FL_GRAY_RAMP);
- }
- return 1;
- }
- return 0;
-}
-
-#endif // HAVE_GL_OVERLAY
-
-
-float Fl_WinAPI_Gl_Window_Driver::pixels_per_unit()
-{
- int ns = Fl_Window_Driver::driver(pWindow)->screen_num();
- return Fl::screen_driver()->scale(ns);
-}
-
-
-int Fl_WinAPI_Gl_Window_Driver::mode_(int m, const int *a) {
- int oldmode = mode();
- pWindow->context(0);
- mode( m); alist(a);
- if (pWindow->shown()) {
- g( find(m, a) );
- if (!g() || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) {
- pWindow->hide();
- pWindow->show();
- }
- } else {
- g(0);
- }
- return 1;
-}
-
-void Fl_WinAPI_Gl_Window_Driver::make_current_after() {
-#if USE_COLORMAP
- if (fl_palette) {
- fl_GetDC(fl_xid(pWindow));
- SelectPalette((HDC)fl_graphics_driver->gc(), fl_palette, FALSE);
- RealizePalette((HDC)fl_graphics_driver->gc());
- }
-#endif // USE_COLORMAP
-}
-
-//#define HAVE_GL_OVERLAY 1 //test only
-
-void Fl_WinAPI_Gl_Window_Driver::swap_buffers() {
-# if HAVE_GL_OVERLAY
- // Do not swap the overlay, to match GLX:
- BOOL ret = wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_MAIN_PLANE);
- DWORD err = GetLastError();
-# else
- SwapBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc);
-# endif
-}
-
-
-// Start of swap_interval implementation in the three possibel ways for X11
-
-// -1 = not yet initialized, 0 = none found, 1 = GLX, 2 = MESA, 3 = SGI
-static signed char swap_interval_type = -1;
-
-typedef const char *(WINAPI *WGL_Get_Extension_String_Proc)();
-typedef BOOL (WINAPI *WGL_Swap_Iterval_Proc)(int interval);
-typedef int (WINAPI *WGL_Get_Swap_Iterval_Proc)();
-
-static WGL_Swap_Iterval_Proc wglSwapIntervalEXT = NULL;
-static WGL_Get_Swap_Iterval_Proc wglGetSwapIntervalEXT = NULL;
-
-static void init_swap_interval() {
- if (swap_interval_type != -1)
- return;
- swap_interval_type = 0;
- WGL_Get_Extension_String_Proc wglGetExtensionsStringEXT = NULL;
- wglGetExtensionsStringEXT = (WGL_Get_Extension_String_Proc)wglGetProcAddress("wglGetExtensionsStringEXT");
- if (!wglGetExtensionsStringEXT)
- return;
- const char *extensions = wglGetExtensionsStringEXT();
- if (extensions && strstr(extensions, "WGL_EXT_swap_control")) {
- wglSwapIntervalEXT = (WGL_Swap_Iterval_Proc)wglGetProcAddress("wglSwapIntervalEXT");
- wglGetSwapIntervalEXT = (WGL_Get_Swap_Iterval_Proc)wglGetProcAddress("wglGetSwapIntervalEXT");
- swap_interval_type = 1;
- }
-}
-
-void Fl_WinAPI_Gl_Window_Driver::swap_interval(int interval) {
- if (swap_interval_type == -1)
- init_swap_interval();
- if (swap_interval_type == 1) {
- if (wglSwapIntervalEXT)
- wglSwapIntervalEXT(interval);
- }
-}
-
-int Fl_WinAPI_Gl_Window_Driver::swap_interval() const {
- if (swap_interval_type == -1)
- init_swap_interval();
- int interval = -1;
- if (swap_interval_type == 1) {
- if (wglGetSwapIntervalEXT)
- interval = wglGetSwapIntervalEXT();
- }
- return interval;
-}
-
-// end of swap_interval implementation
-
-#if HAVE_GL_OVERLAY
-#endif
-
-int Fl_WinAPI_Gl_Window_Driver::flush_begin(char& valid_f_) {
-#if HAVE_GL_OVERLAY
- char save_valid_f = valid_f_;
- // Draw into hardware overlay planes if they are damaged:
- if (overlay() && overlay() != pWindow
- && (pWindow->damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid_f & 1)) {
- set_gl_context(pWindow, (GLContext)overlay());
- if (fl_overlay_depth)
- wglRealizeLayerPalette(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, 1, TRUE);
- glDisable(GL_SCISSOR_TEST);
- glClear(GL_COLOR_BUFFER_BIT);
- Fl_Xlib_Graphics_Driver::fl_overlay = 1;
- draw_overlay();
- Fl_Xlib_Graphics_Driver::fl_overlay = 0;
- valid_f_ = save_valid_f;
- wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_OVERLAY1);
- // if only the overlay was damaged we are done, leave main layer alone:
- if (pWindow->damage() == FL_DAMAGE_OVERLAY) {
- return 1;
- }
- }
-#endif
- return 0;
-}
-
-void* Fl_WinAPI_Gl_Window_Driver::GetProcAddress(const char *procName) {
- return (void*)wglGetProcAddress((LPCSTR)procName);
-}
-
-
-void Fl_WinAPI_Gl_Window_Driver::draw_string_legacy(const char* str, int n) {
- draw_string_legacy_get_list(str, n);
-}
-
-int Fl_WinAPI_Gl_Window_Driver::genlistsize() {
- return 0x10000;
-}
-
-void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {
- if (!fl_fontsize->listbase) {
- fl_fontsize->listbase = glGenLists(genlistsize());
- }
- glListBase(fl_fontsize->listbase);
-}
-
-void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) {
- Fl_GDI_Font_Descriptor* gl_fd = (Fl_GDI_Font_Descriptor*)fd;
- if (gl_fd->glok[r]) return;
- gl_fd->glok[r] = 1;
- unsigned int ii = r * 0x400;
- HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid);
- wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, 0x400, gl_fd->listbase+ii);
- SelectObject((HDC)fl_graphics_driver->gc(), oldFid);
-}
-
-
-typedef void (WINAPI *glUseProgram_type)(GLint);
-static glUseProgram_type glUseProgram_f = NULL;
-
-void Fl_WinAPI_Gl_Window_Driver::switch_to_GL1() {
- if (!glUseProgram_f) {
- glUseProgram_f = (glUseProgram_type)GetProcAddress("glUseProgram");
- }
- glGetIntegerv(GL_CURRENT_PROGRAM, &current_prog);
- if (current_prog) glUseProgram_f(0);
-}
-
-void Fl_WinAPI_Gl_Window_Driver::switch_back() {
- if (current_prog) glUseProgram_f((GLuint)current_prog);
-}
-
-
-class Fl_WinAPI_Gl_Plugin : public Fl_WinAPI_Plugin {
-public:
- Fl_WinAPI_Gl_Plugin() : Fl_WinAPI_Plugin(name()) { }
- const char *name() override { return "gl.winapi.fltk.org"; }
- void invalidate(Fl_Window *w) override {
- w->as_gl_window()->valid(0);
- }
-};
-
-
-static Fl_WinAPI_Gl_Plugin Gl_Invalidate_Plugin;
-
-
-FL_EXPORT HGLRC fl_win32_glcontext(GLContext rc) { return (HGLRC)rc; }
-
-#endif // HAVE_GL
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx
deleted file mode 100644
index 06cc1e477..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Pen_Driver.cxx
+++ /dev/null
@@ -1,518 +0,0 @@
-//
-// Definition of Windows Pen/Tablet event driver.
-//
-// Copyright 2025-2026 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-// Note: We require Windows 8 or later features for Pen/Tablet support.
-// Defining WINVER and _WIN32_WINNT to 0x0602 *may* be required on some
-// Windows build platforms. Must be done before all #include's.
-
-#if !defined(WINVER) || (WINVER < 0x0602)
-# ifdef WINVER
-# undef WINVER
-# endif
-# define WINVER 0x0602
-#endif
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0602)
-# ifdef _WIN32_WINNT
-# undef _WIN32_WINNT
-# endif
-# define _WIN32_WINNT 0x0602
-#endif
-
-#include "src/drivers/Base/Fl_Base_Pen_Events.H"
-
-#include <FL/platform.H>
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include "../../Fl_Screen_Driver.H"
-#include <math.h>
-#include <windows.h>
-#include <ole2.h>
-#include <shellapi.h>
-// Some versions of MinGW now require us to explicitly include winerror to get S_OK defined
-#include <winerror.h>
-
-extern Fl_Window *fl_xmousewin;
-
-static constexpr uint8_t _FL_PEN = 0; // internal use
-static constexpr uint8_t _FL_ERASER = 1; // internal use
-static uint8_t device_type_ = _FL_PEN;
-
-static int _e_x_down = 0;
-static int _e_y_down = 0;
-
-// Click counting state
-static DWORD last_click_time_ = 0;
-static int last_click_x_ = 0;
-static int last_click_y_ = 0;
-static Fl::Pen::State last_click_trigger_ = Fl::Pen::State::NONE;
-
-// The trait list keeps track of traits for every pen ID that appears while
-// handling events.
-// AppKit does not tell us what traits are available per pen or tablet, so
-// we use the first 5 motion events to discover event values that are not
-// the default value, and enter that knowledge into the traits database.
-typedef std::map<int, Fl::Pen::Trait> TraitList;
-static TraitList trait_list_;
-static int trait_countdown_ { 5 };
-static int current_pen_id_ { -1 };
-static Fl::Pen::Trait current_pen_trait_ { Fl::Pen::Trait::DRIVER_AVAILABLE };
-static Fl::Pen::Trait driver_traits_ {
- Fl::Pen::Trait::DRIVER_AVAILABLE | Fl::Pen::Trait::PEN_ID |
- Fl::Pen::Trait::ERASER | Fl::Pen::Trait::PRESSURE |
- Fl::Pen::Trait::TILT_X |
- Fl::Pen::Trait::TILT_Y | Fl::Pen::Trait::TWIST
- // Notably missing: PROXIMITY, BARREL_PRESSURE
-};
-
-// Temporary storage of event data for the driver;
-static Fl::Pen::EventData ev;
-
-
-namespace Fl {
-
-// namespace Private {
-
-// // Global mouse position at mouse down event
-// extern int e_x_down;
-// extern int e_y_down;
-
-// }; // namespace Private
-
-namespace Pen {
-
-class Windows_Driver : public Driver {
-public:
- Windows_Driver() = default;
- //virtual void subscribe(Fl_Widget* widget) override;
- //virtual void unsubscribe(Fl_Widget* widget) override;
- //virtual void release() override;
- virtual Trait traits() override { return driver_traits_; }
- virtual Trait pen_traits(int pen_id) override {
- auto it = trait_list_.find(pen_id);
- if (pen_id == 0)
- return current_pen_trait_;
- if (it == trait_list_.end()) {
- return Trait::DRIVER_AVAILABLE;
- } else {
- return it->second;
- }
- }
-};
-
-Windows_Driver windows_driver;
-Driver& driver { windows_driver };
-
-} // namespace Pen
-
-} // namespace Fl
-
-
-using namespace Fl::Pen;
-
-/*
- Copy the event state.
- */
-static void copy_state() {
- Fl::Pen::State tr = (Fl::Pen::State)((uint32_t)Fl::Pen::e.state ^ (uint32_t)ev.state);
- Fl::Pen::e = ev;
- Fl::Pen::e.trigger = tr;
- Fl::e_x = (int)ev.x;
- Fl::e_y = (int)ev.y;
- Fl::e_x_root = (int)ev.rx;
- Fl::e_y_root = (int)ev.ry;
-}
-
-/*
- Check if coordinates are within the widget box.
- Coordinates are in top_window space. We iterate up the hierarchy to ensure
- that we handle subwindows correctly.
- */
-static bool event_inside(Fl_Widget *w, double x, double y) {
- if (w->as_window()) {
- return ((x >= 0) && (y >= 0) && (x < w->w()) && (y < w->h()));
- } else {
- return ((x >= w->x()) && (y >= w->y()) && (x < w->x() + w->w()) && (y < w->y() + w->h()));
- }
-}
-
-/*
- Find the widget under the pen event.
- Search the subscriber list for widgets that are inside the same window,
- are visible, and are within the give coordinates. Subwindow aware.
- */
-static Fl_Widget *find_below_pen(Fl_Window *win, double x, double y) {
- for (auto &sub: subscriber_list_) {
- Fl_Widget *candidate = sub.second->widget();
- if (candidate && ((candidate == win) || (!candidate->as_window() && candidate->window() == win))) {
- if (candidate->visible() && event_inside(candidate, x, y)) {
- return candidate;
- }
- }
- }
- return nullptr;
-}
-
-/*
- Send the current event and event data to a widget.
- Note: we will get the wrong coordinates if the widget is not a child of
- the current event window (LEAVE events between windows).
- */
-static int pen_send(Fl_Widget *w, int event, State trigger, bool &copied) {
- // Copy most event data only once
- if (!copied) {
- copy_state();
- copied = true;
- }
- // Copy the top_window coordinates again as they may change when w changes
- Fl::e_x = e.x = ev.x;
- Fl::e_y = e.y = ev.y;
- // Send the event.
- e.trigger = trigger;
- return w->handle(event);
-}
-
-/*
- Send an event to all subscribers.
- */
-static int pen_send_all(int event, State trigger) {
- bool copied = false;
- // use local value because handler may still change ev values
- for (auto &it: subscriber_list_) {
- auto w = it.second->widget();
- if (w)
- pen_send(w, event, trigger, copied);
- }
- return 1;
-}
-
-/*
- Convert the NSEvent button number to Fl::Pen::State,
- */
-static State button_to_trigger(POINTER_BUTTON_CHANGE_TYPE button, bool down) {
- switch (button) {
- case POINTER_CHANGE_FIRSTBUTTON_DOWN:
- case POINTER_CHANGE_FIRSTBUTTON_UP:
- if ( (ev.state & (State::ERASER_DOWN | State::ERASER_HOVERS)) != State::NONE ) {
- return down ? State::ERASER_DOWN : State::ERASER_HOVERS;
- } else {
- return down ? State::TIP_DOWN : State::TIP_HOVERS;
- }
- case POINTER_CHANGE_SECONDBUTTON_DOWN:
- case POINTER_CHANGE_SECONDBUTTON_UP:
- return State::BUTTON0;
- case POINTER_CHANGE_THIRDBUTTON_DOWN:
- case POINTER_CHANGE_THIRDBUTTON_UP:
- return State::BUTTON1;
- case POINTER_CHANGE_FOURTHBUTTON_DOWN:
- case POINTER_CHANGE_FOURTHBUTTON_UP:
- return State::BUTTON2;
- case POINTER_CHANGE_FIFTHBUTTON_DOWN:
- case POINTER_CHANGE_FIFTHBUTTON_UP:
- return State::BUTTON3;
- default: return State::NONE;
- }
-}
-
-/*
- Handle events coming from the Win32 API.
- WM_TABLET (Windows 2000 and up)
- WM_POINTER (Windows 8 and up)
- https://learn.microsoft.com/en-us/windows/win32/inputmsg/messages-and-notifications-portal
- #if(WINVER >= 0x0602) ... #endif
- \return -1 if we did not handle the event and want the main event handler to call DefWindowProc()
- \return any other value that will then be return from WndProc() directly.
- */
-LRESULT fl_win32_tablet_handler(MSG& msg) {
- auto message = msg.message;
- if (message < WM_NCPOINTERUPDATE || message > WM_POINTERROUTEDRELEASED) {
- return -1;
- }
-
- Fl_Window *eventWindow = fl_find(msg.hwnd); // can be nullptr
- bool is_proximity = false;
- bool is_down = false;
- bool is_up = false;
- bool is_motion = false;
-
- switch (msg.message) {
- case WM_NCPOINTERDOWN: // pen pushed over window decoration, don't care
- case WM_NCPOINTERUP: // pen released over window decoration, don't care
- case WM_NCPOINTERUPDATE: // pen moved over decoration, don't care
- case WM_POINTERACTIVATE: // shall the pointer activate an inactive window?
- return -1; // let the system handle this forwarding this to DefWindowProc
-
- case WM_POINTERENTER: // pointer moved into window area from top or sides
- is_proximity = true;
- break;
- case WM_POINTERLEAVE: // left window area to top or sides
- is_proximity = true;
- break;
-
-
- case WM_POINTERDOWN:
- is_down = true;
- break;
- case WM_POINTERUP:
- is_up = true;
- break;
- case WM_POINTERUPDATE:
- is_motion = true;
- break;
-
- case WM_POINTERCAPTURECHANGED:
- case WM_TOUCHHITTESTING:
- case WM_POINTERWHEEL:
- case WM_POINTERHWHEEL:
- case DM_POINTERHITTEST:
- case WM_POINTERROUTEDTO:
- case WM_POINTERROUTEDAWAY:
- case WM_POINTERROUTEDRELEASED:
- default:
- // printf("Windows message: msg=0x%04X wParam=0x%08X lParam=0x%08X\n",
- // msg.message, (unsigned)msg.wParam, (unsigned)msg.lParam);
- return -1;
- }
- // printf(" msg=0x%04X wParam=0x%08X lParam=0x%08X\n",
- // msg.message, (unsigned)msg.wParam, (unsigned)msg.lParam);
-
- POINTER_PEN_INFO info;
- BOOL has_position = GetPointerPenInfo(
- GET_POINTERID_WPARAM(msg.wParam),
- &info
- );
- // if (has_position && info.pointerInfo.ButtonChangeType!=0) {
- // printf(" pointerFlags: %08x [", (unsigned)info.pointerInfo.pointerFlags);
- // if (info.pointerInfo.pointerFlags & POINTER_FLAG_FIRSTBUTTON) printf(" 1ST");
- // if (info.pointerInfo.pointerFlags & POINTER_FLAG_SECONDBUTTON) printf(" 2ND");
- // if (info.pointerInfo.pointerFlags & POINTER_FLAG_THIRDBUTTON) printf(" 3RD");
- // if (info.pointerInfo.pointerFlags & POINTER_FLAG_FOURTHBUTTON) printf(" 4TH");
- // if (info.pointerInfo.pointerFlags & POINTER_FLAG_FIFTHBUTTON) printf(" 5TH");
- // printf(" ]\n penFlags: %08x [", (unsigned)info.penFlags);
- // if (info.penFlags & PEN_FLAG_BARREL) printf(" BARREL");
- // if (info.penFlags & PEN_FLAG_INVERTED) printf(" INVERTED");
- // if (info.penFlags & PEN_FLAG_ERASER) printf(" ERASER");
- // printf(" ]\n penMask: %08x ButtonChangeType: %d\n",
- // (unsigned)info.penMask, info.pointerInfo.ButtonChangeType);
- // }
-
- // Event has extended pen data set:
- if (has_position) {
- // Get the position data.
- double s = Fl::screen_driver()->scale(0);
- double ex = info.pointerInfo.ptPixelLocation.x/s;
- double ey = info.pointerInfo.ptPixelLocation.y/s;
- // Go from global coordinates to event window coordinates
- Fl_Widget *p = eventWindow;
- while (p) {
- if (p->as_window()) {
- ex -= p->x();
- ey -= p->y();
- }
- p = p->parent();
- };
- ev.x = ex;
- ev.y = ey;
- ev.rx = info.pointerInfo.ptPixelLocation.x/s;
- ev.ry = info.pointerInfo.ptPixelLocation.y/s;
- if (!is_proximity) {
- // Get the extended data.
- if (info.penMask & PEN_MASK_PRESSURE)
- ev.pressure = info.pressure / 1024.0;
- if (info.penMask & PEN_MASK_TILT_X)
- ev.tilt_x = -info.tiltX / 90.0;
- if (info.penMask & PEN_MASK_TILT_Y)
- ev.tilt_y = -info.tiltY / 90.0;
- if (info.penMask & PEN_MASK_ROTATION)
- ev.twist = info.rotation > 180 ? (info.rotation - 360) : info.rotation;
- if (info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT)
- ev.proximity = 0.0;
- else
- ev.proximity = 1.0;
- }
- if (info.penFlags & PEN_FLAG_INVERTED) {
- device_type_ = _FL_ERASER;
- if (info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT)
- ev.state = State::ERASER_DOWN;
- else
- ev.state = State::ERASER_HOVERS;
- } else {
- device_type_ = _FL_PEN;
- if (info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT)
- ev.state = State::TIP_DOWN;
- else
- ev.state = State::TIP_HOVERS;
- }
- // Add pen barrel button states
- // Note: POINTER_FLAG_FIRSTBUTTON is the pen tip
- // PEN_FLAG_BARREL and POINTER_FLAG_SECONDBUTTON both indicate the primary barrel button
- if ((info.penFlags & PEN_FLAG_BARREL) || (info.pointerInfo.pointerFlags & POINTER_FLAG_SECONDBUTTON))
- ev.state |= State::BUTTON0;
- // Note: the following code does not work very well with the Wayland driver
- // More research is needed to find out how to get these button states reliably.
- if (info.pointerInfo.pointerFlags & POINTER_FLAG_THIRDBUTTON) ev.state |= State::BUTTON1;
- if (info.pointerInfo.pointerFlags & POINTER_FLAG_FOURTHBUTTON) ev.state |= State::BUTTON2;
- if (info.pointerInfo.pointerFlags & POINTER_FLAG_FIFTHBUTTON) ev.state |= State::BUTTON3;
- }
- // printf(" %08x\n", (unsigned)ev.state);
- if (is_proximity) {
- ev.pen_id = GET_POINTERID_WPARAM(msg.wParam);
- }
- if ((msg.message == WM_POINTERENTER) || (msg.message == WM_POINTERLEAVE)) {
- if (msg.message == WM_POINTERENTER) {
- // Check if this is the first time we see this pen, or if the pen changed
- if (current_pen_id_ != ev.pen_id) {
- current_pen_id_ = ev.pen_id;
- auto it = trait_list_.find(current_pen_id_);
- if (it == trait_list_.end()) { // not found, create a new entry
- trait_list_[current_pen_id_] = Trait::DRIVER_AVAILABLE;
- trait_countdown_ = 5;
- pen_send_all(Fl::Pen::DETECTED, State::NONE);
- // printf("IN RANGE, NEW PEN\n");
- } else {
- pen_send_all(Fl::Pen::CHANGED, State::NONE);
- // printf("IN RANGE, CHANGED PEN\n");
- }
- trait_list_[0] = trait_list_[current_pen_id_]; // set current pen traits
- } else {
- pen_send_all(Fl::Pen::IN_RANGE, State::NONE);
- // printf("IN RANGE\n");
- }
- } else {
- pen_send_all(Fl::Pen::OUT_OF_RANGE, State::NONE);
- // printf("OUT OF RANGE\n");
- }
- }
-
- Fl_Widget *receiver = nullptr;
- bool pushed = false;
- bool event_data_copied = false;
-
- if (has_position) {
- if (trait_countdown_) {
- trait_countdown_--;
- if (ev.tilt_x != 0.0) current_pen_trait_ |= Trait::TILT_X;
- if (ev.tilt_y != 0.0) current_pen_trait_ |= Trait::TILT_Y;
- if (ev.pressure != 1.0) current_pen_trait_ |= Trait::PRESSURE;
- if (ev.barrel_pressure != 0.0) current_pen_trait_ |= Trait::BARREL_PRESSURE;
- if (ev.pen_id != 0) current_pen_trait_ |= Trait::PEN_ID;
- if (ev.twist != 0.0) current_pen_trait_ |= Trait::TWIST;
- //if (ev.proximity != 0) current_pen_trait_ |= Trait::PROXIMITY;
- trait_list_[current_pen_id_] = current_pen_trait_;
- }
- fl_xmousewin = eventWindow;
- if (pushed_ && pushed_->widget() && (Fl::pushed() == pushed_->widget())) {
- receiver = pushed_->widget();
- if (Fl::grab() && (Fl::grab() != receiver->top_window()))
- return -1;
- if (Fl::modal() && (Fl::modal() != receiver->top_window()))
- return -1;
- pushed = true;
- } else {
- if (Fl::grab() && (Fl::grab() != eventWindow))
- return -1;
- if (Fl::modal() && (Fl::modal() != eventWindow))
- return -1;
- auto bpen = below_pen_ ? below_pen_->widget() : nullptr;
- auto bmouse = Fl::belowmouse();
- auto bpen_old = bmouse && (bmouse == bpen) ? bpen : nullptr;
- auto bpen_now = find_below_pen(eventWindow, ev.x, ev.y);
-
- if (bpen_now != bpen_old) {
- if (bpen_old) {
- pen_send(bpen_old, Fl::Pen::LEAVE, State::NONE, event_data_copied);
- }
- below_pen_ = nullptr;
- if (bpen_now) {
- State state = (device_type_ == _FL_ERASER) ? State::ERASER_HOVERS : State::TIP_HOVERS;
- if (pen_send(bpen_now, Fl::Pen::ENTER, state, event_data_copied)) {
- below_pen_ = subscriber_list_[bpen_now];
- Fl::belowmouse(bpen_now);
- }
- }
- }
-
- receiver = below_pen_ ? below_pen_->widget() : nullptr;
- if (!receiver)
- return -1;
- }
- } else {
- // Proximity events were handled earlier.
- }
-
- if (!receiver)
- return -1;
-
- if (is_down) {
- if (!pushed) {
- pushed_ = subscriber_list_[receiver];
- Fl::pushed(receiver);
- }
- State trigger = button_to_trigger(info.pointerInfo.ButtonChangeType, true);
- if (msg.message == WM_POINTERDOWN) {
- Fl::e_is_click = 1;
- _e_x_down = (int)ev.x;
- _e_y_down = (int)ev.y;
-
- // Implement click counting using Windows system metrics
- DWORD current_time = GetMessageTime();
- DWORD double_click_time = GetDoubleClickTime();
- int double_click_dx = GetSystemMetrics(SM_CXDOUBLECLK) / 2;
- int double_click_dy = GetSystemMetrics(SM_CYDOUBLECLK) / 2;
-
- // Check if this is a multi-click: same trigger, within time and distance thresholds
- if (trigger == last_click_trigger_ &&
- (current_time - last_click_time_) < double_click_time &&
- abs((int)ev.rx - last_click_x_) < double_click_dx &&
- abs((int)ev.ry - last_click_y_) < double_click_dy) {
- Fl::e_clicks++;
- } else {
- Fl::e_clicks = 0;
- }
-
- last_click_time_ = current_time;
- last_click_x_ = (int)ev.rx;
- last_click_y_ = (int)ev.ry;
- last_click_trigger_ = trigger;
-
- pen_send(receiver, Fl::Pen::TOUCH, trigger, event_data_copied);
- } else {
- pen_send(receiver, Fl::Pen::BUTTON_PUSH, trigger, event_data_copied);
- }
- } else if (is_up) {
- if ( (ev.state & State::ANY_DOWN) == State::NONE ) {
- Fl::pushed(nullptr);
- pushed_ = nullptr;
- }
- State trigger = button_to_trigger(info.pointerInfo.ButtonChangeType, true);
- if (info.pointerInfo.ButtonChangeType == 0)
- pen_send(receiver, Fl::Pen::LIFT, trigger, event_data_copied);
- else
- pen_send(receiver, Fl::Pen::BUTTON_RELEASE, trigger, event_data_copied);
- } else if (is_motion) {
- if ( Fl::e_is_click &&
- ( (fabs((int)ev.x - _e_x_down) > 5) ||
- (fabs((int)ev.y - _e_y_down) > 5) ) )
- Fl::e_is_click = 0;
- if (pushed) {
- pen_send(receiver, Fl::Pen::DRAW, State::NONE, event_data_copied);
- } else {
- pen_send(receiver, Fl::Pen::HOVER, State::NONE, event_data_copied);
- }
- }
- // Always return 0 because at this point, we capture pen events and don't
- // want mouse events anymore!
- return 0;
-}
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
deleted file mode 100644
index 4b74c76cb..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx
+++ /dev/null
@@ -1,518 +0,0 @@
-//
-// Printing support for Windows for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2024 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include "../GDI/Fl_GDI_Graphics_Driver.H"
-#include <FL/Fl_PDF_File_Surface.H>
-#include <FL/Fl_Paged_Device.H>
-#include <FL/Fl_Printer.H>
-#include <FL/Fl_Native_File_Chooser.H>
-#include <FL/fl_ask.H>
-#include <FL/math.h>
-#include <FL/fl_draw.H>
-#include <FL/platform.H> // for fl_win32_xid()
-#include <FL/fl_string_functions.h> // fl_strdup()
-#include <commdlg.h>
-#include <winspool.h> // DocumentProperties(), OpenPrinter(), ClosePrinter()
-
-extern HWND fl_window;
-
-/** Support for printing on the Windows platform */
-class Fl_WinAPI_Printer_Driver : public Fl_Paged_Device {
- friend class Fl_Printer;
-protected:
- int abortPrint;
- PRINTDLG pd;
- HDC hPr;
- int prerr;
- int left_margin;
- int top_margin;
- void absolute_printable_rect(int *x, int *y, int *w, int *h);
- Fl_WinAPI_Printer_Driver(void);
- int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL) FL_OVERRIDE;
- int begin_page (void) FL_OVERRIDE;
- int printable_rect(int *w, int *h) FL_OVERRIDE;
- void margins(int *left, int *top, int *right, int *bottom) FL_OVERRIDE;
- void origin(int *x, int *y) FL_OVERRIDE;
- void origin(int x, int y) FL_OVERRIDE;
- void scale (float scale_x, float scale_y = 0.) FL_OVERRIDE;
- void rotate(float angle) FL_OVERRIDE;
- void translate(int x, int y) FL_OVERRIDE;
- void untranslate(void) FL_OVERRIDE;
- int end_page (void) FL_OVERRIDE;
- void end_job (void) FL_OVERRIDE;
- ~Fl_WinAPI_Printer_Driver(void);
-};
-
-Fl_WinAPI_Printer_Driver::Fl_WinAPI_Printer_Driver(void) : Fl_Paged_Device() {
- hPr = NULL;
- driver(new Fl_GDI_Printer_Graphics_Driver);
-}
-
-Fl_Paged_Device* Fl_Printer::newPrinterDriver(void)
-{
- return new Fl_WinAPI_Printer_Driver();
-}
-
-
-Fl_WinAPI_Printer_Driver::~Fl_WinAPI_Printer_Driver(void) {
- if (hPr) end_job();
- delete driver();
-}
-
-static void WIN_SetupPrinterDeviceContext(HDC prHDC)
-{
- if ( !prHDC ) return;
-
- fl_window = 0;
- SetGraphicsMode(prHDC, GM_ADVANCED); // to allow for rotations
- SetMapMode(prHDC, MM_ANISOTROPIC);
- SetTextAlign(prHDC, TA_BASELINE|TA_LEFT);
- SetBkMode(prHDC, TRANSPARENT);
- // this matches 720 logical units to the number of device units in 10 inches of paper
- // thus the logical unit is the point (= 1/72 inch)
- SetWindowExtEx(prHDC, 720, 720, NULL);
- SetViewportExtEx(prHDC, 10*GetDeviceCaps(prHDC, LOGPIXELSX), 10*GetDeviceCaps(prHDC, LOGPIXELSY), NULL);
-}
-
-
-class Fl_PDF_GDI_File_Surface : public Fl_WinAPI_Printer_Driver
-{
-private:
- static LPSTR pdf_printer_name_;
-public:
- char *doc_fname;
- Fl_PDF_GDI_File_Surface();
- ~Fl_PDF_GDI_File_Surface() { if (doc_fname) free(doc_fname); }
- int begin_job(const char *defaultname,
- char **perr_message = NULL);
- int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use
- int begin_document(const char* outname,
- enum Fl_Paged_Device::Page_Format format,
- enum Fl_Paged_Device::Page_Layout layout,
- char **perr_message);
- void end_job() FL_OVERRIDE;
-};
-
-LPSTR Fl_PDF_GDI_File_Surface::pdf_printer_name_ = _strdup("Microsoft Print to PDF");
-
-Fl_PDF_GDI_File_Surface::Fl_PDF_GDI_File_Surface() {
- driver(new Fl_GDI_Graphics_Driver());
- doc_fname = NULL;
-}
-
-Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) {
- Fl_PDF_GDI_File_Surface *surf = new Fl_PDF_GDI_File_Surface();
- *pfname = (const char**)&surf->doc_fname;
- return surf;
-}
-
-int Fl_PDF_File_Surface::begin_job(const char* defaultfilename,
- char **perr_message) {
- return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message);
-}
-
-int Fl_PDF_File_Surface::begin_document(const char* defaultfilename,
- enum Fl_Paged_Device::Page_Format format,
- enum Fl_Paged_Device::Page_Layout layout,
- char **perr_message) {
- return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message);
-}
-
-
-int Fl_PDF_GDI_File_Surface::begin_job(const char *defaultfname, char **perr_message) {
- int err = 0;
- abortPrint = FALSE;
-
- HANDLE hPr2;
- err = OpenPrinterA(pdf_printer_name_, &hPr2, NULL);
- if (err == 0) {
- if (perr_message) {
- int l = 240;
- *perr_message = new char[l];
- snprintf(*perr_message, l,
- "Class Fl_PDF_File_Surface requires printer '%s' available in Windows 10+.",
- pdf_printer_name_);
- }
- return 1;
- }
- HWND hwndOwner = fl_win32_xid(Fl::first_window());
- LONG count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, NULL, NULL, 0);
- if (count <= 0) { ClosePrinter(hPr2); return 1; }
- char *buffer = new char[count];
- DEVMODEA *pDevMode = (DEVMODEA*)buffer;
- memset(buffer, 0, count);
- pDevMode->dmSize = (WORD)count;
- count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, pDevMode, NULL, DM_OUT_BUFFER | DM_IN_PROMPT);
- ClosePrinter(hPr2);
- if (count == IDCANCEL || count < 0) { delete[] buffer; return 1; }
-
- Fl_Native_File_Chooser fnfc;
- fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
- fnfc.filter("PDF\t*.pdf\n");
- if (defaultfname && strlen(defaultfname) > 0) fnfc.preset_file(defaultfname);
- fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM);
- if (fnfc.show() == 0) this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, pDevMode);
- delete[] buffer;
- if (!this->hPr) return 1;
- DOCINFOW di;
- wchar_t docName [256];
- wchar_t outName [256];
- fl_utf8towc("FLTK", 4, docName, 256);
- fl_utf8towc(fnfc.filename(), (unsigned int)strlen(fnfc.filename()), outName, 256);
- memset(&di, 0, sizeof(DOCINFOW));
- di.cbSize = sizeof(DOCINFOW);
- di.lpszDocName = (LPCWSTR)docName;
- di.lpszOutput = (LPCWSTR)outName;
- err = StartDocW(this->hPr, &di);
- if (err <= 0) {
- DWORD dw = GetLastError();
- DeleteDC(this->hPr);
- this->hPr = NULL;
- if (dw != ERROR_CANCELLED) {
- if (perr_message) {
- int l = 40;
- *perr_message = new char[l];
- snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw);
- }
- return 2;
- }
- return 1;
- }
- x_offset = 0;
- y_offset = 0;
- WIN_SetupPrinterDeviceContext(this->hPr);
- driver()->gc(this->hPr);
- doc_fname = fl_strdup(fnfc.filename());
- return 0;
-}
-
-
-int Fl_PDF_GDI_File_Surface::begin_document(const char* outfname,
- enum Fl_Paged_Device::Page_Format format,
- enum Fl_Paged_Device::Page_Layout layout,
- char **perr_message) {
- int err = 0;
- abortPrint = FALSE;
-
- DEVMODEA inDevMode;
- memset(&inDevMode, 0, sizeof(DEVMODEA)); inDevMode.dmSize = sizeof(DEVMODEA);
- inDevMode.dmOrientation = (layout == PORTRAIT ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
- inDevMode.dmPaperSize = (format == A4 ? DMPAPER_A4 : DMPAPER_LETTER);
- inDevMode.dmFields = DM_ORIENTATION | DM_PAPERSIZE ;
-
- this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, &inDevMode);
- if (!this->hPr) {
- if (perr_message) {
- int l = 150;
- *perr_message = new char[l];
- snprintf(*perr_message, l, "Class Fl_PDF_File_Surface requires printer '%s'.",
- pdf_printer_name_);
- }
- return 2;
- }
- DOCINFOW di;
- wchar_t docName[256];
- wchar_t outName[256];
- fl_utf8towc("FLTK", 4, docName, 256);
- memset(&di, 0, sizeof(DOCINFOW));
- di.cbSize = sizeof(DOCINFOW);
- di.lpszDocName = (LPCWSTR)docName;
- di.lpszOutput = (LPCWSTR)outName;
- fl_utf8towc(outfname, (unsigned int)strlen(outfname), outName, 256);
- err = StartDocW(hPr, &di);
- if (err <= 0) {
- DWORD dw = GetLastError();
- DeleteDC(this->hPr);
- this->hPr = NULL;
- if (perr_message) {
- int l = 50;
- *perr_message = new char[l];
- snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw);
- }
- return 2;
- }
- x_offset = 0;
- y_offset = 0;
- WIN_SetupPrinterDeviceContext(this->hPr);
- driver()->gc(this->hPr);
- doc_fname = fl_strdup(outfname);
- return 0;
-}
-
-
-int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message)
-// returns 0 iff OK
-{
- if (pagecount == 0) pagecount = 10000;
- DOCINFO di;
- char docName [256];
- int err = 0;
-
- abortPrint = FALSE;
- memset (&pd, 0, sizeof (PRINTDLG));
- pd.lStructSize = sizeof (PRINTDLG);
- pd.hwndOwner = GetForegroundWindow();
- pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_NOSELECTION;
- pd.nMinPage = 1;
- pd.nMaxPage = pagecount;
- BOOL b = PrintDlg (&pd);
- if (pd.hwndOwner) { // restore the correct state of mouse buttons and keyboard modifier keys (STR #3221)
- WNDPROC windproc = (WNDPROC)GetWindowLongPtrW(pd.hwndOwner, GWLP_WNDPROC);
- CallWindowProc(windproc, pd.hwndOwner, WM_ACTIVATEAPP, 1, 0);
- }
- if (b != 0) {
- hPr = pd.hDC;
- if (hPr != NULL) {
- strcpy (docName, "FLTK");
- memset(&di, 0, sizeof(DOCINFO));
- di.cbSize = sizeof (DOCINFO);
- di.lpszDocName = (LPCSTR) docName;
- prerr = StartDoc (hPr, &di);
- if (prerr < 1) {
- abortPrint = TRUE;
- DWORD dw = GetLastError();
- err = (dw == ERROR_CANCELLED ? 1 : 2);
- if (perr_message && err == 2) {
- wchar_t *lpMsgBuf;
- DWORD retval = FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- dw,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPWSTR) &lpMsgBuf,
- 0, NULL);
- if (retval) {
- unsigned srclen = lstrlenW(lpMsgBuf);
- while (srclen > 0 && (lpMsgBuf[srclen-1] == '\n' || lpMsgBuf[srclen-1] == '\r')) srclen--;
- unsigned l = fl_utf8fromwc(NULL, 0, lpMsgBuf, srclen);
- *perr_message = new char[l+51];
- snprintf(*perr_message, l+51, "begin_job() failed with error %lu: ", dw);
- fl_utf8fromwc(*perr_message + strlen(*perr_message), l+1, lpMsgBuf, srclen);
- LocalFree(lpMsgBuf);
- }
- }
- }
- }
- } else {
- err = 1;
- }
- if(!err) {
- if((pd.Flags & PD_PAGENUMS) != 0 ) {
- if (frompage) *frompage = pd.nFromPage;
- if (topage) *topage = pd.nToPage;
- }
- else {
- if (frompage) *frompage = 1;
- if (topage) *topage = pagecount;
- }
- x_offset = 0;
- y_offset = 0;
- WIN_SetupPrinterDeviceContext (hPr);
- driver()->gc(hPr);
- }
- return err;
-}
-
-void Fl_PDF_GDI_File_Surface::end_job(void)
-{
- if (hPr != NULL) {
- if (! abortPrint) {
- if (EndDoc (hPr) <= 0) {
- fl_message ("Error in EndDoc() call");
- }
- DeleteDC (hPr);
- }
- hPr = NULL;
- }
-}
-
-void Fl_WinAPI_Printer_Driver::end_job (void)
-{
- if (hPr != NULL) {
- if (! abortPrint) {
- prerr = EndDoc (hPr);
- if (prerr < 0) {
- fl_alert ("EndDoc error %d", prerr);
- }
- }
- DeleteDC (hPr);
- if (pd.hDevMode != NULL) {
- GlobalFree (pd.hDevMode);
- }
- if (pd.hDevNames != NULL) {
- GlobalFree (pd.hDevNames);
- }
- }
- hPr = NULL;
-}
-
-void Fl_WinAPI_Printer_Driver::absolute_printable_rect(int *x, int *y, int *w, int *h)
-{
- POINT physPageSize;
- POINT pixelsPerInch;
- XFORM transform;
-
- if (hPr == NULL) return;
- HDC gc = (HDC)driver()->gc();
- GetWorldTransform(gc, &transform);
- ModifyWorldTransform(gc, NULL, MWT_IDENTITY);
- SetWindowOrgEx(gc, 0, 0, NULL);
-
- physPageSize.x = GetDeviceCaps(hPr, HORZRES);
- physPageSize.y = GetDeviceCaps(hPr, VERTRES);
- DPtoLP(hPr, &physPageSize, 1);
- *w = physPageSize.x + 1;
- *h = physPageSize.y + 1;
- pixelsPerInch.x = GetDeviceCaps(hPr, LOGPIXELSX);
- pixelsPerInch.y = GetDeviceCaps(hPr, LOGPIXELSY);
- DPtoLP(hPr, &pixelsPerInch, 1);
- left_margin = (pixelsPerInch.x / 4);
- *w -= (pixelsPerInch.x / 2);
- top_margin = (pixelsPerInch.y / 4);
- *h -= (pixelsPerInch.y / 2);
-
- *x = left_margin;
- *y = top_margin;
- origin(x_offset, y_offset);
- SetWorldTransform(gc, &transform);
-}
-
-void Fl_WinAPI_Printer_Driver::margins(int *left, int *top, int *right, int *bottom)
-{
- int x = 0, y = 0, w = 0, h = 0;
- absolute_printable_rect(&x, &y, &w, &h);
- if (left) *left = x;
- if (top) *top = y;
- if (right) *right = x;
- if (bottom) *bottom = y;
-}
-
-int Fl_WinAPI_Printer_Driver::printable_rect(int *w, int *h)
-{
- int x, y;
- absolute_printable_rect(&x, &y, w, h);
- return 0;
-}
-
-int Fl_WinAPI_Printer_Driver::begin_page (void)
-{
- int rsult, w, h;
-
- rsult = 0;
- if (hPr != NULL) {
- Fl_Surface_Device::push_current(this);
- WIN_SetupPrinterDeviceContext (hPr);
- prerr = StartPage (hPr);
- if (prerr < 0) {
- Fl_Surface_Device::pop_current();
- fl_alert ("StartPage error %d", prerr);
- rsult = 1;
- }
- printable_rect(&w, &h);
- origin(0, 0);
- fl_clip_region(0);
- }
- return rsult;
-}
-
-void Fl_WinAPI_Printer_Driver::origin (int deltax, int deltay)
-{
- SetWindowOrgEx( (HDC)driver()->gc(), - left_margin - deltax, - top_margin - deltay, NULL);
- x_offset = deltax;
- y_offset = deltay;
-}
-
-void Fl_WinAPI_Printer_Driver::scale (float scalex, float scaley)
-{
- if (scaley == 0.) scaley = scalex;
- int w, h;
- SetWindowExtEx((HDC)driver()->gc(), (int)(720 / scalex + 0.5), (int)(720 / scaley + 0.5), NULL);
- printable_rect(&w, &h);
- origin(0, 0);
-}
-
-void Fl_WinAPI_Printer_Driver::rotate (float rot_angle)
-{
- XFORM mat;
- float angle;
- angle = (float) - (rot_angle * M_PI / 180.);
- mat.eM11 = (float)cos(angle);
- mat.eM12 = (float)sin(angle);
- mat.eM21 = - mat.eM12;
- mat.eM22 = mat.eM11;
- mat.eDx = mat.eDy = 0;
- SetWorldTransform((HDC)driver()->gc(), &mat);
-}
-
-int Fl_WinAPI_Printer_Driver::end_page (void)
-{
- int rsult;
-
- rsult = 0;
- if (hPr != NULL) {
- Fl_Surface_Device::pop_current();
- prerr = EndPage (hPr);
- if (prerr < 0) {
- abortPrint = TRUE;
- fl_alert ("EndPage error %d", prerr);
- rsult = 1;
- }
- else { // make sure rotation is not transferred to next page
- ModifyWorldTransform(hPr, NULL, MWT_IDENTITY);
- }
- }
- return rsult;
-}
-
-static int translate_stack_depth = 0;
-const int translate_stack_max = 5;
-static int translate_stack_x[translate_stack_max];
-static int translate_stack_y[translate_stack_max];
-
-static void do_translate(int x, int y, HDC gc)
-{
- XFORM tr;
- tr.eM11 = tr.eM22 = 1;
- tr.eM12 = tr.eM21 = 0;
- tr.eDx = (FLOAT) x;
- tr.eDy = (FLOAT) y;
- ModifyWorldTransform(gc, &tr, MWT_LEFTMULTIPLY);
-}
-
-void Fl_WinAPI_Printer_Driver::translate (int x, int y)
-{
- do_translate(x, y, (HDC)driver()->gc());
- if (translate_stack_depth < translate_stack_max) {
- translate_stack_x[translate_stack_depth] = x;
- translate_stack_y[translate_stack_depth] = y;
- translate_stack_depth++;
- }
-}
-
-void Fl_WinAPI_Printer_Driver::untranslate (void)
-{
- if (translate_stack_depth > 0) {
- translate_stack_depth--;
- do_translate( - translate_stack_x[translate_stack_depth], - translate_stack_y[translate_stack_depth], (HDC)driver()->gc() );
- }
-}
-
-void Fl_WinAPI_Printer_Driver::origin(int *x, int *y)
-{
- Fl_Paged_Device::origin(x, y);
-}
-
-
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
deleted file mode 100644
index b038fc5f1..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
+++ /dev/null
@@ -1,104 +0,0 @@
-//
-// Windows screen interface for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_WinAPI_Screen_Driver.H
- \brief Definition of Windows screen interface.
- */
-
-#ifndef FL_WINAPI_SCREEN_DRIVER_H
-#define FL_WINAPI_SCREEN_DRIVER_H
-
-#include "../../Fl_Screen_Driver.H"
-#include <windows.h>
-
-class Fl_Window;
-
-
-class Fl_WinAPI_Screen_Driver : public Fl_Screen_Driver
-{
-protected:
- RECT screens[MAX_SCREENS];
- RECT work_area[MAX_SCREENS];
- float scale_of_screen[MAX_SCREENS];
-
- static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM);
- BOOL screen_cb(HMONITOR mon, HDC, LPRECT r);
- int get_mouse_unscaled(int &mx, int &my);
-
-public:
- float dpi[MAX_SCREENS][2];
- enum APP_SCALING_CAPABILITY scaling_capability;
- void update_scaling_capability();
- Fl_WinAPI_Screen_Driver();
- // --- display management
- int visual(int flags) FL_OVERRIDE;
- // --- screen configuration
- void init() FL_OVERRIDE;
- int x() FL_OVERRIDE;
- int y() FL_OVERRIDE;
- int w() FL_OVERRIDE;
- int h() FL_OVERRIDE;
- void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE;
- void screen_xywh_unscaled(int &X, int &Y, int &W, int &H, int n);
- void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE;
- int screen_num_unscaled(int x, int y);
- void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE;
- // --- audible output
- void beep(int type) FL_OVERRIDE;
- // --- global events
- void flush() FL_OVERRIDE;
- void grab(Fl_Window* win) FL_OVERRIDE;
- // --- global colors
- void get_system_colors() FL_OVERRIDE;
- int dnd(int unused) FL_OVERRIDE;
- int compose(int &del) FL_OVERRIDE;
- Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE;
- Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win);
- int get_mouse(int &x, int &y) FL_OVERRIDE;
- void enable_im() FL_OVERRIDE;
- void disable_im() FL_OVERRIDE;
- void open_display_platform() FL_OVERRIDE;
- void offscreen_size(Fl_Offscreen off, int &width, int &height) FL_OVERRIDE;
- APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE {
- return scaling_capability;
- }
- float scale(int n) FL_OVERRIDE {
- return scale_of_screen[n];
- }
- void scale(int n, float f) FL_OVERRIDE {
- scale_of_screen[n] = f;
- }
- void desktop_scale_factor() FL_OVERRIDE;
- void default_icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE;
- // this one is implemented in Fl_win32.cxx
- void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE;
- // this one is implemented in Fl_win32.cxx
- void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE;
- // this one is implemented in Fl_win32.cxx
- int clipboard_contains(const char *type) FL_OVERRIDE;
- // this one is implemented in Fl_win32.cxx
- void clipboard_notify_change() FL_OVERRIDE;
- // this one is implemented in Fl_win32.cxx
- void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) FL_OVERRIDE;
- // these two are implemented in Fl_get_key_win32.cxx
- int event_key(int) FL_OVERRIDE;
- int get_key(int) FL_OVERRIDE;
- float base_scale(int numscreen) FL_OVERRIDE;
-};
-
-
-#endif // FL_WINAPI_SCREEN_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
deleted file mode 100644
index b1ddc9f91..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ /dev/null
@@ -1,493 +0,0 @@
-//
-// Windows screen interface for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include "Fl_WinAPI_Screen_Driver.H"
-#include "../GDI/Fl_Font.H"
-#include <FL/Fl.H>
-#include <FL/platform.H>
-#include <FL/Fl_RGB_Image.H>
-#include <FL/fl_ask.H>
-#include <stdio.h>
-
-
-// these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx
-extern const char *fl_fg;
-extern const char *fl_bg;
-extern const char *fl_bg2;
-// end of extern additions workaround
-
-
-#if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500)
-# define COMPILE_MULTIMON_STUBS
-# include <multimon.h>
-#endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500
-
-static Fl_Text_Editor::Key_Binding extra_bindings[] = {
- // Define Windows specific accelerators...
- { 'y', FL_CTRL, Fl_Text_Editor::kf_redo ,0},
- { 0, 0, 0 ,0}
-};
-
-
-Fl_WinAPI_Screen_Driver::Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
- text_editor_extra_key_bindings = extra_bindings;
- for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1;
- scaling_capability = SYSTEMWIDE_APP_SCALING;
-}
-
-int Fl_WinAPI_Screen_Driver::visual(int flags)
-{
- fl_GetDC(0);
- if (flags & FL_DOUBLE) return 0;
- HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc();
- if (!(flags & FL_INDEX) &&
- GetDeviceCaps(gc,BITSPIXEL) <= 8) return 0;
- if ((flags & FL_RGB8) && GetDeviceCaps(gc,BITSPIXEL)<24) return 0;
- return 1;
-}
-
-
-// We go the much more difficult route of individually picking some multi-screen
-// functions from the USER32.DLL . If these functions are not available, we
-// will gracefully fall back to single monitor support.
-//
-// If we were to insist on the existence of "EnumDisplayMonitors" and
-// "GetMonitorInfoA", it would be impossible to use FLTK on Windows 2000
-// before SP2 or earlier.
-
-// BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM)
-typedef BOOL(WINAPI* fl_edm_func)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
-// BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO)
-typedef BOOL(WINAPI* fl_gmi_func)(HMONITOR, LPMONITORINFO);
-
-static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA
-
-
-BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC hdc, LPRECT r, LPARAM d)
-{
- Fl_WinAPI_Screen_Driver *drv = (Fl_WinAPI_Screen_Driver*)d;
- return drv->screen_cb(mon, hdc, r);
-}
-
-
-BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC, LPRECT r)
-{
- if (num_screens >= MAX_SCREENS) return TRUE;
-
- MONITORINFOEX mi;
- mi.cbSize = sizeof(mi);
-
- // GetMonitorInfo(mon, &mi);
- // (but we use our self-acquired function pointer instead)
- if (fl_gmi(mon, &mi)) {
- screens[num_screens] = mi.rcMonitor;
- // If we also want to record the work area, we would also store mi.rcWork at this point
- work_area[num_screens] = mi.rcWork;
- num_screens++;
- }
- return TRUE;
-}
-
-
-void Fl_WinAPI_Screen_Driver::init()
-{
- open_display();
- // Since not all versions of Windows include multiple monitor support,
- // we do a run-time check for the required functions...
- HMODULE hMod = GetModuleHandle("USER32.DLL");
-
- if (hMod) {
- // check that EnumDisplayMonitors is available
- fl_edm_func fl_edm = (fl_edm_func)GetProcAddress(hMod, "EnumDisplayMonitors");
-
- if (fl_edm) {
- // we have EnumDisplayMonitors - do we also have GetMonitorInfoA ?
- fl_gmi = (fl_gmi_func)GetProcAddress(hMod, "GetMonitorInfoA");
- if (fl_gmi) {
- // We have GetMonitorInfoA, enumerate all the screens...
- // EnumDisplayMonitors(0,0,screen_cb,0);
- // (but we use our self-acquired function pointer instead)
- // NOTE: num_screens is incremented in screen_cb so we must first reset it here...
- num_screens = 0;
- fl_edm(0, 0, screen_cb, (LPARAM)this);
- return;
- }
- }
- }
-
- // If we get here, assume we have 1 monitor...
- num_screens = 1;
- screens[0].top = 0;
- screens[0].left = 0;
- screens[0].right = GetSystemMetrics(SM_CXSCREEN);
- screens[0].bottom = GetSystemMetrics(SM_CYSCREEN);
- work_area[0] = screens[0];
-}
-
-
-void Fl_WinAPI_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n)
-{
- if (num_screens < 0) init();
- if (n < 0 || n >= num_screens) n = 0;
- X = int(work_area[n].left/scale_of_screen[n]);
- Y = int(work_area[n].top/scale_of_screen[n]);
- W = int((work_area[n].right - work_area[n].left)/scale_of_screen[n]);
- H = int((work_area[n].bottom - work_area[n].top)/scale_of_screen[n]);
-}
-
-
-void Fl_WinAPI_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n)
-{
- if (num_screens < 0) init();
-
- if ((n < 0) || (n >= num_screens))
- n = 0;
-
- if (num_screens > 0) {
- X = int(screens[n].left/scale_of_screen[n]);
- Y = int(screens[n].top/scale_of_screen[n]);
- W = int((screens[n].right - screens[n].left)/scale_of_screen[n]);
- H = int((screens[n].bottom - screens[n].top)/scale_of_screen[n]);
- } else {
- /* Fallback if something is broken... */
- X = 0;
- Y = 0;
- W = GetSystemMetrics(SM_CXSCREEN);
- H = GetSystemMetrics(SM_CYSCREEN);
- }
-}
-
-
-void Fl_WinAPI_Screen_Driver::screen_xywh_unscaled(int &X, int &Y, int &W, int &H, int n) {
- if (num_screens < 0) init();
- if ((n < 0) || (n >= num_screens)) n = 0;
- X = screens[n].left;
- Y = screens[n].top;
- W = screens[n].right - screens[n].left;
- H = screens[n].bottom - screens[n].top;
-};
-
-
-void Fl_WinAPI_Screen_Driver::screen_dpi(float &h, float &v, int n)
-{
- if (num_screens < 0) init();
- h = v = 0.0f;
- if (n >= 0 && n < num_screens) {
- h = float(dpi[n][0]);
- v = float(dpi[n][1]);
- }
-}
-
-
-int Fl_WinAPI_Screen_Driver::x()
-{
- /*RECT r;
-
- SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
- return r.left;*/
- int X, Y, W, H;
- screen_work_area(X, Y, W, H, 0);
- return X;
-}
-
-
-int Fl_WinAPI_Screen_Driver::y()
-{
- /*RECT r;
-
- SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
- return r.top;*/
- int X, Y, W, H;
- screen_work_area(X, Y, W, H, 0);
- return Y;
-}
-
-
-int Fl_WinAPI_Screen_Driver::h()
-{
- /*RECT r;
-
- SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
- return r.bottom - r.top;*/
- int X, Y, W, H;
- screen_work_area(X, Y, W, H, 0);
- return H;
-}
-
-
-int Fl_WinAPI_Screen_Driver::w()
-{
- /*RECT r;
-
- SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
- return r.right - r.left;*/
- int X, Y, W, H;
- screen_work_area(X, Y, W, H, 0);
- return W;
-}
-
-
-// Implements fl_beep(). See documentation in src/fl_ask.cxx.
-void Fl_WinAPI_Screen_Driver::beep(int type)
-{
- switch (type) {
- case FL_BEEP_QUESTION :
- case FL_BEEP_PASSWORD :
- MessageBeep(MB_ICONQUESTION);
- break;
- case FL_BEEP_MESSAGE :
- MessageBeep(MB_ICONASTERISK);
- break;
- case FL_BEEP_NOTIFICATION :
- MessageBeep(MB_ICONASTERISK);
- break;
- case FL_BEEP_ERROR :
- MessageBeep(MB_ICONERROR);
- break;
- default :
- MessageBeep(0xFFFFFFFF);
- break;
- }
-}
-
-
-void Fl_WinAPI_Screen_Driver::flush()
-{
- GdiFlush();
-}
-
-
-extern void fl_fix_focus(); // in Fl.cxx
-
-// We have to keep track of whether we have captured the mouse, since
-// Windows shows little respect for this... Grep for fl_capture to
-// see where and how this is used.
-extern HWND fl_capture;
-
-
-void Fl_WinAPI_Screen_Driver::grab(Fl_Window* win)
-{
- if (win) {
- if (!Fl::grab_) {
- SetActiveWindow(fl_capture = fl_xid(Fl::first_window()));
- SetCapture(fl_capture);
- }
- Fl::grab_ = win;
- } else {
- if (Fl::grab_) {
- fl_capture = 0;
- ReleaseCapture();
- Fl::grab_ = 0;
- fl_fix_focus();
- }
- }
-}
-
-
-static void set_selection_color(uchar r, uchar g, uchar b)
-{
- Fl::set_color(FL_SELECTION_COLOR,r,g,b);
-}
-
-
-static void getsyscolor(int what, const char* arg, void (*func)(uchar,uchar,uchar))
-{
- if (arg) {
- uchar r,g,b;
- if (!fl_parse_color(arg, r,g,b))
- Fl::error("Unknown color: %s", arg);
- else
- func(r,g,b);
- } else {
- DWORD x = GetSysColor(what);
- func(uchar(x&255), uchar(x>>8), uchar(x>>16));
- }
-}
-
-
-void Fl_WinAPI_Screen_Driver::get_system_colors()
-{
- if (!bg2_set) getsyscolor(COLOR_WINDOW, fl_bg2,Fl::background2);
- if (!fg_set) getsyscolor(COLOR_WINDOWTEXT, fl_fg, Fl::foreground);
- if (!bg_set) getsyscolor(COLOR_BTNFACE, fl_bg, Fl::background);
- getsyscolor(COLOR_HIGHLIGHT, 0, set_selection_color);
-}
-
-
-int Fl_WinAPI_Screen_Driver::compose(int &del) {
- unsigned char ascii = (unsigned char)Fl::e_text[0];
- /* WARNING: The [AltGr] key on international keyboards sets FL_CTRL.
- 2nd line in condition below asks [AltGr] key (a.k.a. VK_RMENU) not to be down.
- */
- int condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) &&
- !( (Fl::e_state & FL_CTRL) && (GetAsyncKeyState(VK_RMENU) >> 15) );
- if (condition) { // this stuff is to be treated as a function key
- del = 0;
- return 0;
- }
- del = Fl::compose_state;
- Fl::compose_state = 0;
- // Only insert non-control characters:
- if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) {
- return 0;
- }
- return 1;
-}
-
-
-Fl_RGB_Image * // O - image or NULL if failed
-Fl_WinAPI_Screen_Driver::read_win_rectangle(
- int X, // I - Left position
- int Y, // I - Top position
- int w, // I - Width of area to read
- int h, // I - Height of area to read
- Fl_Window *win, // I - window to capture from or NULL to capture from current offscreen
- bool may_capture_subwins, bool *did_capture_subwins)
-{
- float s = Fl_Surface_Device::surface()->driver()->scale();
- int ws, hs;
- if (int(s) == s) { ws = w * int(s); hs = h * int(s);}
- else {
- ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Fl_Scalable_Graphics_Driver::floor(X, s),
- hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Fl_Scalable_Graphics_Driver::floor(Y, s);
- if (ws < 1) ws = 1;
- if (hs < 1) hs = 1;
- }
- return read_win_rectangle_unscaled(Fl_Scalable_Graphics_Driver::floor(X, s), Fl_Scalable_Graphics_Driver::floor(Y, s), ws, hs, win);
-}
-
-Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win)
-{
- // Depth of image is always 3 here
-
- // Grab all of the pixels in the image...
-
- // Assure that we are not trying to read non-existing data. If it is so, the
- // function should still work, but the out-of-bounds part of the image is
- // untouched (initialized with the alpha value or 0 (black), resp.).
-
- int ww = w; // We need the original width for output data line size
-
- int shift_x = 0; // X target shift if X modified
- int shift_y = 0; // Y target shift if X modified
-
- if (X < 0) {
- shift_x = -X;
- w += X;
- X = 0;
- }
- if (Y < 0) {
- shift_y = -Y;
- h += Y;
- Y = 0;
- }
-
- if (h < 1 || w < 1) return 0; // nothing to copy
-
- // Allocate and initialize the image data array
- size_t arraySize = ((size_t)w * h) * 3;
- uchar *p = new uchar[arraySize];
- memset(p, 0, arraySize);
-
- int line_size = ((3*w+3)/4) * 4; // each line is aligned on a DWORD (4 bytes)
- uchar *dib = new uchar[line_size*h]; // create temporary buffer to read DIB
-
- // fill in bitmap info for GetDIBits
-
- BITMAPINFO bi;
- bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bi.bmiHeader.biWidth = w;
- bi.bmiHeader.biHeight = -h; // negative => top-down DIB
- bi.bmiHeader.biPlanes = 1;
- bi.bmiHeader.biBitCount = 24; // 24 bits RGB
- bi.bmiHeader.biCompression = BI_RGB;
- bi.bmiHeader.biSizeImage = 0;
- bi.bmiHeader.biXPelsPerMeter = 0;
- bi.bmiHeader.biYPelsPerMeter = 0;
- bi.bmiHeader.biClrUsed = 0;
- bi.bmiHeader.biClrImportant = 0;
-
- // copy bitmap from original DC (Window, Fl_Offscreen, ...)
- if (win && Fl_Window::current() != win) win->make_current();
- HDC gc = (HDC)fl_graphics_driver->gc();
- HDC hdc = CreateCompatibleDC(gc);
- HBITMAP hbm = CreateCompatibleBitmap(gc,w,h);
-
- int save_dc = SaveDC(hdc); // save context for cleanup
- SelectObject(hdc,hbm); // select bitmap
- BitBlt(hdc,0,0,w,h,gc,X,Y,SRCCOPY); // copy image section to DDB
-
- // copy RGB image data to the allocated DIB
-
- GetDIBits(hdc, hbm, 0, h, dib, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
-
- // finally copy the image data to the user buffer
-
- for (int j = 0; j<h; j++) {
- const uchar *src = dib + j * line_size; // source line
- uchar *tg = p + (j + shift_y) * 3 * ww + shift_x * 3; // target line
- for (int i = 0; i<w; i++) {
- uchar b = *src++;
- uchar g = *src++;
- *tg++ = *src++; // R
- *tg++ = g; // G
- *tg++ = b; // B
- }
- }
-
- // free used GDI and other structures
-
- RestoreDC(hdc,save_dc); // reset DC
- DeleteDC(hdc);
- DeleteObject(hbm);
- delete[] dib; // delete DIB temporary buffer
-
- Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, 3);
- rgb->alloc_array = 1;
- return rgb;
-}
-
-
-void Fl_WinAPI_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
-{
- BITMAP bitmap;
- if ( GetObject((HBITMAP)off, sizeof(BITMAP), &bitmap) ) {
- width = bitmap.bmWidth;
- height = bitmap.bmHeight;
- }
-}
-
-//NOTICE: returns -1 if x,y is not in any screen
-int Fl_WinAPI_Screen_Driver::screen_num_unscaled(int x, int y)
-{
- int screen = -1;
- if (num_screens < 0) init();
- for (int i = 0; i < num_screens; i ++) {
- if (x >= screens[i].left && x < screens[i].right &&
- y >= screens[i].top && y < screens[i].bottom) {
- screen = i;
- break;
- }
- }
- return screen;
-}
-
-
-float Fl_WinAPI_Screen_Driver::base_scale(int numscreen) {
- return float(dpi[numscreen][0] / 96.);
-}
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
deleted file mode 100644
index 016cad9fa..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
+++ /dev/null
@@ -1,124 +0,0 @@
-//
-// Windows system driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_WinAPI_System_Driver.H
- \brief Definition of Windows system driver.
- */
-
-#ifndef FL_WINAPI_SYSTEM_DRIVER_H
-#define FL_WINAPI_SYSTEM_DRIVER_H
-
-#include "../../Fl_System_Driver.H"
-#include <stdarg.h>
-#include <string.h> // strdup
-
-/*
- Move everything here that manages the system interface.
-
- There is exactly one system driver.
-
- - filename and pathname management
- - directory and file access
- - system time and system timer
- - multithreading
- - string management
- */
-
-class Fl_WinAPI_System_Driver : public Fl_System_Driver
-{
-public:
- void warning(const char *format, va_list args) FL_OVERRIDE;
- void error(const char *format, va_list args) FL_OVERRIDE;
- void fatal(const char *format, va_list args) FL_OVERRIDE;
- char *utf2mbcs(const char *s) FL_OVERRIDE;
- char *getenv(const char *var) FL_OVERRIDE;
- int putenv(const char *var) FL_OVERRIDE;
- int open(const char *fnam, int oflags, int pmode) FL_OVERRIDE;
- int open_ext(const char *fnam, int binary, int oflags, int pmode) FL_OVERRIDE;
- FILE *fopen(const char *fnam, const char *mode) FL_OVERRIDE;
- int system(const char *cmd) FL_OVERRIDE;
- int execvp(const char *file, char *const *argv) FL_OVERRIDE;
- int chmod(const char *fnam, int mode) FL_OVERRIDE;
- int access(const char *fnam, int mode) FL_OVERRIDE;
- int flstat(const char *fnam, struct stat *b) FL_OVERRIDE;
- char *getcwd(char *b, int l) FL_OVERRIDE;
- int chdir(const char *path) FL_OVERRIDE;
- int unlink(const char *fnam) FL_OVERRIDE;
- int mkdir(const char *fnam, int mode) FL_OVERRIDE;
- int rmdir(const char *fnam) FL_OVERRIDE;
- int rename(const char *fnam, const char *newnam) FL_OVERRIDE;
- // Windows commandline argument conversion to UTF-8
- int args_to_utf8(int argc, char ** &argv) FL_OVERRIDE;
- // Windows specific UTF-8 conversions
- unsigned utf8towc(const char *src, unsigned srclen, wchar_t* dst, unsigned dstlen) FL_OVERRIDE;
- unsigned utf8fromwc(char *dst, unsigned dstlen, const wchar_t* src, unsigned srclen) FL_OVERRIDE;
- int utf8locale() FL_OVERRIDE;
- unsigned utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) FL_OVERRIDE;
- unsigned utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) FL_OVERRIDE;
-
- int clocale_vprintf(FILE *output, const char *format, va_list args) FL_OVERRIDE;
- int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) FL_OVERRIDE;
- int clocale_vsscanf(const char *input, const char *format, va_list args) FL_OVERRIDE;
- int filename_list(const char *d, dirent ***list,
- int (*sort)(struct dirent **, struct dirent **),
- char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE;
- int filename_expand(char *to,int tolen, const char *from) FL_OVERRIDE;
- int filename_relative(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE;
- int filename_absolute(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE;
- int filename_isdir(const char *n) FL_OVERRIDE;
- int filename_isdir_quick(const char *n) FL_OVERRIDE;
- const char *filename_ext(const char *buf) FL_OVERRIDE;
- int open_uri(const char *uri, char *msg, int msglen) FL_OVERRIDE;
- int use_recent_tooltip_fix() FL_OVERRIDE {return 1;}
- int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) FL_OVERRIDE;
- int file_browser_load_directory(const char *directory, char *filename, size_t name_size,
- dirent ***pfiles, Fl_File_Sort_F *sort,
- char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE;
- void newUUID(char *uuidBuffer) FL_OVERRIDE;
- char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
- const char *application) FL_OVERRIDE;
- void *load(const char *filename) FL_OVERRIDE;
- void png_extra_rgba_processing(unsigned char *array, int w, int h) FL_OVERRIDE;
- const char *next_dir_sep(const char *start) FL_OVERRIDE;
- // these 3 are implemented in Fl_lock.cxx
- void awake(void*) FL_OVERRIDE;
- int lock() FL_OVERRIDE;
- void unlock() FL_OVERRIDE;
- // this one is implemented in Fl_win32.cxx
- void* thread_message() FL_OVERRIDE;
- int file_type(const char *filename) FL_OVERRIDE;
- const char *home_directory_name() FL_OVERRIDE;
- const char *filesystems_label() FL_OVERRIDE { return "My Computer"; }
- int backslash_as_slash() FL_OVERRIDE {return 1;}
- int colon_is_drive() FL_OVERRIDE {return 1;}
- int case_insensitive_filenames() FL_OVERRIDE {return 1;}
- // this one is implemented in Fl_win32.cxx
- const char *filename_name(const char *buf) FL_OVERRIDE;
- void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE;
- void add_fd(int fd, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE;
- void remove_fd(int, int when) FL_OVERRIDE;
- void remove_fd(int) FL_OVERRIDE;
- void gettime(time_t *sec, int *usec) FL_OVERRIDE;
- char* strdup(const char *s) FL_OVERRIDE { return ::_strdup(s); }
- void lock_ring() FL_OVERRIDE;
- void unlock_ring() FL_OVERRIDE;
- double wait(double time_to_wait) FL_OVERRIDE;
- int ready() FL_OVERRIDE;
- int close_fd(int fd) FL_OVERRIDE;
-};
-
-#endif // FL_WINAPI_SYSTEM_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
deleted file mode 100644
index 9eab455df..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
+++ /dev/null
@@ -1,1134 +0,0 @@
-//
-// Definition of Windows system driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2025 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-#include <config.h>
-#include <FL/platform.H>
-#include "Fl_WinAPI_System_Driver.H"
-#include <FL/Fl.H>
-#include <FL/fl_utf8.h>
-#include <FL/filename.H>
-#include <FL/Fl_File_Browser.H>
-#include <FL/Fl_File_Icon.H>
-#include "../../flstring.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <windows.h>
-#include <rpc.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/timeb.h>
-#include <shellapi.h>
-#include <wchar.h>
-#include <process.h>
-#include <locale.h>
-#include <time.h>
-#include <direct.h>
-#include <io.h>
-#include <fcntl.h>
-#include <string>
-
-// We must define _WIN32_IE at least to 0x0500 before inclusion of 'shlobj.h' to enable
-// the declaration of SHGFP_TYPE_CURRENT for some older versions of MinGW, notably
-// header versions 5.3.0 and earlier, whereas 5.4.2 seems to define _WIN32_IE as needed.
-#if !(defined _WIN32_IE) || (_WIN32_IE < 0x0500)
-# undef _WIN32_IE
-# define _WIN32_IE 0x0500
-#endif /* _WIN32_WINNT checks */
-
-#include <shlobj.h>
-
-// function pointer for the UuidCreate Function
-// RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid);
-typedef RPC_STATUS (WINAPI *uuid_func)(UUID __RPC_FAR *Uuid);
-
-// Apparently Borland C++ defines DIRECTORY in <direct.h>, which
-// interferes with the Fl_File_Icon enumeration of the same name.
-# ifdef DIRECTORY
-# undef DIRECTORY
-# endif // DIRECTORY
-
-#ifdef __CYGWIN__
-# include <mntent.h>
-#endif
-
-// Optional helper function to debug Fl_WinAPI_System_Driver::home_directory_name()
-#ifndef DEBUG_HOME_DIRECTORY_NAME
-#define DEBUG_HOME_DIRECTORY_NAME 0
-#endif
-#if DEBUG_HOME_DIRECTORY_NAME
-static void print_env(const char *ev) {
- const char *val = getenv(ev);
- printf("%-30.30s = \"%s\"\n", ev, val ? val : "<null>");
- fflush(stdout);
-}
-#endif // DEBUG_HOME_DIRECTORY_NAME
-
-static inline int isdirsep(char c) { return c == '/' || c == '\\'; }
-
-static wchar_t *mbwbuf = NULL;
-static wchar_t *wbuf = NULL;
-static wchar_t *wbuf1 = NULL;
-
-extern "C" {
- int fl_scandir(const char *dirname, struct dirent ***namelist,
- int (*select)(struct dirent *),
- int (*compar)(struct dirent **, struct dirent **),
- char *errmsg, int errmsg_len);
-}
-
-/*
- Convert UTF-8 string to Windows wide character encoding (UTF-16).
-
- This helper function is used throughout this file to convert UTF-8
- strings to Windows specific UTF-16 encoding for filenames, paths, or
- other strings to be used by system functions.
-
- The input string can be a null-terminated string or its length can be
- provided by the optional argument 'lg'. If 'lg' is omitted or less than 0
- (default = -1) the string length is determined with strlen(), otherwise
- 'lg' takes precedence. Zero (0) is a valid string length (an empty string).
-
- The argument 'wbuf' must have been initialized with NULL or a previous
- call to malloc() or realloc().
-
- If the converted string doesn't fit into the allocated size of 'wbuf' or if
- 'wbuf' is NULL a new buffer is allocated with realloc(). Hence the pointer
- 'wbuf' can be shared among multiple calls to this function if it has been
- initialized with NULL (or malloc or realloc) before the first call.
-
- The return value is either the old value of 'wbuf' (if the string fits)
- or a pointer to the (re)allocated buffer.
-
- Pseudo doxygen docs (static function intentionally not documented):
-
- param[in] utf8 input string (UTF-8)
- param[in,out] wbuf in: pointer to output string buffer or NULL
- out: new string (the pointer may be changed)
- param[in] lg optional: input string length (default = -1)
-
- returns pointer to string buffer
-*/
-static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) {
- unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8);
- unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length
- wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn);
- wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string
- wbuf[wn] = 0;
- return wbuf;
-}
-
-/*
- Convert a Windows wide character (UTF-16) string to UTF-8 encoding.
-
- This helper function is used throughout this file to convert Windows
- wide character strings as returned by system functions to UTF-8
- encoding for internal usage.
-
- The argument 'utf8' must have been initialized with NULL or a previous
- call to malloc() or realloc().
-
- If the converted string doesn't fit into the allocated size of 'utf8' or if
- 'utf8' is NULL a new buffer is allocated with realloc(). Hence the pointer
- 'utf8' can be shared among multiple calls to this function if it has been
- initialized with NULL (or malloc or realloc) before the first call.
- Ideally every call to this function has its own static pointer though.
-
- The return value is either the old value of 'utf8' (if the string fits)
- or a pointer at the (re)allocated buffer.
-
- Pseudo doxygen docs (static function intentionally not documented):
-
- param[in] wstr input string (wide character, UTF-16)
- param[in,out] utf8 in: pointer to output string buffer
- out: new string (pointer may be changed)
-
- returns pointer to string buffer
-*/
-static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) {
- unsigned len = (unsigned)wcslen(wstr);
- unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length
- utf8 = (char *)realloc(utf8, wn);
- wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string
- utf8[wn] = 0;
- return utf8;
-}
-
-void Fl_WinAPI_System_Driver::warning(const char *format, va_list args) {
- // Show nothing for warnings under Windows...
-}
-
-void Fl_WinAPI_System_Driver::error(const char *format, va_list args) {
- char buf[1024];
- vsnprintf(buf, 1024, format, args);
- MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
-}
-
-void Fl_WinAPI_System_Driver::fatal(const char *format, va_list args) {
- char buf[1024];
- vsnprintf(buf, 1024, format, args);
- MessageBox(0, buf, "Error", MB_ICONSTOP | MB_SYSTEMMODAL);
- ::exit(1);
-}
-
-char *Fl_WinAPI_System_Driver::utf2mbcs(const char *utf8) {
- static char *buf = NULL;
- if (!utf8) return NULL;
-
- unsigned len = (unsigned)strlen(utf8);
-
- unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 7; // Query length
- mbwbuf = (wchar_t *)realloc(mbwbuf, sizeof(wchar_t) * wn);
- len = fl_utf8toUtf16(utf8, len, (unsigned short *)mbwbuf, wn); // Convert string
- mbwbuf[len] = 0;
-
- buf = (char*)realloc(buf, len * 6 + 2);
- len = (unsigned)wcstombs(buf, mbwbuf, len * 6);
- buf[len] = 0;
- buf[len+1] = 0; // in case the result is a UTF-16 string
- return buf;
-}
-
-char *Fl_WinAPI_System_Driver::getenv(const char *var) {
- static char *buf = NULL;
- wchar_t *ret = _wgetenv(utf8_to_wchar(var, wbuf));
- if (!ret) return NULL;
- return wchar_to_utf8(ret, buf);
-}
-
-int Fl_WinAPI_System_Driver::putenv(const char *var) {
- unsigned len = (unsigned)strlen(var);
- unsigned wn = fl_utf8toUtf16(var, len, NULL, 0) + 1; // Query length
- wchar_t *wbuf = (wchar_t *)malloc(sizeof(wchar_t) * wn);
- wn = fl_utf8toUtf16(var, len, (unsigned short *)wbuf, wn);
- wbuf[wn] = 0;
- int ret = _wputenv(wbuf);
- free(wbuf);
- return ret;
-}
-
-int Fl_WinAPI_System_Driver::open(const char *fnam, int oflags, int pmode) {
- utf8_to_wchar(fnam, wbuf);
- if (pmode == -1) return _wopen(wbuf, oflags);
- else return _wopen(wbuf, oflags, pmode);
-}
-
-int Fl_WinAPI_System_Driver::open_ext(const char *fnam, int binary, int oflags, int pmode) {
- if (oflags == 0) oflags = _O_RDONLY;
- oflags |= (binary ? _O_BINARY : _O_TEXT);
- return this->open(fnam, oflags, pmode);
-}
-
-FILE *Fl_WinAPI_System_Driver::fopen(const char *fnam, const char *mode) {
- utf8_to_wchar(fnam, wbuf);
- utf8_to_wchar(mode, wbuf1);
- return _wfopen(wbuf, wbuf1);
-}
-
-int Fl_WinAPI_System_Driver::system(const char *cmd) {
- return _wsystem(utf8_to_wchar(cmd, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::execvp(const char *file, char *const *argv) {
- int n = 0;
- while (argv[n]) n++; // count args
- wchar_t **ar = (wchar_t **)calloc(sizeof(wchar_t *), n + 1);
- // convert arguments first; trailing NULL provided by calloc()
- for (int i = 0; i < n; i++)
- ar[i] = utf8_to_wchar(argv[i], ar[i]); // alloc and assign
- // convert executable file and execute it ...
- utf8_to_wchar(file, wbuf);
- _wexecvp(wbuf, ar); // STR #3040
- // clean up (reached only if _wexecvp() failed)
- for (int i = 0; i < n; i++)
- free(ar[i]);
- free(ar);
- return -1; // STR #3040
-}
-
-int Fl_WinAPI_System_Driver::chmod(const char *fnam, int mode) {
- return _wchmod(utf8_to_wchar(fnam, wbuf), mode);
-}
-
-int Fl_WinAPI_System_Driver::access(const char *fnam, int mode) {
- return _waccess(utf8_to_wchar(fnam, wbuf), mode);
-}
-
-int Fl_WinAPI_System_Driver::flstat(const char *fnam, struct stat *b) {
-
- // remove trailing '/' or '\'
- unsigned len = (unsigned)strlen(fnam);
- if (len > 0 && (fnam[len-1] == '/' || fnam[len-1] == '\\'))
- len--;
- // convert filename and execute _wstat()
- return _wstat(utf8_to_wchar(fnam, wbuf, len), (struct _stat *)b);
-}
-
-char *Fl_WinAPI_System_Driver::getcwd(char *buf, int len) {
-
- static wchar_t *wbuf = NULL;
- wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * (len + 1));
- wchar_t *ret = _wgetcwd(wbuf, len);
- if (!ret) return NULL;
-
- unsigned dstlen = (unsigned)len;
- len = (int)wcslen(wbuf);
- dstlen = fl_utf8fromwc(buf, dstlen, wbuf, (unsigned)len);
- buf[dstlen] = 0;
- return buf;
-}
-
-int Fl_WinAPI_System_Driver::chdir(const char *path) {
- return _wchdir(utf8_to_wchar(path, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::unlink(const char *fnam) {
- return _wunlink(utf8_to_wchar(fnam, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::mkdir(const char *fnam, int mode) {
- return _wmkdir(utf8_to_wchar(fnam, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::rmdir(const char *fnam) {
- return _wrmdir(utf8_to_wchar(fnam, wbuf));
-}
-
-int Fl_WinAPI_System_Driver::rename(const char *fnam, const char *newnam) {
- utf8_to_wchar(fnam, wbuf);
- utf8_to_wchar(newnam, wbuf1);
- return _wrename(wbuf, wbuf1);
-}
-
-// See Fl::args_to_utf8()
-int Fl_WinAPI_System_Driver::args_to_utf8(int argc, char ** &argv) {
- int i;
-
- // Convert the command line arguments to UTF-8
- LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc);
- argv = (char **)malloc((argc + 1) * sizeof(char *));
- for (i = 0; i < argc; i++) {
- // find the required size of the buffer
- int u8size = WideCharToMultiByte(CP_UTF8, // CodePage
- 0, // dwFlags
- wideArgv[i], // lpWideCharStr
- -1, // cchWideChar
- NULL, // lpMultiByteStr
- 0, // cbMultiByte
- NULL, // lpDefaultChar
- NULL); // lpUsedDefaultChar
- if (u8size > 0) {
- char *strbuf = (char*)::malloc(u8size);
- int ret = WideCharToMultiByte(CP_UTF8, // CodePage
- 0, // dwFlags
- wideArgv[i], // lpWideCharStr
- -1, // cchWideChar
- strbuf, // lpMultiByteStr
- u8size, // cbMultiByte
- NULL, // lpDefaultChar
- NULL); // lpUsedDefaultChar
-
- if (ret) {
- argv[i] = strbuf;
- } else {
- argv[i] = _strdup("");
- ::free(strbuf);
- }
- } else {
- argv[i] = _strdup("");
- }
- }
- argv[argc] = NULL; // required NULL pointer at end of list
-
- // Free the wide character string array
- LocalFree(wideArgv);
-
- // Note: the allocated memory or argv[] will not be free'd by the system
- // on exit. This does not constitute a memory leak.
-
- return argc;
-}
-
-
-// Two Windows-specific functions fl_utf8_to_locale() and fl_locale_to_utf8()
-// from file fl_utf8.cxx are put here for API compatibility
-
-static char *buf = NULL;
-static int buf_len = 0;
-static unsigned short *wbufa = NULL;
-unsigned int fl_codepage = 0;
-
-
-// FIXME: This should *maybe* return 'const char *' instead of 'char *'
-char *fl_utf8_to_locale(const char *s, int len, UINT codepage)
-{
- if (!s) return (char *)"";
- int l = 0;
- unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length
- wn = wn * 2 + 1;
- if (wn >= (unsigned)buf_len) {
- buf_len = wn;
- buf = (char*) realloc(buf, buf_len);
- wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
- }
- if (codepage < 1) codepage = fl_codepage;
- l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string
- wbufa[l] = 0;
- buf[l] = 0;
- l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL);
- if (l < 0) l = 0;
- buf[l] = 0;
- return buf;
-}
-
-// FIXME: This should maybe return 'const char *' instead of 'char *'
-char *fl_locale_to_utf8(const char *s, int len, UINT codepage)
-{
- if (!s) return (char *)"";
- int l = 0;
- if (buf_len < len * 5 + 1) {
- buf_len = len * 5 + 1;
- buf = (char*) realloc(buf, buf_len);
- wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
- }
- if (codepage < 1) codepage = fl_codepage;
- buf[l] = 0;
-
- l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len);
- if (l < 0) l = 0;
- wbufa[l] = 0;
- l = fl_utf8fromwc(buf, buf_len, (wchar_t*)wbufa, l);
- buf[l] = 0;
- return buf;
-}
-
-///////////////////////////////////
-
-unsigned Fl_WinAPI_System_Driver::utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen) {
- return fl_utf8toUtf16(src, srclen, (unsigned short*)dst, dstlen);
-}
-
-unsigned Fl_WinAPI_System_Driver::utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen) {
- unsigned i = 0;
- unsigned count = 0;
- if (dstlen) for (;;) {
- unsigned ucs;
- if (i >= srclen) {
- dst[count] = 0;
- return count;
- }
- ucs = src[i++];
- if (ucs < 0x80U) {
- dst[count++] = ucs;
- if (count >= dstlen) {dst[count-1] = 0; break;}
- } else if (ucs < 0x800U) { /* 2 bytes */
- if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
- dst[count++] = 0xc0 | (ucs >> 6);
- dst[count++] = 0x80 | (ucs & 0x3F);
- } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
- src[i] >= 0xdc00 && src[i] <= 0xdfff) {
- /* surrogate pair */
- unsigned ucs2 = src[i++];
- ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff);
- /* all surrogate pairs turn into 4-byte UTF-8 */
- if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;}
- dst[count++] = 0xf0 | (ucs >> 18);
- dst[count++] = 0x80 | ((ucs >> 12) & 0x3F);
- dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
- dst[count++] = 0x80 | (ucs & 0x3F);
- } else {
- /* all others are 3 bytes: */
- if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;}
- dst[count++] = 0xe0 | (ucs >> 12);
- dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
- dst[count++] = 0x80 | (ucs & 0x3F);
- }
- }
- /* we filled dst, measure the rest: */
- while (i < srclen) {
- unsigned ucs = src[i++];
- if (ucs < 0x80U) {
- count++;
- } else if (ucs < 0x800U) { /* 2 bytes */
- count += 2;
- } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 &&
- src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) {
- /* surrogate pair */
- ++i;
- count += 4;
- } else {
- count += 3;
- }
- }
- return count;
-}
-
-int Fl_WinAPI_System_Driver::utf8locale()
-{
- static int ret = (GetACP() == CP_UTF8);
- return ret;
-}
-
-unsigned Fl_WinAPI_System_Driver::utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) {
- wchar_t lbuf[1024];
- wchar_t *buf = lbuf;
- unsigned length = fl_utf8towc(src, srclen, buf, 1024);
- unsigned ret;
- if (length >= 1024) {
- buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
- fl_utf8towc(src, srclen, buf, length+1);
- }
- if (dstlen) {
- // apparently this does not null-terminate, even though msdn documentation claims it does:
- ret =
- WideCharToMultiByte(GetACP(), 0, buf, length, dst, dstlen, 0, 0);
- dst[ret] = 0;
- }
- // if it overflows or measuring length, get the actual length:
- if (dstlen==0 || ret >= dstlen-1)
- ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0);
- if (buf != lbuf) free(buf);
- return ret;
-}
-
-unsigned Fl_WinAPI_System_Driver::utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) {
- wchar_t lbuf[1024];
- wchar_t *buf = lbuf;
- unsigned length;
- unsigned ret;
- length = MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024);
- if ((length == 0)&&(GetLastError()==ERROR_INSUFFICIENT_BUFFER)) {
- length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0);
- buf = (wchar_t*)(malloc(length*sizeof(wchar_t)));
- MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length);
- }
- ret = fl_utf8fromwc(dst, dstlen, buf, length);
- if (buf != lbuf) free((void*)buf);
- return ret;
-}
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/)
-static _locale_t c_locale = NULL;
-#endif
-
-int Fl_WinAPI_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) {
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/)
- if (!c_locale)
- c_locale = _create_locale(LC_NUMERIC, "C");
- int retval = _vfprintf_l(output, format, c_locale, args);
-#else
- char *saved_locale = setlocale(LC_NUMERIC, NULL);
- setlocale(LC_NUMERIC, "C");
- int retval = vfprintf(output, format, args);
- setlocale(LC_NUMERIC, saved_locale);
-#endif
- return retval;
-}
-
-int Fl_WinAPI_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) {
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/)
- if (!c_locale)
- c_locale = _create_locale(LC_NUMERIC, "C");
- int retval = _vsnprintf_l(output, output_size, format, c_locale, args);
-#else
- char *saved_locale = setlocale(LC_NUMERIC, NULL);
- setlocale(LC_NUMERIC, "C");
- int retval = vsnprintf(output, output_size, format, args);
- setlocale(LC_NUMERIC, saved_locale);
-#endif
- return retval;
-}
-
-int Fl_WinAPI_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) {
- char *saved_locale = setlocale(LC_NUMERIC, NULL);
- setlocale(LC_NUMERIC, "C");
- int retval = vsscanf(input, format, args);
- setlocale(LC_NUMERIC, saved_locale);
- return retval;
-}
-
-
-int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list,
- int (*sort)(struct dirent **, struct dirent **),
- char *errmsg, int errmsg_sz) {
- // For Windows we have a special scandir implementation that uses
- // the Win32 "wide" functions for lookup, avoiding the code page mess
- // entirely. It also fixes up the trailing '/'.
- return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz);
-}
-
-int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) {
- char *temp = new char[tolen];
- strlcpy(temp,from, tolen);
- char *start = temp;
- char *end = temp+strlen(temp);
- int ret = 0;
- for (char *a=temp; a<end; ) { // for each slash component
- char *e; for (e=a; e<end && !isdirsep(*e); e++) {/*empty*/} // find next slash
- const char *value = 0; // this will point at substitute value
- switch (*a) {
- case '~': // a home directory name
- if (e <= a+1) { // current user's directory
- value = home_directory_name();
- }
- break;
- case '$': /* an environment variable */
- {char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
- break;
- }
- if (value) {
- // substitutions that start with slash delete everything before them:
- if (isdirsep(value[0])) start = a;
- // also if it starts with "A:"
- if (value[0] && value[1]==':') start = a;
- int t = (int) strlen(value); if (isdirsep(value[t-1])) t--;
- if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t);
- memmove(a+t, e, end+1-e);
- end = a+t+(end-e);
- *end = '\0';
- memcpy(a, value, t);
- ret++;
- } else {
- a = e+1;
- if (*e == '\\') {*e = '/'; ret++;} // ha ha!
- }
- }
- strlcpy(to, start, tolen);
- delete[] temp;
- return ret;
-}
-
-int // O - 0 if no change, 1 if changed
-Fl_WinAPI_System_Driver::filename_relative(char *to, // O - Relative filename
- int tolen, // I - Size of "to" buffer
- const char *dest_dir, // I - Absolute filename
- const char *base_dir) // I - Find path relative to this path
-{
- // Find the relative path from base_dir to dest_dir.
- // Both paths must be absolute and well formed (contain no /../ and /./ segments).
-
- // return if any of the pointers is NULL
- if (!to || !dest_dir || !base_dir) {
- return 0;
- }
-
- // if there is a drive letter, make sure both paths use the same drive
- if ( (unsigned)base_dir[0] < 128 && isalpha(base_dir[0]) && base_dir[1] == ':'
- && (unsigned)dest_dir[0] < 128 && isalpha(dest_dir[0]) && dest_dir[1] == ':') {
- if (tolower(base_dir[0]) != tolower(dest_dir[0])) {
- strlcpy(to, dest_dir, tolen);
- return 0;
- }
- // same drive, so skip to the start of the path
- base_dir += 2;
- dest_dir += 2;
- }
-
- // return if `base_dir` or `dest_dir` is not an absolute path
- if (!isdirsep(*base_dir) || !isdirsep(*dest_dir)) {
- strlcpy(to, dest_dir, tolen);
- return 0;
- }
-
- const char *base_i = base_dir; // iterator through the base directory string
- const char *base_s = base_dir; // pointer to the last dir separator found
- const char *dest_i = dest_dir; // iterator through the destination directory
- const char *dest_s = dest_dir; // pointer to the last dir separator found
-
- // compare both path names until we find a difference
- for (;;) {
-#if 0 // case sensitive
- base_i++;
- dest_i++;
- char b = *base_i, d = *dest_i;
-#else // case insensitive
- base_i += fl_utf8len1(*base_i);
- int b = fl_tolower(fl_utf8decode(base_i, NULL, NULL));
- dest_i += fl_utf8len1(*dest_i);
- int d = fl_tolower(fl_utf8decode(dest_i, NULL, NULL));
-#endif
- int b0 = (b == 0) || (isdirsep(b));
- int d0 = (d == 0) || (isdirsep(d));
- if (b0 && d0) {
- base_s = base_i;
- dest_s = dest_i;
- }
- if (b == 0 || d == 0)
- break;
- if (b != d)
- break;
- }
- // base_s and dest_s point at the last separator we found
- // base_i and dest_i point at the first character that differs
-
- // test for the exact same string and return "." if so
- if ( (base_i[0] == 0 || (isdirsep(base_i[0]) && base_i[1] == 0))
- && (dest_i[0] == 0 || (isdirsep(dest_i[0]) && dest_i[1] == 0))) {
- strlcpy(to, ".", tolen);
- return 0;
- }
-
- // prepare the destination buffer
- to[0] = '\0';
- to[tolen - 1] = '\0';
-
- // count the directory segments remaining in `base_dir`
- int n_up = 0;
- for (;;) {
- char b = *base_s++;
- if (b == 0)
- break;
- if (isdirsep(b) && *base_s)
- n_up++;
- }
-
- // now add a "previous dir" sequence for every following slash in the cwd
- if (n_up > 0)
- strlcat(to, "..", tolen);
- for (; n_up > 1; --n_up)
- strlcat(to, "/..", tolen);
-
- // finally add the differing path from "from"
- if (*dest_s) {
- if (n_up)
- strlcat(to, "/", tolen);
- strlcat(to, dest_s + 1, tolen);
- }
-
- return 1;
-}
-
-int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) {
- if (isdirsep(*from) || *from == '|' || from[1]==':' || !base) {
- strlcpy(to, from, tolen);
- return 0;
- }
- char *a;
- char *temp = new char[tolen];
- const char *start = from;
- strlcpy(temp, base, tolen);
- for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
- /* remove trailing '/' in current working directory */
- if (isdirsep(*(a-1))) a--;
- /* remove intermediate . and .. names: */
- while (*start == '.') {
- if (start[1]=='.' && (isdirsep(start[2]) || start[2]==0) ) {
- // found "..", remove the last directory segment form cwd
- char *b;
- for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/}
- if (b < temp) break;
- a = b;
- if (start[2] == 0)
- start += 2;
- else
- start += 3;
- } else if (isdirsep(start[1])) {
- // found "./" in path, just skip it
- start += 2;
- } else if (!start[1]) {
- // found "." at end of path, just skip it
- start ++;
- break;
- } else
- break;
- }
- *a++ = '/';
- strlcpy(a,start,tolen - (a - temp));
- strlcpy(to, temp, tolen);
- delete[] temp;
- return 1;
-}
-
-int Fl_WinAPI_System_Driver::filename_isdir(const char *n) {
- char fn[4]; // used for drive letter only: "X:/"
- int length = (int)strlen(n);
- // Strip trailing slash from name...
- if (length > 0 && isdirsep(n[length - 1]))
- length --;
- if (length < 1)
- return 0;
-
- // This workaround brought to you by the fine folks at Microsoft!
- // (read lots of sarcasm in that...)
-
- if (length == 2 && isalpha(n[0]) && n[1] == ':') { // trailing '/' already "removed"
- // Always use "X:/" for drive letters
- fn[0] = n[0];
- strcpy(fn + 1, ":/");
- n = fn;
- length = 3;
- }
-
- // convert filename to wide chars using *length*
- utf8_to_wchar(n, wbuf, length);
-
- DWORD fa = GetFileAttributesW(wbuf);
- return (fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY);
-}
-
-int Fl_WinAPI_System_Driver::filename_isdir_quick(const char *n) {
- // Do a quick optimization for filenames with a trailing slash...
- if (*n && isdirsep(n[strlen(n) - 1])) return 1;
- return filename_isdir(n);
-}
-
-const char *Fl_WinAPI_System_Driver::filename_ext(const char *buf) {
- const char *q = 0;
- const char *p = buf;
- for (p = buf; *p; p++) {
- if (isdirsep(*p) ) q = 0;
- else if (*p == '.') q = p;
- }
- return q ? q : p;
-}
-
-int Fl_WinAPI_System_Driver::open_uri(const char *uri, char *msg, int msglen) {
- if (msg) snprintf(msg, msglen, "open %s", uri);
- return (int)(ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > (void *)32);
-}
-
-int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename,
- int lname, Fl_File_Icon *icon) {
- int num_files = 0;
-# ifdef __CYGWIN__
- //
- // Cygwin provides an implementation of setmntent() to get the list
- // of available drives...
- //
- FILE *m = setmntent("/-not-used-", "r");
- struct mntent *p;
- while ((p = getmntent (m)) != NULL) {
- browser->add(p->mnt_dir, icon);
- num_files ++;
- }
- endmntent(m);
-# else
- //
- // Normal Windows code uses drive bits...
- //
- DWORD drives; // Drive available bits
- drives = GetLogicalDrives();
- for (int i = 'A'; i <= 'Z'; i ++, drives >>= 1) {
- if (drives & 1) {
- snprintf(filename, lname, "%c:/", i);
- if (i < 'C') // see also: GetDriveType and GetVolumeInformation in Windows
- browser->add(filename, icon);
- else
- browser->add(filename, icon);
- num_files ++;
- }
- }
-# endif // __CYGWIN__
- return num_files;
-}
-
-int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename,
- size_t name_size, dirent ***pfiles,
- Fl_File_Sort_F *sort,
- char *errmsg, int errmsg_sz)
-{
- strlcpy(filename, directory, name_size);
- int i = (int) (strlen(filename) - 1);
- if (i == 2 && filename[1] == ':' &&
- (filename[2] == '/' || filename[2] == '\\'))
- filename[2] = '/';
- else if (filename[i] != '/' && filename[i] != '\\')
- strlcat(filename, "/", name_size);
- return filename_list(filename, pfiles, sort, errmsg, errmsg_sz);
-}
-
-void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
-{
- // First try and use the win API function UuidCreate(), but if that is not
- // available, fall back to making something up from scratch.
- // We do not want to link against the Rpcrt4.dll, as we will rarely use it,
- // so we load the DLL dynamically, if it is available, and work from there.
- static HMODULE hMod = NULL;
- UUID ud;
- UUID *pu = &ud;
- int got_uuid = 0;
-
- if (!hMod) { // first time in?
- hMod = LoadLibrary("Rpcrt4.dll");
- }
-
- if (hMod) { // do we have a usable handle to Rpcrt4.dll?
- uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate");
- if (uuid_crt != NULL) {
- RPC_STATUS rpc_res = uuid_crt(pu);
- if ( // is the return status OK for our needs?
- (rpc_res == RPC_S_OK) || // all is well
- (rpc_res == RPC_S_UUID_LOCAL_ONLY) || // only unique to this machine
- (rpc_res == RPC_S_UUID_NO_ADDRESS) // probably only locally unique
- ) {
- got_uuid = -1;
- snprintf(uuidBuffer, 36+1, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1],
- pu->Data4[2], pu->Data4[3], pu->Data4[4],
- pu->Data4[5], pu->Data4[6], pu->Data4[7]);
- }
- }
- }
- if (got_uuid == 0) { // did not make a UUID - use fallback logic
- unsigned char b[16];
- time_t t = time(0); // first 4 byte
- b[0] = (unsigned char)t;
- b[1] = (unsigned char)(t>>8);
- b[2] = (unsigned char)(t>>16);
- b[3] = (unsigned char)(t>>24);
- int r = rand(); // four more bytes
- b[4] = (unsigned char)r;
- b[5] = (unsigned char)(r>>8);
- b[6] = (unsigned char)(r>>16);
- b[7] = (unsigned char)(r>>24);
- // Now we try to find 4 more "random" bytes. We extract the
- // lower 4 bytes from the address of t - it is created on the
- // stack so *might* be in a different place each time...
- // This is now done via a union to make it compile OK on 64-bit systems.
- union { void *pv; unsigned char a[sizeof(void*)]; } v;
- v.pv = (void *)(&t);
- // NOTE: This assume that all WinXX systems are little-endian
- b[8] = v.a[0];
- b[9] = v.a[1];
- b[10] = v.a[2];
- b[11] = v.a[3];
- TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; // only used to make last four bytes
- DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
- // GetComputerName() does not depend on any extra libs, and returns something
- // analogous to gethostname()
- GetComputerName(name, &nSize);
- // use the first 4 TCHAR's of the name to create the last 4 bytes of our UUID
- for (int ii = 0; ii < 4; ii++) {
- b[12 + ii] = (unsigned char)name[ii];
- }
- snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
- b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
- }
-}
-
-/*
- Note: `prefs` can be NULL!
- */
-char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_Preferences::Root root, const char *vendor,
- const char *application)
-{
- static char *filename = 0L;
- // make enough room for a UTF-16 pathname
- if (!filename) filename = (char*)::malloc(2 * FL_PATH_MAX);
- HRESULT res;
-
- // https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw
-
- int appdata = CSIDL_APPDATA; // assume user preferences
- if ((root & Fl_Preferences::ROOT_MASK) == Fl_Preferences::SYSTEM)
- appdata = CSIDL_COMMON_APPDATA; // use system preferences
-
- res = SHGetFolderPathW(NULL, // hwnd: Reserved!
- appdata, // csidl: User or common Application Data (Roaming)
- NULL, // hToken (unused)
- SHGFP_TYPE_CURRENT, // dwFlags: use current, potentially redirected path
- (LPWSTR)filename); // out: filename in Windows wide string encoding
- if (res != S_OK) {
- // don't write data into some arbitrary directory! Just return NULL.
- return 0L;
- }
-
- // convert the path from Windows wide character (UTF-16) to UTF-8
- // FIXME: can this be simplified? Don't allocate/copy/move/free more than necessary!
- char *buf = NULL;
- wchar_to_utf8((wchar_t *)filename, buf); // allocates buf for conversion
- strcpy(filename, buf);
- free(buf);
-
- // Make sure that the parameters are not NULL
- if ( (vendor==0L) || (vendor[0]==0) )
- vendor = "unknown";
- if ( (application==0L) || (application[0]==0) )
- application = "unknown";
-
- // append vendor, application, and ".prefs", and convert '\' to '/'
- snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename),
- "/%s/%s.prefs", vendor, application);
- for (char *s = filename; *s; s++) if (*s == '\\') *s = '/';
- return filename;
-}
-
-void *Fl_WinAPI_System_Driver::load(const char *filename) {
- return LoadLibraryW(utf8_to_wchar(filename, wbuf));
-}
-
-void Fl_WinAPI_System_Driver::png_extra_rgba_processing(unsigned char *ptr, int w, int h)
-{
- // Some Windows graphics drivers don't honor transparency when RGB == white
- // Convert RGB to 0 when alpha == 0...
- for (int i = w * h; i > 0; i --, ptr += 4) {
- if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
- }
-}
-
-const char *Fl_WinAPI_System_Driver::next_dir_sep(const char *start)
-{
- const char *p = strchr(start, '/');
- if (!p) p = strchr(start, '\\');
- return p;
-}
-
-int Fl_WinAPI_System_Driver::file_type(const char *filename)
-{
- int filetype;
- if (filename[strlen(filename) - 1] == '/')
- filetype = Fl_File_Icon::DIRECTORY;
- else if (filename_isdir(filename))
- filetype = Fl_File_Icon::DIRECTORY;
- else
- filetype = Fl_File_Icon::PLAIN;
- return filetype;
-}
-
-// Note: the result is cached in a static variable
-const char *Fl_WinAPI_System_Driver::home_directory_name()
-{
- static std::string home;
- if (!home.empty())
- return home.c_str();
-
-#if (DEBUG_HOME_DIRECTORY_NAME)
- print_env("HOMEDRIVE");
- print_env("HOMEPATH");
- print_env("UserProfile");
- print_env("HOME");
-#endif
-
- // Implement various ways to retrieve the HOME path.
- // Note, from `man getenv`:
- // "The implementation of getenv() is not required to be reentrant.
- // The string pointed to by the return value of getenv() may be statically
- // allocated, and can be modified by a subsequent call to getenv()...".
- // Tests show that this is the case in some MinGW implementations.
-
- if (home.empty()) {
- const char *home_drive = getenv("HOMEDRIVE");
- if (home_drive) {
- home = home_drive; // copy *before* calling getenv() again, see above
- const char *home_path = getenv("HOMEPATH");
- if (home_path) {
- home.append(home_path);
- } else {
- home.clear(); // reset
- } // home_path
- } // home_drive
- } // empty()
-
- if (home.empty()) {
- const char *h = getenv("UserProfile");
- if (h)
- home = h;
- }
-
- if (home.empty()) {
- const char *h = getenv("HOME");
- if (h)
- home = h;
- }
- if (home.empty()) {
- home = "~/"; // last resort
- }
- // Make path canonical.
- for (char& c : home) {
- if (c == '\\')
- c = '/';
- }
-#if (DEBUG_HOME_DIRECTORY_NAME)
- printf("home_directory_name() returns \"%s\"\n", home.c_str());
- fflush(stdout);
-#endif
- return home.c_str();
-}
-
-void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) {
- struct _timeb t;
- _ftime(&t);
- *sec = t.time;
- *usec = t.millitm * 1000;
-}
-
-//
-// Code for lock support
-//
-
-// These pointers are in Fl_win32.cxx:
-extern void (*fl_lock_function)();
-extern void (*fl_unlock_function)();
-
-// The main thread's ID
-static DWORD main_thread;
-
-// Microsoft's version of a MUTEX...
-static CRITICAL_SECTION cs;
-static CRITICAL_SECTION *cs_ring;
-
-void Fl_WinAPI_System_Driver::unlock_ring() {
- LeaveCriticalSection(cs_ring);
-}
-
-void Fl_WinAPI_System_Driver::lock_ring() {
- if (!cs_ring) {
- cs_ring = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
- InitializeCriticalSection(cs_ring);
- }
- EnterCriticalSection(cs_ring);
-}
-
-//
-// 'unlock_function()' - Release the lock.
-//
-
-static void unlock_function() {
- LeaveCriticalSection(&cs);
-}
-
-//
-// 'lock_function()' - Get the lock.
-//
-
-static void lock_function() {
- EnterCriticalSection(&cs);
-}
-
-int Fl_WinAPI_System_Driver::lock() {
- if (!main_thread) InitializeCriticalSection(&cs);
-
- lock_function();
-
- if (!main_thread) {
- fl_lock_function = lock_function;
- fl_unlock_function = unlock_function;
- main_thread = GetCurrentThreadId();
- }
- return 0;
-}
-
-void Fl_WinAPI_System_Driver::unlock() {
- unlock_function();
-}
-
-void Fl_WinAPI_System_Driver::awake(void* msg) {
- PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0);
-}
-
-int Fl_WinAPI_System_Driver::close_fd(int fd) {
- return _close(fd);
-}
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
deleted file mode 100644
index 3cf26b67c..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// Definition of Windows window driver
-// for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 2010-2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-/**
- \file Fl_WinAPI_Window_Driver.H
- \brief Definition of Windows window driver.
- */
-
-#ifndef FL_WINAPI_WINDOW_DRIVER_H
-#define FL_WINAPI_WINDOW_DRIVER_H
-
-#include <FL/Fl_Plugin.H>
-#include "../../Fl_Window_Driver.H"
-#include <windows.h>
-
-/*
- Move everything here that manages the native window interface.
-
- There is one window driver for each Fl_Window. Window drivers manage window
- actions such as resizing, events, decoration, fullscreen modes, etc. . All
- drawing and rendering is managed by the Surface device and the associated
- graphics driver.
-
- - window specific event handling
- - window types and styles, depth, etc.
- - decorations
-
- ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx?
- */
-
-
-
-class Fl_WinAPI_Window_Driver : public Fl_Window_Driver
-{
- struct icon_data {
- const void *legacy_icon;
- Fl_RGB_Image **icons;
- int count;
- HICON big_icon;
- HICON small_icon;
- };
- struct shape_data_type {
- int lw_; ///< width of shape image
- int lh_; ///< height of shape image
- Fl_Image* shape_; ///< shape image
- Fl_Bitmap *effective_bitmap_; ///< auxiliary bitmap image
- } *shape_data_;
-private:
- void shape_bitmap_(Fl_Image* b);
- void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE;
-public:
- Fl_WinAPI_Window_Driver(Fl_Window*);
- ~Fl_WinAPI_Window_Driver();
- static inline Fl_WinAPI_Window_Driver* driver(const Fl_Window *w) {return (Fl_WinAPI_Window_Driver*)Fl_Window_Driver::driver(w);}
- HDC private_dc; // used for OpenGL
- RECT border_width_title_bar_height(int &bx, int &by, int &bt);
-
- struct icon_data *icon_;
- HCURSOR cursor;
- int custom_cursor;
- void set_minmax(LPMINMAXINFO minmax);
- int fake_X_wm(int &X, int &Y, int &bt, int &bx, int &by, DWORD style = 0, DWORD styleEx = 0);
- void make_fullscreen(int X, int Y, int W, int H);
- // --- window data
- int decorated_w() FL_OVERRIDE;
- int decorated_h() FL_OVERRIDE;
- const Fl_Image* shape() FL_OVERRIDE;
-
- // --- window management
- void makeWindow() FL_OVERRIDE;
- void size_range() FL_OVERRIDE {
- // currently nothing to do
- }
- void flush_double() FL_OVERRIDE;
- void flush_overlay() FL_OVERRIDE;
- void draw_begin() FL_OVERRIDE;
- void make_current() FL_OVERRIDE;
- void show() FL_OVERRIDE;
- void label(const char *name,const char *iname) FL_OVERRIDE;
- void resize(int X,int Y,int W,int H) FL_OVERRIDE;
- void hide() FL_OVERRIDE;
- void map() FL_OVERRIDE;
- void unmap() FL_OVERRIDE;
- void fullscreen_on() FL_OVERRIDE;
- void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE;
- void maximize() FL_OVERRIDE;
- void un_maximize() FL_OVERRIDE;
- bool maximize_needs_hide() FL_OVERRIDE { return true; }
- void iconize() FL_OVERRIDE;
- void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE;
- // --- window cursor stuff
- int set_cursor(Fl_Cursor) FL_OVERRIDE;
- int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE;
-
- void shape(const Fl_Image* img) FL_OVERRIDE;
- void icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE;
- const void *icon() const FL_OVERRIDE;
- void icon(const void * ic) FL_OVERRIDE;
- void free_icons() FL_OVERRIDE;
- void set_icons(); // driver-internal support function
- // this one is implemented in Fl_win32.cxx
- void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE;
- int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
- void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE;
-};
-
-
-class Fl_WinAPI_Plugin : public Fl_Plugin {
-public:
- Fl_WinAPI_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { }
- virtual const char *klass() { return "winapi.fltk.org"; }
- virtual const char *name() = 0;
- virtual void invalidate(Fl_Window*) = 0;
-};
-
-
-#endif // FL_WINAPI_WINDOW_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
deleted file mode 100644
index 4b27753bf..000000000
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ /dev/null
@@ -1,731 +0,0 @@
-//
-// Definition of Windows window driver for the Fast Light Tool Kit (FLTK).
-//
-// Copyright 1998-2025 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include <config.h>
-#include <FL/Fl.H>
-#include <FL/fl_draw.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Image.H>
-#include <FL/Fl_Bitmap.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Image_Surface.H>
-#include <FL/Fl_Overlay_Window.H>
-#include <FL/platform.H>
-#include "Fl_WinAPI_Window_Driver.H"
-#include "Fl_WinAPI_Screen_Driver.H"
-#include "../GDI/Fl_GDI_Graphics_Driver.H"
-#include <windows.h>
-#include <ole2.h>
-#include <math.h> // for ceil()
-
-#if USE_COLORMAP
-extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
-#endif
-
-
-Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win)
-: Fl_Window_Driver(win)
-{
- icon_ = new icon_data;
- shape_data_ = NULL;
- memset(icon_, 0, sizeof(icon_data));
- cursor = NULL;
- screen_num_ = -1;
-}
-
-
-Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver()
-{
- if (shape_data_) {
- delete shape_data_->effective_bitmap_;
- delete shape_data_;
- }
- delete icon_;
-}
-
-
-//FILE*LOG=fopen("log.log","w");
-
-
-RECT // frame of the decorated window in screen coordinates
- Fl_WinAPI_Window_Driver::border_width_title_bar_height(
- int &bx, // left and right border width
- int &by, // bottom border height (=bx)
- int &bt // height of window title bar
- )
-{
- Fl_Window *win = pWindow;
- RECT r = {0,0,0,0};
- bx = by = bt = 0;
- if (win->shown() && !win->parent() && win->border() && win->visible()) {
- static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
- typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
- static DwmGetWindowAttribute_type DwmGetWindowAttribute = dwmapi_dll ?
- (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute") : NULL;
- int need_r = 1;
- if (DwmGetWindowAttribute) {
- const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
- if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
- need_r = 0;
- }
- }
- if (need_r) {
- GetWindowRect(fl_xid(win), &r);
- }
- int width, height;
- RECT rc;
- GetClientRect(fl_xid(win), &rc);
- width = rc.right;
- height = rc.bottom;
- bx = (r.right - r.left - width)/2;
- if (bx < 1) bx = 1;
- by = bx;
- bt = r.bottom - r.top - height - 2 * by;
- }
- return r;
-}
-
-
-// --- window data
-
-int Fl_WinAPI_Window_Driver::decorated_w()
-{
- int bt, bx, by;
- float s = Fl::screen_driver()->scale(screen_num());
- border_width_title_bar_height(bx, by, bt);
- int mini_bx = int(bx/s); if (mini_bx < 1) mini_bx = 1;
- return w() + 2 * mini_bx;
-}
-
-int Fl_WinAPI_Window_Driver::decorated_h()
-{
- int bt, bx, by;
- border_width_title_bar_height(bx, by, bt);
- float s = Fl::screen_driver()->scale(screen_num());
- int mini_by = int(by / s); if (mini_by < 1) mini_by = 1;
- return h() + int((bt + by) / s) + mini_by;
-}
-
-
-// --- window management
-
-
-
-void Fl_WinAPI_Window_Driver::shape_bitmap_(Fl_Image* b) {
- shape_data_->shape_ = b;
-}
-
-void Fl_WinAPI_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
- int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8;
- unsigned u;
- uchar byte, onebit;
- // build an Fl_Bitmap covering the non-fully transparent/black part of the image
- const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap
- const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels
- for (i = 0; i < h; i++) {
- uchar *p = (uchar*)bits + i * bytesperrow;
- byte = 0;
- onebit = 1;
- for (j = 0; j < w; j++) {
- if (d == 3) {
- u = *alpha;
- u += *(alpha+1);
- u += *(alpha+2);
- }
- else u = *alpha;
- if (u > 0) { // if the pixel is not fully transparent/black
- byte |= onebit; // turn on the corresponding bit of the bitmap
- }
- onebit = onebit << 1; // move the single set bit one position to the left
- if (onebit == 0 || j == w-1) {
- onebit = 1;
- *p++ = byte; // store in bitmap one pack of bits
- byte = 0;
- }
- alpha += d; // point to alpha value of next pixel
- }
- }
- Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h);
- bitmap->alloc_array = 1;
- shape_bitmap_(bitmap);
- shape_data_->effective_bitmap_ = bitmap;
- shape_data_->shape_ = img;
-}
-
-void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) {
- if (shape_data_) {
- if (shape_data_->effective_bitmap_) { delete shape_data_->effective_bitmap_; }
- }
- else {
- shape_data_ = new shape_data_type;
- }
- memset(shape_data_, 0, sizeof(shape_data_type));
- pWindow->border(false);
- int d = img->d();
- if (d && img->count() >= 2) {
- shape_pixmap_((Fl_Image*)img);
- shape_data_->shape_ = (Fl_Image*)img;
- }
- else if (d == 0) shape_bitmap_((Fl_Image*)img);
- else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
- else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
-}
-
-
-static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); }
-
-static HRGN bitmap2region(Fl_Image* image) {
- HRGN hRgn = 0;
- /* Does this need to be dynamically determined, perhaps? */
- const int ALLOC_UNIT = 100;
- DWORD maxRects = ALLOC_UNIT;
-
- RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects));
- pData->rdh.dwSize = sizeof(RGNDATAHEADER);
- pData->rdh.iType = RDH_RECTANGLES;
- pData->rdh.nCount = pData->rdh.nRgnSize = 0;
- SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
-
- const int bytesPerLine = (image->w() + 7)/8;
- BYTE* p, *data = (BYTE*)*image->data();
- for (int y = 0; y < image->h(); y++) {
- // each row, left to right
- for (int x = 0; x < image->w(); x++) {
- int x0 = x;
- while (x < image->w()) {
- p = data + x / 8;
- if (!((*p) & bit(x))) break; // transparent pixel
- x++;
- }
- if (x > x0) {
- RECT *pr;
- /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
- * in the region
- */
- if (pData->rdh.nCount >= maxRects) {
- maxRects += ALLOC_UNIT;
- pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER)
- + (sizeof(RECT)*maxRects));
- }
- pr = (RECT*)&pData->Buffer;
- SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
- if (x0 < pData->rdh.rcBound.left)
- pData->rdh.rcBound.left = x0;
- if (y < pData->rdh.rcBound.top)
- pData->rdh.rcBound.top = y;
- if (x > pData->rdh.rcBound.right)
- pData->rdh.rcBound.right = x;
- if (y+1 > pData->rdh.rcBound.bottom)
- pData->rdh.rcBound.bottom = y+1;
- pData->rdh.nCount++;
- /* On Windows98, ExtCreateRegion() may fail if the
- * number of rectangles is too large (ie: >
- * 4000). Therefore, we have to create the region by
- * multiple steps.
- */
- if (pData->rdh.nCount == 2000) {
- HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
- + (sizeof(RECT)*maxRects), pData);
- if (hRgn) {
- CombineRgn(hRgn, hRgn, h, RGN_OR);
- DeleteObject(h);
- } else
- hRgn = h;
- pData->rdh.nCount = 0;
- SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
- }
- }
- }
- /* Go to next row */
- data += bytesPerLine;
- }
- /* Create or extend the region with the remaining rectangles*/
- HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
- + (sizeof(RECT)*maxRects), pData);
- if (hRgn) {
- CombineRgn(hRgn, hRgn, h, RGN_OR);
- DeleteObject(h);
- } else hRgn = h;
- free(pData); // I've created the region so I can free this now, right?
- return hRgn;
-}
-
-
-void Fl_WinAPI_Window_Driver::draw_begin()
-{
- if (shape_data_) {
- float s = Fl::screen_driver()->scale(screen_num());
- if ((shape_data_->lw_ != s*w() || shape_data_->lh_ != s*h()) && shape_data_->shape_) {
- // size of window has changed since last time
- shape_data_->lw_ = int(s * w());
- shape_data_->lh_ = int(s * h());
- Fl_Image* temp = shape_data_->effective_bitmap_ ? shape_data_->effective_bitmap_ : shape_data_->shape_;
- temp = temp->copy(shape_data_->lw_, shape_data_->lh_);
- HRGN region = bitmap2region(temp);
- SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed
- delete temp;
- }
- }
-}
-
-
-void Fl_WinAPI_Window_Driver::flush_double()
-{
- if (!shown()) return;
- pWindow->make_current(); // make sure fl_gc is non-zero
- Fl_X *i = Fl_X::flx(pWindow);
- if (!i) return; // window not yet created
-
- if (!other_xid) {
- other_xid = new Fl_Image_Surface(w(), h(), 1);
- pWindow->clear_damage(FL_DAMAGE_ALL);
- }
- if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
- fl_clip_region(i->region); i->region = 0;
-#if 0 /* Short form that transiently changes the current Fl_Surface_Device */
- Fl_Surface_Device::push_current(other_xid);
- fl_graphics_driver->clip_region( 0 );
- draw();
- Fl_Surface_Device::pop_current();
-#else
- /* Alternative form that avoids changing the current Fl_Surface_Device.
- The code run in the window draw() method can call Fl_Surface_Device::surface()
- and conclude that it's drawing to the display, which is ultimately true
- for an Fl_Double_Window.
- */
- HDC sgc = fl_gc;
- fl_gc = fl_makeDC((HBITMAP)other_xid->offscreen());
- int savedc = SaveDC(fl_gc);
- fl_graphics_driver->gc(fl_gc);
- fl_graphics_driver->restore_clip(); // duplicate clip region into new gc
-# if defined(FLTK_HAVE_CAIROEXT)
- if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow);
-# endif
- draw();
- RestoreDC(fl_gc, savedc);
- DeleteDC(fl_gc);
- fl_graphics_driver->gc(sgc);
-#endif
- }
- int X = 0, Y = 0, W = 0, H = 0;
- fl_clip_box(0, 0, w(), h(), X, Y, W, H);
- if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y);
-}
-
-
-void Fl_WinAPI_Window_Driver::flush_overlay()
-{
- Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
-
- if (!shown()) return;
- pWindow->make_current(); // make sure fl_gc is non-zero
- Fl_X *i = Fl_X::flx(pWindow);
- if (!i) return; // window not yet created
-
- int eraseoverlay = (pWindow->damage()&FL_DAMAGE_OVERLAY);
- pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
-
- if (!other_xid) {
- other_xid = new Fl_Image_Surface(w(), h(), 1);
- pWindow->clear_damage(FL_DAMAGE_ALL);
- }
- if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
- fl_clip_region(i->region); i->region = 0;
- Fl_Surface_Device::push_current(other_xid);
- fl_graphics_driver->clip_region(0);
- draw();
- Fl_Surface_Device::pop_current();
- }
-
- if (eraseoverlay) fl_clip_region(0);
- int X, Y, W, H; fl_clip_box(0, 0, w(), h(), X, Y, W, H);
- if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y);
-
- if (overlay() == oWindow) oWindow->draw_overlay();
-}
-
-
-void Fl_WinAPI_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) {
- free_icons();
-
- if (count > 0) {
- icon_->icons = new Fl_RGB_Image*[count];
- icon_->count = count;
- // FIXME: Fl_RGB_Image lacks const modifiers on methods
- for (int i = 0;i < count;i++) {
- icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy();
- icon_->icons[i]->normalize();
- }
- }
-
- if (Fl_X::flx(pWindow))
- set_icons();
-}
-
-const void *Fl_WinAPI_Window_Driver::icon() const {
- return icon_->legacy_icon;
-}
-
-void Fl_WinAPI_Window_Driver::icon(const void * ic) {
- free_icons();
- icon_->legacy_icon = ic;
-}
-
-void Fl_WinAPI_Window_Driver::free_icons() {
- int i;
- icon_->legacy_icon = 0L;
- if (icon_->icons) {
- for (i = 0;i < icon_->count;i++)
- delete icon_->icons[i];
- delete [] icon_->icons;
- icon_->icons = 0L;
- }
- icon_->count = 0;
- if (icon_->big_icon)
- DestroyIcon(icon_->big_icon);
- if (icon_->small_icon)
- DestroyIcon(icon_->small_icon);
- icon_->big_icon = NULL;
- icon_->small_icon = NULL;
-}
-
-
-void Fl_WinAPI_Window_Driver::make_current() {
- fl_GetDC(fl_xid(pWindow));
-
-#if USE_COLORMAP
- // Windows maintains a hardware and software color palette; the
- // SelectPalette() call updates the current soft->hard mapping
- // for all drawing calls, so we must select it here before any
- // code does any drawing...
- fl_select_palette();
-#endif // USE_COLORMAP
-
- fl_graphics_driver->clip_region(0);
- ((Fl_GDI_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num()));
-#if defined(FLTK_HAVE_CAIROEXT)
- if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow);
-#endif
-}
-
-void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) {
- if (shown() && !parent()) {
- if (!name) name = "";
- size_t l = strlen(name);
- // WCHAR *lab = (WCHAR*) malloc((l + 1) * sizeof(short));
- // l = fl_utf2unicode((unsigned char*)name, l, (wchar_t*)lab);
- unsigned wlen = fl_utf8toUtf16(name, (unsigned) l, NULL, 0); // Pass NULL to query length
- wlen++;
- unsigned short * lab = (unsigned short*)malloc(sizeof(unsigned short)*wlen);
- wlen = fl_utf8toUtf16(name, (unsigned) l, lab, wlen);
- lab[wlen] = 0;
- SetWindowTextW(fl_xid(pWindow), (WCHAR *)lab);
- free(lab);
- }
-}
-
-
-extern void fl_clipboard_notify_retarget(HWND wnd);
-extern void fl_update_clipboard(void);
-extern char fl_i_own_selection[2];
-
-void Fl_WinAPI_Window_Driver::hide() {
- Fl_X* ip = Fl_X::flx(pWindow);
- // STR#3079: if there remains a window and a non-modal window, and the window is deleted,
- // the app remains running without any apparent window.
- // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s)
- // but does not delete it(them) in FLTK.
- // Fix for it:
- // when hiding a window, build list of windows it owns, and do hide/show on them.
- int count = 0;
- Fl_Window *win, **doit = NULL;
- for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
- if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) {
- count++;
- }
- }
- if (count) {
- doit = new Fl_Window*[count];
- count = 0;
- for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
- if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) {
- doit[count++] = win;
- }
- }
- }
-
- if (hide_common()) {
- delete[] doit; // note: `count` and `doit` may be NULL (see PR #241)
- return;
- }
-
- // Issue #569: undo RegisterDragDrop()
- RevokeDragDrop((HWND)ip->xid);
-
- fl_i_own_selection[1] = 0; // issue #1233
-
- // make sure any custom icons get freed
- // icons(NULL, 0); // free_icons() is called by the Fl_Window destructor
- // this little trick keeps the current clipboard alive, even if we are about
- // to destroy the window that owns the selection.
- if (GetClipboardOwner() == (HWND)ip->xid)
- fl_update_clipboard();
- // Make sure we unlink this window from the clipboard chain
- fl_clipboard_notify_retarget((HWND)ip->xid);
- // Send a message to myself so that I'll get out of the event loop...
- PostMessage((HWND)ip->xid, WM_APP, 0, 0);
- if (private_dc) fl_release_dc((HWND)ip->xid, private_dc);
- if ((HWND)ip->xid == fl_window && fl_graphics_driver->gc()) {
- fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc());
- fl_window = (HWND)-1;
- fl_graphics_driver->gc(0);
-# ifdef FLTK_HAVE_CAIROEXT
- if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0);
-# endif
- }
-
- if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
-
- // this little trickery seems to avoid the popup window stacking problem
- HWND p = GetForegroundWindow();
- if (p==GetParent((HWND)ip->xid)) {
- ShowWindow((HWND)ip->xid, SW_HIDE);
- ShowWindow(p, SW_SHOWNA);
- }
- DestroyWindow((HWND)ip->xid);
- // end of fix for STR#3079
- if (count) {
- int ii;
- for (ii = 0; ii < count; ii++) doit[ii]->hide();
- for (ii = 0; ii < count; ii++) {
- if (ii != 0) doit[0]->show(); // Fix for STR#3165
- doit[ii]->show();
- }
- }
- delete[] doit; // note: `count` and `doit` may be NULL (see PR #241)
-
- // Try to stop the annoying "raise another program" behavior
- if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown())
- Fl::first_window()->show();
- delete ip;
- screen_num_ = -1;
-}
-
-
-void Fl_WinAPI_Window_Driver::map() {
- ShowWindow(fl_xid(pWindow), SW_RESTORE); // extra map calls are harmless
-}
-
-
-void Fl_WinAPI_Window_Driver::unmap() {
- ShowWindow(fl_xid(pWindow), SW_HIDE);
-}
-
-#if !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning
-
-void Fl_WinAPI_Window_Driver::make_fullscreen(int X, int Y, int W, int H) {
- HWND xid = fl_xid(pWindow);
- int top, bottom, left, right;
- int sx, sy, sw, sh;
-
- top = fullscreen_screen_top();
- bottom = fullscreen_screen_bottom();
- left = fullscreen_screen_left();
- right = fullscreen_screen_right();
-
- if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
- top = screen_num();
- bottom = top;
- left = top;
- right = top;
- }
-
- Fl_WinAPI_Screen_Driver *scr_dr = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver();
- scr_dr->screen_xywh_unscaled(sx, Y, sw, sh, top);
- scr_dr->screen_xywh_unscaled(sx, sy, sw, sh, bottom);
- H = sy + sh - Y;
- scr_dr->screen_xywh_unscaled(X, sy, sw, sh, left);
- scr_dr->screen_xywh_unscaled(sx, sy, sw, sh, right);
- W = sx + sw - X;
-
- DWORD flags = GetWindowLong(xid, GWL_STYLE);
- flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
- SetWindowLong(xid, GWL_STYLE, flags);
-
- // SWP_NOSENDCHANGING is so that we can override size limits
- SetWindowPos(xid, HWND_TOP, X, Y, W, H, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
-}
-
-#endif // !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning
-
-
-void Fl_WinAPI_Window_Driver::fullscreen_on() {
- pWindow->_set_fullscreen();
- make_fullscreen(x(), y(), w(), h());
- Fl::handle(FL_FULLSCREEN, pWindow);
-}
-
-
-void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
- pWindow->_clear_fullscreen();
- DWORD style = GetWindowLong(fl_xid(pWindow), GWL_STYLE);
- if (pWindow->border()) style |= WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_CAPTION;
- // Remove the xid temporarily so that Fl_WinAPI_Window_Driver::fake_X_wm() behaves like it
- // does in Fl_WinAPI_Window_Driver::makeWindow().
- HWND xid = fl_xid(pWindow);
- Fl_X::flx(pWindow)->xid = 0;
- int wx, wy, bt, bx, by;
- switch (fake_X_wm(wx, wy, bt, bx, by, style)) {
- case 0:
- break;
- case 1:
- style |= WS_CAPTION;
- break;
- case 2:
- /*if (border()) {
- style |= WS_THICKFRAME | WS_CAPTION;
- }*/
- break;
- }
- Fl_X::flx(pWindow)->xid = (fl_uintptr_t)xid;
- SetWindowLong(fl_xid(pWindow), GWL_STYLE, style);
- if (!pWindow->maximize_active()) {
- // compute window position and size in scaled units
- float s = Fl::screen_driver()->scale(screen_num());
- int scaledX = int(ceil(X*s)), scaledY= int(ceil(Y*s)), scaledW = int(ceil(W*s)), scaledH = int(ceil(H*s));
- // Adjust for decorations (but not if that puts the decorations
- // outside the screen)
- if ((X != x()) || (Y != y())) {
- scaledX -= bx;
- scaledY -= by+bt;
- }
- scaledW += bx*2;
- scaledH += by*2+bt;
- SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH,
- SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
- } else {
- int WX, WY, WW, WH;
- ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->screen_xywh_unscaled(WX, WY, WW, WH, screen_num());
- SetWindowPos(fl_xid(pWindow), 0, WX, WY, WW, WH,
- SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
- }
- Fl::handle(FL_FULLSCREEN, pWindow);
-}
-
-
-void Fl_WinAPI_Window_Driver::maximize() {
- if (!border()) return Fl_Window_Driver::maximize();
- ShowWindow(fl_xid(pWindow), SW_SHOWMAXIMIZED);
-}
-
-void Fl_WinAPI_Window_Driver::un_maximize() {
- if (!border()) return Fl_Window_Driver::un_maximize();
- ShowWindow(fl_xid(pWindow), SW_SHOWNORMAL);
-}
-
-
-void Fl_WinAPI_Window_Driver::iconize() {
- ShowWindow(fl_xid(pWindow), SW_SHOWMINNOACTIVE);
-}
-
-
-void Fl_WinAPI_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) {
- int minw, minh, maxw, maxh, set;
- set = pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL);
- if (set && (maxw != minw || maxh != minh)) {
- *left = *right = GetSystemMetrics(SM_CXSIZEFRAME);
- *top = *bottom = GetSystemMetrics(SM_CYSIZEFRAME);
- } else {
- *left = *right = GetSystemMetrics(SM_CXFIXEDFRAME);
- *top = *bottom = GetSystemMetrics(SM_CYFIXEDFRAME);
- }
- *top += GetSystemMetrics(SM_CYCAPTION);
-}
-
-int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
- void (*draw_area)(void*, int,int,int,int), void* data)
-{
- typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
- static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
- static char first_time = 1;
- // We will have to do some Region magic now, so let's see if the
- // required function is available (and it should be starting w/Win95)
- if (first_time) {
- HMODULE hMod = GetModuleHandle("GDI32.DLL");
- if (hMod) {
- fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
- }
- first_time = 0;
- }
- float s = Fl::screen_driver()->scale(screen_num());
- src_x = int(src_x * s); src_y = int(src_y * s);
- src_w = int(src_w * s); src_h = int(src_h * s);
- dest_x = int(dest_x * s); dest_y = int(dest_y * s);
- // Now check if the source scrolling area is fully visible.
- // If it is, we will do a quick scroll and just update the
- // newly exposed area. If it is not, we go the safe route and
- // re-render the full area instead.
- // Note 1: we could go and find the areas that are actually
- // obscured and recursively call fl_scroll for the newly found
- // rectangles. However, this practice would rely on the
- // elements of the undocumented Rgn structure.
- // Note 2: although this method should take care of most
- // multi-screen solutions, it will not solve issues scrolling
- // from a different resolution screen onto another.
- // Note 3: this has been tested with image maps, too.
- HDC gc = (HDC)fl_graphics_driver->gc();
- if (fl_GetRandomRgn) {
- // get the DC region minus all overlapping windows
- HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
- fl_GetRandomRgn(gc, sys_rgn, 4);
- // now get the source scrolling rectangle
- HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
- POINT offset = { 0, 0 };
- if (GetDCOrgEx(gc, &offset)) {
- OffsetRgn(src_rgn, offset.x, offset.y);
- }
- // see if all source pixels are available in the system region
- // Note: we could be a bit more merciful and subtract the
- // scroll destination region as well.
- HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
- int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
- DeleteObject(dst_rgn);
- DeleteObject(src_rgn);
- DeleteObject(sys_rgn);
- if (r != NULLREGION) {
- return 1;
- }
- }
- // Great, we can do an accelerated scroll instead of re-rendering
- BitBlt(gc, dest_x, dest_y, src_w, src_h, gc, src_x, src_y,SRCCOPY);
- return 0;
-}
-
-
-const Fl_Image* Fl_WinAPI_Window_Driver::shape() {
- return shape_data_ ? shape_data_->shape_ : NULL;
-}
-
-
-HWND fl_win32_xid(const Fl_Window *win) {
- return (HWND)Fl_Window_Driver::xid(win);
-}
-
-
-Fl_Window *fl_win32_find(HWND xid) {
- return Fl_Window_Driver::find((fl_uintptr_t)xid);
-}
diff --git a/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx b/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx
deleted file mode 100644
index b5ffe2449..000000000
--- a/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// Windows-specific code to initialize Windows support.
-//
-// Copyright 2022 by Bill Spitzak and others.
-//
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file. If this
-// file is missing or damaged, see the license at:
-//
-// https://www.fltk.org/COPYING.php
-//
-// Please see the following page on how to report bugs and issues:
-//
-// https://www.fltk.org/bugs.php
-//
-
-
-#include "../GDI/Fl_GDI_Copy_Surface_Driver.H"
-#include "../GDI/Fl_GDI_Graphics_Driver.H"
-#include "Fl_WinAPI_Screen_Driver.H"
-#include "Fl_WinAPI_System_Driver.H"
-#include "Fl_WinAPI_Window_Driver.H"
-#include "../GDI/Fl_GDI_Image_Surface_Driver.H"
-#include "../Base/Fl_Base_Pen_Events.H"
-
-
-Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h)
-{
- return new Fl_GDI_Copy_Surface_Driver(w, h);
-}
-
-
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
-#if USE_GDIPLUS
- // Initialize GDI+.
- static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
- if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_CLOSED) {
- Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_STARTUP;
- Gdiplus::Status ret = GdiplusStartup(&Fl_GDIplus_Graphics_Driver::gdiplus_token_, &gdiplusStartupInput, NULL);
- if (ret == 0) { // 0 is same as Gdiplus::Status::Ok, but old mingw64 barks at that
- Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_OPEN;
- } else {
- Fl::warning("GdiplusStartup failed with error code %d.", ret);
- Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED;
- return new Fl_GDI_Graphics_Driver();
- }
- } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_OPEN) {
-// Fl::warning("GdiplusStartup() called, but driver is already open.");
- } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_SHUTDOWN) {
-// Fl::warning("GdiplusStartup() called while driver is shutting down.");
- } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_STARTUP) {
-// Fl::warning("GdiplusStartup() called recursively.");
- }
- Fl_Graphics_Driver *driver = new Fl_GDIplus_Graphics_Driver();
- return driver;
-#else
- return new Fl_GDI_Graphics_Driver();
-#endif
-}
-
-
-Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver()
-{
- return new Fl_WinAPI_Screen_Driver();
-}
-
-
-Fl_System_Driver *Fl_System_Driver::newSystemDriver()
-{
- return new Fl_WinAPI_System_Driver();
-}
-
-
-Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
-{
- return new Fl_WinAPI_Window_Driver(w);
-}
-
-
-Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off)
-{
- return new Fl_GDI_Image_Surface_Driver(w, h, high_res, off);
-}
-
diff --git a/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx
index 7282528ca..822acc826 100644
--- a/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx
@@ -40,12 +40,10 @@ public:
}
};
-#ifndef FLTK_USE_WAYLAND
Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
{
return new Fl_X11_Gl_Window_Driver(w);
}
-#endif
void Fl_X11_Gl_Window_Driver::draw_string_legacy(const char* str, int n) {
draw_string_legacy_get_list(str, n);
diff --git a/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H b/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
index fa3c0ee90..3904fa19e 100644
--- a/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
+++ b/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
@@ -20,7 +20,7 @@
#include <FL/Fl_Copy_Surface.H>
#include <FL/platform.H>
#if FLTK_USE_CAIRO
-# include <cairo/cairo.h>
+# include <cairo.h>
#endif // FLTK_USE_CAIRO
class Fl_Image_Surface;
diff --git a/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx b/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
index f60f748f5..281a6590e 100644
--- a/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
@@ -24,7 +24,7 @@
#if FLTK_USE_CAIRO
# include <cairo-xlib.h>
# include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H"
-# include <cairo/cairo.h>
+# include <cairo.h>
#else
# include "Fl_Xlib_Graphics_Driver.H"
#endif // FLTK_USE_CAIRO
diff --git a/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H b/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
index 382daf886..f90f2cc79 100644
--- a/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
+++ b/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
@@ -19,7 +19,7 @@
#include <FL/Fl_Image_Surface.H>
#if FLTK_USE_CAIRO
-# include <cairo/cairo.h>
+# include <cairo.h>
#endif // FLTK_USE_CAIRO
class Fl_Xlib_Image_Surface_Driver : public Fl_Image_Surface_Driver {