/**************************************************************************** * This module is all new * by Rob Nation ****************************************************************************/ /*********************************************************************** * * fvwm pager handling code * ***********************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include "../../libs/fvwmlib.h" #include "../../fvwm/fvwm.h" #include "FvwmPager.h" extern ScreenInfo Scr; extern Display *dpy; Pixel back_pix, fore_pix, hi_pix; Pixel focus_pix; Pixel focus_fore_pix; extern Pixel win_back_pix, win_fore_pix, win_hi_back_pix, win_hi_fore_pix; extern int window_w, window_h,window_x,window_y,usposition,uselabel,xneg,yneg; extern int StartIconic; extern int MiniIcons; extern int ShowBalloons, ShowPagerBalloons, ShowIconBalloons; extern int icon_w, icon_h, icon_x, icon_y; XFontStruct *font, *windowFont; GC NormalGC,DashedGC,HiliteGC,rvGC; GC StdGC; GC MiniIconGC; GC BalloonGC; extern PagerWindow *Start; extern PagerWindow *FocusWin; static Atom wm_del_win; extern char *MyName; extern int desk1, desk2, ndesks; extern int Rows,Columns; extern int fd[2]; int desk_w = 0; int desk_h = 0; int label_h = 0; DeskInfo *Desks; int Wait = 0; XErrorHandler FvwmErrorHandler(Display *, XErrorEvent *); /* assorted gray bitmaps for decorative borders */ #define g_width 2 #define g_height 2 static char g_bits[] = {0x02, 0x01}; #define l_g_width 4 #define l_g_height 2 static char l_g_bits[] = {0x08, 0x02}; #define s_g_width 4 #define s_g_height 4 static char s_g_bits[] = {0x01, 0x02, 0x04, 0x08}; Window icon_win; /* icon window */ BalloonWindow balloon; /* balloon window */ /*********************************************************************** * * Procedure: * Initialize_pager - creates the pager window, if needed * * Inputs: * x,y location of the window * ***********************************************************************/ char *pager_name = "Fvwm Pager"; XSizeHints sizehints = { (PMinSize | PResizeInc | PBaseSize | PWinGravity), 0, 0, 100, 100, /* x, y, width and height */ 1, 1, /* Min width and height */ 0, 0, /* Max width and height */ 1, 1, /* Width and height increments */ {0, 0}, {0, 0}, /* Aspect ratio - not used */ 1, 1, /* base size */ (NorthWestGravity) /* gravity */ }; void initialize_pager(void) { XWMHints wmhints; XClassHint class1; XTextProperty name; unsigned long valuemask; XSetWindowAttributes attributes; extern char *PagerFore, *PagerBack, *HilightC; extern char *WindowBack, *WindowFore, *WindowHiBack, *WindowHiFore; extern char *BalloonFore, *BalloonBack, *BalloonFont; extern char *BalloonBorderColor; extern int BalloonBorderWidth, BalloonYOffset; extern char *font_string, *smallFont; int n,m,w,h,i,x,y; XGCValues gcv; unsigned long gcm; #if 1 /* I don't think that this is necessary - just let pager die */ /* domivogt (07-mar-1999): But it is! A window being moved in the pager * might die at any moment causing the Xlib calls to generate BadMatch * errors. Without an error handler the pager will die! */ XSetErrorHandler((XErrorHandler)FvwmErrorHandler); #endif /* 1 */ wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); /* load the font */ if (!uselabel || ((font = XLoadQueryFont(dpy, font_string)) == NULL)) { if ((font = XLoadQueryFont(dpy, "fixed")) == NULL) { fprintf(stderr,"%s: No fonts available\n",MyName); exit(1); } }; if(uselabel) label_h = font->ascent + font->descent+2; else label_h = 0; if(smallFont!= NULL) { windowFont= XLoadQueryFont(dpy, smallFont); } else windowFont= NULL; /* Load the colors */ fore_pix = GetColor(PagerFore); back_pix = GetColor(PagerBack); hi_pix = GetColor(HilightC); if (WindowBack && WindowFore && WindowHiBack && WindowHiFore) { win_back_pix = GetColor (WindowBack); win_fore_pix = GetColor (WindowFore); win_hi_back_pix = GetColor (WindowHiBack); win_hi_fore_pix = GetColor (WindowHiFore); } /* Load pixmaps for mono use */ if(Scr.d_depth<2) { Scr.gray_pixmap = XCreatePixmapFromBitmapData(dpy,Scr.Root,g_bits, g_width,g_height, fore_pix,back_pix,Scr.d_depth); Scr.light_gray_pixmap = XCreatePixmapFromBitmapData(dpy,Scr.Root,l_g_bits,l_g_width,l_g_height, fore_pix,back_pix,Scr.d_depth); Scr.sticky_gray_pixmap = XCreatePixmapFromBitmapData(dpy,Scr.Root,s_g_bits,s_g_width,s_g_height, fore_pix,back_pix,Scr.d_depth); } n = Scr.VxMax/Scr.MyDisplayWidth; m = Scr.VyMax/Scr.MyDisplayHeight; /* Size the window */ if(Rows < 0) { if(Columns < 0) { Columns = ndesks; Rows = 1; } else { Rows = ndesks/Columns; if(Rows*Columns < ndesks) Rows++; } } if(Columns < 0) { if (Rows == 0) Rows = 1; Columns = ndesks/Rows; if(Rows*Columns < ndesks) Columns++; } if(Rows*Columns < ndesks) { if (Columns == 0) Columns = 1; Rows = ndesks/Columns; if (Rows*Columns < ndesks) Rows++; } if(window_w > 0) { window_w = ((window_w - n)/(n+1))*(n+1)+n; Scr.VScale = Columns*(Scr.VxMax + Scr.MyDisplayWidth)/ (window_w-Columns+1-Columns*n); } if(window_h > 0) { window_h = ((window_h - m)/(m+1))*(m+1)+m; Scr.VScale = Rows*(Scr.VyMax + Scr.MyDisplayHeight)/ (window_h+2-Rows*(label_h -m-1)); } if(window_w <= 0) window_w = Columns*((Scr.VxMax + Scr.MyDisplayWidth)/Scr.VScale + n) + Columns-1; if(window_h <= 0) { window_h = Rows*((Scr.VyMax + Scr.MyDisplayHeight)/Scr.VScale + m + label_h + 1)-2; } if(xneg) { sizehints.win_gravity = NorthEastGravity; window_x = Scr.MyDisplayWidth - window_w + window_x -2; } if(yneg) { window_y = Scr.MyDisplayHeight - window_h + window_y -2; if(sizehints.win_gravity == NorthEastGravity) sizehints.win_gravity = SouthEastGravity; else sizehints.win_gravity = SouthWestGravity; } if(usposition) sizehints.flags |= USPosition; valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); attributes.background_pixel = back_pix; attributes.border_pixel = fore_pix; attributes.event_mask = (StructureNotifyMask); sizehints.width = window_w; sizehints.height = window_h; sizehints.x = window_x; sizehints.y = window_y; sizehints.width_inc = Columns*(n+1); sizehints.height_inc = Rows*(m+1); sizehints.base_width = Columns * n + Columns - 1; sizehints.base_height = Rows*(m + label_h+1) -2; sizehints.min_width = Columns * n + Columns - 1; sizehints.min_height = Rows*(m + label_h+1) -2; Scr.Pager_w = XCreateWindow (dpy, Scr.Root, window_x, window_y, window_w, window_h, (unsigned int) 1, CopyFromParent, InputOutput, (Visual *) CopyFromParent, valuemask, &attributes); XSetWMProtocols(dpy,Scr.Pager_w,&wm_del_win,1); XSetWMNormalHints(dpy,Scr.Pager_w,&sizehints); if((desk1==desk2)&&(Desks[0].label != NULL)) XStringListToTextProperty(&Desks[0].label,1,&name); else XStringListToTextProperty(&pager_name,1,&name); attributes.event_mask = (StructureNotifyMask| ExposureMask); if(icon_w < 1) icon_w = (window_w - Columns+1)/Columns; if(icon_h < 1) icon_h = (window_h - Rows* label_h - Rows + 1)/Rows; icon_w = (icon_w / (n+1)) *(n+1)+n; icon_h = (icon_h / (m+1)) *(m+1)+m; icon_win = XCreateWindow (dpy, Scr.Root, window_x, window_y, icon_w,icon_h, (unsigned int) 1, CopyFromParent, InputOutput, (Visual *) CopyFromParent, valuemask, &attributes); XGrabButton(dpy, 1, AnyModifier, icon_win, True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, None); XGrabButton(dpy, 2, AnyModifier, icon_win, True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, None); XGrabButton(dpy, 3, AnyModifier, icon_win, True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, None); if(!StartIconic) wmhints.initial_state = NormalState; else wmhints.initial_state = IconicState; wmhints.flags = 0; if(icon_x > -10000) { if(icon_x < 0) icon_x = Scr.MyDisplayWidth + icon_x - icon_w; if(icon_y > -10000) { if(icon_y < 0) icon_y = Scr.MyDisplayHeight + icon_y - icon_h; } else icon_y = 0; wmhints.icon_x = icon_x; wmhints.icon_y = icon_y; wmhints.flags = IconPositionHint; } wmhints.icon_window = icon_win; wmhints.input = False; wmhints.flags |= InputHint | StateHint | IconWindowHint; class1.res_name = MyName; class1.res_class = "FvwmModule"; XSetWMProperties(dpy,Scr.Pager_w,&name,&name,NULL,0, &sizehints,&wmhints,&class1); XFree((char *)name.value); for(i=0;ifid; NormalGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); MiniIconGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); gcv.foreground = hi_pix; if(Scr.d_depth < 2) { gcv.foreground = fore_pix; gcv.background = back_pix; } HiliteGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); if((Scr.d_depth < 2)||(fore_pix == hi_pix)) gcv.foreground = back_pix; else gcv.foreground = fore_pix; rvGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); if(windowFont != NULL) { /* Create GC's for doing window labels */ gcv.foreground = focus_fore_pix; gcv.background = focus_pix; gcv.font = windowFont->fid; StdGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); } gcm = gcm | GCLineStyle; gcv.foreground = fore_pix; gcv.background = back_pix; gcv.line_style = LineOnOffDash; DashedGC = XCreateGC(dpy, Scr.Root, gcm, &gcv); /* create balloon window -- ric@giccs.georgetown.edu */ if ( ShowBalloons ) { valuemask = CWOverrideRedirect | CWEventMask | CWBackPixel | CWBorderPixel; /* tell WM to ignore this window */ attributes.override_redirect = True; attributes.event_mask = ExposureMask; attributes.border_pixel = GetColor(BalloonBorderColor); /* if given in config set this now, otherwise it'll be set for each pager window when drawn later */ attributes.background_pixel = (BalloonBack == NULL) ? 0 : GetColor(BalloonBack); /* get font for balloon */ if ( (balloon.font = XLoadQueryFont(dpy, BalloonFont)) == NULL ) { if ( (balloon.font = XLoadQueryFont(dpy, "fixed")) == NULL ) { fprintf(stderr,"%s: No fonts available.\n", MyName); exit(1); } fprintf(stderr, "%s: Can't find font '%s', using fixed.\n", MyName, BalloonFont); } balloon.height = balloon.font->ascent + balloon.font->descent + 1; /* this may have been set in config */ balloon.border = BalloonBorderWidth; /* we don't allow yoffset of 0 because it allows direct transit from pager window to balloon window, setting up a LeaveNotify/EnterNotify event loop */ if ( BalloonYOffset ) balloon.yoffset = BalloonYOffset; else { fprintf(stderr, "%s: Warning: you're not allowed BalloonYOffset 0; defaulting to +2\n", MyName); balloon.yoffset = 2; } /* now create the window */ balloon.w = XCreateWindow(dpy, Scr.Root, 0, 0, /* coords set later */ 1, /* width set later */ balloon.height, balloon.border, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes); /* set font */ gcv.font = balloon.font->fid; /* if fore given in config set now, otherwise it'll be set later */ gcv.foreground = (BalloonFore == NULL) ? 0 : GetColor(BalloonFore); BalloonGC = XCreateGC(dpy, balloon.w, GCFont | GCForeground, &gcv); /* Make sure we don't get balloons initially with the Icon option. */ ShowBalloons = ShowPagerBalloons; } /* ShowBalloons */ } /**************************************************************************** * * Loads a single color * ****************************************************************************/ Pixel GetColor(char *name) { XColor color; XWindowAttributes attributes; XGetWindowAttributes(dpy,Scr.Root,&attributes); color.pixel = 0; if (!XParseColor (dpy, attributes.colormap, name, &color)) { nocolor("parse",name); } else if(!XAllocColor (dpy, attributes.colormap, &color)) { nocolor("alloc",name); } return color.pixel; } void nocolor(char *a, char *b) { fprintf(stderr,"%s: can't %s %s\n", MyName, a,b); } /**************************************************************************** * * Decide what to do about received X events * ****************************************************************************/ void DispatchEvent(XEvent *Event) { int i,x,y; Window JunkRoot, JunkChild; int JunkX, JunkY; unsigned JunkMask; switch(Event->xany.type) { case EnterNotify: if ( ShowBalloons ) MapBalloonWindow(Event); break; case LeaveNotify: if ( ShowBalloons ) UnmapBalloonWindow(); break; case ConfigureNotify: ReConfigure(); break; case Expose: HandleExpose(Event); break; case ButtonRelease: if((Event->xbutton.button == 1)|| (Event->xbutton.button == 2)) { for(i=0;ixany.window == Desks[i].w) SwitchToDeskAndPage(i,Event); if(Event->xany.window == Desks[i].title_w) SwitchToDesk(i); } if(Event->xany.window == icon_win) { IconSwitchPage(Event); } } else if (Event->xbutton.button == 3) { for(i=0;ixany.window == Desks[i].w) { XQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild, &JunkX, &JunkY,&x, &y, &JunkMask); Scroll(desk_w, desk_h, x, y, i); } } if(Event->xany.window == icon_win) { XQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild, &JunkX, &JunkY,&x, &y, &JunkMask); Scroll(icon_w, icon_h, x, y, -1); } } break; case ButtonPress: if ( ShowBalloons ) UnmapBalloonWindow(); if (((Event->xbutton.button == 2)|| ((Event->xbutton.button == 3)&& (Event->xbutton.state & Mod1Mask)))&& (Event->xbutton.subwindow != None)) { MoveWindow(Event); } else if (Event->xbutton.button == 3) { for(i=0;ixany.window == Desks[i].w) { if (Scr.CurrentDesk != i + desk1) { SwitchToDeskAndPage(i,Event); Scr.CurrentDesk = i + desk1; Wait = 0; } XQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild, &JunkX, &JunkY,&x, &y, &JunkMask); Scroll(desk_w, desk_h, x, y, i); break; } } if(Event->xany.window == icon_win) { XQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild, &JunkX, &JunkY,&x, &y, &JunkMask); Scroll(icon_w, icon_h, x, y, -1); } } break; case MotionNotify: while(XCheckMaskEvent(dpy, PointerMotionMask | ButtonMotionMask,Event)); if(Event->xmotion.state == Button3MotionMask) { for(i=0;ixany.window == Desks[i].w) { XQueryPointer(dpy, Desks[i].w, &JunkRoot, &JunkChild, &JunkX, &JunkY,&x, &y, &JunkMask); Scroll(desk_w, desk_h, x, y, i); } } if(Event->xany.window == icon_win) { XQueryPointer(dpy, icon_win, &JunkRoot, &JunkChild, &JunkX, &JunkY,&x, &y, &JunkMask); Scroll(icon_w, icon_h, x, y, -1); } } break; case ClientMessage: if ((Event->xclient.format==32) && (Event->xclient.data.l[0]==wm_del_win)) { exit(0); } break; } } void HandleExpose(XEvent *Event) { int i; PagerWindow *t; /* ric@giccs.georgetown.edu */ if ( Event->xany.window == balloon.w ) { DrawInBalloonWindow(); return; } for(i=0;ixany.window == Desks[i].w) ||(Event->xany.window == Desks[i].title_w)) DrawGrid(i,0); } if(Event->xany.window == icon_win) DrawIconGrid(0); t = Start; while(t!= NULL) { if(t->PagerView == Event->xany.window) { LabelWindow(t); PictureWindow(t); } else if(t->IconView == Event->xany.window) { LabelIconWindow(t); PictureIconWindow(t); } t = t->next; } } /**************************************************************************** * * Respond to a change in window geometry. * ****************************************************************************/ void ReConfigure(void) { Window root; unsigned border_width, depth; int n,m,w,h,n1,m1,x,y,i,j,k; XGetGeometry(dpy,Scr.Pager_w,&root,&x,&y, (unsigned *)&window_w,(unsigned *)&window_h, &border_width,&depth); n1 = Scr.Vx/Scr.MyDisplayWidth; m1 = Scr.Vy/Scr.MyDisplayHeight; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; desk_w = (window_w - Columns + 1)/Columns; desk_h = (window_h - Rows*label_h - Rows + 2)/Rows; w = (desk_w - n)/(n+1); h = (desk_h - m)/(m+1); sizehints.width_inc = Columns*(n+1); sizehints.height_inc = Rows*(m+1); sizehints.base_width = Columns * n + Columns - 1; sizehints.base_height = Rows*(m + label_h+1) -2; sizehints.min_width = Columns * n + Columns - 1; sizehints.min_height = Rows*(m + label_h+1) -2; XSetWMNormalHints(dpy,Scr.Pager_w,&sizehints); x = (desk_w-n)* Scr.Vx/(Scr.VxMax+Scr.MyDisplayWidth) +n1; y = (desk_h-m)*Scr.Vy/(Scr.VyMax+Scr.MyDisplayHeight) +m1; for(k=0;k= desk1)&&(Scr.CurrentDesk <=desk2)) sptr = Desks[Scr.CurrentDesk -desk1].label; else { sprintf(str,"Desk %d",Scr.CurrentDesk); sptr = &str[0]; } if (XStringListToTextProperty(&sptr,1,&name) == 0) { fprintf(stderr,"%s: cannot allocate window name",MyName); return; } XSetWMIconName(dpy,Scr.Pager_w,&name); } } void ReConfigureAll(void) { PagerWindow *t; t = Start; while(t!= NULL) { MoveResizePagerView(t); t = t->next; } } void ReConfigureIcons(void) { PagerWindow *t; int x,y,w,h,n,m,n1,m1; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; t = Start; while(t!= NULL) { n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/ (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/ (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if (w < 1) w = 1; if (h < 1) h = 1; t->icon_view_width = w; t->icon_view_height = h; if(Scr.CurrentDesk == t->desk) XMoveResizeWindow(dpy,t->IconView,x,y,w,h); else XMoveResizeWindow(dpy,t->IconView,-1000,-1000,w,h); t = t->next; } } /**************************************************************************** * * Draw grid lines for desk #i * ****************************************************************************/ void DrawGrid(int i, int erase) { int y, y1, y2, x, x1, x2,d,hor_off,w; int MaxW,MaxH; char str[15], *ptr; if((i < 0 ) ||(i >= ndesks)) return; MaxW = (Scr.VxMax + Scr.MyDisplayWidth); MaxH = Scr.VyMax + Scr.MyDisplayHeight; x = Scr.MyDisplayWidth; y1 = 0; y2 = desk_h; while(x < MaxW) { x1 = x*desk_w/MaxW; XDrawLine(dpy,Desks[i].w,DashedGC,x1,y1,x1,y2); x += Scr.MyDisplayWidth; } y = Scr.MyDisplayHeight; x1 = 0; x2 = desk_w; while(y < MaxH) { y1 = y*(desk_h)/MaxH; XDrawLine(dpy,Desks[i].w,DashedGC,x1,y1,x2,y1); y += Scr.MyDisplayHeight; } if((Scr.CurrentDesk - desk1) == i) { if(uselabel) XFillRectangle(dpy,Desks[i].title_w,HiliteGC, 0,0,desk_w,label_h -1); } else { if(uselabel && erase) XClearArea(dpy,Desks[i].title_w, 0,0,desk_w,label_h - 1,False); } d = desk1+i; ptr = Desks[i].label; w=XTextWidth(font,ptr,strlen(ptr)); if( w > desk_w) { sprintf(str,"%d",d); ptr = str; w=XTextWidth(font,ptr,strlen(ptr)); } if((w<= desk_w)&&(uselabel)) { hor_off = (desk_w -w)/2; if(i == (Scr.CurrentDesk - desk1)) XDrawString (dpy, Desks[i].title_w,rvGC,hor_off,font->ascent +1 , ptr, strlen(ptr)); else XDrawString (dpy, Desks[i].title_w,NormalGC,hor_off,font->ascent+1 , ptr, strlen(ptr)); } } void DrawIconGrid(int erase) { int y, y1, y2, x, x1, x2,w,h,n,m,n1,m1; int MaxW,MaxH; MaxW = (Scr.VxMax + Scr.MyDisplayWidth); MaxH = Scr.VyMax + Scr.MyDisplayHeight; if(erase) XClearWindow(dpy,icon_win); x = Scr.MyDisplayWidth; y1 = 0; y2 = icon_h; while(x < MaxW) { x1 = x*icon_w/MaxW; XDrawLine(dpy,icon_win,DashedGC,x1,y1,x1,y2); x += Scr.MyDisplayWidth; } y = Scr.MyDisplayHeight; x1 = 0; x2 = icon_w; while(y < MaxH) { y1 = y*(icon_h)/MaxH; XDrawLine(dpy,icon_win,DashedGC,x1,y1,x2,y1); y += Scr.MyDisplayHeight; } n1 = Scr.Vx/Scr.MyDisplayWidth; m1 = Scr.Vy/Scr.MyDisplayHeight; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; w = (icon_w - n)/(n+1); h = (icon_h - m)/(m+1); x = (icon_w-n)* Scr.Vx/(Scr.VxMax+Scr.MyDisplayWidth) +n1; y = (icon_h-m)*Scr.Vy/(Scr.VyMax+Scr.MyDisplayHeight) +m1; XFillRectangle(dpy,icon_win,HiliteGC, x,y,w,h); } void SwitchToDesk(int Desk) { char command[256]; sprintf(command,"Desk 0 %d\n",Desk+desk1); SendInfo(fd,command,0); } void SwitchToDeskAndPage(int Desk, XEvent *Event) { #ifndef NON_VIRTUAL char command[256]; if (Scr.CurrentDesk != (Desk+desk1)) { int vx, vy; SendInfo(fd,"Desk 0 10000\n",0); /* patch to let mouse button 3 change desks and do not cling to a page */ vx = Event->xbutton.x*(Scr.VxMax+Scr.MyDisplayWidth)/ (desk_w*Scr.MyDisplayWidth); vy = Event->xbutton.y*(Scr.VyMax+Scr.MyDisplayHeight)/ (desk_h*Scr.MyDisplayHeight); Scr.Vx = vx * Scr.MyDisplayWidth; Scr.Vy = vy * Scr.MyDisplayHeight; sprintf(command,"GotoPage %d %d\n", vx, vy); SendInfo(fd,command,0); sprintf(command,"Desk 0 %d\n",Desk+desk1); SendInfo(fd,command,0); } else { sprintf(command,"GotoPage %d %d\n", Event->xbutton.x*(Scr.VxMax+Scr.MyDisplayWidth)/ (desk_w*Scr.MyDisplayWidth), Event->xbutton.y*(Scr.VyMax+Scr.MyDisplayHeight)/ (desk_h*Scr.MyDisplayHeight)); SendInfo(fd,command,0); } #endif Wait = 1; } void IconSwitchPage(XEvent *Event) { #ifndef NON_VIRTUAL char command[256]; sprintf(command,"GotoPage %d %d\n", Event->xbutton.x*(Scr.VxMax+Scr.MyDisplayWidth)/ (icon_w*Scr.MyDisplayWidth), Event->xbutton.y*(Scr.VyMax+Scr.MyDisplayHeight)/ (icon_h*Scr.MyDisplayHeight)); SendInfo(fd,command,0); #endif Wait = 1; } void AddNewWindow(PagerWindow *t) { unsigned long valuemask; XSetWindowAttributes attributes; int i,x,y,w,h,n,m,n1,m1; i = t->desk - desk1; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; x = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(desk_w-n)/ (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(desk_h-m)/ (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if(w<1) w = 1; if(h<1) h = 1; t->pager_view_width = w; t->pager_view_height = h; valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); attributes.background_pixel = t->back; attributes.border_pixel = fore_pix; attributes.event_mask = (ExposureMask); /* ric@giccs.georgetown.edu -- added Enter and Leave events for popping up balloon window */ attributes.event_mask = (ExposureMask | EnterWindowMask | LeaveWindowMask); if((i >= 0)&& (i PagerView = XCreateWindow(dpy,Desks[i].w, x, y, w, h,1, CopyFromParent, InputOutput,CopyFromParent, valuemask,&attributes); XMapRaised(dpy,t->PagerView); } else t->PagerView = None; x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/ (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/ (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if(w<1) w = 1; if(h<1) h = 1; t->icon_view_width = w; t->icon_view_height = h; if(Scr.CurrentDesk == t->desk) { t->IconView = XCreateWindow(dpy,icon_win, x, y, w, h,1, CopyFromParent, InputOutput,CopyFromParent, valuemask,&attributes); XGrabButton(dpy, 2, AnyModifier, t->IconView, True, ButtonPressMask | ButtonReleaseMask|ButtonMotionMask, GrabModeAsync, GrabModeAsync, None, None); XMapRaised(dpy,t->IconView); } else { t->IconView = XCreateWindow(dpy,icon_win, -1000, -1000, w, h,1, CopyFromParent, InputOutput,CopyFromParent, valuemask,&attributes); XMapRaised(dpy,t->IconView); } Hilight(t,OFF); } void ChangeDeskForWindow(PagerWindow *t,long newdesk) { int i,x,y,w,h,n,m,n1,m1; i = newdesk - desk1; if(t->PagerView == None) { t->desk = newdesk; XDestroyWindow(dpy,t->IconView); AddNewWindow( t); return; } n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; x = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(desk_w-n) / (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(desk_h-m) / (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if (w < 1) w = 1; if (h < 1) h = 1; t->pager_view_width = w; t->pager_view_height = h; if((i >= 0)&&(i < ndesks)) { XReparentWindow(dpy, t->PagerView, Desks[i].w, x,y); XResizeWindow(dpy,t->PagerView,w,h); } else { XDestroyWindow(dpy,t->PagerView); t->PagerView = None; } t->desk = i+desk1; x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(icon_w-n) / (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(icon_h-m) / (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if (w < 1) w = 1; if (h < 1) h = 1; t->icon_view_width = w; t->icon_view_height = h; if(Scr.CurrentDesk == t->desk) XMoveResizeWindow(dpy,t->IconView,x,y,w,h); else XMoveResizeWindow(dpy,t->IconView,-1000,-1000,w,h); } void MoveResizePagerView(PagerWindow *t) { int x,y,w,h,n,m,n1,m1; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; x = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(desk_w-n)/ (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(desk_h-m)/ (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if (w < 1) w = 1; if (h < 1) h = 1; t->pager_view_width = w; t->pager_view_height = h; if(t->PagerView != None) XMoveResizeWindow(dpy,t->PagerView,x,y,w,h); else if((t->desk >= desk1)&&(t->desk <= desk2)) { XDestroyWindow(dpy,t->IconView); AddNewWindow(t); return; } x = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; y = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; w = (Scr.Vx + t->x + t->width+2)*(icon_w-n)/ (Scr.VxMax + Scr.MyDisplayWidth) - 2 - x + n1; h = (Scr.Vy + t->y + t->height+2)*(icon_h-m)/ (Scr.VyMax + Scr.MyDisplayHeight) -2 - y +m1; if (w < 1) w = 1; if (h < 1) h = 1; t->icon_view_width = w; t->icon_view_height = h; if(Scr.CurrentDesk == t->desk) XMoveResizeWindow(dpy,t->IconView,x,y,w,h); else XMoveResizeWindow(dpy,t->IconView,-1000,-1000,w,h); } void MoveStickyWindows(void) { PagerWindow *t; t = Start; while(t!= NULL) { if(((t->flags & ICONIFIED)&&(t->flags & StickyIcon))|| (t->flags & STICKY)) { if(t->desk != Scr.CurrentDesk) { ChangeDeskForWindow(t,Scr.CurrentDesk); } else { MoveResizePagerView(t); } } t = t->next; } } void Hilight(PagerWindow *t, int on) { if(!t)return; if(Scr.d_depth < 2) { if(on) { if(t->PagerView != None) XSetWindowBackgroundPixmap(dpy,t->PagerView,Scr.gray_pixmap); XSetWindowBackgroundPixmap(dpy,t->IconView,Scr.gray_pixmap); } else { if(t->flags & STICKY) { if(t->PagerView != None) XSetWindowBackgroundPixmap(dpy,t->PagerView, Scr.sticky_gray_pixmap); XSetWindowBackgroundPixmap(dpy,t->IconView, Scr.sticky_gray_pixmap); } else { if(t->PagerView != None) XSetWindowBackgroundPixmap(dpy,t->PagerView, Scr.light_gray_pixmap); XSetWindowBackgroundPixmap(dpy,t->IconView, Scr.light_gray_pixmap); } } } else { if(on) { if(t->PagerView != None) XSetWindowBackground(dpy,t->PagerView,focus_pix); XSetWindowBackground(dpy,t->IconView,focus_pix); } else { if(t->PagerView != None) XSetWindowBackground(dpy,t->PagerView,t->back); XSetWindowBackground(dpy,t->IconView,t->back); } } if(t->PagerView != None) XClearWindow(dpy,t->PagerView); XClearWindow(dpy,t->IconView); LabelWindow(t); LabelIconWindow(t); PictureWindow(t); PictureIconWindow(t); } /* Use Desk == -1 to scroll the icon window */ void Scroll(int window_w, int window_h, int x, int y, int Desk) { #ifndef NON_VIRTUAL char command[256]; int sx, sy; if(Wait == 0) { /* Desk < 0 means we want to scroll an icon window */ if(Desk >= 0 && Desk + desk1 != Scr.CurrentDesk) { return; } if(x < 0) x = 0; if(y < 0) y = 0; if(x > window_w) x = window_w; if(y > window_h) y = window_h; sx = (100*(x*(Scr.VxMax+Scr.MyDisplayWidth)/window_w- Scr.Vx)) / Scr.MyDisplayWidth; sy = (100*(y*(Scr.VyMax+Scr.MyDisplayHeight)/window_h - Scr.Vy)) / Scr.MyDisplayHeight; /* Make sure we don't get stuck a few pixels fromt the top/left border. * Since sx/sy are ints, values between 0 and 1 are rounded down. */ if(sx == 0 && x == 0 && Scr.Vx != 0) sx = -1; if(sy == 0 && y == 0 && Scr.Vy != 0) sy = -1; sprintf(command,"Scroll %d %d\n",sx,sy); SendInfo(fd,command,0); Wait = 1; } #endif } void MoveWindow(XEvent *Event) { char command[100]; int x1,y1,finished = 0,wx,wy,n,x,y,xi=0,yi=0,wx1,wy1,x2,y2; Window dumwin; PagerWindow *t; int m,n1,m1; int NewDesk,KeepMoving = 0; int moved = 0; int row,column; t = Start; while ((t != NULL)&&(t->PagerView != Event->xbutton.subwindow)) t= t->next; if(t==NULL) { t = Start; while ((t != NULL)&&(t->IconView != Event->xbutton.subwindow)) t= t->next; if(t!=NULL) { IconMoveWindow(Event,t); return; } } if(t == NULL) return; NewDesk = t->desk - desk1; if((NewDesk < 0)||(NewDesk >= ndesks)) return; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; wx = (Scr.Vx + t->x)*(desk_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; wy = (Scr.Vy + t->y)*(desk_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; wx1 = wx+(desk_w+1)*(NewDesk%Columns); wy1 = wy + label_h + (desk_h+label_h+1)*(NewDesk/Columns); XReparentWindow(dpy, t->PagerView, Scr.Pager_w,wx1,wy1); XRaiseWindow(dpy,t->PagerView); XTranslateCoordinates(dpy, Event->xany.window, t->PagerView, Event->xbutton.x, Event->xbutton.y, &x1, &y1, &dumwin); xi = x1; yi = y1; while(!finished) { XMaskEvent(dpy,ButtonReleaseMask | ButtonMotionMask|ExposureMask,Event); if(Event->type == MotionNotify) { XTranslateCoordinates(dpy, Event->xany.window, Scr.Pager_w, Event->xmotion.x, Event->xmotion.y, &x, &y, &dumwin); if(moved == 0) { xi = x; yi = y; moved = 1; } if((x < -5)||(y<-5)||(x>window_w+5)||(y>window_h+5)) { KeepMoving = 1; finished = 1; } XMoveWindow(dpy,t->PagerView, x - (x1), y - (y1)); } else if(Event->type == ButtonRelease) { XTranslateCoordinates(dpy, Event->xany.window, Scr.Pager_w, Event->xbutton.x, Event->xbutton.y, &x, &y, &dumwin); XMoveWindow(dpy,t->PagerView, x - (x1), y - (y1)); finished = 1; } else if (Event->type == Expose) { HandleExpose(Event); } } if(moved) { if((x - xi < 3)&&(y - yi < 3)&& (x - xi > -3)&&(y -yi > -3)) moved = 0; } if(KeepMoving) { NewDesk = Scr.CurrentDesk; if(NewDesk != t->desk) { XMoveWindow(dpy,t->w,Scr.MyDisplayWidth+Scr.VxMax, Scr.MyDisplayHeight+Scr.VyMax); XSync(dpy,0); sprintf(command,"MoveToDesk 0 %d", NewDesk); SendInfo(fd,command,t->w); t->desk = NewDesk; } if((NewDesk>=desk1)&&(NewDesk<=desk2)) XReparentWindow(dpy, t->PagerView, Desks[NewDesk-desk1].w,0,0); else { XDestroyWindow(dpy,t->PagerView); t->PagerView = None; } XTranslateCoordinates(dpy, Scr.Pager_w, Scr.Root, x, y, &x1, &y1, &dumwin); XUngrabPointer(dpy,CurrentTime); XSync(dpy,0); sprintf(command, "Move %dp %dp", x, y); SendInfo(fd,command,t->w); SendInfo(fd,"Raise",t->w); SendInfo(fd,"Move",t->w); return; } else { column = (x/(desk_w+1)); row = (y/(desk_h+ label_h+1)); NewDesk = column + (row)*Columns; if((NewDesk <0)||(NewDesk >=ndesks)) { NewDesk = Scr.CurrentDesk - desk1; x = xi; y = yi; moved = 0; } XTranslateCoordinates(dpy, Scr.Pager_w,Desks[NewDesk].w, x-x1, y-y1, &x2,&y2,&dumwin); n1 = x2*(Scr.VxMax + Scr.MyDisplayWidth)/(desk_w * Scr.MyDisplayWidth); m1 = y2*(Scr.VyMax + Scr.MyDisplayHeight)/(desk_h * Scr.MyDisplayHeight); x = (x2-n1)* (Scr.VxMax + Scr.MyDisplayWidth)/(desk_w-n) - Scr.Vx; y = (y2-m1)* (Scr.VyMax + Scr.MyDisplayHeight)/(desk_h-m) - Scr.Vy; if(x + t->frame_width + Scr.Vx < 0 ) x = -Scr.Vx; if(y+t->frame_height + Scr.Vy< 0) y = -Scr.Vy; if(x + Scr.Vx > Scr.MyDisplayWidth+Scr.VxMax) x = Scr.MyDisplayWidth + Scr.VxMax - t->frame_width - Scr.Vx; if(y +Scr.Vy> Scr.MyDisplayHeight+Scr.VyMax) y = Scr.MyDisplayHeight+ Scr.VyMax - t->frame_height - Scr.Vy; if(((t->flags & ICONIFIED)&&(t->flags & StickyIcon))|| (t->flags & STICKY)) { NewDesk = Scr.CurrentDesk - desk1; if(x > Scr.MyDisplayWidth -16) x = Scr.MyDisplayWidth - 16; if(y > Scr.MyDisplayHeight-16) y = Scr.MyDisplayHeight - 16; if(x + t->width < 16) x = 16 - t->width; if(y + t->height < 16) y = 16 - t->height; } if(NewDesk +desk1 != t->desk) { if(((t->flags & ICONIFIED)&&(t->flags & StickyIcon))|| (t->flags & STICKY)) { NewDesk = Scr.CurrentDesk - desk1; if(t->desk != Scr.CurrentDesk) ChangeDeskForWindow(t,Scr.CurrentDesk); } else { sprintf(command,"MoveToDesk 0 %d", NewDesk + desk1); SendInfo(fd,command,t->w); t->desk = NewDesk + desk1; } } if((NewDesk >= 0)&&(NewDesk < ndesks)) { XReparentWindow(dpy, t->PagerView, Desks[NewDesk].w,x,y); if(moved) { if(t->flags & ICONIFIED) XMoveWindow(dpy,t->icon_w,x,y); else XMoveWindow(dpy,t->w,x+t->border_width, y+t->title_height+t->border_width); XSync(dpy,0); } else MoveResizePagerView(t); SendInfo(fd,"Raise",t->w); } if(Scr.CurrentDesk == t->desk) { XSync(dpy,0); usleep(5000); XSync(dpy,0); if(t->flags & ICONIFIED) { /* RBW - reverting to old code for 2.2... The new handling causes an unwanted viewport change whenever Button2 is used; the old handling causes focus to be sent to No Input windows regardless of the Lenience setting. After 2.2 we will revisit this issue. I suspect it will involve expanding the module message to include wmhints and such. */ #if 0 SendInfo(fd, "Focus", t->icon_w); #else XSetInputFocus (dpy, t->icon_w, RevertToParent, Event->xbutton.time); #endif } else { #if 0 SendInfo(fd, "Focus", t->w); #else XSetInputFocus (dpy, t->w, RevertToParent, Event->xbutton.time); #endif } } } } /*********************************************************************** * * Procedure: * FvwmErrorHandler - displays info on internal errors * ************************************************************************/ XErrorHandler FvwmErrorHandler(Display *dpy, XErrorEvent *event) { #if 1 extern Bool error_occured; error_occured = True; return 0; #else /* really should just exit here... */ /* domivogt (07-mar-1999): No, not really. See comment above. */ fprintf(stderr,"%s: XError! Bagging out!\n",MyName); exit(0); #endif /* 1 */ } void LabelWindow(PagerWindow *t) { XGCValues Globalgcv; unsigned long Globalgcm; if(windowFont == NULL) { return; } if (MiniIcons && t->mini_icon.picture && (t->PagerView != None)) { return; /* will draw picture instead... */ } if(t->icon_name == NULL) { return; } if(t == FocusWin) { Globalgcv.foreground = focus_fore_pix; Globalgcv.background = focus_pix; Globalgcm = GCForeground|GCBackground; XChangeGC(dpy, StdGC,Globalgcm,&Globalgcv); } else { Globalgcv.foreground = t->text; Globalgcv.background = t->back; Globalgcm = GCForeground|GCBackground; XChangeGC(dpy, StdGC,Globalgcm,&Globalgcv); } if(t->PagerView != None) { XClearWindow(dpy, t->PagerView); XDrawString (dpy, t->PagerView,StdGC,2,windowFont->ascent+2 , t->icon_name, strlen(t->icon_name)); } } void LabelIconWindow(PagerWindow *t) { XGCValues Globalgcv; unsigned long Globalgcm; if(windowFont == NULL) { return; } if (MiniIcons && t->mini_icon.picture && (t->PagerView != None)) { return; /* will draw picture instead... */ } if(t->icon_name == NULL) { return; } if(t == FocusWin) { Globalgcv.foreground = focus_fore_pix; Globalgcv.background = focus_pix; Globalgcm = GCForeground|GCBackground; XChangeGC(dpy,StdGC,Globalgcm,&Globalgcv); } else { Globalgcv.foreground = t->text; Globalgcv.background = t->back; Globalgcm = GCForeground|GCBackground; XChangeGC(dpy,StdGC,Globalgcm,&Globalgcv); } XClearWindow(dpy, t->IconView); XDrawString (dpy, t->IconView,StdGC,2,windowFont->ascent+2 , t->icon_name, strlen(t->icon_name)); } void PictureWindow (PagerWindow *t) { XGCValues Globalgcv; unsigned long Globalgcm; int iconX; int iconY; if (MiniIcons) { if (t->mini_icon.picture && (t->PagerView != None)) { if (t->pager_view_width > t->mini_icon.width) iconX = (t->pager_view_width - t->mini_icon.width) / 2; else if (t->pager_view_width < t->mini_icon.width) iconX = -((t->mini_icon.width - t->pager_view_width) / 2); else iconX = 0; if (t->pager_view_height > t->mini_icon.height) iconY = (t->pager_view_height - t->mini_icon.height) / 2; else if (t->pager_view_height < t->mini_icon.height) iconY = -((t->mini_icon.height - t->pager_view_height) / 2); else iconY = 0; Globalgcm = GCForeground | GCBackground | GCClipMask | GCClipXOrigin | GCClipYOrigin; Globalgcv.clip_mask = t->mini_icon.mask; Globalgcv.clip_x_origin = iconX; Globalgcv.clip_y_origin = iconY; if (t == FocusWin) { Globalgcv.foreground = focus_fore_pix; Globalgcv.background = focus_pix; } else { Globalgcv.foreground = t->text; Globalgcv.background = t->back; } XChangeGC (dpy, MiniIconGC, Globalgcm, &Globalgcv); XClearWindow (dpy, t->PagerView); XCopyArea (dpy, t->mini_icon.picture, t->PagerView, MiniIconGC, 0, 0, t->mini_icon.width, t->mini_icon.height, iconX, iconY); } } } void PictureIconWindow (PagerWindow *t) { XGCValues Globalgcv; unsigned long Globalgcm; int iconX; int iconY; if (MiniIcons) { if (t->mini_icon.picture && (t->IconView != None)) { if (t->icon_view_width > t->mini_icon.width) iconX = (t->icon_view_width - t->mini_icon.width) / 2; else if (t->icon_view_width < t->mini_icon.width) iconX = -((t->mini_icon.width - t->icon_view_width) / 2); else iconX = 0; if (t->icon_view_height > t->mini_icon.height) iconY = (t->icon_view_height - t->mini_icon.height) / 2; else if (t->icon_view_height < t->mini_icon.height) iconY = -((t->mini_icon.height - t->icon_view_height) / 2); else iconY = 0; Globalgcm = GCForeground | GCBackground | GCClipMask | GCClipXOrigin | GCClipYOrigin; Globalgcv.clip_mask = t->mini_icon.mask; Globalgcv.clip_x_origin = iconX; Globalgcv.clip_y_origin = iconY; if (t == FocusWin) { Globalgcv.foreground = focus_fore_pix; Globalgcv.background = focus_pix; } else { Globalgcv.foreground = t->text; Globalgcv.background = t->back; } XChangeGC (dpy, MiniIconGC, Globalgcm, &Globalgcv); XClearWindow (dpy, t->IconView); XCopyArea (dpy, t->mini_icon.picture, t->IconView, MiniIconGC, 0, 0, t->mini_icon.width, t->mini_icon.height, iconX, iconY); } } } void IconMoveWindow(XEvent *Event,PagerWindow *t) { char command[100]; int x1,y1,finished = 0,wx,wy,n,x=0,y=0,xi=0,yi=0; Window dumwin; int m,n1,m1; int moved = 0; int KeepMoving = 0; if(t==NULL) return; n = (Scr.VxMax)/Scr.MyDisplayWidth; m = (Scr.VyMax)/Scr.MyDisplayHeight; n1 = (Scr.Vx+t->x)/Scr.MyDisplayWidth; m1 = (Scr.Vy+t->y)/Scr.MyDisplayHeight; wx = (Scr.Vx + t->x)*(icon_w-n)/(Scr.VxMax + Scr.MyDisplayWidth) +n1; wy = (Scr.Vy + t->y)*(icon_h-m)/(Scr.VyMax + Scr.MyDisplayHeight)+m1; XRaiseWindow(dpy,t->IconView); XTranslateCoordinates(dpy, Event->xany.window, t->IconView, Event->xbutton.x, Event->xbutton.y, &x1, &y1, &dumwin); while(!finished) { XMaskEvent(dpy,ButtonReleaseMask | ButtonMotionMask|ExposureMask,Event); if(Event->type == MotionNotify) { x = Event->xbutton.x; y = Event->xbutton.y; if(moved == 0) { xi = x; yi = y; moved = 1; } XMoveWindow(dpy,t->IconView, x - (x1), y - (y1)); if((x < -5)||(y < -5)||(x>icon_w+5)||(y>icon_h+5)) { finished = 1; KeepMoving = 1; } } else if(Event->type == ButtonRelease) { x = Event->xbutton.x; y = Event->xbutton.y; XMoveWindow(dpy,t->PagerView, x - (x1),y - (y1)); finished = 1; } else if (Event->type == Expose) { HandleExpose(Event); } } if(moved) { if((x - xi < 3)&&(y - yi < 3)&& (x - xi > -3)&&(y -yi > -3)) moved = 0; } if(KeepMoving) { XTranslateCoordinates(dpy, t->IconView, Scr.Root, x, y, &x1, &y1, &dumwin); XUngrabPointer(dpy,CurrentTime); XSync(dpy,0); sprintf(command, "Move %dp %dp", x, y); SendInfo(fd,command,t->w); SendInfo(fd,"Raise",t->w); SendInfo(fd,"Move",t->w); } else { x = x - x1; y = y - y1; n1 = x*(Scr.VxMax + Scr.MyDisplayWidth)/(icon_w * Scr.MyDisplayWidth); m1 = y*(Scr.VyMax + Scr.MyDisplayHeight)/(icon_h * Scr.MyDisplayHeight); x = (x-n1)* (Scr.VxMax + Scr.MyDisplayWidth)/(icon_w-n) - Scr.Vx; y = (y-m1)* (Scr.VyMax + Scr.MyDisplayHeight)/(icon_h-m) - Scr.Vy; if(((t->flags & ICONIFIED)&&(t->flags & StickyIcon))|| (t->flags & STICKY)) { if(x > Scr.MyDisplayWidth -16) x = Scr.MyDisplayWidth - 16; if(y > Scr.MyDisplayHeight-16) y = Scr.MyDisplayHeight - 16; if(x + t->width < 16) x = 16 - t->width; if(y + t->height < 16) y = 16 - t->height; } if(moved) { if(t->flags & ICONIFIED) XMoveWindow(dpy,t->icon_w,x,y); else XMoveWindow(dpy,t->w,x,y); XSync(dpy,0); } else { MoveResizePagerView(t); } SendInfo(fd,"Raise",t->w); if(t->flags & ICONIFIED) { /* RBW - reverting to old code for 2.2...temporarily. See note above, in MoveWindow. */ #if 0 SendInfo(fd, "Focus", t->icon_w); #else XSetInputFocus (dpy, t->icon_w, RevertToParent, Event->xbutton.time); #endif } else { #if 0 SendInfo(fd, "Focus", t->w); #else XSetInputFocus (dpy, t->w, RevertToParent, Event->xbutton.time); #endif } } } /* Just maps window ... draw stuff in it later after Expose event -- ric@giccs.georgetown.edu */ void MapBalloonWindow (XEvent *event) { PagerWindow *t; XWindowChanges window_changes; Window view, dummy; int view_width, view_height; int matched_window = 0; int x, y; extern char *BalloonBack; /* is this the best way to match X event window ID to PagerWindow ID? */ t = Start; while ( ! matched_window ) { if (t == NULL) { return; } else if ( t->PagerView == event->xcrossing.window ) { view = t->PagerView; view_width = t->pager_view_width; view_height = t->pager_view_height; matched_window = 1; } else if ( t->IconView == event->xcrossing.window ) { view = t->IconView; view_width = t->icon_view_width; view_height = t->icon_view_height; matched_window = 1; } else { t = t->next; } } /* associate balloon with its pager window */ balloon.pw = t; /* calculate window width to accommodate string */ window_changes.width = 4 + XTextWidth(balloon.font, t->icon_name, strlen(t->icon_name)); /* get x and y coords relative to pager window */ x = (view_width / 2) - (window_changes.width / 2) - balloon.border; if ( balloon.yoffset > 0 ) y = view_height + balloon.yoffset; else y = balloon.yoffset - balloon.height - (2 * balloon.border); /* balloon is a top-level window, therefore need to translate pager window coords to root window coords */ XTranslateCoordinates(dpy, view, Scr.Root, x, y, &window_changes.x, &window_changes.y, &dummy); /* make sure balloon doesn't go off screen (actually 2 pixels from edge rather than 0 just to be pretty :-) */ /* too close to left */ if ( window_changes.x < 2 ) window_changes.x = 2; /* too close to right */ else if ( window_changes.x + window_changes.width > Scr.MyDisplayWidth - (2 * balloon.border) - 2 ) window_changes.x = Scr.MyDisplayWidth - window_changes.width - (2 * balloon.border) - 2; /* too close to top ... make yoffset +ve */ if ( window_changes.y < 2 ) { y = - balloon.yoffset + view_height; XTranslateCoordinates(dpy, view, Scr.Root, x, y, &window_changes.x, &window_changes.y, &dummy); } /* too close to bottom ... make yoffset -ve */ else if ( window_changes.y + balloon.height > Scr.MyDisplayHeight - (2 * balloon.border) - 2 ) { y = - balloon.yoffset - balloon.height - (2 * balloon.border); XTranslateCoordinates(dpy, view, Scr.Root, x, y, &window_changes.x, &window_changes.y, &dummy); } /* make changes to window */ XConfigureWindow(dpy, balloon.w, CWX | CWY | CWWidth, &window_changes); /* if background not set in config make it match pager window */ if ( BalloonBack == NULL ) XSetWindowBackground(dpy, balloon.w, t->back); XMapRaised(dpy, balloon.w); } /* -- ric@giccs.georgetown.edu */ void UnmapBalloonWindow (void) { XUnmapWindow(dpy, balloon.w); } /* Draws string in balloon window -- call after it's received Expose event -- ric@giccs.georgetown.edu */ void DrawInBalloonWindow (void) { extern char *BalloonFore; /* if foreground not set in config make it match pager window */ if ( BalloonFore == NULL ) XSetForeground(dpy, BalloonGC, balloon.pw->text); XDrawString(dpy, balloon.w, BalloonGC, 2, balloon.font->ascent, balloon.pw->icon_name, strlen(balloon.pw->icon_name)); }