Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Viewports: switching windowed/fullscreen mode #2196

Open
BrutPitt opened this issue Nov 18, 2018 · 4 comments
Open

Viewports: switching windowed/fullscreen mode #2196

BrutPitt opened this issue Nov 18, 2018 · 4 comments

Comments

@BrutPitt
Copy link

BrutPitt commented Nov 18, 2018

Version/Branch of Dear ImGui:

Viewports 1.66 WIP

Back-end file/Renderer/OS:

Back-ends: imgui_impl_GLFW.cpp + imgui_impl_opengl3.cpp
Renderer: OpenGL
OS: any

My Issue/Question:
Just a question/advice on how to recall all windows inside, switching in full screen mode, and vice versa.
(full screen, not maximized window)

Currently, in viewports mode, when I switch to full screen mode, all the windows that are outside the main viewport, remains outside (on desktop) and not are visualized in full screen (in main viewport).
I'm trying to recall they inside, and bring them outside when I return to the window mode.

I tried two ways, (tested only in Windows):

First way

    ImGuiWindow *wnd = ImGui::GetCurrentWindow();

///////////////////
//Fullscreen

//save previous state
    previouslyOwned = wnd->ViewportOwned;
//recall window inside
    wnd->ViewportTryMerge = true;

...

///////////////////
//Windowed

//put again window outside
    if(previouslyOwned) wnd->ViewportTrySplit = true;

This is simple and work well, but if a floating window, with its own viewport, is partially outside of desktop area (even just a pixel outside of desktop), the window remains outside the main viewport and not merged.

Second way

    ImGuiWindow *wnd = ImGui::GetCurrentWindow();

///////////////////
//Fullscreen

//save previous state
    previouslyOwned = wnd->ViewportOwned;

    ImGuiViewportP* viewport = (ImGuiViewportP*)ImGui::FindViewportByID(wnd->ID);
//save monitor pos
    monitorPos = viewport ? viewport->PlatformMonitor : 0;

//recall window inside
    wnd->Viewport = ((ImGuiContext *) GImGui)->Windows[0]->Viewport;
    wnd->ViewportId = ImGui::GetMainViewport()->ID;
    wnd->ViewportOwned = false;
    // or ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);

...

///////////////////
//Windowed
        if(previouslyOwned) {   // if previuos owened restore pos e viewport

            ImGuiViewportP* viewport; 
//Create new viewport and push_back in ImGuiContext 
            viewport = IM_NEW(ImGuiViewportP)();
            viewport->ID = wnd->ID;
            viewport->Idx = ((ImGuiContext *) GImGui)->Viewports.Size;
            viewport->Pos = viewport->LastPos = wnd->Pos;
            viewport->Size = wnd->Size;
            viewport->PlatformMonitor = monitorPos;    //previusly saved
            viewport->Window = wnd;
            viewport->Flags = ImGuiViewportFlags_None;
            viewport->LastFrameActive = ((ImGuiContext *) GImGui)->FrameCount;
            ((ImGuiContext *) GImGui)->Viewports.push_back(viewport);

//put again window outside
            wnd->Viewport = viewport;
            wnd->ViewportId = viewport->ID;
            wnd->ViewportOwned = true;
    }

It works fine (for now), with no problems (it seems) ... but I am not well aware of the consequence of my actions internally to ImGui, and most of all I replied your internal code (of a static function), which may be subject to future changes.

Any suggestions on how can I operate and/or if maybe some future feature could be envisaged?

I know the version is under development, but perhaps it is a question that sooner or later could be presented.

Thanks in advance,
Michele

@ocornut ocornut assigned ocornut and unassigned ocornut Nov 18, 2018
@ocornut
Copy link
Owner

ocornut commented Nov 27, 2018

Hello @BrutPitt,

Coincidentally I think some of the work I have been doing in the viewport branch this week have affected many of the things you are mentioning. Could you have a look at the latest version and confirm?

The ViewportTryMerge / ViewportTrySplit flags made things unnecessarily stateful and led to various inconsistency.

As the current version aim for a more stateless split/merge based on bounding boxes and z-order, this may become more complicated to handle:

but if a floating window, with its own viewport, is partially outside of desktop area (even just a pixel outside of desktop), the window remains outside the main viewport and not merged.

Will the current code it will always remain outside the main viewport.

By your definition of "fullscreen", it looks like you may be essentially wanting to completely enable / disable multi-viewport, and maybe toying with the master ImGuiConfigFlags_ViewportsEnable flag would be more appropriate?

@BrutPitt
Copy link
Author

BrutPitt commented Nov 27, 2018

Ciao @ocornut, and thanks for reply.
It sounds good, and need of very little work to implement it.

I tryed it and with only:

// toggle windowed
    ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
...
// toggle fullscreen
    ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable; 

When I switch from Windowed->Fullscreen everything works well, but when I go back from Fullscreen->Windowed, I get an ASSERT Exception in imgui.cpp, line 3250, ImGui::NewFrame():

IM_ASSERT((g.FrameCount == 0 || g.FrameCount == g.FrameCountPlatformEnded) && "Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ applications for reference.");

because g.FrameCount != 0
(and the previous loop, without ImGuiConfigFlags_ViewportsEnable flag, did not call ImGui::UpdatePlatformWindows(); and ImGui::RenderPlatformWindowsDefault();)

If I add, to previous code, ImGui::UpdatePlatformWindows();, like this:

// toggle windowed
    ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
    ImGui::UpdatePlatformWindows();
...
// toggle fullscreen
    ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable; 

everything seems to work fine.
But I ask you: if I call ImGui::UpdatePlatformWindows(), only, before the xxxx_NewFrame() calls, and without a subsequent ImGui::RenderPlatformWindowsDefault() (and only when switch from fullscreen->windowed, like the previous code), can to be it a problem in the long run?

Will the current code it will always remain outside the main viewport.

I meant that, if the windows are outside of screen/desktop, they are not incorporated in main viewport.
With this method, the windows continue to stay outside the desktop (screen), but they become "child windows" of main viewport, and that was what I expected.

Thank you, again.
Michele

@ocornut
Copy link
Owner

ocornut commented Nov 27, 2018

First update to latest master. (c08b4b4 is useful here)
It's probably better if you don't toggle this flag mid-frame, toggle it before NewFrame() instead.

@BrutPitt
Copy link
Author

BrutPitt commented Nov 27, 2018

I tried it.
compared to the previous version (a few minutes ago), the child windows are much better.
Now they refer to the upper left corner of the main viewport: very well
I'll test it, in depth, in the next days.

It's probably better if you don't toggle this flag mid-frame, toggle it before NewFrame() instead.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants