mirror of
https://github.com/fltk/fltk.git
synced 2025-12-12 14:26:11 +08:00
macOS 15.0 Sequoia: fix capture of window titlebars
The previous procedure using CGWindowListCreateImageFromArray() is obsoleted in macOS 15.0 . The new procedure requires an additional framework: ScreenCaptureKit; FLTK uses it only for macOS ≥ 15.0
This commit is contained in:
@@ -186,8 +186,8 @@ Changes in FLTK 1.4.0 Released: Feb ?? 2024
|
|||||||
Other Improvements
|
Other Improvements
|
||||||
|
|
||||||
- (add new items here)
|
- (add new items here)
|
||||||
- Added support of macOS 14.0 "Sonoma", 13.0 "Ventura", 12.0 "Monterey",
|
- Added support of macOS 15.0 beta "Sequoia", 14.0 "Sonoma",
|
||||||
and 11.0 "Big Sur".
|
13.0 "Ventura", 12.0 "Monterey", and 11.0 "Big Sur".
|
||||||
- Added macOS support for the arm64 architecture since 11.0 (Big Sur).
|
- Added macOS support for the arm64 architecture since 11.0 (Big Sur).
|
||||||
- Added support for macOS 10.15 "Catalina"
|
- Added support for macOS 10.15 "Catalina"
|
||||||
- Added support for macOS 10.14 "Mojave": all drawing to windows is done
|
- Added support for macOS 10.14 "Mojave": all drawing to windows is done
|
||||||
|
|||||||
@@ -123,23 +123,31 @@ if(APPLE)
|
|||||||
endif(NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0))
|
endif(NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0))
|
||||||
else()
|
else()
|
||||||
set(FLTK_COCOA_FRAMEWORKS "-framework Cocoa")
|
set(FLTK_COCOA_FRAMEWORKS "-framework Cocoa")
|
||||||
set(UTI_CONDITION FALSE)
|
set(UTI_CONDITION FALSE) # TRUE when framework UniformTypeIdentifiers is used
|
||||||
|
set(SCK_CONDITION FALSE) # TRUE when framework ScreenCaptureKit is used
|
||||||
string(LENGTH "${CMAKE_OSX_DEPLOYMENT_TARGET}" TARGET_LEN)
|
string(LENGTH "${CMAKE_OSX_DEPLOYMENT_TARGET}" TARGET_LEN)
|
||||||
string(LENGTH "${CMAKE_SYSTEM_VERSION}" SDK_LEN)
|
string(LENGTH "${CMAKE_SYSTEM_VERSION}" SDK_LEN)
|
||||||
if(TARGET_LEN GREATER 0)
|
if(TARGET_LEN GREATER 0)
|
||||||
if( ${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_GREATER_EQUAL 11.0)
|
if( ${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_GREATER_EQUAL 11.0)
|
||||||
set(UTI_CONDITION TRUE)
|
set(UTI_CONDITION TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
if( ${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_GREATER_EQUAL 15.0)
|
||||||
|
set(SCK_CONDITION TRUE)
|
||||||
|
endif()
|
||||||
elseif(SDK_LEN GREATER 0)
|
elseif(SDK_LEN GREATER 0)
|
||||||
if( ${CMAKE_SYSTEM_VERSION} VERSION_GREATER_EQUAL 20.0 )
|
if( ${CMAKE_SYSTEM_VERSION} VERSION_GREATER_EQUAL 20.0 )
|
||||||
set(UTI_CONDITION TRUE)
|
set(UTI_CONDITION TRUE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
if( ${CMAKE_SYSTEM_VERSION} VERSION_GREATER_EQUAL 24.0 )
|
||||||
if(UTI_CONDITION) # a.k.a. macOS version ≥ 11.0
|
set(SCK_CONDITION TRUE)
|
||||||
if (NOT (CMAKE_OSX_ARCHITECTURES STREQUAL "ppc" OR CMAKE_OSX_ARCHITECTURES STREQUAL "i386"))
|
|
||||||
list(APPEND FLTK_COCOA_FRAMEWORKS "-framework UniformTypeIdentifiers")
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
if(UTI_CONDITION) # a.k.a. macOS version ≥ 11.0
|
||||||
|
list(APPEND FLTK_COCOA_FRAMEWORKS "-framework UniformTypeIdentifiers")
|
||||||
|
if(SCK_CONDITION) # a.k.a. macOS version ≥ 15.0
|
||||||
|
list(APPEND FLTK_COCOA_FRAMEWORKS "-framework ScreenCaptureKit")
|
||||||
|
endif(SCK_CONDITION)
|
||||||
|
endif(UTI_CONDITION)
|
||||||
endif(FLTK_BACKEND_X11)
|
endif(FLTK_BACKEND_X11)
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
|
|||||||
3
FL/mac.H
3
FL/mac.H
@@ -99,6 +99,9 @@ typedef class FLWindow *Window; // pointer to the FLWindow objective-c class
|
|||||||
#ifndef MAC_OS_VERSION_14_0
|
#ifndef MAC_OS_VERSION_14_0
|
||||||
#define MAC_OS_VERSION_14_0 140000
|
#define MAC_OS_VERSION_14_0 140000
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MAC_OS_VERSION_15_0
|
||||||
|
#define MAC_OS_VERSION_15_0 150000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
|
#ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
|
||||||
|
|||||||
@@ -1012,6 +1012,9 @@ AS_CASE([$host_os_gui], [cygwin* | mingw*], [
|
|||||||
AS_IF([test $macosversion_maj -ge 11], [
|
AS_IF([test $macosversion_maj -ge 11], [
|
||||||
LIBS="$LIBS -framework UniformTypeIdentifiers"
|
LIBS="$LIBS -framework UniformTypeIdentifiers"
|
||||||
])
|
])
|
||||||
|
AS_IF([test $macosversion_maj -ge 15], [
|
||||||
|
LIBS="$LIBS -framework ScreenCaptureKit"
|
||||||
|
])
|
||||||
|
|
||||||
AS_IF([test x$have_pthread = xyes], [
|
AS_IF([test x$have_pthread = xyes], [
|
||||||
AC_DEFINE([HAVE_PTHREAD])
|
AC_DEFINE([HAVE_PTHREAD])
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ int Fl_Widget_Surface::printable_rect(int *w, int *h) {return 1;}
|
|||||||
void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int win_offset_x, int win_offset_y)
|
void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int win_offset_x, int win_offset_y)
|
||||||
{
|
{
|
||||||
Fl_RGB_Image *top=0, *left=0, *bottom=0, *right=0;
|
Fl_RGB_Image *top=0, *left=0, *bottom=0, *right=0;
|
||||||
if (win->border() && !win->parent()) {
|
if (win->shown() && win->border() && !win->parent()) {
|
||||||
Fl_Window_Driver::driver(win)->capture_titlebar_and_borders(top, left, bottom, right);
|
Fl_Window_Driver::driver(win)->capture_titlebar_and_borders(top, left, bottom, right);
|
||||||
}
|
}
|
||||||
bool need_push = !is_current();
|
bool need_push = !is_current();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// macOS-Cocoa specific code for the Fast Light Tool Kit (FLTK).
|
// macOS-Cocoa specific code for the Fast Light Tool Kit (FLTK).
|
||||||
//
|
//
|
||||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
// Copyright 1998-2024 by Bill Spitzak and others.
|
||||||
//
|
//
|
||||||
// This library is free software. Distribution and use rights are outlined in
|
// 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
|
// the file "COPYING" which should have been included with this file. If this
|
||||||
@@ -49,6 +49,9 @@ extern "C" {
|
|||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_15_0
|
||||||
|
# import <ScreenCaptureKit/ScreenCaptureKit.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define DEBUG_SELECT // UNCOMMENT FOR SELECT()/THREAD DEBUGGING
|
// #define DEBUG_SELECT // UNCOMMENT FOR SELECT()/THREAD DEBUGGING
|
||||||
#ifdef DEBUG_SELECT
|
#ifdef DEBUG_SELECT
|
||||||
@@ -4607,20 +4610,85 @@ int Fl_Cocoa_Window_Driver::decorated_h()
|
|||||||
return h() + bt/s;
|
return h() + bt/s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_15_0
|
||||||
|
|
||||||
|
// Requires -framework ScreenCaptureKit and used by FLTK for macOS ≥ 15.0
|
||||||
|
static CGImageRef capture_titlebar_macOS15(NSWindow *nswin) {
|
||||||
|
__block CGImageRef capture = NULL;
|
||||||
|
__block BOOL capture_err = NO;
|
||||||
|
void (^block_to_stop_main_loop)(void) = ^{ CFRunLoopStop(CFRunLoopGetMain()); };
|
||||||
|
CGWindowID target_id = [nswin windowNumber];
|
||||||
|
NSRect r = [nswin frame];
|
||||||
|
int W = r.size.width, H = r.size.height;
|
||||||
|
[SCShareableContent getCurrentProcessShareableContentWithCompletionHandler: // macOS 14.4
|
||||||
|
^(SCShareableContent *shareableContent, NSError *error) {
|
||||||
|
SCWindow *scwin = nil;
|
||||||
|
if (!error) {
|
||||||
|
NSEnumerator *enumerator = [[shareableContent windows] objectEnumerator];
|
||||||
|
while ((scwin = (SCWindow*)[enumerator nextObject]) != nil) {
|
||||||
|
if ([scwin windowID] == target_id) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!scwin) {
|
||||||
|
capture_err = YES;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), block_to_stop_main_loop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SCContentFilter *filter = [[[SCContentFilter alloc] initWithDesktopIndependentWindow:scwin] autorelease];
|
||||||
|
int s = (int)[filter pointPixelScale];
|
||||||
|
SCStreamConfiguration *config = [[[SCStreamConfiguration alloc] init] autorelease];
|
||||||
|
[config setIgnoreShadowsSingleWindow:YES];
|
||||||
|
[config setWidth:W*s];
|
||||||
|
[config setHeight:H*s];
|
||||||
|
[config setIncludeChildWindows:NO]; // macOS 14.2
|
||||||
|
[SCScreenshotManager captureImageWithFilter:filter
|
||||||
|
configuration:config
|
||||||
|
completionHandler:^(CGImageRef sampleBuffer, NSError *error) {
|
||||||
|
if (error) capture_err = YES;
|
||||||
|
else {
|
||||||
|
capture = sampleBuffer;
|
||||||
|
CGImageRetain(capture);
|
||||||
|
}
|
||||||
|
dispatch_async(dispatch_get_main_queue(), block_to_stop_main_loop);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
// run the main loop until the 1 or 2 blocks above have finished and have stopped the loop
|
||||||
|
while (!capture_err && !capture) CFRunLoopRun();
|
||||||
|
if (capture_err) return NULL;
|
||||||
|
int bt = [nswin frame].size.height - [[nswin contentView] frame].size.height;
|
||||||
|
int s = CGImageGetWidth(capture) / W;
|
||||||
|
CGRect cgr = CGRectMake(0, 0, W * s, bt * s);
|
||||||
|
CGImageRef title_bar = CGImageCreateWithImageInRect(capture, cgr);
|
||||||
|
CGImageRelease(capture);
|
||||||
|
return title_bar;
|
||||||
|
}
|
||||||
|
#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_15_0
|
||||||
|
|
||||||
|
|
||||||
void Fl_Cocoa_Window_Driver::draw_titlebar_to_context(CGContextRef gc, int w, int h)
|
void Fl_Cocoa_Window_Driver::draw_titlebar_to_context(CGContextRef gc, int w, int h)
|
||||||
{
|
{
|
||||||
FLWindow *nswin = fl_xid(pWindow);
|
FLWindow *nswin = fl_xid(pWindow);
|
||||||
if ([nswin canBecomeMainWindow]) [nswin makeMainWindow];
|
if ([nswin canBecomeMainWindow]) [nswin makeMainWindow];
|
||||||
[NSApp nextEventMatchingMask:NSEventMaskAny untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO];
|
[NSApp nextEventMatchingMask:NSEventMaskAny untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO];
|
||||||
CGImageRef img;
|
CGImageRef img = NULL;
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||||
if (fl_mac_os_version >= 100600) { // verified OK from 10.6
|
# if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_15_0
|
||||||
|
if (fl_mac_os_version >= 150000) img = capture_titlebar_macOS15(nswin);
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
if (fl_mac_os_version >= 100600) { // verified OK from 10.6
|
||||||
NSInteger win_id = [nswin windowNumber];
|
NSInteger win_id = [nswin windowNumber];
|
||||||
CFArrayRef array = CFArrayCreate(NULL, (const void**)&win_id, 1, NULL);
|
CFArrayRef array = CFArrayCreate(NULL, (const void**)&win_id, 1, NULL);
|
||||||
CGRect rr = NSRectToCGRect([nswin frame]);
|
CGRect rr = NSRectToCGRect([nswin frame]);
|
||||||
rr.origin.y = CGDisplayBounds(CGMainDisplayID()).size.height - (rr.origin.y + rr.size.height);
|
rr.origin.y = CGDisplayBounds(CGMainDisplayID()).size.height - (rr.origin.y + rr.size.height);
|
||||||
rr.size.height = h;
|
rr.size.height = h;
|
||||||
|
# if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_15_0
|
||||||
img = CGWindowListCreateImageFromArray(rr, array, kCGWindowImageBoundsIgnoreFraming); // 10.5
|
img = CGWindowListCreateImageFromArray(rr, array, kCGWindowImageBoundsIgnoreFraming); // 10.5
|
||||||
|
# endif
|
||||||
CFRelease(array);
|
CFRelease(array);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user