Ejemplo n.º 1
0
/** Set a client's desktop. This will update transients. */
void SetClientDesktop(ClientNode *np, unsigned int desktop)
{

   ClientNode *tp;

   Assert(np);

   if(JUNLIKELY(desktop >= settings.desktopCount)) {
      return;
   }

   if(!(np->state.status & STAT_STICKY)) {
      int x;
      for(x = 0; x < LAYER_COUNT; x++) {
         for(tp = nodes[x]; tp; tp = tp->next) {
            if(tp == np || tp->owner == np->window) {

               tp->state.desktop = desktop;

               if(desktop == currentDesktop) {
                  ShowClient(tp);
               } else {
                  HideClient(tp);
               }

               SetCardinalAtom(tp->window, ATOM_NET_WM_DESKTOP,
                               tp->state.desktop);
            }
         }
      }
      RequirePagerUpdate();
      RequireTaskUpdate();
   }

}
Ejemplo n.º 2
0
/** Set a client's state to withdrawn. */
void SetClientWithdrawn(ClientNode *np)
{

   Assert(np);

   if(activeClient == np) {
      activeClient = NULL;
      np->state.status &= ~STAT_ACTIVE;
      FocusNextStacked(np);
   }

   if(np->state.status & STAT_MAPPED) {
      UnmapClient(np);
      if(np->parent != None) {
         JXUnmapWindow(display, np->parent);
      }
   } else if(np->state.status & STAT_SHADED) {
      if(!(np->state.status & STAT_MINIMIZED)) {
         if(np->parent != None) {
            JXUnmapWindow(display, np->parent);
         }
      }
   }

   np->state.status &= ~STAT_SHADED;
   np->state.status &= ~STAT_MINIMIZED;
   np->state.status &= ~STAT_SDESKTOP;

   WriteState(np);
   RequireTaskUpdate();
   RequirePagerUpdate();

}
Ejemplo n.º 3
0
/** Minimize a client window and all of its transients. */
void MinimizeClient(ClientNode *np, char lower)
{
   Assert(np);
   MinimizeTransients(np, lower);
   RequireRestack();
   RequireTaskUpdate();
}
Ejemplo n.º 4
0
/** Update callback for clients with the urgency hint set. */
void SignalUrgent(const TimeType *now, int x, int y, Window w, void *data)
{

   ClientNode *np = (ClientNode*)data;

   /* Redraw borders. */
   if(np->state.status & STAT_FLASH) {
      np->state.status &= ~STAT_FLASH;
   } else if(!(np->state.status & STAT_NOTURGENT)) {
      np->state.status |= STAT_FLASH;
   }
   DrawBorder(np);
   RequireTaskUpdate();
   RequirePagerUpdate();

}
Ejemplo n.º 5
0
/** Set the active client. */
void FocusClient(ClientNode *np)
{
   if(np->state.status & STAT_HIDDEN) {
      return;
   }
   if(!(np->state.status & (STAT_CANFOCUS | STAT_TAKEFOCUS))) {
      return;
   }

   if(activeClient != np || !(np->state.status & STAT_ACTIVE)) {

      if(activeClient) {
         activeClient->state.status &= ~STAT_ACTIVE;
         if(!(activeClient->state.status & STAT_OPACITY)) {
            SetOpacity(activeClient, settings.inactiveClientOpacity, 0);
         }
         DrawBorder(activeClient);
      }
      np->state.status |= STAT_ACTIVE;
      activeClient = np;
      if(!(np->state.status & STAT_OPACITY)) {
         SetOpacity(np, settings.activeClientOpacity, 0);
      }

      DrawBorder(np);
      RequirePagerUpdate();
      RequireTaskUpdate();

   }

   if(np->state.status & STAT_MAPPED) {
      UpdateClientColormap(np);
      SetWindowAtom(rootWindow, ATOM_NET_ACTIVE_WINDOW, np->window);
      if(np->state.status & STAT_CANFOCUS) {
         JXSetInputFocus(display, np->window, RevertToParent, eventTime);
      }
      if(np->state.status & STAT_TAKEFOCUS) {
         SendClientMessage(np->window, ATOM_WM_PROTOCOLS, ATOM_WM_TAKE_FOCUS);
      }
   } else {
      JXSetInputFocus(display, rootWindow, RevertToParent, eventTime);
   }

}
Ejemplo n.º 6
0
/** 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();
}
Ejemplo n.º 7
0
/** Load windows that are already mapped. */
void StartupClients(void)
{

   XWindowAttributes attr;
   Window rootReturn, parentReturn, *childrenReturn;
   unsigned int childrenCount;
   unsigned int x;

   clientCount = 0;
   activeClient = NULL;
   currentDesktop = 0;

   /* Clear out the client lists. */
   for(x = 0; x < LAYER_COUNT; x++) {
      nodes[x] = NULL;
      nodeTail[x] = NULL;
   }

   /* Query client windows. */
   JXQueryTree(display, rootWindow, &rootReturn, &parentReturn,
               &childrenReturn, &childrenCount);

   /* Add each client. */
   for(x = 0; x < childrenCount; x++) {
      if(JXGetWindowAttributes(display, childrenReturn[x], &attr)) {
         if(attr.override_redirect == False && attr.map_state == IsViewable) {
            AddClientWindow(childrenReturn[x], 1, 1);
         }
      }
   }

   JXFree(childrenReturn);

   LoadFocus();

   RequireTaskUpdate();
   RequirePagerUpdate();

}
Ejemplo n.º 8
0
/** Add a client to the task bar. */
void AddClientToTaskBar(ClientNode *np)
{
   TaskEntry *tp = NULL;
   ClientEntry *cp = Allocate(sizeof(ClientEntry));
   cp->client = np;

   if(np->className && settings.groupTasks) {
      for(tp = taskEntries; tp; tp = tp->next) {
         const char *className = tp->clients->client->className;
         if(className && !strcmp(np->className, className)) {
            break;
         }
      }
   }
   if(tp == NULL) {
      tp = Allocate(sizeof(TaskEntry));
      tp->clients = NULL;
      tp->next = NULL;
      tp->prev = taskEntriesTail;
      if(taskEntriesTail) {
         taskEntriesTail->next = tp;
      } else {
         taskEntries = tp;
      }
      taskEntriesTail = tp;
   }

   cp->next = tp->clients;
   if(tp->clients) {
      tp->clients->prev = cp;
   }
   cp->prev = NULL;
   tp->clients = cp;

   RequireTaskUpdate();
   UpdateNetClientList();

}
Ejemplo n.º 9
0
/** Remove a client from the task bar. */
void RemoveClientFromTaskBar(ClientNode *np)
{
   TaskEntry *tp;
   for(tp = taskEntries; tp; tp = tp->next) {
      ClientEntry *cp;
      for(cp = tp->clients; cp; cp = cp->next) {
         if(cp->client == np) {
            if(cp->prev) {
               cp->prev->next = cp->next;
            } else {
               tp->clients = cp->next;
            }
            if(cp->next) {
               cp->next->prev = cp->prev;
            }
            Release(cp);
            if(!tp->clients) {
               if(tp->prev) {
                  tp->prev->next = tp->next;
               } else {
                  taskEntries = tp->next;
               }
               if(tp->next) {
                  tp->next->prev = tp->prev;
               } else {
                  taskEntriesTail = tp->prev;
               }
               Release(tp);
            }
            RequireTaskUpdate();
            UpdateNetClientList();
            return;
         }
      }
   }
}
Ejemplo n.º 10
0
Archivo: tray.c Proyecto: Nehamkin/jwm
/** Resize a tray. */
void ResizeTray(TrayType *tp)
{

   TrayComponentType *cp;
   int variableSize;
   int variableRemainder;
   int xoffset, yoffset;
   int width, height;

   Assert(tp);

   LayoutTray(tp, &variableSize, &variableRemainder);

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

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

      if(cp->Resize) {
         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 = width;
         cp->height = height;
         (cp->Resize)(cp);
      }

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

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

   JXMoveResizeWindow(display, tp->window, tp->x, tp->y,
                      tp->width, tp->height);

   RequireTaskUpdate();
   DrawSpecificTray(tp);

   if(tp->hidden) {
      HideTray(tp);
   }

}
Ejemplo n.º 11
0
Archivo: tray.c Proyecto: 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();

}
Ejemplo n.º 12
0
/** Handle a property notify event. */
char HandlePropertyNotify(const XPropertyEvent *event)
{
   ClientNode *np = FindClientByWindow(event->window);
   if(np) {
      char changed = 0;
      switch(event->atom) {
      case XA_WM_NAME:
         ReadWMName(np);
         changed = 1;
         break;
      case XA_WM_NORMAL_HINTS:
         ReadWMNormalHints(np);
         if(ConstrainSize(np)) {
            ResetBorder(np);
         }
         changed = 1;
         break;
      case XA_WM_HINTS:
         if(np->state.status & STAT_URGENT) {
            UnregisterCallback(SignalUrgent, np);
         }
         ReadWMHints(np->window, &np->state, 1);
         if(np->state.status & STAT_URGENT) {
            RegisterCallback(URGENCY_DELAY, SignalUrgent, np);
         }
         WriteState(np);
         break;
      case XA_WM_TRANSIENT_FOR:
         JXGetTransientForHint(display, np->window, &np->owner);
         break;
      case XA_WM_ICON_NAME:
      case XA_WM_CLIENT_MACHINE:
         break;
      default:
         if(event->atom == atoms[ATOM_WM_COLORMAP_WINDOWS]) {
            ReadWMColormaps(np);
            UpdateClientColormap(np);
         } else if(event->atom == atoms[ATOM_WM_PROTOCOLS]) {
            ReadWMProtocols(np->window, &np->state);
         } else if(event->atom == atoms[ATOM_NET_WM_ICON]) {
            LoadIcon(np);
            changed = 1;
         } else if(event->atom == atoms[ATOM_NET_WM_NAME]) {
            ReadWMName(np);
            changed = 1;
         } else if(event->atom == atoms[ATOM_NET_WM_STRUT_PARTIAL]) {
            ReadClientStrut(np);
         } else if(event->atom == atoms[ATOM_NET_WM_STRUT]) {
            ReadClientStrut(np);
         } else if(event->atom == atoms[ATOM_MOTIF_WM_HINTS]) {
            UpdateState(np);
            WriteState(np);
            ResetBorder(np);
            changed = 1;
         } else if(event->atom == atoms[ATOM_NET_WM_WINDOW_OPACITY]) {
            ReadWMOpacity(np->window, &np->state.opacity);
            if(np->parent != None) {
               SetOpacity(np, np->state.opacity, 1);
            }
         }
         break;
      }

      if(changed) {
         DrawBorder(np);
         RequireTaskUpdate();
         RequirePagerUpdate();
      }
      if(np->state.status & STAT_WMDIALOG) {
         return 0;
      } else {
         return 1;
      }
   }

   return 1;
}
Ejemplo n.º 13
0
/** Handle a _NET_WM_STATE request. */
void HandleNetWMState(const XClientMessageEvent *event, ClientNode *np)
{

   unsigned int x;
   MaxFlags maxFlags;
   char actionStick;
   char actionShade;
   char actionFullScreen;
   char actionMinimize;
   char actionNolist;
   char actionNopager;
   char actionBelow;
   char actionAbove;

   /* Up to two actions to be applied together. */
   maxFlags = MAX_NONE;
   actionStick = 0;
   actionShade = 0;
   actionFullScreen = 0;
   actionMinimize = 0;
   actionNolist = 0;
   actionNopager = 0;
   actionBelow = 0;
   actionAbove = 0;

   for(x = 1; x <= 2; x++) {
      if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_STICKY]) {
         actionStick = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_MAXIMIZED_VERT]) {
         maxFlags |= MAX_VERT;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_MAXIMIZED_HORZ]) {
         maxFlags |= MAX_HORIZ;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_SHADED]) {
         actionShade = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_FULLSCREEN]) {
         actionFullScreen = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_HIDDEN]) {
         actionMinimize = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_SKIP_TASKBAR]) {
         actionNolist = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_SKIP_PAGER]) {
         actionNopager = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_BELOW]) {
         actionBelow = 1;
      } else if(event->data.l[x]
         == (long)atoms[ATOM_NET_WM_STATE_ABOVE]) {
         actionAbove = 1;
      }
   }

   switch(event->data.l[0]) {
   case 0: /* Remove */
      if(actionStick) {
         SetClientSticky(np, 0);
      }
      if(maxFlags != MAX_NONE && np->state.maxFlags) {
         MaximizeClient(np, np->state.maxFlags & ~maxFlags);
      }
      if(actionShade) {
         UnshadeClient(np);
      }
      if(actionFullScreen) {
         SetClientFullScreen(np, 0);
      }
      if(actionMinimize) {
         RestoreClient(np, 0);
      }
      if(actionNolist) {
         np->state.status &= ~STAT_NOLIST;
         RequireTaskUpdate();
      }
      if(actionNopager) {
         np->state.status &= ~STAT_NOPAGER;
         RequirePagerUpdate();
      }
      if(actionBelow && np->state.layer == LAYER_BELOW) {
         SetClientLayer(np, np->state.defaultLayer);
      }
      if(actionAbove && np->state.layer == LAYER_ABOVE) {
         SetClientLayer(np, np->state.defaultLayer);
      }
      break;
   case 1: /* Add */
      if(actionStick) {
         SetClientSticky(np, 1);
      }
      if(maxFlags != MAX_NONE) {
         MaximizeClient(np, np->state.maxFlags | maxFlags);
      }
      if(actionShade) {
         ShadeClient(np);
      }
      if(actionFullScreen) {
         SetClientFullScreen(np, 1);
      }
      if(actionMinimize) {
         MinimizeClient(np, 1);
      }
      if(actionNolist) {
         np->state.status |= STAT_NOLIST;
         RequireTaskUpdate();
      }
      if(actionNopager) {
         np->state.status |= STAT_NOPAGER;
         RequirePagerUpdate();
      }
      if(actionBelow) {
         SetClientLayer(np, LAYER_BELOW);
      }
      if(actionAbove) {
         SetClientLayer(np, LAYER_ABOVE);
      }
      break;
   case 2: /* Toggle */
      if(actionStick) {
         if(np->state.status & STAT_STICKY) {
            SetClientSticky(np, 0);
         } else {
            SetClientSticky(np, 1);
         }
      }
      if(maxFlags) {
         MaximizeClient(np, np->state.maxFlags ^ maxFlags);
      }
      if(actionShade) {
         if(np->state.status & STAT_SHADED) {
            UnshadeClient(np);
         } else {
            ShadeClient(np);
         }
      }
      if(actionFullScreen) {
         if(np->state.status & STAT_FULLSCREEN) {
            SetClientFullScreen(np, 0);
         } else {
            SetClientFullScreen(np, 1);
         }
      }
      if(actionBelow) {
         if(np->state.layer == LAYER_BELOW) {
            SetClientLayer(np, np->state.defaultLayer);
         } else {
            SetClientLayer(np, LAYER_BELOW);
         }
      }
      if(actionAbove) {
         if(np->state.layer == LAYER_ABOVE) {
            SetClientLayer(np, np->state.defaultLayer);
         } else {
            SetClientLayer(np, LAYER_ABOVE);
         }
      }
      /* Note that we don't handle toggling of hidden per EWMH
       * recommendations. */
      if(actionNolist) {
         np->state.status ^= STAT_NOLIST;
         RequireTaskUpdate();
      }
      if(actionNopager) {
         np->state.status ^= STAT_NOPAGER;
         RequirePagerUpdate();
      }
      break;
   default:
      Debug("bad _NET_WM_STATE action: %ld", event->data.l[0]);
      break;
   }

   /* Update _NET_WM_STATE if needed.
    * The state update is handled elsewhere for the other actions.
    */
   if(actionNolist | actionNopager | actionAbove | actionBelow) {
      WriteState(np);
   }

}
Ejemplo n.º 14
0
/** Restore a client window and its transients. */
void RestoreClient(ClientNode *np, char raise)
{
   RestoreTransients(np, raise);
   RequireRestack();
   RequireTaskUpdate();
}