Query cursor position with GTK - c

Is there a way to query the cursor position using the GTK C libraries? I am writing a program where I need to read out the position of the cursor in real time (either through a callback function or by polling the values to look for change). I have scanned through the GTK documentation, but I couldn't find anything obvious that exposes the cursor position.
I am currently writing this program using the GTK C libraries because a) I already have some code written in C to interface with the low level Raspberry Pi peripherals, and I'd rather not rewrite it for a different language if I can avoid it. The low level code is based on mmap(), which I believe still works with C++, so if push comes to shove, I supposed I can rewrite it in C++ with some other GUI library like wxWidgets or QT. (Are there easy ways to read the cursor position with those libraries?)

You can take a look at how it's done in those toy widgets which draw eyes on the panel, e.g. xfce4-eyes-plugin.
gboolean
where (void)
{
gint x, y;
GdkWindow *window;
GdkDevice *mouse_device;
#if GTK_CHECK_VERSION (3,20,0)
GdkSeat *seat = gdk_display_get_default_seat (gdk_display_get_default ());
mouse_device = gdk_seat_get_pointer (seat);
#else
GdkDeviceManager *devman = gdk_display_get_device_manager (gdk_display_get_default ());
mouse_device = gdk_device_manager_get_client_pointer (devman);
#endif
window = gdk_display_get_default_group (gdk_display_get_default ());
gdk_window_get_device_position (window, mouse_device, &x, &y, NULL);
g_message ("pointer: %i %i", x, y);
return G_SOURCE_CONTINUE;
}

Related

Calling Chicken Scheme function from SDL2 audio callback function hangs

I am trying to embed Chicken Scheme into a C program, to generate sounds to be played with SDL2's audio system. I would have liked to use the sdl2 egg, but it does not seem to support Audio yet (despite the documentation mentioning the 'audio flag for the init! function).
At first, I was using SDL_QueueAudio from C, passing it a buffer that I had allocated in C and then filled in Scheme. This worked fine, passing a Sint16 * and size_t into Scheme, then using pointer-s16-set! from Scheme to fill it and returning a size_t to note how many cells were filled.
Then, when I realised that using the callback api for generating the audio was much better suited to this, I tried switching to it (having already used it before in C), only for the Scheme function to never be entered. Logging something in the callback function before the Scheme call worked, but logging directly within the Scheme function, or after the Scheme call, never happened.
I can only imagine that this is due to SDL2's audio callback running on a separate thread, and that messing with calling through to Scheme somehow. With this in mind, I tried calling CHICKEN_run(C_toplevel); from within the callback function, the first time that it was called, but that only resulted in a bus error.
So my question is: is there a way of calling embedded Chicken Scheme from SDL2's audio callback?
I am on macOs 10.13.6 High Sierra, with SDL2 and chicken both installed and up-to-date through Homebrew.
I compile with (as I said, this works fine when using the queue audio api):
csc code.c codescm.scm -embedded -o code -L -lSDL2
My simplified code is below:
#include <chicken.h>
#include "SDL2/SDL.h"
extern size_t fill_sound_buffer(Sint16 *buffer, size_t buffer_length);
void fill_sound_callback(void *user_data, Uint8 *stream, int stream_length)
{
// Logging here prints to the console
fill_sound_buffer((Sint16 *)stream, stream_length / 2);
// Logging here does not print to the console
}
void play(void)
{
SDL_AudioSpec audio_want;
SDL_zero(audio_want);
audio_want.freq = 44100;
audio_want.format = AUDIO_S16SYS;
audio_want.channels = 1;
audio_want.samples = 2048;
audio_want.callback = fill_sound_callback;
SDL_AudioSpec audio_have;
SDL_AudioDeviceID audio_device = SDL_OpenAudioDevice(NULL, 0, &audio_want, &audio_have, 0);
SDL_PauseAudioDevice(audio_device, 0);
SDL_Delay(5000);
// Logging here shows up after 5 seconds, but the program then continues to wait
SDL_CloseAudioDevice(audio_device);
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_AUDIO);
CHICKEN_run(C_toplevel);
play();
SDL_Quit();
return 0;
}
(import (chicken format)
(chicken foreign)
(chicken memory)
(chicken platform))
(define-external (fill_sound_buffer ((c-pointer short) buffer) (size_t buffer_length)) size_t
; This never prints when using the callback api
(printf "In Scheme~%")
; Removed the code that calculates a sine wave and fills the buffer with it, which works
0)
(return-to-host)

switching to a specific window

I'm writing a program using XLIB and gtk, I'm supposed to implement a function to switch a specific window(using any human identifyable reference, window name, process name or anything that is going to be static everytime that application is run)
I'm completely lost and I cannot find anything to guide me through the beginning of the application
thanks
You can do this with X libraries but it'll be a bit of a pain: you'll have to understand X IPC and properties. Fortunately there's an easier way, assuming you can use other libraries: use Libwnck. Here's a minimal example to list windows (adapted from the "Getting started" page):
WnckScreen *screen = wnck_screen_get_default ();
WnckWindow *active_window = wnck_screen_get_active_window (screen);
GList *l;
for (l = wnck_screen_get_windows (screen); l != NULL; l = window_l->next) {
WnckWindow *window = WNCK_WINDOW (window_l->data);
g_print ("%s%s\n", wnck_window_get_name (window),
window == active_window ? " (active)" : "");
}
Switching to a specific window should be just:
wnck_window_activate (window, 0);
The only gotcha is that wnck is designed to be used with a GLib mainloop. If you are not running one (as would be the case for a simple command line app), you'll need to use wnck_screen_force_update () to fetch the current data from X (see the "Getting started" example).

Flickering ACS_CKBOARD using ncurses in rxvt

I wanted to get familiar with the curses interface (never used it before), so I wrote a little snake game last weekend. There's a one-line status WINDOW * and the rest of the screen is the field WINDOW * The game logic calls a central drawing function to put an item, only when necessary:
/* note: CP_* are just enum values to give my own color pairs names */
void
screen_putItem(Screen *self, int y, int x, Item item, int refresh)
{
switch (item)
{
case EMPTY:
mvwaddch(self->field, y, x, ' '|COLOR_PAIR(CP_WHITE));
break;
case HEAD:
#ifdef WIN32
/* 'smiley' character for windows console */
mvwaddch(self->field, y, x,
1|COLOR_PAIR(CP_YELLOW)|A_BOLD|A_ALTCHARSET);
#else
mvwaddch(self->field, y, x, '#'|COLOR_PAIR(CP_YELLOW)|A_BOLD);
#endif
break;
case TAIL:
mvwaddch(self->field, y, x, ACS_CKBOARD|COLOR_PAIR(CP_YELLOW));
break;
case FOOD:
mvwaddch(self->field, y, x, '#'|COLOR_PAIR(CP_GREEN)|A_BOLD);
break;
case FFOOD:
mvwaddch(self->field, y, x, '#'|COLOR_PAIR(CP_GREEN));
break;
case WALL:
mvwaddch(self->field, y, x,
' '|COLOR_PAIR(CP_RED)|A_REVERSE);
break;
}
if (refresh) wrefresh(self->field);
}
Problem is: in rxvt, the body of the snake (made from TAIL items) is sometimes flickering. It is not redrawn on snake movement, only the last position of the head is replaced by a TAIL and the tail item at the end of the snake is replaced by an EMPTY.
For your reference, the whole project is on github, see the revision at time of asking this question.
For input, the code uses getch() and I already checked this isn't the problem (it shouldn't be, stdscr is refreshed at init and never touched again) by using only wgetch() on the field window with the same result.
Also, it works fine (flicker-free) in good old xterm and in the windows console, using pdcurses. It works fine in rxvt iff I replace the ACS_CKBOARD in the snippet above with some "ordinary" character.
So, now I'd like to know: Did I encounter a bug/shortcoming in rxvt? Is there something special about the ACS_* characters that could cause a terminal to flicker? Is there anything just wrong with my approach?
Tracing shows me that your program does almost all wgetch's from stdscr, but almost all refresh's are done against the second window created (looks like the first is just a status line).
ncurses' trace feature is normally in a debug-library; the copies that I compile for myself have it compiled in normally.

GTK/C sharing data and variables between functions

The problem is: what's the best way to share data between functions, but specifically in GTK/C application? The best means the most 'proper', the fastest in run and/or absorbing as low CPU power as possible.
I'm asking because I have to code some app with GUI under linux, but I'm rather a microcontroller programmer (and maybe it's hard to me to think like big computer). In small 8-bit MCU's world, where code is in plain C, globals are the fastest and commonly used way to share data between functions.
But I guess that in much more complicated app running under operating system there must be other 'special' way to do that. To this point I noticed that GTK (GDK, Glib etc.) offer many special functions and build-in mechanisms to makes programmer's life easiest, so I suppose it should be something elegant for sharing variables between functions.
Searching through the net I've seen different solutions:
- classes with private variables and methods to get/set them - but my app is coded in C, not C++, I'd like to avoid using object programming,
- global structs or even one big global struct with many members,
- good plain globals,
- GtkClipboard, but I think it's for different purposes.
What I want to do is simply to set some variable 'A' in one callback function, set that variable once again in second callback, and then in another callback do something depending upon value of variable 'A', like this:
callback_func1{
//...
A = some_func();
//...
}
callback_func2{
//...
A = another_func();
//...
}
callback_func3{
//...
if(A>threshold) do_something();
else do_nothing();
//...
}
You're right to be wary of globals, especially if you only want to allow certain functions to be modifying them.
Assuming you're retaining more data than just A (which for simplicity I've defined as int), you can set up your structure in the familiar way
typedef struct t_MYCBSD
{
int A;
// other members
} MYCBSD; // callback struct data
including other data members as necessary. (I've included the t_MYCBSD in case there is some self-referencing).
You can then implement your callback functions as follows:
void callback_func1( GtkWidget *widget, gpointer user_data )
{
MYCBSD *data = user_data;
data->A = some_func();
}
void callback_func2( GtkWidget *widget, gpointer user_data )
{
MYCBSD *data = user_data;
data->A = another_func();
}
void callback_func3( GtkWidget *widget, gpointer user_data )
{
MYCBSD *data = user_data;
if( data->A > threshold ) do_something();
else do_nothing();
}
Obviously, some_func(), another_func(), threshold, do_something() and do_nothing() are valid in this context.
NOTE: the data pointer to your struct makes the syntax a little more clear. You can also use:
((MYCBSD *) user_data)->A = some_func();
In any case, you usually set up your callbacks when creating your widgets. In the following (heavily culled, non-GtkBuilder) code, MYCBSD mydata will be locally scoped. I'm assuming the callbacks will be set for some buttons with the "clicked" event.
int main( int argc, char* argv[] )
{
MYCBSD mydata;
// Below-referenced widgets
GtkWidget *mywidget1, *mywidget2, *mywidget3;
// ... other widgets and variables
mydata.A = 0; // Optionally set an initial value to A
// Standard init via gtk_init( &argc, &argv );
// ... Create the toplevel and a container of some kind
// Create mywidget1,2,3 (as buttons, for example)
mywidget1 = gtk_button_new_with_label ("widget1");
mywidget2 = gtk_button_new_with_label ("widget2");
mywidget1 = gtk_button_new_with_label ("widget3");
g_signal_connect( mywidget1, "clicked", G_CALLBACK(callback_func1), &mydata );
g_signal_connect( mywidget2, "clicked", G_CALLBACK(callback_func2), &mydata );
g_signal_connect( mywidget3, "clicked", G_CALLBACK(callback_func3), &mydata );
// ... Attach those widgets to container
// ... and show all
// Run the app in a standard way via gtk_main();
return 0;
}
The important lines here are:
g_signal_connect( mywidget1, "clicked", G_CALLBACK(callback_func1), &mydata );
g_signal_connect( mywidget2, "clicked", G_CALLBACK(callback_func2), &mydata );
g_signal_connect( mywidget3, "clicked", G_CALLBACK(callback_func3), &mydata );
where the last parameter passes your data to the callback functions.
If you're only looking to share a single value, A, you can pass that in a similar way without the need of a struct.
If you want to use globals, just use globals. And, regardless of what the world says, nobody died because used globals.
Globals are avoided because make maintenance hard on big programs and, from your description, this just does not seem to be the case.
On the sharing side, GTK+ programs are usually not parallel, so you can freely access globals in RW without problems. And also when tasks are used, it is best practice to put all the GTK+ calls on the same task: you are still allowed to access globals in RW from the same task.

Is there a Linux equivalent of SetWindowPos?

A while ago I wrote a script in C that used the Windows API functions EnumWindows, SetWindowPos and SetForegroundWindow to automatically arrange windows (by title) in a particular layout that I commonly wanted.
Are there Linux equivalents for these functions? I will be using Kubuntu, so KDE-specific and/or Ubuntu-specific solutions are fine.
The best way to do this is either in the window manager itself (if yours supports extensions) or with the protocols and hints designed to support "pagers" (pager = any non-window-manager process that does window organization or navigation things).
The EWMH spec includes a _NET_MOVERESIZE_WINDOW designed for use by pagers. http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2731465
Raw Xlib or Xcb is pretty rough but there's a library called libwnck specifically designed to do the kind of thing you're talking about. (I wrote the original library long ago but it's been maintained by others forever.) Even if you don't use it, read the code to see how to do stuff. KDE may have an equivalent with KDE-style APIs I'm not sure.
There should be no need to use anything KDE or GNOME or distribution specific since the needed stuff is all spelled out in EWMH. That said, for certain window managers doing this as an extension may be easier than writing a separate app.
Using old school X calls directly can certainly be made to work but there are lots of details to handle there that require significant expertise if you want to iron out all the bugs and corner cases, in my opinion, so using a WM extension API or pager library would be my advice.
#andrewdotn has a fine answer there but you can do this old school as well fairly simply by walking the tree starting at the root window of the display using XQueryTree and fetching the window name with XFetchName then moving it with XMoveWindow. Here is an example that will list all the windows and if any are called 'xeyes' they get moved to the top left. Like most X programs, there is more to it and this should probably be calling XGetWindowProperty to fetch the _NET_WM_NAME extended window manager property but the example works ok as a starter. Compile with gcc -Wall -g -o demo demo.c -lX11
#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>
static int
EnumWindows(Display *display, Window window, int depth)
{
Window parent, *children;
unsigned int count = 0;
int r = 1, n = 0;
char *name = NULL;
XFetchName(display, window, &name);
for (n = 0; n < depth; ++n) putchar(' ');
printf("%08x %s\n", (int)window, name?name:"(null)");
if (name && strcmp("xeyes", name) == 0) {
XMoveWindow(display, window, 5, 5);
}
if (name) XFree(name);
if (XQueryTree(display, window, &window, &parent, &children, &count) == 0) {
fprintf(stderr, "error: XQueryTree error\n");
return 0;
}
for (n = 0; r && n < count; ++n) {
r = EnumWindows(display, children[n], depth+1);
}
XFree(children);
return r;
}
int
main(int argc, char *const argv[])
{
Display *display = NULL;
if ((display = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "error: cannot connect to X server\n");
return 1;
}
EnumWindows(display, DefaultRootWindow(display), 0);
XCloseDisplay(display);
return 0;
}
Yes, you can do this using the X Windows protocol. It’s a very low-level protocol so it will take some work. You can use xcb_query_tree to find the window to operate on, and then move it with xcb_configure_window. This page gives some details on how to do it. There’s a basic tutorial on using the library those functions come from, but you’ll probably want to Google for a better one.
It may seem daunting, but it’s not too bad. Here’s a 50-line C program that will move all your xterms 10px to the right:
#include <stdio.h>
#include <string.h>
#include <xcb/xcb.h>
void handle(xcb_connection_t* connection, xcb_window_t window) {
xcb_query_tree_reply_t *tree = xcb_query_tree_reply(connection,
xcb_query_tree(connection, window), NULL);
xcb_window_t *children = xcb_query_tree_children(tree);
for (int i = 0; i < xcb_query_tree_children_length(tree); i++) {
xcb_get_property_reply_t *class_reply = xcb_get_property_reply(
connection,
xcb_get_property(connection, 0, children[i], XCB_ATOM_WM_CLASS,
XCB_ATOM_STRING, 0, 512), NULL);
char* class = (char*)xcb_get_property_value(class_reply);
class[xcb_get_property_value_length(class_reply)] = '\0';
if (!strcmp(class, "xterm")) {
/* Get geometry relative to parent window */
xcb_get_geometry_reply_t* geom = xcb_get_geometry_reply(
connection,
xcb_get_geometry(connection, window),
NULL);
/* Move 10 pixels right */
uint32_t values[] = {geom->x + 10};
xcb_configure_window(connection, children[i],
XCB_CONFIG_WINDOW_X, values);
}
/* Recurse down window tree */
handle(connection, children[i]);
}
}
int main() {
xcb_connection_t *connection;
const xcb_setup_t *setup;
connection = xcb_connect(NULL, NULL);
setup = xcb_get_setup(connection);
xcb_screen_iterator_t screen = xcb_setup_roots_iterator(setup);
handle(connection, screen.data->root);
return 0;
}
There’s no error-checking or memory management, and what it can do is pretty limited. But it should be straightforward to update into a program that does what you want, or to turn it into a general-purpose helper program by adding command-line options to specify which windows to operate on and which operations to perform on them.
As it seems you are not looking specifically for a solution in code, but rather in a desktop environment, you need to take a look at one of the window managers that handle the window placement in such a desktop environment.
KDE's KWin's Window Attributes
Compiz (GNOME) has "Window Rules" and "Place Windows" in the CompizConfig Settings Manager application. See e.g. here
Openbox seems a lot harder to get right, although they link to a GUI tool at the bottom of this page.
The problem with using X directly is that X in itself knows nothing about your desktop environment (panels, shortcuts, etc.) and you'll have to compensate manually.
After googling for this, I'm surprised KDE is the only one that has a simple way to do this.

Resources