예제 #1
0
파일: client.c 프로젝트: pecarter-work/jwm
/** Show a hidden client. This will not update transients. */
void ShowClient(ClientNode *np)
{
   if(np->state.status & STAT_HIDDEN) {
      np->state.status &= ~STAT_HIDDEN;
      if(np->state.status & (STAT_MAPPED | STAT_SHADED)) {
         if(!(np->state.status & STAT_MINIMIZED)) {
            if(np->parent != None) {
               JXMapWindow(display, np->parent);
            } else {
               JXMapWindow(display, np->window);
            }
            if(np->state.status & STAT_ACTIVE) {
               FocusClient(np);
            }
         }
      }
   }
}
예제 #2
0
파일: client.c 프로젝트: pecarter-work/jwm
/** Restore a window with its transients (helper method). */
void RestoreTransients(ClientNode *np, char raise)
{

   ClientNode *tp;
   int x;

   Assert(np);

   /* Make sure this window is on the current desktop. */
   SetClientDesktop(np, currentDesktop);

   /* Restore this window. */
   if(!(np->state.status & STAT_MAPPED)) {
      if(np->state.status & STAT_SHADED) {
         if(np->parent != None) {
            JXMapWindow(display, np->parent);
         }
      } else {
         JXMapWindow(display, np->window);
         if(np->parent != None) {
            JXMapWindow(display, np->parent);
         }
         np->state.status |= STAT_MAPPED;
      }
   }
   np->state.status &= ~STAT_MINIMIZED;
   np->state.status &= ~STAT_SDESKTOP;

   /* Restore transient windows. */
   for(x = 0; x < LAYER_COUNT; x++) {
      for(tp = nodes[x]; tp; tp = tp->next) {
         if(tp->owner == np->window && (tp->state.status & STAT_MINIMIZED)) {
            RestoreTransients(tp, raise);
         }
      }
   }

   if(raise) {
      FocusClient(np);
      RaiseClient(np);
   }
   WriteState(np);

}
예제 #3
0
파일: event.c 프로젝트: GustavoMOG/JWM
/** Handle a map request. */
void HandleMapRequest(const XMapEvent *event) {

   ClientNode *np;

   Assert(event);

   if(CheckSwallowMap(event)) {
      return;
   }

   np = FindClientByWindow(event->window);
   if(!np) {
      JXSync(display, False);
      JXGrabServer(display);
      np = AddClientWindow(event->window, 0, 1);
      if(np) {
         if(focusModel == FOCUS_CLICK && !(np->state.status & STAT_NOFOCUS)) {
            FocusClient(np);
         }
      } else {
         JXMapWindow(display, event->window);
      }
      JXSync(display, False);
      JXUngrabServer(display);
   } else {
      if(!(np->state.status & STAT_MAPPED)) {
         np->state = ReadWindowState(np->window);
         np->state.status |= STAT_MAPPED;
         if(!(np->state.status & STAT_STICKY)) {
            np->state.desktop = currentDesktop;
         }
         JXMapWindow(display, np->window);
         JXMapWindow(display, np->parent);
         if(!(np->state.status & STAT_NOFOCUS)) {
            RaiseClient(np);
            FocusClient(np);
         }
         UpdateTaskBar();
         UpdatePager();
      }
   }
   RestackClients();
}
예제 #4
0
/** Load the background for the specified desktop. */
void LoadBackground(int desktop) {

   XSetWindowAttributes attr;
   long attrValues;
   BackgroundNode *bp;

   /* Determine the background to load. */
   for(bp = backgrounds; bp; bp = bp->next) {
      if(bp->desktop == desktop) {
         break;
      }
   }
   if(!bp) {
      bp = defaultBackground;
   }

   /* If there is no background specified for this desktop, just return. */
   if(!bp || !bp->value) {
      return;
   }

   /* If the background isn't changing, don't do anything. */
   if(   lastBackground
      && bp->type == lastBackground->type
      && !strcmp(bp->value, lastBackground->value)) {
      return;
   }
   if(lastBackground && lastBackground->window) {
      JXUnmapWindow(display, lastBackground->window);
   }
   lastBackground = bp;

   /* Load the background based on type. */
   switch(bp->type) {
   case BACKGROUND_COMMAND:
      RunCommand(bp->value);
      return;
   default:
      attrValues = CWBackPixmap;
      attr.background_pixmap = bp->pixmap;
      break;
   }

   JXChangeWindowAttributes(display, bp->window, attrValues, &attr);
   JXClearWindow(display, bp->window);
   JXMapWindow(display, bp->window);

   SetPixmapAtom(rootWindow, ATOM_XSETROOT_ID, bp->window);

}
예제 #5
0
파일: event.c 프로젝트: pecarter-work/jwm
/** Handle a map request. */
void HandleMapRequest(const XMapEvent *event)
{
   ClientNode *np;
   Assert(event);
   if(CheckSwallowMap(event->window)) {
      return;
   }
   np = FindClientByWindow(event->window);
   if(!np) {
      GrabServer();
      np = AddClientWindow(event->window, 0, 1);
      if(np) {
         if(!(np->state.status & STAT_NOFOCUS)) {
            FocusClient(np);
         }
      } else {
         JXMapWindow(display, event->window);
      }
      UngrabServer();
   } else {
      if(!(np->state.status & STAT_MAPPED)) {
         UpdateState(np);
         np->state.status |= STAT_MAPPED;
         XMapWindow(display, np->window);
         if(np->parent != None) {
            XMapWindow(display, np->parent);
         }
         if(!(np->state.status & STAT_STICKY)) {
            np->state.desktop = currentDesktop;
         }
         if(!(np->state.status & STAT_NOFOCUS)) {
            FocusClient(np);
            RaiseClient(np);
         }
         WriteState(np);
         RequireTaskUpdate();
         RequirePagerUpdate();
      }
   }
   RequireRestack();
}
예제 #6
0
파일: client.c 프로젝트: pecarter-work/jwm
/** Unshade a client. */
void UnshadeClient(ClientNode *np)
{

   Assert(np);

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

   if(!(np->state.status & (STAT_MINIMIZED | STAT_SDESKTOP))) {
      JXMapWindow(display, np->window);
      np->state.status |= STAT_MAPPED;
   }
   np->state.status &= ~STAT_SHADED;

   WriteState(np);
   ResetBorder(np);
   RefocusClient();
   RequirePagerUpdate();

}
예제 #7
0
파일: tray.c 프로젝트: Nehamkin/jwm
/** Startup trays. */
void StartupTray(void)
{

   XSetWindowAttributes attr;
   Atom atom;
   unsigned long attrMask;
   TrayType *tp;
   TrayComponentType *cp;
   int variableSize;
   int variableRemainder;
   int width, height;
   int xoffset, yoffset;

   for(tp = trays; tp; tp = tp->next) {

      LayoutTray(tp, &variableSize, &variableRemainder);

      /* Create the tray window. */
      /* The window is created larger for a border. */
      attrMask = CWOverrideRedirect;
      attr.override_redirect = True;

      /* We can't use PointerMotionHintMask since the exact position
       * of the mouse on the tray is important for popups. */
      attrMask |= CWEventMask;
      attr.event_mask
         = ButtonPressMask
         | ButtonReleaseMask
         | SubstructureNotifyMask
         | ExposureMask
         | KeyPressMask
         | KeyReleaseMask
         | EnterWindowMask
         | PointerMotionMask;

      attrMask |= CWBackPixel;
      attr.background_pixel = colors[COLOR_TRAY_BG2];

      attrMask |= CWBorderPixel;
      attr.border_pixel = colors[COLOR_TRAY_OUTLINE];

      Assert(tp->width > 0);
      Assert(tp->height > 0);
      tp->window = JXCreateWindow(display, rootWindow,
                                  tp->x, tp->y, tp->width, tp->height,
                                  TRAY_BORDER_SIZE,
                                  rootVisual.depth, InputOutput,
                                  rootVisual.visual, attrMask, &attr);

      if(settings.trayOpacity < UINT_MAX) {
         /* Can't use atoms yet as it hasn't been initialized. */
         atom = JXInternAtom(display, opacityAtom, False);
         JXChangeProperty(display, tp->window, atom, XA_CARDINAL, 32,
                          PropModeReplace,
                          (unsigned char*)&settings.trayOpacity, 1);
      }

      SetDefaultCursor(tp->window);

      /* Create and layout items on the tray. */
      xoffset = 0;
      yoffset = 0;
      for(cp = tp->components; cp; cp = cp->next) {

         if(cp->Create) {
            if(tp->layout == LAYOUT_HORIZONTAL) {
               height = tp->height;
               width = cp->width;
               if(width == 0) {
                  width = variableSize;
                  if(variableRemainder) {
                     width += 1;
                     variableRemainder -= 1;
                  }
               }
            } else {
               width = tp->width;
               height = cp->height;
               if(height == 0) {
                  height = variableSize;
                  if(variableRemainder) {
                     height += 1;
                     variableRemainder -= 1;
                  }
               }
            }
            cp->width = Max(1, width);
            cp->height = Max(1, height);
            (cp->Create)(cp);
         }

         cp->x = xoffset;
         cp->y = yoffset;
         cp->screenx = tp->x + xoffset;
         cp->screeny = tp->y + yoffset;

         if(cp->window != None) {
            JXReparentWindow(display, cp->window, tp->window,
                             xoffset, yoffset);
         }

         if(tp->layout == LAYOUT_HORIZONTAL) {
            xoffset += cp->width;
         } else {
            yoffset += cp->height;
         }
      }

      /* Show the tray. */
      JXMapWindow(display, tp->window);

      trayCount += 1;

   }

   RequirePagerUpdate();
   RequireTaskUpdate();

}
예제 #8
0
파일: client.c 프로젝트: pecarter-work/jwm
/** Remove a client window from management. */
void RemoveClient(ClientNode *np)
{

   ColormapNode *cp;

   Assert(np);
   Assert(np->window != None);

   /* Remove this client from the client list */
   if(np->next) {
      np->next->prev = np->prev;
   } else {
      nodeTail[np->state.layer] = np->prev;
   }
   if(np->prev) {
      np->prev->next = np->next;
   } else {
      nodes[np->state.layer] = np->next;
   }
   clientCount -= 1;
   XDeleteContext(display, np->window, clientContext);
   if(np->parent != None) {
      XDeleteContext(display, np->parent, frameContext);
   }

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

   /* Make sure this client isn't active */
   if(activeClient == np && !shouldExit) {
      FocusNextStacked(np);
   }
   if(activeClient == np) {

      /* Must be the last client. */
      SetWindowAtom(rootWindow, ATOM_NET_ACTIVE_WINDOW, None);
      activeClient = NULL;
      JXSetInputFocus(display, rootWindow, RevertToParent, eventTime);

   }

   /* If the window manager is exiting (ie, not the client), then
    * reparent etc. */
   if(shouldExit && !(np->state.status & STAT_WMDIALOG)) {
      if(np->state.maxFlags) {
         np->x = np->oldx;
         np->y = np->oldy;
         np->width = np->oldWidth;
         np->height = np->oldHeight;
         JXMoveResizeWindow(display, np->window,
                            np->x, np->y, np->width, np->height);
      }
      GravitateClient(np, 1);
      if(!(np->state.status & STAT_MAPPED)
         && (np->state.status & (STAT_MINIMIZED | STAT_SHADED))) {
         JXMapWindow(display, np->window);
      }
      JXUngrabButton(display, AnyButton, AnyModifier, np->window);
      JXReparentWindow(display, np->window, rootWindow, np->x, np->y);
      JXRemoveFromSaveSet(display, np->window);
   }

   /* Destroy the parent */
   if(np->parent) {
      JXDestroyWindow(display, np->parent);
   }

   if(np->name) {
      Release(np->name);
   }
   if(np->instanceName) {
      JXFree(np->instanceName);
   }
   if(np->className) {
      JXFree(np->className);
   }

   RemoveClientFromTaskBar(np);
   RemoveClientStrut(np);

   while(np->colormaps) {
      cp = np->colormaps->next;
      Release(np->colormaps);
      np->colormaps = cp;
   }

   DestroyIcon(np->icon);

   Release(np);

   RequireRestack();

}
예제 #9
0
파일: client.c 프로젝트: pecarter-work/jwm
/** 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;

}
예제 #10
0
파일: tray.c 프로젝트: GustavoMOG/JWM
/** Startup trays. */
void StartupTray() {

   XSetWindowAttributes attr;
   Atom opacityAtom;
   unsigned long attrMask;
   TrayType *tp;
   TrayComponentType *cp;
   int variableSize;
   int variableRemainder;
   int width, height;
   int xoffset, yoffset;

   for(tp = trays; tp; tp = tp->next) {

      LayoutTray(tp, &variableSize, &variableRemainder);

      /* Create the tray window. */
      /* The window is created larger for a border. */
      attrMask = CWOverrideRedirect;
      attr.override_redirect = True;

      /* We can't use PointerMotionHintMask since the exact position
       * of the mouse on the tray is important for popups. */
      attrMask |= CWEventMask;
      attr.event_mask
         = ButtonPressMask
         | ButtonReleaseMask
         | SubstructureNotifyMask
         | ExposureMask
         | KeyPressMask
         | KeyReleaseMask
         | EnterWindowMask
         | PointerMotionMask;

      attrMask |= CWBackPixel;
      attr.background_pixel = colors[COLOR_TRAY_BG];

      tp->window = JXCreateWindow(display, rootWindow,
         tp->x, tp->y, tp->width, tp->height,
         0, rootDepth, InputOutput, rootVisual, attrMask, &attr);

      if(trayOpacity < UINT_MAX) {
         /* Can't use atoms yet as it hasn't been initialized. */
         opacityAtom = JXInternAtom(display, "_NET_WM_WINDOW_OPACITY", False);
         JXChangeProperty(display, tp->window, opacityAtom, XA_CARDINAL, 32,
            PropModeReplace, (unsigned char*)&trayOpacity, 1);
         JXSync(display, False);
      }

      SetDefaultCursor(tp->window);

      /* Create and layout items on the tray. */
      xoffset = tp->border;
      yoffset = tp->border;
      for(cp = tp->components; cp; cp = cp->next) {

         if(cp->Create) {
            if(tp->layout == LAYOUT_HORIZONTAL) {
               height = tp->height - 2 * tp->border;
               width = cp->width;
               if(width == 0) {
                  width = variableSize;
                  if(variableRemainder) {
                     ++width;
                     --variableRemainder;
                  }
               }
            } else {
               width = tp->width - 2 * tp->border;
               height = cp->height;
               if(height == 0) {
                  height = variableSize;
                  if(variableRemainder) {
                     ++height;
                     --variableRemainder;
                  }
               }
            }
            cp->width = width;
            cp->height = height;
            (cp->Create)(cp);
         }

         cp->x = xoffset;
         cp->y = yoffset;
         cp->screenx = tp->x + xoffset;
         cp->screeny = tp->y + yoffset;

         if(cp->window != None) {
            JXReparentWindow(display, cp->window, tp->window,
               xoffset, yoffset);
         }

         if(tp->layout == LAYOUT_HORIZONTAL) {
            xoffset += cp->width;
         } else {
            yoffset += cp->height;
         }
      }

      /* Show the tray. */
      JXMapWindow(display, tp->window);

      ++trayCount;

   }

   UpdatePager();
   UpdateTaskBar();

}