Add and locate widgets in Gtk::DrawingArea - gtkmm

Greetings to all, I would like to know whether there is a way to add and locate a Gtk::Widget in Gtk::DrawingArea. My purpose of doing that is to show some detailed information on the graphics in the drawing area when the graphics is clicked. The detailed information can be rich-formatted.
I understood that Gtk::DrawingArea does not have the function like add(Widget). So I wonder if a work-around is available.
Thanks in advance & best regards.
CHEN Kai

Not sure how helpful it is, but I found this by searching:
Old Nabble - Gtk+ - Python - overlaying gtk widget over a gtk.drawing area
seems there is a gtk.Fixed()->put() function, but I cannot tell if it should run in a drawing loop or not.. (edit: see also GTK v1.2 Tutorial: Container Widgets)
Cheers!

Yep it's possible. Here you are. Enjoy the code in C:
#include <gtk/gtk.h>
#include <math.h>
GtkWidget *window;
GtkWidget *layout;
GtkWidget *canvas;
GtkWidget *image;
GtkWidget *eventbox;
static gboolean on_window_draw (GtkWidget *da, GdkEventExpose *event, gpointer data)
{
GdkWindow *window;
GdkDrawingContext *drawingContext;
cairo_region_t *cairoRegion;
cairo_t *cr;
cairoRegion = cairo_region_create();
window = gtk_layout_get_bin_window(GTK_LAYOUT(layout));
drawingContext = gdk_window_begin_draw_frame(window, cairoRegion);
cr = gdk_drawing_context_get_cairo_context(drawingContext);
cairo_set_line_width(cr, 9);
cairo_set_source_rgb(cr, 0.69, 0.19, 0);
cairo_translate(cr, 300/2, 200/2);
cairo_arc(cr, 0, 0, 50, 0, 2 * M_PI);
cairo_stroke_preserve(cr);
cairo_set_source_rgb(cr, 0.3, 0.4, 0.6);
cairo_fill(cr);
gdk_window_end_draw_frame(window, drawingContext);
cairo_region_destroy(cairoRegion);
return FALSE;
}
int main ( int argc, char **argv)
{
GtkWidget *button;
gtk_init (&argc , &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 300, 200);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit) , NULL);
canvas = gtk_drawing_area_new ();
layout = gtk_layout_new(NULL,NULL);
gtk_container_add (GTK_CONTAINER (layout), canvas);
gtk_container_add (GTK_CONTAINER (window), layout);
button = gtk_button_new_with_label("I feel alone...");
gtk_container_add(GTK_CONTAINER(layout), button);
gtk_layout_move(GTK_LAYOUT(layout), button, 90, 50);
g_signal_connect (canvas, "draw", (GCallback) on_window_draw, NULL);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}

Related

Have the information that GstPadProbeReturn have been called by my main

When my source is grabbing the stream, the callback function is called and I have the wxMessageBox("Got buffer"); which display the text Got Buffer. But At this point I don't know how to have the information in my main code that my stream is actually grabing something and so I can display it (I want to sure that my pipeline is grabbing something before asking for display). For example, changing my toolbar icon that indicate the user that the pipeline is actually grabbing something and he can display it. you can find my code bellow :
#include "MainWindow.h"
wxBEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_TOOL(10001, LoadVideo)
wxEND_EVENT_TABLE()
MainWindow::MainWindow(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxPoint(30, 30), wxSize(1224, 1024))
{
wxInitAllImageHandlers();
wxBitmap load(wxT("bitmap.png"), wxBITMAP_TYPE_PNG);
wxPanel* bg = new wxPanel(this, wxID_ANY);
bg->SetBackgroundColour(wxColor(230, 230, 230));
m_renderWindow = new wxWindow(bg, wxID_ANY);
m_renderWindow->SetBackgroundColour(*wxBLACK);
// Layout the UI.
wxBoxSizer* szr1 = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* szr2 = new wxBoxSizer(wxHORIZONTAL);
szr1->Add(m_renderWindow, wxSizerFlags(1).Expand().Border(wxBOTTOM));
szr1->Add(szr2, wxSizerFlags(0));
bg->SetSizer(szr1);
toolbar->AddTool(10001, _T("ContinuousShot"), load);
toolbar->Realize();
Layout();
// Set up the event handlers.
#ifdef __WXGTK__
m_renderWindow->Bind(wxEVT_CREATE, &MainWindow::OnRendererWinCreated, this);
#endif
// Initialize GStreamer.
m_xid = 0;
m_pipeline = NULL;
gst_init(NULL, NULL);
}
GstPadProbeReturn buffer_out_cb(GstPad* pad, GstPadProbeInfo* info, gpointer user_data)
{
GstElement* pipe = (GstElement*)user_data;
//toolbar->SetToolNormalBitmap(10001, wxBitmap(wxT(icon-open-device.png), wxBITMAP_TYPE_PNG));
wxMessageBox("Got buffer");
gst_element_set_state(pipe, GST_STATE_PAUSED);
//remove the probe if you don't need it anymore, otherwise return GST_PAD_PROBE_OK
return GST_PAD_PROBE_REMOVE;
}
void MainWindow::LoadVideo(wxWindowCreateEvent&)
{
GstPad* pad;
GError* error = NULL;
//GstElement* pipeline;
GstElement* source;
GstCaps* caps = gst_caps_new_simple("application/x-rtp",
"media", G_TYPE_STRING, "video",
"payload", G_TYPE_INT, 96,
"encoding-name", G_TYPE_STRING, "H264",
NULL);
m_pipeline = gst_parse_launch("udpsrc name=source !rtpjitterbuffer !rtph264depay !h264parse !avdec_h264 !autovideoconvert !d3dvideosink name=mysink sync=false ", &error);
if (!m_pipeline) {
g_print("Parse error: %s\n", error->message);
exit(1);
}
source = gst_bin_get_by_name(GST_BIN(m_pipeline), "source");
g_object_set(G_OBJECT(source), "caps", caps, NULL);
g_object_set(G_OBJECT(source), "port", m_port, NULL);
pad = gst_element_get_static_pad(source, "src");
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback)buffer_out_cb, m_pipeline, NULL);
gst_object_unref(pad);
#ifdef __WXGTK__
GstElement* sink = gst_bin_get_by_name((GstBin*)m_pipeline, "mysink");
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink), m_xid);
#elif defined __WXMSW__
GstElement* sink = gst_bin_get_by_name((GstBin*)m_pipeline, "mysink");
WXWidget hwnd = m_renderWindow->GetHandle();
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink),
reinterpret_cast<guintptr>(hwnd));
#endif
gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
}
The solution :
pass a pointer in the callback function (gpointer user_data), for example a int that is at 0 if the callback is not called and at 1 if it is called

How can I divide two cfg.enable_streams in D435 camera?

I wish to see two parts of a video by IntelRealsence D435 camera.
one is RGB in 640x480, another is IR(depth camera) in 1280x720.
the following code got error, maybe cfg.enable_stream can't be divided by size.
how can I divide them?
Here is my code:
#include <opencv2/opencv.hpp>
#include "example.hpp"
#include <stdio.h>
using namespace std;
using namespace cv;
int main()
{
rs2::pipeline pipe;
rs2::config cfg;
//Add desired streams to configuration
cfg.enable_stream(RS2_STREAM_COLOR, RS2_FORMAT_BGR8, 30);
//for infrared
//cfg.enable_stream(RS2_STREAM_INFRARED, 1280, 720, RS2_FORMAT_Y8, 30);
cfg.enable_stream(RS2_STREAM_DEPTH, RS2_FORMAT_Z16, 30);
pipe.start(cfg);
texture depth_image;
rs2::align align_to(RS2_STREAM_DEPTH);
rs2::decimation_filter dec;
dec.set_option(RS2_OPTION_FILTER_MAGNITUDE, 2);
rs2::disparity_transform depth2disparity;
// Define spatial filter (edge-preserving)
rs2::spatial_filter spat;
spat.set_option(RS2_OPTION_HOLES_FILL, 5);
rs2::temporal_filter temp;
rs2::disparity_transform disparity2depth(false);
rs2::frame_queue postprocessed_frames;
CvSize size = cvSize(1280, 720);
for (;;)
{
rs2::frameset frames = pipe.wait_for_frames();
rs2::frame color_frame = frames.get_color_frame();
rs2::colorizer color_map;
rs2::frame depth_frame = color_map(frames.get_depth_frame());
I will run this code to get picture
Mat color(Size(640, 480), CV_8UC3, (void*)color_frame.get_data(), Mat::AUTO_STEP);
const IplImage image_frame_show = new IplImage(color);
namedWindow("Display color", WINDOW_AUTOSIZE);
cvShowImage("Display color", image_frame_show);
Mat depth_show(Size(1280, 720), CV_8UC3, (void)depth_frame.get_data(), Mat::AUTO_STEP);
const IplImage *depth_frame_show = new IplImage(depth_show);
namedWindow("Display depth", WINDOW_AUTOSIZE);
cvShowImage("Display depth", depth_frame_show);
waitKey(10);
}
return 0;
}
The stream can be configured separately, please try to code below for configuration within pipeline.
rs2::pipeline pipe;
rs2::config cfg;
cfg.enable_stream(RS2_STREAM_COLOR, 640, 480, RS2_FORMAT_RGB8, 30);
cfg.enable_stream(RS2_STREAM_DEPTH, 1280, 720, RS2_FORMAT_Z16, 30);
pipe.start(cfg);

How to draw a texture as background in gtk?

I want to add a texture as background in a gtk container, is it possible?
What I want is similar to the repeat-x repeat-y properties in css, but it's not supported in gtk yet, so, how to do it without any ugly hacks?. Another example is what nautilus have, where you can change the background.
thanks :)
pd:sorry 4 ma english
I did it this way:
private bool draw_background (Cairo.Context cr) {
int width = this.get_allocated_width ();
int height = this.get_allocated_height ();
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
var background_style = this.get_style_context ();
background_style.render_background (cr, 0, 0, width, height);
background_style.render_frame (cr, 0, 0, width, height);
var pat = new Cairo.Pattern.for_surface (new Cairo.ImageSurface.from_png (Build.PKGDATADIR + "/files/texture.png"));
pat.set_extend (Cairo.Extend.REPEAT);
cr.set_source (pat);
cr.paint_with_alpha (0.6);
return false;
}

Sandboxing turned on and is there a more Objective-C way to go about opening a com port?

Right now I got the following class and its not working. It fails at the open call. I think this is because of sandboxing but I'm not sure how to move forward. Also this seems ver C like, is there a better more Objective-C (IOKIT?) way to fo this?
The device itself is a USB serial port.
Error given:
Failed to open device: Operation not permitted
Current code:
#include <termios.h>
#import "Com.h"
#define BAUDCOUNT 17
speed_t baud_const[BAUDCOUNT] = { B50, B75, B110, B134, B150, B200,
B300, B600, B1200, B1800, B2400, B4800,
B9600, B19200, B38400, B57600, B115200 };
unsigned long baud_value[BAUDCOUNT] = { 50, 75, 110, 134, 150, 200,
300, 600, 1200, 1800, 2400, 4800,
9600, 19200, 38400, 57600, 115200 };
#interface Com()
#property (assign) int fd;
#property (assign) struct termios oldio;
#end
#implementation Com
#synthesize fd = _fd;
#synthesize oldio = _oldio;
- (id)init
{
self = [super init];
if (self)
{
self.fd = -1;
return self;
}
return nil;
}
- (BOOL)open:(NSString*)device withBaud:(int)baud
{
struct termios oldio;
struct termios newtio;
// Find the correct baud rate
int baudid = -1;
for(int i = 0; i < BAUDCOUNT; i++) {
if (baud_value[i] == baud) {
baudid = i;
break;
}
}
if(baudid == -1)
{
NSLog(#"Invlaid baud rate: %d", baud);
return NO;
}
// Open the device
self.fd = open([device UTF8String], O_RDWR | O_NOCTTY | O_NDELAY);
if (self.fd < 0)
{
NSLog(#"Failed to open device: %s", strerror(errno));
return NO;
}
// Save old settings
tcgetattr(self.fd, &oldio);
self.oldio = oldio;
// Init memory
memset(&newtio, 0x00 , sizeof(newtio));
cfmakeraw(&newtio);
// settings flags
newtio.c_cflag |= CS8;
newtio.c_cflag |= CLOCAL;
newtio.c_cflag |= CREAD;
newtio.c_iflag = IGNPAR | IGNBRK;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
// Timeout in 100ms
newtio.c_cc[VTIME] = 0;
// read 1 character
newtio.c_cc[VMIN] = 0;
// Setting baudrate
cfsetispeed (&newtio, baud_const[baudid]);
cfsetospeed (&newtio, baud_const[baudid]);
// Flushing buffer
tcflush(self.fd, TCIOFLUSH);
// aplying new configuration
tcsetattr(self.fd, TCSANOW, &newtio);
return YES;
}
#end
Current Entitlements:
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
There are a couple of Objective C frameworks for handling the serial port.
AMSerialPort
SerialConnect
Update: It looks to me like you might need the com.apple.security.device.serial entitlement. Despite the fact you are using a USB Serial adapter I believe the OS device drivers make all serial ports appear the same, i.e. not USB devices. I suspect the com.apple.security.device.usb entitlement that you do have doesn't apply to USB serial devices.
Update 2: I've just found this Open Radar from August last year which reports your problem. So it looks like the com.apple.security.device.serial entitlement doesn't work (or certainly didn't work back in August).
Update 3: If you do need to access the USB device directly (and assuming this works with the com.apple.security.device.usb entitlement) then you probably want to look at the IOSerialFamily source code which is available at http://opensource.apple.com/source/IOSerialFamily/IOSerialFamily-59/.
Source tarball: http://opensource.apple.com/tarballs/IOSerialFamily/IOSerialFamily-59.tar.gz
you are doing some kernel programming which may be what you are wanting to do, but if you can use the IOKit then I do recommend that. In short doing anything with the kernel + sandboxing I simply do not recommend as you have found out.
The IOKit is another type of animal and really isn't too bad. Here is an example with a quick snippet that will disable the system from sleeping. This demonstrates how you can use the IOKit and I do believe it does work with a Sandboxed app.
IOPMAssertionID assertionID;
IOReturn err = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, CFSTR("Add Reason Here"), &assertionID);
if ( err == kIOReturnSuccess ) {
// Do stuff here while system is unable to sleep
// Let the system resume ability to sleep
err = IOPMAssertionRelease(assertionID);
}
This documentation should also help: link
Note: "Important If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices."

How to get the list of hyperlinks of a webpage in Webkit/Gtk?

In here a window is being created and a webpage is generated:
int main(int argc, char* argv[])
{
WebKitWebView *webView;
GtkWidget *main_window;
gtk_init(&argc, &argv);
if (!g_thread_supported())
g_thread_init(NULL);
#ifndef GTK_API_VERSION_2
disablePlugin("Shockwave Flash");
#endif
main_window = createWindow(&webView);
gchar *uri =(gchar*)(argc > 1 ? argv[1] : "http://www.google.com/");
gchar *fileURL = filenameToURL(uri);
webkit_web_view_load_uri(webView, fileURL ? fileURL : uri);
g_free(fileURL);
gtk_widget_grab_focus(GTK_WIDGET(webView));
gtk_widget_show_all(main_window);
gtk_main();
return 0;
}
And here is where a notification says that a page is being loaded:
void FrameLoaderClient::postProgressFinishedNotification()
{
WebKitWebView* webView = getViewFromFrame(m_frame);
WebKitWebViewPrivate* privateData = webView->priv;
if (!privateData->disposing)
g_signal_emit_by_name(webView, "load-finished", m_frame);
}
Now after the page is loaded, I want to get the list of focusable nodes such as hyperlinks, checkbox.
how can i do it?
What you want to look at is how to access the DOM from WebKit. WebKit has a webkit_web_view_get_dom_document() (http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#webkit-web-view-get-dom-document) which returns an instance of WebKitDOMDocument (https://live.gnome.org/WebKitGtk/ProgrammingGuide/Reference). This will give you direct access to the DOM and has methods like webkit_dom_document_get_elements_by_tag_name() to query the DOM. You could do something like this:
WebKitDomDocument *dom = webkit_web_view_get_dom_document(webview);
WebKitDOMNodeList *elements = webkit_dom_document_get_elements_by_tag_name(dom, "a");
int i = 0;
WebKitDOMElement *anchor = NULL;
for (; i < webkit_dom_node_list_get_length(elements); i++) {
anchor = (WebKitDOMElement *)webkit_dom_node_list_item(elements, i);
}
This is not perfect code, but you should get the idea from it. If you want to take a look at a somewhat comprehensive sample look here: http://www.opensource.apple.com/source/WebKit/WebKit-7533.16/gtk/tests/testdomdocument.c. Hope that helps.