Beispiel #1
0
/** Show a popup window. */
void ShowPopup(int x, int y, const char *text,
               const PopupMaskType context)
{

   const ScreenType *sp;

   Assert(text);

   if(!(settings.popupMask & context)) {
      return;
   }

   if(popup.text) {
      if(x == popup.x && y == popup.y && !strcmp(popup.text, text)) {
         // This popup is already shown.
         return;
      }
      Release(popup.text);
      popup.text = NULL;
   }

   if(text[0] == 0) {
      return;
   }

   GetMousePosition(&popup.mx, &popup.my, &popup.mw);
   popup.text = CopyString(text);
   popup.height = GetStringHeight(FONT_POPUP) + 2;
   popup.width = GetStringWidth(FONT_POPUP, popup.text) + 9;

   sp = GetCurrentScreen(x, y);

   if(popup.width > sp->width) {
      popup.width = sp->width;
   }

   popup.x = x;
   if(y + 2 * popup.height + 2 >= sp->height) {
      popup.y = y - popup.height - 2;
   } else {
      popup.y = y + popup.height + 2;
   }

   if(popup.width + popup.x > sp->x + sp->width) {
      popup.x = sp->x + sp->width - popup.width - 2;
   }
   if(popup.height + popup.y > sp->y + sp->height) {
      popup.y = sp->y + sp->height - popup.height - 2;
   }
   if(popup.x < 2) {
      popup.x = 2;
   }
   if(popup.y < 2) {
      popup.y = 2;
   }

   if(popup.window == None) {

      XSetWindowAttributes attr;
      unsigned long attrMask = 0;

      attrMask |= CWEventMask;
      attr.event_mask = ExposureMask
                      | PointerMotionMask | PointerMotionHintMask;

      attrMask |= CWSaveUnder;
      attr.save_under = True;

      attrMask |= CWDontPropagate;
      attr.do_not_propagate_mask = PointerMotionMask
                                 | ButtonPressMask
                                 | ButtonReleaseMask;

      popup.window = JXCreateWindow(display, rootWindow, popup.x, popup.y,
                                    popup.width, popup.height, 0,
                                    CopyFromParent, InputOutput,
                                    CopyFromParent, attrMask, &attr);
      SetAtomAtom(popup.window, ATOM_NET_WM_WINDOW_TYPE,
                  ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION);
      JXMapRaised(display, popup.window);

   } else {

      JXMoveResizeWindow(display, popup.window, popup.x, popup.y,
                         popup.width, popup.height);
      JXFreePixmap(display, popup.pmap);

   }

   popup.pmap = JXCreatePixmap(display, popup.window,
                               popup.width, popup.height,
                               rootDepth);

   JXSetForeground(display, rootGC, colors[COLOR_POPUP_BG]);
   JXFillRectangle(display, popup.pmap, rootGC, 0, 0,
                   popup.width - 1, popup.height - 1);
   JXSetForeground(display, rootGC, colors[COLOR_POPUP_OUTLINE]);
   JXDrawRectangle(display, popup.pmap, rootGC, 0, 0,
                   popup.width - 1, popup.height - 1);
   RenderString(popup.pmap, FONT_POPUP, COLOR_POPUP_FG, 4, 1,
                popup.width, popup.text);
   JXCopyArea(display, popup.pmap, popup.window, rootGC,
              0, 0, popup.width, popup.height, 0, 0);

}
Beispiel #2
0
/** Constrain the size of the client. */
char ConstrainSize(ClientNode *np)
{

   BoundingBox box;
   const ScreenType *sp;
   int north, south, east, west;
   const int oldWidth = np->width;
   const int oldHeight = np->height;

   /* First we make sure the window isn't larger than the program allows.
    * We do this here to avoid moving the window below.
    */
   np->width = Min(np->width, np->maxWidth);
   np->height = Min(np->height, np->maxHeight);

   /* Constrain the width if necessary. */
   sp = GetCurrentScreen(np->x, np->y);
   GetScreenBounds(sp, &box);
   SubtractTrayBounds(GetTrays(), &box, np->state.layer);
   SubtractStrutBounds(&box, np);
   GetBorderSize(&np->state, &north, &south, &east, &west);
   if(np->width + east + west > sp->width) {
      box.x += west;
      box.width -= east + west;
      if(box.width > np->maxWidth) {
         box.width = np->maxWidth;
      }
      if(box.width > np->width) {
         box.width = np->width;
      }
      np->x = box.x;
      np->width = box.width - (box.width % np->xinc);
   }

   /* Constrain the height if necessary. */
   if(np->height + north + south > sp->height) {
      box.y += north;
      box.height -= north + south;
      if(box.height > np->maxHeight) {
         box.height = np->maxHeight;
      }
      if(box.height > np->height) {
         box.height = np->height;
      }
      np->y = box.y;
      np->height = box.height - (box.height % np->yinc);
   }

   /* If the program has a minimum constraint, we apply that here.
    * Note that this could cause the window to overlap something. */
   np->width = Max(np->width, np->minWidth);
   np->height = Max(np->height, np->minHeight);

   /* Fix the aspect ratio. */
   if(np->sizeFlags & PAspect) {
      if(np->width * np->aspect.miny < np->height * np->aspect.minx) {
         np->height = (np->width * np->aspect.miny) / np->aspect.minx;
      }
      if(np->width * np->aspect.maxy > np->height * np->aspect.maxx) {
         np->width = (np->height * np->aspect.maxx) / np->aspect.maxy;
      }
   }

   if(np->width != oldWidth || np->height != oldHeight) {
      return 1;
   } else {
      return 0;
   }

}
Beispiel #3
0
/** Place a maximized client on the screen. */
void PlaceMaximizedClient(ClientNode *np, MaxFlags flags)
{

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

   np->oldx = np->x;
   np->oldy = np->y;
   np->oldWidth = np->width;
   np->oldHeight = np->height;
   np->state.maxFlags = flags;

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

   sp = GetCurrentScreen(np->x + (east + west + np->width) / 2,
                         np->y + (north + south + np->height) / 2);
   GetScreenBounds(sp, &box);
   if(!(flags & (MAX_HORIZ | MAX_LEFT | MAX_RIGHT))) {
      box.x = np->x - west;
      box.width = np->width + east + west;
   }
   if(!(flags & (MAX_VERT | MAX_TOP | MAX_BOTTOM))) {
      box.y = np->y - north;
      box.height = np->height + north + south;
   }
   SubtractTrayBounds(GetTrays(), &box, np->state.layer);
   SubtractStrutBounds(&box, np);

   if(box.width > np->maxWidth) {
      box.width = np->maxWidth;
   }
   if(box.height > np->maxHeight) {
      box.height = np->maxHeight;
   }

   if(np->sizeFlags & PAspect) {
      if(box.width * np->aspect.miny < box.height * np->aspect.minx) {
         box.height = (box.width * np->aspect.miny) / np->aspect.minx;
      }
      if(box.width * np->aspect.maxy > box.height * np->aspect.maxx) {
         box.width = (box.height * np->aspect.maxx) / np->aspect.maxy;
      }
   }

   /* Remove window outlines. */
   if(flags & (MAX_VERT | MAX_TOP)) {
      north = Max(0, north - 1);
   }
   if(flags & (MAX_VERT | MAX_BOTTOM)) {
      south = Max(0, south - 1);
   }
   if(flags & (MAX_HORIZ | MAX_LEFT)) {
      west = Max(0, west - 1);
   }
   if(flags & (MAX_HORIZ | MAX_RIGHT)) {
      east = Max(0, east - 1);
   }

   /* If maximizing horizontally, update width. */
   if(flags & MAX_HORIZ) {
      np->x = box.x;
      np->width = box.width;
      if(!(np->state.status & STAT_IIGNORE)) {
         np->width -= ((np->width - np->baseWidth) % np->xinc);
      }
   } else if(flags & MAX_LEFT) {
      np->x = box.x;
      np->width = box.width / 2 - west;
      if(!(np->state.status & STAT_IIGNORE)) {
         np->width -= ((np->width - np->baseWidth) % np->xinc);
      }
   } else if(flags & MAX_RIGHT) {
      np->x = box.x + box.width / 2 + west;
      np->width = box.width / 2 - east;
      if(!(np->state.status & STAT_IIGNORE)) {
         np->width -= ((np->width - np->baseWidth) % np->xinc);
      }
   }

   /* If maximizing vertically, update height. */
   if(flags & MAX_VERT) {
      np->y = box.y + north;
      np->height = box.height - north;
      if(!(np->state.status & STAT_IIGNORE)) {
         np->height -= ((np->height - np->baseHeight) % np->yinc);
      }
   } else if(flags & MAX_TOP) {
      np->y = box.y + north;
      np->height = box.height / 2 - north - south;
      if(!(np->state.status & STAT_IIGNORE)) {
         np->height -= ((np->height - np->baseHeight) % np->yinc);
      }
   } else if(flags & MAX_BOTTOM) {
      np->y = box.y + box.height / 2 + north;
      np->height = box.height / 2 - north - south;
      if(!(np->state.status & STAT_IIGNORE)) {
         np->height -= ((np->height - np->baseHeight) % np->yinc);
      }
   }

}
Beispiel #4
0
/** Show the menu associated with a task list item. */
void ShowClientList(TaskBarType *bar, TaskEntry *tp)
{
   Menu *menu;
   MenuItem *item;
   ClientEntry *cp;

   const ScreenType *sp;
   int x, y;
   Window w;

   if(settings.groupTasks) {

      menu = CreateMenu();

      item = CreateMenuItem(MENU_ITEM_NORMAL);
      item->name = CopyString(_("Close"));
      item->action.type = MA_CLOSE | MA_GROUP_MASK;
      item->action.context = tp;
      item->next = menu->items;
      menu->items = item;

      item = CreateMenuItem(MENU_ITEM_NORMAL);
      item->name = CopyString(_("Minimize"));
      item->action.type = MA_MINIMIZE | MA_GROUP_MASK;
      item->action.context = tp;
      item->next = menu->items;
      menu->items = item;

      item = CreateMenuItem(MENU_ITEM_NORMAL);
      item->name = CopyString(_("Restore"));
      item->action.type = MA_RESTORE | MA_GROUP_MASK;
      item->action.context = tp;
      item->next = menu->items;
      menu->items = item;

      item = CreateMenuItem(MENU_ITEM_SUBMENU);
      item->name = CopyString(_("Send To"));
      item->action.type = MA_SENDTO_MENU | MA_GROUP_MASK;
      item->action.context = tp;
      item->next = menu->items;
      menu->items = item;

      /* Load the separator and group actions. */
      item = CreateMenuItem(MENU_ITEM_SEPARATOR);
      item->next = menu->items;
      menu->items = item;

      /* Load the clients into the menu. */
      for(cp = tp->clients; cp; cp = cp->next) {
         if(!ShouldFocus(cp->client, 0)) {
            continue;
         }
         item = CreateMenuItem(MENU_ITEM_NORMAL);
         if(cp->client->state.status & STAT_MINIMIZED) {
            size_t len = 0;
            if(cp->client->name) {
               len = strlen(cp->client->name);
            }
            item->name = Allocate(len + 3);
            item->name[0] = '[';
            memcpy(&item->name[1], cp->client->name, len);
            item->name[len + 1] = ']';
            item->name[len + 2] = 0;
         } else {
            item->name = CopyString(cp->client->name);
         }
         item->icon = cp->client->icon ? cp->client->icon : GetDefaultIcon();
         item->action.type = MA_EXECUTE;
         item->action.context = cp->client;
         item->next = menu->items;
         menu->items = item;
      }
   } else {
      /* Not grouping clients. */
      menu = CreateWindowMenu(tp->clients->client);
   }

   /* Initialize and position the menu. */
   InitializeMenu(menu);
   sp = GetCurrentScreen(bar->cp->screenx, bar->cp->screeny);
   GetMousePosition(&x, &y, &w);
   if(bar->layout == LAYOUT_HORIZONTAL) {
      if(bar->cp->screeny + bar->cp->height / 2 < sp->y + sp->height / 2) {
         /* Bottom of the screen: menus go up. */
         y = bar->cp->screeny + bar->cp->height;
      } else {
         /* Top of the screen: menus go down. */
         y = bar->cp->screeny - menu->height;
      }
      x -= menu->width / 2;
      x = Max(x, sp->x);
   } else {
      if(bar->cp->screenx + bar->cp->width / 2 < sp->x + sp->width / 2) {
         /* Left side: menus go right. */
         x = bar->cp->screenx + bar->cp->width;
      } else {
         /* Right side: menus go left. */
         x = bar->cp->screenx - menu->width;
      }
      y -= menu->height / 2;
      y = Max(y, sp->y);
   }

   ShowMenu(menu, RunTaskBarCommand, x, y, 0);

   DestroyMenu(menu);

}