Browse Source

Ensure embedded mode works again

Also implemented application in/out notifications in X11.
Juan Linietsky 5 years ago
parent
commit
239942cfef

+ 31 - 11
platform/linuxbsd/display_server_x11.cpp

@@ -2339,6 +2339,24 @@ void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_ev
 void DisplayServerX11::process_events() {
 void DisplayServerX11::process_events() {
 	_THREAD_SAFE_METHOD_
 	_THREAD_SAFE_METHOD_
 
 
+	if (app_focused) {
+		//verify that one of the windows has focus, else send focus out notification
+		bool focus_found = false;
+		for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+			if (E->get().focused) {
+				focus_found = true;
+			}
+		}
+
+		if (!focus_found) {
+			if (OS::get_singleton()->get_main_loop()) {
+				OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
+			}
+
+			app_focused = false;
+		}
+	}
+
 	do_mouse_warp = false;
 	do_mouse_warp = false;
 
 
 	// Is the current mouse mode one where it needs to be grabbed.
 	// Is the current mouse mode one where it needs to be grabbed.
@@ -2533,12 +2551,12 @@ void DisplayServerX11::process_events() {
 				break;
 				break;
 
 
 			case NoExpose:
 			case NoExpose:
-				minimized = true;
+				windows[window_id].minimized = true;
 				break;
 				break;
 
 
 			case VisibilityNotify: {
 			case VisibilityNotify: {
 				XVisibilityEvent *visibility = (XVisibilityEvent *)&event;
 				XVisibilityEvent *visibility = (XVisibilityEvent *)&event;
-				minimized = (visibility->state == VisibilityFullyObscured);
+				windows[window_id].minimized = (visibility->state == VisibilityFullyObscured);
 			} break;
 			} break;
 			case LeaveNotify: {
 			case LeaveNotify: {
 				if (!mouse_mode_grab) {
 				if (!mouse_mode_grab) {
@@ -2552,10 +2570,8 @@ void DisplayServerX11::process_events() {
 				}
 				}
 			} break;
 			} break;
 			case FocusIn:
 			case FocusIn:
-				minimized = false;
-				window_has_focus = true;
+				windows[window_id].focused = true;
 				_send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN);
 				_send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN);
-				window_focused = true;
 
 
 				if (mouse_mode_grab) {
 				if (mouse_mode_grab) {
 					// Show and update the cursor if confined and the window regained focus.
 					// Show and update the cursor if confined and the window regained focus.
@@ -2582,13 +2598,19 @@ void DisplayServerX11::process_events() {
 				if (windows[window_id].xic) {
 				if (windows[window_id].xic) {
 					XSetICFocus(windows[window_id].xic);
 					XSetICFocus(windows[window_id].xic);
 				}
 				}
+
+				if (!app_focused) {
+					if (OS::get_singleton()->get_main_loop()) {
+						OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
+					}
+					app_focused = true;
+				}
 				break;
 				break;
 
 
 			case FocusOut:
 			case FocusOut:
-				window_has_focus = false;
+				windows[window_id].focused = false;
 				Input::get_singleton()->release_pressed_events();
 				Input::get_singleton()->release_pressed_events();
 				_send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT);
 				_send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT);
-				window_focused = false;
 
 
 				if (mouse_mode_grab) {
 				if (mouse_mode_grab) {
 					for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
 					for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
@@ -2727,7 +2749,7 @@ void DisplayServerX11::process_events() {
 					Point2i new_center = pos;
 					Point2i new_center = pos;
 					pos = last_mouse_pos + xi.relative_motion;
 					pos = last_mouse_pos + xi.relative_motion;
 					center = new_center;
 					center = new_center;
-					do_mouse_warp = window_has_focus; // warp the cursor if we're focused in
+					do_mouse_warp = windows[window_id].focused; // warp the cursor if we're focused in
 				}
 				}
 
 
 				if (!last_mouse_pos_valid) {
 				if (!last_mouse_pos_valid) {
@@ -2787,7 +2809,7 @@ void DisplayServerX11::process_events() {
 				// Don't propagate the motion event unless we have focus
 				// Don't propagate the motion event unless we have focus
 				// this is so that the relative motion doesn't get messed up
 				// this is so that the relative motion doesn't get messed up
 				// after we regain focus.
 				// after we regain focus.
-				if (window_has_focus || !mouse_mode_grab) {
+				if (windows[window_id].focused || !mouse_mode_grab) {
 					Input::get_singleton()->accumulate_input_event(mm);
 					Input::get_singleton()->accumulate_input_event(mm);
 				}
 				}
 
 
@@ -3764,8 +3786,6 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
 
 
 	requested = None;
 	requested = None;
 
 
-	window_has_focus = true; // Set focus to true at init
-
 	/*if (p_desired.layered) {
 	/*if (p_desired.layered) {
 		set_window_per_pixel_transparency_enabled(true);
 		set_window_per_pixel_transparency_enabled(true);
 	}*/
 	}*/

+ 6 - 3
platform/linuxbsd/display_server_x11.h

@@ -139,6 +139,8 @@ class DisplayServerX11 : public DisplayServer {
 		bool borderless = false;
 		bool borderless = false;
 		bool resize_disabled = false;
 		bool resize_disabled = false;
 		Vector2i last_position_before_fs;
 		Vector2i last_position_before_fs;
+		bool focused = false;
+		bool minimized = false;
 	};
 	};
 
 
 	Map<WindowID, WindowData> windows;
 	Map<WindowID, WindowData> windows;
@@ -164,6 +166,7 @@ class DisplayServerX11 : public DisplayServer {
 	uint64_t last_click_ms;
 	uint64_t last_click_ms;
 	int last_click_button_index;
 	int last_click_button_index;
 	uint32_t last_button_state;
 	uint32_t last_button_state;
+	bool app_focused = false;
 
 
 	struct {
 	struct {
 		int opcode;
 		int opcode;
@@ -195,8 +198,8 @@ class DisplayServerX11 : public DisplayServer {
 
 
 	void _handle_key_event(WindowID p_window, XKeyEvent *p_event, bool p_echo = false);
 	void _handle_key_event(WindowID p_window, XKeyEvent *p_event, bool p_echo = false);
 
 
-	bool minimized;
-	bool window_has_focus;
+	//bool minimized;
+	//bool window_has_focus;
 	bool do_mouse_warp;
 	bool do_mouse_warp;
 
 
 	const char *cursor_theme;
 	const char *cursor_theme;
@@ -210,7 +213,7 @@ class DisplayServerX11 : public DisplayServer {
 	bool layered_window;
 	bool layered_window;
 
 
 	String rendering_driver;
 	String rendering_driver;
-	bool window_focused;
+	//bool window_focused;
 	//void set_wm_border(bool p_enabled);
 	//void set_wm_border(bool p_enabled);
 	void set_wm_fullscreen(bool p_enabled);
 	void set_wm_fullscreen(bool p_enabled);
 	void set_wm_above(bool p_enabled);
 	void set_wm_above(bool p_enabled);

+ 5 - 1
scene/main/viewport.cpp

@@ -2913,6 +2913,10 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
 		return;
 		return;
 	}
 	}
 
 
+	if (!_can_consume_input_events()) {
+		return;
+	}
+
 	if (!is_input_handled()) {
 	if (!is_input_handled()) {
 		get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
 		get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
 	}
 	}
@@ -2926,7 +2930,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
 void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
 void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
 	ERR_FAIL_COND(!is_inside_tree());
 	ERR_FAIL_COND(!is_inside_tree());
 
 
-	if (disable_input) {
+	if (disable_input || !_can_consume_input_events()) {
 		return;
 		return;
 	}
 	}
 
 

+ 2 - 0
scene/main/viewport.h

@@ -441,6 +441,8 @@ private:
 	bool _sub_windows_forward_input(const Ref<InputEvent> &p_event);
 	bool _sub_windows_forward_input(const Ref<InputEvent> &p_event);
 	SubWindowResize _sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point);
 	SubWindowResize _sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point);
 
 
+	virtual bool _can_consume_input_events() const { return true; }
+
 protected:
 protected:
 	void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated);
 	void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated);
 
 

+ 8 - 1
scene/main/window.cpp

@@ -874,6 +874,10 @@ void Window::child_controls_changed() {
 	call_deferred("_update_child_controls");
 	call_deferred("_update_child_controls");
 }
 }
 
 
+bool Window::_can_consume_input_events() const {
+	return exclusive_child == nullptr;
+}
+
 void Window::_window_input(const Ref<InputEvent> &p_ev) {
 void Window::_window_input(const Ref<InputEvent> &p_ev) {
 	if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev))) {
 	if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev))) {
 		return; //avoid joy input on editor
 		return; //avoid joy input on editor
@@ -890,10 +894,13 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
 	if (exclusive_child != nullptr) {
 	if (exclusive_child != nullptr) {
 		exclusive_child->grab_focus();
 		exclusive_child->grab_focus();
 
 
-		return; //has an exclusive child, can't get events until child is closed
+		if (!is_embedding_subwindows()) { //not embedding, no need for event
+			return;
+		}
 	}
 	}
 
 
 	emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
 	emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
+
 	input(p_ev);
 	input(p_ev);
 	if (!is_input_handled()) {
 	if (!is_input_handled()) {
 		unhandled_input(p_ev);
 		unhandled_input(p_ev);

+ 1 - 0
scene/main/window.h

@@ -130,6 +130,7 @@ private:
 	void _window_drop_files(const Vector<String> &p_files);
 	void _window_drop_files(const Vector<String> &p_files);
 	void _rect_changed_callback(const Rect2i &p_callback);
 	void _rect_changed_callback(const Rect2i &p_callback);
 	void _event_callback(DisplayServer::WindowEvent p_event);
 	void _event_callback(DisplayServer::WindowEvent p_event);
+	virtual bool _can_consume_input_events() const;
 
 
 protected:
 protected:
 	Viewport *_get_embedder() const;
 	Viewport *_get_embedder() const;