I have an application in SDL 2.0.3 that enters relative mouse mode before entering the main game loop. In addition, function mouse_input is called in each step:
int mdltx = 0, mdlty = 0;
void mouse_input () {
auto r = SDL_GetRelativeMouseState(&mdltx, &mdlty);
if (mdltx != 0 || mdlty != 0)
cout << "(" << mdltx << "," << mdlty << ")" << endl;
// Update mouse key presses
mpul = !!(r&SDL_BUTTON(1)) | ((!!(r&SDL_BUTTON(3)))<<1);
}
According to the documentation of SDL_GetRelativeMouseState:
(...) x and y are set to the mouse deltas since the last call to SDL_GetRelativeMouseState() or since event initialization.
I've added the output lines for debugging purposes, because the resulting effect in the application was very awkward. It turns out that each time I move the mouse (and only when I move it), the console prints values in an unreasonable range. Below is a sample from doing simple mouse movements. The affected axis seems correct (moving horizontally will set mdlty to 0 and moving vertically will set mdltx to 0), but the numbers can get much higher than the screen resolution, and all of them are positive, regardless of the direction I move the mouse.
(342,216)
(47290,0)
(23696,0)
(23730,0)
(23764,0)
(23799,0)
(71190,0)
(117970,83397)
(23491,41802)
(23457,0)
(23423,83811)
(0,41871)
(23389,208322)
(23355,82847)
(0,41320)
(46812,0)
I have been looking around the web for people having the same problem, without any success.
Also note that this application was previously made for SDL 1, relying on SDL_GetMouseState and SDL_WarpMouse, but the latter function does not seem to do anything in some platforms. I'm working on the application under an Arch Linux + LXDE installation, which seems to simply ignore the mouse warp. This is the same machine where this other strange behaviour is happening.
The question is: why is this happening and how can I fix it with compatibility in mind, while keeping the advantages of having relative mouse mode? I even wonder if it could be an issue within SDL itself.
For anyone else struggling with this problem, it might help to set:
SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1", SDL_HINT_OVERRIDE);
SDL_SetRelativeMouseMode(SDL_TRUE);
This seems to give you relative mouse-output, where the center of the screen is (0,0).
However for me it doesn't currently reset the Cursor-coordinates properly, so while every frame resets this to (0,0), it jumps straight to the previous coord += movement.
This is a lot better than the alternative though, it seems.
The same code is working in a different machine, so this seems to be a bug. And it seems that some people found it too, with a broader range of misbehaviours than the one mentioned.
https://bugzilla.libsdl.org/show_bug.cgi?id=2150
Related
I'm currently designing a CLI interface for linux, and for various reasons I am not able to use ncurses. I am using exclusively C++ and the Qt framework.
Therefore, in order to have a user-friendly interface, I have to run this getch loop in a separate thread:
https://stackoverflow.com/a/912796/3605689
Which basically means I have to implement all basic functionalities (such as backspace) by myself. I have already implemented command completion and command history(like when you press tab or uparrow/downarrow in linux), but I can't figure out how to implement leftarrow/rightarrow (aka seeking through the typeahead).
Normally, I implement it like this: upon every gech which is not equal to -1, I check whether the user has pressed a special key (one that modifies the typeahead somehow). I then clear the stdout using the following function:
void inputobject::clear_line(int nletters)
{
QTextStream(stdout) << "\033[2K";
for(int i = 0; i < nletters;i++){
QTextStream(stdout) << "\b";
}
rewind(stdout);
}
And replace it with something else, effectively simulating the typeahead. For example, in the case of backspace, I would save the command call clear_line, and print the command out again, just with one less letter, behaving exactly as a normal console application would.
My real problem is with the cursor, in the case of left/rightarrow, I need to move the cursor visual in order to be able to indicate where in the text is the user seeking:
Because of the nature of how I rewrite the given stdout line to simulate the typeahead, it does not really matter where the cursor REALLY is, as long as it stays on the same line - it is just the visual that matters. How can I achieve moving the cursor visual on linux?
The answer was provided in the comment by Evilruff:
Cursor Movement
ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:
Position the Cursor:
\033[;H
Or
\033[L;Cf
puts the cursor at line L and column C.
Move the cursor up N lines:
\033[NA
Move the cursor down N lines:
\033[NB
Move the cursor forward N columns:
\033[NC
Move the cursor backward N columns:
\033[ND
Clear the screen, move to (0,0):
\033[2J
Erase to end of line:
\033[K
Save cursor position:
\033[s
Restore cursor position:
\033[u
Not using ncurses and co is a serious limitation.
It is hell to make correct input/output on shell for displaying anything.
The only others real solutions (I can't think as a solution to reimplement a ncurse-like library) I think of are:
making call to dialog (for some example www.linuxjournal.com/article/2807 and for the doc: http://linux.die.net/man/1/dialog)
using the framebuffer mecanism with Qt4 (here)
I've only recently started learning to code (About 3 days ago, to be exact!) so I really have no idea what I'm doing, to the point that I'm having trouble researching answers to my questions because I don't really know the terminology for anything.
Anyway, I'm learning on learncpp.com, and I'm up to 1.4a – "A first look at function parameters and arguments".
I tried to run this piece of code:
#include <iostream>
void printValues(int x, int y)
{
std::cout << x << std::endl;
std::cout << y << std::endl;
}
int main()
{
printValues(6, 7);
return 0;
}
Apparently it's supposed to spit out:
6
7
in the console window.
However, when I run it, it just says (lldb) in the console window and in the variable window it says:
[A]x = int (6)
[A]y = int (7)
The program also doesn't seem to finish running as it should – it doesn't spit out the return number at the end and when I try to change it and rerun it it asks if I want to terminate the program that's already running.
If it's any help, it highlights this line in green:
std::cout << x << std::endl;
It might also be worth noting that the tutorials on the website use Visual Studios, so I assume there's a difference between two programs that's causing me to have a problem?
Sorry if there is an obvious way to find the answer to this question, I've done some Googling and I tried watching Youtube tutorials etc. but I can't seem to find anything addressing my issue. Maybe I'm not looking in the right place.
If anybody would be able to help me or even direct me to where I might find an answer that would be much appreciated.
Thank you!
Did you set a breakpoint on that line? Usually the debugger will stop on a line if there's an error, or the developer set a breakpoint on that line. If it's highlighted in green, that's a breakpoint. You should see a blue pointer to the left of the line, like this:
If you click on it, it will turn light blue and the breakpoint will be disabled. You can then either type "continue" at the prompt, or press the continue button (it's a right-pointing triangle with a rectangle to the left of it, sort of like the "Play/Pause" button on a music player).
To remove the breakpoint, grab the blue arrow and drag it to the left and then let go of it. It should disappear in a puff of smoke.
I'm currently designing a CLI interface for linux, and for various reasons I am not able to use ncurses. I am using exclusively C++ and the Qt framework.
Therefore, in order to have a user-friendly interface, I have to run this getch loop in a separate thread:
https://stackoverflow.com/a/912796/3605689
Which basically means I have to implement all basic functionalities (such as backspace) by myself. I have already implemented command completion and command history(like when you press tab or uparrow/downarrow in linux), but I can't figure out how to implement leftarrow/rightarrow (aka seeking through the typeahead).
Normally, I implement it like this: upon every gech which is not equal to -1, I check whether the user has pressed a special key (one that modifies the typeahead somehow). I then clear the stdout using the following function:
void inputobject::clear_line(int nletters)
{
QTextStream(stdout) << "\033[2K";
for(int i = 0; i < nletters;i++){
QTextStream(stdout) << "\b";
}
rewind(stdout);
}
And replace it with something else, effectively simulating the typeahead. For example, in the case of backspace, I would save the command call clear_line, and print the command out again, just with one less letter, behaving exactly as a normal console application would.
My real problem is with the cursor, in the case of left/rightarrow, I need to move the cursor visual in order to be able to indicate where in the text is the user seeking:
Because of the nature of how I rewrite the given stdout line to simulate the typeahead, it does not really matter where the cursor REALLY is, as long as it stays on the same line - it is just the visual that matters. How can I achieve moving the cursor visual on linux?
The answer was provided in the comment by Evilruff:
Cursor Movement
ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:
Position the Cursor:
\033[;H
Or
\033[L;Cf
puts the cursor at line L and column C.
Move the cursor up N lines:
\033[NA
Move the cursor down N lines:
\033[NB
Move the cursor forward N columns:
\033[NC
Move the cursor backward N columns:
\033[ND
Clear the screen, move to (0,0):
\033[2J
Erase to end of line:
\033[K
Save cursor position:
\033[s
Restore cursor position:
\033[u
Not using ncurses and co is a serious limitation.
It is hell to make correct input/output on shell for displaying anything.
The only others real solutions (I can't think as a solution to reimplement a ncurse-like library) I think of are:
making call to dialog (for some example www.linuxjournal.com/article/2807 and for the doc: http://linux.die.net/man/1/dialog)
using the framebuffer mecanism with Qt4 (here)
As you can see the upper dark X's are cut even though there is space for them.
This happens because they have changed color and are printed backwards (from right to left).
Is this a bug, faulty code, a bad setup on my system or (I doubt it) like it is supposed to be?
Here is the code that generates this output:
#include <Windows.h>
#include <iostream>
void moveTo(int x,int y){
COORD kord={x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),kord);
}
void setColor(WORD attributes){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes);
}
void main(){
for(int i=9;i+1;i--)
{
moveTo(i,0);
std::cout.put('X');
}
for(int i=-10;i;i++)
{
moveTo(i+10,1);
std::cout.put('X');
}
setColor(8);
for(int i=9;i+1;i--)
{
moveTo(i,2);
std::cout.put('X');
}
for(int i=-10;i;i++)
{
moveTo(i+10,3);
std::cout.put('X');
}
setColor(7);
for(int i=9;i+1;i--)
{
moveTo(i,4);
std::cout.put('X');
}
for(int i=-10;i;i++)
{
moveTo(i+10,5);
std::cout.put('X');
}
std::cin.get();
}
This is a bug in Windows.
As mentioned in the errata by Hans Passant:
I repro too, VS2008 on Win7. Cool bug. Changing the console font fixes it.
Let's use this bug isolation. I recognize this font as Petite Terminal, which implies you both most likely configured this project as a Win32 Console Application. The additional repro with GCC confirms this hypothesis, and we will assume, from a practical standpoint, that all of you were getting a 32-bit console application running inside of a Windows terminal.
The question becomes why it's writing exactly one additional column of pixels in the context of the default terminal font, color 8, and backwards writing into a console screen buffer.
Specifically, let's break this problem up into its component pieces:
When a write is issued, a character is written to a location in the terminal array
When the default color (7) is selected, pixels do not overflow into other buffers within the array
When color 8 is selected, an additional column of pixels is written to the next region of the buffer, which is only visible when the text is recited backwards
Because of the presence of overspill in (3), this is a bug.
Quoting Raymond Chen:
The console rendering model assumes each character fits neatly inside
its fixed-sized cell. When a new character is written to a cell, the
old cell is overprinted with the new character, but if the old
character has overhang or underhang, those extra pixels are left
behind since they "spilled over" the required cell and infected
neighbor cells. Similarly, if a neighboring character "spilled over",
those "spillover pixels" would get erased.
The set of fonts that could be used in the console window was trimmed
to the fonts that were tested and known to work acceptably in console
windows. For English systems, this brought us down to Lucida Console
and Terminal.
...
"Well, that's stupid. You should've stopped me from choosing a font
that so clearly results in nonsense."
And that's what we did.
Not that I'm blaming Raymond on this one, but he authoritatively illustrates this as a "can't happen."
The selection and testing of console fonts for Windows should have caught this. The fact that it's even an issue at all is an aberration.
I am trying to make the copies of the builtin functions and adding a x to their name so i can understand each functions working.While writing a function for clrscr() i am confused about how it works.Does it use 2 nested loops and print (" ") i.e space all over the screen or it prints("\n") over the screen?Or what?
I tried this:
#include<stdio.h>
#include<conio.h>
void main(void)
{
printf("press any key to make clrscr() work");
getch();
for(int i=0;i<50;i++)
{
printf("\n");
}
// to make the screen come to 1,1
gotoxy(1,1);
getch();
}
clrscr() implementation may depend on the environment your console application runs. Usually it sends the ClearScreen control character (0x0C) to the console driver, that actually clears the screen.
The driver knows about character space to clear as well as all attributes (blink, underline,...) to reset.
If you dont want the driver to handle 0x0C, you can mimic this with 50 times calling printf("\n"). but calling 50x80 calling poutchar(' ') is not similar to calling clrsrc(), since the cursor will be advanced by one what may put it in the next line after scrolling the screen content.
Further you should regard, that the behaviour of the screen depends on the implementation. When the cursor position is in the right column and you output one character the cursor position may stay at the right edge or it may cause a new line. Whe you cursor position is in the lower right corner the next character may cause a new line including scrolling the screen content by one line.
The best way would be to imaging what clrscr() would do and let it make it's job.