How to draw a cairo_surface_t in a Gtkmm DrawingArea - gtk

I am trying to draw a cairo_surface_t in Gtkmm DrawingArea.
Can the cairo_surface_t * be used to initialize a Glib::RefPtr which can be passed to the Cairo::Context::set_source?
#include <gtkmm.h>
class CDrawingArea : Gtk::DrawingArea
{
public:
CDrawingArea();
virtual ~CDrawingArea();
void DrawSurface (cairo_surface_t * surface);
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
cairo_surface_t * m_surface;
};
#include "CDrawingArea.h"
CDrawingArea::CDrawingArea()
{
}
CDrawingArea::~CDrawingArea()
{
}
void CDrawingArea::DrawSurface (cairo_surface_t * surface)
{
m_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);
}
}
bool CDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
// Cairo::RefPtr<Cairo::Surface> refSurface ??;
// cr->set_source(refSurface, 0, 0);
cr->paint();
}

Are you looking for the constructor of Surface?
Cairo::Surface::Surface ( cairo_surface_t * cobject,
bool has_reference = false
) [explicit]
Create a C++ wrapper for the C instance.
This C++ instance should then be given to a RefPtr.
(Copy&Paste broke the formatting, sorry)
https://cairographics.org/documentation/cairomm/reference/classCairo_1_1Surface.html#a47b90669a5a85d187cc0d28dc99915c8

Related

texture will not load to player in sfml

I am trying to load a texture to my player class. I made the function set text to do this operation. but when I call it in the main loop (and I made sure it's not in the poll event) it just shows a white rectangle. I changed it to 32 bits, but it didn't work and then to 8 and that also didn't work (its original bit was 24). I also made sure that it was that the texture wasn't loading, and it is not. all responses are appreciated.
void setText1() {
sf::Texture p1text;
p1text.loadFromFile("player1.png");
rect.setTexture(&p1text);
}
main.cpp
sf::RenderWindow window(sf::VideoMode(800,800), "High noon showdown", sf::Style::Close | sf::Style::Titlebar);
window.setFramerateLimit(60);
player1 player1(50, 70, 85, 325);
player2 player2(50, 70, 715, 325);
player1.setText1();
//game loop
//movement
window.clear(sf::Color(210,180,140,100));
player1.collidewindow1();
player1.drawto1(window);
player2.collidewindow2();
player2.drawto2(window);
window.display();
player1.hpp
#pragma once
#include <SFML/Graphics.hpp>
#include <stdlib.h>
#include <stdio.h>
#include <SFML/Window.hpp>
#include "main.h"
class player1
{
public:
//get player size and position
player1(float x, float y, float px, float py) {
rect.setSize(sf::Vector2f(x,y));
rect.setPosition(sf::Vector2f(px, py));
}
//draw player
void drawto1(sf::RenderWindow &window) {
window.draw(rect);
}
void collidewindow1() {
//Top collision
if(rect.getPosition().y < 0.0f) {
rect.setPosition(rect.getPosition().x, 0.0f);
}
//Bottom collision
if(rect.getPosition().y + rect.getGlobalBounds().height > 800) {
rect.setPosition(rect.getPosition().x, 800 - rect.getGlobalBounds().height );
}
}
void upfalse1() {
up = false;
}
void downfalse1() {
down = false;
}
void moveup1() {
up = true;
if(up == true){
rect.move(0.0f, -5.0f * dt * 32.5f);
}
}
void movedown1() {
down = true;
if(down == true) {
rect.move(0.0f, 5.0f * dt * 32.5f);
}
}
void setText1() {
sf::Texture p1text;
p1text.loadFromFile("p1.png");
rect.setTexture(&p1text);
}
int getx1() {
return rect.getPosition().x;
}
int gety1() {
return rect.getPosition().y;
}
private:
sf::RectangleShape rect;
bool up;
bool down;
};
sf::Sprites need textures to work. They save the textures in pointer form so using temporary variable will not work. You need your texture to either be a dynamic variable or be in a place until the sprite you created is destroyed.
If you don't want to play with dynamic variables i suggest you put the texture variable into a 'player' object.
This is what's breaking your code:
void setText1() {
sf::Texture p1text; <- you create texture
p1text.loadFromFile("player1.png"); <- load the texture
rect.setTexture(&p1text); <- set the rect/sprite with texture
} <- texutre gets deleted thus sprite/rect point to adress with no texture
Fix:
class Player1
{
...
private:
sf::RectangleShape rect;
bool up;
bool down;
sf::Texture texture; <- void setText1() should set this texture
};

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

Drag and drop with TTreeView in Firemonkey

I am using C++ Builder 10.2.2 Tokyo with FireMonkey (FMX).
I want to add drag and drop functionality to a TTreeView, so a user can rearrange the order of the tree items. I have added a handler to the TTreeView.OnMouseDown event, based on this Drag and Drop sample project.
With this, the program can now drag and drop to rearrange items, but it seems that there is some default behavior to move a TTreeViewItem to be a child of the TTreeViewItem it is dropped onto, instead of inserting after that item.
How can I override this default behavior, so that a TTreeViewItem is inserted at the same level in the TTreeView, and at an index 1 greater than the TTreeViewItem it is dropped onto?
Following on Abdullah's suggestion, you can achieve this by creating a custom component. Directions to create a custome component in general are here. I recommend installing it in Standard on the Tool Palette, as that's where TTreeView is.
The custom component, here called TMyTreeView, has this in the header in particular:
class PACKAGE TMyTreeView : public TTreeView
{
private:
bool IsAncestor (TTreeViewItem* oItem, TTreeViewItem* oTargetItem);
protected:
int DragDelta;
void StartDrag ();
void __fastcall DragDrop (const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point);
void __fastcall MouseDown (System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, float X, float Y);
void __fastcall MouseMove (System::Classes::TShiftState Shift, float X, float Y);
public:
__fastcall TMyTreeView(TComponent* Owner);
__fastcall ~TMyTreeView ();
TBitmap* DragBmp;
TPointF MouseDownPoint;
TTreeViewItem* DragStartItem;
__published:
};
//---------------------------------------------------------------------------
where the functions are as follows in the corresponding cpp file:
__fastcall TMyTreeView::TMyTreeView(TComponent* Owner)
: TTreeView(Owner)
{
DragBmp = NULL;
DragStartItem = NULL;
DragDelta = 5;
}
//---------------------------------------------------------------------------
__fastcall TMyTreeView::~TMyTreeView ()
{
if (DragBmp)
delete DragBmp;
}
//---------------------------------------------------------------------------
void __fastcall TMyTreeView::MouseMove (System::Classes::TShiftState Shift, float X, float Y)
{
TTreeView::MouseMove (Shift, X, Y);
if ((abs (X-MouseDownPoint.X) > DragDelta) || (abs (Y-MouseDownPoint.Y) > DragDelta))
StartDrag ();
}
//---------------------------------------------------------------------------
void TMyTreeView::StartDrag ()
{
if (!AllowDrag)
return;
if (!DragStartItem)
return;
if (DragBmp)
delete DragBmp;
_di_IFMXDragDropService service;
if ((TPlatformServices::Current->SupportsPlatformService (__uuidof(IFMXDragDropService)) &&
(service = TPlatformServices::Current->GetPlatformService (__uuidof(IFMXDragDropService)))))
{
TDragObject dragData;
if (!DragStartItem)
return;
dragData.Source = DragStartItem;
DragBmp = DragStartItem->MakeScreenshot ();
dragData.Data = DragBmp;
service->BeginDragDrop ((TForm*)this->Owner, dragData, DragBmp);
DragStartItem = NULL;
}
}
//---------------------------------------------------------------------------
void __fastcall TMyTreeView::MouseDown (System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, float X, float Y)
{
TTreeView::MouseDown (Button, Shift, X, Y);
if (AllowDrag)
{
DragStartItem = ItemByPoint (X, Y);
MouseDownPoint.X = X;
MouseDownPoint.Y = Y;
}
else
DragStartItem = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TMyTreeView::DragDrop (const Fmx::Types::TDragObject &Data, const System::Types::TPointF &Point)
{
TTreeViewItem* item = ItemByPoint (Point.X, Point.Y);
if (!item)
return;
TTreeViewItem* srcItem = (TTreeViewItem*)Data.Source;
if (!srcItem)
return;
if (IsAncestor (srcItem, item))
return;
if (item->ParentItem ())
item->ParentItem ()->InsertObject (item->Index, srcItem);
else
this->InsertObject (item->Index, srcItem);
//TTreeView::DragDrop (Data, Point);
}
//---------------------------------------------------------------------------
bool TMyTreeView::IsAncestor (TTreeViewItem* oItem, TTreeViewItem* oTargetItem)
{
for (int i=0; i<oItem->Count; i++)
{
TTreeViewItem* item = oItem->Items [i];
if (item == oTargetItem)
return true;
if (IsAncestor (item, oTargetItem))
return true;
}
return false;
}
//---------------------------------------------------------------------------
After installing the custom component to your Tool Palette, you can then add it to your form as you would any other component.
Special thanks to Mike Sutton, who had code to modify an earlier version of TTreeView here.
Once added to a form, set the TMyTreeView control's AllowDrag to true.

Creating class object c++ in if-statement

I actually have a small question. I want to create an attribute "function" which should be from the class function1, function2 or function3. Is there a way I can do that?
Here is the code:
double Uppersum::evalIntegral(double p_) {
if (functiontype == FUNKTION1){
Function1 function;
}
else if (functiontype == FUNKTION2) {
Function2 function;
}
else if (functiontype == FUNKTION3){
Function3 function;
}
function.setParameterP(p_);
double increment_h = (boundary_b - boundary_a)/num_subintervalls_m;
double sum = 0;
for (int index_i = 0; index_i < num_subintervalls_m -1; index_i++){
double x_1 = index_i * increment_h;
double x_2 = (index_i+1) * increment_h;
double y_1, y_2;
y_1 = function.evalFunctionValue(x_1);
y_2 = function.evalFunctionValue(x_2);
sum += increment_h * std::max(y_1, y_2);
}
}
class Function {
protected:
double parameter_p;
public:
void setParameterP(double p_);
virtual double evalFunctionValue(double x_)=0;
};
class Function1 : public Function {
public:
double evalFunctionValue(double x_);
};
Why not use inheritance, superclass has the virtual functions setParameterP and evalFunctionValue. and in subclasses, override those virtual functions.
here is the test codeļ¼š
test.cpp
#include <iostream>
typedef enum{
FUNCTION1,
FUNCTION2,
FUNCTION3
}FunctionType;
using namespace std;
class super
{
public:
super(){}
~super(){}
virtual void setParameterP() = 0;
virtual void evalFunctionValue() = 0;
};
class func1:public super
{
public:
func1(){}
virtual void setParameterP(){cout<<"call setParameterP In func1"<<endl;}
virtual void evalFunctionValue(){cout<<"call evalFunctionValue In func1"<<endl;}
};
class func2:public super
{
public:
func2(){}
virtual void setParameterP(){cout<<"call setParameterP In func2"<<endl;}
virtual void evalFunctionValue(){cout<<"call evalFunctionValue In func2"<<endl;}
};
class func3:public super
{
public:
func3(){}
virtual void setParameterP(){cout<<"call setParameterP In func3"<<endl;}
virtual void evalFunctionValue(){cout<<"call evalFunctionValue In func3"<<endl;}
};
class FuncFactory
{
public:
static super* create(FunctionType var)
{
super* ret = nullptr;
switch (var)
{
case FUNCTION1:
ret = new func1();
break;
case FUNCTION2:
ret = new func2();
break;
case FUNCTION3:
ret = new func3();
break;
default:
cout <<"invalid FunctionType" << endl;
}
return ret;
}
};
int main(int argc, char** argv)
{
super* pFunc = FuncFactory::create(FUNCTION1);
pFunc->setParameterP();
pFunc->evalFunctionValue();
delete pFunc;
pFunc = FuncFactory::create(FUNCTION2);
pFunc->setParameterP();
pFunc->evalFunctionValue();
delete pFunc;
pFunc = FuncFactory::create(FUNCTION3);
pFunc->setParameterP();
pFunc->evalFunctionValue();
delete pFunc;
return 0;
}
here is the process result:
result

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?