all repos — tint2 @ 6c57698291c58a22f9606afc903bc9b94eb4b549

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

src/systray/icons.c (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "icons.h"
#include "net.h"
#include <assert.h>
#include <stdlib.h>

gboolean error;
int window_error_handler(Display *d, XErrorEvent *e)
{
  d=d;e=e;
  if (e->error_code == BadWindow) {
    error = TRUE;
  } else {
    g_printerr("X ERROR NOT BAD WINDOW!\n");
    abort();
  }
  return 0;
}


gboolean icon_swallow(TrayWindow *traywin)
{
  XErrorHandler old;

  error = FALSE;
  old = XSetErrorHandler(window_error_handler);
  XReparentWindow(display, traywin->id, win, 0, 0);
  XSync(display, False);
  XSetErrorHandler(old);

  return !error;
}


/*
  The traywin must have its id and type set.
*/
gboolean icon_add(Window id, TrayWindowType type)
{
  TrayWindow *traywin;

  assert(id);
  assert(type);

  if (wmaker) {
    /* do we have room in our window for another icon? */
    unsigned int max = (width / icon_size) * (height / icon_size);
    if (g_slist_length(icons) >= max)
      return FALSE; /* no room, sorry! REJECTED! */
  }

  traywin = g_new0(TrayWindow, 1);
  traywin->type = type;
  traywin->id = id;

  if (!icon_swallow(traywin)) {
    g_free(traywin);
    return FALSE;
  }

  /* find the positon for the systray app window */
  if (!wmaker) {
    traywin->x = border + (horizontal ? width : 0);
    traywin->y = border + (horizontal ? 0 : height);
  } else {
    int count = g_slist_length(icons);
    traywin->x = border + ((width % icon_size) / 2) +
      (count % (width / icon_size)) * icon_size;
    traywin->y = border + ((height % icon_size) / 2) +
      (count / (height / icon_size)) * icon_size;
  }

  /* add the new icon to the list */
  icons = g_slist_append(icons, traywin);

  /* watch for the icon trying to resize itself! BAD ICON! BAD! */
  XSelectInput(display, traywin->id, StructureNotifyMask);

  /* position and size the icon window */
  XMoveResizeWindow(display, traywin->id,
                    traywin->x, traywin->y, icon_size, icon_size);
  
  /* resize our window so that the new window can fit in it */
  fix_geometry();

  /* flush before clearing, otherwise the clear isn't effective. */
  XFlush(display);
  /* make sure the new child will get the right stuff in its background
     for ParentRelative. */
  XClearWindow(display, win);
  
  /* show the window */
  XMapRaised(display, traywin->id);

  return TRUE;
}


void icon_remove(GSList *node)
{
  XErrorHandler old;
  TrayWindow *traywin = node->data;
  Window traywin_id = traywin->id;

  if (traywin->type == NET)
    net_icon_remove(traywin);

  XSelectInput(display, traywin->id, NoEventMask);
  
  /* remove it from our list */
  g_free(node->data);
  icons = g_slist_remove_link(icons, node);

  /* reparent it to root */
  error = FALSE;
  old = XSetErrorHandler(window_error_handler);
  XReparentWindow(display, traywin_id, root, 0, 0);
  XSync(display, False);
  XSetErrorHandler(old);

  reposition_icons();
  fix_geometry();
}