diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 02fac05160..225ad18a3c 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -99,10 +99,13 @@ PACKAGE_DATA_DIRS = { # Some dependencies have extra directories that need to be scanned for DLLs. # This dictionary maps wheel basenames (ie. the part of the .whl basename -# before the first hyphen) to a list of directories inside the .whl. +# before the first hyphen) to a list of tuples, the first value being the +# directory inside the wheel, the second being which wheel to look in (or +# None to look in its own wheel). PACKAGE_LIB_DIRS = { - 'scipy': ['scipy/extra-dll'], + 'scipy': [('scipy/extra-dll', None)], + 'PyQt5': [('PyQt5/Qt5/bin', 'PyQt5_Qt5')], } SITE_PY = u""" @@ -610,6 +613,12 @@ class build_apps(setuptools.Command): # by default. Switch it up if FMOD is not included. if value not in self.plugins and value == 'p3fmod_audio' and 'p3openal_audio' in self.plugins: self.warn("Missing audio plugin p3fmod_audio referenced in PRC data, replacing with p3openal_audio") + value = 'p3openal_audio' + + if var == 'aux-display': + # Silently remove aux-display lines for missing plugins. + if value not in self.plugins: + continue for plugin in check_plugins: if plugin in value and plugin not in self.plugins: @@ -662,8 +671,13 @@ class build_apps(setuptools.Command): # Also look for more specific per-package cases, defined in # PACKAGE_LIB_DIRS at the top of this file. extra_dirs = PACKAGE_LIB_DIRS.get(whl_name, []) - for extra_dir in extra_dirs: - search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep))) + for extra_dir, search_in in extra_dirs: + if not search_in: + search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep))) + else: + for whl2 in wheelpaths: + if os.path.basename(whl2).startswith(search_in + '-'): + search_path.append(os.path.join(whl2, extra_dir.replace('/', os.path.sep))) return search_path diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index d10a4d9026..02fc2d082c 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -404,6 +404,7 @@ class WheelFile(object): # Now add dependencies. On macOS, fix @loader_path references. if sys.platform == "darwin": + is_unsigned = subprocess.call(['codesign', '-d', temp.name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if source_path.endswith('deploy-stubw'): deps_path = '@executable_path/../Frameworks' else: @@ -452,9 +453,15 @@ class WheelFile(object): subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name]) remove_signature = True - # Remove the codesign signature if we modified the library. - if remove_signature: + # Replace the codesign signature if we modified the library. + if self.platform.endswith("_arm64") and (is_unsigned or remove_signature): + subprocess.call(["codesign", "-f", "-s", "-", temp.name]) + elif remove_signature and not is_unsigned: + if GetVerbose(): + print("Removing code signature from {0}".format(source_path)) subprocess.call(["codesign", "--remove-signature", temp.name]) + if self.platform.endswith("_universal2"): + subprocess.call(["codesign", "-a", "arm64", "-s", "-", temp.name]) else: # On other unixes, we just add dependencies normally. for dep in deps: diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.h b/panda/src/cocoadisplay/cocoaGraphicsWindow.h index 092696442a..711e6e4f27 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.h +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.h @@ -68,7 +68,7 @@ protected: virtual void close_window(); virtual bool open_window(); - CGDisplayModeRef find_display_mode(int width, int height); + CFMutableArrayRef find_display_modes(int width, int height); bool do_switch_fullscreen(CGDisplayModeRef mode); virtual void mouse_mode_absolute(); diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index 8fffdbefc5..4ea10a76f4 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -628,18 +628,32 @@ open_window() { if (_properties.get_fullscreen()) { // Change the display mode. - CGDisplayModeRef mode; - mode = find_display_mode(_properties.get_x_size(), - _properties.get_y_size()); + CFMutableArrayRef modes; - if (mode == NULL) { + modes = find_display_modes(_properties.get_x_size(), + _properties.get_y_size()); + + if (CFArrayGetCount(modes) > 0) { + bool switched = false; + for (CFIndex i = 0; i < CFArrayGetCount(modes); i++) { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (do_switch_fullscreen(mode)) { + switched = true; + break; + } + } + CFRelease(modes); + + if (!switched) { + cocoadisplay_cat.error() + << "Failed to change display mode.\n"; + return false; + } + + } else { cocoadisplay_cat.error() << "Could not find a suitable display mode!\n"; - return false; - - } else if (!do_switch_fullscreen(mode)) { - cocoadisplay_cat.error() - << "Failed to change display mode.\n"; + CFRelease(modes); return false; } } @@ -787,38 +801,48 @@ set_properties_now(WindowProperties &properties) { height = _properties.get_y_size(); } - CGDisplayModeRef mode; - mode = find_display_mode(width, height); + CFMutableArrayRef modes = find_display_modes(width, height); - if (mode == NULL) { + if (CFArrayGetCount(modes) > 0) { + bool switched = false; + for (CFIndex i = 0; i < CFArrayGetCount(modes); i++) { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (do_switch_fullscreen(mode)) { + switched = true; + break; + } + } + + if (switched) { + if (_window != nil) { + // For some reason, setting the style mask makes it give up its + // first-responder status. + if ([_window respondsToSelector:@selector(setStyleMask:)]) { + [_window setStyleMask:NSBorderlessWindowMask]; + } + [_window makeFirstResponder:_view]; + [_window setLevel:NSMainMenuWindowLevel+1]; + [_window makeKeyAndOrderFront:nil]; + } + + // We've already set the size property this way; clear it. + properties.clear_size(); + _properties.set_size(width, height); + properties.clear_origin(); + _properties.set_origin(0, 0); + properties.clear_fullscreen(); + _properties.set_fullscreen(true); + + } else { + cocoadisplay_cat.error() + << "Failed to change display mode.\n"; + } + } else { cocoadisplay_cat.error() << "Could not find a suitable display mode with size " << width << "x" << height << "!\n"; - - } else if (do_switch_fullscreen(mode)) { - if (_window != nil) { - // For some reason, setting the style mask makes it give up its - // first-responder status. - if ([_window respondsToSelector:@selector(setStyleMask:)]) { - [_window setStyleMask:NSBorderlessWindowMask]; - } - [_window makeFirstResponder:_view]; - [_window setLevel:NSMainMenuWindowLevel+1]; - [_window makeKeyAndOrderFront:nil]; - } - - // We've already set the size property this way; clear it. - properties.clear_size(); - _properties.set_size(width, height); - properties.clear_origin(); - _properties.set_origin(0, 0); - properties.clear_fullscreen(); - _properties.set_fullscreen(true); - - } else { - cocoadisplay_cat.error() - << "Failed to change display mode.\n"; } + CFRelease(modes); } else { do_switch_fullscreen(NULL); @@ -864,22 +888,33 @@ set_properties_now(WindowProperties &properties) { properties.clear_size(); } else { - CGDisplayModeRef mode = find_display_mode(width, height); + CFMutableArrayRef modes = find_display_modes(width, height); - if (mode == NULL) { - cocoadisplay_cat.error() - << "Could not find a suitable display mode with size " << width - << "x" << height << "!\n"; + if (CFArrayGetCount(modes) > 0) { + bool switched = false; + for (CFIndex i = 0; i < CFArrayGetCount(modes); i++) { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (do_switch_fullscreen(mode)) { + switched = true; + break; + } + } - } else if (do_switch_fullscreen(mode)) { - // Yay! Our resolution has changed. - _properties.set_size(width, height); - properties.clear_size(); + if (switched) { + // Yay! Our resolution has changed. + _properties.set_size(width, height); + properties.clear_size(); + } else { + cocoadisplay_cat.error() + << "Failed to change display mode.\n"; + } } else { cocoadisplay_cat.error() - << "Failed to change display mode.\n"; + << "Could not find a suitable display mode with size " << width + << "x" << height << "!\n"; } + CFRelease(modes); } } @@ -1101,8 +1136,8 @@ set_properties_now(WindowProperties &properties) { * Returns an appropriate CGDisplayModeRef for the given width and height, or * NULL if none was found. */ -CGDisplayModeRef CocoaGraphicsWindow:: -find_display_mode(int width, int height) { +CFMutableArrayRef CocoaGraphicsWindow:: +find_display_modes(int width, int height) { CFDictionaryRef options = NULL; // On macOS 10.15+ (Catalina), we want to select the display mode with the // samescaling factor as the current view to avoid cropping or scaling issues. @@ -1122,6 +1157,9 @@ find_display_mode(int width, int height) { &kCFTypeDictionaryValueCallBacks); } #endif + CFMutableArrayRef valid_modes; + valid_modes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, options); if (options != NULL) { CFRelease(options); @@ -1141,7 +1179,9 @@ find_display_mode(int width, int height) { if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_14 && CGDisplayModeGetWidth(mode) == width && CGDisplayModeGetHeight(mode) == height) { - return mode; + CFArrayAppendValue(valid_modes, mode); + CGDisplayModeRelease(mode); + return valid_modes; } current_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); @@ -1172,17 +1212,14 @@ find_display_mode(int width, int height) { #endif CFStringCompare(pixel_encoding, current_pixel_encoding, 0) == kCFCompareEqualTo) { - CFRetain(mode); - CFRelease(pixel_encoding); - CFRelease(current_pixel_encoding); - CFRelease(modes); - return mode; + CFArrayAppendValue(valid_modes, mode); } + CFRelease(pixel_encoding); } CFRelease(current_pixel_encoding); CFRelease(modes); - return NULL; + return valid_modes; } /** diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 51d97068a8..1cb4e8f3d1 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -302,32 +302,34 @@ set_properties_now(WindowProperties &properties) { // When switching undecorated mode, Windows will keep the window at the // current outer size, whereas we want to keep it with the configured // inner size. Store the current size and origin. - LPoint2i top_left = _properties.get_origin(); - LPoint2i bottom_right = top_left + _properties.get_size(); + if (_parent_window_handle == nullptr) { + LPoint2i top_left = _properties.get_origin(); + LPoint2i bottom_right = top_left + _properties.get_size(); - DWORD window_style = make_style(_properties); - DWORD current_style = GetWindowLong(_hWnd, GWL_STYLE); - SetWindowLong(_hWnd, GWL_STYLE, window_style); + DWORD window_style = make_style(_properties); + DWORD current_style = GetWindowLong(_hWnd, GWL_STYLE); + SetWindowLong(_hWnd, GWL_STYLE, window_style); - // If we switched to/from undecorated, calculate the new size. - if (((window_style ^ current_style) & WS_CAPTION) != 0) { - RECT view_rect; - SetRect(&view_rect, top_left[0], top_left[1], - bottom_right[0], bottom_right[1]); - WINDOWINFO wi; - GetWindowInfo(_hWnd, &wi); - AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle); + // If we switched to/from undecorated, calculate the new size. + if (((window_style ^ current_style) & WS_CAPTION) != 0) { + RECT view_rect; + SetRect(&view_rect, top_left[0], top_left[1], + bottom_right[0], bottom_right[1]); + WINDOWINFO wi; + GetWindowInfo(_hWnd, &wi); + AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle); - SetWindowPos(_hWnd, HWND_NOTOPMOST, view_rect.left, view_rect.top, - view_rect.right - view_rect.left, - view_rect.bottom - view_rect.top, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | - SWP_NOSENDCHANGING | SWP_SHOWWINDOW); - } else { - // We need to call this to ensure that the style change takes effect. - SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | - SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_SHOWWINDOW); + SetWindowPos(_hWnd, HWND_NOTOPMOST, view_rect.left, view_rect.top, + view_rect.right - view_rect.left, + view_rect.bottom - view_rect.top, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | + SWP_NOSENDCHANGING | SWP_SHOWWINDOW); + } else { + // We need to call this to ensure that the style change takes effect. + SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | + SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_SHOWWINDOW); + } } } @@ -464,7 +466,9 @@ set_properties_now(WindowProperties &properties) { // Fall through case WindowProperties::M_confined: - if (confine_cursor()) { + // If we are not the foreground window, we defer confining the cursor + // until we are. + if (GetForegroundWindow() != _hWnd || confine_cursor()) { _properties.set_mouse_mode(properties.get_mouse_mode()); } break; @@ -505,6 +509,11 @@ close_window() { set_cursor_out_of_window(); DestroyWindow(_hWnd); + if (_properties.has_mouse_mode() && + _properties.get_mouse_mode() != WindowProperties::M_absolute) { + ClipCursor(nullptr); + } + if (is_fullscreen()) { // revert to default display mode. do_fullscreen_disable(); @@ -797,7 +806,7 @@ do_reshape_request(int x_origin, int y_origin, bool has_origin, GetWindowInfo(_hWnd, &wi); AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle); - UINT flags = SWP_NOZORDER | SWP_NOSENDCHANGING; + UINT flags = SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE; if (has_origin) { x_origin = view_rect.left; @@ -813,12 +822,6 @@ do_reshape_request(int x_origin, int y_origin, bool has_origin, view_rect.bottom - view_rect.top, flags); - // If we are in confined mode, we must update the clip region. - if (_properties.has_mouse_mode() && - _properties.get_mouse_mode() == WindowProperties::M_confined) { - confine_cursor(); - } - handle_reshape(); return true; } @@ -868,6 +871,28 @@ handle_reshape() { return; } + // If we are in confined mode, we must update the clip region. However, + // we ony do that if the cursor in currently inside the window, to properly + // handle the case where someone is resizing the window straight after + // switching to it (you can do this if you press the start menu key to + // deactive the window, and then trying to resize it) + if (_properties.has_mouse_mode() && + _properties.get_mouse_mode() != WindowProperties::M_absolute && + _hWnd == GetForegroundWindow()) { + + POINT cpos; + if (GetCursorPos(&cpos) && PtInRect(&view_rect, cpos)) { + windisplay_cat.info() + << "ClipCursor() to " << view_rect.left << "," << view_rect.top + << " to " << view_rect.right << "," << view_rect.bottom << endl; + + if (!ClipCursor(&view_rect)) { + windisplay_cat.warning() + << "Failed to re-confine cursor to window.\n"; + } + } + } + WindowProperties properties; properties.set_size((view_rect.right - view_rect.left), (view_rect.bottom - view_rect.top)); @@ -1008,7 +1033,7 @@ do_windowed_switch() { // If we had a confined cursor, we must reconfine it now. if (_properties.has_mouse_mode() && - _properties.get_mouse_mode() == WindowProperties::M_confined) { + _properties.get_mouse_mode() != WindowProperties::M_absolute) { confine_cursor(); } @@ -1049,12 +1074,12 @@ make_style(const WindowProperties &properties) { if (properties.get_fullscreen()) { window_style |= WS_POPUP | WS_SYSMENU; - } else { - if (_parent_window_handle) { - window_style |= WS_CHILD; - } else { - window_style |= WS_POPUP; - } + } + else if (_parent_window_handle) { + window_style |= WS_CHILD; + } + else { + window_style |= WS_POPUP; if (!properties.get_undecorated()) { window_style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); @@ -1585,7 +1610,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // If we had a confined cursor, we must reconfine it upon activation. if (_properties.has_mouse_mode() && - _properties.get_mouse_mode() == WindowProperties::M_confined) { + _properties.get_mouse_mode() != WindowProperties::M_absolute) { if (!confine_cursor()) { properties.set_mouse_mode(WindowProperties::M_absolute); } @@ -1631,7 +1656,7 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // If we had a confined cursor, we must reconfine it upon a resize. if (_properties.has_mouse_mode() && - _properties.get_mouse_mode() == WindowProperties::M_confined) { + _properties.get_mouse_mode() != WindowProperties::M_absolute) { confine_cursor(); } break;