📄 tray.c
字号:
/* * Copyright (C) 2004 Sun Microsystems, Inc. All rights reserved. Use is * subject to license terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License as * published by the Free Software Foundation; either version 2 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ #include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xos.h>#include <X11/Xatom.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include "GnomeSystemTrayService.h"#include "GnomeTrayAppletService.h"#include <X11/Intrinsic.h>#include <X11/StringDefs.h>#include <X11/Vendor.h>#include <X11/Shell.h>#include <X11/IntrinsicP.h>#include <sys/types.h>#include <sys/param.h>#include <sys/stat.h>#include <fcntl.h>#include <dlfcn.h>#include <poll.h>#ifndef POLLRDNORM#define POLLRDNORM POLLIN#endif#ifdef DEBUG#define dprintf printf#else#define dprintf #endifDisplay * awt_display;/* AWT interface functions. */static void *res = NULL;static int initialized_lock = 0;/* AWT interface functions. */static void (* LockIt)(JNIEnv *) = NULL;static void (* UnLockIt)(JNIEnv *) = NULL;static void (* NoFlushUnlockIt)(JNIEnv *) = NULL;/* * awtHandle is initialized in function: * Java_org_jdesktop_jdic_tray_internal_impl_GnomeSystemTrayService_initNative * (JNIEnv *env, jobject object, jstring java_home_string) * This function should be called from Java side after loadLibrary("tray") immediately. */static void *awtHandle = NULL;#ifdef __linux__#define LIBARCH "i386"#else#ifdef __i386#define LIBARCH "i386"#endif#ifdef __sparc#define LIBARCH "sparc"#endif#ifdef __sparcv9#define LIBARCH "sparcv9"#endif#endif#define REFLECT_VOID_FUNCTION(name, arglist, paramlist) \typedef name##_type arglist; \ static void name arglist \{ \ static name##_type *name##_ptr = NULL; \ if (name##_ptr == NULL) { \ name##_ptr = (name##_type *) dlsym(awtHandle, #name); \ if (name##_ptr == NULL) { \ fprintf(stderr,"reflect failed to find " #name ".\n"); \ exit(123); \ return; \ } \ } \ (*name##_ptr)paramlist; \}#define REFLECT_FUNCTION(return_type, name, arglist, paramlist) \typedef return_type name##_type arglist; \ static return_type name arglist \{ \ static name##_type *name##_ptr = NULL; \ if (name##_ptr == NULL) { \ name##_ptr = (name##_type *) dlsym(awtHandle, #name); \ if (name##_ptr == NULL) { \ fprintf(stderr,"reflect failed to find " #name ".\n"); \ exit(123); \ return; \ } \ } \ return (*name##_ptr)paramlist; \}REFLECT_VOID_FUNCTION(getAwtLockFunctions, (void (**AwtLock)(JNIEnv *), void (**AwtUnlock)(JNIEnv *), void (**AwtNoFlushUnlock)(JNIEnv *), void *reserved), (AwtLock, AwtUnlock, AwtNoFlushUnlock, reserved)) REFLECT_VOID_FUNCTION(getAwtData, (int *awt_depth, Colormap *awt_cmap, Visual **awt_visual, int *awt_num_colors, void *pReserved), (awt_depth, awt_cmap, awt_visual, awt_num_colors, pReserved))REFLECT_FUNCTION(Display *, getAwtDisplay, (void), ()) /* Global variables */ Display * display; int screen_num; static char * appname; Atom net_system_tray=0; Atom _NET_WM_ICON=0; Window tray_owner=0; Atom embed_type; Atom embed_info;#define SYSTEM_TRAY_REQUEST_DOCK 0#define SYSTEM_TRAY_BEGIN_MESSAGE 1#define SYSTEM_TRAY_CANCEL_MESSAGE 2static 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_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 failure */ }}void ThreadYield(JNIEnv *env) { static jclass threadClass = NULL; static jmethodID yieldMethodID = NULL; /* Initialize our java identifiers once. Checking before locking * is a huge performance win. */ if (threadClass == NULL) { /* should enter a monitor here... */ Boolean err = FALSE; if (threadClass == NULL) { jclass tc = (*env)->FindClass(env, "java/lang/Thread"); threadClass = (*env)->NewGlobalRef(env, tc); (*env)->DeleteLocalRef(env, tc); if (threadClass != NULL) { yieldMethodID = (*env)->GetStaticMethodID(env, threadClass, "yield", "()V" ); } } if (yieldMethodID == NULL) { threadClass = NULL; err = TRUE; } if (err) { return; } } /* threadClass == NULL*/ (*env)->CallStaticVoidMethod(env, threadClass, yieldMethodID);} voidconfigureNotify(JNIEnv *env,Window window,int x, int y, int w, int h) { static jclass gtaClass = NULL; static jmethodID confMethodID = NULL; if (gtaClass == NULL) { Boolean err = FALSE; if (gtaClass == NULL) { jclass tc = (*env)->FindClass(env, "org/jdesktop/jdic/tray/internal/impl/GnomeTrayAppletService"); gtaClass = (*env)->NewGlobalRef(env, tc); (*env)->DeleteLocalRef(env, tc); if (gtaClass != NULL) { confMethodID = (*env)->GetStaticMethodID(env, gtaClass, "configureNotify", "(JIIII)V" ); } else { dprintf("gtaClass == null"); } } if (confMethodID == NULL) { dprintf("confMethodID == null"); gtaClass = NULL; err = TRUE; } if (err) { return; } } /* gtaClass == NULL*/ (*env)->CallStaticVoidMethod(env, gtaClass, confMethodID,(jlong)window,x,y,w,h);} /* * Class: GnomeSystemTrayService * Method: eventLoop * Signature: ()V */JNIEXPORT void JNICALL Java_org_jdesktop_jdic_tray_internal_impl_GnomeSystemTrayService_eventLoop (JNIEnv *env, jclass klass) { XEvent report; /* Enter event loop */ static struct pollfd pollFds[2]; int timeout = 100; int result; int fdX = ConnectionNumber(display) ; pollFds[0].fd = fdX; pollFds[0].events = POLLRDNORM; pollFds[0].revents = 0; while ( 1 ) { (*LockIt)(env); while ((XEventsQueued(display, QueuedAfterReading) == 0) && (XEventsQueued(display, QueuedAfterFlush) == 0)) { XFlush(display); (*UnLockIt)(env); ThreadYield(env); result = poll( pollFds, 1, (int32_t) timeout ); (*LockIt)(env); } XNextEvent(display, &report); (*UnLockIt)(env); dprintf("type = %x\n",report.type); switch ( report.type ) { case Expose: dprintf("Expose\n"); break; case PropertyNotify: dprintf("PropertyNotify\n"); break; case ClientMessage: dprintf("ClientMessage\n"); break; case ReparentNotify: dprintf("ReparentNotify\n"); dprintf("window = %x parent = %x\n", report.xreparent.window,report.xreparent.parent); break; case ConfigureNotify: dprintf("ConfigureNotify x = %s y=%d w=%d h=%d\n",report.xconfigure.x,report.xconfigure.y, report.xconfigure.width, report.xconfigure.height); configureNotify(env,report.xconfigure.window,report.xconfigure.x,report.xconfigure.y, report.xconfigure.width, report.xconfigure.height); break; case ButtonPress: dprintf("ButtonPress\n"); break; } }}/* * Class: GnomeSystemTrayService * Method: locateSystemTray * Signature: ()Z */JNIEXPORT jboolean JNICALL Java_org_jdesktop_jdic_tray_internal_impl_GnomeSystemTrayService_locateSystemTray (JNIEnv *env, jclass klass) { if (initialized_lock == 0) { getAwtLockFunctions(&LockIt, &UnLockIt, &NoFlushUnlockIt, NULL); initialized_lock = 1 ; } (*LockIt)(env); /* Connect to X server */ if ( (display = XOpenDisplay(NULL)) == NULL ) { fprintf(stderr, "Couldn't connect to X server !\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -