X11 -- choosing which screen to appear on

Found a bug in R'n'D? Report it here!

Moderators: Flumminator, Zomis

filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

X11 -- choosing which screen to appear on

Post by filbo »

Hi, this is a bit obscure but maybe there's a solution?

I'm using 2 screens on my Linux system. Still LinuxMint 17.3 (very out of date). MATE desktop environment 1.12.0, Marco window manager, SDL2 2.0.2; RnD 4.2.3.1

I have a main screen which is 1280x1024; and a giant 43" TV, in portrait mode, which is attached to all 3 of my main machines and swapped between them depending what I'm doing. All 3 maintain windows on it, but obviously I can only see the ones belonging to the machine whose HDMI connection is currently 'active'.

So I'm sitting here on my personal desktop, looking at the 1280x1024 screen. I start RnD, and -- it appears -- or doesn't appear -- on the giant vertical screen. To retrieve it I have to switch the HDMI input on the TV, drag it back, then switch the TV back.(*)

This shows how the system sees the 2 screens:

Code: Select all

$ xrandr | grep -w connected
HDMI1 connected primary 2160x3840+1280+0 right (normal left inverted right x axis y axis) 800mm x 450mm
VGA1 connected 1280x1024+0+2160 (normal left inverted right x axis y axis) 338mm x 270mm
(and I see that it has the dot pitch of the large screen wrong, but that's irrelevant...)

So, for instance, `xterm -geometry +0+2160` pops up an xterm in the upper left corner of the small screen.

Unfortunately:

Code: Select all

$ ./rocksndiamonds -geometry +20+2180
[FATAL] unrecognized option '-geometry'
[FATAL] try option '--help' for more information
[FATAL] aborting
(same with --geometry)

I looked for SDL options and the closest I could find was the environment variable SDL_VIDEO_CENTERED=center, but that doesn't even seem to apply to SDL2.

So I'm looking for a way to specify an X11 geometry or a Xinerama screen number or an Xrandr screen number (I've never really properly understood the relationship between or distinction between Xinerama and Xrandr...)

(*)The reality is somewhat more complex. The HDMI screen is 'still there' while the physical display is connected to a different host or powered off. I can mouse over and grab the window without actually seeing what I'm doing, but it's quite hard to actually hit it. Not as hard as having to catch its titlebar, because my window manager recognizes Alt+drag (anywhere within a window) as drag-to-move. AND, having to deal with this all the time, I actually have `x11vnc` running to cast the HDMI screen, and a VNC client in a window on the small screen, showing the big screen in 1/4 scale, and normally minimized. So I can, without powering on or switching the big screen, pop up the VNC and drag the window across the horizontal boundary between screens, onto the small screen. But this is still a hassle.

None of this bizarrity is actually relevant; the baseline problem is: give me a way to tell RnD which of multiple X11 screens to appear on! -geometry (or --geometry) would be perfect, since it lets you set size as well as position; RnD should come up at the specified location in the specified dimensions (doing whatever it does to fix aspect ratio -- which appears to be, allow the window to have 'wrong' aspect ratio, just use the largest interior rectangle which has the correct aspect ratio). --geometry of course allows either or both of location & size to be specified. There is surely X library code to parse it (looks like xparsegeometry(3)).

Really, SDL itself, when built for X11, ought to intercept those args. But maybe it is not set up to fool around with argv outside the control of the calling program. Maybe there's something RnD needs to do to tell it 'hey, parse this here --geometry flag I received'. SDL doesn't intend that all SDL programs be fullscreen, so it ought to have a way to bridge the local OS's way of specifying a size into the generic program inside...
filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

Re: X11 -- choosing which screen to appear on

Post by filbo »

TLDR :)

Please make a way to specify on command line which of N displays to appear on; or, best, just implement the standard X11 --geometry flag.
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

Hi filbo,

yes, support for the standard X11 style "-geometry" flag in R'n'D would be nice. I assume that SDL does not support it directly because X11 is only one of many targets of that library, and Windows, Mac, Android etc. do not have it. (And probably most people are generally not starting GUI programs via command line anymore nowadays.)

As a quick workaround to ease your pain, please try the following patch:

Code: Select all

--- a/src/libgame/sdl.c
+++ b/src/libgame/sdl.c
@@ -593,8 +593,8 @@ static boolean SDLCreateScreen(boolean fullscreen)

   if (sdl_window == NULL)
     sdl_window = SDL_CreateWindow(program.window_title,
-                                 SDL_WINDOWPOS_CENTERED,
-                                 SDL_WINDOWPOS_CENTERED,
+                                 SDL_WINDOWPOS_CENTERED_DISPLAY(1),
+                                 SDL_WINDOWPOS_CENTERED_DISPLAY(1),
                                  video.window_width,
                                  video.window_height,
                                  surface_flags);
@@ -794,7 +794,7 @@ void SDLSetWindowFullscreen(boolean fullscreen)
   {
     SDLSetWindowScaling(setup.window_scaling_percent);
     SDL_SetWindowPosition(sdl_window,
-                         SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+                         SDL_WINDOWPOS_CENTERED_DISPLAY(1), SDL_WINDOWPOS_CENTERED_DISPLAY(1));

     video.fullscreen_initial = FALSE;
   }
Maybe I could also add a "-screen <nr>" option to use that (so the patch would work in a more generic way).

BTW: I've successfully tested this patch on a Mac with two screens.

Hope that helps!
filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

Re: X11 -- choosing which screen to appear on

Post by filbo »

Thanks, that seems to do it!

New bug you will now hear: 'always starts on the first screen'! :)

So yes, -screen would be good.

I don't know how SDL counts its screens, there will probably be cases where the 'first' screen isn't the one that's wanted... No, wait, this patches it to use '2nd screen'! It's a patch just for my system!

Right, definitely needs a flag...
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

While fiddling around with window positioning (also see here), I've also just added a new option "--display <number>" to open the game window on the specified display, which seems to work fine.

Still have to test this with some multi-monitor setups, though...
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

Tested this on a MacbookPro with external monitor yesterday, and did not have success -- apparently the program (or SDL library) only sees the internal screen (ID 0), but not the external one (ID 1), so "--display 1" did not work. :(

Could anybody check this with the current code from Git repo "build.artsoft.org" on a Linux system with more than one monitor, for example?
filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

Re: X11 -- choosing which screen to appear on

Post by filbo »

Why do you have a separate repo hostname instead of just branches on the one repo?

I ask this from the perspective of 'I am comfortable switching between remote branches on a single repo, but haven't learned git multi-repo stuff yet...' :)

I just tried this and kablooie:

Code: Select all

$ git remote add --fetch build https://build.artsoft.org
Updating build
fatal: unable to access 'https://build.artsoft.org/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
error: Could not fetch build
I got this much further:

Code: Select all

$ GIT_SSL_NO_VERIFY=true git fetch build
fatal: repository 'https://artsoft05.vtnx.net/' not found
$ git remote remove build
$ GIT_SSL_NO_VERIFY=true git remote add --fetch build https://build.artsoft.org/rocksndiamonds.git
Updating build
fatal: repository 'https://artsoft05.vtnx.net/rocksndiamonds.git/' not found
error: Could not fetch build
... and also tried build.git, master.git.

I don't know the syntax for `git remote query what-the-heck-is-the-path?`

... but wait, there's more! viewtopic.php?p=17887 mentions the path, so:

Code: Select all

$ GIT_SSL_NO_VERIFY=true git remote add --fetch build git@build.artsoft.org:~/rocksndiamonds.git
Updating build
Warning: Permanently added 'build.artsoft.org,5.28.40.88' (ECDSA) to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
error: Could not fetch build
... looks like I need credentials?
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

Oops! :oops:
Why do you have a separate repo hostname instead of just branches on the one repo?
Because "build.artsoft.org" was intended to be used for (my own) internal development purposes, while "git.artsoft.org" was meant to be the publicly accessible repository.

I especially did this separation because of heavy history rewriting during development (using "git rebase") in combination with pushing such changes to a central repository (using "git push --force"), causing local branches to be broken (which does not matter / is handled correctly by my build script).

So my main intention of using a second repo was to (a) prevent breaking branches that people might already have pulled, and (b) being able to hide some new stuff from the public (which may not really be necessary).

Therefore, just using development branches on the public repo should also work fine (especially as I can already tell my build script to use different branches for building development versions).

But I totally forgot that accessing "build.artsoft.org" requires a valid SSH public key! Sorry for that! :shock: :oops:

As a quick workaround, I have just pushed the lasted code to branch "master-next-patch-release" -- please use that one (and forget about that "internal" repository for now).
filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

Re: X11 -- choosing which screen to appear on

Post by filbo »

So, origin/master-next-patch-release doesn't build:

Code: Select all

gcc  -DDEBUG -g -Wall -Wstrict-prototypes -Wmissing-prototypes -DTARGET_SDL2 -I/usr/include/SDL2 -D_REENTRANT     -c files.c
files.c: In function ‘CreateCollectElementImages’:
files.c:13492:51: error: ‘SDL_PIXELFORMAT_RGBA32’ undeclared (first use in this function)
     SDL_ConvertSurfaceFormat(dst_bitmap->surface, SDL_PIXELFORMAT_RGBA32, 0);
My SDL libs are 'current' from the Ubuntu repositories -- for my ancient Linux Mint 'rosa' 17.3 desktop, based on Ubuntu 'trusty' 14.04.

Code: Select all

$ sdl2-config --version
2.0.2
$ aptitude show libsdl2-2.0-0 | grep Version:
Version: 2.0.2+dfsg1-3ubuntu1.3
-- commit b137e748 makes RnD incompatible with 'sufficiently old' SDL2 libs. (Ironically, the very next commit, f8666bcc, is 'fixed compiling with SDL versions before 2.0.14 without SDL_OpenURL()'...)

Obviously I should have newer libs (and OS!) -- but this will cause trouble elsewhere. Can you #ifdef around it or something?

I see it's to implement a command line option I have no reason to use, so I've just commented out those calls for now...
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

Yes, as a temporary workaround to be able to compile, just throw away the contents of this function; it won't hurt.

I'll add another "I'm using very old SDL libraries" workaround for this. :-)
filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

Re: X11 -- choosing which screen to appear on

Post by filbo »

Code: Select all

$ ./rocksndiamonds --display 9
[WARN] invalid display 9 -- using display 0 (SDL_GetNumVideoDisplays() returns 0)
I don't have 9 displays, but I do have two. RnD 'future' insists on displaying on the first one, which we see here is due to SDL insisting only one exists.

It plays fine on the 2nd screen if I drag the window there once it's up.

Here's my collection of displays:

Code: Select all

$ xrandr | grep connected
HDMI1 connected 2160x3840+1280+0 right (normal left inverted right x axis y axis) 800mm x 450mm
VGA1 connected primary 1280x1024+0+2160 (normal left inverted right x axis y axis) 338mm x 270mm
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
According to https://wiki.libsdl.org/SDL_GetNumVideoDisplays, this API is supposed to return an integer >= 1. It is literally returning 0 for me. Your code only avoids going nuts by `MAX(0, MIN(display_nr, SDL_GetNumVideoDisplays() - 1))` -- paranoidly (correctly) worrying that it might return 0 when it shouldn't.

Anyway. I changed that to simply:`options.display_nr = display_nr;` -- and now "-display 1" causes it to appear on the HDMI display. Any other number falls back to the default VGA display. So at least for me, the problem seems to be that SDL_GetNumVideoDisplays() is broken and prevents you from even trying to use the other display, which otherwise works fine.

=====

BTW, somewhere along the way of playing with this, my ~/.rocksndiamonds/levelsetup.conf got trashed, completely losing the list of recently played levelsets :(

This turned out to be because I had run `make` in the directory rather than my `MAKE-CMD` script which applies -DBASE_PATH="\"/usr/share/games/rocksndiamonds\"". Without that, the binary only found a limited palette of levels in the source directory, which caused it to purge the 'last_level_series' config entries. Can you please make it *NOT* purge those entries even if they don't match the currently visible world of levelsets? This has plagued me for years and I've only just realized why / how it happens. The fragility is partly my fault (telling it to look for game data in a non-default place, then -- particularly -- mistakenly building without that directive). But it's partly the game's fault for destroying useful info when it doesn't meet its temporarily mistaken worldview.

Preferably they would just be undisturbed. But if it breaks the internal data models too much, maybe they could be saved as comments and NOT trashed on future runs? Then someone could at least manually edit them back to life if necessary... (It wouldn't be sufficient to save them as comments or a .bak file, then overwrite those on next run. It can take several runs to realize what has happened.)

=====

Also, while fooling around with the 'last played level sets' stuff, it felt like as a user experience enhancement, that line should appear on every screen of the levelset explorer; not just the 'root directory'. It should appear below the '.. (parent directory)' entry on every screen.

I should probably post these separately in the bugs forum...
filbo
Posts: 607
Joined: Fri Jun 20, 2014 10:06 am

Re: X11 -- choosing which screen to appear on

Post by filbo »

I'm not doing any further specific testing with this, it seems to just work -- as long as I prevent it from checking that such a screen number actually exists.

I'm having a new problem which I'm not sure if it's caused by the recent code updates. When I switch to a levelset I've solved some levels of, it's insisting that I haven't solved them; I have to turn off 'force solving levels' to be able to get past them. I noticed you added a 'tape solves level' tape-flag, is it now consulting that (in my old tapes which obviously don't have that flag) before letting me pass?
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

According to https://wiki.libsdl.org/SDL_GetNumVideoDisplays, this API is supposed to return an integer >= 1. It is literally returning 0 for me. Your code only avoids going nuts by `MAX(0, MIN(display_nr, SDL_GetNumVideoDisplays() - 1))` -- paranoidly (correctly) worrying that it might return 0 when it shouldn't.
Very strange. Just added the same test output (return code of "SDL_GetNumVideoDisplays()") as you did, and it returns "0" on both my outdated Linux system (using outdated SDL 2.0.6) and my up-to-date Mac system (using SDL 2.0.20, which is not the latest version, but was released in 2022). Even stranger that I wasn't able to find any indication (using Google) that this function seems to be broken on more than one platform, and apparently for a long time. :shock:

I will use the same workaround as you did, and simply try to open the window on the specified display, without doing any range checks. :?
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

Obviously I should have newer libs (and OS!) -- but this will cause trouble elsewhere. Can you #ifdef around it or something?
Fixed (keeping full functionality, although you won't need it).
I will use the same workaround as you did, and simply try to open the window on the specified display, without doing any range checks. :?
Just added this one, too.

Please "git pull" on branch "master-next-patch-release" for both fixes.
User avatar
Holger
Site Admin
Posts: 3773
Joined: Fri Jun 18, 2004 4:13 pm
Location: Germany
Contact:

Re: X11 -- choosing which screen to appear on

Post by Holger »

I'm having a new problem which I'm not sure if it's caused by the recent code updates. When I switch to a levelset I've solved some levels of, it's insisting that I haven't solved them; [...]
I've moved this to a separate thread in the "Bug Reports" section.
Post Reply