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
Dual monitor fix #1238
Dual monitor fix #1238
Conversation
Ah, very cool. Found a similar solution but couldn't be bothered trying to figure out the correct types etc. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a quick note on style: indentation is broken in a few places, there are extra spaces at the end of lines and some parenthesis are missing (see here). Otherwise, I can't judge much the patch as I can't test it. I'll trust @MarioLiebisch for that.
That being said, thanks for the PR! If you manage to fix the issues and squash all that in a nice commit that'd be awesome! :-)
Commit says "Mouse still can't be used in the second screen.". Do you have some ideas to fix that as well?
// Check XRandR version, 1.2 required | ||
if(!XRRQueryVersion(m_display, &xRandRMajor, &xRandRMinor) || xRandRMajor < 1 || xRandRMinor < 2 ) | ||
{ | ||
err() << "XRandR is to old" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/to/too/
Check will fail once v.2 is release (although it's not for tomorrow).
I know it's buggy in its current form and I think this is the right way to go, but I don't have a multi monitor setup to actually test this. However, running a program in fullscreen typically means you can't interact with anything on the second screen/desktop since it has exclusive access. At least that's how it's working on Windows. You can't force the ability to continue working on a secondary display. |
Can this be tested in a VM? |
In theory, but never got multiple screens to work properly. I can set two displays, but "Displays" still only lists a single one. |
e10a5c3
to
4d18bc5
Compare
I changed XRandr check to accept a potential v2. The message "Mouse still can't be used in the second screen." was inaccurate, actually it's possible but you have to alt+tab. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update. I think X11 is tricky enough to be a bit picky about the implementation in order to make it easily maintainable. :-)
@@ -56,7 +56,7 @@ | |||
#include <SFML/Window/Unix/GlxContext.hpp> | |||
typedef sf::priv::GlxContext ContextType; | |||
#endif | |||
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra spaces
output = XRRGetOutputPrimary(m_display, rootWindow); | ||
|
||
// Check if output return is valid, otherwise use the first screen | ||
if(output == None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing space after if
m_oldVideoMode = XRRConfigCurrentConfiguration(config, ¤tRotation); | ||
// If version > 1.2 get the primary screen else take the first screen | ||
RROutput output; | ||
if ((xRandRMajor == 1 && xRandRMinor >= 3) || xRandRMajor > 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to follow strictly our style rules, more parentheses are needed. But I'd argue it's more readable as is. Do others agree? (It's also the case in a few other places.)
XRRFreeScreenResources(res); | ||
|
||
// If outputInfo->connection == RR_Disconnected, free output info | ||
if(!outputInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing space
// Free output info | ||
XRRFreeOutputInfo(outputInfo); | ||
|
||
// Free crtc info |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the // Free <stuff>
comment should be removed -- they don't bring much.
} | ||
|
||
// Check XRandR version, 1.2 required | ||
if (!XRRQueryVersion(m_display, &xRandRMajor, &xRandRMinor) || xRandRMajor < 1 || (xRandRMajor == 1 && xRandRMinor < 2 )) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
} // namespace priv | ||
|
||
} // namespace sf | ||
}// namespace sf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space was removed.
|
||
// Set "this" as the current fullscreen window | ||
fullscreenWindow = this; | ||
for (int i = 0; i < res->nmode; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it was like that before, but it would be much more elegant IMO to have i < res->nmode && !modeFound
as a loop condition and remove the break statement
, wouldn't it?
return; | ||
} | ||
|
||
// Get crtc info from crtc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
X11 & cie being far from trivial, I'd add in the comment what kind of concrete info we're trying to get from CRTC. (screen dimension and rotation?) Otherwise the comment seems of no additional interest than the next function call.
/// \return True if a valid XRandR version found, false otherwise | ||
/// | ||
//////////////////////////////////////////////////////////// | ||
bool checkXRandR(int &xRandRMajor, int &xRandRMinor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be int& x
and not int &x
.
b635dce
to
24cf017
Compare
I pushed a new revision. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update!
Regarding XRRGetOutputPrimary
, looking at https://cgit.freedesktop.org/xorg/lib/libXrandr/refs/tags it seems the function is first tagged in 1.3. It should simply fail to compile with older version, unless I missed something, so we could remove the runtime check altogether.
If, for some X11 specific reason I'm not aware of, the runtime check is best/okay, then I've no complain. Otherwise, it would be actually a good news as the code would be simpler: we just need a version requirement in CMake and that's it. (v1.3 is 8 years old so it should not be an issue to assume it's available on SFML supported system, hence no need to have conditional code for backward compatibility IMO.)
// Get the available screen sizes | ||
int nbSizes; | ||
XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); | ||
// If version > 1.2 get the primary screen else take the first screen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: should be >=
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually version > 1.2, but maybe >= 1.3 is more readable.
RROutput output; | ||
if ((xRandRMajor == 1 && xRandRMinor >= 3) || xRandRMajor > 1) | ||
{ | ||
output = XRRGetOutputPrimary(m_display, rootWindow); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually wondering: is this function define in xrandr 1.2? Isn't it instead defined in 1.3+?
bed993d
to
03610d4
Compare
You are absolutely right about XRRGetOutputPrimary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be interesting to have feedback from others at this point I think. Some things are beyond my knowledge. @bloodsword, it goes without saying that your point of view is also welcome on those issues!
if (!XQueryExtension(m_display, "RANDR", &version, &version, &version)) | ||
// Check if the XRandR extension | ||
int xRandRMajor, xRandRMinor; | ||
if (!checkXRandR(xRandRMajor, xRandRMinor)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't care about the actual version, but just the presence of the extension, then I'd remove the two parameters of checkXRandR
. Having the function is fine, but the simpler it is the better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not enough familiar with X11 & cie, but do we need to actually check for the extension? Or can't we assume that if we were able to link against xrandr the extension will be available at runtime? @binary1248, since you edited those line before, could you clarify that for me. Thanks. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As strange as it sounds, I've experienced implementations where not calling XQueryExtension
would cause the extension to fail even if it should be supported. It seemed like calling XQueryExtension
would load the extension or something. So even if it should be supported, performing the runtime "check" is still the safer variant.
// Check if the XRandR extension is present | ||
int version; | ||
if (!XQueryExtension(m_display, "RANDR", &version, &version, &version)) | ||
// Check if the XRandR extension |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment was truncated, leaving out the end of the sentence.
int nbSizes; | ||
XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); | ||
// Compile time check : if version >= 1.3 get the primary screen else take the first screen | ||
#if (RANDR_MAJOR == 1 && RANDR_MINOR >= 3) || RANDR_MAJOR > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question I'm asking myself is, do really want to support older versions? If not, it would make the code much simpler without those conditional compilation macros. What do @binary1248, @Bromeon and @MarioLiebisch (or anyone who's familiar with Linux actually) think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer runtime version checking. It is done in the above code already anyway, and X on Linux doesn't exactly make it trivial to detect library versions during compile time. X works based on Client-Server so it might even be possible that the header you compile against on the system doesn't match what the X server is actually running.
if (!XQueryExtension(m_display, "RANDR", &version, &version, &version)) | ||
// Check if the XRandR extension | ||
int xRandRMajor, xRandRMinor; | ||
if (!checkXRandR(xRandRMajor, xRandRMinor)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As strange as it sounds, I've experienced implementations where not calling XQueryExtension
would cause the extension to fail even if it should be supported. It seemed like calling XQueryExtension
would load the extension or something. So even if it should be supported, performing the runtime "check" is still the safer variant.
{ | ||
// XRandR extension is not supported: we cannot use fullscreen mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no reason to remove this comment.
int nbSizes; | ||
XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); | ||
// Compile time check : if version >= 1.3 get the primary screen else take the first screen | ||
#if (RANDR_MAJOR == 1 && RANDR_MINOR >= 3) || RANDR_MAJOR > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer runtime version checking. It is done in the above code already anyway, and X on Linux doesn't exactly make it trivial to detect library versions during compile time. X works based on Client-Server so it might even be possible that the header you compile against on the system doesn't match what the X server is actually running.
|
||
if ((sizes[i].width == static_cast<int>(mode.width)) && (sizes[i].height == static_cast<int>(mode.height))) | ||
// If outputInfo->connection == RR_Disconnected, free output info | ||
if (!outputInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be outputInfo
and single line if
blocks omit brackets.
if (!modeFound) | ||
{ | ||
err() << "Failed to find a matching RRMode for fullscreen mode, switching to window mode" << std::endl; | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resources not freed here.
@bloodsword Can you follow up on @binary1248's review? |
@eXpl0it3r yes. I will try to push something this week. |
8ec0b62
to
bd631d8
Compare
Can someone provide a sample code for testing and what the expected/buggy behaviour looks like? |
I don't know what the buggy behaviour looks like since my last commit. Here is a sample code to test (press escape to quit) :
The normal behaviour should be a black fullscreen on one of your screen, your other screen should stay active. |
I attribute the test failure during my last test in part to my "exotic" screen setup. I can't test with 2 screens of the same resolution because... well... I simply don't have 2 screens with the same resolution. If others who can test using screens with the same resolution report that this is still an improvement over the state without it, I am willing to accept it as a partial solution on the way to something more complete. |
I have no problem with same resolution screens (1280x1024 x 2), |
edit: Apologies. See the next post. |
Actually, I take all of that back. I did a double check and the damn thing was still linking to the current version of master. e18b9d2 behaves correctly for me (1920x1080 dual monitor setup). |
No problem. When I booted my Mint trying to reproduce the behaviour you describe I did the same mistake :) |
EDIT: I misunderstood the intention of this PR. Works for me, Fedora 28, KDE. +1 |
Tested on Ubuntu 18.10, NVIDIA driver 396.51. Both "master" and this branch work as expected for me... One monitor is 1366x768. The other is 1920x1080. The fullscreen shows up on the primary monitor. |
Nice to read your feedbacks. |
Merged in 46ce05c |
SFML Tasks
This should fix #1226.
XRRSetCrtcConfig is now used to set video mode instead of XRRSetScreenConfig.