/* Perform several periodic tasks */ void perform_periodic_tasks(int mask) { struct TrayIcon *ti; /* 1. Remove all invalid icons */ while ((ti = icon_list_forall(&find_invalid_icons)) != NULL) { LOG_TRACE(("icon 0x%x is invalid; removing\n", ti->wid)); remove_icon(ti->wid); } /* 2. Print tray status if asked to */ if (tray_status_requested) dump_tray_status(); /* 3. KLUDGE to fix window size on (buggy?) WMs */ if (settings.kludge_flags & KLUDGE_FIX_WND_SIZE) { /* KLUDGE TODO: resolve */ XWindowAttributes xwa; XGetWindowAttributes(tray_data.dpy, tray_data.tray, &xwa); if (!tray_data.is_reparented && (xwa.width != tray_data.xsh.width || xwa.height != tray_data.xsh.height)) { LOG_TRACE(("KLUDGE: fixing tray window size (current: %dx%d, required: %dx%d)\n", xwa.width, xwa.height, tray_data.xsh.width, tray_data.xsh.height)); tray_update_window_props(); } } /* 4. run scrollbars periodic tasks */ if (mask & PT_MASK_SB) scrollbars_periodic_tasks(); }
void systray_destroy_event(TrayWindow *traywin) { if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); remove_icon(traywin); }
static inline DISPLAY_INFO* reset_display_info(DISPLAY_INFO* const di, NOTIFICATION_INFO* const ni) { di->timeout = 500; di->pos = 0; di->offset = 0; di->hover = FALSE; free_notification_info(di->ni); di->ni = ni; gtk_widget_hide_all(di->widget.popup); gtk_window_set_opacity(GTK_WINDOW(di->widget.popup), 0.8); remove_icon(di); return di; }
void destroy_notify(XDestroyWindowEvent ev) { if (!tray_data.is_active && ev.window == tray_data.old_selection_owner) { /* Old tray selection owner was destroyed. Take over selection ownership. */ tray_acquire_selection(); } else if (ev.window != tray_data.tray) { /* Try to remove icon from the tray */ remove_icon(ev.window); #ifndef NO_NATIVE_KDE } else if (kde_tray_is_old_icon(ev.window)) { /* Since X Server may reuse window ids, remove ev.window * from the list of old KDE icons */ kde_tray_old_icons_remove(ev.window); #endif } }
void reparent_notify(XReparentEvent ev) { struct TrayIcon *ti; ti = icon_list_find(ev.window); if (ti == NULL) return; /* Reparenting out of the tray is one of non-destructive * ways to end XEMBED protocol (see spec) */ if (ti->is_embedded && ti->mid_parent != ev.parent) { LOG_TRACE(("will now unembed 0x%x\n", ti->wid)); #ifdef DEBUG print_icon_data(ti); x11_dump_win_info(tray_data.dpy, ev.parent); #endif remove_icon(ev.window); } }
void stop_net() { if (systray_profile) fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__); if (systray.list_icons) { // remove_icon change systray.list_icons while (systray.list_icons) remove_icon((TrayWindow *)systray.list_icons->data); g_slist_free(systray.list_icons); systray.list_icons = NULL; } if (net_sel_win != None) { XDestroyWindow(server.display, net_sel_win); net_sel_win = None; } }
gboolean embed_icon(TrayWindow *traywin) { if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); if (traywin->embedded) return TRUE; Panel *panel = systray.area.panel; XSync(server.display, False); error = FALSE; XErrorHandler old = XSetErrorHandler(window_error_handler); if (0) { Atom acttype; int actfmt; unsigned long nbitem, bytes; unsigned long *data = 0; int ret; if (systray_profile) fprintf(stderr, "XGetWindowProperty(server.display, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, " "server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, &data)\n"); ret = XGetWindowProperty(server.display, traywin->win, server.atom._XEMBED_INFO, 0, 2, False, server.atom._XEMBED_INFO, &acttype, &actfmt, &nbitem, &bytes, (unsigned char **)&data); if (ret == Success) { if (data) { if (nbitem >= 2) { int hide = ((data[1] & XEMBED_MAPPED) == 0); if (hide) { // In theory we have to check the embedding with this and remove icons that refuse embedding. // In practice we have no idea when the other application processes the event and accepts the // embed so we cannot check now without a race. // Race can be triggered with PyGtk(2) apps. // We could defer this for later (if we set PropertyChangeMask in XSelectInput we get notified) // but for some reason it breaks transparency for Qt icons. So we don't. // fprintf(stderr, RED "tint2: window refused embedding" RESET "\n"); // remove_icon(traywin); // XFree(data); // return FALSE; } } XFree(data); } } else { fprintf(stderr, RED "tint2 : xembed error" RESET "\n"); remove_icon(traywin); return FALSE; } } // Redirect rendering when using compositing if (systray_composited) { if (systray_profile) fprintf(stderr, "XDamageCreate(server.display, traywin->parent, XDamageReportRawRectangles)\n"); traywin->damage = XDamageCreate(server.display, traywin->parent, XDamageReportRawRectangles); if (systray_profile) fprintf(stderr, "XCompositeRedirectWindow(server.display, traywin->parent, CompositeRedirectManual)\n"); XCompositeRedirectWindow(server.display, traywin->parent, CompositeRedirectManual); } XRaiseWindow(server.display, traywin->win); // Make the icon visible if (systray_profile) fprintf(stderr, "XMapWindow(server.display, traywin->win)\n"); XMapWindow(server.display, traywin->win); if (!panel->is_hidden) { if (systray_profile) fprintf(stderr, "XMapRaised(server.display, traywin->parent)\n"); XMapRaised(server.display, traywin->parent); } if (systray_profile) fprintf(stderr, "XSync(server.display, False)\n"); XSync(server.display, False); XSetErrorHandler(old); if (error != FALSE) { fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d" RESET "\n", __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid); remove_icon(traywin); return FALSE; } traywin->embedded = TRUE; if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); return TRUE; }
gboolean reparent_icon(TrayWindow *traywin) { if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); if (traywin->reparented) return TRUE; // Watch for the icon trying to resize itself / closing again XSync(server.display, False); error = FALSE; XErrorHandler old = XSetErrorHandler(window_error_handler); if (systray_profile) fprintf(stderr, "XSelectInput(server.display, traywin->win, ...)\n"); XSelectInput(server.display, traywin->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); XWithdrawWindow(server.display, traywin->win, server.screen); XReparentWindow(server.display, traywin->win, traywin->parent, 0, 0); if (systray_profile) fprintf(stderr, "XMoveResizeWindow(server.display, traywin->win = %ld, 0, 0, traywin->width = %d, traywin->height = " "%d)\n", traywin->win, traywin->width, traywin->height); XMoveResizeWindow(server.display, traywin->win, 0, 0, traywin->width, traywin->height); // Embed into parent { XEvent e; e.xclient.type = ClientMessage; e.xclient.serial = 0; e.xclient.send_event = True; e.xclient.message_type = server.atom._XEMBED; e.xclient.window = traywin->win; e.xclient.format = 32; e.xclient.data.l[0] = CurrentTime; e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; e.xclient.data.l[2] = 0; e.xclient.data.l[3] = traywin->parent; e.xclient.data.l[4] = 0; if (systray_profile) fprintf(stderr, "XSendEvent(server.display, traywin->win, False, NoEventMask, &e)\n"); XSendEvent(server.display, traywin->win, False, NoEventMask, &e); } XSync(server.display, False); XSetErrorHandler(old); if (error != FALSE) { fprintf(stderr, RED "systray %d: cannot embed icon for window %lu (%s) parent %lu pid %d" RESET "\n", __LINE__, traywin->win, traywin->name, traywin->parent, traywin->pid); remove_icon(traywin); return FALSE; } traywin->reparented = TRUE; if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); return TRUE; }