Bool CreateTrayWindow() { tray_init(dpy, &tray); XVisualInfo* vi = tray_get_visual(dpy, &tray); Window dock = tray_get_dock(dpy); if (vi && vi->visual) { Window p = DefaultRootWindow (dpy); Colormap colormap = XCreateColormap(dpy, p, vi->visual, AllocNone); XSetWindowAttributes wsa; wsa.background_pixmap = 0; wsa.colormap = colormap; wsa.background_pixel = 0; wsa.border_pixel = 0; tray.window = XCreateWindow(dpy, p, -1, -1, 1, 1, 0, vi->depth, InputOutput, vi->visual, CWBackPixmap|CWBackPixel|CWBorderPixel|CWColormap, &wsa); } else { tray.window = XCreateSimpleWindow (dpy, DefaultRootWindow(dpy), \ 0, 0, 1, 1, 0, \ BlackPixel (dpy, DefaultScreen (dpy)), \ WhitePixel (dpy, DefaultScreen (dpy))); XSetWindowBackgroundPixmap(dpy, tray.window, ParentRelative); } if (tray.window == (Window) NULL) return False; // GNOME, NET WM Specification tray_send_opcode(dpy, dock, CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, 0, 0); XSizeHints size_hints; size_hints.flags = PWinGravity | PBaseSize; size_hints.base_width = 22; size_hints.base_height = 22; XSetWMNormalHints(dpy, tray.window, &size_hints); if (!ProcessTrayIcon(inactive_xpm, &tray.icon[INACTIVE_ICON], &tray.icon_mask[INACTIVE_ICON], &tray.picon[INACTIVE_ICON])) { fprintf(stderr, "failed to get inactive icon image\n"); return False; } if (!ProcessTrayIcon(active_xpm, &tray.icon[ACTIVE_ICON], &tray.icon_mask[ACTIVE_ICON], &tray.picon[ACTIVE_ICON])) { fprintf(stderr, "failed to get active icon image\n"); return False; } /* GCs for copy and drawing on mask */ XGCValues gv; gv.foreground = BlackPixel(dpy, DefaultScreen(dpy)); gv.background = BlackPixel(dpy, DefaultScreen(dpy)); tray.gc = XCreateGC(dpy, tray.window, GCBackground|GCForeground, &gv); XSetClipMask(dpy, tray.gc, tray.icon_mask[0]); XSelectInput (dpy, tray.window, ExposureMask | KeyPressMask | \ ButtonPressMask | ButtonReleaseMask | StructureNotifyMask \ | EnterWindowMask | PointerMotionMask | LeaveWindowMask | VisibilityChangeMask); return True; }
/* 建立 Tray */ void gui_tray_init(void) { winlist_t *win = NULL; if (gui->tray_win) { //return; win = gui->tray_win; } else { #if 0 //manager_window = XGetSelectionOwner(gui->display, selection_atom); manager_window = ManagerWindow(gui->display, gui->screen); if (manager_window != None) { Atom visual_atom = XInternAtom(gui->display, "_NET_SYSTEM_TRAY_VISUAL", False); Atom type; int format; union { unsigned long *prop; unsigned char *prop_ch; } prop = { NULL }; unsigned long nitems; unsigned long bytes_after; int result; type = None; result = XGetWindowProperty (gui->display, manager_window, visual_atom, 0, sizeof(long), False, XA_VISUALID, &type, &format, &nitems, &bytes_after, &(prop.prop_ch)); Visual *default_xvisual; if (result == 0 && type == XA_VISUALID && nitems == 1 && format == 32) { VisualID visual_id = prop.prop[0]; visual = x11_screen_lookup_visual (visual_id); } } #endif #if 1 /* Atom actual_type; int actual_format; unsigned long nitems, bytes_remaining; unsigned char *data = 0; int result = XGetWindowProperty(gui->display, manager_window, visual_atom, 0, 1, False, XA_VISUALID, &actual_type, &actual_format, &nitems, &bytes_remaining, &data); VisualID vid = 0; if (result == Success && data && actual_type == XA_VISUALID && actual_format == 32 && nitems == 1 && bytes_remaining == 0) vid = *(VisualID*)data; if (data) XFree(data); if (vid == 0) return; */ uint mask = VisualScreenMask; XVisualInfo *vi, rvi; int count=0, i; //rvi.visualid = vid; rvi.screen = gui->screen; vi = XGetVisualInfo(gui->display, mask, &rvi, &count); for(i=0; i<count; i++) { if (vi[i].depth == 32 && (vi[i].red_mask == 0xff0000 && vi[i].green_mask == 0x00ff00 && vi[i].blue_mask == 0x0000ff)) { //printf("rgba_visual=%d\n", vi[i].visual->visualid); visual = &vi[i]; break; } } /*if (vi) { //visual = vi[0]; visual = &vi[0]; //return; //XFree((char*)vi); }*/ #endif if(visual && visual->visual) win = gui_new_win_tray((XVisualInfo*)visual); else win = gui_new_win(); } /* Tray 不需要邊框 */ XSetWindowBorderWidth(gui->display, win->window, 0); XSetWindowAttributes win_attr; win_attr.override_redirect = True; XChangeWindowAttributes(gui->display, win->window, CWOverrideRedirect, &win_attr); Pixmap tray, mask; XpmAttributes attributes; attributes.valuemask = 0; if (!ProcessTrayIcon(gui->display, win->window, oxim_tray, &icon, &icon_mask, &picon)) { //fprintf(stderr, "failed to get inactive icon image\n"); return; } #if 1 if(visual && visual->visual) { /* GCs for copy and drawing on mask */ XGCValues gv; gv.foreground = BlackPixel(gui->display, gui->screen); gv.background = BlackPixel(gui->display, gui->screen); //GC gc = XCreateGC(gui->display, win->window, GCBackground|GCForeground, &gv); GC gc = XCreateGC(gui->display, aw, GCBackground|GCForeground, &gv); XSetClipMask(gui->display, gc, icon_mask); } #endif XpmCreatePixmapFromData(gui->display, win->window, oxim_tray, &tray, &mask, &attributes); tray_w = attributes.width; tray_h = attributes.height; win->width = tray_w; win->height = tray_h; XpmFreeAttributes(&attributes); XFreePixmap(gui->display, tray); if (mask) { XFreePixmap(gui->display, mask); } win->pos_x = 0; win->pos_y = 0; win->win_draw_func = NULL; win->win_event_func = gui_focus_event; XSizeHints *size_hints = XAllocSizeHints(); size_hints->flags = PMinSize | PMaxSize; size_hints->min_width = win->width; size_hints->min_height = win->height; size_hints->max_width = win->width; size_hints->max_height = win->height; XSetWMNormalHints(gui->display, win->window, size_hints); XFree(size_hints); Atom xembed_info = XInternAtom(gui->display, "_XEMBED_INFO", False); unsigned int mapping[2]; mapping[0] = 0; /* ver 0 */ mapping[1] = 1; /* request mapping */ XChangeProperty(gui->display, win->window, xembed_info, xembed_info, 32, PropModeReplace, (unsigned char *)mapping, 2); gui->tray_win = win; }