Browse Source

Implement no-window mode for X11 and MacOS

Bonus: Homogeinize and improve OS::alert() for no-window mode
Pedro J. Estébanez 4 years ago
parent
commit
3ec62c82a3

+ 1 - 1
drivers/unix/os_unix.cpp

@@ -156,7 +156,7 @@ void OS_Unix::finalize_core() {
 
 
 void OS_Unix::alert(const String &p_alert, const String &p_title) {
 void OS_Unix::alert(const String &p_alert, const String &p_title) {
 
 
-	fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
+	fprintf(stderr, "ALERT: %s: %s\n", p_title.utf8().get_data(), p_alert.utf8().get_data());
 }
 }
 
 
 String OS_Unix::get_stdin_string(bool p_block) {
 String OS_Unix::get_stdin_string(bool p_block) {

+ 2 - 2
main/main.cpp

@@ -259,7 +259,7 @@ void Main::print_help(const char *p_binary) {
 	OS::get_singleton()->print("  --resolution <W>x<H>             Request window resolution.\n");
 	OS::get_singleton()->print("  --resolution <W>x<H>             Request window resolution.\n");
 	OS::get_singleton()->print("  --position <X>,<Y>               Request window position.\n");
 	OS::get_singleton()->print("  --position <X>,<Y>               Request window position.\n");
 	OS::get_singleton()->print("  --low-dpi                        Force low-DPI mode (macOS and Windows only).\n");
 	OS::get_singleton()->print("  --low-dpi                        Force low-DPI mode (macOS and Windows only).\n");
-	OS::get_singleton()->print("  --no-window                      Disable window creation (Windows only). Useful together with --script.\n");
+	OS::get_singleton()->print("  --no-window                      Run with invisible window. Useful together with --script.\n");
 	OS::get_singleton()->print("  --enable-vsync-via-compositor    When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
 	OS::get_singleton()->print("  --enable-vsync-via-compositor    When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
 	OS::get_singleton()->print("  --disable-vsync-via-compositor   Disable vsync via the OS' window compositor (Windows only).\n");
 	OS::get_singleton()->print("  --disable-vsync-via-compositor   Disable vsync via the OS' window compositor (Windows only).\n");
 	OS::get_singleton()->print("  --tablet-driver                  Tablet input driver (");
 	OS::get_singleton()->print("  --tablet-driver                  Tablet input driver (");
@@ -609,7 +609,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		} else if (I->get() == "--low-dpi") { // force low DPI (macOS only)
 		} else if (I->get() == "--low-dpi") { // force low DPI (macOS only)
 
 
 			force_lowdpi = true;
 			force_lowdpi = true;
-		} else if (I->get() == "--no-window") { // disable window creation (Windows only)
+		} else if (I->get() == "--no-window") { // run with an invisible window
 
 
 			OS::get_singleton()->set_no_window_mode(true);
 			OS::get_singleton()->set_no_window_mode(true);
 		} else if (I->get() == "--tablet-driver") {
 		} else if (I->get() == "--tablet-driver") {

+ 74 - 7
platform/osx/os_osx.mm

@@ -1606,8 +1606,10 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
 	//[window_object setTitle:[NSString stringWithUTF8String:"GodotEnginies"]];
 	//[window_object setTitle:[NSString stringWithUTF8String:"GodotEnginies"]];
 	[window_object setContentView:window_view];
 	[window_object setContentView:window_view];
 	[window_object setDelegate:window_delegate];
 	[window_object setDelegate:window_delegate];
-	[window_object setAcceptsMouseMovedEvents:YES];
-	[(NSWindow *)window_object center];
+	if (!is_no_window_mode_enabled()) {
+		[window_object setAcceptsMouseMovedEvents:YES];
+		[((NSWindow *)window_object) center];
+	}
 
 
 	[window_object setRestorable:NO];
 	[window_object setRestorable:NO];
 
 
@@ -1689,11 +1691,16 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
 
 
 	set_use_vsync(p_desired.use_vsync);
 	set_use_vsync(p_desired.use_vsync);
 
 
-	[NSApp activateIgnoringOtherApps:YES];
+	if (!is_no_window_mode_enabled()) {
+		[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+		[NSApp activateIgnoringOtherApps:YES];
+	}
 
 
 	_update_window();
 	_update_window();
 
 
-	[window_object makeKeyAndOrderFront:nil];
+	if (!is_no_window_mode_enabled()) {
+		[window_object makeKeyAndOrderFront:nil];
+	}
 
 
 	on_top = p_desired.always_on_top;
 	on_top = p_desired.always_on_top;
 	if (p_desired.always_on_top) {
 	if (p_desired.always_on_top) {
@@ -1773,6 +1780,10 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
 
 
 	update_real_mouse_position();
 	update_real_mouse_position();
 
 
+	if (is_no_window_mode_enabled()) {
+		[NSApp hide:nil];
+	}
+
 	return OK;
 	return OK;
 }
 }
 
 
@@ -1880,6 +1891,11 @@ typedef UnixTerminalLogger OSXTerminalLogger;
 #endif
 #endif
 
 
 void OS_OSX::alert(const String &p_alert, const String &p_title) {
 void OS_OSX::alert(const String &p_alert, const String &p_title) {
+	if (is_no_window_mode_enabled()) {
+		print_line("ALERT: " + p_title + ": " + p_alert);
+		return;
+	}
+
 	// Set OS X-compliant variables
 	// Set OS X-compliant variables
 	NSAlert *window = [[NSAlert alloc] init];
 	NSAlert *window = [[NSAlert alloc] init];
 	NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
 	NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
@@ -2447,6 +2463,10 @@ int OS_OSX::get_current_screen() const {
 };
 };
 
 
 void OS_OSX::set_current_screen(int p_screen) {
 void OS_OSX::set_current_screen(int p_screen) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
+
 	Vector2 wpos = get_window_position() - get_screen_position(get_current_screen());
 	Vector2 wpos = get_window_position() - get_screen_position(get_current_screen());
 	set_window_position(wpos + get_screen_position(p_screen));
 	set_window_position(wpos + get_screen_position(p_screen));
 };
 };
@@ -2593,6 +2613,9 @@ Point2 OS_OSX::get_window_position() const {
 }
 }
 
 
 void OS_OSX::set_native_window_position(const Point2 &p_position) {
 void OS_OSX::set_native_window_position(const Point2 &p_position) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	NSPoint pos;
 	NSPoint pos;
 	float displayScale = get_screen_max_scale();
 	float displayScale = get_screen_max_scale();
@@ -2606,6 +2629,10 @@ void OS_OSX::set_native_window_position(const Point2 &p_position) {
 };
 };
 
 
 void OS_OSX::set_window_position(const Point2 &p_position) {
 void OS_OSX::set_window_position(const Point2 &p_position) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
+
 	Point2 position = p_position;
 	Point2 position = p_position;
 	// OS X native y-coordinate relative to get_screens_origin() is negative,
 	// OS X native y-coordinate relative to get_screens_origin() is negative,
 	// Godot passes a positive value
 	// Godot passes a positive value
@@ -2636,6 +2663,10 @@ Size2 OS_OSX::get_min_window_size() const {
 
 
 void OS_OSX::set_min_window_size(const Size2 p_size) {
 void OS_OSX::set_min_window_size(const Size2 p_size) {
 
 
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
+
 	if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) {
 	if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) {
 		ERR_PRINT("Minimum window size can't be larger than maximum window size!");
 		ERR_PRINT("Minimum window size can't be larger than maximum window size!");
 		return;
 		return;
@@ -2652,6 +2683,10 @@ void OS_OSX::set_min_window_size(const Size2 p_size) {
 
 
 void OS_OSX::set_max_window_size(const Size2 p_size) {
 void OS_OSX::set_max_window_size(const Size2 p_size) {
 
 
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
+
 	if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) {
 	if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) {
 		ERR_PRINT("Maximum window size can't be smaller than minimum window size!");
 		ERR_PRINT("Maximum window size can't be smaller than minimum window size!");
 		return;
 		return;
@@ -2668,6 +2703,10 @@ void OS_OSX::set_max_window_size(const Size2 p_size) {
 
 
 void OS_OSX::set_window_size(const Size2 p_size) {
 void OS_OSX::set_window_size(const Size2 p_size) {
 
 
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
+
 	Size2 size = p_size / get_screen_max_scale();
 	Size2 size = p_size / get_screen_max_scale();
 
 
 	NSPoint top_left;
 	NSPoint top_left;
@@ -2687,6 +2726,9 @@ void OS_OSX::set_window_size(const Size2 p_size) {
 };
 };
 
 
 void OS_OSX::set_window_fullscreen(bool p_enabled) {
 void OS_OSX::set_window_fullscreen(bool p_enabled) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	if (zoomed != p_enabled) {
 	if (zoomed != p_enabled) {
 		if (layered_window)
 		if (layered_window)
@@ -2717,6 +2759,9 @@ bool OS_OSX::is_window_fullscreen() const {
 };
 };
 
 
 void OS_OSX::set_window_resizable(bool p_enabled) {
 void OS_OSX::set_window_resizable(bool p_enabled) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	if (p_enabled)
 	if (p_enabled)
 		[window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable];
 		[window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable];
@@ -2732,6 +2777,9 @@ bool OS_OSX::is_window_resizable() const {
 };
 };
 
 
 void OS_OSX::set_window_minimized(bool p_enabled) {
 void OS_OSX::set_window_minimized(bool p_enabled) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	if (p_enabled)
 	if (p_enabled)
 		[window_object performMiniaturize:nil];
 		[window_object performMiniaturize:nil];
@@ -2748,6 +2796,9 @@ bool OS_OSX::is_window_minimized() const {
 };
 };
 
 
 void OS_OSX::set_window_maximized(bool p_enabled) {
 void OS_OSX::set_window_maximized(bool p_enabled) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	if (p_enabled) {
 	if (p_enabled) {
 		restore_rect = Rect2(get_window_position(), get_window_size());
 		restore_rect = Rect2(get_window_position(), get_window_size());
@@ -2766,12 +2817,19 @@ bool OS_OSX::is_window_maximized() const {
 };
 };
 
 
 void OS_OSX::move_window_to_foreground() {
 void OS_OSX::move_window_to_foreground() {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
 	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
 	[window_object makeKeyAndOrderFront:nil];
 	[window_object makeKeyAndOrderFront:nil];
 }
 }
 
 
 void OS_OSX::set_window_always_on_top(bool p_enabled) {
 void OS_OSX::set_window_always_on_top(bool p_enabled) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
+
 	on_top = p_enabled;
 	on_top = p_enabled;
 
 
 	if (is_window_always_on_top() == p_enabled)
 	if (is_window_always_on_top() == p_enabled)
@@ -2792,6 +2850,9 @@ bool OS_OSX::is_window_focused() const {
 }
 }
 
 
 void OS_OSX::request_attention() {
 void OS_OSX::request_attention() {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	[NSApp requestUserAttention:NSCriticalRequest];
 	[NSApp requestUserAttention:NSCriticalRequest];
 }
 }
@@ -2823,12 +2884,18 @@ void OS_OSX::set_window_per_pixel_transparency_enabled(bool p_enabled) {
 		}
 		}
 		[context update];
 		[context update];
 		NSRect frame = [window_object frame];
 		NSRect frame = [window_object frame];
-		[window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES];
-		[window_object setFrame:frame display:YES];
+
+		if (!is_no_window_mode_enabled()) {
+			[window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES];
+			[window_object setFrame:frame display:YES];
+		}
 	}
 	}
 }
 }
 
 
 void OS_OSX::set_borderless_window(bool p_borderless) {
 void OS_OSX::set_borderless_window(bool p_borderless) {
+	if (is_no_window_mode_enabled()) {
+		return;
+	}
 
 
 	// OrderOut prevents a lose focus bug with the window
 	// OrderOut prevents a lose focus bug with the window
 	[window_object orderOut:nil];
 	[window_object orderOut:nil];
@@ -3318,7 +3385,7 @@ OS_OSX::OS_OSX() {
 	[GodotApplication sharedApplication];
 	[GodotApplication sharedApplication];
 
 
 	// In case we are unbundled, make us a proper UI application
 	// In case we are unbundled, make us a proper UI application
-	[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+	[NSApp setActivationPolicy:(NSApplicationActivationPolicyAccessory)];
 
 
 	// Menu bar setup must go between sharedApplication above and
 	// Menu bar setup must go between sharedApplication above and
 	// finishLaunching below, in order to properly emulate the behavior
 	// finishLaunching below, in order to properly emulate the behavior

+ 6 - 4
platform/windows/os_windows.cpp

@@ -1855,10 +1855,12 @@ void OS_Windows::finalize_core() {
 
 
 void OS_Windows::alert(const String &p_alert, const String &p_title) {
 void OS_Windows::alert(const String &p_alert, const String &p_title) {
 
 
-	if (!is_no_window_mode_enabled())
-		MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
-	else
-		print_line("ALERT: " + p_alert);
+	if (is_no_window_mode_enabled()) {
+		print_line("ALERT: " + p_title + ": " + p_alert);
+		return;
+	}
+
+	MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
 }
 }
 
 
 void OS_Windows::set_mouse_mode(MouseMode p_mode) {
 void OS_Windows::set_mouse_mode(MouseMode p_mode) {

+ 4 - 1
platform/x11/context_gl_x11.cpp

@@ -197,7 +197,10 @@ Error ContextGL_X11::initialize() {
 
 
 	ERR_FAIL_COND_V(!x11_window, ERR_UNCONFIGURED);
 	ERR_FAIL_COND_V(!x11_window, ERR_UNCONFIGURED);
 	set_class_hint(x11_display, x11_window);
 	set_class_hint(x11_display, x11_window);
-	XMapWindow(x11_display, x11_window);
+
+	if (!OS::get_singleton()->is_no_window_mode_enabled()) {
+		XMapWindow(x11_display, x11_window);
+	}
 
 
 	XSync(x11_display, False);
 	XSync(x11_display, False);
 	XSetErrorHandler(oldHandler);
 	XSetErrorHandler(oldHandler);

+ 9 - 1
platform/x11/os_x11.cpp

@@ -847,7 +847,9 @@ void OS_X11::finalize() {
 	if (xrandr_handle)
 	if (xrandr_handle)
 		dlclose(xrandr_handle);
 		dlclose(xrandr_handle);
 
 
-	XUnmapWindow(x11_display, x11_window);
+	if (!OS::get_singleton()->is_no_window_mode_enabled()) {
+		XUnmapWindow(x11_display, x11_window);
+	}
 	XDestroyWindow(x11_display, x11_window);
 	XDestroyWindow(x11_display, x11_window);
 
 
 #if defined(OPENGL_ENABLED)
 #if defined(OPENGL_ENABLED)
@@ -3226,6 +3228,12 @@ void OS_X11::swap_buffers() {
 }
 }
 
 
 void OS_X11::alert(const String &p_alert, const String &p_title) {
 void OS_X11::alert(const String &p_alert, const String &p_title) {
+
+	if (is_no_window_mode_enabled()) {
+		print_line("ALERT: " + p_title + ": " + p_alert);
+		return;
+	}
+
 	const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
 	const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
 
 
 	String path = get_environment("PATH");
 	String path = get_environment("PATH");