|
1 | 1 | /*******************************************************************************
|
2 |
| - * Copyright (c) 2011 Google, Inc. |
| 2 | + * Copyright (c) 2011, 2023 Google, Inc. |
3 | 3 | * All rights reserved. This program and the accompanying materials
|
4 | 4 | * are made available under the terms of the Eclipse Public License v1.0
|
5 | 5 | * which accompanies this distribution, and is available at
|
@@ -34,90 +34,6 @@ static void getWidgetBounds(GtkWidget* widget, JNIEnv *envir, jintArray jsizes)
|
34 | 34 | free(sizes);
|
35 | 35 | }
|
36 | 36 |
|
37 |
| -//////////////////////////////////////////////////////////////////////////// |
38 |
| -// |
39 |
| -// Screenshot |
40 |
| -// |
41 |
| -//////////////////////////////////////////////////////////////////////////// |
42 |
| -JNIEnv *m_envir; |
43 |
| -jobject m_callback; |
44 |
| -jmethodID m_IScreenshotCallback_storeImage; |
45 |
| - |
46 |
| -/* for debug purposes uncomment this and add void log(String msg) method to callback object class |
47 |
| -jmethodID m_IScreenshotCallback_log; |
48 |
| -static void logJava(char *str, void *p) { |
49 |
| - char buf[1024]; |
50 |
| - memset(buf, 0, sizeof(buf)); |
51 |
| - sprintf(buf, "%s = %p", str, p); |
52 |
| - jobject jstr = (*m_envir)->NewStringUTF(m_envir, buf); |
53 |
| - (*m_envir)->CallVoidMethod(m_envir, m_callback, m_IScreenshotCallback_log, jstr); |
54 |
| - (*m_envir)->DeleteLocalRef(m_envir, jstr); |
55 |
| -} */ |
56 |
| - |
57 |
| -static cairo_surface_t* copyImageSurface(GdkWindow *sourceWindow, gint width, gint height) { |
58 |
| - cairo_surface_t *targetSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); |
59 |
| - cairo_t *cr = cairo_create(targetSurface); |
60 |
| - gdk_cairo_set_source_window(cr, sourceWindow, 0, 0); |
61 |
| - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); |
62 |
| - cairo_paint(cr); |
63 |
| - cairo_destroy(cr); |
64 |
| - cairo_surface_flush(targetSurface); |
65 |
| - return targetSurface; |
66 |
| -} |
67 |
| - |
68 |
| -static cairo_surface_t* getImageSurface(GdkWindow *window) { |
69 |
| - if (!gdk_window_is_visible(window)) { |
70 |
| - // don't deal with unmapped windows |
71 |
| - return NULL; |
72 |
| - } |
73 |
| - gint width, height; |
74 |
| - gdk_window_get_geometry(window, NULL, NULL, &width, &height); |
75 |
| - // force paint. Note, not all widgets do this completely, known so far is GtkTreeViewer. |
76 |
| - GdkRectangle rect; |
77 |
| - rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; |
78 |
| - gdk_window_begin_paint_rect(window, &rect); |
79 |
| - gdk_window_invalidate_rect(window, &rect, TRUE); |
80 |
| - // access a widget registered with the window |
81 |
| - gpointer widget = NULL; |
82 |
| - gdk_window_get_user_data(window, &widget); |
83 |
| - // end force paint and copy image |
84 |
| - gdk_window_process_updates(window, TRUE); |
85 |
| - gdk_window_end_paint(window); |
86 |
| - cairo_surface_t *surface = copyImageSurface(window, width, height); |
87 |
| - // get Java code notified |
88 |
| - if (m_callback) { |
89 |
| - (*m_envir)->CallVoidMethod(m_envir, m_callback, m_IScreenshotCallback_storeImage, wrap_pointer(m_envir, widget), wrap_pointer(m_envir, surface)); |
90 |
| - } |
91 |
| - // done |
92 |
| - return surface; |
93 |
| -} |
94 |
| - |
95 |
| -static cairo_surface_t* traverse(GdkWindow *window) { |
96 |
| - cairo_surface_t *surface = getImageSurface(window); |
97 |
| - if (surface == NULL) { |
98 |
| - return NULL; |
99 |
| - } |
100 |
| - GList *children = gdk_window_get_children(window); |
101 |
| - guint length = g_list_length(children); |
102 |
| - guint i; |
103 |
| - for (i = 0; i < length; i++) { |
104 |
| - GdkWindow *win = g_list_nth_data(children, i); |
105 |
| - cairo_surface_t* sur = traverse(win); |
106 |
| - if (sur == NULL) { |
107 |
| - continue; |
108 |
| - } |
109 |
| - if (!m_callback) { |
110 |
| - cairo_surface_destroy(sur); |
111 |
| - } |
112 |
| - } |
113 |
| - return surface; |
114 |
| -} |
115 |
| - |
116 |
| -static cairo_surface_t *makeShot(GtkWidget* shellWidget) { |
117 |
| - GdkWindow *window = gtk_widget_get_window(shellWidget); |
118 |
| - return traverse(window); |
119 |
| -} |
120 |
| - |
121 | 37 | ////////////////////////////////////////////////////////////////////////////
|
122 | 38 | //
|
123 | 39 | // Menu
|
@@ -147,8 +63,84 @@ typedef struct _GtkMenuPrivateCopy
|
147 | 63 | GtkWidget *toplevel;
|
148 | 64 | } GtkMenuPrivateCopy;
|
149 | 65 |
|
150 |
| -static cairo_surface_t* fetchMenuVisualData(GtkMenu *menu, JNIEnv *envir, jintArray jsizes) { |
151 |
| - m_callback = NULL; |
| 66 | +//////////////////////////////////////////////////////////////////////////// |
| 67 | +// |
| 68 | +// JNI |
| 69 | +// |
| 70 | +//////////////////////////////////////////////////////////////////////////// |
| 71 | +JNIEXPORT jboolean JNICALL |
| 72 | + OS_NATIVE(_1toggle_1above) |
| 73 | + (JNIEnv *envir, jobject that, JHANDLE widgetHandle, jboolean forceToggle) { |
| 74 | + // NOT IMPLEMENTED |
| 75 | + return JNI_TRUE; |
| 76 | +} |
| 77 | +JNIEXPORT jboolean JNICALL |
| 78 | + OS_NATIVE(_1begin_1shot) |
| 79 | + (JNIEnv *envir, jobject that, JHANDLE widgetHandle) { |
| 80 | + // just show it |
| 81 | + gtk_widget_show_now((GtkWidget*)unwrap_pointer(envir, widgetHandle)); |
| 82 | + return JNI_TRUE; |
| 83 | +} |
| 84 | +JNIEXPORT jboolean JNICALL |
| 85 | + OS_NATIVE(_1end_1shot) |
| 86 | + (JNIEnv *envir, jobject that, JHANDLE widgetHandle) { |
| 87 | + // hide then |
| 88 | + gtk_widget_hide((GtkWidget*)unwrap_pointer(envir, widgetHandle)); |
| 89 | + return JNI_TRUE; |
| 90 | +} |
| 91 | + |
| 92 | +JNIEXPORT JHANDLE JNICALL OS_NATIVE(_1getWidgetWindow) |
| 93 | + (JNIEnv *envir, jobject that, JHANDLE shellHandle) { |
| 94 | + GdkWindow *window = gtk_widget_get_window((GtkWidget*)unwrap_pointer(envir, shellHandle)); |
| 95 | + return wrap_pointer(envir, window); |
| 96 | +} |
| 97 | +JNIEXPORT JHANDLE JNICALL OS_NATIVE(_1getWindowUserData) |
| 98 | + (JNIEnv *envir, jobject that, JHANDLE windowHandle) { |
| 99 | + gpointer widget = NULL; |
| 100 | + gdk_window_get_user_data((GdkWindow*)unwrap_pointer(envir, windowHandle), &widget); |
| 101 | + return wrap_pointer(envir, widget); |
| 102 | +} |
| 103 | +JNIEXPORT jobjectArray JNICALL OS_NATIVE(_1getWindowChildren) |
| 104 | + (JNIEnv *envir, jobject that, JHANDLE windowHandle) { |
| 105 | + GList *children = gdk_window_get_children((GdkWindow*)unwrap_pointer(envir, windowHandle)); |
| 106 | + guint length = g_list_length(children); |
| 107 | + guint i; |
| 108 | + |
| 109 | + jobjectArray pointerArray = create_pointer_array(envir, length); |
| 110 | + |
| 111 | + for (i = 0; i < length; i++) { |
| 112 | + GdkWindow *child = g_list_nth_data(children, i); |
| 113 | + (*envir) -> SetObjectArrayElement(envir, pointerArray, i, wrap_pointer(envir, child)); |
| 114 | + } |
| 115 | + |
| 116 | + g_list_free(children); |
| 117 | + |
| 118 | + return pointerArray; |
| 119 | +} |
| 120 | +JNIEXPORT jboolean JNICALL OS_NATIVE(_1requestWindowRepaint) |
| 121 | + (JNIEnv *envir, jobject that, JHANDLE windowHandle) { |
| 122 | + GdkWindow* window = (GdkWindow*)unwrap_pointer(envir, windowHandle); |
| 123 | + if (!gdk_window_is_visible(window)) { |
| 124 | + // don't deal with unmapped windows |
| 125 | + return JNI_FALSE; |
| 126 | + } |
| 127 | + gint width, height; |
| 128 | + gdk_window_get_geometry(window, NULL, NULL, &width, &height); |
| 129 | + // force paint. Note, not all widgets do this completely, known so far is GtkTreeViewer. |
| 130 | + GdkRectangle rect; |
| 131 | + rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; |
| 132 | + gdk_window_begin_paint_rect(window, &rect); |
| 133 | + gdk_window_invalidate_rect(window, &rect, TRUE); |
| 134 | + // end force paint |
| 135 | + gdk_window_end_paint(window); |
| 136 | + // done |
| 137 | + return JNI_TRUE; |
| 138 | +} |
| 139 | +// menu |
| 140 | +JNIEXPORT jboolean JNICALL |
| 141 | + OS_NATIVE(_1begin_1menu_1shot) |
| 142 | + (JNIEnv *envir, jobject that, JHANDLE menuHandle, jintArray jsizes) { |
| 143 | + GtkMenu *menu = (GtkMenu*)unwrap_pointer(envir, menuHandle); |
152 | 144 | GtkWidget *menuWidget = GTK_WIDGET (menu);
|
153 | 145 | GtkMenuPrivateCopy *priv = (GtkMenuPrivateCopy*)menu->priv;
|
154 | 146 | // try to move menu window outside of the screen
|
@@ -180,79 +172,24 @@ static cairo_surface_t* fetchMenuVisualData(GtkMenu *menu, JNIEnv *envir, jintAr
|
180 | 172 | // copy dimensions into java array
|
181 | 173 | (*envir)->SetIntArrayRegion(envir, jsizes, 0, sizesSize, sizes);
|
182 | 174 | free(sizes);
|
183 |
| - // make screenshot |
184 |
| - cairo_surface_t *surface = NULL; |
185 |
| - GdkWindow *window = gtk_widget_get_window(menuWidget); |
186 |
| - surface = traverse(window); |
187 |
| - // hide menu |
188 |
| - gtk_widget_hide(priv->toplevel); |
189 |
| - gtk_widget_hide(GTK_WIDGET (menu)); |
190 |
| - // all done |
191 |
| - return surface; |
192 |
| -} |
193 |
| - |
194 |
| -//////////////////////////////////////////////////////////////////////////// |
195 |
| -// |
196 |
| -// JNI |
197 |
| -// |
198 |
| -//////////////////////////////////////////////////////////////////////////// |
199 |
| -JNIEXPORT jboolean JNICALL |
200 |
| - OS_NATIVE(_1toggle_1above) |
201 |
| - (JNIEnv *envir, jobject that, JHANDLE widgetHandle, jboolean forceToggle) { |
202 |
| - // NOT IMPLEMENTED |
203 | 175 | return JNI_TRUE;
|
204 | 176 | }
|
205 | 177 | JNIEXPORT jboolean JNICALL
|
206 |
| - OS_NATIVE(_1begin_1shot) |
207 |
| - (JNIEnv *envir, jobject that, JHANDLE widgetHandle) { |
208 |
| - // just show it |
209 |
| - gtk_widget_show_now((GtkWidget*)unwrap_pointer(envir, widgetHandle)); |
210 |
| - return JNI_TRUE; |
211 |
| -} |
212 |
| -JNIEXPORT jboolean JNICALL |
213 |
| - OS_NATIVE(_1end_1shot) |
214 |
| - (JNIEnv *envir, jobject that, JHANDLE widgetHandle) { |
| 178 | + OS_NATIVE(_1end_1menu_1shot) |
| 179 | + (JNIEnv *envir, jobject that, JHANDLE menuHandle) { |
215 | 180 | // hide then
|
216 |
| - gtk_widget_hide((GtkWidget*)unwrap_pointer(envir, widgetHandle)); |
| 181 | + GtkMenu *menu = (GtkMenu*)unwrap_pointer(envir, menuHandle); |
| 182 | + GtkWidget *menuWidget = GTK_WIDGET (menu); |
| 183 | + GtkMenuPrivateCopy *priv = (GtkMenuPrivateCopy*)menu->priv; |
| 184 | + gtk_widget_hide(priv->toplevel); |
| 185 | + gtk_widget_hide(menuWidget); |
217 | 186 | return JNI_TRUE;
|
218 | 187 | }
|
219 |
| -// shot |
220 |
| -JNIEXPORT JHANDLE JNICALL OS_NATIVE(_1makeShot)( |
221 |
| - JNIEnv *envir, jobject that, JHANDLE widgetHandle, jobject callback) { |
222 |
| - m_envir = envir; |
223 |
| - if (callback != NULL) { |
224 |
| - m_callback = (*envir)->NewGlobalRef(envir, callback); |
225 |
| - jclass clazz = (*envir)->GetObjectClass(envir, m_callback); |
226 |
| - m_IScreenshotCallback_storeImage = (*envir)->GetMethodID(envir, clazz, "storeImage", CALLBACK_SIG); |
227 |
| - /* uncomment this for debug purposes |
228 |
| - m_IScreenshotCallback_log = (*envir)->GetMethodID(envir, clazz, "log", "(Ljava/lang/String;)V"); */ |
229 |
| - } |
230 |
| - // make shot |
231 |
| - cairo_surface_t* surface = makeShot((GtkWidget*)unwrap_pointer(envir, widgetHandle)); |
232 |
| - // clean up |
233 |
| - if (callback != NULL) { |
234 |
| - (*envir)->DeleteGlobalRef(envir, m_callback); |
235 |
| - } |
236 |
| - m_callback = NULL; |
237 |
| - return (JHANDLE)wrap_pointer(envir, surface); |
238 |
| -} |
239 |
| -// menu |
240 |
| -JNIEXPORT JHANDLE JNICALL OS_NATIVE(_1fetchMenuVisualData)( |
241 |
| - JNIEnv *envir, jobject that, JHANDLE jmenuHandle, jintArray jsizes) { |
242 |
| - GtkWidget* menu = (GtkWidget*)unwrap_pointer(envir, jmenuHandle); |
243 |
| - cairo_surface_t* surface = fetchMenuVisualData(GTK_MENU(menu), envir, jsizes); |
244 |
| - return wrap_pointer(envir, surface); |
245 |
| -} |
246 | 188 | // tab item bounds
|
247 | 189 | JNIEXPORT void JNICALL OS_NATIVE(_1getWidgetBounds)(
|
248 | 190 | JNIEnv *envir, jobject that, JHANDLE jhandle, jintArray jsizes) {
|
249 | 191 | getWidgetBounds((GtkWidget*)unwrap_pointer(envir, jhandle), envir, jsizes);
|
250 | 192 | }
|
251 |
| -// unref |
252 |
| -JNIEXPORT void JNICALL OS_NATIVE(_1disposeImageHandle)( |
253 |
| - JNIEnv *envir, jobject that, JHANDLE jhandle) { |
254 |
| - cairo_surface_destroy((cairo_surface_t*)unwrap_pointer(envir, jhandle)); |
255 |
| -} |
256 | 193 | // other
|
257 | 194 | static int isValidVersion() {
|
258 | 195 | return gtk_major_version == 3 && gtk_minor_version >= 0;
|
|
0 commit comments