summaryrefslogtreecommitdiff
path: root/src/drivers/WinAPI
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/WinAPI
parent75fc94d6c71fe686f6dde5b41ad91cba2f6bdd6f (diff)
wip: fork
Diffstat (limited to 'src/drivers/WinAPI')
-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
11 files changed, 0 insertions, 4372 deletions
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);
-}
-