这里是截图的代码
static GdkPixmap* copyPixmap(GdkPixmap source, gint width, gint height) {
if (source) {
GdkPixmap pixmap = gdk_pixmap_new(source, width, height, -1);
GdkGC *gc = gdk_gc_new(source);
gdk_draw_drawable(pixmap, gc, source, 0, 0, 0, 0, -1, -1);
g_object_unref(gc);
g_object_unref(source);
return pixmap;
}
return NULL;
}
JNIEnv *m_envir;
jobject m_callback;
jmethodID m_IScreenshotCallback_storeImage;
//
typedef struct _GdkWindowPaint GdkWindowPaint;
struct _GdkWindowPaint {
GdkRegion *region;
GdkPixmap *pixmap;
gint x_offset;
gint y_offset;
};
static void exposeAllWidgetsCallback(GtkWidget *widget, gpointer data);
//
#define PREPARE_EVENT \
GdkEventExpose ev;\
ev.type = GDK_EXPOSE;\
ev.send_event = TRUE;\
ev.area.x = 0;\
ev.area.y = 0;\
ev.count = 0;
#define UPDATE_EVENT \
gdk_window_get_geometry(ev.window, NULL, NULL, &ev.area.width, &ev.area.height, NULL);\
ev.region = gdk_region_rectangle(&ev.area);
static void exposeWidget(GtkWidget widget) {
GdkWindow *window = widget->window;
if (!GTK_WIDGET_REALIZED(widget)) {
return;
}
// g_warning ("type = %s", G_OBJECT_TYPE_NAME (widget));
if (GTK_IS_SPIN_BUTTON(widget)) {
// spin button
GtkWidgetClass *clazz = (GtkWidgetClass *)GTK_SPIN_BUTTON_GET_CLASS(widget);
GtkSpinButton *spin = GTK_SPIN_BUTTON (widget);
{
PREPARE_EVENT
ev.window = spin->panel;
UPDATE_EVENT
clazz->expose_event(widget, &ev);
}
// spin button also contains GtkEntry, so give a chance to expose it too, so no 'else' statement
}
if (GTK_IS_ENTRY(widget)) {
// single text
GtkWidgetClass *clazz = (GtkWidgetClass *)GTK_ENTRY_GET_CLASS(widget);
{
PREPARE_EVENT
ev.window = window;
UPDATE_EVENT
clazz->expose_event(widget, &ev);
}
//
{
PREPARE_EVENT
ev.window = ((GtkEntry)widget)->text_area;
UPDATE_EVENT
clazz->expose_event(widget, &ev);
}
} else if (GTK_IS_TEXT_VIEW(widget)) {
// multi-line text
{
PREPARE_EVENT
ev.window = gtk_text_view_get_window((GtkTextView )widget, GTK_TEXT_WINDOW_TEXT);
UPDATE_EVENT
gtk_widget_send_expose(widget, (GdkEvent)&ev);
}
} else if (GTK_IS_TREE_VIEW(widget)) {
// tree
GtkWidgetClass clazz = (GtkWidgetClass *)GTK_TREE_VIEW_GET_CLASS(widget);
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
{
PREPARE_EVENT
ev.window = gtk_tree_view_get_bin_window(tree_view);
UPDATE_EVENT
clazz->expose_event(widget, &ev);
}
} else {
// everything else
{
PREPARE_EVENT
ev.window = window;
UPDATE_EVENT
gtk_widget_send_expose(widget, (GdkEvent)&ev);
}
}
}
static void exposeAllWidgets(GtkWidget *widget) {
if (!GTK_IS_WIDGET(widget)) {
return;
}
exposeWidget(widget);
if (!GTK_IS_CONTAINER(widget)) {
return;
}
GtkContainer *container = GTK_CONTAINER(widget);
gtk_container_forall(container, exposeAllWidgetsCallback, 0);
}
static GdkPixmap* getPixmap(GdkWindow window, int shouldCallback) {
if (!gdk_window_is_visible(window)) {
// don't deal with unmapped windows
return NULL;
}
gint width, height;
gdk_window_get_geometry(window, NULL, NULL, &width, &height, NULL);
//
GdkRectangle rect;
rect.x = 0; rect.y = 0; rect.width = width; rect.height = height;
//
GdkRegion *region = gdk_region_rectangle(&rect);
gdk_window_begin_paint_region(window, region);
//
region = gdk_region_rectangle(&rect);
gdk_window_invalidate_region(window, region, TRUE);
//
gpointer widget = NULL;
gdk_window_get_user_data(window, &widget);
if (widget != NULL) {
exposeAllWidgets((GtkWidget)widget);
}
//
gdk_window_process_updates(window, TRUE);
//
GdkWindowObject *private = (GdkWindowObject *)(window);
GdkPixmap *internalPixmap = ((GdkWindowPaint *)private->paint_stack->data)->pixmap;
if (internalPixmap == NULL) {
return NULL;
}
//
g_object_ref(internalPixmap);
GdkPixmap *pixmap = copyPixmap(internalPixmap, width, height);
gdk_window_end_paint(window);
//
if (shouldCallback) {
(*m_envir)->CallVoidMethod(m_envir, m_callback, m_IScreenshotCallback_storeImage, wrap_pointer(m_envir, widget), wrap_pointer(m_envir, pixmap));
}
//
return pixmap;
}
static GdkPixmap* traverse(GdkWindow window, int shouldCallback){
gint depth;
gdk_window_get_geometry(window, NULL, NULL, NULL, NULL, &depth);
// strange window
if (depth == 0) {
return NULL;
}
//
GdkPixmap *pixmap = getPixmap(window, shouldCallback);
if (pixmap == NULL) {
return NULL;
}
//
GdkGC *gc = gdk_gc_new(pixmap);
GList *children = gdk_window_get_children(window);
guint length = g_list_length(children);
//
guint i;
for (i = 0; i < length; i++) {
GdkWindow *win = g_list_nth_data(children, i);
GdkPixmap pix = traverse(win, shouldCallback);
if (pix == NULL) {
continue;
}
gint x, y, width, height;
gdk_window_get_geometry(win, &x, &y, &width, &height, NULL);
gdk_draw_drawable(pixmap, gc, pix, 0, 0, x, y, width, height);
if (!shouldCallback) {
g_object_unref(pix);
}
}
g_object_unref(gc);
return pixmap;
}
static void exposeAllWidgetsCallback(GtkWidget widget, gpointer data) {
exposeAllWidgets(widget);
}
static GdkPixmap makeShot(GtkWidget* shellWidget) {
GdkWindow *window = shellWidget->window;
return traverse(window, m_callback != NULL);
}
JNIEXPORT JHANDLE JNICALL OS_NATIVE(_1makeShot)(
JNIEnv envir, jobject that, JHANDLE widgetHandle, jobject callback) {
m_envir = envir;
if (callback != NULL) {
m_callback = (*envir)->NewGlobalRef(envir, callback);
jclass clazz = (*envir)->GetObjectClass(envir, m_callback);
m_IScreenshotCallback_storeImage = (*envir)->GetMethodID(envir, clazz, "storeImage", CALLBACK_SIG);
}
// make shot
GdkPixmap pixmap = makeShot((GtkWidget*)unwrap_pointer(envir, widgetHandle));
// clean up
if (callback != NULL) {
(*envir)->DeleteGlobalRef(envir, m_callback);
}
m_callback = NULL;
return (JHANDLE)wrap_pointer(envir, pixmap);
}
最终是要java利用jni调用接口_1makeShot进行截图。