Xlib - window is not rendering - c++

I am creating library for Xlib (like gtk/qt, but simplified). And i don't see window at my desktop. GDB says nothing. What i must do to fix this bug? Already tried to move display declaration to main function. Used -g flag as compiling (to check with GDB). And no window! Seriously, it's awesome glitch!
FXL++ library:
#include <iostream>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
using namespace std;
class fxlpp{
public:
void init(){
disp = XOpenDisplay(NULL);
if(disp == NULL){ //error 1 if can't open display
cerr << "Can't open display" << endl;
exit(1);
}
screen = DefaultScreen(disp);
}
void mkWin(int winID, int x1, int y1, unsigned x2, unsigned y2){
win[winID] = XCreateSimpleWindow(disp, RootWindow(disp, screen), x1, y1, x2, y2, 0, BlackPixel(disp, screen), WhitePixel(disp, screen));
XSelectInput(disp, win[winID], ExposureMask | KeyPressMask);
XMapWindow(disp, win[winID]);
}
void mkCWin(int cWinID, int pWinID, int x1, int y1, int x2, int y2){
cWin[pWinID][cWinID] = XCreateSimpleWindow(disp, win[pWinID], x1, y1, x2, y2, 1, BlackPixel(disp, screen), WhitePixel(disp, screen));
XSelectInput(disp, cWin[pWinID][cWinID], ExposureMask | KeyPressMask);
XMapWindow(disp, cWin[pWinID][cWinID]);
}
protected:
Display *disp; //declare display pointer
int screen; //declare display num integer
Window win[129]; //declare window
Window cWin[129][129]; //declare child win array
XEvent event; //declare event handler
};
Code to test library:
#include <iostream>
#include "fxlpp.hpp"
using namespace std;
int main(){
class fxlpp fxlpp;
fxlpp.init();
fxlpp.mkWin(1, 100, 100, 500, 300);
sleep(2);
return 0;
}

As I wrote before, there's a lot more to X11 than just create a window, paint some lines on it and expect output. You must setup the X event loop to receive events, handle at a minumum exposure events, but also keyboard, mouse, etc. in the proper way. So I'm afraid it's not a bug, it's a design flaw in your program.
For a short tutorial, see here.

Although event loop is important most times, in this simple case you just need to call XFlush() after drawing.

Related

FLTK: Clearing a graph when drawing another

I wrote a simple FLTK program to draw a circle when clicking on the "Draw Circle" button and to draw a line when clicking on the "Draw Line" button. I supposed to have only one graph. But I got two graphs in the panel. I want only one showing and the other disappearing. The following is the code:
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Box.H>
using namespace std;
int flag = 0;
class Drawing : public Fl_Box {
void draw() {
fl_color(255, 0, 0);
int x, y, x1, y1;
if (flag == 1) {
double radius = 100;
x = (int)(w() / 2);
y = (int)(h() / 2);
fl_circle(x, y, radius);
}
else if (flag == -1) {
x = (int)(w() / 4);
y = (int)(h() / 4);
x1 = (int)(w() *3/ 4);
y1 = (int)(h() *3/ 4);
fl_line(x, y, x1, y1);
}
}
public:
Drawing(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H) {}
};
Drawing* d;
void circle_cb(Fl_Widget*, void*) {
flag = 1;
fl_overlay_clear();
d->redraw();
} // end sumbit_cb
void line_cb(Fl_Widget*, void*) {
flag = -1;
fl_overlay_clear();
d->redraw();
} // end clear_cb
int main(int argc, char** argv) {
Fl_Window* window = new Fl_Window(600, 550); // create a window, originally(400,400)
Drawing dr(0, 0, 600, 600);
d = &dr;
Fl_Button *b, *c;
b = new Fl_Button(150, 80, 100, 25, "&Draw Circle");
b->callback(circle_cb);
c = new Fl_Button(350, 80, 100, 25, "&Draw Line");
c->callback(line_cb);
window->end(); //show the window
window->show(argc, argv);
return Fl::run();
}
I have used fl_overlay_clear() to clear graph. However it is not working. Any help will be appreciated.
There are several issues that need to be fixed in your program, but first of all using the draw() method as you did is basically correct. However, using fl_overlay_clear(); is useless, you can remove it.
My solution: your widget doesn't have a solid background (boxtype), i.e. your draw method draws over the background over and over again w/o clearing it. There are several ways to solve this, but if you want to learn what happens, try this first: add window->resizable(window); before window->show(argc, argv);, run the program again and resize the window. You'll notice that the previous drawing disappears and only one drawing stays. That's because the background is cleared when you resize the widget.
Next step: add a solid boxtype:
d = &dr;
d->box(FL_DOWN_BOX);
and add Fl_Box::draw(); right at the beginning of your draw() method.
If you do that you may notice that your button(s) disappear when you click one of them - because your buttons are inside the area of your Drawing. The last thing(s) I fixed was to correct the coordinates of buttons and to enlarge the window (it was too small anyway to cover the entire Drawing). Here's my complete result:
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Box.H>
using namespace std;
int flag = 0;
class Drawing : public Fl_Box {
void draw() {
Fl_Box::draw();
fl_color(255, 0, 0);
int x, y, x1, y1;
if (flag == 1) {
double radius = 100;
x = (int)(w() / 2);
y = (int)(h() / 2);
fl_circle(x, y, radius);
} else if (flag == -1) {
x = (int)(w() / 4);
y = (int)(h() / 4);
x1 = (int)(w() * 3 / 4);
y1 = (int)(h() * 3 / 4);
fl_line(x, y, x1, y1);
}
}
public:
Drawing(int X, int Y, int W, int H)
: Fl_Box(X, Y, W, H) {}
};
Drawing *d;
void circle_cb(Fl_Widget *, void *) {
flag = 1;
// fl_overlay_clear(); // not useful
d->redraw();
} // end sumbit_cb
void line_cb(Fl_Widget *, void *) {
flag = -1;
// fl_overlay_clear(); // not useful
d->redraw();
} // end clear_cb
int main(int argc, char **argv) {
Fl_Window *window = new Fl_Window(600, 660); // create a window, originally(400,400)
Drawing dr(0, 60, 600, 600); // FIXED
d = &dr;
d->box(FL_DOWN_BOX); // ADDED
Fl_Button *b, *c;
b = new Fl_Button(150, 20, 100, 25, "&Draw Circle"); // FIXED
b->callback(circle_cb);
c = new Fl_Button(350, 20, 100, 25, "&Draw Line"); // FIXED
c->callback(line_cb);
window->end(); // show the window
window->resizable(window); // ADDED
window->show(argc, argv);
return Fl::run();
}
I believe this does what you want.
PS: the official FLTK support forum can be found on our website https://www.fltk.org/ and the direct link to the user forum (Google Groups) is https://groups.google.com/g/fltkgeneral
Just a quick addition to what Albrecht put so perfectly: FLTK drawing coordinates are relative to the window, not relative to the widget. You probably want to offset your drawing by the x() and y() coordinates of your widget.
In your handle() methods line_cb() , circle_cb() should call window()->make_current() and then fl_overlay_rect() after FL_DRAG events, and should call fl_overlay_clear() after a FL_RELEASE event. Refer for more details

Trying to Smoothly animate in console in c++

I'm trying to make smooth animations in the console window in c++. I'm using windows.h for functions like Ellipse, and LineTo. The issue is that the frames are very slow and blink a lot. Sometimes the frames get progressively slower and slower as the program moves along. I tried animating a circle that moves down to the right, and a line that goes from the upper left corner to wherever the circle is. When I used the LineTo function, the line was black. I don't know how to color it. Any help would be appreciated, I just want to be able to draw and animate in the console.
#include <windows.h>
void drawSprt(int x, int y) {
HWND handle = GetConsoleWindow();
HDC dc = GetDC(handle);
int r = 10;
int a;
COLORREF color = 0x00FFFFFF;
Ellipse( dc, x-r,y-r,x+r,y+r);
MoveToEx( dc, 0, 0, NULL);
LineTo( dc, x+r, y+r);
ReleaseDC(handle, dc);
}
int main() {
int x = 100;
int y = 100;
start:
drawSprt(x,y);
Sleep(500);
x+=5;
y+=5;
system("cls");
goto start;
}

Ncurses mvwprintw doesnt print

I have a simple program that has a main window and a small window on the bottom like (without the lines, thats just so you can see the two windows:
+------------------+
| |
| |
| |
+------------------+
| |
+------------------+
I want the bottom area to be a place where you can type in, and here is my source code:
#include <termios.h>
#include <bits/stdc++.h>
#include <ncurses.h>
int main()
{
int scrx;
int scry;
initscr();
cbreak();
noecho();
clear();
raw();
getmaxyx(stdscr, scrx, scry);
WINDOW* input = newwin(1, scrx, scry, 0);
std::string cmdbuf;
while(true)
{
int newx;
int newy;
getmaxyx(stdscr, newx, newy);
if(newx != scrx || newy != scry)
{
// do stuff;
}
char c = wgetch(input);
cmdbuf.push_back(c);
werase(input);
mvwprintw(input, 0, 0, cmdbuf.c_str());
refresh();
wrefresh(input);
}
}
However, it doesn't seem to print anything, just move my cursor (which gets suck halfway across the screen). How can I make it so that text actually gets printed and that my cursor actually moves across the full screen?
Tidied it up for you a bit. Press 'q' to quit. You get the idea.
#include <termios.h>
#include <bits/stdc++.h>
#include <ncurses.h>
int main()
{
int scrx, scry;
initscr();
getmaxyx(stdscr, scry, scrx);
WINDOW *w = newwin(1, scrx, scry - 1, 0);
std::string cmdbuf {};
char c = '\0';
while (c != 'q')
{
int newx, newy;
getmaxyx(stdscr, newx, newy);
if(newx != scrx || newy != scry)
{
// do stuff;
}
c = wgetch(w);
cmdbuf += c;
mvwprintw(w, 0, 0, "%s", cmdbuf.c_str());
wrefresh(w);
}
delwin(w);
endwin();
}
The refresh is overwriting the mvwprintw because they're different windows. For the given example, there's no reason to refresh stdscr because nothing (except for the initscr call) has updated that window. Moving refresh out of the loop would help (but the "do stuff" can obviously interfere with that).
The newx/newy logic is too fragmentary to comment on (I'd use getbegyx ...).
The declaration of newwin is:
WINDOW *newwin(
int nlines, int ncols,
int begin_y, int begin_x);
You are calling:
newwin(1,scry,scrx,0)
Which sets the size of you window to 1 tall and scry wide, and puts it at coordinates (0,srcx). What you want is:
newwin(1,scry,scrx-1,0)
Where 1 is the height of the window.
Also, cbreak overrides raw, so there is no point to calling both.

I'm making a Animal Crossing clone, but I'm having problems rendering the Player

Recently, I decided to make an Animal Crossing clone in
C++ and SFML 2.1. But I'm having some issues. The Player won't show up when commanded to be rendered. The program will compile and run just fine but the player just won't show up.
Here's my code:
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
using namespace sf;
RenderWindow window(VideoMode(700, 500), "Animal Crossing: Old oak");
View view(FloatRect(1000, 1000, 300, 200));
class Villager{
public:
int x, y, w, h;
Sprite pl;
string loadDir;
Villager(int x, int y, int w, int h, Color c, string loadDir){
this->x = x;
this->y = y;
this->w = w;
this->h = h;
Image image;
image.loadFromFile(loadDir);
image.createMaskFromColor(Color::Magenta);
Texture tex;
tex.loadFromImage(image);
pl.setTexture(tex);
}
}
};
int main(){
Villager villager(1100, 1000, 100, 100, Color::Blue, "player.png");
view.zoom(5);
Image grasstexloader;
grasstexloader.loadFromFile("grass.png");
Texture grasstex;
grasstex.loadFromImage(grasstexloader);
Sprite grass;
grass.setTexture(grasstex);
while(window.isOpen()){
Event event;
while(window.pollEvent(event)){
if(event.type == Event::Closed)
window.close();
if(Keyboard::isKeyPressed(Keyboard::Up))
villager.moveUp();
if(Keyboard::isKeyPressed(Keyboard::Down))
villager.moveDown();
if(Keyboard::isKeyPressed(Keyboard::Left))
villager.moveLeft();
if(Keyboard::isKeyPressed(Keyboard::Right))
villager.moveRight();
if(Keyboard::isKeyPressed(Keyboard::Escape))
window.close();
}
window.setView(view);
window.draw(grass);
window.draw(villager.pl);
window.display();
window.clear();
}
}
I've been staring at this code for an hour now. But I just can't find an error!
Please help!
Edit: I solved the problem with the sprite not being visible, but the sprite is just white instead of the appropriate colors. It proboably has something to do with how I load the file. Please post any suggestions you have on how to fix this new problem!
Your sprite is rendered white because in your Villager constructor, you're giving a local Texture variable to setTexture, which then gets destructed at the end of the constructor scope.

How to move mouse with c++

I want to move the mouse cursor with a c++ script. I am using Visual C++ 2010 Express in a Windows 7 inside Parallels and I created a console application.
I know SetCursorPos method but it is just not working (it does nothing).
I managed to simulate clicks with SendInput but it does not actually move the mouse.
This is my code:
#include <Windows.h>
#include <Tlhelp32.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
void mouseLeftClick(const int x, const int y);
// window
HWND hWindow;
int main()
{
// find window
hWindow = FindWindow(NULL, "Calculadora");
if (NULL == hWindow) {
OutputDebugStringA("Couldn't find application.");
}else{
if (!SetForegroundWindow(hWindow)) {
OutputDebugStringA("Couldn't set application to foreground.");
}else{
// click on 1
mouseLeftClick(20 265));
Sleep(500);
// click on 2
mouseLeftClick(60, 265);
Sleep(500);
}
}
return 0;
}
void mouseLeftClick(const int x, const int y)
{
// get the window position
RECT rect;
GetWindowRect(hWindow, &rect);
// calculate scale factor
const double XSCALEFACTOR = 65535 / (GetSystemMetrics(SM_CXSCREEN) - 1);
const double YSCALEFACTOR = 65535 / (GetSystemMetrics(SM_CYSCREEN) - 1);
// get current position
POINT cursorPos;
GetCursorPos(&cursorPos);
double cx = cursorPos.x * XSCALEFACTOR;
double cy = cursorPos.y * YSCALEFACTOR;
// calculate target position relative to application
double nx = (x + rect.left) * XSCALEFACTOR;
double ny = (y + rect.top) * YSCALEFACTOR;
INPUT Input={0};
Input.type = INPUT_MOUSE;
Input.mi.dx = (LONG)nx;
Input.mi.dy = (LONG)ny;
// set move cursor directly and left click
Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;
SendInput(1,&Input,sizeof(INPUT));
}
This happens in Parallels because of SmartMouse is On or on Auto.
In order for a program in Parallels VM to control the mouse with SetCursorPos you need to hide cursor first. You can do that with ShowCursor(0); before you do any mouse movement e.g. SetCursorPos.
Now you will be able to control the mouse while SmartMouse is set to Auto or Off.
I found the problem. It turns out Parallels has a feature called Smart Mouse that allows you move freely between OSX and Windows. Once I deactivated it, mouse moved as expected.