Buttons.C

Index

      
      #include "Manager.h"
      #include "Client.h"
      #include "Menu.h"
      #include <X11/keysym.h>
      #include <sys/time.h>
      
      
      void WindowManager::eventButton(XButtonEvent *e)
  10  {
          Client *c = windowToClient(e->window);
      
          if (e->button == Button3 && m_channelChangeTime == 0) {
              if (dConfig.rightCirculate())
              circulate(e->window == e->root);
              else if (dConfig.rightLower())
                  if (e->window != e->root) c->lower();
              return;
          }
  20  
          if (e->window == e->root) {
      
              if (e->button == Button1 && m_channelChangeTime == 0) {
                  ClientMenu menu(this, (XEvent *)e);
      
              } else if (e->x > DisplayWidth(display(), screen()) -
                         CONFIG_CHANNEL_CLICK_SIZE &&
                         e->y < CONFIG_CHANNEL_CLICK_SIZE) {
      
  30              if (e->button == Button2) {
      
                      if (m_channelChangeTime == 0) flipChannel(True, False, False,0);
                      else flipChannel(False, False, False, 0);
      
                  } else if (e->button == Button1 && m_channelChangeTime != 0) {
      
                      flipChannel(False, True, False, 0);
                  }
      
  40          } else if (e->button == Button2 && m_channelChangeTime == 0) {
                  dConfig.scan();
                  CommandMenu menu(this, (XEvent *)e);
              }
      
          } else if (c) {
      
              if (e->button == Button2 && CONFIG_CHANNEL_SURF) {
                  if (m_channelChangeTime == 0) flipChannel(True, False, False, 0);
                  else flipChannel(False, False, False, c);
  50              return;
              }
      
              c->eventButton(e);
              return;
          }
      }
      
      
      void WindowManager::circulate(Boolean activeFirst)
  60  {
          Client *c = 0;
          if (m_clients.count() == 0) return;
          if (activeFirst) c = m_activeClient;
      
          if (!c) {
      
              int i, j;
      
              if (!m_activeClient) i = -1;
  70          else {
                  for (i = 0; i < m_clients.count(); ++i) {
                      if (m_clients.item(i)->channel() != channel()) continue;
                      if (m_clients.item(i) == m_activeClient) break;
                  }
      
                  if (i >= m_clients.count()-1) i = -1;
              }
      
              for (j = i + 1;
  80               (!m_clients.item(j)->isNormal() ||
                     m_clients.item(j)->isTransient() ||
                     m_clients.item(j)->channel() != channel()); ++j) {
      
                  if (j >= m_clients.count() - 1) j = -1;
                  if (j == i) return; // no suitable clients
              }
      
              c = m_clients.item(j);
          }
  90  
          c->activateAndWarp();
      }
      
      void WindowManager::eventKeyPress(XKeyEvent *ev)
      {
          KeySym key = XKeycodeToKeysym(display(), ev->keycode, 0);
      
          if (CONFIG_USE_KEYBOARD) {
      
 100          Client *c = windowToClient(ev->window);
      
              if (key == CONFIG_QUICKRAISE_KEY && c) {
      
                  if (isTop(c) && (CONFIG_QUICKRAISE_ALSO_LOWERS == True)) {
                      c->lower();
                  } else {
                      c->mapRaised();
                  }
      
 110          } else if (key == CONFIG_QUICKHIDE_KEY && c) {
                  c->hide();
      
              } else if (key == CONFIG_QUICKHEIGHT_KEY && c) {
      
                  if (c->isFullHeight()) {
                      c->normalHeight();
                  } else {
                      c->fullHeight();
                  }
 120  
              } else if (ev->state & CONFIG_ALT_KEY_MASK) {
      
                  if (key >= XK_F1 && key <= XK_F12 &&
                      CONFIG_CHANNEL_SURF && CONFIG_USE_CHANNEL_KEYS) {
      
                      int channel = key - XK_F1 + 1;
                  
                      if (channel == m_currentChannel) {
      
 130                      flipChannel(True, False, False, 0);
      
                      } else if (channel > 0 && channel <= m_channels) {
      
                          while (m_currentChannel != channel) {
                              if (m_currentChannel < channel) {
                                  flipChannel(False, False, True, 0);
                              } else {
                                  flipChannel(False, True, True, 0);
                              }
 140                          XSync(display(), False);
                          }
                      }
      
                  } else {
      
                      // These key names also appear in Client::manage(), so
                      // when adding a key it must be added in both places
      
                      switch (key) {
 150  
                      case CONFIG_FLIP_DOWN_KEY:
                          flipChannel(False, True, False, 0);
                          break;
      
                      case CONFIG_FLIP_UP_KEY:
                          flipChannel(False, False, False, 0);
                          break;
              
                      case CONFIG_CIRCULATE_KEY:
 160                      circulate(False);
                          break;
      
                      case CONFIG_HIDE_KEY:
                          if (c) c->hide();
                          break;
      
                      case CONFIG_DESTROY_KEY:
                          if (c) c->kill();
                          break;
 170  
                      case CONFIG_RAISE_KEY:
                          if (c) c->mapRaised();
                          break;
      
                      case CONFIG_LOWER_KEY:
                          if (c) c->lower();
                          break;
      
                      case CONFIG_FULLHEIGHT_KEY:
 180                      if (c) c->fullHeight();
                          break;
                      
                      case CONFIG_NORMALHEIGHT_KEY:
                          if (c) c->normalHeight();
                          break;
      
                      case CONFIG_STICKY_KEY:
                          if (c) c->setSticky(!(c->isSticky()));
                          break;
 190  
                      case CONFIG_MENU_KEY:
                          if (CONFIG_WANT_KEYBOARD_MENU) {
                              ClientMenu menu(this, (XEvent *)ev);
                              break;
                          }
                      
                      default:
                          return;
                      }
 200              }
              }
      
              XSync(display(), False);
              XUngrabKeyboard(display(), CurrentTime);
          }
      
          return;
      }
      
 210  void WindowManager::eventKeyRelease(XKeyEvent *ev)
      {
          return;
      }
      
      void Client::activateAndWarp()
      {
          mapRaised();
          ensureVisible();
          warpPointer();
 220      activate();
      }
      
      
      void Client::eventButton(XButtonEvent *e)
      {
          if (e->type != ButtonPress) return;
      
          Boolean wasTop = windowManager()->isTop(this);
      
 230      mapRaised();
      
          if (e->button == Button1) {
              if (m_border->hasWindow(e->window)) {
      
                  m_border->eventButton(e);
              }
          }
      
          if (CONFIG_RAISELOWER_ON_CLICK && wasTop && !doSomething)
 240          lower();
      
          if (!isNormal() || isActive() || e->send_event) return;
          activate();
      }
      
      
      int WindowManager::attemptGrab(Window w, Window constrain, int mask, int t)
      {
          int status;
 250      if (t == 0) t = timestamp(False);
          status = XGrabPointer(display(), w, False, mask, GrabModeAsync,
                                GrabModeAsync, constrain, None, t);
          return status;
      }
      
      
      int WindowManager::attemptGrabKey(Window w, int t)
      {
          if (t == 0) t = timestamp(False);
 260      return XGrabKeyboard(display(), w, False, GrabModeAsync, GrabModeAsync, t);
      }
      
      
      void WindowManager::releaseGrab(XButtonEvent *e)
      {
          XEvent ev;
          if (!nobuttons(e)) {
              for (;;) {
                  XMaskEvent(display(), ButtonMask | ButtonMotionMask, &ev);
 270              if (ev.type == MotionNotify) continue;
                  e = &ev.xbutton;
                  if (nobuttons(e)) break;
              }
          }
      
          XUngrabPointer(display(), e->time);
          m_currentTime = e->time;
      }
      
 280  
      void WindowManager::releaseGrabKeyMode(XButtonEvent *e) 
      {
          XEvent ev;
          if (!nobuttons(e)) {
              for (;;) {
                  XMaskEvent(display(), ButtonMask | ButtonMotionMask, &ev);
                  if (ev.type == MotionNotify) continue;
                  e = &ev.xbutton;
                  if (nobuttons(e)) break;
 290          }
          }
      
          XUngrabPointer(display(), e->time);
          m_currentTime = e->time;
      
          XUngrabKeyboard(display(), e->time);
          m_currentTime = e->time;
      }
      
 300  
      void WindowManager::releaseGrabKeyMode(XKeyEvent* e)
      {
          XUngrabPointer(display(), e->time);
          XUngrabKeyboard(display(), e->time);
          m_currentTime = e->time;
      }
      
      
      void Client::move(XButtonEvent *e)
 310  {
          int x = -1, y = -1;
          Boolean done = False;
          ShowGeometry geometry(m_windowManager, (XEvent *)e);
      
          if (m_windowManager->attemptGrab
              (root(), None, DragMask, e->time) != GrabSuccess) {
              return;
          }
      
 320      int mx = DisplayWidth (display(), windowManager()->screen()) - 1;
          int my = DisplayHeight(display(), windowManager()->screen()) - 1;
          int xi = m_border->xIndent();
          int yi = m_border->yIndent();
      
          XEvent event;
          Boolean found;
          struct timeval sleepval;
      
          doSomething = False;
 330      while (!done) {
      
              found = False;
      
              while (XCheckMaskEvent(display(), DragMask | ExposureMask, &event)) {
                  found = True;
                  if (event.type != MotionNotify) break;
              }
      
              if (!found) {
 340              sleepval.tv_sec = 0;
                  sleepval.tv_usec = 50000;
                  select(0, 0, 0, 0, &sleepval);
                  continue;
              }
              
              switch (event.type) {
      
              default:
                  fprintf(stderr, "wmx: unknown event type %d\n", event.type);
 350              break;
      
              case Expose:
      //          m_windowManager->eventExposure(&event.xexpose);
                  m_windowManager->dispatchEvent(&event);
                  break;
      
              case ButtonPress:
                  // don't like this
                  XUngrabPointer(display(), event.xbutton.time);
 360              doSomething = False;
                  done = True;
                  break;
      
              case ButtonRelease:
      
                  if (!nobuttons(&event.xbutton)) doSomething = False;
      
                  m_windowManager->releaseGrab(&event.xbutton);
                  done = True;
 370              break;
      
              case MotionNotify:
      
                  int nx = event.xbutton.x - e->x;
                  int ny = event.xbutton.y - e->y;
      
                  if (nx != x || ny != y) {
      
                      if (doSomething) { // so x,y have sensible values already
 380  
                          // bumping!
      
                          if (nx < x && nx <= 0 && nx > -CONFIG_BUMP_DISTANCE) nx = 0;
                          if (ny < y && ny <= 0 && ny > -CONFIG_BUMP_DISTANCE) ny = 0;
      
                          if (nx > x && nx >= mx - m_w - xi &&
                              nx < mx - m_w - xi + CONFIG_BUMP_DISTANCE)
                              nx = mx - m_w - xi;
                          if (ny > y && ny >= my - m_h - yi &&
 390                          ny < my - m_h - yi + CONFIG_BUMP_DISTANCE)
                              ny = my - m_h - yi;
                      }
      
                      x = nx;
                      y = ny;
      
                      geometry.update(x, y);
                      m_border->moveTo(x + xi, y + yi);
                      doSomething = True;
 400              }
                  break;
              }
          }
      
          geometry.remove();
      
          if (doSomething) {
              m_x = x + xi;
              m_y = y + yi;
 410      }
      
          if (CONFIG_CLICK_TO_FOCUS) activate();
          m_border->moveTo(m_x, m_y);
          sendConfigureNotify();
      }
      
      
      void Client::fixResizeDimensions(int &w, int &h, int &dw, int &dh)
      {
 420      if (w < 50) w = 50;
          if (h < 50) h = 50;
          
          if (m_sizeHints.flags & PResizeInc) {
              w = m_minWidth  + (((w - m_minWidth) / m_sizeHints.width_inc) *
                                 m_sizeHints.width_inc);
              h = m_minHeight + (((h - m_minHeight) / m_sizeHints.height_inc) *
                                 m_sizeHints.height_inc);
      
              dw = (w - m_minWidth)  / m_sizeHints.width_inc;
 430          dh = (h - m_minHeight) / m_sizeHints.height_inc;
          } else {
              dw = w; dh = h;
          }
      
          if (m_sizeHints.flags & PMaxSize) {
              if (w > m_sizeHints.max_width)  w = m_sizeHints.max_width;
              if (h > m_sizeHints.max_height) h = m_sizeHints.max_height;
          }
      
 440      if (w < m_minWidth)  w = m_minWidth;
          if (h < m_minHeight) h = m_minHeight;
      }
      
      
      void Client::resize(XButtonEvent *e, Boolean horizontal, Boolean vertical)
      {
          if (isFixedSize()) return;
          ShowGeometry geometry(m_windowManager, (XEvent *)e);
      
 450      if (m_windowManager->attemptGrab
              (root(), None, DragMask, e->time) != GrabSuccess) {
              return;
          }
      
          if (vertical && horizontal)
              m_windowManager->installCursor(WindowManager::DownrightCursor);
          else if (vertical)
              m_windowManager->installCursor(WindowManager::DownCursor);
          else
 460          m_windowManager->installCursor(WindowManager::RightCursor);
      
          Window dummy;
          XTranslateCoordinates(display(), e->window, parent(),
                                e->x, e->y, &e->x, &e->y, &dummy);
      
          int xorig = e->x;
          int yorig = e->y;
          int x = xorig;
          int y = yorig;
 470      int w = m_w, h = m_h;
          int prevW, prevH;
          int dw, dh;
      
          XEvent event;
          Boolean found;
          Boolean done = False;
          struct timeval sleepval;
      
          doSomething = False;
 480      while (!done) {
      
              found = False;
      
              while (XCheckMaskEvent(display(), DragMask | ExposureMask, &event)) {
                  found = True;
                  if (event.type != MotionNotify) break;
              }
      
              if (!found) {
 490              sleepval.tv_sec = 0;
                  sleepval.tv_usec = 50000;
                  select(0, 0, 0, 0, &sleepval);
                  continue;
              }
              
              switch (event.type) {
      
              default:
                  fprintf(stderr, "wmx: unknown event type %d\n", event.type);
 500              break;
      
              case Expose:
      //          m_windowManager->eventExposure(&event.xexpose);
                  m_windowManager->dispatchEvent(&event);
                  break;
      
              case ButtonPress:
                  // don't like this
                  XUngrabPointer(display(), event.xbutton.time);
 510              done = True;
                  break;
      
              case ButtonRelease:
      
                  x = event.xbutton.x; y = event.xbutton.y;
      
                  if (!nobuttons(&event.xbutton)) x = -1;
                  m_windowManager->releaseGrab(&event.xbutton);
                  
 520              done = True;
                  break;
      
              case MotionNotify:
                  x = event.xbutton.x; y = event.xbutton.y;
      
                  if (vertical && horizontal) {
                      prevH = h; h = y - m_y;
                      prevW = w; w = x - m_x;
                      fixResizeDimensions(w, h, dw, dh);
 530                  if (h == prevH && w == prevW) break;
                      m_border->configure(m_x, m_y, w, h, CWWidth | CWHeight, 0);
                      if (CONFIG_RESIZE_UPDATE)
                          XResizeWindow(display(), m_window, w, h);
                      geometry.update(dw, dh);
                      doSomething = True;
      
                  } else if (vertical) {
                      prevH = h; h = y - m_y;
                      fixResizeDimensions(w, h, dw, dh);
 540                  if (h == prevH) break;
                      m_border->configure(m_x, m_y, w, h, CWHeight, 0);
                      if (CONFIG_RESIZE_UPDATE)
                          XResizeWindow(display(), m_window, w, h);
                      geometry.update(dw, dh);
                      doSomething = True;
      
                  } else {
                      prevW = w; w = x - m_x;
                      fixResizeDimensions(w, h, dw, dh);
 550                  if (w == prevW) break;
                      m_border->configure(m_x, m_y, w, h, CWWidth, 0);
                      if (CONFIG_RESIZE_UPDATE)
                          XResizeWindow(display(), m_window, w, h);
                      geometry.update(dw, dh);
                      doSomething = True;
                  }
      
                  break;
              }
 560      }
      
          if (doSomething) {
      
              geometry.remove();
      
              if (vertical && horizontal) {
                  m_w = x - m_x;
                  m_h = y - m_y;
                  fixResizeDimensions(m_w, m_h, dw, dh);
 570              m_border->configure(m_x, m_y, m_w, m_h, CWWidth|CWHeight, 0, True);
              } else if (vertical) {
                  m_h = y - m_y;
                  fixResizeDimensions(m_w, m_h, dw, dh);
                  m_border->configure(m_x, m_y, m_w, m_h, CWHeight, 0, True);
              } else {
                  m_w = x - m_x;
                  fixResizeDimensions(m_w, m_h, dw, dh);
                  m_border->configure(m_x, m_y, m_w, m_h, CWWidth, 0, True);
              }
 580  
              XMoveResizeWindow(display(), m_window,
                                m_border->xIndent(), m_border->yIndent(), m_w, m_h);
      
              if (vertical) makeThisNormalHeight(); // in case it was full-height
              sendConfigureNotify();
          }
      
          m_windowManager->installCursor(WindowManager::NormalCursor);
      }
 590  
      
      void Client::moveOrResize(XButtonEvent *e)
      {
          if (e->x < m_border->xIndent() && e->y > m_h) {
              resize(e, False, True);
          } else if (e->y < m_border->yIndent() &&
                     e->x > m_w + m_border->xIndent() - m_border->yIndent()) { //hack
              resize(e, True, False);
          } else {
 600          move(e);
          }
      }
      
      
      void Border::eventButton(XButtonEvent *e)
      {
          if (e->window == m_parent) {
      
              if (!m_client->isActive()) return;
 610          if (isTransient()) {
                  if (e->x >= xIndent() && e->y >= yIndent()) {
                      return;
                  } else {
                      m_client->move(e);
                      return;
                  }
              }
      
              m_client->moveOrResize(e);
 620          return;
              
          } else if (e->window == m_tab) {
              m_client->move(e);
              return;
          }
      
          if (e->window == m_resize) {
              m_client->resize(e, True, True);
              return;
 630      }
      
          if (e->window != m_button || e->type == ButtonRelease) return;
      
          if (windowManager()->attemptGrab(m_button, None, MenuGrabMask, e->time)
              != GrabSuccess) {
              return;
          }
      
          XEvent event;
 640      Boolean found;
          Boolean done = False;
          struct timeval sleepval;
          unsigned long tdiff = 0L;
          int x = e->x;
          int y = e->y;
          int action = 1;
          int buttonSize = m_tabWidth - TAB_TOP_HEIGHT*2 - 4;
      
          XFillRectangle(display(), m_button, m_drawGC, 0, 0, buttonSize, buttonSize);
 650  
          while (!done) {
      
              found = False;
      
              if (tdiff > CONFIG_DESTROY_WINDOW_DELAY && action == 1) {
                  windowManager()->installCursor(WindowManager::DeleteCursor);
                  action = 2;
              }
      
 660          while (XCheckMaskEvent(display(), MenuMask, &event)) {
                  found = True;
                  if (event.type != MotionNotify) break;
              }
      
              if (!found) {
                  sleepval.tv_sec = 0;
                  sleepval.tv_usec = 50000;
                  select(0, 0, 0, 0, &sleepval);
                  tdiff += 50;
 670              continue;
              }
      
              switch (event.type) {
      
              default:
                  fprintf(stderr, "wmx: unknown event type %d\n", event.type);
                  break;
      
              case Expose:
 680  //          windowManager()->eventExposure(&event.xexpose);
                  windowManager()->dispatchEvent(&event);
                  break;
      
              case ButtonPress:
                  break;
      
              case ButtonRelease:
      
                  if (!nobuttons(&event.xbutton)) {
 690                  action = 0;
                  }
      
                  if (x < 0 || y < 0 || x >= buttonSize || y >= buttonSize) {
                      action = 0;
                  }
      
                  windowManager()->releaseGrab(&event.xbutton);
                  done = True;
                  break;
 700  
              case MotionNotify:
                  tdiff = event.xmotion.time - e->time;
                  if (tdiff > 5000L) tdiff = 5001L; // in case of overflow!
      
                  x = event.xmotion.x;
                  y = event.xmotion.y;
      
                  if (action == 0 || action == 2) {
                      if (x < 0 || y < 0 || x >= buttonSize || y >= buttonSize) {
 710                      windowManager()->installCursor(WindowManager::NormalCursor);
                          action = 0;
                      } else {
                          windowManager()->installCursor(WindowManager::DeleteCursor);
                          action = 2;
                      }
                  }
      
                  break;
              }
 720      }
      
          XClearWindow(display(), m_button);
          windowManager()->installCursor(WindowManager::NormalCursor);
      
          if (tdiff > 5000L) {        // do nothing, they dithered too long
              return;
          }
      
          if (action == 1) m_client->hide();
 730      else if (action == 2) m_client->kill();
      }
      
      
      

Index

  • WindowManager::eventButton (function) returns void
  • WindowManager::circulate (function) returns void
  • WindowManager::eventKeyPress (function) returns void
  • WindowManager::eventKeyRelease (function) returns void
  • Client::activateAndWarp (function) returns void
  • Client::eventButton (function) returns void
  • WindowManager::attemptGrab (function) returns int
  • WindowManager::attemptGrabKey (function) returns int
  • WindowManager::releaseGrab (function) returns void
  • WindowManager::releaseGrabKeyMode (function) returns void
  • WindowManager::releaseGrabKeyMode (function) returns void
  • Client::move (function) returns void
  • Client::fixResizeDimensions (function) returns void
  • Client::resize (function) returns void
  • Client::moveOrResize (function) returns void
  • Border::eventButton (function) returns void