diff --git a/SheepShaver/src/Unix/video_x.cpp b/SheepShaver/src/Unix/video_x.cpp index 4e595087..bd5e35b9 100644 --- a/SheepShaver/src/Unix/video_x.cpp +++ b/SheepShaver/src/Unix/video_x.cpp @@ -340,6 +340,14 @@ static bool find_visual_for_depth(int depth) * Open display (window or fullscreen) */ +// Set WM_DELETE_WINDOW protocol on window (preventing it from being destroyed by the WM when clicking on the "close" widget) +static Atom WM_DELETE_WINDOW = (Atom)0; +static void set_window_delete_protocol(Window w) +{ + WM_DELETE_WINDOW = XInternAtom(x_display, "WM_DELETE_WINDOW", false); + XSetWMProtocols(x_display, w, &WM_DELETE_WINDOW, 1); +} + // Wait until window is mapped/unmapped void wait_mapped(Window w) { @@ -392,6 +400,9 @@ static bool open_window(int width, int height) // Set window name XStoreName(x_display, the_win, GetString(STR_WINDOW_TITLE)); + // Set delete protocol property + set_window_delete_protocol(the_win); + // Make window unresizable XSizeHints *hints; if ((hints = XAllocSizeHints()) != NULL) { @@ -1423,6 +1434,14 @@ static void handle_events(void) else if (XCheckTypedEvent(x_display, SelectionClear, &event)) ClipboardSelectionClear(&event.xselectionclear); + // Window "close" widget clicked + else if (XCheckTypedEvent(x_display, ClientMessage, &event)) { + if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) { + ADBKeyDown(0x7f); // Power key + ADBKeyUp(0x7f); + } + } + XDisplayUnlock(); break; }