xnotif.c (3799B)
1 #include "shod.h" 2 3 /* create notification window */ 4 static void 5 notifnew(Window win, int w, int h) 6 { 7 struct Notification *notif; 8 9 notif = emalloc(sizeof(*notif)); 10 *notif = (struct Notification){ 11 .w = w + 2 * config.borderwidth, 12 .h = h + 2 * config.borderwidth, 13 .pix = None, 14 .obj.type = TYPE_NOTIFICATION, 15 .obj.win = win, 16 }; 17 TAILQ_INSERT_TAIL(&wm.notifq, (struct Object *)notif, entry); 18 notif->frame = XCreateWindow( 19 dpy, root, 0, 0, 1, 1, 0, 20 depth, CopyFromParent, visual, 21 clientmask, 22 &(XSetWindowAttributes){ 23 .event_mask = SubstructureNotifyMask | SubstructureRedirectMask, 24 .colormap = colormap 25 } 26 ); 27 XReparentWindow(dpy, notif->obj.win, notif->frame, 0, 0); 28 XMapWindow(dpy, notif->obj.win); 29 } 30 31 /* decorate notification */ 32 void 33 notifdecorate(struct Notification *n) 34 { 35 /* (re)create pixmap */ 36 if (n->pw != n->w || n->ph != n->h || n->pix == None) { 37 if (n->pix != None) 38 XFreePixmap(dpy, n->pix); 39 n->pix = XCreatePixmap(dpy, n->frame, n->w, n->h, depth); 40 } 41 n->pw = n->w; 42 n->ph = n->h; 43 44 drawborders(n->pix, n->w, n->h, FOCUSED); 45 46 drawcommit(n->pix, n->frame); 47 } 48 49 /* place notifications */ 50 void 51 notifplace(void) 52 { 53 struct Object *n; 54 struct Notification *notif; 55 int x, y, h; 56 57 h = 0; 58 TAILQ_FOREACH(n, &wm.notifq, entry) { 59 notif = (struct Notification *)n; 60 x = TAILQ_FIRST(&wm.monq)->wx; 61 y = TAILQ_FIRST(&wm.monq)->wy; 62 switch (config.notifgravity[0]) { 63 case 'N': 64 switch (config.notifgravity[1]) { 65 case 'W': 66 break; 67 case 'E': 68 x += TAILQ_FIRST(&wm.monq)->ww - notif->w; 69 break; 70 default: 71 x += (TAILQ_FIRST(&wm.monq)->ww - notif->w) / 2; 72 break; 73 } 74 break; 75 case 'S': 76 switch(config.notifgravity[1]) { 77 case 'W': 78 y += TAILQ_FIRST(&wm.monq)->wh - notif->h; 79 break; 80 case 'E': 81 x += TAILQ_FIRST(&wm.monq)->ww - notif->w; 82 y += TAILQ_FIRST(&wm.monq)->wh - notif->h; 83 break; 84 default: 85 x += (TAILQ_FIRST(&wm.monq)->ww - notif->w) / 2; 86 y += TAILQ_FIRST(&wm.monq)->wh - notif->h; 87 break; 88 } 89 break; 90 case 'W': 91 y += (TAILQ_FIRST(&wm.monq)->wh - notif->h) / 2; 92 break; 93 case 'C': 94 x += (TAILQ_FIRST(&wm.monq)->ww - notif->w) / 2; 95 y += (TAILQ_FIRST(&wm.monq)->wh - notif->h) / 2; 96 break; 97 case 'E': 98 x += TAILQ_FIRST(&wm.monq)->ww - notif->w; 99 y += (TAILQ_FIRST(&wm.monq)->wh - notif->h) / 2; 100 break; 101 default: 102 x += TAILQ_FIRST(&wm.monq)->ww - notif->w; 103 break; 104 } 105 106 if (config.notifgravity[0] == 'S') 107 y -= h; 108 else 109 y += h; 110 h += notif->h + config.notifgap + config.borderwidth * 2; 111 112 XMoveResizeWindow(dpy, notif->frame, x, y, notif->w, notif->h); 113 XMoveResizeWindow(dpy, notif->obj.win, config.borderwidth, config.borderwidth, notif->w - 2 * config.borderwidth, notif->h - 2 * config.borderwidth); 114 XMapWindow(dpy, notif->frame); 115 if (notif->pw != notif->w || notif->ph != notif->h) { 116 notifdecorate(notif); 117 } 118 winnotify(notif->obj.win, x + config.borderwidth, y + config.borderwidth, notif->w - 2 * config.borderwidth, notif->h - 2 * config.borderwidth); 119 } 120 } 121 122 /* add notification window into notification queue; and update notification placement */ 123 void 124 managenotif(struct Tab *tab, struct Monitor *mon, int desk, Window win, Window leader, XRectangle rect, int state, int ignoreunmap) 125 { 126 (void)tab; 127 (void)mon; 128 (void)desk; 129 (void)leader; 130 (void)state; 131 (void)ignoreunmap; 132 notifnew(win, rect.width, rect.height); 133 notifplace(); 134 } 135 136 /* delete notification */ 137 int 138 unmanagenotif(struct Object *obj, int dummy) 139 { 140 struct Notification *notif; 141 142 (void)dummy; 143 notif = (struct Notification *)obj; 144 TAILQ_REMOVE(&wm.notifq, (struct Object *)notif, entry); 145 if (notif->pix != None) 146 XFreePixmap(dpy, notif->pix); 147 XReparentWindow(dpy, notif->obj.win, root, 0, 0); 148 XDestroyWindow(dpy, notif->frame); 149 free(notif); 150 notifplace(); 151 return 0; 152 }