X11 Fullscreen window (OpenGL) - opengl

I'm writing and OpenGL application on linux (Ubuntu 11.10) using Xlib (X11). What is the simplest way to implement toggle between windowed and fullscreen mode?

Here's an implementation of what Havoc P suggested, to save the next person the effort:
void fullscreen(Display* dpy, Window win) {
Atom atoms[2] = { XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False), None };
XChangeProperty(
dpy,
win,
XInternAtom(dpy, "_NET_WM_STATE", False),
XA_ATOM, 32, PropModeReplace, (unsigned char*)atoms, 1
);
}

on the protocol level, see the _NET_WM_STATE property with accompanying client message and the fullscreen state flag. this is specified in the EWMH spec. for bonus points you may want to manually implement fullscreen if the WM does not report support for the official hint, EWMH specs a way to check what is supported. You may also want to grab the mouse pointer and/or
keyboard if you don't want people to accidentally leave fullscreen.
or, to avoid learning low level X gunge, just use SDL or GTK or Qt or something and they should all have a simple method call to toggle fullscreen.

Related

Trap cursor in Window

I wrote my own cameraclass in C++ using DX11.
At the moment I use WM_MOUSEMOVE events to look around in the scene. To prevent the cursur to get out of the window, I call the function SetCursorPos to center the mouse whenever a WM_MOUSEMOVE event occurs.
But if I move my mouse very fast, the cursor gets out of the window.
A solution to that was using the function ClipCursor, but this leads to falter the rotation of the camera when the cursor hits the border of the rect. So ClipCursor solved the original problem, but ended in another.
Do you guys have any solution to that?
For a Windows desktop app, just use ClipCursor giving the rectangle of your window:
RECT rect;
GetClientRect(mWindow, &rect);
POINT ul;
ul.x = rect.left;
ul.y = rect.top;
POINT lr;
lr.x = rect.right;
lr.y = rect.bottom;
MapWindowPoints(mWindow, nullptr, &ul, 1);
MapWindowPoints(mWindow, nullptr, &lr, 1);
rect.left = ul.x;
rect.top = ul.y;
rect.right = lr.x;
rect.bottom = lr.y;
ClipCursor(&rect);
Be sure to have a way to escape this mode so that users can choose to interact with other windows if desired. Typically you call ClipCursor(nullptr); when you go to a 'pause' menu to get out of 'mouse-look' behavior like this.
You can use "raw" input in desktop apps as well, see Taking Advantage of High-Definition Mouse Movement. Keep in mind that raw input works pretty well for relative-movement 'mouse-look' behavior, but (a) it won't work over remote desktop, and (b) you won't get 'pointer-ballistics' which is a non-linear movement rate that makes a mouse more agile so you should generally stick with traditional WM_MOUSE messages when dealing with absolute-movement.
For Universal Windows Platform, you can't use "raw" input as there's no equivalent to WM_INPUT, but you do get high-precision data out of the MouseDevice.MouseMoved event via the MouseDelta property. You don't need to use ClipCursor for relative movement in UWP, just turning off the cursor by setting the CoreWindow.PointerCursor property to nullptr will prevent the system mouse position from being tracked. Again, you should restore the system cursor when you are in a 'pause' menu. See Developing mouse controls (DirectX and C++).
See DirectX Tool Kit Mouse helper class and more importantly the implementation file. For relative mode, it makes use of both ClipCursor and WM_INPUT for the Windows desktop Win32 implementation.
The regular windows message are not the best solution to drive precise controls. They inherit from the OS acceleration system, clipping and depends on other shenanigans as you can see.
The best API to receive mouse inputs is Raw Input. It has the advantage to expose the better dpi and polling rate the hardware can provide and is free of any under the hood manipulation. Once you read the mouse with this, you are free to use SetCapture and clipCursor to prevent unwanted click to an other window.
You can find the documentation here : https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx

Transparent window on top of immersive full-screen mode

I am trying to draw on top of another process while it is in immersive full-screen mode.
I know this is possible using GDI and I have 2 questions:
Is it possible using a top-level transparent window ? (on top of the immersive process)
Is there a higher level API witch I can use instead of GDI?
Thank you :)
In Windows, you have two possibilities for creating a fullscreen window:
A full-screen application with exclusive drawing rights to the display.
A borderless window that extends to the full desktop resolution.
The first option allows you to change display properties like resolution, bit depth and refresh rate, while the second option is bound to use the same options here as a normal (windowed) desktop application.
Overlaying a fullscreen window with a top-level window is only possible if the fullscreen application is implemented with option 2. In that case however, any code that is able to create a transparent top-level window will do (be it pure WinAPI/GDI, or something more sophisticated, like Qt).
With option 1, as the description suggests, the fullscreen application has exclusive drawing rights to the display. Attempting to bring another window in front of it will either minimize the fullscreen application or force it into windowed mode.
There are some hacks how you can still get an overlay in this case, but they are rather invasive. For example, with a fullscreen application based on D3D, you can hook into D3D's Present routine and have D3D draw your overlay before displaying the back buffer. The important point here is that the code for drawing the overlay is executed from within the process of the fullscreen application, as that is the only process that is allowed draw to the screen at that point.
Note that some applications (in particular video games protected by anti-cheat software) do not like it very much if you inject code into the process this way.
Note that the Win API also provides an interface for so called hardware overlays, which allow drawing on top of exclusive fullscreen applications. Unfortunately, this mechanism is not widely supported on consumer hardware and might not work depending on which graphics card you are trying to run it on.

C++ Drawing directly to the screen (like an overlay)

Many laptops nowadays have FN hot keys to change volume, brightness, etc. and usually display a visual cue that is rendered on the screen completely above the operating system. For new Windows 8/8.1 systems this visual even appears outside of the desktop in the metro side. They cannot be drawing inside of a borderless window otherwise it wouldn't show up over the metro interface.
I have tried researching whether DirectX can draw directly to the screen but it doesn't appear it can. I don't even know if I should look into OpenGL... ?
I had some success using GDI; specifically the GetDC function with the parameter NULL to grab the screen device.
#include <Windows.h>
int main() {
const HDC dc = GetDC(NULL);
while (1) {
Rectangle(dc, 100, 100, 500, 500);
}
}
However, this requires re-rendering everything repeatedly because my region of the screen can be overwritten by other windows changing in the background. And even with it re-rendering in a loop, there is massive screen flicker.
How do the OEM manufacturers of these laptops achieve this?
Thanks.
It looks like these are borderless windows.
For example, have a look at the task switcher window:
Related question:
Windows 8 Layered Windows Over Metro Apps
If you want a window on top of Metro, you need it to declare accessibility.

minimize fullscreen Xlib OpenGL Window

I'm currently trying to enable alt-tabbing out of my fullscreen Xlib OpenGL window, but am having some difficulties. I've tried XUnmapWindow(..), which kindof works, but the resolution does not reset (unless I should be doing that manually?) and my Xlib window does not appear as a minimized window (i.e. I can't alt-tab back into the window, even though the app still seems to be running in the background).
The next thing I tried was changing my window from fullscreen to windowed mode (i.e. re-creating the window over again in windowed mode), but obviously, I'd rather not have to do that.
I'm listening to FocusOut and FocusIn events, and the FocusOut seems to be called when I alt-tab, but I'm just not sure how to get my app to minimize properly. If I don't do anything in my code when a FocusOut event is called, my app doesn't do anything (i.e. I can't minimize the window).
Any help would be appreciated!
Edit: Unfortunately, I've been unable to get X Windows to properly minimize a fullscreen window. So, to work around this problem I've decided to destroy() the fullscreen window and then create() a new window in windowed mode. Seems to work well.
XUnmapWindow() completely removes the window from the display. Minimizing a Window happens through EMWH ICCCM state, so that the window manager knows, that the window is still there in some form. And like you already assumed you're responsible for resetting the screen resolution. This is BTW the very same in Windows.
EDIT:
Minimizing a Window in Xlib is done with XIconifyWindow, which will take care to set the right ICCCM properties, and unmaps the window. Both must be done to interact properly with the WM. However X11 only defines the methods, not the policy, so when unmapping a fullscreen window you're also responsible to reset the screen resolution, like I already wrote above.
On a side note: I suggest you don't change the resolution at all, but instead, if such is available, render to a Framebuffer Object of the target size, and map the final result to the full, native screen size. If you combine this with native resolution text/HUD overlays (I assume this is for a game or similar), you get much higher percieved quality and save the resolution switching. You may even combine this with taking a screenshot of the desktop and gradually fading to your content.
EDIT 2 for reference
:
XIconifyWindow is just a helper/convenience function, it's source code is
/*
* This function instructs the window manager to change this window from
* NormalState to IconicState.
*/
Status XIconifyWindow(Display *dpy, Window w, int screen)
{
XClientMessageEvent ev;
Atom prop;
prop = XInternAtom(dpy, "WM_CHANGE_STATE", False);
if(prop == None)
return False;
ev.type = ClientMessage;
ev.window = w;
ev.message_type = prop;
ev.format = 32;
ev.data.l[0] = IconicState;
return XSendEvent(dpy, RootWindow(dpy, screen), False,
SubstructureRedirectMask|SubstructureNotifyMask,
(XEvent *)&ev);
}
You can try to do it like this :
XEvent xev;
Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
Atom wm_hide_win = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False);
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
xev.xclient.data.l[1] = wm_hide_win;
XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureNotifyMask, &xev);
EDIT
If you have access to gnome API, you can use wnck_window_minimize(), or take a look into the source for that function.

Best Method for Minimizable Fullscreen Window

I'm coding a short game in C++ and Win32, and I want to be able to make it in fullscreen with a fixed size. I also want the user to be able to switch focus between the game window and other windows as much as he/she wants without any weird screen glitches.
So far I know of the ChangeDisplaySettings function and creating the window with the WS_POPUP style at initialization to make it fullscreen. To detect the user switching focus to other windows by way of alt+tab or otherwise, what messages should I be handling on the window's WndProc or should I be using another function? When loss of focus is detected should I only call ChangeDisplaySettings(NULL, 0); or are there other functions I should call as well? And what method should I use to handle focus back into the window?
Also can anyone give me some info on how to make it work smoothly for different screen sizes?
Thanks for any help.
If you want an exclusive full screen window, use DirectX.
But I don't recommend it. Changing the display mode causes glitches, rearranges the users icons and so on. Whether done by you, or Direct X.
Rather create a normal window at your native res, and let the user maximize it if wanted.
You could also use the GDI+ library of Windows XP (and newer) to use hardware-accelerated stretching (draw in 640x480, let GDI+ resize it to the native resolution). Then you don't need exclusive mode of DirectDraw nor ChangeDisplaySettings.
Also drawing into a 640x480 big background buffer and bit blitting it on the drawing surface via StretchBlt can be a performant solution.