|
50 | 50 | #include "main/main.h" |
51 | 51 | #include "scene/resources/image_texture.h" |
52 | 52 |
|
| 53 | +#include <AppKit/AppKit.h> |
| 54 | + |
53 | 55 | #if defined(GLES3_ENABLED) |
54 | 56 | #include "drivers/gles3/rasterizer_gles3.h" |
55 | 57 | #endif |
|
1609 | 1611 | } |
1610 | 1612 |
|
1611 | 1613 | Color DisplayServerMacOS::screen_get_pixel(const Point2i &p_position) const { |
1612 | | - Point2i position = p_position; |
1613 | | - // macOS native y-coordinate relative to _get_screens_origin() is negative, |
1614 | | - // Godot passes a positive value. |
1615 | | - position.y *= -1; |
1616 | | - position += _get_screens_origin(); |
| 1614 | + HashSet<CGWindowID> exclude_windows; |
| 1615 | + for (HashMap<WindowID, WindowData>::ConstIterator E = windows.begin(); E; ++E) { |
| 1616 | + if (E->value.hide_from_capture) { |
| 1617 | + exclude_windows.insert([E->value.window_object windowNumber]); |
| 1618 | + } |
| 1619 | + } |
| 1620 | + |
| 1621 | + CFArrayRef on_screen_windows = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); |
| 1622 | + CFMutableArrayRef capture_windows = CFArrayCreateMutableCopy(nullptr, 0, on_screen_windows); |
| 1623 | + for (long i = CFArrayGetCount(on_screen_windows) - 1; i >= 0; i--) { |
| 1624 | + CGWindowID window = (CGWindowID)(uintptr_t)CFArrayGetValueAtIndex(capture_windows, i); |
| 1625 | + if (exclude_windows.has(window)) { |
| 1626 | + CFArrayRemoveValueAtIndex(capture_windows, i); |
| 1627 | + } |
| 1628 | + } |
| 1629 | + |
| 1630 | + Point2i position = p_position - Vector2i(1, 1); |
| 1631 | + position -= screen_get_position(0); // Note: coordinates where the screen origin is in the upper-left corner of the main display and y-axis values increase downward. |
1617 | 1632 | position /= screen_get_max_scale(); |
1618 | 1633 |
|
1619 | 1634 | Color color; |
1620 | | - for (NSScreen *screen in [NSScreen screens]) { |
1621 | | - NSRect frame = [screen frame]; |
1622 | | - if (NSMouseInRect(NSMakePoint(position.x, position.y), frame, NO)) { |
1623 | | - NSDictionary *screenDescription = [screen deviceDescription]; |
1624 | | - CGDirectDisplayID display_id = [[screenDescription objectForKey:@"NSScreenNumber"] unsignedIntValue]; |
1625 | | - CGImageRef image = CGDisplayCreateImageForRect(display_id, CGRectMake(position.x - frame.origin.x, frame.size.height - (position.y - frame.origin.y), 1, 1)); |
1626 | | - if (image) { |
1627 | | - CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); |
1628 | | - if (color_space) { |
1629 | | - uint8_t img_data[4]; |
1630 | | - CGContextRef context = CGBitmapContextCreate(img_data, 1, 1, 8, 4, color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); |
1631 | | - if (context) { |
1632 | | - CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), image); |
1633 | | - color = Color(img_data[0] / 255.0f, img_data[1] / 255.0f, img_data[2] / 255.0f, img_data[3] / 255.0f); |
1634 | | - CGContextRelease(context); |
1635 | | - } |
1636 | | - CGColorSpaceRelease(color_space); |
1637 | | - } |
1638 | | - CGImageRelease(image); |
| 1635 | + CGImageRef image = CGWindowListCreateImageFromArray(CGRectMake(position.x, position.y, 1, 1), capture_windows, kCGWindowListOptionAll); |
| 1636 | + if (image) { |
| 1637 | + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); |
| 1638 | + if (color_space) { |
| 1639 | + uint8_t img_data[4]; |
| 1640 | + CGContextRef context = CGBitmapContextCreate(img_data, 1, 1, 8, 4, color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); |
| 1641 | + if (context) { |
| 1642 | + CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), image); |
| 1643 | + color = Color(img_data[0] / 255.0f, img_data[1] / 255.0f, img_data[2] / 255.0f, img_data[3] / 255.0f); |
| 1644 | + CGContextRelease(context); |
1639 | 1645 | } |
| 1646 | + CGColorSpaceRelease(color_space); |
1640 | 1647 | } |
| 1648 | + CGImageRelease(image); |
1641 | 1649 | } |
1642 | 1650 | return color; |
1643 | 1651 | } |
1644 | 1652 |
|
1645 | 1653 | Ref<Image> DisplayServerMacOS::screen_get_image(int p_screen) const { |
1646 | 1654 | ERR_FAIL_INDEX_V(p_screen, get_screen_count(), Ref<Image>()); |
1647 | 1655 |
|
1648 | | - switch (p_screen) { |
1649 | | - case SCREEN_PRIMARY: { |
1650 | | - p_screen = get_primary_screen(); |
1651 | | - } break; |
1652 | | - case SCREEN_OF_MAIN_WINDOW: { |
1653 | | - p_screen = window_get_current_screen(MAIN_WINDOW_ID); |
1654 | | - } break; |
1655 | | - default: |
1656 | | - break; |
| 1656 | + HashSet<CGWindowID> exclude_windows; |
| 1657 | + for (HashMap<WindowID, WindowData>::ConstIterator E = windows.begin(); E; ++E) { |
| 1658 | + if (E->value.hide_from_capture) { |
| 1659 | + exclude_windows.insert([E->value.window_object windowNumber]); |
| 1660 | + } |
1657 | 1661 | } |
1658 | 1662 |
|
| 1663 | + CFArrayRef on_screen_windows = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); |
| 1664 | + CFMutableArrayRef capture_windows = CFArrayCreateMutableCopy(nullptr, 0, on_screen_windows); |
| 1665 | + for (long i = CFArrayGetCount(on_screen_windows) - 1; i >= 0; i--) { |
| 1666 | + CGWindowID window = (CGWindowID)(uintptr_t)CFArrayGetValueAtIndex(capture_windows, i); |
| 1667 | + if (exclude_windows.has(window)) { |
| 1668 | + CFArrayRemoveValueAtIndex(capture_windows, i); |
| 1669 | + } |
| 1670 | + } |
| 1671 | + |
| 1672 | + Point2i position = screen_get_position(p_screen); |
| 1673 | + position -= screen_get_position(0); // Note: coordinates where the screen origin is in the upper-left corner of the main display and y-axis values increase downward. |
| 1674 | + position /= screen_get_max_scale(); |
| 1675 | + |
| 1676 | + Size2i size = screen_get_size(p_screen); |
| 1677 | + size /= screen_get_max_scale(); |
| 1678 | + |
1659 | 1679 | Ref<Image> img; |
1660 | | - NSArray *screenArray = [NSScreen screens]; |
1661 | | - if ((NSUInteger)p_screen < [screenArray count]) { |
1662 | | - NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; |
1663 | | - NSDictionary *screenDescription = [[screenArray objectAtIndex:p_screen] deviceDescription]; |
1664 | | - CGDirectDisplayID display_id = [[screenDescription objectForKey:@"NSScreenNumber"] unsignedIntValue]; |
1665 | | - CGImageRef image = CGDisplayCreateImageForRect(display_id, CGRectMake(0, 0, nsrect.size.width, nsrect.size.height)); |
1666 | | - if (image) { |
1667 | | - CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); |
1668 | | - if (color_space) { |
1669 | | - NSUInteger width = CGImageGetWidth(image); |
1670 | | - NSUInteger height = CGImageGetHeight(image); |
1671 | | - |
1672 | | - Vector<uint8_t> img_data; |
1673 | | - img_data.resize(height * width * 4); |
1674 | | - CGContextRef context = CGBitmapContextCreate(img_data.ptrw(), width, height, 8, 4 * width, color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); |
1675 | | - if (context) { |
1676 | | - CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); |
1677 | | - img = Image::create_from_data(width, height, false, Image::FORMAT_RGBA8, img_data); |
1678 | | - CGContextRelease(context); |
1679 | | - } |
1680 | | - CGColorSpaceRelease(color_space); |
| 1680 | + CGImageRef image = CGWindowListCreateImageFromArray(CGRectMake(position.x, position.y, size.width, size.height), capture_windows, kCGWindowListOptionAll); |
| 1681 | + if (image) { |
| 1682 | + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); |
| 1683 | + if (color_space) { |
| 1684 | + NSUInteger width = CGImageGetWidth(image); |
| 1685 | + NSUInteger height = CGImageGetHeight(image); |
| 1686 | + |
| 1687 | + Vector<uint8_t> img_data; |
| 1688 | + img_data.resize(height * width * 4); |
| 1689 | + CGContextRef context = CGBitmapContextCreate(img_data.ptrw(), width, height, 8, 4 * width, color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); |
| 1690 | + if (context) { |
| 1691 | + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); |
| 1692 | + img = Image::create_from_data(width, height, false, Image::FORMAT_RGBA8, img_data); |
| 1693 | + CGContextRelease(context); |
| 1694 | + img->resize(screen_get_size(p_screen).x, screen_get_size(p_screen).y, Image::INTERPOLATE_NEAREST); |
1681 | 1695 | } |
1682 | | - CGImageRelease(image); |
| 1696 | + CGColorSpaceRelease(color_space); |
1683 | 1697 | } |
| 1698 | + CGImageRelease(image); |
| 1699 | + } |
| 1700 | + return img; |
| 1701 | +} |
| 1702 | + |
| 1703 | +Ref<Image> DisplayServerMacOS::screen_get_image_rect(const Rect2i &p_rect) const { |
| 1704 | + HashSet<CGWindowID> exclude_windows; |
| 1705 | + for (HashMap<WindowID, WindowData>::ConstIterator E = windows.begin(); E; ++E) { |
| 1706 | + if (E->value.hide_from_capture) { |
| 1707 | + exclude_windows.insert([E->value.window_object windowNumber]); |
| 1708 | + } |
| 1709 | + } |
| 1710 | + |
| 1711 | + CFArrayRef on_screen_windows = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); |
| 1712 | + CFMutableArrayRef capture_windows = CFArrayCreateMutableCopy(nullptr, 0, on_screen_windows); |
| 1713 | + for (long i = CFArrayGetCount(on_screen_windows) - 1; i >= 0; i--) { |
| 1714 | + CGWindowID window = (CGWindowID)(uintptr_t)CFArrayGetValueAtIndex(capture_windows, i); |
| 1715 | + if (exclude_windows.has(window)) { |
| 1716 | + CFArrayRemoveValueAtIndex(capture_windows, i); |
| 1717 | + } |
| 1718 | + } |
| 1719 | + |
| 1720 | + Point2i position = p_rect.position; |
| 1721 | + position -= screen_get_position(0); // Note: coordinates where the screen origin is in the upper-left corner of the main display and y-axis values increase downward. |
| 1722 | + position /= screen_get_max_scale(); |
| 1723 | + |
| 1724 | + Size2i size = p_rect.size; |
| 1725 | + size /= screen_get_max_scale(); |
| 1726 | + |
| 1727 | + Ref<Image> img; |
| 1728 | + CGImageRef image = CGWindowListCreateImageFromArray(CGRectMake(position.x, position.y, size.width, size.height), capture_windows, kCGWindowListOptionAll); |
| 1729 | + if (image) { |
| 1730 | + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); |
| 1731 | + if (color_space) { |
| 1732 | + NSUInteger width = CGImageGetWidth(image); |
| 1733 | + NSUInteger height = CGImageGetHeight(image); |
| 1734 | + |
| 1735 | + Vector<uint8_t> img_data; |
| 1736 | + img_data.resize_zeroed(height * width * 4); |
| 1737 | + CGContextRef context = CGBitmapContextCreate(img_data.ptrw(), width, height, 8, 4 * width, color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); |
| 1738 | + if (context) { |
| 1739 | + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); |
| 1740 | + img = Image::create_from_data(width, height, false, Image::FORMAT_RGBA8, img_data); |
| 1741 | + CGContextRelease(context); |
| 1742 | + img->resize(p_rect.size.x, p_rect.size.y, Image::INTERPOLATE_NEAREST); |
| 1743 | + } |
| 1744 | + CGColorSpaceRelease(color_space); |
| 1745 | + } |
| 1746 | + CGImageRelease(image); |
1684 | 1747 | } |
1685 | 1748 | return img; |
1686 | 1749 | } |
|
2528 | 2591 | NSWindow *w = wd.window_object; |
2529 | 2592 | w.excludedFromWindowsMenu = wd.is_popup || wd.no_focus; |
2530 | 2593 | } break; |
| 2594 | + case WINDOW_FLAG_EXCLUDE_FROM_CAPTURE: { |
| 2595 | + if (p_enabled) { |
| 2596 | + [wd.window_object setSharingType:NSWindowSharingNone]; |
| 2597 | + } else { |
| 2598 | + [wd.window_object setSharingType:NSWindowSharingReadWrite]; |
| 2599 | + } |
| 2600 | + wd.hide_from_capture = p_enabled; |
| 2601 | + } break; |
2531 | 2602 | case WINDOW_FLAG_MOUSE_PASSTHROUGH: { |
2532 | 2603 | wd.mpass = p_enabled; |
2533 | 2604 | } break; |
|
2573 | 2644 | case WINDOW_FLAG_NO_FOCUS: { |
2574 | 2645 | return wd.no_focus; |
2575 | 2646 | } break; |
| 2647 | + case WINDOW_FLAG_EXCLUDE_FROM_CAPTURE: { |
| 2648 | + return wd.hide_from_capture; |
| 2649 | + } break; |
2576 | 2650 | case WINDOW_FLAG_MOUSE_PASSTHROUGH: { |
2577 | 2651 | return wd.mpass; |
2578 | 2652 | } break; |
|
0 commit comments