Don't explicitly send MotionNotify event during Resize (GeometryWindow)
[fvwm.git] / modules / FvwmScroll / GrabWindow.c
blob6dab86a5171d349f7f3481a3cb7e62e8585ba998
1 /* -*-c-*- */
2 /* This module, and the entire GoodStuff program, and the concept for
3 * interfacing this module to the Window Manager, are all original work
4 * by Robert Nation
6 * Copyright 1993, Robert Nation. No guarantees or warantees or anything
7 * are provided or implied in any way whatsoever. Use this program at your
8 * own risk. Permission to use this program for any purpose is given,
9 * as long as the copyright is kept intact. */
11 /* This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #if 0
27 #define MAX_ICON_NAME_LEN 255
28 #endif
30 #include "config.h"
32 #ifdef HAVE_SYS_BSDTYPES_H
33 #include <sys/bsdtypes.h> /* Saul */
34 #endif
36 #include <stdio.h>
37 #include <signal.h>
38 #include <sys/wait.h>
39 #include "libs/ftime.h"
41 #if HAVE_SYS_SELECT_H
42 #include <sys/select.h>
43 #endif
44 #include <ctype.h>
45 #include <X11/Xlib.h>
46 #include <X11/Xatom.h>
48 #include "libs/Module.h"
49 #include "libs/fvwmlib.h"
50 #include "libs/Colorset.h"
51 #include "libs/PictureBase.h"
52 #include "libs/FScreen.h"
53 #include "libs/Graphics.h"
54 #include "libs/Parse.h"
55 #include "libs/Strings.h"
57 #include "FvwmScroll.h"
59 static int Width = 300, Height = 300;
60 static int target_width, target_height;
61 static int target_x_offset = 0, target_y_offset = 0;
62 static int exposed;
63 int Reduction_H = 2;
64 int Reduction_V = 2;
65 int Percent_H = -1;
66 int Percent_V =-1;
68 #define BAR_WIDTH 21
69 #define SCROLL_BAR_WIDTH 9
71 #define PAD_WIDTH2 3
72 #define PAD_WIDTH3 5
74 static Window main_win,holder_win;
75 static Pixel hilite_pix,shadow_pix;
76 extern int colorset;
77 extern char *BackColor;
79 #define MW_EVENTS (ExposureMask | StructureNotifyMask| ButtonReleaseMask |\
80 ButtonPressMask | ButtonMotionMask | FocusChangeMask)
82 Atom wm_del_win;
83 Atom _XA_WM_PROTOCOLS;
84 Atom _XA_WM_COLORMAP_WINDOWS;
88 * Sizes and creates the window
91 XSizeHints mysizehints;
92 void CreateWindow(int x,int y, int w, int h)
94 XGCValues gcv;
95 unsigned long gcm;
96 XSetWindowAttributes attributes;
97 int wx;
98 int wy;
100 wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False);
101 _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
103 mysizehints.flags = PWinGravity| PResizeInc | PBaseSize | PMaxSize | PMinSize
104 | USSize | USPosition;
105 /* subtract one for the right/bottom border */
106 mysizehints.width_inc = 1;
107 mysizehints.height_inc = 1;
108 mysizehints.base_height = BAR_WIDTH + PAD_WIDTH3;
109 mysizehints.base_width = BAR_WIDTH + PAD_WIDTH3;
111 if ( Percent_V > -1 )
113 Width = (ScreenWidth * Percent_V)/100;
114 if ( Width > (w + BAR_WIDTH + PAD_WIDTH3) || Percent_V == 0 )
115 Width = w + BAR_WIDTH + PAD_WIDTH3;
117 else
119 Width = w/Reduction_V + BAR_WIDTH + PAD_WIDTH3;
122 if ( Percent_H > -1 )
124 Height = (ScreenHeight * Percent_H)/100;
125 if ( Height > h || Percent_H == 0 )
126 Height = h + BAR_WIDTH + PAD_WIDTH3;
128 else
130 Height = h/Reduction_H + BAR_WIDTH + PAD_WIDTH3;
133 target_width = w;
134 target_height = h;
135 mysizehints.width = Width;
136 mysizehints.height = Height;
137 wx = x;
138 wy = y;
139 mysizehints.max_width = w + BAR_WIDTH + PAD_WIDTH3;
140 mysizehints.max_height = h + BAR_WIDTH + PAD_WIDTH3;
142 mysizehints.win_gravity = NorthWestGravity;
144 attributes.backing_store = NotUseful;
145 attributes.background_pixel = (colorset < 0) ? GetColor(BackColor)
146 : Colorset[colorset].bg;
147 attributes.border_pixel = 0;
148 attributes.colormap = Pcmap;
149 main_win = XCreateWindow(dpy, Root, wx, wy,
150 mysizehints.width, mysizehints.height, 0, Pdepth,
151 InputOutput, Pvisual, CWBackingStore | CWBackPixel
152 | CWBorderPixel | CWColormap, &attributes);
154 hilite_pix = (colorset < 0) ? GetHilite(attributes.background_pixel)
155 : Colorset[colorset].hilite;
156 shadow_pix = (colorset < 0) ? GetShadow(attributes.background_pixel)
157 : Colorset[colorset].shadow;
159 XSetWMProtocols(dpy,main_win,&wm_del_win,1);
161 /* hack to prevent mapping on wrong screen with StartsOnScreen */
162 FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS, &mysizehints);
163 XSetWMNormalHints(dpy,main_win,&mysizehints);
164 XSelectInput(dpy,main_win,MW_EVENTS);
165 change_window_name(module->name);
167 holder_win = XCreateWindow(dpy, main_win, PAD_WIDTH3, PAD_WIDTH3,
168 mysizehints.width - BAR_WIDTH - PAD_WIDTH3,
169 mysizehints.height - BAR_WIDTH - PAD_WIDTH3,
170 0, Pdepth, InputOutput, Pvisual, CWBackingStore
171 | CWBackPixel | CWBorderPixel | CWColormap,
172 &attributes);
173 XMapWindow(dpy,holder_win);
176 gcm = GCForeground;
177 gcv.foreground = hilite_pix;
178 hiliteGC = fvwmlib_XCreateGC(dpy, holder_win, gcm, &gcv);
179 gcv.foreground = shadow_pix;
180 shadowGC = fvwmlib_XCreateGC(dpy, holder_win, gcm, &gcv);
182 if (colorset >= 0)
183 SetWindowBackground(dpy, main_win, mysizehints.width, mysizehints.height,
184 &Colorset[(colorset)], Pdepth, shadowGC,
185 True);
187 _XA_WM_COLORMAP_WINDOWS = XInternAtom (dpy, "WM_COLORMAP_WINDOWS", False);
191 LoopOnEvents - Process all the X events we get
194 #define RIGHT 7
195 #define LEFT 6
196 #define BOTTOM 5
197 #define TOP 4
198 #define QUIT 3
199 #define VERTICAL 2
200 #define HORIZONTAL 1
201 #define NONE 0
202 int motion = NONE;
204 void LoopOnEvents(Window target)
206 Window root;
207 int x, y;
208 XEvent Event;
209 XEvent ev;
210 unsigned int tw, th, depth, border_width;
211 char *temp;
212 char *prop = NULL;
213 Atom actual = None;
214 int actual_format;
215 unsigned long nitems, bytesafter;
217 while (FPending(dpy)) {
218 FNextEvent(dpy,&Event);
219 switch(Event.type)
221 case Expose:
222 while (FCheckTypedWindowEvent(
223 dpy, main_win, Expose, &Event));
224 exposed = 1;
225 RedrawWindow(target);
226 break;
228 case ConfigureNotify:
229 while (FCheckTypedWindowEvent(
230 dpy, main_win, ConfigureNotify, &ev))
232 if (!ev.xconfigure.send_event)
233 continue;
234 Event.xconfigure.send_event = True;
236 if (!XGetGeometry(
237 dpy, main_win, &root ,&x, &y, &tw, &th,
238 &border_width, &depth))
240 return;
242 if ((tw != Width) || (th != Height))
244 if (colorset >= 0)
245 SetWindowBackground(
246 dpy, main_win, tw, th,
247 &Colorset[(colorset)], Pdepth,
248 shadowGC, True);
249 XResizeWindow(
250 dpy, holder_win,
251 tw - BAR_WIDTH - PAD_WIDTH3,
252 th - BAR_WIDTH - PAD_WIDTH3);
253 Width = tw;
254 Height = th;
255 if (target_y_offset > target_height - Height +
256 BAR_WIDTH)
257 target_y_offset =
258 target_height - Height +
259 BAR_WIDTH;
260 if (target_y_offset < 0)
261 target_y_offset = 0;
262 if (target_x_offset > target_width - Width +
263 BAR_WIDTH)
264 target_x_offset =
265 target_width - Width + BAR_WIDTH;
266 if (target_x_offset < 0)
267 target_x_offset = 0;
269 XMoveWindow(
270 dpy, target, -target_x_offset,
271 -target_y_offset);
273 else if (Event.xconfigure.send_event &&
274 CSET_IS_TRANSPARENT(colorset))
276 SetWindowBackground(
277 dpy, main_win, tw, th,
278 &Colorset[(colorset)], Pdepth,
279 shadowGC, True);
281 break;
283 case ButtonPress:
284 if((Event.xbutton.y > Height-BAR_WIDTH) &&
285 (Event.xbutton.x < SCROLL_BAR_WIDTH+PAD_WIDTH3))
287 motion = LEFT;
288 exposed = 2;
289 RedrawWindow(target);
291 else if((Event.xbutton.y > Height - BAR_WIDTH) &&
292 (Event.xbutton.x > Width - BAR_WIDTH -
293 SCROLL_BAR_WIDTH-2) &&
294 (Event.xbutton.x < Width-BAR_WIDTH))
296 motion = RIGHT;
297 exposed = 2;
298 RedrawWindow(target);
300 else if((Event.xbutton.y < SCROLL_BAR_WIDTH+PAD_WIDTH3)
301 && (Event.xbutton.x > Width-BAR_WIDTH))
303 motion = TOP;
304 exposed = 2;
305 RedrawWindow(target);
307 else if((Event.xbutton.y > Height - BAR_WIDTH -
308 SCROLL_BAR_WIDTH-2) &&
309 (Event.xbutton.y < Height-BAR_WIDTH)&&
310 (Event.xbutton.x > Width-BAR_WIDTH))
312 motion = BOTTOM;
313 exposed = 2;
314 RedrawWindow(target);
316 else if((Event.xbutton.x > Width - BAR_WIDTH)&&
317 (Event.xbutton.y < Height- BAR_WIDTH))
319 motion = VERTICAL;
320 target_y_offset=
321 (Event.xbutton.y - PAD_WIDTH3-
322 SCROLL_BAR_WIDTH)* target_height/
323 (Height-BAR_WIDTH-PAD_WIDTH3 -
324 2*SCROLL_BAR_WIDTH);
325 if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 >
326 target_height)
327 target_y_offset =
328 target_height - Height+BAR_WIDTH
329 +PAD_WIDTH3;
330 if(target_y_offset < 0)
331 target_y_offset = 0;
332 XMoveWindow(
333 dpy,target,-target_x_offset,
334 -target_y_offset);
335 RedrawWindow(target);
337 else if((Event.xbutton.y > Height- BAR_WIDTH ) &&
338 (Event.xbutton.x < Width- BAR_WIDTH))
340 motion=HORIZONTAL;
341 target_x_offset=
342 (Event.xbutton.x -PAD_WIDTH3-
343 SCROLL_BAR_WIDTH)* target_width/
344 (Width-BAR_WIDTH-PAD_WIDTH3-
345 2*SCROLL_BAR_WIDTH);
346 if(target_x_offset < 0)
347 target_x_offset = 0;
349 if(target_x_offset + Width -BAR_WIDTH-PAD_WIDTH3>
350 target_width)
351 target_x_offset =
352 target_width - Width + BAR_WIDTH+
353 PAD_WIDTH3;
354 XMoveWindow(
355 dpy,target,-target_x_offset,
356 -target_y_offset);
357 RedrawWindow(target);
359 else if((Event.xbutton.y > Height- BAR_WIDTH ) &&
360 (Event.xbutton.x > Width- BAR_WIDTH))
362 exposed = 2;
363 motion=QUIT;
365 RedrawWindow(target);
366 break;
368 case ButtonRelease:
369 if((Event.xbutton.y > Height- BAR_WIDTH ) &&
370 (Event.xbutton.x > Width- BAR_WIDTH)&&
371 (motion==QUIT))
373 XUnmapWindow(dpy,main_win);
374 XReparentWindow(dpy,target,Root,x,y);
375 XSync(dpy,0);
376 exit(0);
378 if((motion == LEFT)&&
379 (Event.xbutton.y > Height-BAR_WIDTH) &&
380 (Event.xbutton.x < SCROLL_BAR_WIDTH+PAD_WIDTH3))
382 target_x_offset -= (Width-BAR_WIDTH-PAD_WIDTH2);
383 if(target_x_offset < 0)
384 target_x_offset = 0;
385 XMoveWindow(
386 dpy,target,-target_x_offset,
387 -target_y_offset);
388 motion = NONE;
389 exposed = 2;
391 else if((motion == RIGHT)&&
392 (Event.xbutton.y > Height-BAR_WIDTH) &&
393 (Event.xbutton.x >
394 Width-BAR_WIDTH-SCROLL_BAR_WIDTH-2) &&
395 (Event.xbutton.x < Width-BAR_WIDTH))
397 target_x_offset += (Width-BAR_WIDTH-PAD_WIDTH2);
398 if(target_x_offset+Width-BAR_WIDTH -PAD_WIDTH3 >
399 target_width)
400 target_x_offset =
401 target_width - Width+BAR_WIDTH+
402 PAD_WIDTH3;
403 XMoveWindow(
404 dpy,target,-target_x_offset,
405 -target_y_offset);
406 motion = NONE;
407 exposed = 2;
409 else if((motion == TOP)&&
410 (Event.xbutton.y<SCROLL_BAR_WIDTH+PAD_WIDTH3)&&
411 (Event.xbutton.x > Width-BAR_WIDTH))
413 target_y_offset -= (Height-BAR_WIDTH-PAD_WIDTH2);
414 if(target_y_offset < 0)
415 target_y_offset = 0;
416 XMoveWindow(
417 dpy,target,-target_x_offset,
418 -target_y_offset);
419 motion = NONE;
420 exposed = 2;
422 else if((motion == BOTTOM)&&
423 (Event.xbutton.y >
424 Height-BAR_WIDTH-SCROLL_BAR_WIDTH-2) &&
425 (Event.xbutton.y < Height-BAR_WIDTH)&&
426 (Event.xbutton.x > Width-BAR_WIDTH))
428 target_y_offset += (Height-BAR_WIDTH-PAD_WIDTH2);
429 if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 >
430 target_height)
431 target_y_offset = target_height -
432 Height+BAR_WIDTH+PAD_WIDTH3;
433 XMoveWindow(
434 dpy,target,-target_x_offset,
435 -target_y_offset);
436 motion = NONE;
437 exposed = 2;
439 if(motion == VERTICAL)
441 target_y_offset =
442 (Event.xbutton.y-PAD_WIDTH3-
443 SCROLL_BAR_WIDTH)*target_height /
444 (Height-BAR_WIDTH-PAD_WIDTH3 -
445 2*SCROLL_BAR_WIDTH);
446 if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 >
447 target_height)
448 target_y_offset = target_height - Height+
449 BAR_WIDTH+PAD_WIDTH3;
450 if(target_y_offset < 0)
451 target_y_offset = 0;
452 XMoveWindow(
453 dpy,target,-target_x_offset,
454 -target_y_offset);
456 if(motion == HORIZONTAL)
458 target_x_offset=
459 (Event.xbutton.x -PAD_WIDTH3-
460 SCROLL_BAR_WIDTH) * target_width /
461 (Width-BAR_WIDTH-PAD_WIDTH3-
462 2*SCROLL_BAR_WIDTH);
463 if(target_x_offset < 0)
464 target_x_offset = 0;
466 if(target_x_offset + Width-BAR_WIDTH-PAD_WIDTH3>
467 target_width)
468 target_x_offset =
469 target_width - Width +
470 BAR_WIDTH+PAD_WIDTH3;
471 XMoveWindow(
472 dpy,target,-target_x_offset,
473 -target_y_offset);
475 RedrawWindow(target);
476 motion = NONE;
477 break;
479 case MotionNotify:
480 if((motion == LEFT)&&
481 ((Event.xmotion.y < Height-BAR_WIDTH) ||
482 (Event.xmotion.x > SCROLL_BAR_WIDTH+PAD_WIDTH3)))
484 motion = NONE;
485 exposed = 2;
487 else if((motion == RIGHT)&&
488 ((Event.xmotion.y < Height-BAR_WIDTH) ||
489 (Event.xmotion.x <
490 Width-BAR_WIDTH-SCROLL_BAR_WIDTH-2) ||
491 (Event.xmotion.x > Width-BAR_WIDTH)))
493 motion = NONE;
494 exposed = 2;
496 else if((motion == TOP)&&
497 ((Event.xmotion.y>SCROLL_BAR_WIDTH+PAD_WIDTH3)||
498 (Event.xmotion.x < Width-BAR_WIDTH)))
500 motion = NONE;
501 exposed = 2;
503 else if((motion == BOTTOM)&&
504 ((Event.xmotion.y <
505 Height-BAR_WIDTH-SCROLL_BAR_WIDTH-2) ||
506 (Event.xmotion.y > Height-BAR_WIDTH)||
507 (Event.xmotion.x < Width-BAR_WIDTH)))
509 motion = NONE;
510 exposed = 2;
512 if(motion == VERTICAL)
514 target_y_offset=
515 (Event.xmotion.y-PAD_WIDTH3-
516 SCROLL_BAR_WIDTH)*target_height/
517 (Height-BAR_WIDTH-PAD_WIDTH3-
518 2*SCROLL_BAR_WIDTH);
519 if(target_y_offset+Height-BAR_WIDTH -PAD_WIDTH3 >
520 target_height)
521 target_y_offset =
522 target_height - Height+BAR_WIDTH+
523 PAD_WIDTH3;
524 if(target_y_offset < 0)
525 target_y_offset = 0;
526 XMoveWindow(
527 dpy,target,-target_x_offset,
528 -target_y_offset);
530 if(motion == HORIZONTAL)
532 target_x_offset =
533 (Event.xmotion.x -PAD_WIDTH3-
534 SCROLL_BAR_WIDTH)* target_width/
535 (Width-BAR_WIDTH-PAD_WIDTH3-
536 2*SCROLL_BAR_WIDTH);
537 if(target_x_offset < 0)
538 target_x_offset = 0;
540 if(target_x_offset + Width-BAR_WIDTH-PAD_WIDTH3>
541 target_width)
542 target_x_offset =
543 target_width - Width + BAR_WIDTH+
544 PAD_WIDTH3;
545 XMoveWindow(
546 dpy,target,-target_x_offset,
547 -target_y_offset);
549 if((motion == QUIT)&&
550 ((Event.xbutton.y < Height- BAR_WIDTH )||
551 (Event.xbutton.x < Width- BAR_WIDTH)))
553 motion = NONE;
554 exposed = 2;
556 RedrawWindow(target);
557 break;
558 case ClientMessage:
559 if ((Event.xclient.format==32) &&
560 (Event.xclient.data.l[0]==wm_del_win))
562 DeadPipe(1);
564 break;
565 case PropertyNotify:
566 if(Event.xproperty.atom == XA_WM_NAME)
568 if(XFetchName(dpy, target, &temp)==0)
569 temp = NULL;
570 change_window_name(temp);
572 else if (Event.xproperty.atom == XA_WM_ICON_NAME)
574 if (XGetWindowProperty (
575 dpy,
576 target, Event.xproperty.atom, 0L,
577 (long)MAX_ICON_NAME_LEN, False, XA_STRING,
578 &actual,&actual_format, &nitems,
579 &bytesafter, (unsigned char **) &prop)
580 == Success && (prop != NULL))
581 change_icon_name(prop);
583 else if(Event.xproperty.atom == XA_WM_HINTS)
585 XWMHints *wmhints;
587 wmhints = XGetWMHints(dpy,target);
588 XSetWMHints(dpy,main_win, wmhints);
589 XFree(wmhints);
591 else if(Event.xproperty.atom == XA_WM_NORMAL_HINTS)
593 /* don't do Normal Hints. They alter the size of
594 * the window */
596 else if (Event.xproperty.atom == _XA_WM_COLORMAP_WINDOWS)
598 /* ignore colormap stuff. The FvwmScroll window
599 * may have a different visual to the client and
600 so cannot pass this on */
602 break;
604 case DestroyNotify:
605 DeadPipe(1);
606 break;
608 case UnmapNotify:
609 break;
611 case MapNotify:
612 XMapWindow(dpy,main_win);
613 break;
614 case FocusIn:
615 XSetInputFocus(dpy,target,RevertToParent,CurrentTime);
616 break;
617 case ColormapNotify:
618 /* FvwmScroll may not have the same visual as the
619 * captured window and so cannot share its colormap
621 XWindowAttributes xwa;
622 if(XGetWindowAttributes(dpy,target, &xwa) != 0)
624 XSetWindowColormap(dpy,main_win,xwa.colormap);
628 break;
629 default:
630 break;
636 ProcessMessage - Process the message coming from Fvwm
638 void ProcessMessage(unsigned long type,unsigned long *body)
640 char *tline, *token;
642 switch(type)
644 case M_CONFIG_INFO:
645 tline = (char*)&body[3];
646 tline = GetNextToken(tline, &token);
647 if (StrEquals(token, "Colorset"))
649 /* track all colorset changes and update display
650 * if necessary */
651 if (LoadColorset(tline) == colorset)
653 XSetForeground(
654 dpy, hiliteGC,Colorset[colorset].hilite);
655 XSetForeground(
656 dpy, shadowGC, Colorset[colorset].shadow);
657 SetWindowBackground(
658 dpy, main_win, Width, Height,
659 &Colorset[colorset], Pdepth, shadowGC,
660 True);
663 free(token);
664 break;
665 case MX_PROPERTY_CHANGE:
666 if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND && body[2] == 0 &&
667 CSET_IS_TRANSPARENT_PR(colorset))
669 SetWindowBackground(
670 dpy, main_win, Width, Height,
671 &Colorset[colorset],
672 Pdepth, shadowGC, True);
674 break;
679 Loop - Read and redraw until we die, blocking when can't read
681 void Loop(Window target)
683 while(1)
685 FvwmPacket* packet;
686 fd_set fdset;
688 FD_ZERO(&fdset);
689 FD_SET(fd[1], &fdset);
690 FD_SET(x_fd, &fdset);
692 LoopOnEvents(target);
694 select(fd_width, SELECT_FD_SET_CAST &fdset, NULL, NULL, NULL );
696 /* parse any config lines (colorsets) */
697 if (FD_ISSET(fd[1], &fdset))
699 packet = ReadFvwmPacket(fd[1]);
700 if (!packet)
702 /* fvwm has gone away or done KillModule */
703 XUnmapWindow(dpy,main_win);
704 XReparentWindow(dpy,target,Root,0,0);
705 XSync(dpy,0);
706 exit(0);
708 else
710 ProcessMessage(packet->type, packet->body);
714 return;
722 * Draw the window
725 void RedrawWindow(Window target)
727 static int xv= 0,yv= 0,hv=0,wv=0;
728 static int xh=0,yh=0,hh=0,wh=0;
729 int x,y,w,h;
730 XEvent dummy;
732 while (FCheckTypedWindowEvent(dpy, main_win, Expose, &dummy))
733 exposed |= 1;
735 XSetWindowBorderWidth(dpy,target,0);
737 RelieveRectangle(dpy, main_win, PAD_WIDTH3 - 2, PAD_WIDTH3 - 2,
738 Width-BAR_WIDTH - PAD_WIDTH3 + 3,
739 Height-BAR_WIDTH - PAD_WIDTH3 + 3,
740 shadowGC, hiliteGC, 2);
742 y = (Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)*
743 target_y_offset/target_height
744 + PAD_WIDTH2 + 2 + SCROLL_BAR_WIDTH;
745 x = Width-SCROLL_BAR_WIDTH- PAD_WIDTH2-2;
746 w = SCROLL_BAR_WIDTH;
747 h = (Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)*
748 (Height-BAR_WIDTH-PAD_WIDTH3)/
749 target_height;
750 if((y!=yv)||(x != xv)||(w != wv)||(h != hv)||(exposed & 1))
752 yv = y;
753 xv = x;
754 wv = w;
755 hv = h;
756 XClearArea(dpy,main_win,x,PAD_WIDTH3+SCROLL_BAR_WIDTH,
757 w,Height-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH,False);
759 RelieveRectangle(dpy, main_win, x, y, w - 1, h - 1,
760 hiliteGC, shadowGC, 2);
762 if(exposed & 1)
763 RelieveRectangle(dpy, main_win, x - 2, PAD_WIDTH2, w + 3,
764 Height - BAR_WIDTH - PAD_WIDTH2 + 1,
765 shadowGC, hiliteGC, 2);
766 if(exposed)
768 if(motion == TOP)
769 RedrawTopButton(shadowGC,hiliteGC,x,PAD_WIDTH3);
770 else
771 RedrawTopButton(hiliteGC,shadowGC,x,PAD_WIDTH3);
772 if(motion == BOTTOM)
773 RedrawBottomButton(shadowGC,hiliteGC,x,
774 Height-BAR_WIDTH-SCROLL_BAR_WIDTH);
775 else
776 RedrawBottomButton(hiliteGC,shadowGC,x,
777 Height-BAR_WIDTH-SCROLL_BAR_WIDTH);
780 x = (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)*target_x_offset/
781 target_width+PAD_WIDTH2+2 + SCROLL_BAR_WIDTH;
782 y = Height-SCROLL_BAR_WIDTH-PAD_WIDTH2-2;
783 w = (Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH)*
784 (Width-BAR_WIDTH-PAD_WIDTH3)/target_width;
785 h = SCROLL_BAR_WIDTH;
786 if((y!=yh)||(x != xh)||(w != wh)||(h != hh)||(exposed & 1))
788 yh = y;
789 xh = x;
790 wh = w;
791 hh = h;
792 XClearArea(dpy,main_win,PAD_WIDTH3+SCROLL_BAR_WIDTH,y,
793 Width-BAR_WIDTH-PAD_WIDTH3-2*SCROLL_BAR_WIDTH,h,False);
794 RelieveRectangle(dpy, main_win, x, y, w - 1, h - 1,
795 hiliteGC, shadowGC, 2);
797 if(exposed& 1)
799 RelieveRectangle(dpy, main_win, PAD_WIDTH2, y - 2,
800 Width - BAR_WIDTH - PAD_WIDTH2 + 1, h + 2,
801 shadowGC, hiliteGC, 2);
803 if(exposed)
805 if(motion == LEFT)
806 RedrawLeftButton(shadowGC,hiliteGC,PAD_WIDTH3,y);
807 else
808 RedrawLeftButton(hiliteGC,shadowGC,PAD_WIDTH3,y);
809 if(motion ==RIGHT)
810 RedrawRightButton(shadowGC,hiliteGC,
811 Width-BAR_WIDTH-SCROLL_BAR_WIDTH,y);
812 else
813 RedrawRightButton(hiliteGC,shadowGC,
814 Width-BAR_WIDTH-SCROLL_BAR_WIDTH,y);
817 if(exposed)
819 XClearArea(dpy,main_win,Width-BAR_WIDTH+2,
820 Height-BAR_WIDTH+2,BAR_WIDTH-3,BAR_WIDTH-3,False);
821 if(motion == QUIT)
822 RelieveRectangle(dpy, main_win, Width - SCROLL_BAR_WIDTH - PAD_WIDTH2 - 4,
823 Height - SCROLL_BAR_WIDTH - PAD_WIDTH2 - 4,
824 SCROLL_BAR_WIDTH + 3, SCROLL_BAR_WIDTH + 3,
825 shadowGC, hiliteGC, 2);
826 else
827 RelieveRectangle(dpy, main_win, Width - SCROLL_BAR_WIDTH - PAD_WIDTH2 - 4,
828 Height - SCROLL_BAR_WIDTH - PAD_WIDTH2 - 4,
829 SCROLL_BAR_WIDTH + 3,SCROLL_BAR_WIDTH + 3,
830 hiliteGC, shadowGC, 2);
832 exposed = 0;
837 * Change the window name displayed in the title bar.
839 void change_window_name(char *str)
841 XTextProperty name;
843 if(str == NULL)
844 return;
846 if (XStringListToTextProperty(&str,1,&name) == 0)
848 fprintf(stderr,"%s: cannot allocate window name\n",module->name);
849 return;
851 XSetWMName(dpy,main_win,&name);
852 XFree(name.value);
857 * Change the window name displayed in the icon.
859 void change_icon_name(char *str)
861 XTextProperty name;
863 if(str == NULL)
864 return;
865 if (XStringListToTextProperty(&str,1,&name) == 0)
867 fprintf(stderr,"%s: cannot allocate window name\n",module->name);
868 return;
870 XSetWMIconName(dpy,main_win,&name);
871 XFree(name.value);
875 void GrabWindow(Window target)
877 char *temp;
878 Window Junk,root;
879 unsigned int tw,th,border_width,depth;
880 int x,y;
881 char *prop = NULL;
882 Atom actual = None;
883 int actual_format;
884 unsigned long nitems, bytesafter;
886 XUnmapWindow(dpy,target);
887 XSync(dpy,0);
888 if (!XGetGeometry(dpy,target,&root,&x,&y,
889 (unsigned int *)&tw,(unsigned int *)&th,
890 (unsigned int *)&border_width,
891 (unsigned int *)&depth))
893 fprintf(stderr,"%s: cannot get window geometry\n", module->name);
894 exit(0);
896 XSync(dpy,0);
898 XTranslateCoordinates(dpy, target, Root, 0, 0, &x,&y, &Junk);
900 CreateWindow(x,y,tw,th);
901 XSetWindowBorderWidth(dpy,target,0);
902 XReparentWindow(dpy,target, holder_win,0,0);
903 XMapWindow(dpy,target);
904 XSelectInput(dpy,target, PropertyChangeMask|StructureNotifyMask);
905 if(XFetchName(dpy, target, &temp)==0)
906 temp = NULL;
907 if (XGetWindowProperty (dpy,
908 target, XA_WM_ICON_NAME, 0L,
909 (long)MAX_ICON_NAME_LEN, False, XA_STRING,
910 &actual,&actual_format, &nitems,
911 &bytesafter, (unsigned char **) &prop)
912 == Success && (prop != NULL))
914 change_icon_name(prop);
915 XFree(prop);
917 change_window_name(temp);
919 XWMHints *wmhints;
921 wmhints = XGetWMHints(dpy,target);
922 if(wmhints != NULL)
924 XSetWMHints(dpy,main_win, wmhints);
925 XFree(wmhints);
928 /* FvwmScroll may not share the same visual as the target window
929 * and so cannot share its colormap {
930 XWindowAttributes xwa;
931 if(XGetWindowAttributes(dpy,target, &xwa) != 0)
933 XSetWindowColormap(dpy,main_win,xwa.colormap);
937 XMapWindow(dpy,main_win);
938 RedrawWindow(target);
939 XFree(temp);
946 void RedrawLeftButton(GC rgc, GC sgc,int x1,int y1)
948 XSegment seg[4];
949 int i=0;
951 seg[i].x1 = x1+1; seg[i].y1 = y1+SCROLL_BAR_WIDTH/2;
952 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+1;
954 seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH/2;
955 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1;
956 XDrawSegments(dpy, main_win, rgc, seg, i);
958 i = 0;
959 seg[i].x1 = x1+1; seg[i].y1 =y1+ SCROLL_BAR_WIDTH/2;
960 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 =y1+ SCROLL_BAR_WIDTH - 2;
962 seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH/2;
963 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
965 seg[i].x1 = x1+SCROLL_BAR_WIDTH - 2; seg[i].y1 = y1+1;
966 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
968 seg[i].x1 = x1+SCROLL_BAR_WIDTH - 1; seg[i].y1 = y1;
969 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
970 XDrawSegments(dpy,main_win, sgc, seg, i);
973 void RedrawRightButton(GC rgc, GC sgc,int x1,int y1)
975 XSegment seg[4];
976 int i=0;
978 seg[i].x1 = x1+1; seg[i].y1 = y1+1;
979 seg[i].x2 = x1+1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
981 seg[i].x1 = x1; seg[i].y1 = y1;
982 seg[i].x2 = x1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
984 seg[i].x1 = x1+1; seg[i].y1 = y1+1;
985 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2;
987 seg[i].x1 = x1; seg[i].y1 = y1;
988 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2;
990 XDrawSegments(dpy, main_win, rgc, seg, i);
992 i = 0;
993 seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 2;
994 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2;
996 seg[i].x1 = x1; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 1;
997 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH/2;
998 XDrawSegments(dpy,main_win, sgc, seg, i);
1001 void RedrawTopButton(GC rgc, GC sgc,int x1,int y1)
1003 XSegment seg[4];
1004 int i=0;
1006 seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1+1;
1007 seg[i].x2 = x1+1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
1009 seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1;
1010 seg[i].x2 = x1+0; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
1011 XDrawSegments(dpy, main_win, rgc, seg, i);
1013 i = 0;
1014 seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1+1;
1015 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
1017 seg[i].x1 = x1+SCROLL_BAR_WIDTH/2; seg[i].y1 = y1;
1018 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
1020 seg[i].x1 = x1+1; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 2;
1021 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
1023 seg[i].x1 = x1+0; seg[i].y1 = y1+SCROLL_BAR_WIDTH - 1;
1024 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
1025 XDrawSegments(dpy,main_win, sgc, seg, i);
1028 void RedrawBottomButton(GC rgc, GC sgc,int x1, int y1)
1030 XSegment seg[4];
1031 int i=0;
1033 seg[i].x1 = x1+1; seg[i].y1 = y1+1;
1034 seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
1036 seg[i].x1 = x1; seg[i].y1 = y1+0;
1037 seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
1039 seg[i].x1 = x1+1; seg[i].y1 = y1+1;
1040 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 2; seg[i++].y2 = y1+1;
1042 seg[i].x1 = x1; seg[i].y1 = y1+0;
1043 seg[i].x2 = x1+SCROLL_BAR_WIDTH - 1; seg[i++].y2 = y1+0;
1044 XDrawSegments(dpy,main_win, rgc, seg, i);
1046 i = 0;
1047 seg[i].x1 = x1+SCROLL_BAR_WIDTH - 2; seg[i].y1 = y1+1;
1048 seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 2;
1050 seg[i].x1 = x1+SCROLL_BAR_WIDTH - 1; seg[i].y1 = y1+0;
1051 seg[i].x2 = x1+SCROLL_BAR_WIDTH/2; seg[i++].y2 = y1+SCROLL_BAR_WIDTH - 1;
1052 XDrawSegments(dpy, main_win, sgc, seg, i);