Border.C

Index

      
      #include "Border.h"
      #include "Client.h"
      #include "Manager.h"
      #include "Rotated.h"
      
      // Some shaping mods due to Jacques Garrigue, garrigue@kurims.kyoto-u.ac.jp
      
      #if CONFIG_USE_PIXMAPS != False
  10  #include <X11/xpm.h>
      #include "background.xpm"
      #endif
      
      // These are degenerate initialisations, don't change them
      int Border::m_tabWidth = -1;
      XRotFontStruct *Border::m_tabFont = 0;
      GC Border::m_drawGC = 0;
      
      unsigned long Border::m_foregroundPixel;
  20  unsigned long Border::m_backgroundPixel;
      unsigned long Border::m_frameBackgroundPixel;
      unsigned long Border::m_buttonBackgroundPixel;
      unsigned long Border::m_borderPixel;
      Pixmap Border::m_backgroundPixmap = None;
      
      static int borderCounter = 0;
      
      
      class BorderRectangle  // must resemble XRectangle in storage
  30  {
      public:
          BorderRectangle() { }
          BorderRectangle(int xx, int yy, int ww, int hh) {
              x = xx; y = yy; width = ww; height = hh;
          }
          BorderRectangle(const BorderRectangle &b) {
              x = b.x; y = b.y; width = b.width; height = b.height;
          }
      
  40      XRectangle *xrectangle() { return (XRectangle *)this; }
      
          short x, y;
          unsigned short width, height;
      };
      
      declareList(RectangleList, BorderRectangle);
      implementList(RectangleList, BorderRectangle);
      
      class BorderRectangleList  : public RectangleList
  50  {
      public:
          BorderRectangleList() { }
          virtual ~BorderRectangleList() { }
      
          void append(const BorderRectangle &r) { RectangleList::append(r); }
          void append(int x, int y, int w, int h);
          XRectangle *xrectangles() { return (XRectangle *)array(0, count()); }
      };
      
  60  void BorderRectangleList::append(int x, int y, int w, int h)
      {
          append(BorderRectangle(x, y, w, h));
      }
      
      
      Border::Border(Client *const c, Window child) :
          m_client(c), m_parent(0), m_tab(0),
          m_child(child), m_button(0), m_resize(0), m_label(0),
          m_prevW(-1), m_prevH(-1), m_tabHeight(-1)
  70  {
          m_parent = root();
          if (m_tabFont == 0) initialiseStatics(c->windowManager());
          ++borderCounter;
      
      //#if CONFIG_MAD_FEEDBACK != 0
          m_feedback = 0;
          m_fedback = False;
      //#endif
      }
  80  
      
      Border::~Border()
      {
          if (m_parent != root()) {
              if (!m_parent) fprintf(stderr,"wmx: zero parent in Border::~Border\n");
              else {
                  XDestroyWindow(display(), m_tab);
                  XDestroyWindow(display(), m_button);
                  XDestroyWindow(display(), m_parent);
  90  
                  // bad window if its parent has already gone:
                  XDestroyWindow(display(), m_resize);
              }
          }
      
          if (m_label) free(m_label);
      
          if (--borderCounter == 0) {
              XFreeGC(display(), m_drawGC);
 100          m_drawGC = 0;
              if (m_backgroundPixmap != None) {
                  XFreePixmap(display(), m_backgroundPixmap);
              }
          }
      }
      
      
      void Border::initialiseStatics(WindowManager *wm)
      {
 110      if (m_drawGC) return;
      
          if (sizeof(BorderRectangle) != sizeof(XRectangle)) {
              wm->fatal("internal error: border rectangle and X rectangle\n"
                        "have different storage requirements -- bailing out");
          }
          
          if (!(m_tabFont = XRotLoadFont(wm->display(), CONFIG_NICE_FONT, 90.0)) &&
              !(m_tabFont = XRotLoadFont(wm->display(), CONFIG_NASTY_FONT, 90.0))) {
              wm->fatal("couldn't load default rotated font, bailing out");
 120      }
      
          m_tabWidth = m_tabFont->height + 4;
          if (m_tabWidth < TAB_TOP_HEIGHT * 2 + 8) {
              m_tabWidth = TAB_TOP_HEIGHT * 2 + 8;
          }
      
          m_foregroundPixel = wm->allocateColour
              (CONFIG_TAB_FOREGROUND, "tab foreground");
          m_backgroundPixel = wm->allocateColour
 130          (CONFIG_TAB_BACKGROUND, "tab background");
          m_frameBackgroundPixel = wm->allocateColour
              (CONFIG_FRAME_BACKGROUND, "frame background");
          m_buttonBackgroundPixel = wm->allocateColour
              (CONFIG_BUTTON_BACKGROUND, "button background");
          m_borderPixel = wm->allocateColour
              (CONFIG_BORDERS, "border");
      
          XGCValues values;
          values.foreground = m_foregroundPixel;
 140      values.background = m_backgroundPixel;
          values.function = GXcopy;
          values.line_width = 0;
          values.subwindow_mode = IncludeInferiors;
      
          m_drawGC = XCreateGC(wm->display(), wm->root(),
                               GCForeground | GCBackground | GCFunction |
                               GCLineWidth | GCSubwindowMode,
                               &values);
      
 150      if (!m_drawGC) {
              wm->fatal("couldn't allocate border GC");
          }
      
      #if CONFIG_USE_PIXMAPS != False
          if (CONFIG_USE_PIXMAPS) {
              int use_dynamic = True;
              XpmAttributes attrs;
              attrs.valuemask = 0L;
              char *home = getenv ("HOME");
 160          if (home) {
                  char *pixMapPath = (char *) malloc (sizeof (char) * (strlen (home)
                                        + strlen (CONFIG_COMMAND_MENU) + 20));
                  if (pixMapPath) {
                      strcpy (pixMapPath, home);
                      strcat (pixMapPath, "/");
                      strcat (pixMapPath, CONFIG_COMMAND_MENU);
                      strcat (pixMapPath, "/border.xpm");
      
                      // look for background pixmap file in
 170                  // the users .wmx directory. It is *not*
                      // an error, if none is found. (joze)
                      // 
                      // (todo: omit compiling in default pixmap, and look for
                      //  it in systemwide directory)
                      if (XpmReadFileToPixmap (wm->display(), wm->root(), pixMapPath,
                                               &m_backgroundPixmap, NULL, &attrs)
                          != XpmSuccess) {
                          use_dynamic = False;
                      }
 180                  free (pixMapPath);
                  }
              }
              if (use_dynamic == False
                  && XpmCreatePixmapFromData (wm->display(), wm->root(), background,
                                             &m_backgroundPixmap, NULL, &attrs)
                  != XpmSuccess) {
                  fprintf(stderr, "wmx: couldn't create background pixmap\n"); 
                  m_backgroundPixmap = None;
              }
 190      } else
      #endif  
              m_backgroundPixmap = None;
      }
      
      
      Pixmap Border::backgroundPixmap(WindowManager *wm)
      {
          if (!m_drawGC) Border::initialiseStatics(wm);
          return m_backgroundPixmap;
 200  }
      
      
      GC Border::drawGC(WindowManager *wm)
      {
          if (!m_drawGC) Border::initialiseStatics(wm);
          return m_drawGC;
      }
      
      
 210  void Border::fatal(char *s)
      {
          windowManager()->fatal(s);
      }
      
      
      Display *Border::display()
      {
          return m_client->display();
      }
 220  
      
      WindowManager *Border::windowManager()
      {
          return m_client->windowManager();
      }
      
      
      Window Border::root()
      {
 230      return m_client->root();
      }
      
      
      void Border::expose(XExposeEvent *e)
      {
          if (e->window != m_tab) return;
          drawLabel();
      }
      
 240  
      void Border::drawLabel()
      {
          if (m_label) {
              XClearWindow(display(), m_tab);
              XRotDrawString(display(), m_tabFont, m_tab, m_drawGC,
                             2 + m_tabFont->max_ascent, m_tabHeight - 1,
                             m_label, strlen(m_label));
          }
      }
 250  
      
      Boolean Border::isTransient(void)
      {
          return m_client->isTransient();
      }
      
      
      Boolean Border::isFixedSize(void)
      {
 260      return m_client->isFixedSize();
      }
      
      
      void Border::fixTabHeight(int maxHeight)
      {
          m_tabHeight = 0x7fff;
          maxHeight -= m_tabWidth;    // for diagonal
      
          // At least we need the button and its box.
 270      if (maxHeight < m_tabWidth + 2) maxHeight = m_tabWidth + 2;
      
          if (m_label) free(m_label);
          m_label = NewString(m_client->label());
          
          if (m_label) {
              m_tabHeight =
                  XRotTextWidth(m_tabFont, m_label, strlen(m_label)) + 6 + m_tabWidth;
          }
      
 280      if (m_tabHeight <= maxHeight) return;
      
      //!!!
      //    if (m_label) free(m_label);
      //    m_label = m_client->iconName() ?
      //      NewString(m_client->iconName()) : NewString("incognito");
          if (!m_label) {
              m_label = m_client->iconName() ?
                  NewString(m_client->iconName()) : NewString("incognito");
          }
 290  
          int len = strlen(m_label);
          m_tabHeight = XRotTextWidth(m_tabFont, m_label, len) + 6 + m_tabWidth;
          if (m_tabHeight <= maxHeight) return;
      
          char *newLabel = (char *)malloc(len + 3);
      
          do {
              strncpy(newLabel, m_label, len - 1);
              strcpy(newLabel + len - 1, "...");
 300          m_tabHeight = XRotTextWidth(m_tabFont, newLabel,
                                          strlen(newLabel)) + 6 + m_tabWidth;
              --len;
      
          } while (m_tabHeight > maxHeight && len > 2);
      
          free(m_label);
          m_label = newLabel;
      
          if (m_tabHeight > maxHeight) {
 310          m_tabHeight = maxHeight;
              free(m_label);
              m_label = NewString("");
          }
      }
      
      
      void Border::shapeTransientParent(int w, int h)
      {
          BorderRectangle r(xIndent() - 1, yIndent() - 1, w + 2, h + 2);
 320  
          XShapeCombineRectangles
              (display(), m_parent, ShapeBounding, 0, 0,
               r.xrectangle(), 1, ShapeSet, YXBanded);
      
          r = BorderRectangle(xIndent(), yIndent(), w, h);
      
          XShapeCombineRectangles
              (display(), m_parent, ShapeClip, 0, 0,
               r.xrectangle(), 1, ShapeSet, YXBanded);
 330  }
      
      
      void Border::setTransientFrameVisibility(Boolean visible, int w, int h)
      {
          int i;
          BorderRectangleList rl;
      
          rl.append(0, 0, w + 1, yIndent() - 1);
          for (i = 1; i < yIndent(); ++i) {
 340          rl.append(w + 1, i - 1, i + 1, 1);
          }
          rl.append(0, yIndent() - 1, xIndent() - 1, h - yIndent() + 2);
          for (i = 1; i < yIndent(); ++i) {
              rl.append(i - 1, h, 1, i + 2);
          }
      
          XShapeCombineRectangles
              (display(), m_parent, ShapeBounding,
               0, 0, rl.xrectangles(), rl.count(),
 350           visible ? ShapeUnion : ShapeSubtract, YXSorted);
      
          rl.remove_all();
      
          rl.append(1, 1, w, yIndent() - 2);
          for (i = 2; i < yIndent(); ++i) {
              rl.append(w + 1, i - 1, i, 1);
          }
          rl.append(1, yIndent() - 1, xIndent() - 2, h - yIndent() + 1);
          for (i = 2; i < yIndent(); ++i) {
 360          rl.append(i - 1, h, 1, i + 1);
          }
      
          XShapeCombineRectangles
              (display(), m_parent, ShapeClip,
               0, 0, rl.xrectangles(), rl.count(),
               visible ? ShapeUnion : ShapeSubtract, YXSorted);
      }   
      
      
 370  void Border::shapeParent(int w, int h)
      {
          int i;
          int mainRect;
          BorderRectangleList rl;
      
          if (isTransient()) {
              shapeTransientParent(w, h);
              return;
          }
 380  
          // Bounding rectangles -- clipping will be the same except for
          // child window border
      
          // top of tab
          rl.append(0, 0, w + m_tabWidth + 1, TAB_TOP_HEIGHT + 2);
      
          // struts in tab, left...
          rl.append(0, TAB_TOP_HEIGHT + 1,
                    TAB_TOP_HEIGHT + 2, m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
 390  
          // ...and right
          rl.append(m_tabWidth - TAB_TOP_HEIGHT, TAB_TOP_HEIGHT + 1,
                    TAB_TOP_HEIGHT + 2, m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
      
          mainRect = rl.count();
          rl.append(xIndent() - 1, yIndent() - 1, w + 2, h + 2);
      
          // main tab
          rl.append(0, m_tabWidth - TAB_TOP_HEIGHT, m_tabWidth + 2,
 400                m_tabHeight - m_tabWidth + TAB_TOP_HEIGHT);
      
          // diagonal
          for (i = 1; i < m_tabWidth - 1; ++i) {
              int y = m_tabHeight + i - 1;
              /* JG: Check position */
              if (y < h) rl.append(i, y, m_tabWidth - i + 2, 1);
      //      rl.append(i, m_tabHeight + i - 1, m_tabWidth - i + 2, 1);
          }
      
 410      XShapeCombineRectangles
              (display(), m_parent, ShapeBounding,
               0, 0, rl.xrectangles(), rl.count(), ShapeSet, YXSorted);
      
          rl.item(mainRect).x ++;
          rl.item(mainRect).y ++;
          rl.item(mainRect).width -= 2;
          rl.item(mainRect).height -= 2;
      
          XShapeCombineRectangles
 420          (display(), m_parent, ShapeClip,
               0, 0, rl.xrectangles(), rl.count(), ShapeSet, YXSorted);
      }
      
      
      void Border::shapeTab(int w, int h)
      {
          int i;
          BorderRectangleList rl;
      
 430      if (isTransient()) {
              return;
          }
      
          // Bounding rectangles
      
          rl.append(0, 0, w + m_tabWidth + 1, TAB_TOP_HEIGHT + 2);
          rl.append(0, TAB_TOP_HEIGHT + 1, TAB_TOP_HEIGHT + 2,
                    m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
          
 440      rl.append(m_tabWidth - TAB_TOP_HEIGHT, TAB_TOP_HEIGHT + 1,
                    TAB_TOP_HEIGHT + 2, m_tabWidth - TAB_TOP_HEIGHT*2 - 1);
      
          rl.append(0, m_tabWidth - TAB_TOP_HEIGHT, m_tabWidth + 2,
                    m_tabHeight - m_tabWidth + TAB_TOP_HEIGHT);
      
          for (i = 1; i < m_tabWidth - 1; ++i) {
              int y = m_tabHeight + i - 1;
              /* JG: Check position */
              if (y <= h) rl.append(i, y, m_tabWidth - i + 2, 1);
 450  //      rl.append(i, m_tabHeight + i - 1, m_tabWidth - i + 2, 1);
          }
      
          XShapeCombineRectangles
              (display(), m_tab, ShapeBounding,
               0, 0, rl.xrectangles(), rl.count(), ShapeSet, YXSorted);
      
          rl.remove_all();
      
          // Clipping rectangles
 460  
          rl.append(1, 1, w + m_tabWidth - 1, TAB_TOP_HEIGHT);
      
          rl.append(1, TAB_TOP_HEIGHT + 1, TAB_TOP_HEIGHT,
                    m_tabWidth + TAB_TOP_HEIGHT*2 - 1);
      
          rl.append(m_tabWidth - TAB_TOP_HEIGHT + 1, TAB_TOP_HEIGHT + 1,
                    TAB_TOP_HEIGHT, m_tabWidth + TAB_TOP_HEIGHT*2 - 1);
      
          rl.append(1, m_tabWidth - TAB_TOP_HEIGHT + 1, m_tabWidth,
 470                m_tabHeight - m_tabWidth + TAB_TOP_HEIGHT - 1);
      
          for (i = 1; i < m_tabWidth - 2; ++i) {
              int y = m_tabHeight + i - 1;
              /* JG: Check position */
              if (y < h) rl.append(i + 1, y, m_tabWidth - i, 1);
      //      rl.append(i + 1, m_tabHeight + i - 1, m_tabWidth - i, 1);
          }
      
          XShapeCombineRectangles
 480          (display(), m_tab, ShapeClip,
               0, 0, rl.xrectangles(), rl.count(), ShapeSet, YXSorted);
      }
      
      
      void Border::resizeTab(int h)
      {
          int i;
          int shorter, longer, operation;
      
 490      if (isTransient()) {
              return;
          }
      
          int prevTabHeight = m_tabHeight;
          fixTabHeight(h);
          // If resize is not needed, title might be needed redraw.
          // Because this is called from rename() sometimes.
          // So do it independently.
          if (m_tabHeight == prevTabHeight) drawLabel();
 500      if (m_tabHeight == prevTabHeight) return;
      
          XWindowChanges wc;
          wc.height = m_tabHeight + 2 + m_tabWidth;
          XConfigureWindow(display(), m_tab, CWHeight, &wc);
      
          if (m_tabHeight > prevTabHeight) {
      
              shorter = prevTabHeight;
              longer = m_tabHeight;
 510          operation = ShapeUnion;
      
          } else {
      
              shorter = m_tabHeight;
              longer = prevTabHeight + m_tabWidth;
              operation = ShapeSubtract;
          }
      
          BorderRectangle r(0, shorter, m_tabWidth + 2, longer - shorter);
 520  
          XShapeCombineRectangles(display(), m_parent, ShapeBounding,
                                  0, 0, r.xrectangle(), 1, operation, YXBanded);
      
          XShapeCombineRectangles(display(), m_parent, ShapeClip,
                                  0, 0, r.xrectangle(), 1, operation, YXBanded);
      
          XShapeCombineRectangles(display(), m_tab, ShapeBounding,
                                  0, 0, r.xrectangle(), 1, operation, YXBanded);
      
 530      r.x ++; r.width -= 2;
      
          XShapeCombineRectangles(display(), m_tab, ShapeClip,
                                  0, 0, r.xrectangle(), 1, operation, YXBanded);
      
          if (m_client->isActive()) {
              // restore a bit of the frame edge
              r.x = m_tabWidth + 1; r.y = shorter;
              r.width = FRAME_WIDTH - 1; r.height = longer - shorter;
              XShapeCombineRectangles(display(), m_parent, ShapeBounding,
 540                                  0, 0, r.xrectangle(), 1, ShapeUnion, YXBanded);
          }
      
          BorderRectangleList rl;
          for (i = 1; i < m_tabWidth - 1; ++i) {
              rl.append(i, m_tabHeight + i - 1, m_tabWidth - i + 2, 1);
          }
              
          XShapeCombineRectangles
              (display(), m_parent, ShapeBounding,
 550           0, 0, rl.xrectangles(), rl.count(), ShapeUnion, YXBanded);
      
          XShapeCombineRectangles
              (display(), m_parent, ShapeClip,
               0, 0, rl.xrectangles(), rl.count(), ShapeUnion, YXBanded);
      
          XShapeCombineRectangles
              (display(), m_tab, ShapeBounding,
               0, 0, rl.xrectangles(), rl.count(), ShapeUnion, YXBanded);
      
 560      if (rl.count() < 2) return;
      
          for (i = 0; i < rl.count() - 1; ++i) {
              rl.item(i).x ++; rl.item(i).width -= 2;
          }
      
          XShapeCombineRectangles
              (display(), m_tab, ShapeClip,
               0, 0, rl.xrectangles(), rl.count() - 1, ShapeUnion, YXBanded);
      }
 570  
      
      void Border::shapeResize()
      {
          int i;
          BorderRectangleList rl;
      
          for (i = 0; i < FRAME_WIDTH*2; ++i) {
              rl.append(FRAME_WIDTH*2 - i - 1, i, i + 1, 1);
          }
 580  
          XShapeCombineRectangles
              (display(), m_resize, ShapeBounding, 0, 0,
               rl.xrectangles(), rl.count(), ShapeSet, YXBanded);
      
          rl.remove_all();
      
          for (i = 1; i < FRAME_WIDTH*2; ++i) {
              rl.append(FRAME_WIDTH*2 - i, i, i, 1);
          }
 590  
          XShapeCombineRectangles
              (display(), m_resize, ShapeClip, 0, 0,
               rl.xrectangles(), rl.count(), ShapeSet, YXBanded);
      
          rl.remove_all();
      
          for (i = 0; i < FRAME_WIDTH*2 - 3; ++i) {
              rl.append(FRAME_WIDTH*2 - i - 1, i + 3, 1, 1);
          }
 600  
          XShapeCombineRectangles
              (display(), m_resize, ShapeClip, 0, 0,
               rl.xrectangles(), rl.count(), ShapeSubtract, YXBanded);
      
          windowManager()->installCursorOnWindow
              (WindowManager::DownrightCursor, m_resize);
      }
      
      
 610  void Border::setFrameVisibility(Boolean visible, int w, int h)
      {
          BorderRectangleList rl;
      
          if (CONFIG_PROD_SHAPE) {
              shapeParent(w, h);
              shapeTab(w, h);
          }
      
          if (isTransient()) {
 620          setTransientFrameVisibility(visible, w, h);
              return;
          }
      
          // Bounding rectangles
      
          rl.append(m_tabWidth + w + 1, 0, FRAME_WIDTH + 1, FRAME_WIDTH);
      
          rl.append(m_tabWidth + 2, TAB_TOP_HEIGHT + 2, w,
                    FRAME_WIDTH - TAB_TOP_HEIGHT - 2);
 630  
          // for button
          int ww = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
          rl.append((m_tabWidth + 2 - ww) / 2, (m_tabWidth+2 - ww) / 2, ww, ww);
      
          rl.append(m_tabWidth + 2, FRAME_WIDTH,
                    FRAME_WIDTH - 2, m_tabHeight + m_tabWidth - FRAME_WIDTH - 2);
      
          // swap last two if sorted wrong
          if (rl.item(rl.count()-2).y > rl.item(rl.count()-1).y) {
 640          rl.append(rl.item(rl.count()-2));
              rl.remove(rl.count()-3);
          }
      
          int final = rl.count();
          rl.append(rl.item(final-1));
          rl.item(final).x -= 1;
          rl.item(final).y += rl.item(final).height;
          rl.item(final).width += 1;
          rl.item(final).height = h - rl.item(final).height + 2;
 650  
          XShapeCombineRectangles(display(), m_parent, ShapeBounding,
                                  0, 0, rl.xrectangles(), rl.count(),
                                  visible ? ShapeUnion : ShapeSubtract, YXSorted);
          rl.remove_all();
      
          // Clip rectangles
      
          rl.append(m_tabWidth + w + 1, 1, FRAME_WIDTH, FRAME_WIDTH - 1);
      
 660      rl.append(m_tabWidth + 2, TAB_TOP_HEIGHT + 2, w,
                    FRAME_WIDTH - TAB_TOP_HEIGHT - 2);
      
          // for button
          ww = m_tabWidth - TAB_TOP_HEIGHT*2 - 6;
          rl.append((m_tabWidth + 2 - ww) / 2, (m_tabWidth+2 - ww) / 2, ww, ww);
      
          rl.append(m_tabWidth + 2, FRAME_WIDTH,
                    FRAME_WIDTH - 2, h - FRAME_WIDTH);
      
 670      // swap last two if sorted wrong
          if (rl.item(rl.count()-2).y > rl.item(rl.count()-1).y) {
              rl.append(rl.item(rl.count()-2));
              rl.remove(rl.count()-3);
          }
      
          rl.append(m_tabWidth + 2, h, FRAME_WIDTH - 2, FRAME_WIDTH + 1);
      
          XShapeCombineRectangles(display(), m_parent, ShapeClip,
                                  0, 0, rl.xrectangles(), rl.count(),
 680                              visible ? ShapeUnion : ShapeSubtract, YXSorted);
          rl.remove_all();
      
          if (visible && !isFixedSize()) {
              XMapRaised(display(), m_resize);
          } else {
              XUnmapWindow(display(), m_resize);
          }
      }
      
 690  
      void Border::configure(int x, int y, int w, int h,
                             unsigned long mask, int detail,
                             Boolean force) // must reshape everything
      {
          if (!m_parent || m_parent == root()) {
      
              // create windows, then shape them afterwards
      
              m_parent = XCreateSimpleWindow
 700              (display(), root(), 1, 1, 1, 1, 0,
                   m_borderPixel, m_frameBackgroundPixel);
      
              m_tab = XCreateSimpleWindow
                  (display(), m_parent, 1, 1, 1, 1, 0,
                   m_borderPixel, m_backgroundPixel);
      
              m_button = XCreateSimpleWindow
                  (display(), m_parent, 1, 1, 1, 1, 0,
                   m_borderPixel, m_buttonBackgroundPixel);
 710  
              m_resize = XCreateWindow
                  (display(), m_parent, 1, 1, FRAME_WIDTH*2, FRAME_WIDTH*2, 0,
                   CopyFromParent, InputOutput, CopyFromParent, 0L, 0);
      
      //#if CONFIG_MAD_FEEDBACK != 0
              if (CONFIG_MAD_FEEDBACK) {
                  m_feedback = XCreateSimpleWindow
                      (display(), root(), 0, 0, 1, 1, 1,
                       m_borderPixel, m_backgroundPixel);
 720          }
      //#endif
      
              shapeResize();
      
              XSelectInput(display(), m_parent,
                           SubstructureRedirectMask | SubstructureNotifyMask |
                           ButtonPressMask | ButtonReleaseMask);
      
              if (!isTransient()) {
 730              XSelectInput(display(), m_tab,
                               ExposureMask | ButtonPressMask | ButtonReleaseMask |
                               EnterWindowMask);
              }
      
              XSelectInput(display(), m_button, ButtonPressMask | ButtonReleaseMask);
              XSelectInput(display(), m_resize, ButtonPressMask | ButtonReleaseMask);
              mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
      
              XSetWindowAttributes wa;
 740          wa.background_pixmap = m_backgroundPixmap;
      
              if (m_backgroundPixmap) {
                  XChangeWindowAttributes(display(), m_parent, CWBackPixmap, &wa);
                  XChangeWindowAttributes(display(), m_tab,    CWBackPixmap, &wa);
                  XChangeWindowAttributes(display(), m_button, CWBackPixmap, &wa);
              }
      
              if (CONFIG_MAD_FEEDBACK) {
                  wa.save_under =
 750                  (DoesSaveUnders(ScreenOfDisplay(display(), 0)) ? True : False);
                  if (m_backgroundPixmap) {
                      XChangeWindowAttributes
                          (display(), m_feedback, CWSaveUnder | CWBackPixmap, &wa);
                  } else {
                      XChangeWindowAttributes(display(), m_feedback, CWSaveUnder, &wa);
                  }
              }
          }
      
 760      XWindowChanges wc;
          wc.x = x - xIndent();
          wc.y = y - yIndent();
          wc.width  = w + xIndent() + 1;
          wc.height = h + yIndent() + 1;
          wc.border_width = 0;
          wc.sibling = None;
          wc.stack_mode = detail;
          XConfigureWindow(display(), m_parent, mask, &wc);
      
 770      unsigned long rmask = 0L;
          if (mask & CWWidth)  rmask |= CWX;
          if (mask & CWHeight) rmask |= CWY;
          wc.x = w - FRAME_WIDTH*2 + xIndent();
          wc.y = h - FRAME_WIDTH*2 + yIndent();
          XConfigureWindow(display(), m_resize, rmask, &wc);
          
          if (force ||
              (m_prevW < 0 || m_prevH < 0) ||
              ((mask & (CWWidth | CWHeight)) && (w != m_prevW || h != m_prevH))) {
 780  
              int prevTabHeight = m_tabHeight;
              if (isTransient()) m_tabHeight = 10; // arbitrary
              else fixTabHeight(h);
      
              shapeParent(w, h);
              setFrameVisibility(m_client->isActive(), w, h);
      
              if (force ||
                  prevTabHeight != m_tabHeight || m_prevW < 0 || m_prevH < 0) {
 790  
                  wc.x = 0;
                  wc.y = 0;
                  wc.width = w + xIndent();
                  wc.height = m_tabHeight + 2 + m_tabWidth;
                  XConfigureWindow(display(), m_tab, mask, &wc);
                  shapeTab(w, h);
              }
      
              m_prevW = w;
 800          m_prevH = h;
      
          } else {
      
              resizeTab(h);
          }
      
          wc.x = TAB_TOP_HEIGHT + 2;
          wc.y = wc.x;
          wc.width = wc.height = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
 810      XConfigureWindow(display(), m_button, mask, &wc);
      }
      
      
      void Border::moveTo(int x, int y)
      {
          XWindowChanges wc;
          wc.x = x - xIndent();
          wc.y = y - yIndent();
          XConfigureWindow(display(), m_parent, CWX | CWY, &wc);
 820  }
      
      
      void Border::map()
      {
          if (m_parent == root()) {
              fprintf(stderr, "wmx: bad parent in Border::map()\n");
          } else {
              XMapWindow(display(), m_parent);
      
 830          if (!isTransient()) {
                  XMapWindow(display(), m_tab);
                  XMapWindow(display(), m_button);
              }
      
              if (!isFixedSize()) XMapWindow(display(), m_resize);
          }
      }
      
      
 840  void Border::mapRaised()
      {
          if (m_parent == root()) {
              fprintf(stderr, "wmx: bad parent in Border::mapRaised()\n");
          } else {
              XMapRaised(display(), m_parent);
      
              if (!isTransient()) {
                  XMapWindow(display(), m_tab);
                  XMapRaised(display(), m_button);
 850          }
      
              if (!isFixedSize()) XMapRaised(display(), m_resize);
          }
      }
      
      
      void Border::lower()
      {
          XLowerWindow(display(), m_parent);
 860  }
      
      
      void Border::unmap()
      {
          if (m_parent == root()) {
              fprintf(stderr, "wmx: bad parent in Border::unmap()\n");
          } else {
              XUnmapWindow(display(), m_parent);
      
 870          if (!isTransient()) {
                  XUnmapWindow(display(), m_tab);
                  XUnmapWindow(display(), m_button);
      //          XUnmapWindow(display(), m_resize); // no, will unmap with parent
              }
          }
      }
      
      
      void Border::decorate(Boolean active, int w, int h)
 880  {
          setFrameVisibility(active, w, h);
      }
      
      
      void Border::reparent()
      {
          XReparentWindow(display(), m_child, m_parent, xIndent(), yIndent());
      }
      
 890  
      void Border::toggleFeedback(int x, int y, int w, int h)
      {
          m_fedback = !m_fedback;
          if (!m_feedback || !CONFIG_MAD_FEEDBACK) return;
      
          if (m_fedback) {
      
              w += CONFIG_FRAME_THICKNESS + 1;
              h += CONFIG_FRAME_THICKNESS - TAB_TOP_HEIGHT + 1;
 900  
              XMoveResizeWindow(display(), m_feedback,
                                x - CONFIG_FRAME_THICKNESS - 1,
                                y - CONFIG_FRAME_THICKNESS + TAB_TOP_HEIGHT - 1,
                                w, h);
      
              XRectangle r[2];
      
              r[0].x = 0; r[0].y = 0; r[0].width = w;
              r[0].height = CONFIG_FRAME_THICKNESS - 2;
 910          r[1].x = 0; r[1].y = r[0].height; r[1].width = r[0].height + 2;
              r[1].height = h - r[0].height;
      
              XShapeCombineRectangles(display(), m_feedback, ShapeBounding,
                                      0, 0, r, 2, ShapeSet, YXBanded);
      
              r[0].x++; r[0].y++; r[0].width -= 2; r[0].height -= 2;
              r[1].x++; r[1].y--; r[1].width -= 2;
      
              XShapeCombineRectangles(display(), m_feedback, ShapeClip, 0, 0, r, 2,
 920                                  ShapeSet, YXBanded);
      
      /* I just can't decide!
      
              r[0].x = w - 1; r[0].y = 0; r[0].width = 1; r[0].height = h - 1;
              r[1].x = 0; r[1].y = h - 1; r[1].width = w - 1; r[1].height = 1;
      
              XShapeCombineRectangles(display(), m_feedback, ShapeBounding,
                                      0, 0, r, 2, ShapeUnion, YXBanded);
                                      */
 930          XMapRaised(display(), m_feedback);
      
          } else {
              XUnmapWindow(display(), m_feedback);
          }
      }
      
      void Border::showFeedback(int x, int y, int w, int h)
      {
          if (!m_fedback) toggleFeedback(x, y, w, h);
 940  }
      
      void Border::removeFeedback()
      {
          if (m_fedback) toggleFeedback(0, 0, 0, 0);
      }
      
      
      
      

Index

  • BorderRectangle Class declaration
  • BorderRectangle (constructor)
  • BorderRectangle (constructor)
  • BorderRectangle (constructor)
  • xrectangle (function) returns XRectangle *
  • BorderRectangleList Class declaration
  • BorderRectangleList (constructor)
  • append (function) returns void
  • append (prototype) returns void
  • xrectangles (function) returns XRectangle *
  • BorderRectangleList::append (function) returns void
  • Border::initialiseStatics (function) returns void
  • Border::backgroundPixmap (function) returns Pixmap
  • Border::drawGC (function) returns GC
  • Border::fatal (function) returns void
  • Border::display (function) returns Display *
  • Border::windowManager (function) returns WindowManager *
  • Border::root (function) returns Window
  • Border::expose (function) returns void
  • Border::drawLabel (function) returns void
  • Border::isTransient (function) returns Boolean
  • Border::isFixedSize (function) returns Boolean
  • Border::fixTabHeight (function) returns void
  • Border::shapeTransientParent (function) returns void
  • Border::setTransientFrameVisibility (function) returns void
  • Border::shapeParent (function) returns void
  • Border::shapeTab (function) returns void
  • Border::resizeTab (function) returns void
  • Border::shapeResize (function) returns void
  • Border::setFrameVisibility (function) returns void
  • Border::configure (function) returns void
  • Border::moveTo (function) returns void
  • Border::map (function) returns void
  • Border::mapRaised (function) returns void
  • Border::lower (function) returns void
  • Border::unmap (function) returns void
  • Border::decorate (function) returns void
  • Border::reparent (function) returns void
  • Border::toggleFeedback (function) returns void
  • Border::showFeedback (function) returns void
  • Border::removeFeedback (function) returns void