In a purely GDK 3.10 (no GTK) project how do I refresh/clear/redraw a transparent background of a GdkWindow?
This test.c sets the background correctly on initialization (gdk_window_show()) and when I iconify+deiconify the window but not on resizing or moving it around per mouse:
#include <gdk/gdk.h>
// #include <gdk/gdkx.h> // GDK X11
// #include <X11/Xlib.h> // Xlib
// #include <X11/Xutil.h>
void eventHandler(GdkEvent *evt, gpointer data) {
GdkWindow *win = (GdkWindow *)data;
switch(evt->type)
{
case GDK_CONFIGURE: {
// refresh window background here
printf("refresh background here\n");
break;
}
case GDK_DELETE: {
gdk_window_destroy(win);
_exit(0);
break;
}
default:
break;
}
}
int main(int argc, char *argv[]) {
gdk_init(NULL, NULL);
GdkDisplay *disp=gdk_display_get_default();
GdkScreen *scr = gdk_display_get_default_screen (disp);
GdkWindow *root = gdk_screen_get_root_window(scr);
GdkWindowAttr attr;
attr.width=200;
attr.height=200;
attr.x=0;
attr.y=0;
attr.window_type = GDK_WINDOW_TOPLEVEL;
attr.wclass=GDK_INPUT_OUTPUT;
GdkVisual *vis = gdk_screen_get_rgba_visual (scr);
attr.visual = vis;
GdkWindow *newWin=gdk_window_new(root,&attr, GDK_WA_X | GDK_WA_Y);
GdkRGBA color = { .red=1.0, .green=0.0, .blue=1.0, .alpha=0.0};
gdk_window_set_background_rgba(newWin, &color);
gdk_event_handler_set (eventHandler, newWin, NULL);
gdk_window_show(newWin);
GMainLoop *mainloop = g_main_new (TRUE);
g_main_loop_run (mainloop);
gdk_display_close(disp);
return 0;
}
gcc build command:
gcc -o test test.c `pkg-config gdk-3.0 --libs --cflags`
Outcome:
Note: I'm targeting X11 so I'm also allowed to include Xlib or GDK X11 backend functions.
Thank you for any help or pointers.
The solution to this is a fix of a rather silly mistake I made passing an incomplete attribute mask to gdk_window_new().
To make it work the line in question has to be changed to:
GdkWindow *newWin=gdk_window_new(root,&attr, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_WMCLASS);
Related
The code looks like this:
#include"global.h"
static const int width = 800;
static const int height = 600;
int main (int argc, char **argv)
{
SDL_Init(SDL_INIT_VIDEO);
// Create the window
SDL_Window *window = SDL_CreateWindow("Ferengine",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,width,height, SDL_WINDOW_OPENGL);
// renderer
SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
// settings
SDL_SetRenderDrawColor(renderer,255,0,0,255);
SDL_SetWindowOpacity(window,1.0f);
// loop
bool running = true;
SDL_Event event;
while(running)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
// release resources
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
global.h looks like this:
// SDL
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
my make file looks like this
CC=gcc
S_DIR=Source
B_DIR=Build
build:
$(CC) \
-o \
$(B_DIR)/Ferengine \
$(S_DIR)/main.c \
-lSDL2
clean:
rm -f $(B_DIR)/*
file structure:
main folder
Makefile
source | build/executable
source/main.c | source/global.h
when I run make and then run the executable either the window is rendering whats behind it or it is transparent I saw another question like this but its answer did not work. I am using sdl2 version 2.0.22-2.
I read the tutorial wrong it should be
while(running)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
I'm having trouble running an SDL2 program, I compiled the program successfully using this command.
gcc -g main.c -o main.exe -IC:\\SDL2\\i686-w64-mingw32\\include -LC:\\SDL2\\i686-w64-mingw32\\lib -lmingw32 -lSDL2main -lSDL2 -Wall -Werror
Now that I'm trying to run it, I expect to get a window and to log hello in the console but nothing happens and the program exits immediately.
I'm using windows 10 and using the MinGw compiler.
This is the code.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
static const int width = 800;
static const int height = 600;
int main(int argc, char **argv)
{
SDL_Log("hello");
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Hello, SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
bool running = true;
SDL_Event event;
while(running)
{
// Process events
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
}
// Clear screen
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I am using GTK as the user interface to a piece of hardware (a 3D printer). The hardware can create events as a result of user interactions with the machine (not the GUI). For example, they can remove the build plate which trips a switch thus sending a signal to my program that this has happened, but how do I get gtk_main() to recognize that this event has happened?
In other words, how do I get gtk_main() to watch for non-standard device input events?
You can use custom actions provided by GtkApplication.
In any case you must implement by yourself the monitoring code, either by polling your hardware status or by leveraging more advanced techniques (if possible).
/* gcc -o monitor monitor.c $(pkg-config --cflags --libs gtk+-3.0) */
#include <gtk/gtk.h>
static void
startup(GtkApplication *application)
{
GAction *action;
/* plate-removed is a custom action */
action = G_ACTION(g_simple_action_new("plate-removed", NULL));
g_action_map_add_action(G_ACTION_MAP(application), action);
g_object_unref(action);
/* You can connect your callbacks to the GAction::activate signal */
action = g_action_map_lookup_action(G_ACTION_MAP(application), "plate-removed");
g_signal_connect_swapped(action, "activate",
G_CALLBACK(g_print), "Plate has been removed\n");
}
static gpointer
worker_thread(gpointer user_data)
{
GApplication *application = G_APPLICATION(user_data);
for (;;) {
g_usleep(g_random_int_range(500000, 5000000));
/* Event occurred: emit the signal */
g_action_group_activate_action(G_ACTION_GROUP(application),
"plate-removed", NULL);
}
return NULL;
}
static gboolean
polling_loop(gpointer user_data)
{
GApplication *application = G_APPLICATION(user_data);
if (g_random_int_range(1, 20) == 8) {
/* Event occurred: emit the signal */
g_action_group_activate_action(G_ACTION_GROUP(application),
"plate-removed", NULL);
}
return G_SOURCE_CONTINUE;
}
static void
activate(GtkApplication *application)
{
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_application_add_window(application, GTK_WINDOW(window));
gtk_widget_show_all(window);
/* You can use whatever you want to monitor your hardware, in particular
* a polling loop or a worker thread */
g_timeout_add(50, polling_loop, application);
/* g_thread_new("WorkerThread", worker_thread, application); */
}
int
main(int argc, char *argv[])
{
GtkApplication *application;
int retval;
application = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
g_signal_connect(application, "startup", G_CALLBACK(startup), NULL);
g_signal_connect(application, "activate", G_CALLBACK(activate), NULL);
retval = g_application_run(G_APPLICATION(application), argc, argv);
g_object_unref(application);
return retval;
}
I have a lightweight application that catches Xorg and dbus events. In order to do this I initialized dbus loop and started g_main_loop, but I don't know how to add Xorg event handling in a natural way:
GMainLoop * mainloop = NULL;
mainloop = g_main_loop_new(NULL,FALSE);
dbus_g_thread_init ();
dbus_init();
// <<<<<<<<<<<<<<<<<<<<<<<<<
//1 way using timeout
//g_timeout_add(100, kbdd_default_iter, mainloop);
//2nd way using pthread
//GThread * t = g_thread_create(kbdd_default_loop, NULL, FALSE, NULL);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>
g_main_loop_run(mainloop);
in default iter I'm checking if there is waiting X-event and handle them.
Both ways seems bad, first because I have unneeded calls for checking event, second because I make an additional thread and have to make additional locks.
P.S. I know I can use gtk lib, but I don't want to have dependencies on any toolkit.
If you want to add Xorg event handling to the main loop without using a timeout (which as you state is wasteful), you'll need to add a source that polls the X connection. For that, you'll need to get below the Xlib abstraction layer to get the underlying X connection file descriptor. That's what the complete program below does. It is an adaptation of C. Tronche's excellent X11 tutorial to use the glib main loop for polling. I also drew from "Foundations of GTK+ Development" by Andrew Krause.
If this doesn't seem very "natural", that's because I doubt there is a very "natural" way to do this - you're really re-implementing a core part of GDK here.
/* needed to break into 'Display' struct internals. */
#define XLIB_ILLEGAL_ACCESS
#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <glib.h>
typedef struct _x11_source {
GSource source;
Display *dpy;
Window w;
} x11_source_t;
static gboolean
x11_fd_prepare(GSource *source,
gint *timeout)
{
*timeout = -1;
return FALSE;
}
static gboolean
x11_fd_check (GSource *source)
{
return TRUE;
}
static gboolean
x11_fd_dispatch(GSource* source, GSourceFunc callback, gpointer user_data)
{
static gint counter = 0;
Display *dpy = ((x11_source_t*)source)->dpy;
Window window = ((x11_source_t*)source)->w;
XEvent e;
while (XCheckWindowEvent(dpy,
window,
EnterWindowMask,
&e))
{
if (e.type == EnterNotify)
g_print("We're in!!! (%d)\n", ++counter);
}
return TRUE;
}
static gboolean
msg_beacon(gpointer data)
{
static gint counter = 0;
g_print("Beacon %d\n", ++counter);
return TRUE;
}
int
main()
{
Display *dpy = XOpenDisplay(NULL);
assert(dpy);
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, blackColor, blackColor);
XSelectInput(dpy, w, StructureNotifyMask | EnterWindowMask);
XMapWindow(dpy, w);
for (;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify)
break;
}
GMainLoop *mainloop = NULL;
mainloop = g_main_loop_new(NULL, FALSE);
/* beacon to demonstrate we're not blocked. */
g_timeout_add(300, msg_beacon, mainloop);
GPollFD dpy_pollfd = {dpy->fd,
G_IO_IN | G_IO_HUP | G_IO_ERR,
0};
GSourceFuncs x11_source_funcs = {
x11_fd_prepare,
x11_fd_check,
x11_fd_dispatch,
NULL, /* finalize */
NULL, /* closure_callback */
NULL /* closure_marshal */
};
GSource *x11_source =
g_source_new(&x11_source_funcs, sizeof(x11_source_t));
((x11_source_t*)x11_source)->dpy = dpy;
((x11_source_t*)x11_source)->w = w;
g_source_add_poll(x11_source, &dpy_pollfd);
g_source_attach(x11_source, NULL);
g_main_loop_run(mainloop);
return 0;
}
dude here im gonna create client and combine with GIO Channel, and after i put it all together, it seems appears to work on socket, but the g_io_channel not as watching, like crashing or such..
please see following code :
#include <stdio.h>
#include <gio/gio.h> // g_timeout_add
#include <gtk/gtk.h> // gtk
#include <netinet/in.h> //sockaddr_in
#include <sys/socket.h> // socket();
#include <arpa/inet.h> // inet_addr();
#include <string.h> // memset();
struct dada
{
gint id_sock;
guint id_gio_watch;
};
gboolean incoming(GIOChannel *chan, GIOCondition condition, struct dada *didi )
{
int byte;
int insock = g_io_channel_unix_get_fd(chan);
#define MAXMAX 128
char buff[128];
printf("sock : %d\n",insock);
byte = recv(insock,buff,MAXMAX-1,0);
if(byte <= 0)
{
perror("recv");
close(didi->id_sock);
g_source_remove(didi->id_gio_watch);
return FALSE;
}
else
{
buff[byte] = '\0';
printf("coming : %s",buff);
}
return TRUE;
}
// gtk area
void hello(GtkWidget *widget, gpointer data)
{
g_print("Haii world %s\n", (char *)data);
}
gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
g_print("a delete event has been occured properly :D\n");
return(0);
}
void destroy(GtkWidget * widget, gpointer data)
{
gtk_main_quit();
}
// end of gtk area
int main(int argc, char **argv)
{
//gtk bussines from here
GtkWidget *window;
GtkWidget *button;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL);
gtk_container_set_border_width(GTK_CONTAINER(window),10);
button = gtk_button_new_with_label("ohayo");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(hello), (gpointer)"hha" );
gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
gtk_container_add(GTK_CONTAINER(window),button);
gtk_widget_show(button);
gtk_widget_show(window);
//gtk bussiness done here...
// network code //
struct dada didi;
memset(&didi,0,sizeof(didi));
struct sockaddr_in my; // set my network device info
gint rootsock; // handle the root socket
//socket
rootsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//binding
memset(&my,0,sizeof(my));
my.sin_addr.s_addr = inet_addr("127.0.0.1");
my.sin_family = AF_INET;
my.sin_port = htons(1111);
//bind(rootsock,(struct sockaddr*)&my,sizeof(my));
printf("sock : %d\n",rootsock);
connect(rootsock,(struct sockaddr*)&my,sizeof(my));
didi.id_sock = rootsock;
didi.id_gio_watch = g_io_add_watch(g_io_channel_unix_new(didi.id_sock),G_IO_IN|G_IO_OUT,(GIOFunc)incoming,&didi);
// network code //
gtk_main();
return 0;
}
compiling :
$ gcc -o konek_gioglib konek_gioglib.c `pkg-config glib-2.0 --libs --cflags gtk+-2.0`
my own pc run as server with port 1111 and stream connection ( TCP ) :
$ nc -v -l 1111
running my app :
$ ./konek_gioglib
sock : 6
sock : 6
server got connection and send some word :
$ nc -v -l 1111
Connection from 127.0.0.1 port 1111 [tcp/*] accepted
a
a
and when the server send something, gtk window show but with error like these :
is there anyone dont mind to explain, why these things could happened to mine ?
well last night I brainstormed myself with my own heart, and finally could make these thing work,
here the proper code
#include <stdio.h>
#include <gio/gio.h> // g_timeout_add
#include <gtk/gtk.h> // gtk
#include <netinet/in.h> //sockaddr_in
#include <sys/socket.h> // socket();
#include <arpa/inet.h> // inet_addr();
#include <string.h> // memset();
#include <fcntl.h>
#include <stdlib.h>
struct dada
{
gint id_sock;
guint id_gio_connect;
guint id_gio_watch;
};
gboolean readdata(GIOChannel *chan,GIOCondition condition, struct dada *didi)
{
gchar dada[20] = {0};
int dadaz =0;
if( condition != G_IO_IN )
return FALSE;
if(dadaz = recv(g_io_channel_unix_get_fd(chan),dada,19,0)<=0)
{
perror("recv");
close(didi->id_sock);
g_source_remove(didi->id_gio_connect);
g_source_remove(didi->id_gio_watch);
exit(0);
return FALSE;
}
printf("data in : %s\n",dada);
return TRUE;
}
gboolean incoming(GIOChannel *chan, GIOCondition condition, struct dada *didi )
{
if( condition & G_IO_ERR || condition & G_IO_HUP )
return FALSE;
didi->id_gio_watch = g_io_add_watch(chan,G_IO_IN | G_IO_ERR | G_IO_HUP,(GIOFunc)readdata,didi);
return FALSE;
}
// gtk area
void hello(GtkWidget *widget, gpointer data)
{
g_print("Haii world %s\n", (char *)data);
}
gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
g_print("a delete event has been occured properly :D\n");
return(0);
}
void destroy(GtkWidget * widget, gpointer data)
{
gtk_main_quit();
}
// end of gtk area
int main(int argc, char **argv)
{
//gtk bussines from here
GtkWidget *window;
GtkWidget *button;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL);
gtk_container_set_border_width(GTK_CONTAINER(window),10);
button = gtk_button_new_with_label("ohayo");
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(hello), (gpointer)"hha" );
gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
gtk_container_add(GTK_CONTAINER(window),button);
gtk_widget_show(button);
gtk_widget_show(window);
//gtk bussiness done here...
// network code //
struct dada didi;
memset(&didi,0,sizeof(didi));
struct sockaddr_in your; // set my network device info
gint rootsock; // handle the root socket
//socket
rootsock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
memset(&your,0,sizeof(your));
printf("sock : %d\n",rootsock);
your.sin_family = AF_INET;
your.sin_addr.s_addr = inet_addr("127.0.0.1");
your.sin_port = htons(1111);
connect(rootsock,(struct sockaddr*)&your,sizeof(your));
didi.id_sock = rootsock;
didi.id_gio_connect = g_io_add_watch(g_io_channel_unix_new(didi.id_sock),G_IO_IN | G_IO_OUT | G_IO_ERR | G_IO_HUP,(GIOFunc)incoming,&didi);
// network code //
gtk_main();
return 0;
}
and the only different had made is the "worked" code , need :
- gio for connecting, and gio for watching
instead of be "non-worked" code ( only gio for connecting ), but again i just wondering "why", why on connect() need two gio (recursively) in order make these "gio things" work,
these is really odd, if I see back then on g_io_channel + socket = server , still just get one client ? in C language
which on accept() just need only one gio and only for watching.
if someone could explain these, how great it'll be :)