According to https://developer.gnome.org/gdk3/stable/GdkScreen.html#gdk-screen-get-active-window,
gdk_screen_get_active_window has been deprecated since version 3.22 and should not be used in newly-written code.
But, what should be used instead? (This is one of many deprecated GdkScreen functions.)
To be specific, how would I obtain the location and geometry of the active window?
Edit 12/10/16: After a couple of days looking into this, I've come to the conclusion the answer to this question is outside developer.gnome.org. It may be that separate code needs to be written directly targeting X11, wayland, and mir.
For what it's worth, below is get_window-areas.c that I have written exploring what can be found in Gtk without using deprecated functions. It seems there isn't a way to get window titles or active status; so that, I could not duplicate the functionality of #theGtknerd's answer which uses unstable Wnck libraries.
I am just learning Gtk, so I do appreciate any comments for improving this. I started with the empty window code https://developer.gnome.org/gtk3/stable/gtk-getting-started.html#id-1.2.3.5, added a textview with buffer to it, and then inserted information about the geometry and location of each window into the text buffer.
gcc `pkg-config --cflags gtk+-3.0` -o get_window-areas get_window-areas.c `pkg-config --libs gtk+-3.0`
Compile get_window-areas.c below with the gcc command above.
#include <gtk/gtk.h>
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window = NULL;
GtkWidget *text_view;
GtkTextBuffer *buffer;
int x = 0, y = 0, width = 0, height = 0;
char char_x[5], char_y[5], char_width[5], char_height[5];
GdkScreen *screen;
GdkWindow *dwindow;
GList *gl_item = NULL, *gl = NULL;
window = gtk_application_window_new (app);
screen = gtk_window_get_screen (GTK_WINDOW(window));
buffer = gtk_text_buffer_new (NULL);
text_view = gtk_text_view_new_with_buffer (buffer);
gtk_container_add (GTK_CONTAINER (window), text_view);
if(screen != NULL)
{
gl = gdk_screen_get_window_stack(screen);
for (gl_item = g_list_first(gl); gl_item != NULL; gl_item = gl_item->next)
{
dwindow=gl_item->data;
gdk_window_get_root_origin(dwindow, &x, &y);
width = gdk_window_get_width(dwindow);
height = gdk_window_get_height(dwindow);
g_object_unref(dwindow);
snprintf (char_x, 5, "%d", x);
snprintf (char_y, 5, "%d", y);
snprintf (char_width, 5, "%d", width);
snprintf (char_height, 5, "%d", height);
gtk_text_buffer_insert_at_cursor(buffer,char_width,-1);
gtk_text_buffer_insert_at_cursor(buffer,"x", -1);
gtk_text_buffer_insert_at_cursor(buffer,char_height,-1);
gtk_text_buffer_insert_at_cursor(buffer," at (", -1);
gtk_text_buffer_insert_at_cursor(buffer,char_x, -1);
gtk_text_buffer_insert_at_cursor(buffer,",", -1);
gtk_text_buffer_insert_at_cursor(buffer,char_y,-1);
gtk_text_buffer_insert_at_cursor(buffer,")\n", -1);
};
g_list_free (gl);
}
else {gtk_text_buffer_insert_at_cursor(buffer, "Failed to get default screen.\n", -1);}
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("com.github.colinkeenan.silentcast", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
Here is Python code that gets the active window and prints its geometry.
#!/usr/bin/python
import gi
gi.require_version('Wnck', '3.0')
from gi.repository import Wnck
screen = Wnck.Screen.get_default()
screen.force_update() # recommended per Wnck documentation
# loop all windows
for window in screen.get_windows():
if window.is_active() == True:
print (window.get_geometry())
window_name = window.get_name()
print (window_name)
# clean up Wnck (saves resources, check documentation)
window = None
screen = None
Wnck.shutdown()
The documentation is https://developer.gnome.org/libwnck/stable/WnckWindow.html.
Edit: I am trying to compile the C I have with:
gcc `pkg-config --cflags --libs libwnck-3.0` -o wnck wnck.c
and I get the error:
/usr/include/libwnck-3.0/libwnck/window.h:30:2: error: #error "libwnck should only be used if you understand that it's subject to frequent change, and is not supported as a fixed API/ABI or as part of the platform"
there is a workaround, but I am not sure Wnck is a good replacement for GdkScreen. I really do not know what to tell you at this point.
(edit 3/11/17 to eliminate memory leaks by closing display whenever opened)
(edit 3/6/17 to initialize s in get_top_window)
(edit 12/24 to provide a complete answer for X11, and marking as correct answer until somebody has a general solution). It is part of my in progress rewriting/refactoring of my silentcast application (previously just a series of bash scripts using yad for the UI) on github, although I have not yet put any of this Gtk code on github.
My "Correct Answer" below allows you to actually get the active GdkWindow, it's geometry & extents, or the active X11 window with children, and it's geometry.
Correct Answer
(note that it only applies to X11 so should include and compile against gtk/gtkx.h, not gtk/gtk.h)
.h file
/*
* Filename: SC_X11_get_active_window.h
* App Name: Silentcast <https://github.com/colinkeenan/silentcast>
* Copyright © 2016, 2017 Colin N Keenan <colinnkeenan#gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Description: defines some custom X11 error messags and exposes 3 functions:
* SC_get_active_gdkwindow (...), SC_get_geomeotry_for (...),
* and SC_get_active_windows_and_geometry (...)
*/
#include <gtk/gtkx.h>
#define SC_X11_ERROR0 " \n"
#define SC_X11_ERROR1 "Failed to connect to X server.\n"
#define SC_X11_ERROR2 "x11 error trying to get focused window\n"
#define SC_X11_ERROR3 "X11 reports no focused window\n"
#define SC_X11_ERROR4 "X11 error trying to get top window\n"
#define D_ERR 1
#define FOCUS_ERR1 2
#define FOCUS_ERR2 3
#define TOP_ERR 4
#define UKN_ERR 5
#define SC_X11_E1 D_ERR
#define SC_X11_E2 FOCUS_ERR1
#define SC_X11_E3 FOCUS_ERR2
#define SC_X11_E4 TOP_ERR
#define SC_X11_E0 UKN_ERR
unsigned int SC_get_active_X11window (Window *w, Window* *w_children, ssize_t *n);
gboolean SC_get_active_gdkwindow (Window aw, Window *aw_children, ssize_t n, GdkWindow* *gdkwindow);
void SC_get_geometry_for (Window aw, Window *aw_children, ssize_t n, int *x, int *y,
unsigned int *width, unsigned int *height, GdkRectangle *extents, GdkWindow* *gdkwindow);
gboolean SC_get_active_windows_and_geometry (Window *aw, Window* *aw_children, ssize_t *n,
int *x, int *y, unsigned int *width, unsigned int *height, GdkRectangle *extents, GdkWindow* *gdkwindow);
.c file
/*
* Filename: SC_X11_get_active_window.c
* App Name: Silentcast <https://github.com/colinkeenan/silentcast>
* Copyright © 2016 Colin N Keenan <colinnkeenan#gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Description: adapted from "get the active window on X window system"
* https://gist.github.com/kui/2622504
* to get Gdk geometry of the active window, both the
* inner window and the extents
*/
#include "SC_X11_get_active_window.h"
Bool xerror = False;
static int handle_error (Display* display, XErrorEvent* error) {
xerror = True;
return 1;
}
static int get_focus_window (Display* d, Window *w) {
int revert_to;
XGetInputFocus (d, w, &revert_to);
if (xerror) return FOCUS_ERR1; //X error trying to get focused window
else if (w == None) return FOCUS_ERR2; //no focused window
else return 0;
}
static int get_top_window (Display* d, Window start, Window *w, Window* *w_children, ssize_t *n) {
Window parent = start, root = None, *children = NULL;
*w = start;
unsigned int nchildren;
Status s = XQueryTree (d, *w, &root, &parent, &children, &nchildren), s_prev;
/* ultimately trying to get *w and *w_children */
while (parent != root && !xerror) {
*w = parent; //previous parent
s_prev = s; //previous status of XQueryTree
if (s_prev) {
*w_children = children; //previous children
*n = nchildren; //previous number of children
}
s = XQueryTree (d, *w, &root, &parent, &children, &nchildren);
/* When parent == root, the previous "parent" is the top window.
* Save the children of the top window too, but XFree all other
* children.
*/
if (parent != root) {
// parent is not root, so previous parent wasn't top window, so don't need it's children
if (s_prev) XFree (*w_children);
} else
if (s) XFree (children); // don't keep the children of root either
}
if (xerror) return TOP_ERR;
else return 0;
}
unsigned int
SC_get_active_X11window (Window *w, Window* *w_children, ssize_t *n)
{
Display* d = NULL;
unsigned int e = 0;
XSetErrorHandler (handle_error);
d = XOpenDisplay (NULL);
if (d == NULL) {
return D_ERR;
} else {
/* set w to the focused window */
e = get_focus_window (d, w);
if (e) { //if error
XCloseDisplay (d);
return e;
}
/* get_top_window will set w to the top focused window (active window) */
e = get_top_window (d, *w, w, w_children, n);
if (e) { //if error
XCloseDisplay (d);
return e;
}
XCloseDisplay(d);
}
return 0; //no error
}
/* SC_get_active_gdkwindow (...) tries to match a GdkWindow to one of the passed X11
* windows (supposed to be the active X11 window and it's n children), and returns
* TRUE if such a match is found, FALSE if not
*/
gboolean
SC_get_active_gdkwindow (Window aw, Window *aw_children, ssize_t n, GdkWindow* *gdkwindow) {
ssize_t i = 0;
GdkWindow *dwindow = NULL;
GdkScreen *screen = NULL;
GList *gl_item = NULL, *gl = NULL;
gboolean active_window_found = FALSE;
screen = gdk_screen_get_default ();
if (screen != NULL) {
/* Go through all windows known to Gtk and check XID against active X11 window, aw. */
gl = gdk_screen_get_window_stack (screen);
for (gl_item = g_list_first (gl); !active_window_found && gl_item != NULL; gl_item = gl_item->next) {
dwindow = gl_item->data;
if (gdk_x11_window_get_xid (dwindow) == aw) active_window_found = TRUE;
else for (i = 0; i < n; i++) //aw didn't match this dwindow, so check all of aw_children
if (gdk_x11_window_get_xid (dwindow) == aw_children[i]) active_window_found = TRUE;
if (!active_window_found) g_object_unref (dwindow);
else *gdkwindow = dwindow;
}
g_list_free (gl);
}
return active_window_found;
}
/* SC_get_geometry_for (...) trys to get the Gdk geometry for the GdkWindow
* matching the passed X11 window with children, getting both the internal
* window geometry and it's extents (title-bar/frame). If can't get Gdk info
* will get the X11 geometry, setting both inner and extents geometry to
* the same values.
*/
void
SC_get_geometry_for (Window aw, Window *aw_children, ssize_t n, GdkRectangle *win_rect, GdkRectangle *extents, GdkWindow* *dwindow) {
unsigned int bwidth = 0, depth = 0, width, height;
int x, y;
Window root = 0;
if (SC_get_active_gdkwindow (aw, aw_children, n, dwindow)) {
gdk_window_get_frame_extents (*dwindow, extents); //{top-left corner, width & height} of title-bar/borders
gdk_window_get_origin(*dwindow, &x, &y); //top-left corner of interior window (not title bar/borders)
width = gdk_window_get_width (*dwindow); //width of interior window
height = gdk_window_get_height (*dwindow); //height of interior window
win_rect->x = x;
win_rect->y = y;
win_rect->width = (int) width;
win_rect->height = (int) height;
} else {
fprintf (stderr, "Failed to get GdkWindow. Falling back on X11 geometry of active window, saved as both extents and interior geometry.");
Display* d = XOpenDisplay (NULL);
if (d) {
XGetGeometry (d, aw, &root, &x, &y, &width, &height, &bwidth, &depth);
XCloseDisplay (d);
extents->x = x;
extents->y = y;
extents->width = (int) width;
extents->height = (int) height;
}
}
}
/* SC_get_active_windows_and_geometry (...) calls get_active_x11window (...) to get the active X11 window
* and it's children, then calls SC_get_geometry_for (...) to get geometry (hopefully Gdk) that matches
*/
gboolean
SC_get_active_windows_and_geometry (Window *aw, Window* *aw_children, ssize_t *n,
GdkRectangle *win_rect, GdkRectangle *extents, GdkWindow* *dwindow) {
switch (SC_get_active_X11window(aw, aw_children, n)) { get aw, aw_children, and n (number of children)
case 0: SC_get_geometry_for (*aw, *aw_children, *n, win_rect, extents, dwindow); return TRUE;
case SC_X11_E1: fprintf (stderr, SC_X11_ERROR1); break;
case SC_X11_E2: fprintf (stderr, SC_X11_ERROR2); break;
case SC_X11_E3: fprintf (stderr, SC_X11_ERROR3); break;
case SC_X11_E4: fprintf (stderr, SC_X11_ERROR4); break;
}
return FALSE; //failed to get active window due to X11 error
}
My Previous answer that usually got correct geometry, but not the window
I have adapted code from "get the active window on X window system" https://gist.github.com/kui/2622504 to work with my example in the question. I turned it into a library. I'm not marking this as the correct answer because this is the first library file I've ever written and I'm completely new to Gtk as well. I also don't have much experience writing C code. Finally, the correct answer should include libraries for X11, Wayland, and MIR. I would be happy to see an answer including my library with improvements + the missing two libraries.
Compile below with:
gcc `pkg-config --cflags gtk+-3.0` -o get_window-areas X11_get_active_window_geometry.c get_window-areas.c `pkg-config --libs gtk+-3.0` -lX11
X11_get_active_window_geometry.h
#include <X11/Xlib.h>
#define SC_X11_ERROR0 "Uknown error from get_actve_window_geometry.\n"
#define SC_X11_ERROR1 "Failed to connect to X server.\n"
#define SC_X11_ERROR2 "x11 error trying to get focused window\n"
#define SC_X11_ERROR3 "X11 reports no focused window\n"
#define SC_X11_ERROR4 "X11 error trying to get top window\n"
#define SC_X11_ERROR5 "X11 error trying to get the active-window geometry.\n"
#define D_ERR 1
#define FOCUS_ERR1 2
#define FOCUS_ERR2 3
#define TOP_ERR 4
#define GEOM_ERR 5
#define SC_X11_E1 D_ERR
#define SC_X11_E2 FOCUS_ERR1
#define SC_X11_E3 FOCUS_ERR2
#define SC_X11_E4 TOP_ERR
#define SC_X11_E5 GEOM_ERR
unsigned int get_active_window_geometry (int *x, int *y, unsigned int *width, unsigned int *height);
X11_get_active_window_geometry.c
#include "X11_get_active_window_geometry.h"
Bool xerror = False;
static int handle_error (Display* display, XErrorEvent* error) {
xerror = True;
return 1;
}
static int get_focus_window (Display* d, Window *w) {
int revert_to;
XGetInputFocus (d, w, &revert_to);
if (xerror) return FOCUS_ERR1; //X error trying to get focused window
else if (w == None) return FOCUS_ERR2; //no focused window
else return 0;
}
static int get_top_window (Display* d, Window start, Window *w){
Window parent = start, root = None, *children;
*w = start;
unsigned int nchildren;
Status s;
while (parent != root && !xerror) {
*w = parent;
s = XQueryTree (d, *w, &root, &parent, &children, &nchildren);
if (s)
XFree (children);
}
if (xerror) return TOP_ERR;
else return 0;
}
unsigned int get_active_window_geometry (int *x, int *y,
unsigned int *width, unsigned int *height)
{
Display* d = NULL;
Window root, w;
unsigned int bwidth = 0, depth = 0, e = 0;
XSetErrorHandler (handle_error);
d = XOpenDisplay (NULL);
if (d == NULL) {
return D_ERR;
} else {
e = get_focus_window (d,&w); //get focused window w
if (e) return e;
e = get_top_window (d, w, &w); //get top focused window w (the active window)
if (e) return e;
XGetGeometry (d, w, &root, x, y, width, height, &bwidth, &depth);
if (xerror) return GEOM_ERR;
}
return 0;
}
get_active_window.c
#include <gtk/gtk.h>
#include "X11_get_active_window_geometry.h"
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window = NULL, *text_view;
GtkTextBuffer *buffer;
unsigned int width = 0, height = 0, widtha = 0, heighta = 0, iwidtha = 0, iheighta = 0;
int x = 0, y = 0, xa = 0, ya = 0, ixa =0, iya = 0;
GdkRectangle extents= { 0, 0, 0, 0 };
char char_x[5], char_y[5], char_width[5], char_height[5];
GdkScreen *screen;
GdkWindow *dwindow;
GList *gl_item = NULL, *gl = NULL;
window = gtk_application_window_new (app);
screen = gtk_window_get_screen (GTK_WINDOW(window));
buffer = gtk_text_buffer_new (NULL);
text_view = gtk_text_view_new_with_buffer (buffer);
gtk_container_add (GTK_CONTAINER (window), text_view);
#define ADD_TEXT(STRING) gtk_text_buffer_insert_at_cursor (buffer,STRING,-1)
#define ADD_INT(CHAR_INT,INT) snprintf (CHAR_INT, 5, "%d", INT); ADD_TEXT(CHAR_INT);
#define ADD_GEOMETRY_TEXT(X,Y,WIDTH,HEIGHT) ADD_INT(char_width, WIDTH); ADD_TEXT("x"); ADD_INT(char_height, HEIGHT); ADD_TEXT(" at ("); ADD_INT(char_x, X); ADD_TEXT(","); ADD_INT(char_y, Y); ADD_TEXT(")\n");
/* get active window geometry using X11 and handle error, if any*/
switch (get_active_window_geometry(&xa, &ya, &widtha, &heighta)) {
case 0:
ADD_TEXT("GEOMETRY FOR ACTIVE WINDOW USING X11\n");
ADD_GEOMETRY_TEXT(xa, ya, widtha, heighta);
ADD_TEXT("\n");
break;
case SC_X11_E1:
ADD_TEXT(SC_X11_ERROR1);
break;
case SC_X11_E2:
ADD_TEXT(SC_X11_ERROR2);
break;
case SC_X11_E3:
ADD_TEXT(SC_X11_ERROR3);
break;
case SC_X11_E4:
ADD_TEXT(SC_X11_ERROR4);
break;
case SC_X11_E5:
ADD_TEXT(SC_X11_ERROR5);
break;
default:
ADD_TEXT(SC_X11_ERROR0);
}
/* get window geometry for all windows using Gtk and identify the active one by comparison with X11 result*/
if (screen != NULL) {
ADD_TEXT("GEOMETRY FOR ALL WINDOWS USING Gtk:\n\n");
gl = gdk_screen_get_window_stack (screen);
for (gl_item = g_list_first (gl); gl_item != NULL; gl_item = gl_item->next) {
dwindow=gl_item->data;
gdk_window_get_frame_extents (dwindow, &extents); //{top-left corner, width & height} of title-bar/borders
ADD_TEXT("Entirety of Window: ");
ADD_GEOMETRY_TEXT(extents.x, extents.y, extents.width, extents.height);
gdk_window_get_origin(dwindow, &x, &y); //top-left corner of interior window (not title bar/borders)
width = gdk_window_get_width (dwindow); //width of interior window
height = gdk_window_get_height (dwindow); //height of interior window
ADD_TEXT("Interior of Window: ");
ADD_GEOMETRY_TEXT(x, y, width, height);
ADD_TEXT("\n");
/*If extents matches active window geometry, save interior window geometry */
if (extents.x == xa && extents.y == ya && extents.width == widtha && extents.height == heighta) {
ixa = x; iya = y; iwidtha = width; iheighta = height;
}
g_object_unref (dwindow);
};
g_list_free (gl);
ADD_TEXT("MATCHING THE ACTIVE WINDOW REPORTED BY X11 WITH THE GTK WINDOW GEOMETRIES:\n");
ADD_TEXT("Entirety of Active Window: ");
ADD_GEOMETRY_TEXT(xa, ya, widtha, heighta);
ADD_TEXT("Interior of Active Window: ");
ADD_GEOMETRY_TEXT(ixa, iya, iwidtha, iheighta);
} else {
ADD_TEXT("Failed to get default screen.\n");
}
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("com.github.colinkeenan.silentcast", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
Related
Recently, I am trying to use bpf ringbuf in uprobe example of libbpf. But when running, error occurred which is "libbpf: load bpf program failed: Invalid argument". I have no idea why this happened. Could anyone help? Below is my test code.
Kernel space code: uprobe.bpf.c, define a rb struct, and use bpf_ringbuf_reserve in uprobe code block.
#include <linux/bpf.h>
#include <linux/ptrace.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "Dual BSD/GPL";
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");
SEC("uprobe/func")
int BPF_KPROBE(uprobe, int a, int b)
{
__u64* e = bpf_ringbuf_reserve(&rb, sizeof(__u64), 0);
if (!e)
return 0;
bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b);
return 0;
}
SEC("uretprobe/func")
int BPF_KRETPROBE(uretprobe, int ret)
{
bpf_printk("UPROBE EXIT: return = %d\n", ret);
return 0;
}
User space code: uprobe.c
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "uprobe.skel.h"
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
static void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}
/* Find process's base load address. We use /proc/self/maps for that,
* searching for the first executable (r-xp) memory mapping:
*
* 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat
* ^^^^^^^^^^^^ ^^^^^^^^
*
* Subtracting that region's offset (4th column) from its absolute start
* memory address (1st column) gives us the process's base load address.
*/
static long get_base_addr() {
size_t start, offset;
char buf[256];
FILE *f;
f = fopen("/proc/self/maps", "r");
if (!f)
return -errno;
while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) {
if (strcmp(buf, "r-xp") == 0) {
fclose(f);
return start - offset;
}
}
fclose(f);
return -1;
}
static int handle_event(void *ctx, void *data, size_t data_sz)
{
return 0;
}
/* It's a global function to make sure compiler doesn't inline it. */
int uprobed_function(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct uprobe_bpf *skel;
long base_addr, uprobe_offset;
int err, i;
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
bump_memlock_rlimit();
/* Load and verify BPF application */
skel = uprobe_bpf__open_and_load();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
base_addr = get_base_addr();
if (base_addr < 0) {
fprintf(stderr, "Failed to determine process's load address\n");
err = base_addr;
goto cleanup;
}
/* uprobe/uretprobe expects relative offset of the function to attach
* to. This offset is relateve to the process's base load address. So
* easy way to do this is to take an absolute address of the desired
* function and substract base load address from it. If we were to
* parse ELF to calculate this function, we'd need to add .text
* section offset and function's offset within .text ELF section.
*/
uprobe_offset = (long)&uprobed_function - base_addr;
/* Attach tracepoint handler */
skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe,
false /* not uretprobe */,
0 /* self pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* we can also attach uprobe/uretprobe to any existing or future
* processes that use the same binary executable; to do that we need
* to specify -1 as PID, as we do here
*/
skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe,
true /* uretprobe */,
-1 /* any pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uretprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* Set up ring buffer polling */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
fprintf(stderr, "Failed to create ring buffer\n");
goto cleanup;
}
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
"to see output of the BPF programs.\n");
for (i = 0; ; i++) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* trigger our BPF programs */
fprintf(stderr, ".");
uprobed_function(i, i + 1);
sleep(1);
}
cleanup:
ring_buffer__free(rb);
uprobe_bpf__destroy(skel);
return -err;
}
I am learning Wayland client programming and now I'm trying to make transparent surface.
I created a buffer and paint each pixels to shared memory. I am using WL_SHM_FORMAT_ARGB8888 format but it is not working as I expected.
As I understand, 0x00ff0000 means 255 red, 0 green, 0 blue and 0 alpha so the pixel should not shown. But it shows semi-transparent red surface to me.
Below is entire source code working on Weston compositor.
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>
#include "xdg-shell.h"
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_surface *surface;
struct zxdg_shell_v6 *xdg_shell = NULL;
struct zxdg_surface_v6 *xdg_surface;
struct zxdg_toplevel_v6 *xdg_toplevel;
struct wl_shm *shm;
struct wl_buffer *buffer;
void *shm_data;
int WIDTH = 480;
int HEIGHT = 360;
//===============
// Xdg
//===============
static void xdg_shell_ping_handler(void *data, struct zxdg_shell_v6 *xdg_shell,
uint32_t serial)
{
zxdg_shell_v6_pong(xdg_shell, serial);
printf("ping pong!\n");
}
static const struct zxdg_shell_v6_listener xdg_shell_listener = {
.ping = xdg_shell_ping_handler,
};
static void xdg_toplevel_configure_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height,
struct wl_array *states)
{
printf("Configure: %dx%d\n", width, height);
}
static void xdg_toplevel_close_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel)
{
printf("Close\n");
}
static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure_handler,
.close = xdg_toplevel_close_handler,
};
static void xdg_surface_configure_handler(void *data,
struct zxdg_surface_v6 *xdg_surface, uint32_t serial)
{
fprintf(stderr, "xdg_surface_configure_handler().\n");
zxdg_surface_v6_ack_configure(xdg_surface, serial);
}
static const struct zxdg_surface_v6_listener xdg_surface_listener = {
.configure = xdg_surface_configure_handler,
};
//=================
// File system
//=================
static int set_cloexec_or_close(int fd)
{
long flags;
if (fd == -1) {
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags == -1)
goto err;
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
goto err;
return fd;
err:
close(fd);
return -1;
}
static int create_tmpfile_cloexec(char *tmpname)
{
int fd;
#ifdef HAVE_MKOSTEMP
fd= mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0) {
unlink(tmpname);
}
#else
fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd);
unlink(tmpname);
}
#endif
return fd;
}
int os_create_anonymous_file(off_t size)
{
static const char template[] = "/blusher-shared-XXXXXX";
const char *path;
char *name;
int fd;
path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
name = malloc(strlen(path) + sizeof(template));
if (!name) {
return -1;
}
strcpy(name, path);
strcat(name, template);
fd = create_tmpfile_cloexec(name);
free(name);
if (fd < 0) {
return -1;
}
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
//==============
// Painting
//==============
static void paint_pixels()
{
uint32_t *pixel = shm_data;
fprintf(stderr, "Painting pixels.\n");
for (int n = 0; n < WIDTH * HEIGHT; ++n) {
if (n > 1100 && n < 1200) {
pixel[n] = 0xffff0000; // please ignore this
} else {
pixel[n] = 0x00ff0000;
}
}
}
static struct wl_buffer* create_buffer()
{
struct wl_shm_pool *pool;
int stride = WIDTH * 4; // 4 bytes per pixel
int size = stride * HEIGHT;
int fd;
struct wl_buffer *buff;
fd = os_create_anonymous_file(size);
if (fd < 0) {
fprintf(stderr, "Creating a buffer file for %d B filed: %m\n",
size);
exit(1);
}
shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED) {
fprintf(stderr, "mmap filed: %m\n");
close(fd);
exit(1);
}
pool = wl_shm_create_pool(shm, fd, size);
buff = wl_shm_pool_create_buffer(
pool,
0,
WIDTH,
HEIGHT,
stride,
WL_SHM_FORMAT_ARGB8888
);
wl_shm_pool_destroy(pool);
return buff;
}
static void create_window()
{
buffer = create_buffer();
wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_damage(surface, 0, 0, WIDTH, HEIGHT);
wl_surface_commit(surface);
}
static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
// struct display *d = data;
// d->formats |= (1 << format);
fprintf(stderr, "Format %d\n", format);
}
struct wl_shm_listener shm_listener = {
shm_format,
};
//==============
// Global
//==============
static void global_registry_handler(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
if (strcmp(interface, "wl_compositor") == 0) {
fprintf(stderr, "Interface is <wl_compositor>.\n");
compositor = wl_registry_bind(
registry,
id,
&wl_compositor_interface,
version
);
} else if (strcmp(interface, "zxdg_shell_v6") == 0) {
fprintf(stderr, "Interface is <zxdg_shell_v6>.\n");
xdg_shell = wl_registry_bind(registry, id, &zxdg_shell_v6_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
fprintf(stderr, "Interface is <wl_shm>.\n");
shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
wl_shm_add_listener(shm, &shm_listener, NULL);
} else {
// printf("(%d) Got a registry event for <%s> id <%d>\n",
// version, interface, id);
}
}
static void global_registry_remover(void *data, struct wl_registry *registry,
uint32_t id)
{
printf("Got a registry losing event for <%d>\n", id);
}
static const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};
//==============
// Main
//==============
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "Can't connect to display.\n");
exit(1);
}
printf("Connected to display.\n");
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, ®istry_listener, NULL);
wl_display_dispatch(display);
// wl_display_roundtrip(display);
// Check compositor.
fprintf(stderr, " - Checking compositor...\n");
if (compositor == NULL) {
fprintf(stderr, "Can't find compositor.\n");
exit(1);
}
// Check surface.
fprintf(stderr, " - Checking surface...\n");
surface = wl_compositor_create_surface(compositor);
if (surface == NULL) {
fprintf(stderr, "Can't create surface.\n");
exit(1);
}
if (xdg_shell == NULL) {
fprintf(stderr, "Haven't got a Xdg shell.\n");
exit(1);
}
zxdg_shell_v6_add_listener(xdg_shell, &xdg_shell_listener, NULL);
// Check shell surface.
xdg_surface =
zxdg_shell_v6_get_xdg_surface(xdg_shell, surface);
zxdg_surface_v6_add_listener(xdg_surface, &xdg_surface_listener, NULL);
xdg_toplevel = zxdg_surface_v6_get_toplevel(xdg_surface);
zxdg_toplevel_v6_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL);
// Signal that the surface is ready to be configured.
wl_surface_commit(surface);
// Wait for the surface to be configured.
wl_display_roundtrip(display);
create_window();
paint_pixels();
// wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_commit(surface);
while (wl_display_dispatch(display) != -1) {
;
}
wl_display_disconnect(display);
printf("Disconnected from display.\n");
return 0;
}
# Makefile
default:
wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.c
gcc -lwayland-client -lwayland-egl -lEGL -lGLESv2 main.c xdg-shell.c
But when I set pixel to 0x00000000, then it is fully transparent.
And in some tests, subsurfaces are completely transparent even there are color bits set. I want to know what is prevent the transparent toplevel surface with color bits.
If your wayland compositor supports alpha-compositing-v1 protocol you can use it do what you want.
In short; get a reference to zwp_alpha_compositing_v1 struct in you registry handler then after creating your surface you set it like this:
struct zwp_blending_v1* blending = zwp_alpha_compositing_v1_get_blending(<YOUR_ZWP_ALPHA_COMPOSITING>, <YOUR_WL_SURFACE>);
zwp_blending_v1_set_blending(blending, ZWP_BLENDING_V1_BLENDING_EQUATION_STRAIGHT);
This is an equivalent to (src_alpha, one_minus_src_alpha) blending.
#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.
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?
I have list of background processes and their pid running in background in iphone got from following code. My projects requirement is-
(its like an antivirus)
Get information on each process
a. Name
b. Size
c. Last Modified Date/Time
d. Associated Files
e. What the process is accessing from all interfaces (storage, USB, Bluetooth, Wi-Fi etc)
f. Any other information available
Thanks in advance.
#import <mach/mach_host.h>
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "sys/sysctl.h"
#include <CoreFoundation/CoreFoundation.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
- (void)viewDidLoad
{
[super viewDidLoad];
[self printProcessInfo];
}
-(int) printProcessInfo
{
int mib[5];
struct kinfo_proc *procs = NULL, *newprocs;
int i, st, nprocs;
size_t miblen, size;
/* Set up sysctl MIB */
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ALL;
mib[3] = 0;
miblen = 4;
/* Get initial sizing */
st = sysctl(mib, miblen, NULL, &size, NULL, 0);
/* Repeat until we get them all ... */
do {
/* Room to grow */
size += size / 10;
newprocs = realloc(procs, size);
if (!newprocs) {
if (procs) {
free(procs);
}
perror("Error: realloc failed.");
return (0);
}
procs = newprocs;
st = sysctl(mib, miblen, procs, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st != 0) {
perror("Error: sysctl(KERN_PROC) failed.");
return (0);
}
/* Do we match the kernel? */
assert(size % sizeof(struct kinfo_proc) == 0);
nprocs = size / sizeof(struct kinfo_proc);
if (!nprocs) {
perror("Error: printProcessInfo.");
return(0);
}
printf(" PID\tName\n");
printf("-----\t--------------\n");
self.lists = [[NSMutableString alloc] init];
for (i = nprocs-1; i >=0; i--) {
printf("%5d\t%s\n",(int)procs[i].kp_proc.p_pid, procs[i].kp_proc.p_comm);
}
NSLog(#"%#",lists);
listsText.text = lists;
free(procs);
return (0);
}
answer a)name of process you are getting in above code.
answer d)to get associated files,pass pid of process to this function (we have got pid in questions code)-
void print_argv_of_pid(int pid) {
printf("%d\n", pid);
int mib[3], argmax, nargs, c = 0;
size_t size;
char *procargs, *sp, *np, *cp;
extern int eflg;
int show_args = 1;
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
size = sizeof(argmax);
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
goto ERROR_A;
}
/* Allocate space for the arguments. */
procargs = (char *)malloc(argmax);
if (procargs == NULL) {
goto ERROR_A;
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = pid;
size = (size_t)argmax;
if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
goto ERROR_B;
}
memcpy(&nargs, procargs, sizeof(nargs));
cp = procargs + sizeof(nargs);
/* Skip the saved exec_path. */
for (; cp < &procargs[size]; cp++) {
if (*cp == '\0') {
/* End of exec_path reached. */
break;
}
}
if (cp == &procargs[size]) {
goto ERROR_B;
}
/* Skip trailing '\0' characters. */
for (; cp < &procargs[size]; cp++) {
if (*cp != '\0') {
/* Beginning of first argument reached. */
break;
}
}
if (cp == &procargs[size]) {
goto ERROR_B;
}
/* Save where the argv[0] string starts. */
sp = cp;
for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
if (*cp == '\0') {
c++;
if (np != NULL) {
/* Convert previous '\0'. */
*np = ' ';
} else {
/* *argv0len = cp - sp; */
}
/* Note location of current '\0'. */
np = cp;
if (!show_args) {
/*
* Don't convert '\0' characters to ' '.
* However, we needed to know that the
* command name was terminated, which we
* now know.
*/
break;
}
}
}
if (np == NULL || np == sp) {
/* Empty or unterminated string. */
goto ERROR_B;
}
/* Make a copy of the string. */
printf("%s\n", sp);
/* Clean up. */
free(procargs);
return;
ERROR_B:
free(procargs);
ERROR_A:
printf("error");
}
answer b),c)-size and access times-
struct stat st;
//pass filepath upto /.app/ to stat function (use 'componentsseparatedby' of nsstring apply on full path which we got in answer d's code above)
if (stat(filename, &st)) {
perror(filename);
} else {
printf("%s: mtime = %lld.%.9ld\n", filename, (long long)st.st_mtimespec.tv_sec, st.st_mtimespec.tv_nsec);
printf("File size: %lld bytes\n",
(long long) st.st_size);
printf("Last status change: %s", ctime(&st.st_ctime));
printf("Last file access: %s", ctime(&st.st_atime));
printf("Last file modification: %s", ctime(&st.st_mtime));
}
other information-
TO KILL THE PROCESS-
just pass pid of process to be killed-
int pid_exists(long pid)
{
int kill_ret;
// save some time if it's an invalid PID
if (pid < 0) {
return 0;
}
// if kill returns success of permission denied we know it's a valid PID
kill_ret = kill(pid , 0);
if ( (0 == kill_ret) || (EPERM == errno) ) {
return 1;
}
// otherwise return 0 for PID not found
return 0;
}