I build one simple xfce panel plugin which dispalys a button labeled as 'Hello World". However, only half of the string can be displayed.
http://en.zimagez.com/miniature/debian807092016010347.png
The code is simple:
#include <gtk/gtk.h>
#include <libxfce4panel/xfce-panel-plugin.h>
static void sample_construct(XfcePanelPlugin *plugin);
XFCE_PANEL_PLUGIN_REGISTER(sample_construct);
static void hello(GtkWidget *widget, gpointer data)
{
g_print("Hello World\n");
}
static void sample_construct(XfcePanelPlugin *plugin)
{
GtkWidget *button;
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (hello), NULL);
gtk_container_add (GTK_CONTAINER (plugin), button);
gtk_widget_show (button);
}
build and install with this script:
#!/bin/bash
gcc -Wall -shared -o libsample.so -fPIC sample.c $(pkg-config --cflags --libs libxfce4panel-1.0) $(pkg-config --cflags --libs gtk+-2.0) || \
{ echo "Compiling failed!"; exit 10; }
cp libsample.so /usr/lib/xfce4/panel-plugins
cp sample.desktop /usr/share/xfce4/panel-plugins
OTHER INFO: xfce4.10, Debian 8 jessie.
You missed the "size-changed" signal.
If you add the following code it's going to work as expected:
static gboolean
sample_size_changed (XfcePanelPlugin *plugin,
gint size,
void *data)
{
GtkOrientation orientation;
orientation = xfce_panel_plugin_get_orientation (plugin);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_set_size_request (GTK_WIDGET (plugin), -1, size);
else
gtk_widget_set_size_request (GTK_WIDGET (plugin), size, -1);
return TRUE;
}
static void sample_construct(XfcePanelPlugin *plugin)
{
...
g_signal_connect (G_OBJECT (plugin), "size-changed",
G_CALLBACK (sample_size_changed), NULL);
gtk_widget_show_all (button);
}
Pay attention that you're also missing important callbacks such as "free-data" and "orientation-changed". Note that since Xfce 4.12, GTK+ 3.0 plugins are also supported, you only need to set X-XFCE-API=2.0 in .desktop file.
Source: xfce4-sample-plugin
Related
I try move some library from Arduino IDE to Eclipse IDE. In both cases the same compiler is used arm-none-eabi-gcc. But example in Arduino is linked succesfull, but project in Eclipse while linked have error:
RemoteXYWire.h:30: undefined reference to `vtable for CRemoteXYWire'.
And I understand that needed to define pure virtual function. But why the same toolchain work without error in Arduino IDE? That file:
#ifndef RemoteXYWire_h
#define RemoteXYWire_h
#include "RemoteXYComm.h"
#define REMOTEXY_INIT_CRC 0xffff
#define REMOTEXY_PACKAGE_START_BYTE 0x55
#define REMOTEXY_PACKAGE_MIN_LENGTH 6
struct CRemoteXYPackage {
uint8_t command;
uint8_t * buffer;
uint16_t length;
};
class CRemoteXYReceivePackageListener {
public:
virtual void receivePackage (CRemoteXYPackage * package) = 0;
};
class CRemoteXYWire {
private:
CRemoteXYReceivePackageListener * receivePackageListener;
public:
CRemoteXYWire () {
receivePackageListener = NULL;
}
public:
void setReceivePackageListener (CRemoteXYReceivePackageListener * listener) {
receivePackageListener = listener;
}
public:
void notifyReceivePackageListener (CRemoteXYPackage * package) {
if (receivePackageListener) receivePackageListener->receivePackage (package);
}
public:
virtual void handler () {};
virtual uint8_t running ();
virtual void stop ();
virtual void sendPackage (uint8_t command, uint8_t *buf, uint16_t length, uint8_t fromPgm);
};
#endif // RemoteXYWire_h
Calling linker in Arduino IDE:
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -DNDEBUG --specs=nano.specs -Wl,--defsym=LD_FLASH_OFFSET=0 -Wl,--defsym=LD_MAX_SIZE=65536 -Wl,--defsym=LD_MAX_DATA_SIZE=8192 -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--default-script=/home/kv193/.arduino15/packages/STMicroelectronics/hardware/stm32/2.3.0/variants/STM32F0xx/F030R8T/ldscript.ld -Wl,--script=/home/kv193/.arduino15/packages/STMicroelectronics/hardware/stm32/2.3.0/system/ldscript.ld -Wl,-Map,remxy-prj.ino.map -L/home/kv193/.arduino15/packages/STMicroelectronics/tools/CMSIS/5.7.0/CMSIS/DSP/Lib/GCC/ -larm_cortexM0l_math -o remxy-prj.ino.elf #object.list -lc -Wl,--end-group -lm -lgcc -lstdc++
Call linker from Eclipse:
arm-none-eabi-g++ --specs=nano.specs --specs=nosys.specs -mcpu=cortex-m3 -mthumb -mfloat-abi=soft -T"/home/kv193/KV/sRobot/verter-f1/LinkerScript.ld" -Wl,-Map=output.map -Wl,--gc-sections -fno-exceptions -fno-rtti -o "verter-f1.elf" #"objects.list" -lm
Why so significant difference results in that IDE's?
I am trying to set up server that also has a gui using GTK on a Raspberry Pi. The program is just a proof-of-concept demo.
I create a socket and the client can connect and send data, I see it in wireshark. But the read does not complete until the client disconnects. My code uses g_data_input_stream_read_line_async and g_data_input_stream_read_line_finish. The program displays the data the client sent after the client disconnects.
Here is the output of the program (that is the correct data that was sent by the client).
g_socket_listener_add_inet_port status: 1
g_signal_connect status: 2 (waits here until client connects)
socket connection established!
after g_data_input_stream_new
after g_data_input_stream_set_newline_type
after g_data_input_stream_read_line_async (waits here after client connects, and after client sends data)
before g_data_input_stream_read_line_finish (displays remaining output lines after client disconnects)
after g_data_input_stream_read_line_finish
length: 14
0 5 0 4 0 1 0 1 0 6 0 0 0 7
I suspect I am missing something simple since the data is received, but I've spent quite a few hours unsuccessfully trying to figure out what is missing.
// compiles with:
// gcc `pkg-config --cflags gtk+-3.0` gtk3serv.c -o gtk3serv `pkg-config --libs gtk+-3.0`
#include <gtk/gtk.h>
#include <gio/gio.h>
static void
print_hello (GtkWidget *widget,
gpointer data)
{
g_print ("Hello World\n");
}
static void
activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
// v<>v<>v<>v<>v<>v<>v<>v<>v<>v<>v
static void on_input_read_finish(GObject *object,
GAsyncResult *result,
gpointer user_data)
{
gchar *clientdata;
gsize length = -1;
gsize i;
g_print("before g_data_input_stream_read_line_finish\n"); // only for debug
clientdata = g_data_input_stream_read_line_finish(G_DATA_INPUT_STREAM(object),
result,
&length,
NULL);
g_print("after g_data_input_stream_read_line_finish\n"); // only for debug
g_print("length: %d\n", length); // only for debug
for(i=0; i<length; i++)
{
g_print("%x ", clientdata[i]);
}
g_print("\n");
}
gboolean sockconnectionestablished(GSocketService *sockservice,
GSocketConnection *connection,
GObject *source_object,
gpointer user_Data)
{
char *clientdata;
gsize length = -1;
gsize i;
g_print("socket connection established!\n"); // only for debug
GDataInputStream *gis = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(connection)));
g_print("after g_data_input_stream_new\n"); // only for debug
g_data_input_stream_set_newline_type(G_DATA_INPUT_STREAM(gis), G_DATA_STREAM_NEWLINE_TYPE_ANY);
g_print("after g_data_input_stream_set_newline_type\n"); // only for debug
g_data_input_stream_read_line_async(G_DATA_INPUT_STREAM(gis),
G_PRIORITY_DEFAULT,
NULL,
on_input_read_finish,
NULL);
g_print("after g_data_input_stream_read_line_async\n"); // only for debug
return 1;
}
// ^<>^<>^<>^<>^<>^<>^<>^<>^<>^<>^
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
// v<>v<>v<>v<>v<>v<>v<>v<>v<>v<>v
GError *sockerror = NULL;
GSocketService *sockservice;
gboolean sockstatus;
sockservice = g_socket_service_new();
sockstatus = g_socket_listener_add_inet_port(G_SOCKET_LISTENER(sockservice),
8888,
NULL,
NULL);
g_print("g_socket_listener_add_inet_port status: %d\n", sockstatus); // only for debug
status = g_signal_connect(sockservice,
"incoming",
G_CALLBACK(sockconnectionestablished),
NULL);
g_print("g_signal_connect status: %d\n", status); // only for debug
// ^<>^<>^<>^<>^<>^<>^<>^<>^<>^<>^
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
I am creating a music player and trying to use GTK3+ for creating user interface. I am using SDL_CreateWindowFrom function to let SDL2 use GTK3+ window rather than creating one but cann't figure out the steps I need to follow in order to render the SDL2 textures into GTK3+ window.
Code getting GTK3 window ID
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "---");
gtk_widget_show(window);
gdkWin = gtk_widget_get_window(GTK_WIDGET(window));
data->playContext->winID = GDK_WINDOW_XID(gdkWin);
gtk_main();
Code Setting SDL2 window
playContext->display->window = SDL_CreateWindowFrom((const void *)playContext->winID);
playContext->display->renderer = SDL_CreateRenderer(playContext->display->window, -1, playContext->display->render_flags);
Code Rendering SDL2 textures
SDL_RenderClear(playContext->display->renderer);
SDL_RenderCopy(playContext->display->renderer, playContext->textureQ.head->bmp, NULL, NULL);
SDL_RenderPresent(playContext->display->renderer);
Since example you put is effectively incomplete even on most important bits (e.g. renderer creation flags), and you don't specify which part gives you a problem, here is my example (which, on my system, works on both gtk2 and gtk3 - I wouldn't vouch it is completely fine though):
#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <SDL.h>
#include <stdbool.h>
static SDL_Window *sdl_window;
static SDL_Renderer *sdl_renderer;
static SDL_Surface *sdl_surface;
static GtkWindow *gtk_window;
static GtkWidget *gtk_da;
static void *gdk_window;
static void *window_id;
static gboolean idle(void *ud) {
(void)ud;
if(!sdl_window) {
printf("creating SDL window for window id %p\n", window_id);
sdl_window = SDL_CreateWindowFrom(window_id);
printf("sdl_window=%p\n", sdl_window);
if(!sdl_window) {
printf("%s\n", SDL_GetError());
}
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
printf("sdl_renderer=%p\n", sdl_renderer);
if(!sdl_renderer) {
printf("%s\n", SDL_GetError());
}
} else {
SDL_SetRenderDrawColor(sdl_renderer, 255, 0, 0, 255);
SDL_RenderClear(sdl_renderer);
SDL_RenderPresent(sdl_renderer);
}
return true;
}
int main(int argc, char **argv) {
gtk_init(&argc, &argv);
gtk_window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(gtk_window, "test");
gtk_da = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(gtk_window), gtk_da);
gtk_widget_show_all(GTK_WIDGET(gtk_window));
gdk_window = gtk_widget_get_window(GTK_WIDGET(gtk_da));
window_id = (void*)(intptr_t)GDK_WINDOW_XID(gdk_window);
SDL_Init(SDL_INIT_VIDEO);
g_idle_add(&idle, 0);
gtk_main();
return 0;
}
I have 2 threads
1)Holds the GTK main and gtk screen display codes (code is explained below) 2)generates key events according to user rquirement
if() block i ported into my code. but result is same. Once the signal is generated .after that its not coming to 2nd thread(signal generation thread). Have put debug prints ,but its not happening Seems its waiting on gtk_main on first thread.
What my code is :
void S1(void)
{
GtkWidget *Win_1;
GtkBuilder *builder;
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "/home/glade/glade1.glade", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "Win_1"));
g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
g_signal_connect (G_OBJECT (window), "key_press_event", G_CALLBACK(kp_event), NULL);
gtk_widget_show_all(window);
gtk_main();
}
kp_event()
{
gtk_widget_destroy (window);
S2();
}
S2 is same as S1,only screen item difference.Am calling S2() from keypress handler of S1 & vice versa. Since i have no keyboards attached,need to change two screens base on some user input via sockets or something.
You may need to call gtk_main() just one time, and use gtk_widget_hide() and gtk_window_present(), instead of gtk_widget_destroy(), declaring window1 and window2 as global variables, and creating the two windows at startup. A sample code:
GtkWidget * window1;
GtkWidget * window2;
void S1() {
// create the window
window1 = GTK_WIDGET (gtk_builder_get_object (builder, "Win_1"));
// do not call gtk_main()
}
void S2() {
// create the window
window2 = GTK_WIDGET (gtk_builder_get_object (builder, "Win_2"));
// do not call gtk_main()
}
kp_event_S1() {
gtk_widget_hide(window1);
gtk_window_present(GTK_WINDOW(window2));
}
kp_event_S2() {
gtk_widget_hide(window2);
gtk_window_present(GTK_WINDOW(window1));
}
int main() {
gtk_init();
S1();
S2();
gtk_widget_hide(window2);
gtk_main();
}
If you don't want to use global variables, you can do:
GtkWidget * S1() {
// create the window
GtkWidget * window1 = GTK_WIDGET (gtk_builder_get_object (builder, "Win_1"));
return window1;
}
GtkWidget * S2() {
// create the window
GtkWidget * window2 = GTK_WIDGET (gtk_builder_get_object (builder, "Win_2"));
return window2;
}
gboolean kp_event_S1(GtkWidget * window, GdkEvent e, gpointer user_data) {
gtk_widget_hide(window);
gtk_window_present(GTK_WINDOW(user_data));
}
gboolean kp_event_S2(GtkWidget * window, GdkEvent e, gpointer user_data) {
gtk_widget_hide(window);
gtk_window_present(GTK_WINDOW(user_data));
}
int main() {
gtk_init();
GtkWidget * w1 = S1();
GtkWidget * w2 = S2();
gtk_widget_hide(w2);
g_signal_connect (G_OBJECT (w1), "key-press-event", G_CALLBACK(kp_event_S1), (gpointer)w2);
g_signal_connect (G_OBJECT (w2), "key-press-event", G_CALLBACK(kp_event_S2), (gpointer)w1);
gtk_main();
}
I would like to make the background transparent, and only the widgets are visible.
Here is my code:
#include <gtk/gtk.h>
int main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
// Title
gtk_window_set_title(GTK_WINDOW (window), "Transparency");
//gtk_window_set_opacity(GTK_WINDOW(window), 0.5);
// CSS
GtkCssProvider *provider = gtk_css_provider_new();
GdkDisplay *display = gdk_display_get_default();
GdkScreen *screen = gdk_display_get_default_screen(display);
gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_css_provider_load_from_data(GTK_CSS_PROVIDER (provider),
"GtkWindow {\n"
" background-color: rgba(0,0,0,0);\n"
"}\n",
-1, NULL);
g_object_unref (provider);
// Window
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_resize(GTK_WINDOW(window), 400, 300);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I use gtk3. When the program execute, it just shows black. The CSS (or rgba) function does not work.
I try to use gtk_window_set_opacity(), but it also just shows black.
How do I fix my code?
I followed the link suggested by the comment, but unfortunately it was written for Gtk 2. I have re-worked it for Gtk 3. (I am using Gtk 3.8, but as far as I know it does not use anything deprecated in Gtk 3.10). The program produces a green semi-transparent square with button in it. Of course, you could make the square completely transparent by changing the last argument for the function cairo_set_source_rgba to 0.
Note: I compiled this with the following command (assuming you call the file transparent.c):
gcc -o transparent transparent.c `pkg-config gtk+-3.0 --libs --cflags`
Here is the code:
Version for C
/**
* Original code by: Mike - http://plan99.net/~mike/blog (now a dead link--unable to find it).
* Modified by karlphillip for StackExchange:
* (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
* Re-worked for Gtk 3 by Louis Melahn, L.C., January 30, 2014.
*/
#include <gtk/gtk.h>
static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer user_data);
static gboolean draw(GtkWidget *widget, cairo_t *new_cr, gpointer user_data);
static void clicked(GtkWindow *win, GdkEventButton *event, gpointer user_data);
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
gtk_window_set_title(GTK_WINDOW(window), "Alpha Demo");
g_signal_connect(G_OBJECT(window), "delete-event", gtk_main_quit, NULL);
gtk_widget_set_app_paintable(window, TRUE);
g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(draw), NULL);
g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(screen_changed), NULL);
gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(clicked), NULL);
GtkWidget* fixed_container = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), fixed_container);
GtkWidget* button = gtk_button_new_with_label("button1");
gtk_widget_set_size_request(button, 100, 100);
gtk_container_add(GTK_CONTAINER(fixed_container), button);
screen_changed(window, NULL, NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
gboolean supports_alpha = FALSE;
static void screen_changed(GtkWidget *widget, GdkScreen *old_screen, gpointer userdata)
{
/* To check if the display supports alpha channels, get the visual */
GdkScreen *screen = gtk_widget_get_screen(widget);
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
if (!visual)
{
printf("Your screen does not support alpha channels!\n");
visual = gdk_screen_get_system_visual(screen);
supports_alpha = FALSE;
}
else
{
printf("Your screen supports alpha channels!\n");
supports_alpha = TRUE;
}
gtk_widget_set_visual(widget, visual);
}
static gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer userdata)
{
cairo_save (cr);
if (supports_alpha)
{
cairo_set_source_rgba (cr, 0.5, 1.0, 0.50, 0.5); /* transparent */
}
else
{
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
}
/* draw the background */
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_restore (cr);
return FALSE;
}
static void clicked(GtkWindow *win, GdkEventButton *event, gpointer user_data)
{
/* toggle window manager frames */
gtk_window_set_decorated(win, !gtk_window_get_decorated(win));
}
Version for C++
I include a very similar program, this time written for gtkmm in C++. It can be compiled with the following command:
g++ -otransparent main.cpp transparent.cpp `pkg-config gtkmm-3.0 --cflags --libs` -std=c++11
Note that I used some of the features in the new C++-11 standard, so you will need a compiler that supports them. (If you don't have one, you just have to replace the auto keyword when it appears with the appropriate type, which you can figure out from the definition of the function.) There are three files: main.cpp, transparent.h, and transparent.cpp.
main.cpp
/**
* main.cpp
*
* Code adapted from 'alphademo.c' by Mike
* (http://plan99.net/~mike/blog--now a dead link--unable to find it.)
* as modified by karlphillip for StackExchange:
* (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
* Re-worked for Gtkmm 3.0 by Louis Melahn, L.C. January 31, 2014.
*/
#include "transparent.h"
#include
int main (int argc, char *argv[])
{
Glib::RefPtr app = Gtk::Application::create(argc, argv, "org.gtkmm.example.transparent");
Transparent transparent;
//Shows the window and returns when it is closed.
return app->run(transparent);
}
transparent.h
/**
* transparent.h
*
* Code adapted from 'alphademo.c' by Mike
* (http://plan99.net/~mike/blog--now a dead link--unable to find it.)
* as modified by karlphillip for StackExchange:
* (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
* Re-worked for Gtkmm 3.0 by Louis Melahn, L.C. January 31, 2014.
*/
#ifndef TRANSPARENT_H_
#define TRANSPARENT_H_
#include <iostream>
#include <gtk/gtk.h>
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/alignment.h>
class Transparent : public Gtk::Window
{
private:
std::string _buttonLabel;
public:
Transparent();
void set_visual(Glib::RefPtr<Gdk::Visual> visual);
virtual ~Transparent();
protected:
// Signal handlers:
// Note that on_draw is actually overriding a virtual function
// from the Gtk::Window class. I set it as virtual here in case
// someone wants to override it again in a derived class.
void on_button_clicked();
virtual bool on_draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr);
void on_screen_changed(const Glib::RefPtr<Gdk::Screen>& previous_screen);
bool on_window_clicked(GdkEventButton* event);
// Member widgets:
Gtk::Alignment _alignment;
Gtk::Button _button;
bool _SUPPORTS_ALPHA = false;
};
#endif /* TRANSPARENT_H_ */
transparent.cpp
/**
* transparent.cpp
*
* Code adapted from 'alphademo.c' by Mike
* (http://plan99.net/~mike/blog--now a dead link--unable to find it.)
* as modified by karlphillip for StackExchange:
* (https://stackoverflow.com/questions/3908565/how-to-make-gtk-window-background-transparent)
* Re-worked for Gtkmm 3.0 by Louis Melahn, L.C. January 31, 2014.
*/
#include "transparent.h"
Transparent::Transparent() :
_buttonLabel("Button1"),
_alignment(Gtk::ALIGN_START, Gtk::ALIGN_START, 0.0, 0.0), // Aligns the button.
_button(_buttonLabel) // Creates a new button with label '_buttonLabel'.
{
// Set up the top-level window.
set_title("Transparency test");
set_default_size(400,400);
set_decorated(false);
add_events(Gdk::BUTTON_PRESS_MASK);
set_position(Gtk::WIN_POS_CENTER);
set_app_paintable(true);
// Signal handlers
signal_draw().connect(sigc::mem_fun(*this, &Transparent::on_draw));
signal_screen_changed().connect(sigc::mem_fun(*this, &Transparent::on_screen_changed));
signal_button_press_event().connect(sigc::mem_fun(*this, &Transparent::on_window_clicked));
_button.signal_clicked().connect(sigc::mem_fun(*this, &Transparent::on_button_clicked));
// Widgets
on_screen_changed(get_screen());
// This will add the aligner.
add(_alignment);
// Now pack the button into the aligner.
_alignment.add(_button);
// Set up the button
_button.set_size_request(100, 100);
// Show the window and all its children.
show_all();
}
Transparent::~Transparent()
{
}
void Transparent::on_button_clicked()
{
std::cout << "The button '" << _buttonLabel << "' was pressed." << std::endl;
}
bool Transparent::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
cr->save();
if (_SUPPORTS_ALPHA) {
cr->set_source_rgba(0.5, 1.0, 0.5, 0.5); // transparent
} else {
cr->set_source_rgb(0.5, 1.0, 0.5); // opaque
}
cr->set_operator(Cairo::OPERATOR_SOURCE);
cr->paint();
cr->restore();
return Gtk::Window::on_draw(cr);
}
/**
* Checks to see if the display supports alpha channels
*/
void Transparent::on_screen_changed(const Glib::RefPtr<Gdk::Screen>& previous_screen) {
auto screen = get_screen();
auto visual = screen->get_rgba_visual();
if (!visual) {
std::cout << "Your screen does not support alpha channels!" << std::endl;
} else {
std::cout << "Your screen supports alpha channels!" << std::endl;
_SUPPORTS_ALPHA = TRUE;
}
set_visual(visual);
}
/**
* This simply adds a method which seems to be missing in Gtk::Widget,
* so I had to use Gtk+ manually.
*
* Sets the visual for 'this' (the current widget).
*/
void Transparent::set_visual(Glib::RefPtr<Gdk::Visual> visual) {
gtk_widget_set_visual(GTK_WIDGET(gobj()), visual->gobj());
}
/**
* If I click somewhere other than the button, this toggles
* between having window decorations and not having them.
*/
bool Transparent::on_window_clicked(GdkEventButton* event) {
set_decorated(!get_decorated());
return false;
}
Hope this helps!
While struggling with the same issue, I have noticed that if I call gtk_window_set_opacity() on the toplevel window after the show_all function, making the whole window (partial) transparent works for me. Give this a try:
gtk_widget_show_all ( window );
gtk_widget_set_opacity (GTK_WIDGET (window), 0.5);
Does that work for you too?