/*************************************<->************************************* * * DoPlacement (pcd) * * * Description: * ----------- * Gets window configuration from the user via pointer/keyboard interaction * * * Inputs: * ------ * pcd - pointer to client data * * * Outputs: * ------- * pcd - clientX, clientY, clientWidth, and clientHeight members * could be changed * * Comments: * -------- * We try to be careful only to remove events that we need from the * event queue while we're in our own event processing loop. * *************************************<->***********************************/ void DoPlacement (ClientData *pcd) { XEvent event; /* * Initialization */ SetupPlacement (pcd); /* * Process events */ placementDone = FALSE; while (!placementDone) { GetConfigEvent (DISPLAY, ACTIVE_ROOT, GRAB_MASK, placePointerX, placePointerY, placeX, placeY, placeWidth, placeHeight, &event); switch (event.type) { case KeyPress: HandlePlacementKeyEvent(pcd, (XKeyEvent *)&event); break; case ButtonPress: HandlePlacementButtonEvent((XButtonEvent *)&event); break; case ButtonRelease: HandlePlacementButtonEvent((XButtonEvent *)&event); break; case MotionNotify: HandlePlacementMotionEvent(pcd, (XMotionEvent *)&event); break; } } /* copy back the configuration information */ pcd->clientX = placeX + placeOffsetX; pcd->clientY = placeY + placeOffsetY; pcd->clientWidth = placeWidth - 2*placeOffsetX; pcd->clientHeight = placeHeight - placeOffsetX - placeOffsetY; /* clean up */ MoveOutline (0,0,0,0); HideFeedbackWindow(pcd->pSD); } /* END OF FUNCTION DoPlacement */
void HandlePlacementMotionEvent (ClientData *pcd, XMotionEvent *pev) { int diffx, diffy; /* * If in pre-resize mode, check for motion crossing threshhold before * switching modes */ if (wmGD.preMove) { diffx = pev->x_root - wmGD.preMoveX; diffy = pev->y_root - wmGD.preMoveY; if ((ABS(diffx) > wmGD.moveThreshold) || (ABS(diffy) > wmGD.moveThreshold)) { StartInteractiveSizing(pcd, pev->time); } return; } if (placeResize) { /* * Track lower right corner */ if (pev->x_root > placeX) placeWidth = pev->x_root - placeX + 1; if (pev->y_root > placeY) placeHeight = pev->y_root - placeY + 1; } else { /* * track window position */ placeX = pev->x_root; placeY = pev->y_root; } placePointerX = pev->x_root; placePointerY = pev->y_root; FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight, placeResize); MoveOutline (placeX, placeY, placeWidth, placeHeight); if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT) { DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight, 0, placeResize); } } /* END OF FUNCTION HandlePlacementMotionEvent */
/*************************************<->************************************* * * SetupPlacement (pcd) * * * Description: * ----------- * Perform the initialization for interactive placement * * * Inputs: * ------ * pcd - pointer to client data * * Outputs: * ------- * * * Comments: * -------- * o sets up global data and puts initial display on the screen * *************************************<->***********************************/ void SetupPlacement (ClientData *pcd) { int cX, cY, junk; Window junk_win; /* * Restore the state of the last "depressed" frame gadget */ if (wmGD.gadgetClient && wmGD.gadgetDepressed) { PopGadgetOut(wmGD.gadgetClient, wmGD.gadgetDepressed); } /* get offset of frame origin from window origin */ placeOffsetX = pcd->clientOffset.x; placeOffsetY = pcd->clientOffset.y; XQueryPointer (DISPLAY, ACTIVE_ROOT, &junk_win, &junk_win, &cX, &cY, &junk, &junk, (unsigned int *)&junk); /* convert to frame coordinates */ placePointerX = placeX = cX; placePointerY = placeY = cY; placeWidth = pcd->clientWidth; placeHeight = pcd->clientHeight; ClientToFrame (pcd, &cX, &cY, &placeWidth, &placeHeight); /* in "position" mode to start with */ placeResize = FALSE; wmGD.preMove = FALSE; /* normal window being dealt with, not icon */ wmGD.movingIcon = FALSE; if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT) { DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight, (FB_SIZE | FB_POSITION), placeResize); } /* set up initial visual feedback */ MoveOutline (placeX, placeY, placeWidth, placeHeight); } /* END OF FUNCTION SetupPlacement */
void HandlePlacementKeyEvent (ClientData *pcd, XKeyEvent *pev) { XEvent KeyEvent; KeySym keysym; Boolean control, valid; int big_inc; int tmpX = 0; int tmpY = 0; int warpX, warpY, newX, newY; int keyPlaceX = placeX; int keyPlaceY = placeY; unsigned int keyPlaceWidth = placeWidth; unsigned int keyPlaceHeight = placeHeight; /* filter out repeating keys */ placeKeyMultiplier = 1; if (pev->type == KeyPress) { while (placeKeyMultiplier <= 10 && XCheckIfEvent (DISPLAY, &KeyEvent, IsRepeatedKeyEvent, (char *) pev)) { placeKeyMultiplier++; } } /* convert event data to useful key data */ #ifdef FIX_1611 keysym = WmKeycodeToKeysym(DISPLAY, pev->keycode); #else keysym = XKeycodeToKeysym (DISPLAY, pev->keycode, 0); #endif control = (pev->state & ControlMask) != 0; big_inc = DisplayWidth(DISPLAY, ACTIVE_PSD->screen) / 20; /* interpret key data */ valid = FALSE; switch (keysym) { case XK_Left: tmpX = (control) ? (-big_inc) : -1; valid = TRUE; break; case XK_Up: tmpY = (control) ? (-big_inc) : -1; valid = TRUE; break; case XK_Right: tmpX = (control) ? (big_inc) : 1; valid = TRUE; break; case XK_Down: tmpY = (control) ? (big_inc) : 1; valid = TRUE; break; case XK_space: StartInteractiveSizing(pcd, pev->time); break; case XK_Return: placementDone = TRUE; /* global "done" flag */ break; default: break; } /* if a valid key was pressed, then react to it */ if (valid) { tmpX *= placeKeyMultiplier; tmpY *= placeKeyMultiplier; if (placeResize) { keyPlaceWidth += tmpX; /* change size of outline */ keyPlaceHeight += tmpY; FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth, &keyPlaceHeight, placeResize); warpX = keyPlaceX+keyPlaceWidth-1; warpY = keyPlaceY+keyPlaceHeight-1; SetPointerPosition (warpX, warpY, &newX, &newY); if ((warpX == newX) && (warpY == newY)) { placeWidth = keyPlaceWidth; placeHeight = keyPlaceHeight; } else { placeWidth = newX - keyPlaceX + 1; placeHeight = newY - keyPlaceY + 1; } } else { keyPlaceX += tmpX; /* change position of outline */ keyPlaceY += tmpY; FixFrameValues(pcd, &keyPlaceX, &keyPlaceY, &keyPlaceWidth, &keyPlaceHeight, placeResize); warpX = keyPlaceX; warpY = keyPlaceY; SetPointerPosition (warpX, warpY, &newX, &newY); placeX = newX; placeY = newY; } placePointerX = newX; placePointerY = newY; } FixFrameValues (pcd, &placeX, &placeY, &placeWidth, &placeHeight, placeResize); MoveOutline (placeX, placeY, placeWidth, placeHeight); if (wmGD.showFeedback & WM_SHOW_FB_PLACEMENT) { DoFeedback (pcd, placeX, placeY, placeWidth, placeHeight, 0, placeResize); } } /* END OF FUNCTION HandlePlacementKeyEvent */
/**************************************************************************** * * Move the rubberband around, return with the new window location * ****************************************************************************/ void moveLoop(FvwmWindow *tmp_win, int XOffset, int YOffset, int Width, int Height, int *FinalX, int *FinalY,Bool opaque_move, Bool AddWindow) { Bool finished = False; Bool done; int xl,yt,delta_x,delta_y; #ifndef NO_PAGER unsigned int pagerwidth,pagerheight; int ww,wh; int wx,wy; int MaxH,MaxW; int last_x = -10000, last_y = -10000; #endif XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,&xl, &yt, &JunkX, &JunkY, &JunkMask); xl += XOffset; yt += YOffset; if(((!opaque_move)&&(!(Scr.flags & MWMMenus)))||(AddWindow)) MoveOutline(Scr.Root, xl, yt, Width,Height); DisplayPosition(tmp_win,xl+Scr.Vx,yt+Scr.Vy,True); while (!finished) { /* block until there is an interesting event */ XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask | ButtonMotionMask | ExposureMask, &Event); StashEventTime(&Event); /* discard any extra motion events before a logical release */ if (Event.type == MotionNotify) { while(XCheckMaskEvent(dpy, PointerMotionMask | ButtonMotionMask | ButtonPressMask |ButtonRelease, &Event)) { StashEventTime(&Event); if(Event.type == ButtonRelease) break; } } done = FALSE; /* Handle a limited number of key press events to allow mouseless * operation */ if(Event.type == KeyPress) Keyboard_shortcuts(&Event,ButtonRelease); switch(Event.type) { case KeyPress: done = TRUE; break; case ButtonPress: XAllowEvents(dpy,ReplayPointer,CurrentTime); if(((Event.xbutton.button == 2)&&(!(Scr.flags & MWMMenus)))|| ((Event.xbutton.button == 1)&&(Scr.flags & MWMMenus)&& (Event.xbutton.state & ShiftMask))) { NeedToResizeToo = True; /* Fallthrough to button-release */ } else { done = 1; break; } case ButtonRelease: if(!opaque_move) MoveOutline(Scr.Root, 0, 0, 0, 0); xl = Event.xmotion.x_root + XOffset; yt = Event.xmotion.y_root + YOffset; /* Resist moving windows over the edge of the screen! */ if(((xl + Width) >= Scr.MyDisplayWidth)&& ((xl + Width) < Scr.MyDisplayWidth+Scr.MoveResistance)) xl = Scr.MyDisplayWidth - Width - tmp_win->bw; if((xl <= 0)&&(xl > -Scr.MoveResistance)) xl = 0; if(((yt + Height) >= Scr.MyDisplayHeight)&& ((yt + Height) < Scr.MyDisplayHeight+Scr.MoveResistance)) yt = Scr.MyDisplayHeight - Height - tmp_win->bw; if((yt <= 0)&&(yt > -Scr.MoveResistance)) yt = 0; *FinalX = xl; *FinalY = yt; done = TRUE; finished = TRUE; break; case MotionNotify: /* update location of the pager_view window */ #ifndef NO_PAGER if((Scr.FvwmPager != NULL)&& (xl < Scr.FvwmPager->frame_x + Scr.FvwmPager->frame_width)&& (xl+Width > Scr.FvwmPager->frame_x)&& (yt < Scr.FvwmPager->frame_y + Scr.FvwmPager->frame_height)&& (yt+ Height > Scr.FvwmPager->frame_y)&&(!opaque_move)) MoveOutline(Scr.Root,0,0,0,0); #endif xl = Event.xmotion.x_root; yt = Event.xmotion.y_root; HandlePaging(Scr.MyDisplayWidth,Scr.MyDisplayHeight,&xl,&yt, &delta_x,&delta_y,False); /* redraw the rubberband */ xl += XOffset; yt += YOffset; /* Resist moving windows over the edge of the screen! */ if(((xl + Width) >= Scr.MyDisplayWidth)&& ((xl + Width) < Scr.MyDisplayWidth+Scr.MoveResistance)) xl = Scr.MyDisplayWidth - Width - tmp_win->bw; if((xl <= 0)&&(xl > -Scr.MoveResistance)) xl = 0; if(((yt + Height) >= Scr.MyDisplayHeight)&& ((yt + Height) < Scr.MyDisplayHeight+Scr.MoveResistance)) yt = Scr.MyDisplayHeight - Height - tmp_win->bw; if((yt <= 0)&&(yt > -Scr.MoveResistance)) yt = 0; #ifndef NO_PAGER if(Scr.FvwmPager) { pagerwidth = Scr.FvwmPager->frame_width - 2*Scr.FvwmPager->boundary_width; pagerheight = Scr.FvwmPager->frame_height - Scr.FvwmPager->title_height - 2*Scr.FvwmPager->boundary_width; MaxW = Scr.VxMax + Scr.MyDisplayWidth; MaxH = Scr.VyMax + Scr.MyDisplayHeight; if(!(tmp_win->flags & STICKY)&& (!(tmp_win->flags&ICONIFIED)|| (!(tmp_win->flags&SUPPRESSICON)))&& (!(tmp_win->flags&ICONIFIED)||(!(Scr.flags & StickyIcons)))) { /* show the actual window */ wx = (xl + Scr.Vx)*(int)pagerwidth/MaxW; wy = (yt + Scr.Vy)*(int)pagerheight/MaxH; if((last_x - wx >= 2)||(last_x - wx <= -2)|| (last_y - wy >= 2)||(last_y - wy <= -2)) { ww = Width*(int)pagerwidth/MaxW; wh = Height*(int)pagerheight/MaxH; if(ww<2)ww=2; if(wh<2)wh=2; XMoveResizeWindow(dpy, tmp_win->pager_view, wx, wy, ww, wh); last_x = wx; last_y = wy; } } } #endif if(!opaque_move) MoveOutline(Scr.Root, xl, yt, Width,Height); else { if (tmp_win->flags & ICONIFIED) { tmp_win->icon_x_loc = xl ; tmp_win->icon_xl_loc = xl - (tmp_win->icon_w_width - tmp_win->icon_p_width)/2; tmp_win->icon_y_loc = yt; if(tmp_win->icon_pixmap_w != None) XMoveWindow (dpy, tmp_win->icon_pixmap_w, tmp_win->icon_x_loc,yt); else if (tmp_win->icon_w != None) XMoveWindow(dpy, tmp_win->icon_w,tmp_win->icon_xl_loc, yt+tmp_win->icon_p_height); } else XMoveWindow(dpy,tmp_win->frame,xl,yt); } DisplayPosition(tmp_win,xl+Scr.Vx,yt+Scr.Vy,False); done = TRUE; break; default: break; } if(!done) { if(!opaque_move) MoveOutline(Scr.Root,0,0,0,0); DispatchEvent(); if(!opaque_move) MoveOutline(Scr.Root, xl, yt, Width, Height); } } }