1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It is one of the source files comprising zwgc, the Zephyr WindowGram
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
7 * $Id: X_gram.c,v 1.22 1999/01/22 23:20:09 ghudson Exp $
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_X_gram_c[] = "$Id: X_gram.c,v 1.22 1999/01/22 23:20:09 ghudson Exp $";
20 #include <zephyr/mit-copyright.h>
22 #ifndef X_DISPLAY_MISSING
26 #include <X11/Xutil.h>
27 #include <X11/cursorfont.h>
32 #include "new_string.h"
33 #include "xrevstack.h"
37 extern XContext desc_context;
38 extern char *app_instance;
39 extern unsigned long x_string_to_color();
40 extern char *getenv();
46 int internal_border_width = 2;
48 unsigned long default_fgcolor;
49 unsigned long default_bgcolor;
50 unsigned long default_bordercolor;
52 static int reset_saver;
53 static int border_width = 1;
54 static int cursor_code = XC_sailboat;
55 static int set_transient;
56 static int enable_delete;
57 static char *title_name,*icon_name;
59 static Window group_leader; /* In order to have transient windows,
60 * I need a top-level window to always exist
62 static XClassHint classhint;
63 static XSetWindowAttributes xattributes;
64 static unsigned long xattributes_mask;
68 * the following properties must be set on all top-level windows:
70 * WM_NAME XStoreName(dpy,w,name);
71 * WM_ICON_NAME XSetIconName(dpy,w,name);
72 * WM_NORMAL_HINTS XSetNormalHints(dpy,w,sizehints);
73 * WM_HINTS XSetWMHints(dpy,w,wmhints);
74 * WM_CLASS XSetClassHint(dpy,w,classhint);
76 * and for individual zgrams:
78 * WM_TRANSIENT_FOR XSetTransientForHint(dpy,w,main_window);
79 * WM_PROTOCOLS XSetWMProtocols(dpy,w,protocols,cnt);
82 /* set all properties defined in ICCCM. If main_window == 0,
83 * per-zgram initialization is not done.
87 void x_set_icccm_hints(dpy,w,name,icon_name,psizehints,pwmhints,main_window)
92 XSizeHints *psizehints;
96 XStoreName(dpy,w,name);
97 XSetIconName(dpy,w,icon_name);
98 XSetNormalHints(dpy,w,psizehints);
99 XSetWMHints(dpy,w,pwmhints);
100 XSetClassHint(dpy,w,&classhint);
101 /* in order for some wm's to iconify, the window shouldn't be transient.
103 if (main_window != None) {
105 XSetTransientForHint(dpy,w,main_window);
108 XSetWMProtocols(dpy,w,&XA_WM_DELETE_WINDOW,1);
111 void x_gram_init(dpy)
115 XSizeHints sizehints;
119 default_fgcolor = BlackPixelOfScreen(DefaultScreenOfDisplay(dpy));
120 default_bgcolor = WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
121 rv = get_bool_resource("reverseVideo", "ReverseVideo", 0);
123 tc = default_fgcolor;
124 default_fgcolor = default_bgcolor;
125 default_bgcolor = tc;
127 if (temp = get_string_resource("foreground","Foreground"))
128 default_fgcolor = x_string_to_color(temp,default_fgcolor);
129 if (temp = get_string_resource("background","Background"))
130 default_bgcolor = x_string_to_color(temp,default_bgcolor);
131 default_bordercolor = default_fgcolor;
132 if (temp = get_string_resource("borderColor","BorderColor"))
133 default_bordercolor = x_string_to_color(temp,default_bordercolor);
135 temp = get_string_resource("minTimeToLive","MinTimeToLive");
136 if (temp && atoi(temp)>=0)
139 reverse_stack = get_bool_resource("reverseStack", "ReverseStack", 0);
140 reset_saver = get_bool_resource("resetSaver", "ResetSaver", 1);
141 /* The default here should be 1, but mwm sucks */
142 set_transient = get_bool_resource("transient", "Transient", 0);
143 enable_delete = get_bool_resource("enableDelete", "EnableDelete", 1);
145 temp = get_string_resource("borderWidth", "BorderWidth");
147 if (temp && atoi(temp)>=0)
148 border_width = atoi(temp);
150 temp = get_string_resource("internalBorder", "InternalBorder");
152 if (temp && atoi(temp)>=0)
153 internal_border_width = atoi(temp);
155 temp = get_string_resource("cursorCode", "CursorCode");
157 if (temp && atoi(temp))
158 cursor_code = atoi(temp);
160 cursor = XCreateFontCursor(dpy, cursor_code);
162 cursor = XCreateFontCursor(dpy, XC_sailboat);
164 temp = get_string_resource("pointerColor", "Foreground");
167 XColor cursor_fore, cursor_back;
168 /* XXX need to do our own parsing here, since the RecolorCursor
169 routine requires an XColor, not an unsigned long (pixel) */
170 if (!(temp2 = get_string_resource("background","Background"))) {
171 if (default_bgcolor == WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)))
177 DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy)),
178 temp, &cursor_fore) &&
180 DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy)),
181 temp2, &cursor_back)) {
182 XRecolorCursor(dpy, cursor, &cursor_fore, &cursor_back);
185 if (!(title_name=get_string_resource("title","Title")))
186 if (!(title_name=get_string_resource("name","Name")))
187 title_name=app_instance;
189 if (!(icon_name=get_string_resource("iconName","IconName")))
190 if (!(icon_name=get_string_resource("name","Name")))
191 icon_name=app_instance;
193 if (!(temp=get_string_resource("name","Name")))
194 if (!(temp=(char *) getenv("RESOURCE_NAME")))
196 classhint.res_name=string_Copy(temp);
197 classhint.res_class="Zwgc";
200 group_leader=XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,100,100,
201 0,default_bordercolor,default_bgcolor);
204 sizehints.width = 100;
205 sizehints.height = 100;
206 sizehints.flags = PPosition | PSize;
208 wmhints.input = False;
209 wmhints.initial_state = DontCareState;
210 wmhints.flags = InputHint | StateHint;
212 x_set_icccm_hints(dpy,group_leader,"ZwgcGroup","ZwgcGroup",&sizehints,
215 xattributes.border_pixel = default_bordercolor;
216 xattributes.cursor = cursor;
217 xattributes.event_mask = (ExposureMask|ButtonReleaseMask|ButtonPressMask
218 |LeaveWindowMask|Button1MotionMask
219 |Button3MotionMask|StructureNotifyMask);
220 xattributes_mask = (CWBackPixel|CWBorderPixel|CWEventMask|CWCursor);
221 temp = get_string_resource ("backingStore", "BackingStore");
224 xattributes_mask |= CWBackingStore;
225 if (!strcasecmp (temp, "notuseful"))
226 xattributes.backing_store = NotUseful;
227 else if (!strcasecmp (temp, "whenmapped"))
228 xattributes.backing_store = WhenMapped;
229 else if (!strcasecmp (temp, "always"))
230 xattributes.backing_store = Always;
231 else if (!strcasecmp (temp, "default"))
232 xattributes_mask &= ~CWBackingStore;
234 switch (get_bool_resource ("backingStore", "BackingStore", -1)) {
236 xattributes.backing_store = NotUseful;
239 xattributes.backing_store = WhenMapped;
243 "zwgc: Cannot interpret backing-store resource value `%s'.\n",
245 xattributes_mask &= ~CWBackingStore;
251 void x_gram_create(dpy, gram, xalign, yalign, xpos, ypos, xsize, ysize,
261 XSizeHints sizehints;
263 XSetWindowAttributes attributes;
264 extern void x_get_input();
267 * Adjust xpos, ypos based on the alignments xalign, yalign and the sizes:
270 xpos = WidthOfScreen(DefaultScreenOfDisplay(dpy)) - xpos - xsize
272 else if (xalign == 0)
273 xpos = (WidthOfScreen(DefaultScreenOfDisplay(dpy)) - xsize
274 - 2*border_width)>>1 + xpos;
277 ypos = HeightOfScreen(DefaultScreenOfDisplay(dpy)) - ypos - ysize
279 else if (yalign == 0)
280 ypos = (HeightOfScreen(DefaultScreenOfDisplay(dpy)) - ysize
281 - 2*border_width)>>1 + ypos;
286 attributes = xattributes;
287 attributes.background_pixel = gram->bgcolor;
289 gram->w = w = XCreateWindow (dpy, DefaultRootWindow (dpy), xpos, ypos,
290 xsize, ysize, border_width, 0,
291 CopyFromParent, CopyFromParent,
292 xattributes_mask, &attributes);
296 sizehints.width = xsize;
297 sizehints.height = ysize;
298 sizehints.flags = USPosition|USSize;
300 wmhints.input = True;
301 wmhints.initial_state = NormalState;
303 wmhints.window_group = group_leader;
304 wmhints.flags = InputHint | StateHint | WindowGroupHint;
306 x_set_icccm_hints(dpy,w,title_name,icon_name,&sizehints,&wmhints,
309 wmhints.flags = InputHint | StateHint;
311 x_set_icccm_hints(dpy,w,title_name,icon_name,&sizehints,&wmhints,0);
315 XSaveContext(dpy, w, desc_context, (caddr_t)gram);
317 gram->can_die.tv_sec = 0;
325 if (reverse_stack && bottom_gram) {
326 XWindowChanges winchanges;
328 winchanges.sibling=bottom_gram->w;
329 winchanges.stack_mode=Below;
330 begin_xerror_trap (dpy);
331 XReconfigureWMWindow (dpy, w, DefaultScreen (dpy),
332 CWSibling|CWStackMode, &winchanges);
333 end_xerror_trap (dpy);
334 if (xerror_happened) {
335 /* The event didn't go. Print an error message, and continue. */
336 ERROR ("Error configuring window to the bottom of the stack.\n");
339 /* we always need to keep a linked list of windows */
345 XResetScreenSaver(dpy);
348 /* Because the flushing/syncing/etc with the error trapping can cause
349 events to be read into the Xlib queue, we need to go through the queue
350 here before exiting so that any pending events get processed.
355 void x_gram_draw(dpy, w, gram, region)
366 int startblock,endblock,startpixel,endpixel;
369 gcvals.foreground=fg; \
370 XChangeGC(dpy,gc,GCForeground,&gcvals)
372 gc = XCreateGC(dpy, w, 0, &gcvals);
373 XSetRegion(dpy,gc,region);
375 if ((markgram == gram) && (STARTBLOCK != -1) && (ENDBLOCK != -1)) {
376 if (xmarkSecond() == XMARK_END_BOUND) {
377 startblock=STARTBLOCK;
379 startpixel=STARTPIXEL;
392 for (i=0,xb=gram->blocks ; i<gram->numblocks ; i++,xb++) {
393 if (XRectInRegion(region,xb->x1,xb->y1,xb->x2-xb->x1,
394 xb->y2-xb->y1) != RectangleOut) {
397 SetFG(gram->bgcolor);
398 XFillRectangle(dpy,w,gc,xb->x1,xb->y1,startpixel,
401 XFillRectangle(dpy,w,gc,xb->x1+startpixel,xb->y1,
402 (endpixel-startpixel),(xb->y2-xb->y1));
403 SetFG(gram->bgcolor);
404 XFillRectangle(dpy,w,gc,xb->x1+endpixel,xb->y1,
405 (xb->x2-xb->x1-endpixel),(xb->y2-xb->y1));
407 SetFG(gram->bgcolor);
408 XFillRectangle(dpy,w,gc,xb->x1,xb->y1,startpixel,
411 XFillRectangle(dpy,w,gc,xb->x1+startpixel,xb->y1,
412 (xb->x2-xb->x1-startpixel),(xb->y2-xb->y1));
414 } else if (i==endblock) {
416 XFillRectangle(dpy,w,gc,xb->x1,xb->y1,endpixel,
418 SetFG(gram->bgcolor);
419 XFillRectangle(dpy,w,gc,xb->x1+endpixel,xb->y1,
420 (xb->x2-xb->x1-endpixel),(xb->y2-xb->y1));
422 if ((startblock < i) && (i < endblock)) {
425 SetFG(gram->bgcolor);
427 XFillRectangle(dpy,w,gc,xb->x1,xb->y1,(xb->x2-xb->x1),
433 gcvals.function=GXxor;
434 XChangeGC(dpy,gc,GCFunction,&gcvals);
436 for (i=0,xb=gram->blocks ; i<gram->numblocks ; i++,xb++) {
437 if ((xb->strlen > 0) &&
438 (XRectInRegion(region,xb->x1,xb->y1,xb->x2-xb->x1,
439 xb->y2-xb->y1) != RectangleOut)) {
440 SetFG(gram->bgcolor^xb->fgcolor);
441 text.chars=gram->text+xb->strindex;
442 text.nchars=xb->strlen;
445 XDrawText(dpy,w,gc,xb->x,xb->y,&text,1);
452 void x_gram_expose(dpy,w,gram,event)
458 static Region region;
459 static int partregion;
462 rect.x = (short) event->x;
463 rect.y = (short) event->y;
464 rect.width = (unsigned short) event->width;
465 rect.height = (unsigned short) event->height;
468 printf("----- xeventExpose:\nx=%d y=%d w=%d h=%d\n-----",
469 event->x,event->y,event->width,event->height);
473 region=XCreateRegion();
477 if (rect.width && rect.height) XUnionRectWithRegion(&rect,region,region);
479 if (event->count == 0) {
480 x_gram_draw(dpy,w,gram,region);
482 XDestroyRegion(region);
486 #endif /* X_DISPLAY_MISSING */