feat(print): add initial Windows printing support via GDI#20828
feat(print): add initial Windows printing support via GDI#20828adinjithj wants to merge 5 commits intodarktable-org:masterfrom
Conversation
Add a Windows-native print backend (win_print.c) implementing the
same API as the CUPS backend. Uses Windows GDI for printer discovery,
paper enumeration, and bitmap printing.
- Printer discovery via EnumPrinters()
- Paper sizes via DeviceCapabilities()
- Printer metrics via GetDeviceCaps()
- PDF printing via ShellExecute("print")
- Color management defaults to sRGB
Build system updated to conditionally compile the Windows backend
when BUILD_PRINT is enabled on Windows, and the CUPS backend on
Linux/macOS.
Refs: darktable-org#19856
There was a problem hiding this comment.
Pull request overview
Adds a Windows-native printing backend to enable print mode on Windows builds, aligning with the existing CUPS-based print API used on Linux/macOS.
Changes:
- Introduces
src/common/win_print.cimplementing printer discovery, paper enumeration, and PDF printing via Windows APIs. - Updates CMake logic to build print view/settings modules based on
BUILD_PRINT(notCUPS_FOUND), and selects CUPS vs Windows backend per-platform. - Enables
BUILD_PRINTon Windows by removing the forced disable in the top-level CMake.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
src/views/CMakeLists.txt |
Build print view module when BUILD_PRINT is enabled. |
src/libs/CMakeLists.txt |
Build print settings module when BUILD_PRINT is enabled. |
src/common/win_print.c |
New Windows print backend implementation using WinSpool/GDI + ShellExecute. |
src/CMakeLists.txt |
Chooses Windows backend on WIN32, CUPS backend otherwise, and adjusts link libs/defines. |
CMakeLists.txt |
Stops forcibly disabling BUILD_PRINT on Windows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add missing <shellapi.h> include for ShellExecuteW - Switch from ANSI (A) to wide (W) Win32 APIs for proper UTF-8 support via g_utf8_to_utf16/g_utf16_to_utf8 conversion - Use "WINSPOOL" as driver name in CreateDCW for reliable DC creation - Fix printer status filter to check PAUSED, OFFLINE, NOT_AVAILABLE in addition to ERROR - Check _cancel flag during printer enumeration loop for proper abort support - Use "printto" verb with printer name in ShellExecuteW to target the user-selected printer instead of system default - Fix sort_papers to use g_list_sort() instead of g_list_sort_with_data() to match its 2-argument signature - Add gdi32 and shell32 to Windows link libraries in CMakeLists
TurboGit
left a comment
There was a problem hiding this comment.
Thanks for working on this. Definitly something missing on Windows and we had many user requests about this.
The CI fails with:
D:/a/darktable/darktable/src/src/common/printing.c: In function 'dt_printing_setup_image':
D:/a/darktable/darktable/src/src/common/printing.c:332:16: error: 'pos.x' may be used uninitialized [-Werror=maybe-uninitialized]
332 | dt_image_pos pos;
| ^~~
compilation terminated due to -Wfatal-errors.
cc1.exe: all warnings being treated as errors
I let you look at the Copilot report.
| @@ -0,0 +1,472 @@ | |||
| /* | |||
| This file is part of darktable, | |||
| Copyright (C) 2025 darktable developers. | |||
TurboGit
left a comment
There was a problem hiding this comment.
Another GitLab CI compilation issue:
D:/a/_temp/msys64/ucrt64/include/libsecret-1 -isystem D:/a/_temp/msys64/ucrt64/include/GraphicsMagick -isystem D:/a/_temp/msys64/ucrt64/include/osmgpsmap-1.0 -isystem D:/a/_temp/msys64/ucrt64/include/libsoup-3.0 -isystem D:/a/_temp/msys64/ucrt64/include/Imath -isystem D:/a/_temp/msys64/ucrt64/include/OpenEXR -Wall -Wno-format -Wshadow -Wtype-limits -Wvla -Wold-style-declaration -Wmaybe-uninitialized -Wno-unknown-pragmas -Wno-error=varargs -Wno-format-truncation -Wno-error=address-of-packed-member -fopenmp -march=native -msse2 -g -mfpmath=sse -O3 -DNDEBUG -O3 -ffast-math -fno-finite-math-only -fexpensive-optimizations -std=c99 -DUNICODE -D_UNICODE -Werror -Wfatal-errors -MD -MT bin/CMakeFiles/lib_darktable.dir/common/win_print.c.obj -MF bin\CMakeFiles\lib_darktable.dir\common\win_print.c.obj.d -o bin/CMakeFiles/lib_darktable.dir/common/win_print.c.obj -c D:/a/darktable/darktable/src/src/common/win_print.c
In file included from D:/a/darktable/darktable/src/src/win/win.h:5,
from D:/a/darktable/darktable/src/src/common/darktable.h:33,
from D:/a/darktable/darktable/src/src/common/color_harmony.h:21,
from D:/a/darktable/darktable/src/src/common/image.h:21,
from D:/a/darktable/darktable/src/src/common/win_print.c:33:
D:/a/_temp/msys64/ucrt64/include/winsock2.h:15:2: error: #warning Please include winsock2.h before windows.h [-Werror=cpp]
15 | #warning Please include winsock2.h before windows.h
| ^~~~~~~
compilation terminated due to -Wfatal-errors.
cc1.exe: all warnings being treated as errors
|
okay i have to take a better look on this |
|
@adinjithj : Sure no urgency, I have set this to draft for now. Ping me when you think it is in a reviewable state. TIA. |
The Windows API requires that winsock2.h must be included before windows.h to avoid conflicts. This fix reorders the includes in win_print.c so that: - winsock2.h is first - windows.h follows - Other headers follow in logical groups This resolves the MSYS2/Windows CI build failure with: 'winsock2.h:15: error: #warning Please include winsock2.h before windows.h' The entire win_print.c is guarded by #ifdef _WIN32, so this change only affects Windows builds and is safe for Linux/macOS where the file is not compiled.
…ackend Address potential NULL pointer dereferences when encoding conversion fails: - Check wprinter before CreateDCW in dt_get_printer_info() - Check name_utf8 before logging skipped printers - Check name_utf8 before using in dt_get_printer_info() - Check paper_name_utf8 before copying to struct - Check both wfilename and wprinter before ShellExecuteW() Also fix malloc -> g_malloc0 in paper enumeration for consistency with project's glib allocation pattern. These changes prevent crashes if g_utf16_to_utf8() or g_utf8_to_utf16() encounter encoding errors or OOM conditions.
TurboGit
left a comment
There was a problem hiding this comment.
I have spotted many routines just duplicated from cups_print.c. This should be avoided and have the code shared with cups_print.c.
Also, can you clarify how the printer profile (ICC) is handled on Windows?
| g_free(wprinter); | ||
| } | ||
|
|
||
| void dt_get_print_layout(const dt_print_info_t *prt, |
There was a problem hiding this comment.
If I'm not mistaken this is the very same code as dt_get_print_layout found in cups_print.c. Why is it duplicated here?
| } | ||
| } | ||
|
|
||
| dt_paper_info_t *dt_get_paper(GList *papers, |
There was a problem hiding this comment.
Very same code as in cups_print.c I think. Should not be duplicated.
| _cancel = 1; | ||
| } | ||
|
|
||
| void dt_printers_discovery(void (*cb)(dt_printer_info_t *pr, void *user_data), |
There was a problem hiding this comment.
Almost same code as in cups_print.c. Only _cancel = 0 is new here, if really needed should be added into cups_print.c too.
| } | ||
|
|
||
| // initialize the pinfo structure | ||
| void dt_init_print_info(dt_print_info_t *pinfo) |
|
@adinjithj : We are feature freeze in 10 days for 5.6, do you think you can handle the review above and answer the question about ICC? I'd be very happy to see this in 5.6 if possible. Please let me know. TIA. |
Add a Windows-native print backend (win_print.c) implementing the same API as the CUPS backend. Uses Windows GDI for printer discovery, paper enumeration, and bitmap printing.
Build system updated to conditionally compile the Windows backend when BUILD_PRINT is enabled on Windows, and the CUPS backend on Linux/macOS.
Refs: #19856