Example #1
0
/** Stop move. */
void StopMove(ClientNode *np, int doMove,
              int oldx, int oldy, MaxFlags maxFlags)
{

   int north, south, east, west;

   Assert(np);
   Assert(np->controller);

   (np->controller)(0);

   np->controller = NULL;

   SetDefaultCursor(np->parent);
   UnregisterCallback(SignalMove, NULL);

   if(!doMove) {

      np->x = oldx;
      np->y = oldy;

      /* Restore maximized status. */
      if(maxFlags) {
         MaximizeClient(np, maxFlags);
      }
      return;

   }

   GetBorderSize(&np->state, &north, &south, &east, &west);

   if(np->parent != None) {
      JXMoveWindow(display, np->parent, np->x - west, np->y - north);
   } else {
      JXMoveWindow(display, np->window, np->x - west, np->y - north);
   }
   SendConfigureEvent(np);

   /* Restore maximized status. */
   if(maxFlags) {
      MaximizeClient(np, maxFlags);
   }

}
Example #2
0
/** Maximize a client window. */
void MaximizeClient(ClientNode *np, MaxFlags flags)
{

    /* Return if we don't have a client. */
    if(np == NULL) {
        return;
    }

   /* Don't allow maximization of full-screen clients. */
   if(np->state.status & STAT_FULLSCREEN) {
      return;
   }
   if(!(np->state.border & BORDER_MAX)) {
      return;
   }

   if(np->state.status & STAT_SHADED) {
      UnshadeClient(np);
   }

   RaiseClient(np);
   FocusClient(np);
   if(np->state.maxFlags) {
      /* Undo existing maximization. */
      np->x = np->oldx;
      np->y = np->oldy;
      np->width = np->oldWidth;
      np->height = np->oldHeight;
      np->state.maxFlags = MAX_NONE;
   }
   if(flags != MAX_NONE) {
      /* Maximize if requested. */
      PlaceMaximizedClient(np, flags);
   }

   WriteState(np);
   ResetBorder(np);
   DrawBorder(np);
   SendConfigureEvent(np);
   RequirePagerUpdate();

}
Example #3
0
/** Stop move. */
void StopMove(ClientNode *np, int doMove,
              int oldx, int oldy, int hmax, int vmax)
{

   int north, south, east, west;

   Assert(np);
   Assert(np->controller);

   (np->controller)(0);

   np->controller = NULL;

   SetDefaultCursor(np->parent);
   UnregisterCallback(SignalMove, NULL);

   if(!doMove) {

      np->x = oldx;
      np->y = oldy;

      /* Restore maximized status if only maximized in one direction. */
      if((hmax || vmax) && !(hmax && vmax)) {
         MaximizeClient(np, hmax, vmax);
      }

      return;

   }

   GetBorderSize(&np->state, &north, &south, &east, &west);

   JXMoveWindow(display, np->parent, np->x - west, np->y - north);
   SendConfigureEvent(np);

   /* Restore maximized status. */
   if((hmax || vmax) && !(hmax && vmax)) {
      MaximizeClient(np, hmax, vmax);
   }

}
Example #4
0
File: move.c Project: Nehamkin/jwm
/** Move a client window. */
char MoveClient(ClientNode *np, int startx, int starty)
{

   XEvent event;
   int oldx, oldy;
   int doMove;
   int north, south, east, west;
   int height;
   MaxFlags maxFlags;

   Assert(np);

   if(!(np->state.border & BORDER_MOVE)) {
      return 0;
   }
   if(np->state.status & STAT_FULLSCREEN) {
      return 0;
   }

   GrabMouseForMove();

   RegisterCallback(0, SignalMove, NULL);
   np->controller = MoveController;
   shouldStopMove = 0;

   oldx = np->x;
   oldy = np->y;
   maxFlags = np->state.maxFlags;

   if(!(GetMouseMask() & (Button1Mask | Button2Mask))) {
      StopMove(np, 0, oldx, oldy, maxFlags);
      return 0;
   }

   GetBorderSize(&np->state, &north, &south, &east, &west);

   startx -= west;
   starty -= north;

   currentClient = np;
   atTop = atBottom = atLeft = atRight = 0;
   doMove = 0;
   for(;;) {

      WaitForEvent(&event);

      if(shouldStopMove) {
         np->controller = NULL;
         SetDefaultCursor(np->parent);
         UnregisterCallback(SignalMove, NULL);
         return doMove;
      }

      switch(event.type) {
      case ButtonRelease:
         if(event.xbutton.button == Button1
            || event.xbutton.button == Button2) {
            StopMove(np, doMove, oldx, oldy, maxFlags);
            return doMove;
         }
         break;
      case MotionNotify:

         DiscardMotionEvents(&event, np->window);

         np->x = event.xmotion.x_root - startx;
         np->y = event.xmotion.y_root - starty;

         /* Get the move time used for desktop switching. */
         if(!(atLeft | atTop | atRight | atBottom)) {
            if(event.xmotion.state & Mod1Mask) {
               moveTime.seconds = 0;
               moveTime.ms = 0;
            } else {
               GetCurrentTime(&moveTime);
            }
         }

         /* Determine if we are at a border for desktop switching. */
         atLeft = atTop = atRight = atBottom = 0;
         if(event.xmotion.x_root == 0) {
            atLeft = 1;
         } else if(event.xmotion.x_root == rootWidth - 1) {
            atRight = 1;
         }
         if(event.xmotion.y_root == 0) {
            atTop = 1;
         } else if(event.xmotion.y_root == rootHeight - 1) {
            atBottom = 1;
         }

         if(event.xmotion.state & Mod1Mask) {
            /* Switch desktops immediately if alt is pressed. */
            if(atLeft | atRight | atTop | atBottom) {
               TimeType now;
               GetCurrentTime(&now);
               UpdateDesktop(&now);
            }
         } else {
            /* If alt is not pressed, snap to borders. */
            DoSnap(np);
         }

         if(!doMove && (abs(np->x - oldx) > MOVE_DELTA
            || abs(np->y - oldy) > MOVE_DELTA)) {

            if(np->state.maxFlags) {
               MaximizeClient(np, MAX_NONE);
               startx = np->width / 2;
               starty = -north / 2;
               MoveMouse(np->parent, startx, starty);
            }

            CreateMoveWindow(np);
            doMove = 1;
         }

         if(doMove) {

            if(settings.moveMode == MOVE_OUTLINE) {
               ClearOutline();
               height = north + south;
               if(!(np->state.status & STAT_SHADED)) {
                  height += np->height;
               }
               DrawOutline(np->x - west, np->y - north,
                           np->width + west + east, height);
            } else {
               JXMoveWindow(display, np->parent, np->x - west,
                            np->y - north);
               SendConfigureEvent(np);
            }
            UpdateMoveWindow(np);
            RequirePagerUpdate();
         }

         break;
      default:
         break;
      }
   }
}
Example #5
0
File: move.c Project: Nehamkin/jwm
/** Move a client window (keyboard or menu initiated). */
char MoveClientKeyboard(ClientNode *np)
{

   XEvent event;
   int oldx, oldy;
   int moved;
   int height;
   int north, south, east, west;
   MaxFlags maxFlags;

   Assert(np);

   if(!(np->state.border & BORDER_MOVE)) {
      return 0;
   }
   if(np->state.status & STAT_FULLSCREEN) {
      return 0;
   }

   maxFlags = np->state.maxFlags;
   if(np->state.maxFlags != MAX_NONE) {
      MaximizeClient(np, MAX_NONE);
   }

   if(JUNLIKELY(JXGrabKeyboard(display, np->parent, True, GrabModeAsync,
                               GrabModeAsync, CurrentTime))) {
      Debug("MoveClient: could not grab keyboard");
      return 0;
   }
   GrabMouseForMove();

   GetBorderSize(&np->state, &north, &south, &east, &west);

   oldx = np->x;
   oldy = np->y;

   RegisterCallback(0, SignalMove, NULL);
   np->controller = MoveController;
   shouldStopMove = 0;

   CreateMoveWindow(np);
   UpdateMoveWindow(np);

   MoveMouse(rootWindow, np->x, np->y);
   DiscardMotionEvents(&event, np->window);

   if(np->state.status & STAT_SHADED) {
      height = 0;
   } else {
      height = np->height;
   }

   for(;;) {

      WaitForEvent(&event);

      if(shouldStopMove) {
         np->controller = NULL;
         SetDefaultCursor(np->parent);
         UnregisterCallback(SignalMove, NULL);
         return 1;
      }

      moved = 0;

      if(event.type == KeyPress) {

         DiscardKeyEvents(&event, np->window);
         switch(GetKey(&event.xkey) & 0xFF) {
         case KEY_UP:
            if(np->y + height > 0) {
               np->y -= 10;
            }
            break;
         case KEY_DOWN:
            if(np->y < rootHeight) {
               np->y += 10;
            }
            break;
         case KEY_RIGHT:
            if(np->x < rootWidth) {
               np->x += 10;
            }
            break;
         case KEY_LEFT:
            if(np->x + np->width > 0) {
               np->x -= 10;
            }
            break;
         default:
            StopMove(np, 1, oldx, oldy, maxFlags);
            return 1;
         }

         MoveMouse(rootWindow, np->x, np->y);
         DiscardMotionEvents(&event, np->window);

         moved = 1;

      } else if(event.type == MotionNotify) {

         DiscardMotionEvents(&event, np->window);

         np->x = event.xmotion.x;
         np->y = event.xmotion.y;

         moved = 1;

      } else if(event.type == ButtonRelease) {

         StopMove(np, 1, oldx, oldy, maxFlags);
         return 1;

      }

      if(moved) {

         if(settings.moveMode == MOVE_OUTLINE) {
            ClearOutline();
            DrawOutline(np->x - west, np->y - west,
                        np->width + west + east, height + north + west);
         } else {
            JXMoveWindow(display, np->parent, np->x - west, np->y - north);
            SendConfigureEvent(np);
         }

         UpdateMoveWindow(np);
         RequirePagerUpdate();

      }

   }

}
Example #6
0
/** Move a client window. */
char MoveClient(ClientNode *np, int startx, int starty, int snap)
{

   XEvent event;
   int oldx, oldy;
   int doMove;
   int north, south, east, west;
   int height;
   int hmax, vmax;

   Assert(np);

   if(!(np->state.border & BORDER_MOVE)) {
      return 0;
   }
   if(np->state.status & STAT_FULLSCREEN) {
      return 0;
   }

   GrabMouseForMove();

   RegisterCallback(0, SignalMove, NULL);
   np->controller = MoveController;
   shouldStopMove = 0;

   oldx = np->x;
   oldy = np->y;
   vmax = 0;
   hmax = 0;

   if(!(GetMouseMask() & (Button1Mask | Button2Mask))) {
      StopMove(np, 0, oldx, oldy, 0, 0);
      return 0;
   }

   GetBorderSize(&np->state, &north, &south, &east, &west);

   startx -= west;
   starty -= north;

   currentClient = np;
   atTop = 0;
   atBottom = 0;
   atLeft = 0;
   atRight = 0;
   doMove = 0;
   for(;;) {

      WaitForEvent(&event);

      if(shouldStopMove) {
         np->controller = NULL;
         SetDefaultCursor(np->parent);
         UnregisterCallback(SignalMove, NULL);
         return doMove;
      }

      switch(event.type) {
      case ButtonRelease:
         if(event.xbutton.button == Button1
            || event.xbutton.button == Button2) {
            StopMove(np, doMove, oldx, oldy, hmax, vmax);
            return doMove;
         }
         break;
      case MotionNotify:

         DiscardMotionEvents(&event, np->window);

         np->x = event.xmotion.x_root - startx;
         np->y = event.xmotion.y_root - starty;

         GetCurrentTime(&moveTime);
         atLeft = 0;
         atTop = 0;
         atRight = 0;
         atBottom = 0;
         if(event.xmotion.x_root == 0) {
            atLeft = 1;
         } else if(event.xmotion.x_root == rootWidth - 1) {
            atRight = 1;
         }
         if(event.xmotion.y_root == 0) {
            atTop = 1;
         } else if(event.xmotion.y_root == rootHeight - 1) {
            atBottom = 1;
         }

         if(snap) {
            DoSnap(np);
         }

         if(!doMove && (abs(np->x - oldx) > MOVE_DELTA
            || abs(np->y - oldy) > MOVE_DELTA)) {

            if(np->state.status & (STAT_HMAX | STAT_VMAX)) {
               if(np->state.status & STAT_HMAX) {
                  hmax = 1;
               }
               if(np->state.status & STAT_VMAX) {
                  vmax = 1;
               }
               MaximizeClient(np, 0, 0);
               startx = np->width / 2;
               starty = -north / 2;
               MoveMouse(np->parent, startx, starty);
            }

            CreateMoveWindow(np);
            doMove = 1;
         }

         if(doMove) {

            if(settings.moveMode == MOVE_OUTLINE) {
               ClearOutline();
               height = north + south;
               if(!(np->state.status & STAT_SHADED)) {
                  height += np->height;
               }
               DrawOutline(np->x - west, np->y - north,
                           np->width + west + east, height);
            } else {
               JXMoveWindow(display, np->parent, np->x - west,
                            np->y - north);
               SendConfigureEvent(np);
            }
            UpdateMoveWindow(np);
            UpdatePager();
         }

         break;
      default:
         break;
      }
   }
}
Example #7
0
/** Process a configure request. */
void HandleConfigureRequest(const XConfigureRequestEvent *event)
{
   XWindowChanges wc;
   ClientNode *np;

   if(HandleDockConfigureRequest(event)) {
      return;
   }

   np = FindClientByWindow(event->window);
   if(np) {

      int deltax, deltay;
      char changed = 0;
      char resized = 0;

      GetGravityDelta(np, np->gravity, &deltax, &deltay);
      if((event->value_mask & CWWidth) && (event->width != np->width)) {
         switch(np->gravity) {
         case EastGravity:
         case NorthEastGravity:
         case SouthEastGravity:
            /* Right side should not move. */
            np->x -= event->width - np->width;
            break;
         case WestGravity:
         case NorthWestGravity:
         case SouthWestGravity:
            /* Left side should not move. */
            break;
         case CenterGravity:
            /* Center of the window should not move. */
            np->x -= (event->width - np->width) / 2;
            break;
         default:
            break;
         }
         np->width = event->width;
         changed = 1;
         resized = 1;
      }
      if((event->value_mask & CWHeight) && (event->height != np->height)) {
         switch(np->gravity) {
         case NorthGravity:
         case NorthEastGravity:
         case NorthWestGravity:
            /* Top should not move. */
            break;
         case SouthGravity:
         case SouthEastGravity:
         case SouthWestGravity:
            /* Bottom should not move. */
            np->y -= event->height - np->height;
            break;
         case CenterGravity:
            /* Center of the window should not move. */
            np->y -= (event->height - np->height) / 2;
            break;
         default:
            break;
         }
         np->height = event->height;
         changed = 1;
         resized = 1;
      }
      if((event->value_mask & CWX) && (event->x - deltax != np->x)) {
         np->x = event->x - deltax;
         changed = 1;
      }
      if((event->value_mask & CWY) && (event->y - deltay != np->y)) {
         np->y = event->y - deltay;
         changed = 1;
      }

      /* Update stacking. */
      if((event->value_mask & CWStackMode)) {
         Window above = None;
         if(event->value_mask & CWSibling) {
            above = event->above;
         }
         RestackClient(np, above, event->detail);
      }

      /* Return early if there's nothing to do. */
      if(!changed) {
         return;
      }

      if(np->controller) {
         (np->controller)(0);
      }
      if(np->state.maxFlags) {
         MaximizeClient(np, MAX_NONE);
      }

      if(np->state.border & BORDER_CONSTRAIN) {
         resized = 1;
      }
      if(resized) {
         ConstrainSize(np);
         ConstrainPosition(np);
         ResetBorder(np);
      } else {
         int north, south, east, west;
         GetBorderSize(&np->state, &north, &south, &east, &west);
         if(np->parent != None) {
            JXMoveWindow(display, np->parent, np->x - west, np->y - north);
         } else {
            JXMoveWindow(display, np->window, np->x, np->y);
         }
      }

      SendConfigureEvent(np);
      RequirePagerUpdate();

   } else {

      /* We don't know about this window, just let the configure through. */

      wc.stack_mode = event->detail;
      wc.sibling = event->above;
      wc.border_width = event->border_width;
      wc.x = event->x;
      wc.y = event->y;
      wc.width = event->width;
      wc.height = event->height;
      JXConfigureWindow(display, event->window, event->value_mask, &wc);

   }
}
Example #8
0
/** Handle a _NET_MOVERESIZE_WINDOW request. */
void HandleNetMoveResize(const XClientMessageEvent *event, ClientNode *np)
{

   long flags;
   int gravity;
   int deltax, deltay;

   Assert(event);
   Assert(np);

   flags = event->data.l[0] >> 8;
   gravity = event->data.l[0] & 0xFF;
   if(gravity == 0) {
      gravity = np->gravity;
   }
   GetGravityDelta(np, gravity, &deltax, &deltay);

   if(flags & (1 << 2)) {
      const long width = event->data.l[3];
      switch(gravity) {
      case EastGravity:
      case NorthEastGravity:
      case SouthEastGravity:
         /* Right side should not move. */
         np->x -= width - np->width;
         break;
      case WestGravity:
      case NorthWestGravity:
      case SouthWestGravity:
         /* Left side should not move. */
         break;
      case CenterGravity:
         /* Center of the window should not move. */
         np->x -= (width - np->width) / 2;
         break;
      default:
         break;
      }
      np->width = width;
   }
   if(flags & (1 << 3)) {
      const long height = event->data.l[4];
      switch(gravity) {
      case NorthGravity:
      case NorthEastGravity:
      case NorthWestGravity:
         /* Top should not move. */
         break;
      case SouthGravity:
      case SouthEastGravity:
      case SouthWestGravity:
         /* Bottom should not move. */
         np->y -= height - np->height;
         break;
      case CenterGravity:
         /* Center of the window should not move. */
         np->y -= (height - np->height) / 2;
         break;
      default:
         break;
      }
      np->height = height;
   }
   if(flags & (1 << 0)) {
      np->x = event->data.l[1] - deltax;
   }
   if(flags & (1 << 1)) {
      np->y = event->data.l[2] - deltay;
   }

   /* Don't let maximized clients be moved or resized. */
   if(JUNLIKELY(np->state.status & STAT_FULLSCREEN)) {
      SetClientFullScreen(np, 0);
   }
   if(JUNLIKELY(np->state.maxFlags)) {
      MaximizeClient(np, MAX_NONE);
   }

   ConstrainSize(np);
   ResetBorder(np);
   SendConfigureEvent(np);
   RequirePagerUpdate();

}
Example #9
0
/** Set a client's full screen state. */
void SetClientFullScreen(ClientNode *np, char fullScreen)
{

   XEvent event;
   int north, south, east, west;
   BoundingBox box;
   const ScreenType *sp;

   Assert(np);

   /* Make sure there's something to do. */
   if(!fullScreen == !(np->state.status & STAT_FULLSCREEN)) {
      return;
   }
   if(!(np->state.border & BORDER_FULLSCREEN)) {
      return;
   }

   if(np->state.status & STAT_SHADED) {
      UnshadeClient(np);
   }

   if(fullScreen) {

      np->state.status |= STAT_FULLSCREEN;

      if(!(np->state.maxFlags)) {
         np->oldx = np->x;
         np->oldy = np->y;
         np->oldWidth = np->width;
         np->oldHeight = np->height;
      }

      sp = GetCurrentScreen(np->x, np->y);
      GetScreenBounds(sp, &box);

      GetBorderSize(&np->state, &north, &south, &east, &west);
      box.x += west;
      box.y += north;
      box.width -= east + west;
      box.height -= north + south;

      np->x = box.x;
      np->y = box.y;
      np->width = box.width;
      np->height = box.height;
      ResetBorder(np);

   } else {

      np->state.status &= ~STAT_FULLSCREEN;

      np->x = np->oldx;
      np->y = np->oldy;
      np->width = np->oldWidth;   
      np->height = np->oldHeight;
      ConstrainSize(np);
      ConstrainPosition(np);

      if(np->state.maxFlags != MAX_NONE) {
         PlaceMaximizedClient(np, np->state.maxFlags);
      }

      ResetBorder(np);

      event.type = MapRequest;
      event.xmaprequest.send_event = True;
      event.xmaprequest.display = display;
      event.xmaprequest.parent = np->parent;
      event.xmaprequest.window = np->window;
      JXSendEvent(display, rootWindow, False,
                  SubstructureRedirectMask, &event);

   }

   WriteState(np);
   SendConfigureEvent(np);
   RequireRestack();

}
Example #10
0
/** Add a window to management. */
ClientNode *AddClientWindow(Window w, char alreadyMapped, char notOwner)
{

   XWindowAttributes attr;
   ClientNode *np;

   Assert(w != None);

   /* Get window attributes. */
   if(JXGetWindowAttributes(display, w, &attr) == 0) {
      return NULL;
   }

   /* Determine if we should care about this window. */
   if(attr.override_redirect == True) {
      return NULL;
   }
   if(attr.class == InputOnly) {
      return NULL;
   }

   /* Prepare a client node for this window. */
   np = Allocate(sizeof(ClientNode));
   memset(np, 0, sizeof(ClientNode));

   np->window = w;
   np->owner = None;
   np->state.desktop = currentDesktop;

   np->x = attr.x;
   np->y = attr.y;
   np->width = attr.width;
   np->height = attr.height;
   np->cmap = attr.colormap;
   np->state.status = STAT_NONE;
   np->state.maxFlags = MAX_NONE;
   np->state.layer = LAYER_NORMAL;
   np->state.defaultLayer = LAYER_NORMAL;

   np->state.border = BORDER_DEFAULT;
   np->borderAction = BA_NONE;

   ReadClientInfo(np, alreadyMapped);

   if(!notOwner) {
      np->state.border = BORDER_OUTLINE | BORDER_TITLE | BORDER_MOVE;
      np->state.status |= STAT_WMDIALOG | STAT_STICKY;
      np->state.layer = LAYER_ABOVE;
      np->state.defaultLayer = LAYER_ABOVE;
   }

   ApplyGroups(np);
   if(np->icon == NULL) {
      LoadIcon(np);
   }

   /* We now know the layer, so insert */
   np->prev = NULL;
   np->next = nodes[np->state.layer];
   if(np->next) {
      np->next->prev = np;
   } else {
      nodeTail[np->state.layer] = np;
   }
   nodes[np->state.layer] = np;

   SetDefaultCursor(np->window);
   ReparentClient(np, notOwner);
   PlaceClient(np, alreadyMapped);

   if(!((np->state.status & STAT_FULLSCREEN) || np->state.maxFlags)) {
      int north, south, east, west;
      GetBorderSize(&np->state, &north, &south, &east, &west);
      if(np->parent != None) {
         JXMoveResizeWindow(display, np->parent, np->x - west, np->y - north,
                            np->width + east + west,
                            np->height + north + south);
         JXMoveResizeWindow(display, np->window, west, north,
                            np->width, np->height);
      } else {
         JXMoveResizeWindow(display, np->window, np->x, np->y,
                            np->width, np->height);
      }
   }

   /* If one of these fails we are SOL, so who cares. */
   XSaveContext(display, np->window, clientContext, (void*)np);
   if(np->parent != None) {
      XSaveContext(display, np->parent, frameContext, (void*)np);
   }

   if(np->state.status & STAT_MAPPED) {
      JXMapWindow(display, np->window);
      if(np->parent != None) {
         JXMapWindow(display, np->parent);
      }
   }

   clientCount += 1;

   if(!alreadyMapped) {
      RaiseClient(np);
   }

   if(np->state.status & STAT_OPACITY) {
      SetOpacity(np, np->state.opacity, 1);
   } else {
      SetOpacity(np, settings.inactiveClientOpacity, 1);
   }
   if(np->state.status & STAT_STICKY) {
      SetCardinalAtom(np->window, ATOM_NET_WM_DESKTOP, ~0UL);
   } else {
      SetCardinalAtom(np->window, ATOM_NET_WM_DESKTOP, np->state.desktop);
   }

   /* Shade the client if requested. */
   if(np->state.status & STAT_SHADED) {
      np->state.status &= ~STAT_SHADED;
      ShadeClient(np);
   }

   /* Minimize the client if requested. */
   if(np->state.status & STAT_MINIMIZED) {
      np->state.status &= ~STAT_MINIMIZED;
      MinimizeClient(np, 0);
   }

   /* Maximize the client if requested. */
   if(np->state.maxFlags) {
      const MaxFlags flags = np->state.maxFlags;
      np->state.maxFlags = MAX_NONE;
      MaximizeClient(np, flags);
   }

   if(np->state.status & STAT_URGENT) {
      RegisterCallback(URGENCY_DELAY, SignalUrgent, np);
   }

   /* Update task bars. */
   AddClientToTaskBar(np);

   /* Make sure we're still in sync */
   WriteState(np);
   SendConfigureEvent(np);

   /* Hide the client if we're not on the right desktop. */
   if(np->state.desktop != currentDesktop
      && !(np->state.status & STAT_STICKY)) {
      HideClient(np);
   }

   ReadClientStrut(np);

   /* Focus transients if their parent has focus. */
   if(np->owner != None) {
      if(activeClient && np->owner == activeClient->window) {
         FocusClient(np);
      }
   }

   /* Make the client fullscreen if requested. */
   if(np->state.status & STAT_FULLSCREEN) {
      np->state.status &= ~STAT_FULLSCREEN;
      SetClientFullScreen(np, 1);
   }
   ResetBorder(np);

   return np;

}
Example #11
0
/** Handle a _NET_MOVERESIZE_WINDOW request. */
void HandleNetMoveResize(const XClientMessageEvent *event, ClientNode *np) {

   long flags, gravity;
   long x, y;
   long width, height;
   int deltax, deltay;
   int north, south, east, west;

   Assert(event);
   Assert(np);

   gravity = event->data.l[0] & 0xFF;
   flags = event->data.l[0] >> 8;

   x = np->x;
   y = np->y;
   width = np->width;
   height = np->height;

   if(flags & (1 << 0)) {
      x = event->data.l[1];
   }
   if(flags & (1 << 1)) {
      y = event->data.l[2];
   }
   if(flags & (1 << 2)) {
      width = event->data.l[3];
   }
   if(flags & (1 << 3)) {
      height = event->data.l[4];
   }

   if(gravity == 0) {
      gravity = np->gravity;
   }

   GetBorderSize(np, &north, &south, &east, &west);
   GetGravityDelta(np, &deltax, &deltay);

   x -= deltax;
   y -= deltay;

   np->x = x;
   np->y = y;
   np->width = width;
   np->height = height;

   if(np->state.status & STAT_FULLSCREEN) {
      Warning("Fullscreen state will be shaped!");
   }

   /** Reset shaped bound */
   ResetRoundedRectWindow(np->parent);
   ShapeRoundedRectWindow(np->parent, 
      np->width + east + west,
      np->height + north + south);
   JXMoveResizeWindow(display, np->parent,
      np->x - west, np->y - north,
      np->width + east + west,
      np->height + north + south);
   JXMoveResizeWindow(display, np->window, west, north,
      np->width, np->height);

   WriteState(np);
   SendConfigureEvent(np);

}
Example #12
0
/** Resize a client window (mouse initiated). */
void ResizeClient(ClientNode *np, BorderActionType action,
                  int startx, int starty) {

   XEvent event;
   int oldx, oldy;
   int oldw, oldh;
   int gwidth, gheight;
   int lastgwidth, lastgheight;
   int delta;
   int north, south, east, west;
   int ratio, minr, maxr;

   Assert(np);

   if(!(np->state.border & BORDER_RESIZE)) {
      return;
   }

   if(JUNLIKELY(!GrabMouseForResize(action))) {
      Debug("ResizeClient: could not grab mouse");
      return;
   }

   if(np->state.status & STAT_SHADED) {
      action &= ~(BA_RESIZE_N | BA_RESIZE_S);
   }

   np->controller = ResizeController;
   shouldStopResize = 0;

   oldx = np->x;
   oldy = np->y;
   oldw = np->width;
   oldh = np->height;

   gwidth = (np->width - np->baseWidth) / np->xinc;
   gheight = (np->height - np->baseHeight) / np->yinc;

   GetBorderSize(np, &north, &south, &east, &west);

   startx += np->x - west;
   starty += np->y - north;

   CreateResizeWindow(np);
   UpdateResizeWindow(np, gwidth, gheight);

   if(!(GetMouseMask() & (Button1Mask | Button3Mask))) {
      StopResize(np);
      return;
   }

   for(;;) {

      WaitForEvent(&event);

      if(shouldStopResize) {
         np->controller = NULL;
         return;
      }

      switch(event.type) {
      case ButtonRelease:
         if(   event.xbutton.button == Button1
            || event.xbutton.button == Button3) {
            StopResize(np);
            return;
         }
         break;
      case MotionNotify:

         SetMousePosition(event.xmotion.x_root, event.xmotion.y_root);
         DiscardMotionEvents(&event, np->window);

         if(action & BA_RESIZE_N) {
            delta = (event.xmotion.y - starty) / np->yinc;
            delta *= np->yinc;
            if(oldh - delta >= np->minHeight
               && (oldh - delta <= np->maxHeight || delta > 0)) {
               np->height = oldh - delta;
               np->y = oldy + delta;
            }
            if(!(action & (BA_RESIZE_E | BA_RESIZE_W))) {
               FixWidth(np);
            }
         }
         if(action & BA_RESIZE_S) {
            delta = (event.xmotion.y - starty) / np->yinc;
            delta *= np->yinc;
            np->height = oldh + delta;
            np->height = Max(np->height, np->minHeight);
            np->height = Min(np->height, np->maxHeight);
            if(!(action & (BA_RESIZE_E | BA_RESIZE_W))) {
               FixWidth(np);
            }
         }
         if(action & BA_RESIZE_E) {
            delta = (event.xmotion.x - startx) / np->xinc;
            delta *= np->xinc;
            np->width = oldw + delta;
            np->width = Max(np->width, np->minWidth);
            np->width = Min(np->width, np->maxWidth);
            if(!(action & (BA_RESIZE_N | BA_RESIZE_S))) {
               FixHeight(np);
            }
         }
         if(action & BA_RESIZE_W) {
            delta = (event.xmotion.x - startx) / np->xinc;
            delta *= np->xinc;
            if(oldw - delta >= np->minWidth
               && (oldw - delta <= np->maxWidth || delta > 0)) {
               np->width = oldw - delta;
               np->x = oldx + delta;
            }
            if(!(action & (BA_RESIZE_N | BA_RESIZE_S))) {
               FixHeight(np);
            }
         }

         if(np->sizeFlags & PAspect) {
            if((action & (BA_RESIZE_N | BA_RESIZE_S)) &&
               (action & (BA_RESIZE_E | BA_RESIZE_W))) {

               /* Fixed point with a 16-bit fraction. */
               ratio = (np->width << 16) / np->height;

               minr = (np->aspect.minx << 16) / np->aspect.miny;
               if(ratio < minr) {
                  delta = np->width;
                  np->width = (np->height * minr) >> 16;
                  if(action & BA_RESIZE_W) {
                     np->x -= np->width - delta;
                  }
               }

               maxr = (np->aspect.maxx << 16) / np->aspect.maxy;
               if(ratio > maxr) {
                  delta = np->height;
                  np->height = (np->width << 16) / maxr;
                  if(action & BA_RESIZE_N) {
                     np->y -= np->height - delta;
                  }
               }

            }
         }

         lastgwidth = gwidth;
         lastgheight = gheight;

         gwidth = (np->width - np->baseWidth) / np->xinc;
         gheight = (np->height - np->baseHeight) / np->yinc;

         if(lastgheight != gheight || lastgwidth != gwidth) {

            if(np->state.status & (STAT_HMAX | STAT_VMAX)) {
               np->state.status &= ~(STAT_HMAX | STAT_VMAX);
               WriteState(np);
               SendConfigureEvent(np);
            }

            UpdateResizeWindow(np, gwidth, gheight);

            if(resizeMode == RESIZE_OUTLINE) {
               ClearOutline();
               if(np->state.status & STAT_SHADED) {
                  DrawOutline(np->x - west, np->y - north,
                     np->width + west + east, north + south);
               } else {
                  DrawOutline(np->x - west, np->y - north,
                     np->width + west + east,
                     np->height + north + south);
               }
            } else {
               ResetRoundedRectWindow(np->parent);
               if(np->state.status & STAT_SHADED) {
                  ShapeRoundedRectWindow(np->parent, 
                     np->width + east + west,
                     north + south);
                  JXMoveResizeWindow(display, np->parent,
                     np->x - west, np->y - north,
                     np->width + west + east, north + south);
               } else {
                  ShapeRoundedRectWindow(np->parent, 
                     np->width + east + west,
                     np->height + north + south);
                  JXMoveResizeWindow(display, np->parent,
                     np->x - west, np->y - north,
                     np->width + west + east,
                     np->height + north + south);
               }
               JXMoveResizeWindow(display, np->window, west,
                  north, np->width, np->height);
               SendConfigureEvent(np);
            }

            UpdatePager();

         }

         break;
      default:
         break;
      }