Problems on M1 Mac

I haven’t tried using shaders yet but I have also experienced some problems switching from Intel Mac (MacOS 10.9) to M1 Mac (MacOS 14.6, Python 3.12).

Most severely a crash when switching from “pseudo fullscreen” or “desktop fullscreen” (don’t know how you call it) to fullscreen.
I mean the mode that is activated when clicking the green button in the title bar. It used to be “maximize” or “zoom” but now it says “enter fullscreen”. When you activate that and then tell panda to switch to fullscreen the program crashes.

To replicate (a simple “hello world” program that accepts “f” to enter/exit fullscreen):

from direct.showbase.ShowBase import ShowBase
from panda3d import core

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.accept("f", self.toggle_fullscreen, [])

    def toggle_fullscreen(self):
        isFullscreen = self.win.getProperties().getFullscreen()
        print(f"Fullscreen {isFullscreen}")
        window_props = core.WindowProperties()
        if not isFullscreen:
            window_props.setFullscreen(True)
        else:
            window_props.setFullscreen(False)
        self.win.requestProperties(window_props)

app = MyApp()
app.run()

Crash report:

Process:               Python [1253]
Path:                  /opt/local/Library/Frameworks/Python.framework/Versions/3.12/Resources/Python.app/Contents/MacOS/Python
Identifier:            org.python.python
Version:               3.12.5 (3.12.5)
Code Type:             ARM-64 (Native)
Parent Process:        zsh [1248]
Responsible:           Terminal [900]
User ID:               502

Date/Time:             2024-09-05 22:13:07.0314 +0200
OS Version:            macOS 14.6.1 (23G93)
Report Version:        12
Anonymous UUID:        


Time Awake Since Boot: 4200 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Termination Reason:    Namespace SIGNAL, Code 6 Abort trap: 6
Terminating Process:   Python [1253]

Application Specific Information:
abort() called


Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x19adf55f0 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x19ae2dc20 pthread_kill + 288
2   libsystem_c.dylib             	       0x19ad3aa30 abort + 180
3   libc++abi.dylib               	       0x19ade4d08 abort_message + 132
4   libc++abi.dylib               	       0x19add4fc0 demangling_terminate_handler() + 348
5   libobjc.A.dylib               	       0x19aa6fbf0 _objc_terminate() + 144
6   libc++abi.dylib               	       0x19ade40cc std::__terminate(void (*)()) + 16
7   libc++abi.dylib               	       0x19ade75f8 __cxa_rethrow + 204
8   libobjc.A.dylib               	       0x19aa8b2c4 objc_exception_rethrow + 44
9   AppKit                        	       0x19e7ad920 NSPerformVisuallyAtomicChange + 144
10  AppKit                        	       0x19e7ad7dc -[NSWindow setStyleMask:] + 176
11  libpandagl.dylib              	       0x104a97324 CocoaGraphicsWindow::set_properties_now(WindowProperties&) + 400
12  libpanda.1.10.dylib           	       0x10355c06c GraphicsWindow::process_events() + 164
13  libpandagl.dylib              	       0x104a952fc CocoaGraphicsWindow::process_events() + 40
14  libpanda.1.10.dylib           	       0x10353c570 GraphicsEngine::WindowRenderer::do_frame(GraphicsEngine*, Thread*) + 704
15  libpanda.1.10.dylib           	       0x10353aea0 GraphicsEngine::render_frame() + 1988
16  core.cpython-312-darwin.so    	       0x104f3016c Dtool_GraphicsEngine_render_frame_516(_object*, _object*) + 72
17  Python                        	       0x102daae40 _PyEval_EvalFrameDefault + 49756
18  Python                        	       0x102cb81cc method_vectorcall + 184
19  core.cpython-312-darwin.so    	       0x105270b14 PythonThread::call_python_func(_object*, _object*) + 196
20  core.cpython-312-darwin.so    	       0x105275998 PythonTask::do_python_task() + 456
21  core.cpython-312-darwin.so    	       0x1052757b4 PythonTask::do_task() + 32
22  libpanda.1.10.dylib           	       0x103573890 AsyncTask::unlock_and_do_task() + 304
23  libpanda.1.10.dylib           	       0x1035775f4 AsyncTaskChain::service_one_task(AsyncTaskChain::AsyncTaskChainThread*) + 508
24  libpanda.1.10.dylib           	       0x10357682c AsyncTaskChain::do_poll() + 428
25  libpanda.1.10.dylib           	       0x10357d6a0 AsyncTaskManager::poll() + 68
26  core.cpython-312-darwin.so    	       0x104f5e1b4 Dtool_AsyncTaskManager_poll_138(_object*, _object*) + 60
27  Python                        	       0x102daae40 _PyEval_EvalFrameDefault + 49756
28  Python                        	       0x102d9e974 PyEval_EvalCode + 184
29  Python                        	       0x102dffcd8 run_eval_code_obj + 88
30  Python                        	       0x102dfdd70 run_mod + 132
31  Python                        	       0x102dfd280 pyrun_file + 156
32  Python                        	       0x102dfc660 _PyRun_SimpleFileObject + 288
33  Python                        	       0x102dfc2ac _PyRun_AnyFileObject + 80
34  Python                        	       0x102e20ff4 pymain_run_file_obj + 164
35  Python                        	       0x102e20d6c pymain_run_file + 72
36  Python                        	       0x102e202f8 Py_RunMain + 764
37  Python                        	       0x102e207e8 pymain_main + 304
38  Python                        	       0x102e20888 Py_BytesMain + 40
39  dyld                          	       0x19aaa3154 start + 2476

Hi, welcome to the forums!

I split off your posts to a new thread since they were not directly related to the original thread.

I can reproduce your problems with switching to fullscreen while macOS’ own fullscreen mode is active. I have checked in some fixes to Git, the next Panda release will not have these problems.

Panda’s fullscreen doesn’t play well with macOS’ fullscreen, so I made a change so that it will switch out of macOS’ fullscreen mode when switching to Panda’s fullscreen mode.

Maybe in the future we can think about how to better integrate these different fullscreen modes. Perhaps we should just use macOS’ fullscreen mode on versions that support it, if we can make the resolution switching work right.

Thank you for reporting this issue!

1 Like

Thank you for looking into this!
The problem is Panda knows only 3 window modes: windowed, minimized and fullscreen.
For comparison, in Godot there are 5:
WindowMode WINDOW_MODE_WINDOWED = 0
WindowMode WINDOW_MODE_MINIMIZED = 1
WindowMode WINDOW_MODE_MAXIMIZED = 2
WindowMode WINDOW_MODE_FULLSCREEN = 3
WindowMode WINDOW_MODE_EXCLUSIVE_FULLSCREEN = 4
(DisplayServer — Godot Engine (stable) documentation in English)

Another problem with this ‘non exclusive fullscreen’ mode is that the system mouse cursor remains hidden (in case you have your own mouse cursor like most games do) when you hit the upper edge of the screen which brings up the menu bar.

So, then there is no mouse cursor. I worked around it by temporarily unhiding the system cursor in this case:

    def hide_system_cursor(self, do_hide):
        window_props = core.WindowProperties()
        window_props.setCursorHidden(do_hide)
        self.win.requestProperties(window_props)
    
    def unhide_system_cursor_temporarily_on_top_screen_edge(self, mouse_y):
        """ check if mouse is at the top edge of the screen in 'non exclusive
        fullscreen mode'.
        On MacOS, make the system cursor reappear for a period of time
        so that the now active menu bar and title bar can be used
        Todo: What about Linux, Windows?
        """
        props = self.win.getProperties()
        if (not props.getFullscreen()
            and self.pipe.get_display_width() == props.getXSize()
            and self.pipe.get_display_height() == props.getYSize()
            and mouse_y > 1 - 2/props.getYSize()):
            pf = platform.system()
            if pf == "Darwin":
                if props.getCursorHidden():
                    self.hide_system_cursor(False)
                    self.taskMgr.doMethodLater(7.0, self.hide_system_cursor,
                        'Hide_System_Cursor', extraArgs=[True])
  
1 Like

Does Godot map one of those to macOS’ native fullscreen mode?

Usually, the difference between non-exclusive and exclusive fullscreen mode is that the non-exclusive one is really just a screen-filling undecorated window, which you can do with the undecorated window property. It doesn’t necessarily have anything to do with macOS’ own fullscreen mode.

Hm, I actually don’t use Godot. Maybe, there’s something here:
https://github.com/godotengine/godot/blob/master/platform/macos/display_server_macos.mm

Possibly, these lines address the problem with the mouse cursor:

	if (borderless_full) {
		// If the window covers up the screen set the level to above the main menu and hide on deactivate.
		[(NSWindow *)p_wd.window_object setLevel:NSMainMenuWindowLevel + 1];
		[(NSWindow *)p_wd.window_object setHidesOnDeactivate:YES];

But if that means that the menu bar is suppressed completely (the window is always above the menu bar), then I don’t think it is a good solution.

Anyway, i think it’s important to be able to query which of these 5 modes are active when switching to and from fullscreen because when going fullscreen → windowed one doesn’t want to restore the window to either maximized or “borderless fullscreen” mode but to the original window size. But I noticed there is now (in 1.10.11) a method getMaximized() in addition to getMinimized() and getFullscreen() for the window properties. I think this is good enough since

   props = self.win.get_properties()
   not props.getFullscreen()
   and self.pipe.get_display_width() == props.getXSize()
   and self.pipe.get_display_height() == props.getYSize()

seems to be a suitable test for this “non exclusive” or borderless fullscreen mode.