Fast drawing tilings GTK and Cairo - gtk

I am new at drawing with Cairo and GTK, and the program I'm working on needs to draw a circle tiling of 500x500 or 1000x1000. Also, there are some work to do before drawing but right now I am focused on the drawing part which will involve mouse interaction to change the color of any circle.
So, the tiling is the same, and over time the circles have to change their color (all of them). I have to check with each circle and perform an operation, and after I check all circles, I have to display the changes. This process has to be performed any number of times.
Right now I have the tiling with a scrolled window, but just with this it takes a lot of time the scrolling. Thanks in advance. My code is next:
#include <cairo.h>
#include <gtk/gtk.h>
#include <math.h>
static void do_drawing(cairo_t *, GtkWidget *);
static int cellRadius=5;
static int cellDiameter=10;
static int latticeSideSize=500;
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data){
do_drawing(cr, widget);
return FALSE;
}
static void do_drawing(cairo_t *cr, GtkWidget *widget)
{
int i=0,j=0;
GtkWidget *win = gtk_widget_get_toplevel(widget);
int width, height;
gtk_window_get_size(GTK_WINDOW(win), &width, &height);
cairo_set_line_width(cr, .5);
cairo_set_source_rgb(cr, 0.69, 0.19, 0);
cairo_save (cr);
for(i=0;i<latticeSideSize;i++){
for(j=0;j<latticeSideSize;j++){
if(i%2 == 0){
cairo_arc(cr, cellRadius + 2*cellRadius + j*cellDiameter, cellRadius + cellRadius + i*cellDiameter, cellRadius, 0, 2 * M_PI);
cairo_stroke(cr);
}else{
cairo_arc(cr, cellRadius + cellRadius + j*cellDiameter, cellRadius + cellRadius + i*cellDiameter, cellRadius, 0, 2 * M_PI);
cairo_stroke(cr);
}
}
}
cairo_restore (cr);
}
static void destroy( GtkWidget *widget, gpointer data ){
gtk_main_quit ();
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *scrolled_window;
GtkWidget *darea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(scrolled_window), darea);
gtk_container_add(GTK_CONTAINER(window), scrolled_window);
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
g_signal_connect(G_OBJECT(scrolled_window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request( scrolled_window, 500, 500 );
gtk_window_set_default_size(GTK_WINDOW(window), 1024, 800);
gtk_widget_set_hexpand( scrolled_window, TRUE );
gtk_widget_set_vexpand( scrolled_window, TRUE );
gtk_window_set_title(GTK_WINDOW(window), "HexaGrid");
gtk_widget_set_size_request(darea,cellDiameter*latticeSideSize + 20,cellDiameter*latticeSideSize + 20);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_container_set_border_width(GTK_CONTAINER (scrolled_window), 10);
gtk_widget_show_all(window);
gtk_main();
return 0;
}

There's two problems here. First, you're doing the same fairly demanding calculation (the circle) 250000 times per draw, so 15 million circles per second if scrolling was smooth: that's not a realistic requirement. You should probably do the circle once and then apply the same result as surface pattern with CAIRO_EXTEND_REPEAT extend mode. You set the position of the pattern by using cairo_translate() and use cairo_set_source() to set your circle pattern as the source and then cairo_rectangle() + cairo_fill() to draw it. Cairo samples contain an example using a bitmap.
If some of the circles need to be in different color, you could draw some or all of them "manually" (without the repeating extend mode) but using a pattern is still probably a good idea to avoid calculating the circle many times.
Second, in the case of complex widgets it makes sense to not draw the whole widget but only the dirty region: see draw-signal documentation.

Related

How to draw a poppler document in a gtkmm DrawingArea

I am trying to draw a PDF with poppler gtk and a gtkmm DrawingArea, but it is not working, I am not sure what is wrong. The drawing area does not draw the document. I know the drawing area works otherwise with Cairo::Context::stroke(). Do I need to use a more gtk approach and wrap widget's to gtkmm?
Code:
// PdfViewer.h
#include <gtkmm.h>
#include <poppler.h>
#include "DrawingAreaFoo.h"
class PdfViewer: public Gtk::Box
{
public:
PdfViewer();
virtual ~PdfViewer();
private:
PopplerDocument *m_document;
PopplerPage *m_page;
DrawingAreaFoo m_drawingArea;
};
// PdfViewer.cpp
#include "PdfViewer.h"
PdfViewer::PdfViewer():
{
const char * uri = "file:////path/to/file/pdf.pdf";
m_document = poppler_document_new_from_file (uri, NULL, NULL);
auto total_pages = poppler_document_get_n_pages (m_document);
pack_start(m_drawingArea, TRUE, TRUE);
int w, h;
double width, height;
m_page = poppler_document_get_page (m_document, 0);
poppler_page_get_size (m_page, &width, &height);
w = (int) ceil(width);
h = (int) ceil(height);
cairo_surface_t * surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
m_drawingArea.drawSurface(surface);
}
PdfViewer::~PdfViewer(){}
// DrawinAreFoo.h
#include <gtkmm.h>
class DrawingAreaFoo : public Gtk::DrawingArea
{
public:
DrawingAreaFoo();
virtual ~DrawingAreaFoo();
void drawSurface (cairo_surface_t * surface);
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
Cairo::RefPtr<Cairo::Surface> m_refSurface;
};
// DrawinAreFoo.cpp
#include "DrawingAreaFoo.h"
DrawingAreaFoo::DrawingAreaFoo() {}
DrawingAreaFoo::~DrawingAreaFoo() {}
bool DrawingAreaFoo::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
if (m_refSurface)
{
cr->set_source(m_refSurface, 0, 0);
cr->paint();
}
return true;
}
void DrawingAreaFoo::drawSurface (cairo_surface_t * surface)
{
m_refSurface = Cairo::RefPtr<Cairo::Surface>{new Cairo::Surface(surface)} ;
Glib::RefPtr<Gdk::Window> win = get_window();
if (win)
{
Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height());
win->invalidate_rect(r, false);
}
}
UPDATE
The following after cairo_image_surface_create makes the code work.
cairo_t *cr = cairo_create (surface);
poppler_page_render (m_page, cr);
cairo_destroy (cr);
Added
cairo_t *cr = cairo_create (surface);
poppler_page_render (m_page, cr);
cairo_destroy (cr);
after
cairo_surface_t * surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);

How to render SDL2 texture into GTK3+ window?

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;
}

making a vending machine out of GTK

#include "UI.h"
GtkWidget* create_main_frame(gint wid, gint hgt)
{
GtkWidget* main_frame = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/* window attributes */
gtk_window_set_title( GTK_WINDOW(main_frame), "Welcome!!" );
gtk_window_set_default_size( GTK_WINDOW(main_frame), wid, hgt );
/* signals */
g_signal_connect(main_frame, "destroy", G_CALLBACK(gtk_main_quit), NULL);
return main_frame;
}
GtkWidget* create_scrolled_window(void)
{
GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS );
gtk_container_set_border_width( GTK_CONTAINER(scrolled_window), 10 );
return scrolled_window;
}
GtkWidget* create_box(GtkOrientation orn, gint spc)
{
GtkWidget* box = gtk_box_new(orn, spc);
//gtk_container_set_border_width( GTK_CONTAINER(box), 5 );
return box;
}
GtkWidget* create_layout(guint wid, guint hgt)
{
GtkWidget* layout = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(layout), wid, hgt );
return layout;
}
GtkWidget* create_grid(guint rsp, guint csp)
{
GtkWidget* grid = gtk_grid_new();
gtk_grid_set_row_spacing( GTK_GRID(grid), rsp );
gtk_grid_set_column_spacing( GTK_GRID(grid), csp );
return grid;
}
/*
GtkWidget* create_token_button(Token* tkn)
{
char parsed_value[11];
char* string = parse_to_string(tkn -> value, parsed_value);
GtkWidget* button = gtk_button_new_with_label(value);
//gtk_signal_connect(button, "clicked", G_CALLBACK, );
return button;
}
*/
GtkWidget* create_commodity_button(Commodity* com)
{
GtkWidget* button = gtk_button_new_with_label(com -> name);
//gtk_signal_connect(button, "clicked", G_CALLBACK, );
return button;
}
#include "UI.h"
int main(int argc, char* argv[])
{
int i, j;
/* vending machine */
VendingMachine* vending_machine;
/* frames */
GtkWidget* main_frame;
GtkWidget* scrolled_window;
GtkWidget* commodity_box, * commodity_layout, * commodity_grid, * commodity_button;
/* initialize */
gtk_init(&argc, &argv);
make_new_vending_machine_memory(&vending_machine, sizeof(VendingMachine) );
boot_vending_machine(vending_machine, 13, 13);
/* setting main frame */
main_frame = create_main_frame(1000, 750);
/* setting commodty frames and button table */
commodity_box = create_box(GTK_ORIENTATION_HORIZONTAL, 10);
scrolled_window = create_scrolled_window();
commodity_layout = create_layout(500, 700);
commodity_grid = create_grid(10, 10);
for (i = 0; i < 13; i++)
for (j = 0; j < 13; j++) {
commodity_button = create_commodity_button(&vending_machine -> commodity[i][j]);
gtk_grid_attach( GTK_GRID(commodity_grid), commodity_button, i * 300, j * 300, 5, 7 );
}
/* start adding and packing */
gtk_layout_put( GTK_LAYOUT(commodity_layout), commodity_grid, 10, 10 );
gtk_container_add( GTK_CONTAINER(scrolled_window), commodity_layout );
gtk_box_pack_start( GTK_BOX(commodity_box), scrolled_window, TRUE, TRUE, 10 );
gtk_container_add( GTK_CONTAINER(main_frame), commodity_box );
/* show all */
gtk_widget_show_all(main_frame);
gtk_main();
return 0;
}
I'm done writing the basic functions that are needed in my small vending machine project.
Now, I'm trying to make an UI out of the functions with GTK+. And I'm very confused since
this is the first time I'm actually using GTK.
I want a grid of commodity buttons that should be displayed on the left side, but I got
pretty much stuck on this part. What I'm trying to do is, since I "malloc"ed the commodities
for the purpose of adding and remove comms, I want a scroll bar attached to the comm window.
what I did as you can see in the source code
I made a grid of comm buttons and added on a layout widget.
I added the layout on a scrollbar widget
I added that scrollbar on a box and packed it.
I added that box to the main window.
the result is well "not satisfing"
I'm struggling through the GNOME official APIs
can somebody help me with this??
If you don't see how to create your user interface, give Glade a try. You'll be able to quickly try and see how the widgets fit together.

How do I make a gtkwindow background transparent on Linux?

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?

What could cause glutMainLoop() to not call the function passed to glutDisplayFunc()?

Trying to get a very simple opengl/glut/glew program up and running. Currently the display() function passed to glutDisplayFunc() is not being called. When executed, init() sets everything up and gives me a blank white window, but display never fills it with the generated points. Here is the init() function which is called just before entering the glutMainLoop():
void init()
{
//generate points
const int NumPoints = 5000;
point3 points[NumPoints];
point3 vertices[3] = {point3(-1.0, -1.0, 0.0),
point3(0.0, 1.0, 0.0),
point3(1.0, -1.0, 0.0)};
points[0] = point3(0.25, 0.5, 0.0);
for(int k = 1; k < NumPoints; k++)
{
int j = rand() % 3;
points[k] = (points[k-1]+vertices[j])/2.0;
}
//load shaders and use the resulting shader program
GLuint program = InitShader("shaders/vshader.glsl", "shaders/fshader.glsl");
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if( !linked ){
std::cerr << "Shader program failed to link" << std::endl;
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char *logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg);
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
glUseProgram( program );
//create Vertex-Array object
GLuint aBuffer;
glGenVertexArrays(1, &aBuffer);
glBindVertexArray((GLuint)&aBuffer);
//create Buffer object
GLuint buffer;
//glGenBuffers(1, &buffer);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points),
points, GL_STATIC_DRAW);
//initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation( program, "vPosition");
glEnableVertexAttribArray( loc );
glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glClearColor( 1.0, 1.0, 1.0, 1.0); // white background
}
and here are the main() and display() functions:
void display()
{
fprintf(stderr, "display called!\n");
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 5000);
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutDisplayFunc(display);
glutCreateWindow("Program 1");
glewInit();
init();
glutMainLoop();
return 0;
}
using eclipse CDT C/C++ with MinGW. Debugging shows that glutMainLoop is indeed being called but I can't follow it past that. Could it be a shader issue? They are reportedly compiling and linking fine, but here they are
vshader.glsl
#version 150
in vec4 vPosition;
void main() {
gl_Position = vPosition;
}
.
fshader.glsl
#version 150
out vec4 fColor;
void main() {
fColor = vec4(1.0, 0.0, 0.0, 1.0);
}
edit: the shaders definitely work. By inserting glutIdleFunc(display); into the main(), the program executes properly and draws all the expected points. So like I originally thought, for some reason glutMainLoop() just doesnt want to call the function passed to glutDisplayFunc()? Or am I doing something terribly wrong?
GLUT can create multiple windows. glutDisplayFunc operates on the currently active window, so you must call glutCreateWindow before the glut…Func functions.