Fix CursorMove command to correctly honour EdgeScroll settings.
[fvwm.git] / modules / FvwmDragWell / fvwmDragWell.c
blobde64ff7903cb79ac8c26f871614459777f90861e
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "config.h"
28 #ifdef HAVE_SYS_BSDTYPES_H
29 #include <sys/bsdtypes.h> /* Saul */
30 #endif
32 #include <stdio.h>
33 #include <signal.h>
34 #include <fcntl.h>
35 #include <sys/wait.h>
36 #include "libs/ftime.h"
37 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <ctype.h>
42 #include <X11/Xlib.h>
43 #include <X11/keysym.h>
45 #include <X11/Xutil.h>
46 #include <X11/Xproto.h>
47 #include <X11/Xatom.h>
48 #include <X11/Intrinsic.h>
50 #include "libs/fvwmlib.h"
51 #include "libs/FShape.h"
52 #include "libs/Module.h"
53 #include "libs/Colorset.h"
54 #include "libs/PictureBase.h"
55 #include "libs/fvwmsignal.h"
56 #include "libs/FScreen.h"
57 #include "libs/FRenderInit.h"
58 #include "libs/ColorUtils.h"
59 #include "libs/Graphics.h"
60 #include "libs/Parse.h"
61 #include "libs/Strings.h"
62 #include "libs/System.h"
64 #include "fvwmDragWell.h"
65 #include "dragSource.h"
67 #define hostnameStrLen 64
69 extern DragSource dsg;
70 extern void xdndInit(Display *, Window);
71 extern void dragSourceInit(DragSource *,Display *,Window,Window);
73 void XStartup(char *appName);
74 void veryLongLoop(void);
75 char *shuffleDown(char **,short *,int,int);
76 int shrinkList(char **,short *,int,int);
77 int dilateList(char **,short *,int,int);
78 void changeWindowName(Window, char *);
79 void readHistory(void);
80 void writeHistory(void);
81 int dummy(DragWellButton *);
82 void createRootMenu(void);
83 void flushHistory(void);
84 void getReliefColors(void);
85 void createBackground(void);
86 void createWindow(void);
87 void parseOptions(void);
88 void parseFvwmMessage(char *msg);
89 int myXNextEvent(XEvent *event, char *fvwmMessage);
90 Atom xdndSrcDoDrag(DragSource *ds, Window srcWin, Atom action,
91 Atom * typelist);
92 void dragSrcInit(DragSource *ds,Display *dpy,Window root,Window client);
93 static RETSIGTYPE TerminateHandler(int);
95 int fd[2]; /*used for reading .fvwm2rc options*/
96 /*fd[0] module2fvwm*/
97 /*fd[1] fvwm2module*/
98 XGlobals xg; /*X related globals*/
99 DragWellMenuGlobals mg; /*menu related globals */
100 DragWellButton dragBut; /*not really used as a button but rather a drag well*/
101 char dropData[MAX_PATH_LEN]; /*data used for the drop*/
102 Bool Swallowed = False;
104 /* Don't know what this does yet...*/
105 void deadPipe(int nonsense)
107 /*writeHistory();*/
108 exit(0);
114 #ifdef DRAW_KILLBUTTON
115 /* drawX - draws an "x" on a button
116 * Dimension (w-8,h-8), roughly centered
117 * Arguments:
118 * but - the button to draw upon
120 int drawX(DragWellButton *but)
122 /*upper left to bottom right*/
123 XDrawLine(xg.dpy, but->win, xg.antiReliefGC, but->wx+4, but->wy+4,
124 but->wx+but->w-4,but->wy+but->h-4);
125 /*bottom left to upper right*/
126 XDrawLine(xg.dpy, but->win, xg.antiReliefGC, but->wx+4, but->wy+but->h-5,
127 but->wx+but->w-5,but->wy+4);
129 #endif
133 int main(int argc, char **argv)
135 Window app_win;
137 fd[MODULE_TO_FVWM] = atoi (argv[1]); /*used to get info from .fvwm2rc*/
138 fd[FVWM_TO_MODULE] = atoi (argv[2]);
140 sscanf (argv[4], "%x", (unsigned int *)&app_win);
142 /*dsg.mfsErr = fopen("/tmp/mfsErr","w");*/
144 XStartup(argv[0]); /*initializes variables*/
145 veryLongLoop(); /*event loop*/
147 return 0;
153 /* initDragWellButton - initializes a DragWellButton
154 * Doesn't return anything useful
155 * Arguments:
156 * but - the button to be initialized
157 * win - the window the button is drawn on
158 * x,y - the upper left corner of the button, in (Window win) coords.
159 * drawFunc - a function pointer for drawing something on the button
161 void initDragWellButton(DragWellButton *but,Window win, int x, int y, int w,
162 int h, int (*drawFunc)(DragWellButton *))
164 but->win = win;
165 but->wx = x;
166 but->wy = y;
167 but->w = w;
168 but->h = h;
169 but->state = DRAGWELL_BUTTON_NOT_PUSHED;
170 but->drawButFace = drawFunc;
175 /* drawDragWellButton - draws a DragWellButton
176 * Doesn't return anything meaningful
177 * Arguments:
178 * but - the button to be drawn
180 void drawDragWellButton(DragWellButton *but)
182 (*(but->drawButFace))(but); /*draws face of button*/
183 if (but->state==DRAGWELL_BUTTON_NOT_PUSHED)
184 RelieveRectangle(xg.dpy, but->win, but->wx, but->wy, but->w - 1, but->h - 1,
185 xg.hiliteGC, xg.shadowGC, 2);
186 else
187 RelieveRectangle(xg.dpy, but->win, but->wx, but->wy, but->w - 1, but->h - 1,
188 xg.shadowGC, xg.hiliteGC, 2);
193 /* mouseInButton - returns true if the pointer is in a DragWellButton
194 * returns 1 if in button and 0 otherwise.
195 * Arguments:
196 * but - the button to be drawn
197 * x,y - the pointer coords in (DragWellButton->win) coords
199 int mouseInButton(DragWellButton *but, int x, int y)
201 if ((but->wx <=x)&&(x<=(but->wx+but->w)))
202 if ((but->wy <=y)&&(y<=(but->wy+but->h)))
203 return 1;
204 return 0;
209 /*dragwellAnimate - does an animation in the dragwell
210 * Does not return anything useful */
211 void dragwellAnimate(void)
213 int i;
214 int sleepTime;
215 /*only one animation type for now*/
216 switch (xg.animationType) {
217 case DEFAULT_ANIMATION:
218 /*animate*/
219 if (dragBut.state == DRAGWELL_BUTTON_PUSHED)
220 XClearArea(xg.dpy,xg.win,xg.dbx+2,xg.dby+2,xg.dbw-2,xg.dbh-2,False);
221 else
222 XFillRectangle(
223 xg.dpy,xg.win,xg.buttonGC,xg.dbx+2,xg.dby+2,xg.dbw-2,xg.dbh-2);
224 /*This way, the animation time is constant regardless of size of
225 * box(assuming drawing is instantaneous...*/
226 sleepTime = TOTAL_ANIMATION_TIME/(xg.dbh-3);
227 for (i=xg.dby+xg.dbh-2;i>xg.dby;i--) {
228 if (dragBut.state == DRAGWELL_BUTTON_PUSHED)
229 XFillRectangle(
230 xg.dpy,xg.win,xg.buttonGC,xg.dbx+2,i,xg.dbw-3,xg.dby+xg.dbh-1-i);
231 else
232 XClearArea(xg.dpy,xg.win,xg.dbx+2,i,xg.dbw-3,xg.dby+xg.dbh-1-i,False);
233 XFlush(xg.dpy);
234 usleep(sleepTime);
236 drawDragWellButton(&dragBut);
237 break;
242 /* Main event loop*/
243 void veryLongLoop(void)
245 int x,y;
246 XEvent xev;
247 char fvwmMessage[512];
248 int eventType;
250 initDragWellButton(&dragBut,xg.win,xg.dbx,xg.dby,xg.dbw,xg.dbh,dummy);
251 dragBut.state = DRAGWELL_BUTTON_NOT_PUSHED;
252 drawDragWellButton(&dragBut);
254 while (!isTerminated)
256 /*get next event*/
257 if ((eventType=myXNextEvent (&xev,fvwmMessage))==FOUND_XEVENT)
259 /* we have a X event*/
260 switch(xev.type) {
261 case ButtonPress:
262 x = xev.xbutton.x;
263 y = xev.xbutton.y;
264 if (mg.dragState == DRAGWELLMENU_HAVE_DRAG_ITEM) {
265 if (mouseInButton(&dragBut,x,y)) {
266 if (mg.dragDataType==DRAG_DATA_TYPE_PATH)
267 mg.typelist[0] = mg.textUriAtom;
268 else
269 mg.typelist[0] = XInternAtom(xg.dpy,mg.dragTypeStr,False);
270 xdndSrcDoDrag(&dsg,xg.win,mg.action,mg.typelist);
273 break;
274 case ClientMessage:
275 /*close window option */
276 if ((xev.xclient.format==32) &&
277 (xev.xclient.data.l[0]==xg.wmAtomDelWin))
278 deadPipe(1);
279 break;
280 case Expose:
281 drawDragWellButton(&dragBut); /*draws the drag icon*/
282 break;
283 case ConfigureNotify:
284 if (xg.colorset >= 0 && Colorset[xg.colorset].pixmap == ParentRelative)
285 XClearArea(xg.dpy, xg.win, 0,0,0,0, True);
286 break;
288 } else if (eventType==FOUND_FVWM_MESSAGE) { /* we have an fvwm message */
289 /* two cases, one where item is a file, other where we have a subdir */
290 parseFvwmMessage(fvwmMessage);
291 dragwellAnimate();
292 } else {
293 /* no window*/
294 /* deadPipe(0);*/
301 /* parseFvwmMessage - decodes a SendToModule command.
302 * Arguments:
303 * msg - the fvwm message
304 * sets dragBut.state */
306 static char *dragopts[] = {
307 "DragType",
308 "DragData"
311 void parseFvwmMessage(char *msg)
313 char *dragtype = NULL, *dragData = NULL;
314 char *optString, *option, *args;
315 char hostname[hostnameStrLen];
317 /* parse line into comma separated pieces, set dragtype and dragdata */
318 while (msg && *msg) {
319 msg = GetQuotedString(msg, &optString, ",", NULL, NULL, NULL);
320 if (!optString)
321 break;
322 args = GetNextToken(optString, &option);
323 if (!option) {
324 free(optString);
325 break;
327 switch(GetTokenIndex(option, dragopts, 0, NULL))
329 case 0:
330 CopyString(&dragtype, args);
331 break;
332 case 1:
333 CopyString(&dragData, args);
334 break;
336 if (option) {
337 free(option);
338 option = NULL;
340 free(optString);
341 optString = NULL;
344 if (dragtype != NULL) {
345 strcpy(mg.dragTypeStr,dragtype);
346 mg.dragDataType = DRAG_DATA_TYPE_NONPATH;
347 } else {
348 mg.dragDataType = DRAG_DATA_TYPE_PATH;
349 strcpy(mg.dragTypeStr,"text/uri-list");
352 if (dragData == NULL || *dragData == 0) {
353 mg.dragState = DRAGWELLMENU_NO_DRAG_ITEM;
354 dragBut.state = DRAGWELL_BUTTON_NOT_PUSHED;
355 } else {
356 mg.dragState = DRAGWELLMENU_HAVE_DRAG_ITEM;
357 strcpy(mg.dragData, dragData);
358 dragBut.state = DRAGWELL_BUTTON_PUSHED;
361 /*setup a drag*/
362 if (mg.dragState == DRAGWELLMENU_HAVE_DRAG_ITEM) {
363 if (mg.dragDataType == DRAG_DATA_TYPE_PATH) {
364 strcpy(dropData, "file://");
365 gethostname(hostname, hostnameStrLen);
366 strcat(dropData, hostname);
367 strcat(dropData, mg.dragData);
368 } else {
369 strcpy(dropData, mg.dragData);
376 * TerminateHandler - signal handler to make FvwmIconBox exit cleanly
378 static RETSIGTYPE
379 TerminateHandler(int sig)
382 * This function might not return - it could "long-jump"
383 * right out, so we need to do everything we need to do
384 * BEFORE we call it ...
386 fvwmSetTerminate(sig);
387 SIGNAL_RETURN;
393 /* XStartup - sets up the X and menu state. Return value is meaningless.
394 * Arguments:
395 * appName - the name of the application.
397 void XStartup(char *appName)
399 char *appNameStart;
401 /*setup exit stuff*/
402 #ifdef HAVE_SIGACTION
403 struct sigaction sigact;
405 #ifdef SA_INTERRUPT
406 sigact.sa_flags = SA_INTERRUPT;
407 #else
408 sigact.sa_flags = 0;
409 #endif
410 sigemptyset(&sigact.sa_mask);
411 sigaddset(&sigact.sa_mask, SIGPIPE);
412 sigaddset(&sigact.sa_mask, SIGTERM);
413 sigaddset(&sigact.sa_mask, SIGINT);
414 sigact.sa_handler = TerminateHandler;
416 sigaction(SIGPIPE, &sigact, NULL);
417 sigaction(SIGTERM, &sigact, NULL);
418 sigaction(SIGINT, &sigact, NULL);
419 #else
421 * No sigaction, so fall back onto standard and unreliable signals
423 #ifdef USE_BSD_SIGNALS
424 fvwmSetSignalMask( sigmask(SIGPIPE) | sigmask(SIGTERM) | sigmask(SIGINT) );
425 #endif
426 signal(SIGPIPE, TerminateHandler);
427 signal(SIGTERM, TerminateHandler);
428 signal(SIGINT, TerminateHandler);
429 #ifdef HAVE_SIGINTERRUPT
430 siginterrupt(SIGPIPE, 1);
431 siginterrupt(SIGTERM, 1);
432 siginterrupt(SIGINT, 1);
433 #endif
434 #endif
436 memset(&xg, 0, sizeof(xg));
437 if (!(xg.dpy = XOpenDisplay (NULL))) {
438 fprintf (stderr, "%s: can't open display %s",xg.appName,
439 XDisplayName (NULL));
440 exit (1);
443 /*xg.log = fopen("/home/straub/Work/C++/Xdnd/fvwm-snap-19990906/modules/FvwmDragWell/qfs.log","w");*/
444 /*Name the starting window name to the invocation name*/
445 appNameStart = strrchr(appName,'/')+1; /*remove the path from the name*/
446 if (appNameStart == NULL) {
447 appNameStart = appName;
450 xg.appName = (char *) malloc(sizeof(char) * (strlen(appNameStart)+1));
451 strcpy(xg.appName,appNameStart); /*save the name of the application*/
452 flib_init_graphics(xg.dpy);
454 /*get X stuff*/
455 xg.xfd = XConnectionNumber(xg.dpy);
456 xg.fdWidth = GetFdWidth();
458 xg.screen = DefaultScreen(xg.dpy);
459 xg.root = RootWindow(xg.dpy,xg.screen);
460 xg.dpyDepth = DefaultDepth(xg.dpy, xg.screen);
461 xg.dpyHeight = DisplayHeight(xg.dpy,xg.screen);
462 xg.dpyWidth = DisplayWidth(xg.dpy,xg.screen);
463 xg.dbx = 9;
464 xg.dby = 9;
465 xg.dbw = 30;
466 xg.dbh = 30;
467 xg.w = 48;
468 xg.h = 48;
469 /*Setup defaults*/
470 mg.exportAsURL = True;
471 mg.fontname = NULL;
472 xg.foreColorStr = NULL;
473 xg.backColorStr = NULL;
474 xg.shadowColorStr = NULL;
475 xg.hiliteColorStr = NULL;
476 xg.colorset = -1; /*no colorset*/
477 parseOptions(); /*overide defaults from .fvwm2rc*/
478 if (xg.foreColorStr==NULL)
479 CopyString(&xg.foreColorStr,"grey60");
480 if (xg.backColorStr==NULL)
481 CopyString(&xg.backColorStr,"black");
482 if (xg.shadowColorStr==NULL)
483 CopyString(&xg.shadowColorStr,"grey20");
484 if (xg.hiliteColorStr==NULL)
485 CopyString(&xg.hiliteColorStr,"grey90");
486 getReliefColors();
487 createWindow();
488 createBackground();
490 mg.dragState = DRAGWELLMENU_NO_DRAG_ITEM;
491 /*more initialization menu stuff, using font info*/
492 /*mg.fontHeight = mg.font->max_bounds.ascent + mg.font->max_bounds.descent;*/
494 xdndInit(xg.dpy, xg.root);
495 dragSrcInit(&dsg,xg.dpy,xg.root,xg.win);
497 mg.action = dsg.atomSel->xdndActionMove;
498 mg.textUriAtom = XInternAtom(xg.dpy,"text/uri-list",False);
499 mg.typelist = (Atom *) malloc(4*sizeof(Atom));
500 mg.typelist[1] = None;
501 mg.typelist[2] = None;
502 mg.typelist[3] = 0;
503 xg.animationType = DEFAULT_ANIMATION;
505 /* tell fvwm we're running */
506 SendFinishedStartupNotification(fd);
511 /*getReliefColors - sets up the colors for the dragwell
512 *Arguments:*/
513 void getReliefColors(void) {
514 if(xg.dpyDepth < 2) {
515 /*for mono display, not well implemented...*/
516 xg.fore = GetColor("white");
517 xg.back = GetColor("black");
518 xg.hilite = xg.fore;
519 xg.shadow = xg.back;
520 } else if (xg.colorset >=0) { /*using a colorset*/
521 xg.hilite = Colorset[xg.colorset].hilite;
522 xg.shadow = Colorset[xg.colorset].shadow;
523 xg.fore = Colorset[xg.colorset].fg;
524 xg.back = Colorset[xg.colorset].bg;
525 } else { /*no colorset*/
526 xg.fore = GetColor(xg.foreColorStr);
527 xg.back = GetColor(xg.backColorStr);
528 xg.shadow = GetColor(xg.shadowColorStr);
529 xg.hilite = GetColor(xg.hiliteColorStr);
535 /* createBackground - sets the background of the dragwell window
536 * Arguments:*/
537 void createBackground(void) {
538 unsigned long gcm;
539 XGCValues gcv;
540 /*Graphic context stuff*/
541 gcm = GCForeground|GCBackground|GCSubwindowMode;
542 gcv.subwindow_mode = IncludeInferiors;
544 gcv.foreground = xg.hilite;
545 gcv.background = xg.back;
546 xg.hiliteGC = fvwmlib_XCreateGC(xg.dpy, xg.win, gcm, &gcv);
548 gcv.foreground = xg.shadow;
549 gcv.background = xg.back;
550 xg.shadowGC = fvwmlib_XCreateGC(xg.dpy, xg.win, gcm, &gcv);
552 gcv.foreground = xg.fore;
553 gcv.background = xg.back;
554 xg.buttonGC = fvwmlib_XCreateGC(xg.dpy, xg.win, gcm, &gcv);
556 if (xg.colorset >=0) /*colorset*/
557 SetWindowBackground(xg.dpy, xg.win, xg.w, xg.h, &Colorset[xg.colorset],
558 Pdepth, xg.buttonGC, False);
559 else /*just use background pixel*/
560 XSetWindowBackground(xg.dpy, xg.win, xg.back);
565 /* parseOptions - loads in options from the .fvwm2rc file.
566 * Arguments: */
567 void parseOptions(void)
569 char *token,*next,*tline=NULL,*tline2,*resource;
570 char *arg1,*arg2;
572 /* loop that parses through the .fvwm2rc line by line.*/
573 for (GetConfigLine(fd,&tline); tline != NULL; GetConfigLine(fd,&tline)) {
574 tline2 = GetModuleResource(tline, &resource, xg.appName);
575 if (!resource) {/*not a xg.appName resource(*FvwmDragWell) resource*/
576 token = PeekToken(tline, &next);
577 if (StrEquals(token, "Colorset")) {
578 LoadColorset(next);
580 else if (StrEquals(token, XINERAMA_CONFIG_STRING)) {
581 FScreenConfigureModule(next);
583 continue;
585 tline2 = GetNextToken(tline2, &arg1);
586 if (!arg1)
588 arg1 = (char *)safemalloc(1);
589 arg1[0] = 0;
591 tline2 = GetNextToken(tline2, &arg2);
592 if (!arg2)
594 arg2 = (char *)safemalloc(1);
595 arg2[0] = 0;
599 if (StrEquals(resource, "ExportAsURL")) {
600 if (StrEquals(arg1,"True"))
601 mg.exportAsURL = True;
602 else
603 mg.exportAsURL = False;
604 } else if (StrEquals(resource, "Font")) {
605 CopyString(&mg.fontname,arg1);
606 } else if (StrEquals(resource, "Fore")) {
607 CopyString(&xg.foreColorStr,arg1);
608 } else if (StrEquals(resource, "Back")) {
609 CopyString(&xg.backColorStr,arg1);
610 } else if (StrEquals(resource, "Shadow")) {
611 CopyString(&xg.shadowColorStr,arg1);
612 } else if (StrEquals(resource, "Hilite")) {
613 CopyString(&xg.hiliteColorStr,arg1);
614 } else if (StrEquals(resource, "Colorset")) {
615 sscanf(arg1, "%d", &xg.colorset);
616 AllocColorset(xg.colorset);
617 } else if (StrEquals(resource, "Geometry")) {
618 int g_x,g_y,flags;
619 unsigned width,height;
620 xg.w = 48;
621 xg.h = 48;
622 xg.x = 0;
623 xg.y = 0;
624 xg.xneg = 0;
625 xg.yneg = 0;
626 xg.usposition = 0;
627 flags = FScreenParseGeometry(arg1,&g_x,&g_y,&width,&height);
628 if (flags & WidthValue) {
629 xg.w = width;
631 if (flags & HeightValue) {
632 xg.h= height;
634 if (flags & XValue) {
635 xg.x = g_x;
636 xg.usposition = 1;
638 if (flags & YValue) {
639 xg.y = g_y;
640 xg.usposition = 1;
642 if (flags & XNegative) {
643 xg.xneg = 1;
645 if (flags & YNegative) {
646 xg.yneg = 1;
648 } else if (StrEquals(resource, "DragWellGeometry")) {
649 int g_x,g_y,flags;
650 unsigned width,height;
651 xg.dbw = 30;
652 xg.dbh = 30;
653 xg.dbx = 9;
654 xg.dby = 9;
655 flags = FScreenParseGeometry(arg1,&g_x,&g_y,&width,&height);
656 if (flags & WidthValue) {
657 xg.dbw = width;
659 if (flags & HeightValue) {
660 xg.dbh= height;
662 if (flags & XValue) {
663 xg.dbx = g_x;
665 if (flags & YValue) {
666 xg.dby = g_y;
669 free(resource);
670 free(arg1);
671 free(arg2);
674 #ifdef USE_UNUSED
675 if (!mg.nw) {
676 /*Allocate font here because we need size information to create the main menu*/
677 if (mg.fontname==NULL) {
678 mg.fontname =
679 (char *) malloc(sizeof(char)*(strlen("-adobe-helvetica-bold-r-*-*-10-*-*-*-*-*-*-*")+1));
680 strcpy(mg.fontname,"-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*");
682 mg.font = XLoadQueryFont(xg.dpy,mg.fontname);
683 if (mg.font == NULL) {
684 fprintf(stderr,"FvwmDragWell:No font located. Exiting\n");
685 exit(1);
688 #endif
694 /* changeWindowName - change the window name displayed in the title bar.
695 * Arguments:
696 * win - the window
697 * str - the new name of the window
699 void changeWindowName(Window win, char *str)
701 XTextProperty name;
703 if (XStringListToTextProperty(&str,1,&name) == 0)
705 fprintf(stderr,"%s: cannot allocate window name",str);
706 return;
708 XSetWMName(xg.dpy,win,&name);
709 XSetWMIconName(xg.dpy,win,&name);
710 XFree(name.value);
715 /*change_colorset - changes the background of wharf
716 *Arguments:
717 * colorset - the new colorset */
718 static void change_colorset(int colorset)
720 if (colorset == xg.colorset && colorset >= 0)
722 /* update GCs */
723 XFreeGC(xg.dpy, xg.buttonGC);
724 XFreeGC(xg.dpy, xg.shadowGC);
725 XFreeGC(xg.dpy, xg.hiliteGC);
727 /* update background pixmap */
728 getReliefColors();
729 createBackground();
730 XClearWindow(xg.dpy,xg.win);
731 drawDragWellButton(&dragBut); /*draws the drag icon*/
733 XSync(xg.dpy, 0);
734 return;
742 * myXNextEvent - waits for the next event, which is either an XEvent,
743 * or an fvwm event.
744 * Arguements:
745 * event - the XEvent that is possibly found.
746 * fvwmMessage - the FvwmMessage that is possibly found.
747 * Returns FOUND_XEVENT if a XEvent was found.
748 * Returns FOUND_FVWM_MESSAGE if a fvwm M_STRING packet was found.
749 * Returns FOUND_NON_FVWM_MESSAGE for any other fvwm packet type.
750 * Note that for fvwm packet type M_CONFIG(colorset), it updates the
751 * colorset
752 * Borrowed from FvwmPager
754 int myXNextEvent(XEvent *event, char *fvwmMessage)
756 fd_set in_fdset;
757 static int miss_counter = 0;
758 char *msg, *tline, *token;
759 unsigned long *lptr;
760 int colorset;
761 if(FPending(xg.dpy)) /*look for an X event first*/
763 FNextEvent(xg.dpy,event); /*got an X event*/
764 return FOUND_XEVENT;
767 FD_ZERO(&in_fdset);
768 FD_SET(xg.xfd,&in_fdset); /*look for x events*/
769 FD_SET(fd[1],&in_fdset); /*look for fvwm events*/
770 if (select(xg.fdWidth,SELECT_FD_SET_CAST &in_fdset, 0, 0, NULL) > 0) /*wait */
772 if(FD_ISSET(xg.xfd, &in_fdset))
774 if(FPending(xg.dpy))
776 FNextEvent(xg.dpy,event); /*get an X event*/
777 miss_counter = 0;
778 return FOUND_XEVENT;
780 miss_counter++;
781 #ifdef WORRY_ABOUT_MISSED_XEVENTS
782 if(miss_counter > 100)
784 deadPipe(0);
786 #endif
789 if(FD_ISSET(fd[1], &in_fdset))
791 FvwmPacket* packet = ReadFvwmPacket(fd[1]);
792 /*packet format defined in libs/Module.h*/
793 if ( packet == NULL )
795 exit(0);
797 else
799 if (packet->type==M_CONFIG_INFO)
801 tline = (char*)&(packet->body[3]);
802 token = PeekToken(tline, &tline);
803 if (StrEquals(token, "Colorset"))
805 /*colorset packet*/
806 colorset = LoadColorset(tline);
807 change_colorset(colorset);
809 else if (StrEquals(token, XINERAMA_CONFIG_STRING))
811 FScreenConfigureModule(tline);
813 return FOUND_FVWM_NON_MESSAGE;
815 else if (packet->type==M_STRING)
817 if (packet->size>3)
819 /* Note that "SendToModule" calls
820 * SendStrToModule(fvwm/module_interface.c)
821 * which seems to insert three pieces of data at the start of
822 * the body */
823 /* The quoting seems to be wrong in SendToModule */
824 /* Sending "SendToModule "FvwmDragWell" dragitem "stuff"
825 * yields [" dragitem "stuff"]*/
826 lptr = packet->body;
827 msg = (char *) &(lptr[3]);
828 strcpy(fvwmMessage,msg);
829 return FOUND_FVWM_MESSAGE;
831 else
833 return FOUND_FVWM_NON_MESSAGE;
836 else if (packet->type == MX_PROPERTY_CHANGE)
838 if (packet->body[0] == MX_PROPERTY_CHANGE_BACKGROUND &&
839 xg.colorset >= 0 &&
840 Colorset[xg.colorset].pixmap == ParentRelative &&
841 ((!Swallowed && packet->body[2] == 0) ||
842 (Swallowed && packet->body[2] == xg.win)))
844 XClearArea(xg.dpy, xg.win, 0,0,0,0, True);
846 else if (packet->body[0] == MX_PROPERTY_CHANGE_SWALLOW &&
847 packet->body[2] == xg.win)
849 Swallowed = packet->body[1];
851 return FOUND_FVWM_NON_MESSAGE;
854 else
856 return FOUND_FVWM_NON_MESSAGE;
861 return FOUND_FVWM_NON_MESSAGE;
865 /* dummy - used to draw the face of the dragwell button
866 * Arguments:
867 * but - the dragwell button
868 * Does not return anything useful.*/
869 int dummy(DragWellButton *but)
871 if (but->state==DRAGWELL_BUTTON_PUSHED)
872 XFillRectangle(xg.dpy,xg.win,xg.buttonGC,xg.dbx+2,xg.dby+2,xg.dbw-4,
873 xg.dbh-4);
874 return 0;
879 /*createWindow - creates the drag window.
880 * Arguments:*/
881 void createWindow(void)
883 unsigned long valuemask;
884 XSetWindowAttributes attributes;
886 xg.sizehints.min_width = 1;
887 xg.sizehints.min_height = 1;
888 xg.sizehints.width_inc = 1;
889 xg.sizehints.height_inc = 1;
890 xg.sizehints.base_width = xg.w;
891 xg.sizehints.base_height = xg.h;
892 xg.sizehints.win_gravity = NorthWestGravity;
893 xg.sizehints.flags = (PMinSize | PResizeInc | PBaseSize | PWinGravity);
894 if (xg.xneg)
896 xg.sizehints.win_gravity = NorthEastGravity;
897 xg.x = xg.dpyWidth + xg.x - xg.w;
899 if (xg.yneg)
901 xg.y = xg.dpyHeight + xg.y - xg.h;
902 if(xg.sizehints.win_gravity == NorthEastGravity)
903 xg.sizehints.win_gravity = SouthEastGravity;
904 else
905 xg.sizehints.win_gravity = SouthWestGravity;
907 if (xg.usposition)
909 xg.sizehints.flags |= USPosition;
910 /* hack to prevent mapping on wrong screen with StartsOnScreen */
911 FScreenMangleScreenIntoUSPosHints(FSCREEN_XYPOS, &xg.sizehints);
914 valuemask = (CWBackPixmap | CWBorderPixel| CWColormap);
915 attributes.background_pixel = xg.back;
916 attributes.border_pixel = xg.fore;
917 attributes.background_pixmap = None;
919 attributes.colormap = Pcmap;
920 attributes.event_mask = (StructureNotifyMask);
921 xg.win = XCreateWindow (xg.dpy, xg.root, xg.x, xg.y, xg.w,
922 xg.h, 0, Pdepth, InputOutput, Pvisual,
923 valuemask, &attributes);
925 /*_XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);*/
926 xg.wmAtomDelWin = XInternAtom(xg.dpy,"WM_DELETE_WINDOW",False);
927 XSetWMProtocols(xg.dpy,xg.win,&xg.wmAtomDelWin,1);
929 XSetWMNormalHints(xg.dpy,xg.win,&xg.sizehints);
931 changeWindowName(xg.win, xg.appName);
932 XSelectInput(xg.dpy, xg.win, MW_EVENTS);
933 XMapWindow(xg.dpy,xg.win);