Graphviz – Node with HTML label has no ports - graphviz

I have Mrecord nodes, each with a number of fields specified using an HTML label. I have TDs in my table each with a port="..." attribute. When I specify headport and tailport of an edge to use those port names though, I'm always getting a warning that the port is unrecognized:
ex: Warning: node departments, port dept_no unrecognized
and yet I'm 100% certain such a port does exist. Here's a trivial example of html:
<table><tr><td>departments</td></tr><tr><td port="dept_no">dept_no</td></tr></table>
Having set that as the node's label, I'd assume the node would have a dept_no port, but it doesn't.
--
Now a bit more info: I'm using the C API to construct this graph and do the layout etc. After layout the nodes each have a label, with the html boolean as true, but the label itself has no html data, and no ports, etc.
It's puzzling. I can't figure out why the nodes have no ports.
#include <stdio.h>
#include <gvc.h>
#include <gvplugin.h>
extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
extern gvplugin_library_t gvplugin_core_LTX_library;
lt_symlist_t lt_preloaded_symbols[] =
{
{ "gvplugin_dot_layout_LTX_library", &gvplugin_dot_layout_LTX_library},
{ "gvplugin_core_LTX_library", &gvplugin_core_LTX_library},
{ 0, 0}
};
int main(int argc, const char * argv[])
{
GVC_t * gvc = gvContextPlugins(lt_preloaded_symbols, 0);
Agraph_t * gvg = agopen("Graph", Agdirected, NULL);
agattr(gvg, AGRAPH, "dpi", "72");
agattr(gvg, AGRAPH, "resolution", "72");
agattr(gvg, AGRAPH, "sep", "0.27777");
agattr(gvg, AGRAPH, "rankdir", "TB");
agattr(gvg, AGRAPH, "ranksep", "0.5");
agattr(gvg, AGRAPH, "nodesep", "0.4");
agattr(gvg, AGRAPH, "pad", "0.5,0.5");
agattr(gvg, AGRAPH, "margin", "0,0");
agattr(gvg, AGRAPH, "splines", "spline");
agattr(gvg, AGNODE, "shape", "Mrecord");
agattr(gvg, AGNODE, "width", "0");
agattr(gvg, AGNODE, "height", "0");
agattr(gvg, AGNODE, "fixedsize", "false");
agattr(gvg, AGNODE, "margin", "0.0,0.0");
agattr(gvg, AGNODE, "penwidth", "0.0");
agattr(gvg, AGNODE, "fontsize", "13");
agattr(gvg, AGEDGE, "arrowsize", "0.5");
agattr(gvg, AGEDGE, "penwidth", "1.0");
agattr(gvg, AGEDGE, "labelangle", "32");
agattr(gvg, AGEDGE, "labeldistance", "1.8");
agattr(gvg, AGEDGE, "dir", "none");
agattr(gvg, AGEDGE, "headport", "_");
agattr(gvg, AGEDGE, "tailport", "_");
const char * nodeALabel = "<table id=\"dept_emp\" width=\"140\" height=\"26\"><tr><td height=\"26\">dept_emp</td></tr><tr><td height=\"20\" port=\"emp_no\">emp_no</td></tr><tr><td height=\"20\" port=\"dept_no\">dept_no</td></tr></table>";
const char * nodeBLabel = "<table id=\"departments\" width=\"140\" height=\"26\"><tr><td height=\"26\">departments</td></tr><tr><td height=\"20\" port=\"dept_no\">dept_no</td></tr><tr><td height=\"20\" port=\"dept_name\">dept_name</td></tr></table>";
Agnode_t * nodeA = agnode(gvg, "dept_emp", 1);
Agnode_t * nodeB = agnode(gvg, "departments", 1);
char * la = agstrdup_html(gvg, (char *)nodeALabel);
char * lb = agstrdup_html(gvg, (char *)nodeBLabel);
agsafeset(nodeA, "label", la, "");
agsafeset(nodeB, "label", lb, "");
agstrfree(gvg, la);
agstrfree(gvg, lb);
// An edge pointing from dept_emp.dept_no ---> departments.dept_no
Agedge_t * edge = agedge(gvg, nodeA, nodeB, NULL, 1);
agsafeset(edge, "dir", "forward", "none");
agsafeset(edge, "tailport", "dept_no", "_");
agsafeset(edge, "headport", "dept_no", "_");
gvLayout(gvc, gvg, "dot");
// Warning: node dept_emp, port dept_no unrecognized
// Warning: node departments, port dept_no unrecognized
return 0;
}

Although it is confusing that the HTML is rendered, but the ports are not recognized, Record-based nodes and HTML-like labels should just not be mixed. They have conflicting label schemas and overlapping functionality. As confirmed by one of the Graphviz authors, they are incompatible by design and it was simply not expected that people would try to combine the two. So, the solution is to replace Mrecord by none. For details, see https://gitlab.com/graphviz/graphviz/issues/1491.

Related

When i Compile GTK3+ Source code, has Error

when i Compile the GTK+ code ( in C ) gcc has many error !
this code is from GTK Demo but it's Examples not work on my Fedore 37 !
Screenshot from GTK Demo
that is source code :
#include <glib/gi18n.h>
#include <gtk/gtk.h>
enum
{
ICON_NAME_COL,
TEXT_COL
};
static GtkTreeModel *
create_icon_store (void)
{
const char *icon_names[6] = {
"dialog-warning",
"process-stop",
"document-new",
"edit-clear",
NULL,
"document-open"
};
const char *labels[6] = {
N_("Warning"),
N_("Stop"),
N_("New"),
N_("Clear"),
NULL,
N_("Open")
};
GtkTreeIter iter;
GtkListStore *store;
int i;
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
for (i = 0; i < G_N_ELEMENTS (icon_names); i++)
{
if (icon_names[i])
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
ICON_NAME_COL, icon_names[i],
TEXT_COL, _(labels[i]),
-1);
}
else
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
ICON_NAME_COL, NULL,
TEXT_COL, "separator",
-1);
}
}
return GTK_TREE_MODEL (store);
}
/* A GtkCellLayoutDataFunc that demonstrates how one can control
* sensitivity of rows. This particular function does nothing
* useful and just makes the second row insensitive.
*/
static void
set_sensitive (GtkCellLayout *cell_layout,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
GtkTreePath *path;
int *indices;
gboolean sensitive;
path = gtk_tree_model_get_path (tree_model, iter);
indices = gtk_tree_path_get_indices (path);
sensitive = indices[0] != 1;
gtk_tree_path_free (path);
g_object_set (cell, "sensitive", sensitive, NULL);
}
/* A GtkTreeViewRowSeparatorFunc that demonstrates how rows can be
* rendered as separators. This particular function does nothing
* useful and just turns the fourth row into a separator.
*/
static gboolean
is_separator (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data)
{
GtkTreePath *path;
gboolean result;
path = gtk_tree_model_get_path (model, iter);
result = gtk_tree_path_get_indices (path)[0] == 4;
gtk_tree_path_free (path);
return result;
}
static GtkTreeModel *
create_capital_store (void)
{
struct {
const char *group;
const char *capital;
} capitals[] = {
{ "A - B", NULL },
{ NULL, "Albany" },
{ NULL, "Annapolis" },
{ NULL, "Atlanta" },
{ NULL, "Augusta" },
{ NULL, "Austin" },
{ NULL, "Baton Rouge" },
{ NULL, "Bismarck" },
{ NULL, "Boise" },
{ NULL, "Boston" },
{ "C - D", NULL },
{ NULL, "Carson City" },
{ NULL, "Charleston" },
{ NULL, "Cheyenne" },
{ NULL, "Columbia" },
{ NULL, "Columbus" },
{ NULL, "Concord" },
{ NULL, "Denver" },
{ NULL, "Des Moines" },
{ NULL, "Dover" },
{ "E - J", NULL },
{ NULL, "Frankfort" },
{ NULL, "Harrisburg" },
{ NULL, "Hartford" },
{ NULL, "Helena" },
{ NULL, "Honolulu" },
{ NULL, "Indianapolis" },
{ NULL, "Jackson" },
{ NULL, "Jefferson City" },
{ NULL, "Juneau" },
{ "K - O", NULL },
{ NULL, "Lansing" },
{ NULL, "Lincoln" },
{ NULL, "Little Rock" },
{ NULL, "Madison" },
{ NULL, "Montgomery" },
{ NULL, "Montpelier" },
{ NULL, "Nashville" },
{ NULL, "Oklahoma City" },
{ NULL, "Olympia" },
{ "P - S", NULL },
{ NULL, "Phoenix" },
{ NULL, "Pierre" },
{ NULL, "Providence" },
{ NULL, "Raleigh" },
{ NULL, "Richmond" },
{ NULL, "Sacramento" },
{ NULL, "Salem" },
{ NULL, "Salt Lake City" },
{ NULL, "Santa Fe" },
{ NULL, "Springfield" },
{ NULL, "St. Paul" },
{ "T - Z", NULL },
{ NULL, "Tallahassee" },
{ NULL, "Topeka" },
{ NULL, "Trenton" },
{ NULL, NULL }
};
GtkTreeIter iter, iter2;
GtkTreeStore *store;
int i;
store = gtk_tree_store_new (1, G_TYPE_STRING);
for (i = 0; capitals[i].group || capitals[i].capital; i++)
{
if (capitals[i].group)
{
gtk_tree_store_append (store, &iter, NULL);
gtk_tree_store_set (store, &iter, 0, capitals[i].group, -1);
}
else if (capitals[i].capital)
{
gtk_tree_store_append (store, &iter2, &iter);
gtk_tree_store_set (store, &iter2, 0, capitals[i].capital, -1);
}
}
return GTK_TREE_MODEL (store);
}
static void
is_capital_sensitive (GtkCellLayout *cell_layout,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
gboolean sensitive;
sensitive = !gtk_tree_model_iter_has_child (tree_model, iter);
g_object_set (cell, "sensitive", sensitive, NULL);
}
static void
fill_combo_entry (GtkWidget *combo)
{
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "One");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Two");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "2\302\275");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Three");
}
/* A simple validating entry */
#define TYPE_MASK_ENTRY (mask_entry_get_type ())
#define MASK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MASK_ENTRY, MaskEntry))
#define MASK_ENTRY_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), TYPE_MASK_ENTRY, MaskEntryClass))
#define IS_MASK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MASK_ENTRY))
#define IS_MASK_ENTRY_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), TYPE_MASK_ENTRY))
#define MASK_ENTRY_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), TYPE_MASK_ENTRY, MaskEntryClass))
typedef struct _MaskEntry MaskEntry;
struct _MaskEntry
{
GtkEntry entry;
const char *mask;
};
typedef struct _MaskEntryClass MaskEntryClass;
struct _MaskEntryClass
{
GtkEntryClass parent_class;
};
static void mask_entry_editable_init (GtkEditableInterface *iface);
static GType mask_entry_get_type (void);
G_DEFINE_TYPE_WITH_CODE (MaskEntry, mask_entry, GTK_TYPE_ENTRY,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
mask_entry_editable_init));
static void
mask_entry_set_background (MaskEntry *entry)
{
if (entry->mask)
{
if (!g_regex_match_simple (entry->mask, gtk_editable_get_text (GTK_EDITABLE (entry)), 0, 0))
{
PangoAttrList *attrs;
attrs = pango_attr_list_new ();
pango_attr_list_insert (attrs, pango_attr_foreground_new (65535, 32767, 32767));
gtk_entry_set_attributes (GTK_ENTRY (entry), attrs);
pango_attr_list_unref (attrs);
return;
}
}
gtk_entry_set_attributes (GTK_ENTRY (entry), NULL);
}
static void
mask_entry_changed (GtkEditable *editable)
{
mask_entry_set_background (MASK_ENTRY (editable));
}
static void
mask_entry_init (MaskEntry *entry)
{
entry->mask = NULL;
}
static void
mask_entry_class_init (MaskEntryClass *klass)
{ }
static void
mask_entry_editable_init (GtkEditableInterface *iface)
{
iface->changed = mask_entry_changed;
}
GtkWidget *
do_combobox (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *vbox, *frame, *box, *combo, *entry;
GtkTreeModel *model;
GtkCellRenderer *renderer;
GtkTreePath *path;
GtkTreeIter iter;
if (!window)
{
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Combo Boxes");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_widget_set_margin_start (vbox, 10);
gtk_widget_set_margin_end (vbox, 10);
gtk_widget_set_margin_top (vbox, 10);
gtk_widget_set_margin_bottom (vbox, 10);
gtk_window_set_child (GTK_WINDOW (window), vbox);
/* A combobox demonstrating cell renderers, separators and
* insensitive rows
*/
frame = gtk_frame_new ("Items with icons");
gtk_box_append (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start (box, 5);
gtk_widget_set_margin_end (box, 5);
gtk_widget_set_margin_top (box, 5);
gtk_widget_set_margin_bottom (box, 5);
gtk_frame_set_child (GTK_FRAME (frame), box);
model = create_icon_store ();
combo = gtk_combo_box_new_with_model (model);
g_object_unref (model);
gtk_box_append (GTK_BOX (box), combo);
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
"icon-name", ICON_NAME_COL,
NULL);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
renderer,
set_sensitive,
NULL, NULL);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
"text", TEXT_COL,
NULL);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
renderer,
set_sensitive,
NULL, NULL);
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
is_separator, NULL, NULL);
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
/* A combobox demonstrating trees.
*/
frame = gtk_frame_new ("Where are we ?");
gtk_box_append (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start (box, 5);
gtk_widget_set_margin_end (box, 5);
gtk_widget_set_margin_top (box, 5);
gtk_widget_set_margin_bottom (box, 5);
gtk_frame_set_child (GTK_FRAME (frame), box);
model = create_capital_store ();
combo = gtk_combo_box_new_with_model (model);
g_object_unref (model);
gtk_box_append (GTK_BOX (box), combo);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
"text", 0,
NULL);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
renderer,
is_capital_sensitive,
NULL, NULL);
path = gtk_tree_path_new_from_indices (0, 8, -1);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
/* A GtkComboBoxEntry with validation */
frame = gtk_frame_new ("Editable");
gtk_box_append (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start (box, 5);
gtk_widget_set_margin_end (box, 5);
gtk_widget_set_margin_top (box, 5);
gtk_widget_set_margin_bottom (box, 5);
gtk_frame_set_child (GTK_FRAME (frame), box);
combo = gtk_combo_box_text_new_with_entry ();
fill_combo_entry (combo);
gtk_box_append (GTK_BOX (box), combo);
entry = g_object_new (TYPE_MASK_ENTRY, NULL);
MASK_ENTRY (entry)->mask = "^([0-9]*|One|Two|2\302\275|Three)$";
gtk_combo_box_set_child (GTK_COMBO_BOX (combo), entry);
/* A combobox with string IDs */
frame = gtk_frame_new ("String IDs");
gtk_box_append (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start (box, 5);
gtk_widget_set_margin_end (box, 5);
gtk_widget_set_margin_top (box, 5);
gtk_widget_set_margin_bottom (box, 5);
gtk_frame_set_child (GTK_FRAME (frame), box);
combo = gtk_combo_box_text_new ();
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "never", "Not visible");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "when-active", "Visible when active");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "always", "Always visible");
gtk_box_append (GTK_BOX (box), combo);
entry = gtk_entry_new ();
g_object_bind_property (combo, "active-id",
entry, "text",
G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), entry);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
but when i Compile it :
gcc `pkg-config --cflags gtk+-3.0` 1.c -o hello `pkg-config --libs gtk+-3.0`
Errors :
1.c: In function ‘mask_entry_set_background’:
1.c:251:47: warning: implicit declaration of function ‘gtk_editable_get_text’; did you mean ‘gtk_editable_get_type’? [-Wimplicit-function-declaration]
251 | if (!g_regex_match_simple (entry->mask, gtk_editable_get_text (GTK_EDITABLE (entry)), 0, 0))
| ^~~~~~~~~~~~~~~~~~~~~
| gtk_editable_get_type
1.c:251:47: warning: passing argument 2 of ‘g_regex_match_simple’ makes pointer from integer without a cast [-Wint-conversion]
251 | if (!g_regex_match_simple (entry->mask, gtk_editable_get_text (GTK_EDITABLE (entry)), 0, 0))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| int
In file included from /usr/include/glib-2.0/glib.h:77,
from /usr/include/glib-2.0/glib/gi18n.h:23,
from 1.c:1:
/usr/include/glib-2.0/glib/gregex.h:494:71: note: expected ‘const gchar *’ {aka ‘const char *’} but argument is of type ‘int’
494 | const gchar *string,
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~
1.c: In function ‘do_combobox’:
1.c:305:14: error: too few arguments to function ‘gtk_window_new’
305 | window = gtk_window_new ();
| ^~~~~~~~~~~~~~
In file included from /usr/include/gtk-3.0/gtk/gtkdialog.h:32,
from /usr/include/gtk-3.0/gtk/gtkaboutdialog.h:30,
from /usr/include/gtk-3.0/gtk/gtk.h:31,
from 1.c:2:
/usr/include/gtk-3.0/gtk/gtkwindow.h:147:12: note: declared here
147 | GtkWidget* gtk_window_new (GtkWindowType type);
| ^~~~~~~~~~~~~~
1.c:306:5: warning: implicit declaration of function ‘gtk_window_set_display’; did you mean ‘gdk_window_get_display’? [-Wimplicit-function-declaration]
306 | gtk_window_set_display (GTK_WINDOW (window),
| ^~~~~~~~~~~~~~~~~~~~~~
| gdk_window_get_display
1.c:316:5: warning: implicit declaration of function ‘gtk_window_set_child’; did you mean ‘gtk_window_set_role’? [-Wimplicit-function-declaration]
316 | gtk_window_set_child (GTK_WINDOW (window), vbox);
| ^~~~~~~~~~~~~~~~~~~~
| gtk_window_set_role
1.c:322:5: warning: implicit declaration of function ‘gtk_box_append’; did you mean ‘gtk_box_pack_end’? [-Wimplicit-function-declaration]
322 | gtk_box_append (GTK_BOX (vbox), frame);
| ^~~~~~~~~~~~~~
| gtk_box_pack_end
1.c:329:5: warning: implicit declaration of function ‘gtk_frame_set_child’; did you mean ‘gtk_frame_set_label’? [-Wimplicit-function-declaration]
329 | gtk_frame_set_child (GTK_FRAME (frame), box);
| ^~~~~~~~~~~~~~~~~~~
| gtk_frame_set_label
1.c:413:5: warning: implicit declaration of function ‘gtk_combo_box_set_child’; did you mean ‘gtk_combo_box_set_active’? [-Wimplicit-function-declaration]
413 | gtk_combo_box_set_child (GTK_COMBO_BOX (combo), entry);
| ^~~~~~~~~~~~~~~~~~~~~~~
| gtk_combo_box_set_active
1.c:442:5: warning: implicit declaration of function ‘gtk_window_destroy’; did you mean ‘gdk_window_destroy’? [-Wimplicit-function-declaration]
442 | gtk_window_destroy (GTK_WINDOW (window));
| ^~~~~~~~~~~~~~~~~~
| gdk_window_destroy
but when i Click on Run Button on GTK Demo, it run in my computer:
Run Key
Combo Boxes
Is there a problem with the gtk demo ?
Thanks
I tried to compile this code with GCC
and i tried Search on Google
The example code you're looking at and copying is for GTK4 while you're compiling against GTK3
Use
gcc `pkg-config --cflags gtk4` 1.c -o hello `pkg-config --libs gtk4`

Program stops drawing after compiling shaders

I am working on a C program to be compiled to WASM and display an image in the browser. The point of this program is to learn to set things up using EGL, and therefore I am not interested in any answers involving e.g. SDL, GLFW, etc.
This code works to clear the screen to blue (I've ommitted error checking to reduce size):
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "emscripten.h"
struct Environment
{
EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
EGLSurface surface;
};
static struct Environment g_env = {};
bool initGL(struct Environment* env)
{
env->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(env->display, &env->majorVersion, &env->minorVersion);
EGLint numConfigs = 0;
EGLint attribList[] =
{
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 1,
EGL_NONE
};
EGLConfig config;
eglChooseConfig(env->display, attribList, &config, 1, &numConfigs);
env->surface = eglCreateWindowSurface(env->display, config, 0, NULL);
static const EGLint contextAttribList[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
};
EGLContext context = eglCreateContext(env->display, config, EGL_NO_CONTEXT, contextAttribList);
eglMakeCurrent(env->display, env->surface, env->surface, context);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
return true;
}
void draw()
{
glViewport(0, 0, 300, 150);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(g_env.display, g_env.surface);
}
int main(int argc, char *argv[])
{
if (!initGL(&g_env))
{
return 1;
}
emscripten_set_main_loop(clearScreen, 0, 1);
return 0;
}
But as soon as I add the following after glClearColor(...), I no longer see a blue screen in the browser:
const GLuint vertex_shader = load_shader(GL_VERTEX_SHADER, VERTEX_SHADER);
const GLuint fragment_shader = load_shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
I suspect the shader code is not at all relevent to the problem, but just in case, here is the code for load_shader, taken from the OpenGL ES 2 book (error checking ommitted)
GLuint load_shader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader ( type );
// Load the shader source
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader
glCompileShader ( shader );
// Check the compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
return shader;
}
And the shaders themselves:
char VERTEX_SHADER[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
char FRAGMENT_SHADER[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"}
Here is how I compile:
EMSCRIPTEN_OPTS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s MODULARIZE=1
${EMCC} main_web.c -o hello.js ${EMSCRIPTEN_OPTS}
glGetError() is not returning an error code.
And here is my HTML:
<html>
<body>
<p id="output" />
<canvas id="canvas"></canvas>
<script type="application/javascript" src="hello.js"></script>
<script type="application/javascript">
Module({
canvas: (() => document.getElementById('canvas'))(),
print: (() => {
var element = document.getElementById('output');
return function(text) {
element.innerHTML += text + "<br>";
};
})()
})
</script>
</body>
</html>
Why do I stop clearing the screen when I just load the shaders?
The problem is with the HTML. When printing to stdout, the inline element was interefering with the block <canvas> element.
Problem solved by wrapping <p id="output"/> in a div.

freedesktop XEmbed systray client code in C, Xlib

I've been trying to implement a systray icon using straight C and Xlib, going along with the freedesktop specification [0]. I can't seem to get my Window to embed into my desktop manager's systray[1], while other apps seem to be able to do it. I am not sure how to go forward debugging this, but I've provided minimal sample code below.
I haven't been able to find any sample code using straight Xlib and C, and all the suggestions I've seen have been with regard to some framework like Gtk/Qt/Mono/whatever, but I want to understand what is supposed to be happening here as per the spec, and what I'm doing wrong.
#include <X11/Xutil.h>
#include <string.h>
#define MIN(A, B) ((A) < (B) ? (A) : (B))
/* --------- XEMBED and systray stuff */
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
static int trapped_error_code = 0;
static int (*old_error_handler) (Display *, XErrorEvent *);
static int
error_handler(Display *display, XErrorEvent *error) {
trapped_error_code = error->error_code;
return 0;
}
void
trap_errors(void) {
trapped_error_code = 0;
old_error_handler = XSetErrorHandler(error_handler);
}
int
untrap_errors(void) {
XSetErrorHandler(old_error_handler);
return trapped_error_code;
}
void
send_systray_message(Display* dpy, Window w, long message, long data1, long data2, long data3) {
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = w;
ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = data1;
ev.xclient.data.l[3] = data2;
ev.xclient.data.l[4] = data3;
trap_errors();
XSendEvent(dpy, w, False, NoEventMask, &ev);
XSync(dpy, False);
if (untrap_errors()) {
/* Handle errors */
}
}
/* ------------ Regular X stuff */
int
main(int argc, char **argv) {
int width, height;
XWindowAttributes wa;
XEvent ev;
Display *dpy;
int screen;
Window root, win;
/* init */
if (!(dpy=XOpenDisplay(NULL)))
return 1;
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
if(!XGetWindowAttributes(dpy, root, &wa))
return 1;
width = height = MIN(wa.width, wa.height);
/* create window */
win = XCreateSimpleWindow(dpy, root, 0, 0, width, height, 0, 0, 0xFFFF9900);
send_systray_message(dpy, win, SYSTEM_TRAY_REQUEST_DOCK, win, 0, 0);
XMapWindow(dpy, win);
XSync(dpy, False);
/* run */
while(1) {
while(XPending(dpy)) {
XNextEvent(dpy, &ev); /* just waiting until we error because window closed */
}
}
}
Any help would be greatly appreciated. I think this problem is language-agnostic, and more to do with me misunderstanding the protocols, so answers in any language are acceptable, as long as they help me iron out this XEvent stuff.
[0] https://specifications.freedesktop.org/systemtray-spec/systemtray-spec-0.2.html
[1] I'm using dwm with the systray patch http://dwm.suckless.org/patches/systray
You are sending the message to a wrong window. The documentation isn't really helpful, it makes no sense whatsoever to send a tray embed message to your own window!. You need to send it to the tray window.
Here's a a fixed send_systray_message
void
send_systray_message(Display* dpy, long message, long data1, long data2, long data3) {
XEvent ev;
Atom selection_atom = XInternAtom (dpy,"_NET_SYSTEM_TRAY_S0",False);
Window tray = XGetSelectionOwner (dpy,selection_atom);
if ( tray != None)
XSelectInput (dpy,tray,StructureNotifyMask);
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = tray;
ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message;
ev.xclient.data.l[2] = data1; // <--- your window is only here
ev.xclient.data.l[3] = data2;
ev.xclient.data.l[4] = data3;
trap_errors();
XSendEvent(dpy, tray, False, NoEventMask, &ev);
XSync(dpy, False);
usleep(10000);
if (untrap_errors()) {
/* Handle errors */
}
}
and a call to it
send_systray_message(dpy, SYSTEM_TRAY_REQUEST_DOCK, win, 0, 0); // pass win only once
Credits: http://distro.ibiblio.org/vectorlinux/Uelsk8s/GAMBAS/gambas-svn/gambas2/gb.gtk/src/gtrayicon.cpp

how to create second surface in Android NDK

I create surface with following code:
const EGLint attrs[] = {
EGL_LEVEL, 0,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NATIVE_RENDERABLE, EGL_FALSE,
EGL_DEPTH_SIZE, EGL_DONT_CARE,
EGL_NONE
};
FDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint major = 0;
EGLint minor = 0;
if (!eglInitialize(FDisplay, &major, &minor))
return;
EGLConfig eglConfig;
// Obtain the first configuration with a depth buffer
EGLint numConfig = 0;
if (!eglChooseConfig(FDisplay, attrs, &eglConfig, 1, &numConfig))
return;
FSurface = eglCreateWindowSurface(FDisplay, eglConfig,
single_native_window: FNativeHwnd, NULL);
The problem is that eglCreateWindowSurface is not successful, returns EGL_NO_SURFACE when calling for second surface. I call it passing FDisplay which is same display as was used for the first surface. What i do wrong? Maybe there is another approach to create second surface?

GTK+ Code Demos - compile Color Selector

I found out that Color Selector from the GTK+ Code Demos is a quite nice color chooser. Thus, I would like to use it as a standalone application without having to run gtk-demos every time.
I tried to compile the example code which is:
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
static GtkWidget *da;
static GdkColor color;
static GtkWidget *frame;
/* Expose callback for the drawing area
*/
static gboolean
expose_event_callback (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
GdkWindow *window = gtk_widget_get_window (widget);
if (window)
{
GtkStyle *style;
cairo_t *cr;
style = gtk_widget_get_style (widget);
cr = gdk_cairo_create (window);
gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
gdk_cairo_rectangle (cr, &event->area);
cairo_fill (cr);
cairo_destroy (cr);
}
return TRUE;
}
static void
change_color_callback (GtkWidget *button,
gpointer data)
{
GtkWidget *dialog;
GtkColorSelection *colorsel;
gint response;
dialog = gtk_color_selection_dialog_new ("Changing color");
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
colorsel =
GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (GTK_COLOR_SELECTION_DIALOG (dialog)));
gtk_color_selection_set_previous_color (colorsel, &color);
gtk_color_selection_set_current_color (colorsel, &color);
gtk_color_selection_set_has_palette (colorsel, TRUE);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if (response == GTK_RESPONSE_OK)
{
gtk_color_selection_get_current_color (colorsel,
&color);
gtk_widget_modify_bg (da, GTK_STATE_NORMAL, &color);
}
gtk_widget_destroy (dialog);
}
GtkWidget *
do_colorsel (GtkWidget *do_widget)
{
GtkWidget *vbox;
GtkWidget *button;
GtkWidget *alignment;
if (!window)
{
color.red = 0;
color.blue = 65535;
color.green = 0;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_screen (GTK_WINDOW (window),
gtk_widget_get_screen (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Color Selection");
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
vbox = gtk_vbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
gtk_container_add (GTK_CONTAINER (window), vbox);
/*
* Create the color swatch area
*/
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
da = gtk_drawing_area_new ();
g_signal_connect (da, "expose_event",
G_CALLBACK (expose_event_callback), NULL);
/* set a minimum size */
gtk_widget_set_size_request (da, 200, 200);
/* set the color */
gtk_widget_modify_bg (da, GTK_STATE_NORMAL, &color);
gtk_container_add (GTK_CONTAINER (frame), da);
alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
button = gtk_button_new_with_mnemonic ("_Change the above color");
gtk_container_add (GTK_CONTAINER (alignment), button);
gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
g_signal_connect (button, "clicked",
G_CALLBACK (change_color_callback), NULL);
}
if (!gtk_widget_get_visible (window))
{
gtk_widget_show_all (window);
}
else
{
gtk_widget_destroy (window);
window = NULL;
}
return window;
}
The error is:
[orschiro#thinkpad ~]$ gcc `pkg-config --cflags --libs gtk+-3.0` -o colorSelector colorSelector.ccolorSelector.c: In function ‘expose_event_callback’:
colorSelector.c:26:7: warning: ‘gdk_cairo_set_source_color’ is deprecated (declared at /usr/include/gtk-3.0/gdk/gdkcairo.h:58): Use 'gdk_cairo_set_source_rgba' instead [-Wdeprecated-declarations]
colorSelector.c: In function ‘change_color_callback’:
colorSelector.c:44:3: warning: ‘gtk_color_selection_dialog_new’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkcolorseldialog.h:73): Use 'gtk_color_chooser_dialog_new' instead [-Wdeprecated-declarations]
colorSelector.c:49:5: warning: ‘gtk_color_selection_dialog_get_color_selection’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkcolorseldialog.h:75): Use 'GtkColorChooser' instead [-Wdeprecated-declarations]
colorSelector.c:51:3: warning: ‘gtk_color_selection_set_previous_color’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkcolorsel.h:148) [-Wdeprecated-declarations]
colorSelector.c:52:3: warning: ‘gtk_color_selection_set_current_color’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkcolorsel.h:142): Use 'gtk_color_chooser_set_rgba' instead [-Wdeprecated-declarations]
colorSelector.c:53:3: warning: ‘gtk_color_selection_set_has_palette’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkcolorsel.h:100) [-Wdeprecated-declarations]
colorSelector.c:59:7: warning: ‘gtk_color_selection_get_current_color’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkcolorsel.h:145): Use 'gtk_color_chooser_get_rgba' instead [-Wdeprecated-declarations]
colorSelector.c: In function ‘do_colorsel’:
colorSelector.c:91:7: warning: ‘gtk_vbox_new’ is deprecated (declared at /usr/include/gtk-3.0/gtk/deprecated/gtkvbox.h:60): Use 'gtk_box_new' instead [-Wdeprecated-declarations]
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../lib/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Installed packages:
gtk2 2.24.14-1
gtk3 3.6.2-1
gcc-libs-multilib 4.7.2-2
gcc-multilib 4.7.2-2
Could someone please explain me the error?
Your source code is incomplete, the main function is missing. gtk-demo is organised so it has a single main that calls some submodules and processes them the same way, and you're missing that main.
The other warning come from the fact that this example code you're trying to compile was done for GTK 2, and you're trying to build it against GTK 3.
You'll find all the missing parts in the gtk-demo directory of the GTK+ repository.

Resources