Beispiel #1
0
void kde_update_icons()
{
  gulong count = (unsigned) -1; /* grab as many as possible */
  Window *ids;
  unsigned int i;
  GSList *it, *next;
  gboolean removed = FALSE; /* were any removed? */

  if (! xprop_get32(root, kde_systray_prop, XA_WINDOW, sizeof(Window)*8,
                    &count, &ids))
    return;

  /* add new windows to our list */
  for (i = 0; i < count; ++i) {
    for (it = icons; it != NULL; it = g_slist_next(it)) {
      TrayWindow *traywin = it->data;
      if (traywin->id == ids[i])
        break;
    }
    if (!it)
      icon_add(ids[i], KDE);
  }

  /* remove windows from our list that no longer exist in the property */
  for (it = icons; it != NULL;) {
    TrayWindow *traywin = it->data;
    gboolean exists;

    if (traywin->type != KDE) {
      /* don't go removing non-kde windows */
      exists = TRUE;
    } else {
      exists = FALSE;
      for (i = 0; i < count; ++i) {
        if (traywin->id == ids[i]) {
          exists = TRUE;
          break;
        }
      }
    }
    
    next = g_slist_next(it);
    if (!exists) {
      icon_remove(it);
      removed =TRUE;
    }
    it = next;
  }

  if (removed) {
    /* at least one tray app was removed, so reorganize 'em all and resize*/
    reposition_icons();
    fix_geometry();
  }

  XFree(ids);
}
Beispiel #2
0
static void send_xembed_notify(Window w, Window parent){
    XEvent ev;
    ev.xclient.type = ClientMessage;
    ev.xclient.window = w;
    ev.xclient.message_type = xembed;
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = get_X_time();
    ev.xclient.data.l[1] = 0; // XEMBED_EMBEDDED_NOTIFY
    ev.xclient.data.l[2] = 0;
    ev.xclient.data.l[3] = parent;
    ev.xclient.data.l[4] = 0; // version
    void *v=catch_BadWindow_errors();
    XSendEvent(display, w, False, NoEventMask, &ev);
    if(uncatch_BadWindow_errors(v)){
        warn(DEBUG_WARN, "Tray icon %lx is invalid", w);
        icon_remove(w);
    }
}
Beispiel #3
0
static void event(XEvent *ev){
    struct trayicon *icon;
    void *v;

    switch(ev->type){
      case SelectionClear:
        if(ev->xselectionclear.selection == net_system_tray_s && XGetSelectionOwner(display, net_system_tray_s) != selwindow){
            warn(DEBUG_ERROR, "fdtray: Another application (window %lx) has forcibly taken the system tray registration", ev->xselectionclear.window);
            exitapp = True;
        }
        break;

      case PropertyNotify:
        if(ev->xproperty.atom != xembed_info) break;
        icon = icon_find(ev->xproperty.window);
        if(!icon || icon->type!=my_id) break;
        v = catch_BadWindow_errors();
        Bool map = get_map(icon->w);
        if(uncatch_BadWindow_errors(v)){
            warn(DEBUG_WARN, "Tray icon %lx is invalid", icon->w);
            icon_remove(icon->w);
        } else {
            icon_set_mapping(icon, map);
        }
        break;

      case ConfigureNotify:
        icon = icon_find(ev->xconfigure.window);
        if(!icon || icon->type!=my_id) break;
        v = catch_BadWindow_errors();
        {
            XWindowAttributes a;
            XGetWindowAttributes(display, icon->w, &a);
            if(a.width != iconsize || a.height != iconsize)
                XResizeWindow(display, icon->w, iconsize, iconsize);
        }
        if(uncatch_BadWindow_errors(v)){
            warn(DEBUG_WARN, "Tray icon %lx is invalid", icon->w);
            icon_remove(icon->w);
        }
        break;

      case ReparentNotify:
        icon = icon_find(ev->xreparent.window);
        if(!icon || icon->type!=my_id) break;
        if(is_icon_parent(ev->xreparent.parent)){
            send_xembed_notify(icon->w, ev->xreparent.parent);
        } else {
            warn(DEBUG_WARN, "Tray icon %lx was reparented, removing", icon->w);
            icon_remove(icon->w);
        }
        break;

      case DestroyNotify:
        icon = icon_find(ev->xdestroywindow.window);
        if(!icon || icon->type!=my_id) break;
        warn(DEBUG_WARN, "Tray icon %lx was destroyed, removing", icon->w);
        icon_remove(icon->w);
        break;

      case ClientMessage:
        if(ev->xclient.message_type == net_system_tray_opcode){
            switch(ev->xclient.data.l[1]){
              case 0: // SYSTEM_TRAY_REQUEST_DOCK
                add(ev->xclient.data.l[2]);
                break;

              case 1: // SYSTEM_TRAY_BEGIN_MESSAGE
                icon = icon_find(ev->xclient.window);
                if(!icon || icon->type!=my_id) break;
                *(int *)icon->data = ev->xclient.data.l[4];
                icon_begin_message(icon->w, ev->xclient.data.l[4], ev->xclient.data.l[3], ev->xclient.data.l[2]);
                break;

              case 2: // SYSTEM_TRAY_CANCEL_MESSAGE
                icon = icon_find(ev->xclient.window);
                if(!icon || icon->type!=my_id) break;
                icon_cancel_message(icon->w, ev->xclient.data.l[2]);
                break;
            }
        } else if(ev->xclient.message_type == net_system_tray_message_data){
            icon = icon_find(ev->xclient.window);
            if(!icon || icon->type!=my_id) break;
            icon_message_data(icon->w, *(int *)icon->data, ev->xclient.data.b, 20);
        }
        break;
    }
}
Beispiel #4
0
/* Display functions */
static void update(){
    int i, j, x, y, w;
    int icons_per_page=icons_per_row*icons_per_col*num_windows;
    char buf[42];
    Window dummy;
    int pages;

    need_update = False;

redo:
    pages = (num_mapped_icons-1)/icons_per_page+1;
    if(current_page >= pages){
        warn(DEBUG_DEBUG, "Page %d is empty!", current_page+1);
        current_page=pages-1;
    }
    warn(DEBUG_DEBUG, "Updating display: page %d of %d", current_page+1, pages);

    for(i = 0; i<num_windows; i++){
        warn(DEBUG_DEBUG, "Drawing window %d (%lx)", i, iconwin[i]);
        if(arrow_style==0 ||
           (arrow_style==1 && i==0) ||
           (arrow_style==2 && i==num_windows-1)){
            y=(current_page==0)?0:(iconwin[i]==down_window && down_button==-1)?20:10;
            XCopyArea(display, pixmap, iconwin[i], gc5x8, 0,y, 15,10, 4,52);
        }
        if(arrow_style==0 ||
           (arrow_style==1 && i==num_windows-1) ||
           (arrow_style==2 && i==num_windows-1)){
            sprintf(buf, "%d/%d", current_page+1, pages);
            x = strlen(buf);
            XClearArea(display, iconwin[i], 19,52, 25,8, False);
            XDrawString(display, iconwin[i], gc5x8, (current_page>8)?19:24,60, buf, x);
            y=(current_page+1>=pages)?0:(iconwin[i]==down_window && down_button==1)?20:10;
            XCopyArea(display, pixmap, iconwin[i], gc5x8, 15,y, 15,10, 45,52);
        }
        if(id_windows){
            sprintf(buf, "%d", i);
            XDrawString(display, iconwin[i], gc10x20, 8,50, buf, strlen(buf));
        }
    }

    struct trayicon *icon = icons;
    i=-current_page*icons_per_page;
    while(icon){
        void *v=catch_BadWindow_errors();
        if(!icon->mapped || i<0 || i>=icons_per_page){
            warn(DEBUG_DEBUG, "Tray icon %lx is not visible", icon->w);
            icon->visible = False;
            if(icon->parent == None){
                // Parent it somewhere
                warn(DEBUG_DEBUG, "Reparenting %lx to %lx", icon->w, iconwin[0]);
                XReparentWindow(display, icon->w, iconwin[0], 0, 0);
                icon->parent = iconwin[0];
            }
            XUnmapWindow(display, icon->w);
        } else {
            icon->visible = True;
            j = i;
            switch(fill_style){
              case 0:
                w = j / (icons_per_row * icons_per_col);
                j = j % (icons_per_row * icons_per_col);
                y = j / icons_per_row;
                x = j % icons_per_row;
                break;
              case 1:
                y = j / (icons_per_row * num_windows);
                j = j % (icons_per_row * num_windows);
                w = j / icons_per_row;
                x = j % icons_per_row;
                break;
              default:
                x=0; y=0; w=0;
                break;
            }
            x=8+x*iconsize;
            y=4+y*iconsize;
            warn(DEBUG_DEBUG, "[%d] Tray icon %lx at %d %d,%d", i, icon->w, w, x, y);
            if(icon->parent != iconwin[w]){
                warn(DEBUG_DEBUG, "Reparenting %lx to %lx", icon->w, iconwin[w]);
                XReparentWindow(display, icon->w, iconwin[w], x, y);
                icon->parent = iconwin[w];
            }
            XMoveResizeWindow(display, icon->w, x, y, iconsize, iconsize);
            XClearArea(display, icon->w, 0, 0, 0, 0, True);
            XMapRaised(display, icon->w);
            XTranslateCoordinates(display, icon->w, root, iconsize/2, iconsize/2, &icon->x, &icon->y, &dummy);
        }
        if(uncatch_BadWindow_errors(v)){
            warn(DEBUG_INFO, "Tray icon %lx is invalid, removing and restarting layout", icon->w);
            icon_remove(icon->w);
            goto redo;
        }
        if(icon->mapped) i++;
        icon = icon->next;
    }

    // XXX: if point_messages is true, can we re-point any notifications?
}