#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
Display *dis;
int screen;
Window win;
GC gc;
void init_x() {
/* get the colors black and white (see section for details) */
unsigned long black,white;
/* use the information from the environment variable DISPLAY
to create the X connection:
*/
dis=XOpenDisplay((char *)0);
screen=DefaultScreen(dis);
black=BlackPixel(dis,screen), /* get color black */
white=WhitePixel(dis, screen); /* get color white */
/* once the display is initialized, create the window.
This window will be have be 200 pixels across and 300 down.
It will have the foreground white and background black
*/
win=XCreateSimpleWindow(dis,DefaultRootWindow(dis),0,0,
200, 300, 5, white, black);
/* here is where some properties of the window can be set.
The third and fourth items indicate the name which appears
at the top of the window and the name of the minimized window
respectively.
*/
XSetStandardProperties(dis,win,"My Window","HI!",None,NULL,0,NULL);
/* this routine determines which types of input are allowed in
the input. see the appropriate section for details...
*/
XSelectInput(dis, win, ExposureMask|ButtonPressMask|KeyPressMask);
/* create the Graphics Context */
gc=XCreateGC(dis, win, 0,0);
/* here is another routine to set the foreground and background
colors _currently_ in use in the window.
*/
XSetBackground(dis,gc,white);
XSetForeground(dis,gc,black);
/* clear the window and bring it on top of the other windows */
XClearWindow(dis, win);
XMapRaised(dis, win);
}
int main()
{
init_x();
return 0;
}
This is my first program to get started with X programming. I got this sample code from Internet, I compiled and ran the code but there is no output window.Can anyone please guide me what modification is required here to display a window.
You don't have an event loop, so the program initializes the window and then exits immediately.
Try using
XEvent e;
while (1) {
XNextEvent(dis, &e);
if (e.type == KeyPress)
break;
}
and also clean up on exit using
XCloseDisplay(dis);
Related
I'm using XCB to create my x11 window and, somewhere in the code, I want to move it.
I make a little test to print the window position (0, 0), then move it, and print the position again (200, 100).
Saddly, I have always x:10 and y:10.
Here the code:
// g++ -o test test_xcb.cpp -lX11 -lxcb
#include <xcb/xcb.h>
#include <iostream>
using namespace std;
void print_window_xywh(xcb_connection_t *conn, xcb_drawable_t win)
{
auto geo = xcb_get_geometry_reply(
conn, xcb_get_geometry(conn, win), nullptr);
cout << "Window( " << win << ") - x: " << geo->x
<< " - y: " << geo->y
<< " - w: " << geo->width
<< " - h: " << geo->height << endl;
}
int main(void) {
xcb_connection_t *c;
xcb_screen_t *screen;
xcb_window_t win;
/* Open the connection to the X server */
c = xcb_connect (NULL, NULL);
/* Get the first screen */
screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
/* Ask for our window's Id */
win = xcb_generate_id(c);
/* Create the window */
xcb_create_window (c, /* Connection */
XCB_COPY_FROM_PARENT, /* depth (same as root)*/
win, /* window Id */
screen->root, /* parent window */
10, 10, /* x, y */
150, 150, /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
screen->root_visual, /* visual */
0, NULL); /* masks, not used yet */
/* Map the window on the screen */
xcb_map_window (c, win);
/* Make sure commands are sent, so window is shown */
xcb_flush (c);
// Print the position and size of the window
print_window_xywh(c, win);
// Move the window
const static uint32_t values[] = { 200, 100 };
xcb_configure_window(c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
// Print again, should be 200 for x and 100 for y
print_window_xywh(c, win);
return 0;
}
Did I miss something? Thank you.
The short version: You are ignoring the interaction with the window manager.
The long version:
First, the position that GetGeometry gives you is relative to the parent window. With a reparenting window manager, the WM will add a frame window around your window to draw window decorations to (titlebar, close button, ...). If you want the position of your window on screen, you should use use xcb_translate_coordinates(c, win, screen->root, 0, 0). The reply to this request will give you the position of 0,0 of your window translated to the root window.
However, in your example that will still not work. This is because of how the window manager works. It basically forbids your program from moving its window (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT). Due to this, when you try to move your window, the X11 server only sends this request as an event to the window manager. The window manager then needs some time to handle this request. Since you are immediately checking the window position again, the request will not yet have been handled.
I need to get working gtk3 with vtk6.
Ive just built (after some effort) gtkglext for gtk3.
Later I built vtkmm1.2 with the win32 patches and I do not see vtk widget.
Due to this, I discovered I cant see any draw in the gtkglext examples.
On the other side, Ive tried the excellent example of gtkglarea (the new, gtk built in one ) with plain opengl from https://www.bassi.io/articles/2015/02/17/using-opengl-with-gtk/
and I get no draw because "fb setup not supported".
It seems the framebuffer is complete, checking gtkglarea.c.
How can i solve this?
Anyone have been able to draw something in gtk with opengl, for windows?
This is the simplest code i've made,and i'm getting the mentioned error enter image description here, and adapting the signals to the new built in GtkGLArea ("render" instead of "draw")
#include <math.h>
#include <gtk/gtk.h>
//#include <gtkgl/gtkglarea.h> //LUCIANO, gtkglarea is built in now
#include <gtk/gtkglarea.h>
#include <GL/gl.h>
gint init(GtkWidget *widget)
{
/* OpenGL functions can be called only if make_current returns true */
gtk_gl_area_make_current(GTK_GL_AREA(widget));
{
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
glViewport(0, 0, allocation.width, allocation.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,100, 100,0, -1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
return TRUE;
}
/* When widget is exposed it's contents are redrawn. */
gboolean draw (GtkWidget *widget, cairo_t *cr, gpointer data)
{
/* OpenGL functions can be called only if make_current returns true */
gtk_gl_area_make_current(GTK_GL_AREA(widget));
{
/* Draw simple triangle */
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,1,1);
glBegin(GL_TRIANGLES);
glVertex2f(10,10);
glVertex2f(10,90);
glVertex2f(90,90);
glEnd();
/* Swap backbuffer to front */
//ggla_area_swap_buffers(GGLA_AREA(widget));
gtk_gl_area_attach_buffers(GTK_GL_AREA(widget));
}
return TRUE;
}
/* When glarea widget size changes, viewport size is set to match the new size */
gint reshape(GtkWidget *widget, GdkEventConfigure *event)
{
/* OpenGL functions can be called only if make_current returns true */
//if (ggla_area_make_current(GTK_GL_AREA(widget)))
gtk_gl_area_make_current(GTK_GL_AREA(widget));
{
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
glViewport(0, 0, allocation.width, allocation.height);
}
return TRUE;
}
int main(int argc, char **argv)
{
GtkWidget *window,*glarea;
gchar *info_str;
/* Attribute list for gtkglarea widget. Specifies a
list of Boolean attributes and enum/integer
attribute/value pairs. The last attribute must be
GGLA_NONE. See glXChooseVisual manpage for further
explanation.
*/
int attrlist[] = {
// GGLA_RGBA,
// GGLA_RED_SIZE,1,
// GGLA_GREEN_SIZE,1,
// GGLA_BLUE_SIZE,1,
// GGLA_DOUBLEBUFFER,
// GGLA_NONE
};
/* initialize gtk */
gtk_init(&argc, &argv);
/* Check if OpenGL is supported. */
// if (ggla_query() == FALSE) {
// g_print("OpenGL not supported\n");
// return 0;
// }
/* Create new top level window. */
window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Simple");
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
/* Quit form main if got delete event */
g_signal_connect(G_OBJECT(window), "delete-event",
G_CALLBACK(gtk_main_quit), NULL);
/* Create new OpenGL widget. */
//glarea = GTK_WIDGET(gtk_gl_area_new(attrlist));
glarea = gtk_gl_area_new();
/* Events for widget must be set before X Window is created */
gtk_widget_set_events(GTK_WIDGET(glarea),
GDK_EXPOSURE_MASK|
GDK_BUTTON_PRESS_MASK);
init(glarea);
/* Connect signal handlers */
/* Redraw image when exposed. */
// g_signal_connect(G_OBJECT(glarea), "draw",
// G_CALLBACK(draw), NULL);
// /* When window is resized viewport needs to be resized also. */
// g_signal_connect(G_OBJECT(glarea), "configure-event",
// G_CALLBACK(reshape), NULL);
// /* Do initialization when widget has been realized. */
// g_signal_connect(G_OBJECT(glarea), "realize",
// G_CALLBACK(init), NULL);
g_signal_connect(G_OBJECT(glarea), "render",
G_CALLBACK(draw), NULL);
/* When window is resized viewport needs to be resized also. */
// g_signal_connect(G_OBJECT(glarea), "resize",
// G_CALLBACK(reshape), NULL);
/* Do initialization when widget has been realized. */
// g_signal_connect(G_OBJECT(glarea), "create-context",
// G_CALLBACK(init), NULL);
/* set minimum size */
gtk_widget_set_size_request(GTK_WIDGET(glarea), 100,100);
/* put glarea into window and show it all */
gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(glarea));
gtk_widget_show(GTK_WIDGET(glarea));
gtk_widget_show(GTK_WIDGET(window));
/* vendor dependent version info string */
// info_str = ggla_get_info();
// g_print(info_str);
// g_free(info_str);
gtk_main();
return 0;
}
I am having some issues with GLFW's window creation. I am wanting to have a program capable of toggling between windowed and fullscreen mode. To do this in GLFW 2.7.8 one must first destroy the active window, then create a new one. I read that version 3.0 has support for multiple windows, but it is still in development.
I have provided my own function to handle keyboard input. Using the initial 400 by 400 window, the program functions as expected; it will enter fullscreen on f or F, will exit when the escape key is pressed, and will complain when anything else is pressed.
However, when fullscreen mode is entered, the window becomes unresponsive with regards to my provided keyboard function. It will continue to run through the loop in main() and will respond to something like the glfwGetKey(GLFW_KEY_ESC) test. Regardless of if I have the mouse cursor enabled or not, the cursor does not appear.
Again, the fullscreen window is created and the KeyboardCallback function returns back into the main loop. I wish to understand why the fullscreen window is not working with my keyboard function, and why it is not displaying properly.
I am not drawing anything to the window, as I am trying to get some experience with various window abstraction libraries specifically. Drawing a simple triangle did nothing to solve he problem, and the fullscreen window remains black.
My code is as follows:
#include <stdio.h>
#include <stdlib.h>
// glfw32 - 2.7.8
#include <GL\glfw.h>
#pragma comment (lib, "GLFW.lib")
#pragma comment (lib, "opengl32.lib")
using namespace std;
// constants and globals
const int WINDOW_WIDTH=400, WINDOW_HEIGHT=400;
static bool fullscreen=false;
// function declarations
void GLFWCALL KeyboardCallback(int key, int action);
void FatalError(const char* msg) {
fprintf(stderr, "ERROR: Failure in \"%s\"\n", msg);
exit(1);
}
int main() {
// ititialize GLFW
glfwInit();
glfwEnable(GLFW_MOUSE_CURSOR);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
// initial window, 400x400 with 32-bit depth buffer in windowed mode
glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0,0,0,0, 32, 0, GLFW_WINDOW);
glfwSetWindowTitle("Simple Title");
glfwSetWindowPos(0, 0);
// set custom keyboard callback
glfwSetKeyCallback(KeyboardCallback);
while (true) { // loop until exit
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers();
// debug
//printf("Looping...\n");
if ( glfwGetKey(GLFW_KEY_ESC) ) {break;}
}
glfwTerminate();
printf("\nHave a nice day\n");
return 0;
}
void GLFWCALL KeyboardCallback(int key, int action) {
//printf("In keyboard function\n");
if (action) { // if key DOWN,
switch(key) { // do something...
case 'f':
case 'F': {
fullscreen = !fullscreen;
printf("Toggle Fullscreen: %s\n", (fullscreen ? "On" : "Off"));
glfwCloseWindow();
if (! glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0,0,0,0, 32, 0,
fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW)) {
FatalError("toggle fullscreen");
}
glfwSetWindowTitle("New Title");
break;
}
case GLFW_KEY_ESC: {
printf("\nGoodbye cruel world...\n");
glfwTerminate();
exit(0);
}
default: {
printf("Key not implemented: %c\n", key);
break;
}
}
}
printf("Exiting keyboard function\n");
}
I tried James' approach from here but to no effect. Are there GLFW flags I am forgetting to set?
EDIT------- 5/20
I had a thought. Perhaps my callback was being unregistered when the window is destroyed. Turns out that re-registering my function when the new window is created made the window responsive.
While this solves my original problem, I now face a new one. I cannot render to the new window properly. I can insert glClear( GL_COLOR_BUFFER_BIT ); into my main loop, which will successfully set a background colour for the new window. For some reason it does not interact with my arrays and buffers to draw the image.
Code with attempted drawing
EDIT------- 5/21
I converted my code to GLFW 3.0.0. The window management is much cleaner (albeit more complex) and I do not have the rendering issue. Probably because I explicitly have to state the current context to use.
I would still like to solve the rendering issue, both out of curiosity and for if/when I return to 2.7.
Right now the event queue of GLFW is not pumped. You must either set the GLFW_AUTO_POLL_EVENTS option so that glfwSwapBuffers pumps the event queue, or you call glfwPollEvents at the start of a main event loop iteration.
I'm using Ubuntu 12.04 in a VM.
Upper left is never correct. Width and height are correct about 90% of the time.
XMoveWindow and friends have no effect on the rendered position of the window.
Source:
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/X.h>
int main(int argc, char **argv)
{
Display *disp = XOpenDisplay(0);
GLint attr[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GX_DOUBLEBUFFER, None};
XVisualInfo *vinfo = glXChooseVisual(disp,0,attr);
Window rootWnd = DefaultRootWindow(disp);
XSetWindowAttributes setWndAttr = {0};
setWndAttr.colormap = XCreateColormap(disp,rootWnd,vinfo->visual,AllocNone);
setWndAttr.event_mask =
ExposureMask|
StructureNotifyMask;
Window wnd = XCreateWindow(
disp,rootWnd,
64,64, // can be ignored (asinine)
512,512,
0,vinfo->depth,
InputOutput,
vinfo->visual,
CWColormap|CWEventMask,
&setWndAttr
);
XStoreName(disp,wnd,"What is this crap?");
XMapWindow(disp,wnd);
// WMs allowed to completely ignore these, too?
//XMoveWindow(disp,wnd,128,128);
//XMoveResizeWindow(disp,wnd,128,128,256,256);
Atom closeWndAtom = XInternAtom(disp,"WM_DELETE_WINDOW",0);
XSetWMProtocols(disp,wnd,&closeWndAtom,1);
GLXContext ctx = glCreateContext(disp,vinfo,0,GL_TRUE);
glXMakeCurrent(disp,wnd,ctx);
bool run = true;
XEvent evt;
while(run){
XNextEvent(disp,&evt);
switch(evt.type){
case Expose:
{
XWindowAttributes wndAttr;
XGetWindowAttributes(disp,wnd,&wndAttr);
// these are NEVER correct (0,0 most of the time)
printf("%i, %i\n",wndAttr.x,wndAttr.y);
// these are correct, most of the time
//
// occasionally, either width or height will be 0
glViewport(0,0,wndAttr.width,wndAttr.height);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1,0,0);
glVertex2f(0,0);
glColor3f(0,1,0);
glVertex2f(1,0);
glColor3f(0,0,1);
glVertex2f(0,1);
glEnd();
glXSwapBuffers(disp,wnd);
}break;
case ClientMessage:
{
run = false;
}break;
}
}
glXDestroyContext(disp,ctx);
XDestroyWindow(disp,wnd);
XCloseDisplay(disp);
return 0;
}
Note: There might be a spelling error to two, as pasting from within the VM wouldn't format correctly. As a result, I had to re-type it.
EDIT:
Because clarity is needed here: I don't care what the window manager does with the position I give it, I am interested in retrieving this information from the window manager reliably. The position I am given does not correspond to the rendered position of the window on the screen. For example: The window appears at the lower right of the screen, and the coordinates returned to me are (0,0). Moving the window around using the mouse doesn't change what XGetWindowAttributes returns.
It seems you are polling window information from Expose event, which may not have newest information about window at the time. Use ConfigureNotify event and it's properties to get updated position and size:
// you need to have this in your event mask(you've already got that):
EVENT_MASK |= StructureNotifyMask;
// in your event loop
// ...
case ConfigureNotify: // resize or move event
printf("x: %d, y:%d, width: %d, height: %d\n",
event.xconfigure.x,
event.xconfigure.y,
event.xconfigure.width,
event.xconfigure.height);
break;
I think, one of the option is to use XTranslateCoordinates:
XTranslateCoordinates(dpy,
wnd, // get position for this window
root_window, // something like macro: DefaultRootWindow(dpy)
0, 0, // local left top coordinates of the wnd
&dest_x, // these is position of wnd in root_window
&dest_y, // ...
&unused);
You also can use XGetGeometry instead of XGetWindowAttributes to get left, top, width and height of a drawable. As far as I know XGetWindowAttributes calls XGetGeometry to retrieve some of the attributes.
I know, I'm necroposter, but I was also looking for the answer and found out that the incorrect coordinates are related to Window Manager.
{
case ConfigureNotify :
printf("%d, %d : %u, %u\n",
event.xconfigure.x, event.xconfigure.y,
event.xconfigure.width, event.xconfigure.height);
break;
}
# Moving window
353, 100 : 791, 600
363, 113 : 791, 600
# Changing window size
1, 24 : 791, 600 << Pay attention to this
363, 113 : 791, 600
363, 113 : 791, 600
For the additional info you need to read ICCCM (4.1.5. Configuring the Window, 4.2.3. Window Move, 4.2.4. Window Resize) https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.5
I'd like to have width and height of the currently focussed window. The selection of the window works like a charm whereas the height and width are always returning 1.
#include <X11/Xlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
Display *display;
Window focus;
XWindowAttributes attr;
int revert;
display = XOpenDisplay(NULL);
XGetInputFocus(display, &focus, &revert);
XGetWindowAttributes(display, focus, &attr);
printf("[0x%x] %d x %d\n", (unsigned)focus, attr.width, attr.height);
return 0;
}
Is this not the "real" window but the currently active component (like a textbox or a button?) And why would it have the size of 1x1 anyways then? If this is the case, how do i get the main window of the application containig this control? Means... kinda the top-level window, the top-most window except the root window.
PS: Don't know whether it's really important; I use Ubuntu 10.04 32 and 64 bit.
You're right - you're seeing a child window. GTK applications, in particular, create a child window under the "real" window, which is always 1x1, and that always gets the focus when the application has the focus. If you're just running your program using the GNOME terminal, you'll always be seeing a GTK application with the focus (the terminal).
If you run your program in such a way that a non-GTK program happens to have the focus, then this doesn't happen, but you could still end up finding a child window with the focus instead of the top-level window. (One way of doing this is to run sleep before your program like this: sleep 4; ./my_program - this gives you a chance to change the focus.)
To find the top-level window, I think XQueryTree will help - it returns the parent window.
This worked for me:
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
/*
Returns the parent window of "window" (i.e. the ancestor of window
that is a direct child of the root, or window itself if it is a direct child).
If window is the root window, returns window.
*/
Window get_toplevel_parent(Display * display, Window window)
{
Window parent;
Window root;
Window * children;
unsigned int num_children;
while (1) {
if (0 == XQueryTree(display, window, &root,
&parent, &children, &num_children)) {
fprintf(stderr, "XQueryTree error\n");
abort(); //change to whatever error handling you prefer
}
if (children) { //must test for null
XFree(children);
}
if (window == root || parent == root) {
return window;
}
else {
window = parent;
}
}
}
int main(int argc, char *argv[])
{
Display *display;
Window focus, toplevel_parent_of_focus;
XWindowAttributes attr;
int revert;
display = XOpenDisplay(NULL);
XGetInputFocus(display, &focus, &revert);
toplevel_parent_of_focus = get_toplevel_parent(display, focus);
XGetWindowAttributes(display, toplevel_parent_of_focus, &attr);
printf("[0x%x] %d x %d\n", (unsigned)toplevel_parent_of_focus,
attr.width, attr.height);
return 0;
}