Embedding SDL into GTK+ - c

I have an application that uses GTK+ to display some nice GUI, but I am using SDL to display a small RGB frame buffer inside GTK+
I have used the following code to get SDL into GTK+:
char SDL_windowhack[32];
sprintf(SDL_windowhack, "SDL_WINDOWID=%ld", GDK_WINDOW_XWINDOW(deviceWindow->window));
putenv(SDL_windowhack);
Unfortunately, I also use SDL for keyboard and mouse event. The main thread that uses SDL to update the image spawns the following thread:
void *SDLEvent(void *arg)
{
SDL_Event event;
while (1) {
fprintf(stderr, "Test\n");
SDL_WaitEvent(&event);
switch (event.type) {
/* ... */
}
}
}
I see that the print statement is executed twice, then none. As soon as I terminate the thread that SDL uses to update the screen (display), the loop in SDLEvent starts executing very fast again.
This code used to work fine before I integrated SDL into GTK+ so I am thinking GTK+ is maybe blocking SDL in some ways?
Does anyone have any suggestions please?
Thank you very much!

Although I have not used SDL, but as you are looking for events it appears that you are running two event loops. Gtk runs its own event loop which handles events like the ones from mouse & keyboard. I think you need to find a way to integrate the both. Some googling resulted in the following link where in the section "Double event loop issue" your problem has been addressed (I think). Try adding SDLEvent function as idler function using g_idle_add as suggested in the link and see if it works.
Hope this helps!

Related

Call OpenGL functions outside of the GtkGLArea signals

I am trying to create a library where it's possible to create a OpenGL context with GTK3 which gets rendered automatically or with 1 function call (something similar to a swap-buffers function). I was looking at the source code of GtkGLArea, which seems to have the following order of execution:
A new GtkGLArea is created with the superclass GtkWidget.
When the realize signal of the superclass is captured, a GdkGLContext
is created and a realize signal is given to the user. The user is supposed to put the initial OpenGL functions in a function passed to this signal.
The draw signal of the superclass is also captured, some OpenGL initialization code is called for binding the framebuffer (or texture) and the renderbuffer. The buffers are created if they don't exist. After this the render signal is given where the user is supposed to put the rendering OpenGL code. Finally the gdk_cairo_draw_from_gl function is called to draw the renderbuffer (or texture) on the Cairo context of the superclass passed through the draw signal.
For the user it basically comes down to this:
void realize(GtkGLarea *area){
// OpenGL initialization functions
}
gboolean render(GtkGLArea *area, GdkGLContext *context){
// OpenGL rendering functions
return TRUE;
}
// Init functions, setup a GTK window
GtkWidget *gl_area = gtk_gl_area_new();
g_signal_connect(gl_area, "realize", G_CALLBACK(realize), NULL);
g_signal_connect(gl_area, "render", G_CALLBACK(render), NULL);
// Add gl_area to the window and display the window
But that's not what I want, what I want is this:
// Init functions, setup a GTK window
// Setup a OpenGL context on the GTK window
// OpenGL initialization functions
while(1){ // Main loop
if(gtk_events_pending()){
gtk_main_iteration();
}
// OpenGL rendering functions
swapBuffers();
}
What would be the best way to achieve this? I tried this (unsuccessfully) by simulating the functions called around the signals, and by using a GdkGLContext created on a GdkWindow taken from a GtkDrawingArea.
These are the options which I can imagine as solutions now:
Create a custom GTK3 class extending GtkWidget and using GdkGLContext and somehow track when the drawing signal is called so the appropriate OpenGL functions are called around that signal.
Find a way to ignore the whole GTK3 part and try to use the underlying Xlib functions to create a OpenGL context through X11 (which isn't portable at all).
Use a evil hack with threads and setjmp and longjmp to enter and exit the signals from the swapBuffers function.
None of these "solutions" are really appealing to me, is the thing I want impossible, or am I just missing some information?

How to wait for the GPU to finish its work in DirectX9?

I'm looking for a method to wait for the GPU to finish its work in DirectX9. Something equivalent to the glFinish command in OpenGL...
I already know that it's not something I should do, but I have to! I'm writing a threaded Graphics Engine integrated in WPF and I need to make sort of an off-screen rendering in order to give a valid surface to a D3DImage. The frames are very long to compute (more than 100ms) and the rendering of the WPF Image sometimes occurs while the frame is not fully computed by my Engine even if I lock everything the right way. I'm almost sure it's just a Finish issue but I didn't find out how to do that.
So far, I tried to launch a DX9 query like this :
using namespace SlimDX.Direct3D9;
public class GraphicsDevice: Device
{
...
public void Finish()
{
var query = new Query(this, QueryType.Event);
EndScene();
while (!query.CheckStatus(true)) ;
}
}
But it does not seem to work...
So, first question without talking about WPF, do you know how to wait for the GPU to finish what has been sent to the driver?
Thanks!
This was the solution.
I was not aware that it actually work!
I used an EventQuery to 'mark' my last call to the GPU.
Then I put some kind of infinite loop flushing the GPU instructions and waiting for the EventQuery to be finally fired by the GPU, using the GetData/CheckStatus methods.

How to grab mouse on Windows

I'm writing a cross-platform application that on certain condition takes control of all user input for a period of time.
On GNU/Linux I've used gtk+, which allows me to retrieve mouse and keyboard events such as movement or presses. That's something I need as my application responds to them. It has also a small graphical interfce created with gtk+.
I've been trying to grab mouse input on Windows without success as gtk does work well graphically, but does not grab user input. I've tried using BlockIntput() but it does not works as expected because:
I need administrator priviledges to run the application
I can't read mouse nor keyboard input
Is there a way to grab mouse and keyboard input on windows and still being able to read their inputs without administrative rights?
I finally found a solution that fits my requirements. One of Marc's links guided me to the use of hooks on Windows which I had already tried with no success, but I ended up implementing them for both keyboard and mouse grabbing.
My Windows code uses windows libraries and when I need to block input I create a thread which calls a function:
DWORD dwThread;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MouseHooker, NULL, 0, &dwThread);
Then I install the hook:
DWORD WINAPI MouseHooker(LPVOID lpParameter) {
HINSTANCE hExe = GetModuleHandle(NULL);
//The thread's parameter is the first command line argument which is the path to our executable.
if (!hExe) //If it fails we will try to actually load ourselves as a library.
hExe = LoadLibrary((LPCSTR) lpParameter);
if (!hExe)
return 1;
//Install the hook as a low level mouse hook thats calls mouseEvent
hMouseHook = SetWindowsHookEx (WH_MOUSE_LL, (HOOKPROC)MouseEvent, hExe, 0);
...
UnhookWindowsHookEx(hMouseHook);
return 0;
}
And on each mouse event code gets called:
if (nCode == HC_ACTION && ...) { //HC_ACTION means we may process this event, we may add specific mouse events
//We block mouse input here and do our thing
}
//return CallNextHookEx(hKeyHook, nCode, wParam, lParam);
return 1;
So as we not continue with the hook chain input never gets processed and the workstation gets blocked.
The code runs on Windows 7 as expected. I kept using gtk+ on Windows as I can still generate my GUI and retrieve mouse inputs with gdk.
On GNU/Linux code works only using GTK+ libraries as I had no issues when grabbing input.

Gtk and C - Multi-threaded GUI Application and Removing Global Variables

I have the example GTK C application from [1] building and working as expected. I have a pretty little UI application with a + and - button to increment/decrement a value stored in a global variable, and render it in the application in a text label.
I rarely ever work with GUI applications, and I do 99% of my work in C. I have two key questions with respect to tidying up this example and using it as the basis of a project.
Is it possible to have some alternative to global variables, like a
custom struct I create in main(), and have every callback handler reference
it by changing the function protocol for increase()?
Code:
// Can this function protocol be modified?
void increase(GtkWidget *widget, gpointer label) {
count++;
sprintf(buf, "%d", count);
gtk_label_set_text(GTK_LABEL(label), buf);
}
g_signal_connect(minus, "clicked", G_CALLBACK(decrease), label);
Is there a simple means of creating a separate thread to help manage the GUI? For example, if I have a button tied/connected to a function that would take a minute to complete, is there a universally-accepted means of firing off a separate pthread that allows me to have a button or command to cancel the operation, rather than the entire UI app being blocked for the whole minute?
Thank you.
References
Cross Compiling GTK applications For the Raspberry Pi, Accessed 2014-02-20, <http://hertaville.com/2013/07/19/cross-compiling-gtk-applications-for-the-raspberry-pi/>
Yes, you can pass anything you like as the last argument to signal handlers (gpointer is a typedef for void*) just create the structure containing the label widget and the counter variable in main(), pass it as the last argument to g_signal_connect and cast it back to the proper type in your callback.
For running a calculation in another thread and delivering the result to the gtk main loop I'd look at GTask, in particular g_task_run_in_thread_async.

Ncurses mouse wheel scroll up

I want to handle scroll with the mouse wheel using ncurses but I am having a problem similar to this issue :
http://lists.gnu.org/archive/html/bug-ncurses/2012-01/msg00011.html
Besides, mouse wheel-up event is only reported as mask 02000000
(BUTTON4_PRESSED) just one time, even if I scroll the wheel continuously.
I tried ncurses 5.7 to 5.9 on debian 5,6,7 and archlinux.
Every single ncurses lib had NCURSES_MOUSE_VERSION 1, tried recompiling with --enable-ext-mouse.
Scrolling down works perfectly, ncurses reports multiple REPORT_MOUSE_POSITION 0x8000000 per scroll and a single BUTTON2_PRESSED 0x128.
Scrolling up causes only a single report of BUTTON4_PRESSED 0x80000
MEVENT event;
mousemask(BUTTON1_CLICKED|BUTTON4_PRESSED|BUTTON2_PRESSED, NULL); // Tried with REPORT_MOUSE_POSITION also
while(run)
{
switch(in = getch())
{
case KEY_MOUSE:
if(getmouse(&event) == OK)
{
else if (event.bstate & BUTTON4_PRESSED)
line_up();
else if (event.bstate & BUTTON2_PRESSED || event.bstate == 0x8000000)
line_down();
}
break;
}
}
Add mouseinterval(0); somewhere outside of your main loop. (Perhaps right after keypad(stdscr, TRUE);)
This command causes there to be no delay with mouse events, so you won't be able to detect BUTTON1_CLICKED or BUTTON1_DOUBLE_CLICKED and similar things (though you can implement that yourself by keeping track of BUTTON1_PRESSED, BUTTON1_RELEASED, and the time between mouse events).
A small caveat though, when I tested this with C everything worked, except that getmouse returned ERR on scroll wheel down events. This could potentially still be useful though, as it was the only event which gave this result. When I tested the same code in Rust it worked perfectly though, so your mileage may vary.
ncurses5 does not support wheel mouse, except as an optional feature. That is because the layout of bits in mousemask_t chose in the mid-1990s left insufficient space for a fifth mouse-button. At the time, some other devices (for playing games) seemed more important; this was before X provided a protocol for wheel mice.
The "extended mouse" is an optional feature (since it would change the application binary interface), and has not been incorporated in ncurses5 packages, although it has been available for some time.
For reference, see the discussion of --enable-ext-mouse in the ncurses changelog, starting in 2005.
ncurses6 does support wheel mouse (see release notes). Perhaps that will be standard in Debian 9.

Resources