diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/java/lib/res/values/dimens.xml | 4 | ||||
-rw-r--r-- | platform/android/java/lib/src/org/godotengine/godot/Godot.java | 46 | ||||
-rw-r--r-- | platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java | 80 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 249 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.h | 4 | ||||
-rw-r--r-- | platform/osx/display_server_osx.h | 1 | ||||
-rw-r--r-- | platform/osx/display_server_osx.mm | 11 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 20 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 1 |
9 files changed, 248 insertions, 168 deletions
diff --git a/platform/android/java/lib/res/values/dimens.xml b/platform/android/java/lib/res/values/dimens.xml new file mode 100644 index 0000000000..9034dbbcc1 --- /dev/null +++ b/platform/android/java/lib/res/values/dimens.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <dimen name="text_edit_height">48dp</dimen> +</resources> diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 35852f31ef..524f32bf5e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -56,6 +56,8 @@ import android.content.SharedPreferences.Editor; import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Point; +import android.graphics.Rect; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -75,6 +77,7 @@ import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; import android.widget.Button; @@ -148,8 +151,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC private void setButtonPausedState(boolean paused) { mStatePaused = paused; - int stringResourceID = paused ? R.string.text_button_resume : - R.string.text_button_pause; + int stringResourceID = paused ? R.string.text_button_resume : R.string.text_button_pause; mPauseButton.setText(stringResourceID); } @@ -160,8 +162,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC public GodotRenderView mRenderView; private boolean godot_initialized = false; - private GodotEditText mEditText; - private SensorManager mSensorManager; private Sensor mAccelerometer; private Sensor mGravity; @@ -218,6 +218,13 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC containerLayout = new FrameLayout(activity); containerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + // GodotEditText layout + GodotEditText editText = new GodotEditText(activity); + editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, + (int)getResources().getDimension(R.dimen.text_edit_height))); + // ...add to FrameLayout + containerLayout.addView(editText); + GodotLib.setup(command_line); final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name"); @@ -230,9 +237,21 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC View view = mRenderView.getView(); containerLayout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + editText.setView(mRenderView); + io.setEdit(editText); - mEditText = new GodotEditText(activity, mRenderView); - io.setEdit(mEditText); + view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + Point fullSize = new Point(); + activity.getWindowManager().getDefaultDisplay().getSize(fullSize); + Rect gameSize = new Rect(); + mRenderView.getView().getWindowVisibleDisplayFrame(gameSize); + + final int keyboardHeight = fullSize.y - gameSize.bottom; + GodotLib.setVirtualKeyboardHeight(keyboardHeight); + } + }); mRenderView.queueOnRenderThread(new Runnable() { @Override @@ -448,7 +467,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC final Activity activity = getActivity(); Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE); pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this); @@ -585,21 +603,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } @Override - public void onStart() { - super.onStart(); - - mRenderView.getView().post(new Runnable() { - @Override - public void run() { - mEditText.onInitView(); - } - }); - } - - @Override public void onDestroy() { - mEditText.onDestroyView(); - for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { plugin.onMainDestroy(); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java index 6855f91f1c..c95339c583 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java @@ -32,27 +32,16 @@ package org.godotengine.godot.input; import org.godotengine.godot.*; -import android.app.Activity; import android.content.Context; -import android.graphics.Point; -import android.graphics.Rect; import android.os.Handler; import android.os.Message; import android.text.InputFilter; import android.text.InputType; import android.util.AttributeSet; -import android.view.Gravity; import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.view.ViewTreeObserver; -import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; -import android.widget.FrameLayout; -import android.widget.PopupWindow; import java.lang.ref.WeakReference; @@ -67,8 +56,6 @@ public class GodotEditText extends EditText { // Fields // =========================================================== private GodotRenderView mRenderView; - private View mKeyboardView; - private PopupWindow mKeyboardWindow; private GodotTextInputWrapper mInputWrapper; private EditHandler sHandler = new EditHandler(this); private String mOriginText; @@ -93,52 +80,24 @@ public class GodotEditText extends EditText { // =========================================================== // Constructors // =========================================================== - public GodotEditText(final Context context, final GodotRenderView view) { + public GodotEditText(final Context context) { super(context); + initView(); + } - setPadding(0, 0, 0, 0); - setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_DONE); - setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); - - mRenderView = view; - mInputWrapper = new GodotTextInputWrapper(mRenderView, this); - setOnEditorActionListener(mInputWrapper); - view.getView().requestFocus(); - - // Create a popup window with an invisible layout for the virtual keyboard, - // so the view can be resized to get the vk height without resizing the main godot view. - final FrameLayout keyboardLayout = new FrameLayout(context); - keyboardLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); - keyboardLayout.setVisibility(View.INVISIBLE); - keyboardLayout.addView(this); - mKeyboardView = keyboardLayout; - - mKeyboardWindow = new PopupWindow(keyboardLayout, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - mKeyboardWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); - mKeyboardWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - mKeyboardWindow.setFocusable(true); // for the text edit to work - mKeyboardWindow.setTouchable(false); // inputs need to go through - - keyboardLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - Point fullSize = new Point(); - ((Activity)mRenderView.getView().getContext()).getWindowManager().getDefaultDisplay().getSize(fullSize); - Rect gameSize = new Rect(); - mKeyboardWindow.getContentView().getWindowVisibleDisplayFrame(gameSize); - - final int keyboardHeight = fullSize.y - gameSize.bottom; - GodotLib.setVirtualKeyboardHeight(keyboardHeight); - } - }); + public GodotEditText(final Context context, final AttributeSet attrs) { + super(context, attrs); + initView(); } - public void onInitView() { - mKeyboardWindow.showAtLocation(mRenderView.getView(), Gravity.NO_GRAVITY, 0, 0); + public GodotEditText(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + initView(); } - public void onDestroyView() { - mKeyboardWindow.dismiss(); + protected void initView() { + setPadding(0, 0, 0, 0); + setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_DONE); } public boolean isMultiline() { @@ -170,7 +129,7 @@ public class GodotEditText extends EditText { edit.mInputWrapper.setOriginText(text); edit.addTextChangedListener(edit.mInputWrapper); - final InputMethodManager imm = (InputMethodManager)mKeyboardView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(edit, 0); } } break; @@ -179,7 +138,7 @@ public class GodotEditText extends EditText { GodotEditText edit = (GodotEditText)msg.obj; edit.removeTextChangedListener(mInputWrapper); - final InputMethodManager imm = (InputMethodManager)mKeyboardView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); edit.mRenderView.getView().requestFocus(); } break; @@ -193,6 +152,17 @@ public class GodotEditText extends EditText { } // =========================================================== + // Getter & Setter + // =========================================================== + public void setView(final GodotRenderView view) { + mRenderView = view; + if (mInputWrapper == null) + mInputWrapper = new GodotTextInputWrapper(mRenderView, this); + setOnEditorActionListener(mInputWrapper); + view.getView().requestFocus(); + } + + // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index a0aced26ab..b8a62ab7fa 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -83,6 +83,13 @@ #define VALUATOR_TILTX 3 #define VALUATOR_TILTY 4 +//#define DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED +#ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED +#define DEBUG_LOG_X11(...) printf(__VA_ARGS__) +#else +#define DEBUG_LOG_X11(...) +#endif + static const double abs_resolution_mult = 10000.0; static const double abs_resolution_range_mult = 10.0; @@ -681,6 +688,14 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, u return id; } +void DisplayServerX11::show_window(WindowID p_id) { + _THREAD_SAFE_METHOD_ + + WindowData &wd = windows[p_id]; + + XMapWindow(x11_display, wd.x11_window); +} + void DisplayServerX11::delete_sub_window(WindowID p_id) { _THREAD_SAFE_METHOD_ @@ -689,6 +704,8 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { WindowData &wd = windows[p_id]; + DEBUG_LOG_X11("delete_sub_window: %lu (%u) \n", wd.x11_window, p_id); + while (wd.transient_children.size()) { window_set_transient(wd.transient_children.front()->get(), INVALID_WINDOW_ID); } @@ -842,24 +859,34 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd_window = windows[p_window]; - ERR_FAIL_COND(wd_window.transient_parent == p_parent); + WindowID prev_parent = wd_window.transient_parent; + ERR_FAIL_COND(prev_parent == p_parent); ERR_FAIL_COND_MSG(wd_window.on_top, "Windows with the 'on top' can't become transient."); if (p_parent == INVALID_WINDOW_ID) { //remove transient - ERR_FAIL_COND(wd_window.transient_parent == INVALID_WINDOW_ID); - ERR_FAIL_COND(!windows.has(wd_window.transient_parent)); + ERR_FAIL_COND(prev_parent == INVALID_WINDOW_ID); + ERR_FAIL_COND(!windows.has(prev_parent)); - WindowData &wd_parent = windows[wd_window.transient_parent]; + WindowData &wd_parent = windows[prev_parent]; wd_window.transient_parent = INVALID_WINDOW_ID; wd_parent.transient_children.erase(p_window); XSetTransientForHint(x11_display, wd_window.x11_window, None); + + // Set focus to parent sub window to avoid losing all focus with nested menus. + // RevertToPointerRoot is used to make sure we don't lose all focus in case + // a subwindow and its parent are both destroyed. + if (wd_window.menu_type && !wd_window.no_focus) { + if (!wd_parent.no_focus) { + XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime); + } + } } else { ERR_FAIL_COND(!windows.has(p_parent)); - ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent"); + ERR_FAIL_COND_MSG(prev_parent != INVALID_WINDOW_ID, "Window already has a transient parent"); WindowData &wd_parent = windows[p_parent]; wd_window.transient_parent = p_parent; @@ -2285,6 +2312,11 @@ void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_ev void DisplayServerX11::process_events() { _THREAD_SAFE_METHOD_ +#ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED + static int frame = 0; + ++frame; +#endif + if (app_focused) { //verify that one of the windows has focus, else send focus out notification bool focus_found = false; @@ -2301,6 +2333,7 @@ void DisplayServerX11::process_events() { if (delta > 250) { //X11 can go between windows and have no focus for a while, when creating them or something else. Use this as safety to avoid unnecessary focus in/outs. if (OS::get_singleton()->get_main_loop()) { + DEBUG_LOG_X11("All focus lost, triggering NOTIFICATION_APPLICATION_FOCUS_OUT\n"); OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); } app_focused = false; @@ -2323,6 +2356,10 @@ void DisplayServerX11::process_events() { XEvent event; XNextEvent(x11_display, &event); + if (XFilterEvent(&event, None)) { + continue; + } + WindowID window_id = MAIN_WINDOW_ID; // Assign the event to the relevant window @@ -2333,10 +2370,6 @@ void DisplayServerX11::process_events() { } } - if (XFilterEvent(&event, None)) { - continue; - } - if (XGetEventData(x11_display, &event.xcookie)) { if (event.xcookie.type == GenericEvent && event.xcookie.extension == xi.opcode) { XIDeviceEvent *event_data = (XIDeviceEvent *)event.xcookie.data; @@ -2499,32 +2532,63 @@ void DisplayServerX11::process_events() { XFreeEventData(x11_display, &event.xcookie); switch (event.type) { - case Expose: + case MapNotify: { + DEBUG_LOG_X11("[%u] MapNotify window=%lu (%u) \n", frame, event.xmap.window, window_id); + + const WindowData &wd = windows[window_id]; + + // Set focus when menu window is started. + // RevertToPointerRoot is used to make sure we don't lose all focus in case + // a subwindow and its parent are both destroyed. + if (wd.menu_type && !wd.no_focus) { + XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime); + } + } break; + + case Expose: { + DEBUG_LOG_X11("[%u] Expose window=%lu (%u), count='%u' \n", frame, event.xexpose.window, window_id, event.xexpose.count); + Main::force_redraw(); - break; + } break; + + case NoExpose: { + DEBUG_LOG_X11("[%u] NoExpose drawable=%lu (%u) \n", frame, event.xnoexpose.drawable, window_id); - case NoExpose: windows[window_id].minimized = true; - break; + } break; case VisibilityNotify: { + DEBUG_LOG_X11("[%u] VisibilityNotify window=%lu (%u), state=%u \n", frame, event.xvisibility.window, window_id, event.xvisibility.state); + XVisibilityEvent *visibility = (XVisibilityEvent *)&event; windows[window_id].minimized = (visibility->state == VisibilityFullyObscured); } break; + case LeaveNotify: { + DEBUG_LOG_X11("[%u] LeaveNotify window=%lu (%u), mode='%u' \n", frame, event.xcrossing.window, window_id, event.xcrossing.mode); + if (!mouse_mode_grab) { _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT); } } break; + case EnterNotify: { + DEBUG_LOG_X11("[%u] EnterNotify window=%lu (%u), mode='%u' \n", frame, event.xcrossing.window, window_id, event.xcrossing.mode); + if (!mouse_mode_grab) { _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER); } } break; - case FocusIn: - windows[window_id].focused = true; - _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN); + + case FocusIn: { + DEBUG_LOG_X11("[%u] FocusIn window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode); + + WindowData &wd = windows[window_id]; + + wd.focused = true; + + _send_window_event(wd, WINDOW_EVENT_FOCUS_IN); if (mouse_mode_grab) { // Show and update the cursor if confined and the window regained focus. @@ -2548,8 +2612,8 @@ void DisplayServerX11::process_events() { XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask); }*/ #endif - if (windows[window_id].xic) { - XSetICFocus(windows[window_id].xic); + if (wd.xic) { + XSetICFocus(wd.xic); } if (!app_focused) { @@ -2558,12 +2622,17 @@ void DisplayServerX11::process_events() { } app_focused = true; } - break; + } break; + + case FocusOut: { + DEBUG_LOG_X11("[%u] FocusOut window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode); + + WindowData &wd = windows[window_id]; + + wd.focused = false; - case FocusOut: - windows[window_id].focused = false; Input::get_singleton()->release_pressed_events(); - _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT); + _send_window_event(wd, WINDOW_EVENT_FOCUS_OUT); if (mouse_mode_grab) { for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { @@ -2592,14 +2661,26 @@ void DisplayServerX11::process_events() { } xi.state.clear(); #endif - if (windows[window_id].xic) { - XSetICFocus(windows[window_id].xic); + if (wd.xic) { + XSetICFocus(wd.xic); + } + } break; + + case ConfigureNotify: { + DEBUG_LOG_X11("[%u] ConfigureNotify window=%lu (%u), event=%lu, above=%lu, override_redirect=%u \n", frame, event.xconfigure.window, window_id, event.xconfigure.event, event.xconfigure.above, event.xconfigure.override_redirect); + + const WindowData &wd = windows[window_id]; + + // Set focus when menu window is re-used. + // RevertToPointerRoot is used to make sure we don't lose all focus in case + // a subwindow and its parent are both destroyed. + if (wd.menu_type && !wd.no_focus) { + XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime); } - break; - case ConfigureNotify: _window_changed(&event); - break; + } break; + case ButtonPress: case ButtonRelease: { /* exit in case of a mouse button press */ @@ -2627,6 +2708,17 @@ void DisplayServerX11::process_events() { mb->set_pressed((event.type == ButtonPress)); if (event.type == ButtonPress) { + DEBUG_LOG_X11("[%u] ButtonPress window=%lu (%u), button_index=%u \n", frame, event.xbutton.window, window_id, mb->get_button_index()); + + const WindowData &wd = windows[window_id]; + + // Ensure window focus on click. + // RevertToPointerRoot is used to make sure we don't lose all focus in case + // a subwindow and its parent are both destroyed. + if (!wd.no_focus) { + XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime); + } + uint64_t diff = OS::get_singleton()->get_ticks_usec() / 1000 - last_click_ms; if (mb->get_button_index() == last_click_button_index) { @@ -2645,6 +2737,8 @@ void DisplayServerX11::process_events() { last_click_ms += diff; last_click_pos = Point2i(event.xbutton.x, event.xbutton.y); } + } else { + DEBUG_LOG_X11("[%u] ButtonRelease window=%lu (%u), button_index=%u \n", frame, event.xbutton.window, window_id, mb->get_button_index()); } Input::get_singleton()->accumulate_input_event(mb); @@ -3140,12 +3234,37 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask; - WindowID id; + WindowID id = window_id_counter++; + WindowData &wd = windows[id]; + + if ((id != MAIN_WINDOW_ID) && (p_flags & WINDOW_FLAG_BORDERLESS_BIT)) { + wd.menu_type = true; + } + + if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) { + wd.menu_type = true; + wd.no_focus = true; + } + + // Setup for menu subwindows: + // - override_redirect forces the WM not to interfere with the window, to avoid delays due to + // handling decorations and placement. + // On the other hand, focus changes need to be handled manually when this is set. + // - save_under is a hint for the WM to keep the content of windows behind to avoid repaint. + if (wd.menu_type) { + windowAttributes.override_redirect = True; + windowAttributes.save_under = True; + valuemask |= CWOverrideRedirect | CWSaveUnder; + } + { - WindowData wd; wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), p_rect.position.x, p_rect.position.y, p_rect.size.width > 0 ? p_rect.size.width : 1, p_rect.size.height > 0 ? p_rect.size.height : 1, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes); - XMapWindow(x11_display, wd.x11_window); + // Enable receiving notification when the window is initialized (MapNotify) + // so the focus can be set at the right time. + if (wd.menu_type && !wd.no_focus) { + XSelectInput(x11_display, wd.x11_window, StructureNotifyMask); + } //associate PID // make PID known to X11 @@ -3221,58 +3340,26 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u _update_context(wd); - id = window_id_counter++; - - windows[id] = wd; - - { - bool make_utility = false; - - if (p_flags & WINDOW_FLAG_BORDERLESS_BIT) { - Hints hints; - Atom property; - hints.flags = 2; - hints.decorations = 0; - property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); - XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); - - make_utility = true; - } - if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) { - make_utility = true; - } - - if (make_utility) { - //this one seems to disable the fade animations for regular windows - //but has the drawback that will not get focus by default, so - //we need to force it, unless no focus requested - - Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_UTILITY", False); - Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False); - - XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1); - - if (!(p_flags & WINDOW_FLAG_NO_FOCUS_BIT)) { - //but as utility appears unfocused, it needs to be forcefuly focused, unless no focus requested - XEvent xev; - Atom net_active_window = XInternAtom(x11_display, "_NET_ACTIVE_WINDOW", False); + if (p_flags & WINDOW_FLAG_BORDERLESS_BIT) { + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = 0; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + } - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.xclient.window = wd.x11_window; - xev.xclient.message_type = net_active_window; - xev.xclient.format = 32; - xev.xclient.data.l[0] = 1; - xev.xclient.data.l[1] = CurrentTime; + if (wd.menu_type) { + // Set Utility type to disable fade animations. + Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_UTILITY", False); + Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False); - XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - } - } else { - Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_NORMAL", False); - Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False); + XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1); + } else { + Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_NORMAL", False); + Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False); - XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1); - } + XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1); } _update_size_hints(id); @@ -3293,8 +3380,6 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u XFree(visualInfo); } - WindowData &wd = windows[id]; - window_set_mode(p_mode, id); //sync size @@ -3316,6 +3401,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, u if (cursors[current_cursor] != None) { XDefineCursor(x11_display, wd.x11_window, cursors[current_cursor]); } + return id; } @@ -3555,6 +3641,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode window_set_flag(WindowFlags(i), true, main_window); } } + show_window(main_window); //create RenderingDevice if used #if defined(VULKAN_ENABLED) diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index fb50b484a0..b40984cc02 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -132,6 +132,9 @@ class DisplayServerX11 : public DisplayServer { ObjectID instance_id; + bool menu_type = false; + bool no_focus = false; + //better to guess on the fly, given WM can change it //WindowMode mode; bool fullscreen = false; //OS can't exit from this mode @@ -277,6 +280,7 @@ public: virtual Vector<DisplayServer::WindowID> get_window_list() const; virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); + virtual void show_window(WindowID p_id); virtual void delete_sub_window(WindowID p_id); virtual WindowID get_window_at_screen_position(const Point2i &p_position) const; diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index 68e8454fd0..d8f3f81ff6 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -230,6 +230,7 @@ public: virtual Vector<int> get_window_list() const override; virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override; + virtual void show_window(WindowID p_id) override; virtual void delete_sub_window(WindowID p_id) override; virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 1676e0d425..adfb47324e 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -2314,18 +2314,23 @@ DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, u _THREAD_SAFE_METHOD_ WindowID id = _create_window(p_mode, p_rect); - WindowData &wd = windows[id]; for (int i = 0; i < WINDOW_FLAG_MAX; i++) { if (p_flags & (1 << i)) { window_set_flag(WindowFlags(i), true, id); } } + + return id; +} + +void DisplayServerOSX::show_window(WindowID p_id) { + WindowData &wd = windows[p_id]; + if (wd.no_focus) { [wd.window_object orderFront:nil]; } else { [wd.window_object makeKeyAndOrderFront:nil]; } - return id; } void DisplayServerOSX::_send_window_event(const WindowData &wd, WindowEvent p_event) { @@ -3774,7 +3779,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode window_set_flag(WindowFlags(i), true, main_window); } } - [windows[main_window].window_object makeKeyAndOrderFront:nil]; + show_window(MAIN_WINDOW_ID); #if defined(OPENGL_ENABLED) if (rendering_driver == "opengl_es") { diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 9469e35536..cd7f28833b 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -493,15 +493,21 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod wd.no_focus = true; } - _update_window_style(window_id); + return window_id; +} - ShowWindow(wd.hWnd, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show The Window - if (!(p_flags & WINDOW_FLAG_NO_FOCUS_BIT)) { +void DisplayServerWindows::show_window(WindowID p_id) { + WindowData &wd = windows[p_id]; + + if (p_id != MAIN_WINDOW_ID) { + _update_window_style(p_id); + } + + ShowWindow(wd.hWnd, wd.no_focus ? SW_SHOWNOACTIVATE : SW_SHOW); // Show The Window + if (!wd.no_focus) { SetForegroundWindow(wd.hWnd); // Slightly Higher Priority SetFocus(wd.hWnd); // Sets Keyboard Focus To } - - return window_id; } void DisplayServerWindows::delete_sub_window(WindowID p_window) { @@ -3139,9 +3145,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } } - ShowWindow(windows[MAIN_WINDOW_ID].hWnd, SW_SHOW); // Show The Window - SetForegroundWindow(windows[MAIN_WINDOW_ID].hWnd); // Slightly Higher Priority - SetFocus(windows[MAIN_WINDOW_ID].hWnd); // Sets Keyboard Focus To + show_window(MAIN_WINDOW_ID); #if defined(VULKAN_ENABLED) diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 0ad8cd3d07..52f5b0f4a9 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -461,6 +461,7 @@ public: virtual Vector<DisplayServer::WindowID> get_window_list() const; virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); + virtual void show_window(WindowID p_window); virtual void delete_sub_window(WindowID p_window); virtual WindowID get_window_at_screen_position(const Point2i &p_position) const; |